1 /* $OpenBSD: i2c_bitbang.c,v 1.3 2006/01/13 23:56:46 grange Exp $ */ 2 /* $NetBSD: i2c_bitbang.c,v 1.1 2003/09/30 00:35:31 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 2003 Wasabi Systems, Inc. 6 * All rights reserved. 7 * 8 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed for the NetBSD Project by 21 * Wasabi Systems, Inc. 22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 * or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Common module for bit-bang'ing an I2C bus. 41 */ 42 43 #include <sys/param.h> 44 45 #include <dev/i2c/i2cvar.h> 46 #include <dev/i2c/i2c_bitbang.h> 47 48 #define BB_SET(x) ops->ibo_set_bits(v, (x)) 49 #define BB_DIR(x) ops->ibo_set_dir(v, (x)) 50 #define BB_READ ops->ibo_read_bits(v) 51 52 #define SDA ops->ibo_bits[I2C_BIT_SDA] /* i2c signal */ 53 #define SCL ops->ibo_bits[I2C_BIT_SCL] /* i2c signal */ 54 #define OUTPUT ops->ibo_bits[I2C_BIT_OUTPUT] /* SDA is output */ 55 #define INPUT ops->ibo_bits[I2C_BIT_INPUT] /* SDA is input */ 56 57 /*ARGSUSED*/ 58 int 59 i2c_bitbang_send_start(void *v, int flags, i2c_bitbang_ops_t ops) 60 { 61 62 BB_DIR(OUTPUT); 63 64 BB_SET(SDA | SCL); 65 delay(5); /* bus free time (4.7 uS) */ 66 BB_SET( SCL); 67 delay(4); /* start hold time (4.0 uS) */ 68 BB_SET( 0); 69 delay(5); /* clock low time (4.7 uS) */ 70 71 return (0); 72 } 73 74 /*ARGSUSED*/ 75 int 76 i2c_bitbang_send_stop(void *v, int flags, i2c_bitbang_ops_t ops) 77 { 78 79 BB_DIR(OUTPUT); 80 81 BB_SET( SCL); 82 delay(4); /* stop setup time (4.0 uS) */ 83 BB_SET(SDA | SCL); 84 85 return (0); 86 } 87 88 int 89 i2c_bitbang_initiate_xfer(void *v, i2c_addr_t addr, int flags, 90 i2c_bitbang_ops_t ops) 91 { 92 int i2caddr; 93 94 /* XXX Only support 7-bit addressing for now. */ 95 if ((addr & 0x78) == 0x78) 96 return (EINVAL); 97 98 i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0); 99 100 (void) i2c_bitbang_send_start(v, flags, ops); 101 return (i2c_bitbang_write_byte(v, i2caddr, flags & ~I2C_F_STOP, ops)); 102 } 103 104 int 105 i2c_bitbang_read_byte(void *v, uint8_t *valp, int flags, 106 i2c_bitbang_ops_t ops) 107 { 108 int i; 109 uint8_t val = 0; 110 uint32_t bit; 111 112 BB_DIR(INPUT); 113 BB_SET(SDA ); 114 115 for (i = 0; i < 8; i++) { 116 val <<= 1; 117 BB_SET(SDA | SCL); 118 delay(4); /* clock high time (4.0 uS) */ 119 if (BB_READ & SDA) 120 val |= 1; 121 BB_SET(SDA ); 122 delay(5); /* clock low time (4.7 uS) */ 123 } 124 125 bit = (flags & I2C_F_LAST) ? SDA : 0; 126 BB_DIR(OUTPUT); 127 BB_SET(bit ); 128 delay(1); /* data setup time (250 nS) */ 129 BB_SET(bit | SCL); 130 delay(4); /* clock high time (4.0 uS) */ 131 BB_SET(bit ); 132 delay(5); /* clock low time (4.7 uS) */ 133 134 BB_DIR(INPUT); 135 BB_SET(SDA ); 136 delay(5); 137 138 if ((flags & (I2C_F_STOP | I2C_F_LAST)) == (I2C_F_STOP | I2C_F_LAST)) 139 (void) i2c_bitbang_send_stop(v, flags, ops); 140 141 *valp = val; 142 return (0); 143 } 144 145 int 146 i2c_bitbang_write_byte(void *v, uint8_t val, int flags, 147 i2c_bitbang_ops_t ops) 148 { 149 uint32_t bit; 150 uint8_t mask; 151 int error; 152 153 BB_DIR(OUTPUT); 154 155 for (mask = 0x80; mask != 0; mask >>= 1) { 156 bit = (val & mask) ? SDA : 0; 157 BB_SET(bit ); 158 delay(1); /* data setup time (250 nS) */ 159 BB_SET(bit | SCL); 160 delay(4); /* clock high time (4.0 uS) */ 161 BB_SET(bit ); 162 delay(5); /* clock low time (4.7 uS) */ 163 } 164 165 BB_DIR(INPUT); 166 167 BB_SET(SDA ); 168 delay(5); 169 BB_SET(SDA | SCL); 170 delay(4); 171 error = (BB_READ & SDA) ? EIO : 0; 172 BB_SET(SDA ); 173 delay(5); 174 175 if (flags & I2C_F_STOP) 176 (void) i2c_bitbang_send_stop(v, flags, ops); 177 178 return (error); 179 } 180