1 /* $NetBSD: i2c_bitbang.c,v 1.11 2008/06/01 01:13:18 tsutsui Exp $ */
4 * Copyright (c) 2003 Wasabi Systems, Inc.
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
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.
39 * Common module for bit-bang'ing an I2C bus.
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: i2c_bitbang.c,v 1.11 2008/06/01 01:13:18 tsutsui Exp $");
45 #include <sys/param.h>
47 #include <dev/i2c/i2cvar.h>
48 #include <dev/i2c/i2c_bitbang.h>
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)
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 */
59 #ifndef SCL_BAIL_COUNT
60 #define SCL_BAIL_COUNT 1000
63 static inline int i2c_wait_for_scl(void *, i2c_bitbang_ops_t
);
66 i2c_wait_for_scl(void *v
, i2c_bitbang_ops_t ops
)
70 while (((READ
& SCL
) == 0) && (bail
< SCL_BAIL_COUNT
)) {
74 if (bail
== SCL_BAIL_COUNT
) {
75 i2c_bitbang_send_stop(v
, 0, ops
);
83 i2c_bitbang_send_start(void *v
, int flags
, i2c_bitbang_ops_t ops
)
86 /* start condition: put SDL H->L edge during SCL=H */
90 delay(5); /* bus free time (4.7 us) */
92 if (i2c_wait_for_scl(v
, ops
) != 0)
94 delay(4); /* start hold time (4.0 us) */
96 /* leave SCL=L and SDL=L to avoid unexpected start/stop condition */
104 i2c_bitbang_send_stop(void *v
, int flags
, i2c_bitbang_ops_t ops
)
107 /* stop condition: put SDL L->H edge during SCL=H */
109 /* assume SCL=L, SDL=L here */
112 delay(4); /* stop setup time (4.0 us) */
119 i2c_bitbang_initiate_xfer(void *v
, i2c_addr_t addr
, int flags
,
120 i2c_bitbang_ops_t ops
)
126 /* disallow the 10-bit address prefix */
127 if ((addr
& 0x78) == 0x78)
129 i2caddr
= (addr
<< 1) | ((flags
& I2C_F_READ
) ? 1 : 0);
130 (void) i2c_bitbang_send_start(v
, flags
, ops
);
132 return (i2c_bitbang_write_byte(v
, i2caddr
,
133 flags
& ~I2C_F_STOP
, ops
));
135 } else if (addr
< 0x400) {
139 i2caddr
= (addr
<< 1) | ((flags
& I2C_F_READ
) ? 1 : 0) |
142 (void) i2c_bitbang_send_start(v
, flags
, ops
);
143 rv
= i2c_bitbang_write_byte(v
, i2caddr
>> 8,
144 flags
& ~I2C_F_STOP
, ops
);
145 /* did a slave ack the 10-bit prefix? */
149 /* send the lower 7-bits (+ read/write mode) */
150 return (i2c_bitbang_write_byte(v
, i2caddr
& 0xff,
151 flags
& ~I2C_F_STOP
, ops
));
158 i2c_bitbang_read_byte(void *v
, uint8_t *valp
, int flags
, i2c_bitbang_ops_t ops
)
164 /* assume SCL=L, SDA=L here */
168 for (i
= 0; i
< 8; i
++) {
171 /* data is set at SCL H->L edge */
172 /* SDA is set here because DIR() is INPUT */
174 delay(5); /* clock low time (4.7 us) */
176 /* read data at SCL L->H edge */
178 if (i2c_wait_for_scl(v
, ops
) != 0)
182 delay(4); /* clock high time (4.0 us) */
184 /* set SCL H->L before set SDA direction OUTPUT */
187 /* set ack after SCL H->L edge */
188 bit
= (flags
& I2C_F_LAST
) ? SDA
: 0;
191 delay(5); /* clock low time (4.7 us) */
193 /* ack is checked at SCL L->H edge */
195 if (i2c_wait_for_scl(v
, ops
) != 0)
197 delay(4); /* clock high time (4.0 us) */
199 /* set SCL H->L for next data; don't change SDA here */
202 /* leave SCL=L and SDL=L to avoid unexpected start/stop condition */
206 if ((flags
& (I2C_F_STOP
| I2C_F_LAST
)) == (I2C_F_STOP
| I2C_F_LAST
))
207 (void) i2c_bitbang_send_stop(v
, flags
, ops
);
214 i2c_bitbang_write_byte(void *v
, uint8_t val
, int flags
, i2c_bitbang_ops_t ops
)
220 /* assume at SCL=L, SDA=L here */
224 for (mask
= 0x80; mask
!= 0; mask
>>= 1) {
225 bit
= (val
& mask
) ? SDA
: 0;
227 /* set data after SCL H->L edge */
229 delay(5); /* clock low time (4.7 us) */
231 /* data is fetched at SCL L->H edge */
233 if (i2c_wait_for_scl(v
, ops
))
235 delay(4); /* clock high time (4.0 us) */
237 /* put SCL H->L edge; don't change SDA here */
241 /* ack is set at H->L edge */
243 delay(5); /* clock low time (4.7 us) */
245 /* read ack at L->H edge */
246 /* SDA is set here because DIR() is INPUT */
248 if (i2c_wait_for_scl(v
, ops
) != 0)
250 error
= (READ
& SDA
) ? EIO
: 0;
251 delay(4); /* clock high time (4.0 us) */
253 /* set SCL H->L before set SDA direction OUTPUT */
256 /* leave SCL=L and SDL=L to avoid unexpected start/stop condition */
259 if (flags
& I2C_F_STOP
)
260 (void) i2c_bitbang_send_stop(v
, flags
, ops
);