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