1 /* $NetBSD: i2c_bitbang.c,v 1.9 2007/12/11 12:09:21 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Common module for bit-bang'ing an I2C bus. 40 */ 41 42 #include <sys/cdefs.h> 43 __KERNEL_RCSID(0, "$NetBSD: i2c_bitbang.c,v 1.9 2007/12/11 12:09:21 lukem Exp $"); 44 45 #include <sys/param.h> 46 47 #include <dev/i2c/i2cvar.h> 48 #include <dev/i2c/i2c_bitbang.h> 49 50 #define SETBITS(x) ops->ibo_set_bits(v, (x)) 51 #define DIR(x) ops->ibo_set_dir(v, (x)) 52 #define READ ops->ibo_read_bits(v) 53 54 #define SDA ops->ibo_bits[I2C_BIT_SDA] /* i2c signal */ 55 #define SCL ops->ibo_bits[I2C_BIT_SCL] /* i2c signal */ 56 #define OUTPUT ops->ibo_bits[I2C_BIT_OUTPUT] /* SDA is output */ 57 #define INPUT ops->ibo_bits[I2C_BIT_INPUT] /* SDA is input */ 58 59 #ifndef SCL_BAIL_COUNT 60 #define SCL_BAIL_COUNT 1000 61 #endif 62 63 static inline int i2c_wait_for_scl(void *, i2c_bitbang_ops_t); 64 65 static inline int 66 i2c_wait_for_scl(void *v, i2c_bitbang_ops_t ops) 67 { 68 int bail = 0; 69 70 DIR(INPUT); 71 72 while (((READ & SCL) == 0) && (bail < SCL_BAIL_COUNT)) { 73 74 delay(1); 75 bail++; 76 } 77 if (bail == SCL_BAIL_COUNT) { 78 79 i2c_bitbang_send_stop(v, 0, ops); 80 return EIO; 81 } 82 return 0; 83 } 84 85 /*ARGSUSED*/ 86 int 87 i2c_bitbang_send_start(void *v, int flags, i2c_bitbang_ops_t ops) 88 { 89 90 DIR(OUTPUT); 91 SETBITS(SDA | SCL); 92 delay(5); /* bus free time (4.7 uS) */ 93 SETBITS( SCL); 94 95 if (i2c_wait_for_scl(v, ops) != 0) 96 return EIO; 97 delay(4); /* start hold time (4.0 uS) */ 98 99 DIR(OUTPUT); 100 SETBITS( 0); 101 delay(5); /* clock low time (4.7 uS) */ 102 103 return (0); 104 } 105 106 /*ARGSUSED*/ 107 int 108 i2c_bitbang_send_stop(void *v, int flags, i2c_bitbang_ops_t ops) 109 { 110 111 DIR(OUTPUT); 112 SETBITS( SCL); 113 delay(4); /* stop setup time (4.0 uS) */ 114 SETBITS(SDA | SCL); 115 116 return (0); 117 } 118 119 int 120 i2c_bitbang_initiate_xfer(void *v, i2c_addr_t addr, int flags, 121 i2c_bitbang_ops_t ops) 122 { 123 124 if (addr < 0x80) { 125 uint8_t i2caddr; 126 127 /* disallow the 10-bit address prefix */ 128 if ((addr & 0x78) == 0x78) 129 return EINVAL; 130 i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0); 131 (void) i2c_bitbang_send_start(v, flags, ops); 132 133 return (i2c_bitbang_write_byte(v, i2caddr, 134 flags & ~I2C_F_STOP, ops)); 135 136 } else if (addr < 0x400) { 137 uint16_t i2caddr; 138 int rv; 139 140 i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0) | 141 0xf000; 142 143 (void) i2c_bitbang_send_start(v, flags, ops); 144 rv = i2c_bitbang_write_byte(v, i2caddr >> 8, 145 flags & ~I2C_F_STOP, ops); 146 /* did a slave ack the 10-bit prefix? */ 147 if (rv != 0) 148 return rv; 149 150 /* send the lower 7-bits (+ read/write mode) */ 151 return (i2c_bitbang_write_byte(v, i2caddr & 0xff, 152 flags & ~I2C_F_STOP, ops)); 153 154 } else 155 return EINVAL; 156 } 157 158 int 159 i2c_bitbang_read_byte(void *v, uint8_t *valp, int flags, 160 i2c_bitbang_ops_t ops) 161 { 162 int i; 163 uint8_t val = 0; 164 uint32_t bit; 165 166 DIR(OUTPUT); 167 SETBITS(SDA ); 168 169 for (i = 0; i < 8; i++) { 170 val <<= 1; 171 172 DIR(OUTPUT); 173 SETBITS(SDA | SCL); 174 175 if (i2c_wait_for_scl(v, ops) != 0) 176 return EIO; 177 delay(4); /* clock high time (4.0 uS) */ 178 179 DIR(INPUT); 180 if (READ & SDA) 181 val |= 1; 182 183 DIR(OUTPUT); 184 SETBITS(SDA ); 185 delay(5); /* clock low time (4.7 uS) */ 186 } 187 188 bit = (flags & I2C_F_LAST) ? SDA : 0; 189 190 DIR(OUTPUT); 191 SETBITS(bit ); 192 delay(1); /* data setup time (250 nS) */ 193 SETBITS(bit | SCL); 194 195 if (i2c_wait_for_scl(v, ops) != 0) 196 return EIO; 197 delay(4); /* clock high time (4.0 uS) */ 198 199 DIR(OUTPUT); 200 SETBITS(bit ); 201 delay(5); /* clock low time (4.7 uS) */ 202 203 DIR(INPUT); 204 SETBITS(SDA ); 205 delay(5); 206 207 if ((flags & (I2C_F_STOP | I2C_F_LAST)) == (I2C_F_STOP | I2C_F_LAST)) 208 (void) i2c_bitbang_send_stop(v, flags, ops); 209 210 *valp = val; 211 return (0); 212 } 213 214 int 215 i2c_bitbang_write_byte(void *v, uint8_t val, int flags, 216 i2c_bitbang_ops_t ops) 217 { 218 uint32_t bit; 219 uint8_t mask; 220 int error; 221 222 for (mask = 0x80; mask != 0; mask >>= 1) { 223 bit = (val & mask) ? SDA : 0; 224 225 DIR(OUTPUT); 226 SETBITS(bit ); 227 delay(1); /* data setup time (250 nS) */ 228 SETBITS(bit | SCL); 229 230 if (i2c_wait_for_scl(v, ops)) 231 return EIO; 232 delay(4); /* clock high time (4.0 uS) */ 233 234 DIR(OUTPUT); 235 SETBITS(bit ); 236 delay(5); /* clock low time (4.7 uS) */ 237 } 238 239 DIR(OUTPUT); 240 SETBITS(SDA ); 241 delay(5); 242 SETBITS(SDA | SCL); 243 244 if (i2c_wait_for_scl(v, ops) != 0) 245 return EIO; 246 delay(4); 247 248 DIR(INPUT); 249 error = (READ & SDA) ? EIO : 0; 250 251 DIR(OUTPUT); 252 SETBITS(SDA ); 253 delay(5); 254 255 if (flags & I2C_F_STOP) 256 (void) i2c_bitbang_send_stop(v, flags, ops); 257 258 return (error); 259 } 260