1*5b133f3fSguenther /* $OpenBSD: i2c_bitbang.c,v 1.5 2023/03/08 04:43:08 guenther Exp $ */
23a4cbe1aSgrange /* $NetBSD: i2c_bitbang.c,v 1.1 2003/09/30 00:35:31 thorpej Exp $ */
33a4cbe1aSgrange
43a4cbe1aSgrange /*
53a4cbe1aSgrange * Copyright (c) 2003 Wasabi Systems, Inc.
63a4cbe1aSgrange * All rights reserved.
73a4cbe1aSgrange *
83a4cbe1aSgrange * Written by Jason R. Thorpe for Wasabi Systems, Inc.
93a4cbe1aSgrange *
103a4cbe1aSgrange * Redistribution and use in source and binary forms, with or without
113a4cbe1aSgrange * modification, are permitted provided that the following conditions
123a4cbe1aSgrange * are met:
133a4cbe1aSgrange * 1. Redistributions of source code must retain the above copyright
143a4cbe1aSgrange * notice, this list of conditions and the following disclaimer.
153a4cbe1aSgrange * 2. Redistributions in binary form must reproduce the above copyright
163a4cbe1aSgrange * notice, this list of conditions and the following disclaimer in the
173a4cbe1aSgrange * documentation and/or other materials provided with the distribution.
183a4cbe1aSgrange * 3. All advertising materials mentioning features or use of this software
193a4cbe1aSgrange * must display the following acknowledgement:
203a4cbe1aSgrange * This product includes software developed for the NetBSD Project by
213a4cbe1aSgrange * Wasabi Systems, Inc.
223a4cbe1aSgrange * 4. The name of Wasabi Systems, Inc. may not be used to endorse
233a4cbe1aSgrange * or promote products derived from this software without specific prior
243a4cbe1aSgrange * written permission.
253a4cbe1aSgrange *
263a4cbe1aSgrange * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
273a4cbe1aSgrange * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
283a4cbe1aSgrange * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
293a4cbe1aSgrange * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
303a4cbe1aSgrange * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
313a4cbe1aSgrange * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
323a4cbe1aSgrange * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
333a4cbe1aSgrange * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
343a4cbe1aSgrange * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
353a4cbe1aSgrange * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
363a4cbe1aSgrange * POSSIBILITY OF SUCH DAMAGE.
373a4cbe1aSgrange */
383a4cbe1aSgrange
393a4cbe1aSgrange /*
403a4cbe1aSgrange * Common module for bit-bang'ing an I2C bus.
413a4cbe1aSgrange */
423a4cbe1aSgrange
433a4cbe1aSgrange #include <sys/param.h>
443a4cbe1aSgrange
453a4cbe1aSgrange #include <dev/i2c/i2cvar.h>
463a4cbe1aSgrange #include <dev/i2c/i2c_bitbang.h>
473a4cbe1aSgrange
483a4cbe1aSgrange #define BB_SET(x) ops->ibo_set_bits(v, (x))
493a4cbe1aSgrange #define BB_DIR(x) ops->ibo_set_dir(v, (x))
503a4cbe1aSgrange #define BB_READ ops->ibo_read_bits(v)
513a4cbe1aSgrange
523a4cbe1aSgrange #define SDA ops->ibo_bits[I2C_BIT_SDA] /* i2c signal */
533a4cbe1aSgrange #define SCL ops->ibo_bits[I2C_BIT_SCL] /* i2c signal */
543a4cbe1aSgrange #define OUTPUT ops->ibo_bits[I2C_BIT_OUTPUT] /* SDA is output */
553a4cbe1aSgrange #define INPUT ops->ibo_bits[I2C_BIT_INPUT] /* SDA is input */
563a4cbe1aSgrange
573bfc9b60Skettenis #define SCL_BAIL_COUNT 1000
583bfc9b60Skettenis
593bfc9b60Skettenis int i2c_wait_for_scl(void *, i2c_bitbang_ops_t);
603bfc9b60Skettenis
613bfc9b60Skettenis int
i2c_wait_for_scl(void * v,i2c_bitbang_ops_t ops)623bfc9b60Skettenis i2c_wait_for_scl(void *v, i2c_bitbang_ops_t ops)
633bfc9b60Skettenis {
643bfc9b60Skettenis int bail = 0;
653bfc9b60Skettenis
663bfc9b60Skettenis while(((BB_READ & SCL) == 0) && bail < SCL_BAIL_COUNT) {
673bfc9b60Skettenis delay(1);
683bfc9b60Skettenis bail++;
693bfc9b60Skettenis }
703bfc9b60Skettenis if (bail == SCL_BAIL_COUNT) {
713bfc9b60Skettenis i2c_bitbang_send_stop(v, 0, ops);
723bfc9b60Skettenis return (EIO);
733bfc9b60Skettenis }
743bfc9b60Skettenis
753bfc9b60Skettenis return (0);
763bfc9b60Skettenis }
773bfc9b60Skettenis
783a4cbe1aSgrange int
i2c_bitbang_send_start(void * v,int flags,i2c_bitbang_ops_t ops)793a4cbe1aSgrange i2c_bitbang_send_start(void *v, int flags, i2c_bitbang_ops_t ops)
803a4cbe1aSgrange {
813a4cbe1aSgrange
823a4cbe1aSgrange BB_DIR(OUTPUT);
833a4cbe1aSgrange
843a4cbe1aSgrange BB_SET(SDA | SCL);
853a4cbe1aSgrange delay(5); /* bus free time (4.7 uS) */
863a4cbe1aSgrange BB_SET( SCL);
873bfc9b60Skettenis if (i2c_wait_for_scl(v, ops) != 0)
883bfc9b60Skettenis return (EIO);
893a4cbe1aSgrange delay(4); /* start hold time (4.0 uS) */
903a4cbe1aSgrange BB_SET( 0);
913a4cbe1aSgrange delay(5); /* clock low time (4.7 uS) */
923a4cbe1aSgrange
933a4cbe1aSgrange return (0);
943a4cbe1aSgrange }
953a4cbe1aSgrange
963a4cbe1aSgrange int
i2c_bitbang_send_stop(void * v,int flags,i2c_bitbang_ops_t ops)973a4cbe1aSgrange i2c_bitbang_send_stop(void *v, int flags, i2c_bitbang_ops_t ops)
983a4cbe1aSgrange {
993a4cbe1aSgrange
1003a4cbe1aSgrange BB_DIR(OUTPUT);
1013a4cbe1aSgrange
1023a4cbe1aSgrange BB_SET( SCL);
1033a4cbe1aSgrange delay(4); /* stop setup time (4.0 uS) */
1043a4cbe1aSgrange BB_SET(SDA | SCL);
1053a4cbe1aSgrange
1063a4cbe1aSgrange return (0);
1073a4cbe1aSgrange }
1083a4cbe1aSgrange
1093a4cbe1aSgrange int
i2c_bitbang_initiate_xfer(void * v,i2c_addr_t addr,int flags,i2c_bitbang_ops_t ops)1103a4cbe1aSgrange i2c_bitbang_initiate_xfer(void *v, i2c_addr_t addr, int flags,
1113a4cbe1aSgrange i2c_bitbang_ops_t ops)
1123a4cbe1aSgrange {
1133a4cbe1aSgrange int i2caddr;
1143a4cbe1aSgrange
1153a4cbe1aSgrange /* XXX Only support 7-bit addressing for now. */
1163a4cbe1aSgrange if ((addr & 0x78) == 0x78)
1173a4cbe1aSgrange return (EINVAL);
1183a4cbe1aSgrange
1193a4cbe1aSgrange i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0);
1203a4cbe1aSgrange
1213a4cbe1aSgrange (void) i2c_bitbang_send_start(v, flags, ops);
1223a4cbe1aSgrange return (i2c_bitbang_write_byte(v, i2caddr, flags & ~I2C_F_STOP, ops));
1233a4cbe1aSgrange }
1243a4cbe1aSgrange
1253a4cbe1aSgrange int
i2c_bitbang_read_byte(void * v,uint8_t * valp,int flags,i2c_bitbang_ops_t ops)1263a4cbe1aSgrange i2c_bitbang_read_byte(void *v, uint8_t *valp, int flags,
1273a4cbe1aSgrange i2c_bitbang_ops_t ops)
1283a4cbe1aSgrange {
1293a4cbe1aSgrange int i;
1303a4cbe1aSgrange uint8_t val = 0;
1313a4cbe1aSgrange uint32_t bit;
1323a4cbe1aSgrange
1333a4cbe1aSgrange BB_DIR(INPUT);
1343a4cbe1aSgrange BB_SET(SDA );
1353a4cbe1aSgrange
1363a4cbe1aSgrange for (i = 0; i < 8; i++) {
1373a4cbe1aSgrange val <<= 1;
1383a4cbe1aSgrange BB_SET(SDA | SCL);
1393bfc9b60Skettenis if (i2c_wait_for_scl(v, ops) != 0)
1403bfc9b60Skettenis return (EIO);
1413a4cbe1aSgrange delay(4); /* clock high time (4.0 uS) */
1423a4cbe1aSgrange if (BB_READ & SDA)
1433a4cbe1aSgrange val |= 1;
1443a4cbe1aSgrange BB_SET(SDA );
1453a4cbe1aSgrange delay(5); /* clock low time (4.7 uS) */
1463a4cbe1aSgrange }
1473a4cbe1aSgrange
1483a4cbe1aSgrange bit = (flags & I2C_F_LAST) ? SDA : 0;
1493a4cbe1aSgrange BB_DIR(OUTPUT);
1503a4cbe1aSgrange BB_SET(bit );
1513a4cbe1aSgrange delay(1); /* data setup time (250 nS) */
1523a4cbe1aSgrange BB_SET(bit | SCL);
1533bfc9b60Skettenis if (i2c_wait_for_scl(v, ops) != 0)
1543bfc9b60Skettenis return (EIO);
1553a4cbe1aSgrange delay(4); /* clock high time (4.0 uS) */
1563a4cbe1aSgrange BB_SET(bit );
1573a4cbe1aSgrange delay(5); /* clock low time (4.7 uS) */
1583a4cbe1aSgrange
1593a4cbe1aSgrange BB_DIR(INPUT);
1603a4cbe1aSgrange BB_SET(SDA );
1613a4cbe1aSgrange delay(5);
1623a4cbe1aSgrange
1633a4cbe1aSgrange if ((flags & (I2C_F_STOP | I2C_F_LAST)) == (I2C_F_STOP | I2C_F_LAST))
1643a4cbe1aSgrange (void) i2c_bitbang_send_stop(v, flags, ops);
1653a4cbe1aSgrange
1663a4cbe1aSgrange *valp = val;
1673a4cbe1aSgrange return (0);
1683a4cbe1aSgrange }
1693a4cbe1aSgrange
1703a4cbe1aSgrange int
i2c_bitbang_write_byte(void * v,uint8_t val,int flags,i2c_bitbang_ops_t ops)1713a4cbe1aSgrange i2c_bitbang_write_byte(void *v, uint8_t val, int flags,
1723a4cbe1aSgrange i2c_bitbang_ops_t ops)
1733a4cbe1aSgrange {
1743a4cbe1aSgrange uint32_t bit;
1753a4cbe1aSgrange uint8_t mask;
1763a4cbe1aSgrange int error;
1773a4cbe1aSgrange
1783a4cbe1aSgrange BB_DIR(OUTPUT);
1793a4cbe1aSgrange
1803a4cbe1aSgrange for (mask = 0x80; mask != 0; mask >>= 1) {
1813a4cbe1aSgrange bit = (val & mask) ? SDA : 0;
1823a4cbe1aSgrange BB_SET(bit );
1833a4cbe1aSgrange delay(1); /* data setup time (250 nS) */
1843a4cbe1aSgrange BB_SET(bit | SCL);
1853bfc9b60Skettenis if (i2c_wait_for_scl(v, ops) != 0)
1863bfc9b60Skettenis return (EIO);
1873a4cbe1aSgrange delay(4); /* clock high time (4.0 uS) */
1883a4cbe1aSgrange BB_SET(bit );
1893a4cbe1aSgrange delay(5); /* clock low time (4.7 uS) */
1903a4cbe1aSgrange }
1913a4cbe1aSgrange
1923a4cbe1aSgrange BB_DIR(INPUT);
1933a4cbe1aSgrange
1943a4cbe1aSgrange BB_SET(SDA );
1953a4cbe1aSgrange delay(5);
1963a4cbe1aSgrange BB_SET(SDA | SCL);
1973bfc9b60Skettenis if (i2c_wait_for_scl(v, ops) != 0)
1983bfc9b60Skettenis return (EIO);
1993a4cbe1aSgrange delay(4);
2003a4cbe1aSgrange error = (BB_READ & SDA) ? EIO : 0;
2013a4cbe1aSgrange BB_SET(SDA );
2023a4cbe1aSgrange delay(5);
2033a4cbe1aSgrange
2043a4cbe1aSgrange if (flags & I2C_F_STOP)
2053a4cbe1aSgrange (void) i2c_bitbang_send_stop(v, flags, ops);
2063a4cbe1aSgrange
2073a4cbe1aSgrange return (error);
2083a4cbe1aSgrange }
209