1 /* $OpenBSD: i2c_bitbang.c,v 1.4 2013/04/20 14:27:09 kettenis 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 #define SCL_BAIL_COUNT 1000 58 59 int i2c_wait_for_scl(void *, i2c_bitbang_ops_t); 60 61 int 62 i2c_wait_for_scl(void *v, i2c_bitbang_ops_t ops) 63 { 64 int bail = 0; 65 66 while(((BB_READ & SCL) == 0) && bail < SCL_BAIL_COUNT) { 67 delay(1); 68 bail++; 69 } 70 if (bail == SCL_BAIL_COUNT) { 71 i2c_bitbang_send_stop(v, 0, ops); 72 return (EIO); 73 } 74 75 return (0); 76 } 77 78 /*ARGSUSED*/ 79 int 80 i2c_bitbang_send_start(void *v, int flags, i2c_bitbang_ops_t ops) 81 { 82 83 BB_DIR(OUTPUT); 84 85 BB_SET(SDA | SCL); 86 delay(5); /* bus free time (4.7 uS) */ 87 BB_SET( SCL); 88 if (i2c_wait_for_scl(v, ops) != 0) 89 return (EIO); 90 delay(4); /* start hold time (4.0 uS) */ 91 BB_SET( 0); 92 delay(5); /* clock low time (4.7 uS) */ 93 94 return (0); 95 } 96 97 /*ARGSUSED*/ 98 int 99 i2c_bitbang_send_stop(void *v, int flags, i2c_bitbang_ops_t ops) 100 { 101 102 BB_DIR(OUTPUT); 103 104 BB_SET( SCL); 105 delay(4); /* stop setup time (4.0 uS) */ 106 BB_SET(SDA | SCL); 107 108 return (0); 109 } 110 111 int 112 i2c_bitbang_initiate_xfer(void *v, i2c_addr_t addr, int flags, 113 i2c_bitbang_ops_t ops) 114 { 115 int i2caddr; 116 117 /* XXX Only support 7-bit addressing for now. */ 118 if ((addr & 0x78) == 0x78) 119 return (EINVAL); 120 121 i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0); 122 123 (void) i2c_bitbang_send_start(v, flags, ops); 124 return (i2c_bitbang_write_byte(v, i2caddr, flags & ~I2C_F_STOP, ops)); 125 } 126 127 int 128 i2c_bitbang_read_byte(void *v, uint8_t *valp, int flags, 129 i2c_bitbang_ops_t ops) 130 { 131 int i; 132 uint8_t val = 0; 133 uint32_t bit; 134 135 BB_DIR(INPUT); 136 BB_SET(SDA ); 137 138 for (i = 0; i < 8; i++) { 139 val <<= 1; 140 BB_SET(SDA | SCL); 141 if (i2c_wait_for_scl(v, ops) != 0) 142 return (EIO); 143 delay(4); /* clock high time (4.0 uS) */ 144 if (BB_READ & SDA) 145 val |= 1; 146 BB_SET(SDA ); 147 delay(5); /* clock low time (4.7 uS) */ 148 } 149 150 bit = (flags & I2C_F_LAST) ? SDA : 0; 151 BB_DIR(OUTPUT); 152 BB_SET(bit ); 153 delay(1); /* data setup time (250 nS) */ 154 BB_SET(bit | SCL); 155 if (i2c_wait_for_scl(v, ops) != 0) 156 return (EIO); 157 delay(4); /* clock high time (4.0 uS) */ 158 BB_SET(bit ); 159 delay(5); /* clock low time (4.7 uS) */ 160 161 BB_DIR(INPUT); 162 BB_SET(SDA ); 163 delay(5); 164 165 if ((flags & (I2C_F_STOP | I2C_F_LAST)) == (I2C_F_STOP | I2C_F_LAST)) 166 (void) i2c_bitbang_send_stop(v, flags, ops); 167 168 *valp = val; 169 return (0); 170 } 171 172 int 173 i2c_bitbang_write_byte(void *v, uint8_t val, int flags, 174 i2c_bitbang_ops_t ops) 175 { 176 uint32_t bit; 177 uint8_t mask; 178 int error; 179 180 BB_DIR(OUTPUT); 181 182 for (mask = 0x80; mask != 0; mask >>= 1) { 183 bit = (val & mask) ? SDA : 0; 184 BB_SET(bit ); 185 delay(1); /* data setup time (250 nS) */ 186 BB_SET(bit | SCL); 187 if (i2c_wait_for_scl(v, ops) != 0) 188 return (EIO); 189 delay(4); /* clock high time (4.0 uS) */ 190 BB_SET(bit ); 191 delay(5); /* clock low time (4.7 uS) */ 192 } 193 194 BB_DIR(INPUT); 195 196 BB_SET(SDA ); 197 delay(5); 198 BB_SET(SDA | SCL); 199 if (i2c_wait_for_scl(v, ops) != 0) 200 return (EIO); 201 delay(4); 202 error = (BB_READ & SDA) ? EIO : 0; 203 BB_SET(SDA ); 204 delay(5); 205 206 if (flags & I2C_F_STOP) 207 (void) i2c_bitbang_send_stop(v, flags, ops); 208 209 return (error); 210 } 211