Deleted Added
full compact
iicbb.c (67164) iicbb.c (93023)
1/*-
1/*-
2 * Copyright (c) 1998 Nicolas Souchu
2 * Copyright (c) 1998, 2001 Nicolas Souchu
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/iicbus/iicbb.c 67164 2000-10-15 14:19:01Z phk $
26 * $FreeBSD: head/sys/dev/iicbus/iicbb.c 93023 2002-03-23 15:49:15Z nsouch $
27 *
28 */
29
30/*
31 * Generic I2C bit-banging code
32 *
33 * Example:
34 *
35 * iicbus
36 * / \
37 * iicbb pcf
38 * | \
39 * bti2c lpbb
40 *
41 * From Linux I2C generic interface
42 * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
43 *
27 *
28 */
29
30/*
31 * Generic I2C bit-banging code
32 *
33 * Example:
34 *
35 * iicbus
36 * / \
37 * iicbb pcf
38 * | \
39 * bti2c lpbb
40 *
41 * From Linux I2C generic interface
42 * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
43 *
44 * TODO: port Peter's generic bit-banging code <dufault@hda.com>
45 */
46
47#include <sys/param.h>
48#include <sys/kernel.h>
49#include <sys/systm.h>
50#include <sys/module.h>
51#include <sys/bus.h>
52#include <sys/uio.h>
53
54
55#include <dev/iicbus/iiconf.h>
56#include <dev/iicbus/iicbus.h>
57
58#include <dev/smbus/smbconf.h>
59
60#include "iicbus_if.h"
61#include "iicbb_if.h"
62
63struct iicbb_softc {
44 */
45
46#include <sys/param.h>
47#include <sys/kernel.h>
48#include <sys/systm.h>
49#include <sys/module.h>
50#include <sys/bus.h>
51#include <sys/uio.h>
52
53
54#include <dev/iicbus/iiconf.h>
55#include <dev/iicbus/iicbus.h>
56
57#include <dev/smbus/smbconf.h>
58
59#include "iicbus_if.h"
60#include "iicbb_if.h"
61
62struct iicbb_softc {
64 int dummy;
63 device_t iicbus;
65};
66
67static int iicbb_probe(device_t);
68static int iicbb_attach(device_t);
64};
65
66static int iicbb_probe(device_t);
67static int iicbb_attach(device_t);
68static int iicbb_detach(device_t);
69static int iicbb_print_child(device_t, device_t);
70
71static int iicbb_callback(device_t, int, caddr_t);
72static int iicbb_start(device_t, u_char, int);
73static int iicbb_stop(device_t);
74static int iicbb_write(device_t, char *, int, int *, int);
75static int iicbb_read(device_t, char *, int, int *, int, int);
76static int iicbb_reset(device_t, u_char, u_char, u_char *);
77
78static device_method_t iicbb_methods[] = {
79 /* device interface */
80 DEVMETHOD(device_probe, iicbb_probe),
81 DEVMETHOD(device_attach, iicbb_attach),
69static int iicbb_print_child(device_t, device_t);
70
71static int iicbb_callback(device_t, int, caddr_t);
72static int iicbb_start(device_t, u_char, int);
73static int iicbb_stop(device_t);
74static int iicbb_write(device_t, char *, int, int *, int);
75static int iicbb_read(device_t, char *, int, int *, int, int);
76static int iicbb_reset(device_t, u_char, u_char, u_char *);
77
78static device_method_t iicbb_methods[] = {
79 /* device interface */
80 DEVMETHOD(device_probe, iicbb_probe),
81 DEVMETHOD(device_attach, iicbb_attach),
82 DEVMETHOD(device_detach, bus_generic_detach),
82 DEVMETHOD(device_detach, iicbb_detach),
83
84 /* bus interface */
85 DEVMETHOD(bus_print_child, iicbb_print_child),
86
87 /* iicbus interface */
88 DEVMETHOD(iicbus_callback, iicbb_callback),
89 DEVMETHOD(iicbus_start, iicbb_start),
90 DEVMETHOD(iicbus_repeated_start, iicbb_start),

--- 10 unchanged lines hidden (view full) ---

101 iicbb_methods,
102 sizeof(struct iicbb_softc),
103};
104
105static devclass_t iicbb_devclass;
106
107static int iicbb_probe(device_t dev)
108{
83
84 /* bus interface */
85 DEVMETHOD(bus_print_child, iicbb_print_child),
86
87 /* iicbus interface */
88 DEVMETHOD(iicbus_callback, iicbb_callback),
89 DEVMETHOD(iicbus_start, iicbb_start),
90 DEVMETHOD(iicbus_repeated_start, iicbb_start),

--- 10 unchanged lines hidden (view full) ---

101 iicbb_methods,
102 sizeof(struct iicbb_softc),
103};
104
105static devclass_t iicbb_devclass;
106
107static int iicbb_probe(device_t dev)
108{
109 device_set_desc(dev, "I2C generic bit-banging driver");
109 device_set_desc(dev, "I2C bit-banging driver");
110
111 return (0);
112}
113
114static int iicbb_attach(device_t dev)
115{
110
111 return (0);
112}
113
114static int iicbb_attach(device_t dev)
115{
116 struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
117
118 bzero(sc, sizeof(struct iicbb_softc));
119
120 sc->iicbus = device_add_child(dev, "iicbus", -1);
121
122 if (!sc->iicbus)
123 return (ENXIO);
124
125 bus_generic_attach(dev);
126
116 return (0);
117}
118
127 return (0);
128}
129
130static int iicbb_detach(device_t dev)
131{
132 struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
133
134 if (sc->iicbus) {
135 bus_generic_detach(dev);
136 device_delete_child(dev, sc->iicbus);
137 }
138
139 return (0);
140}
141
119static int
120iicbb_print_child(device_t bus, device_t dev)
121{
122 int error;
123 int retval = 0;
124 u_char oldaddr;
125
126 retval += bus_print_child_header(bus, dev);

--- 8 unchanged lines hidden (view full) ---

135
136 retval += printf(" on %s addr 0x%x\n",
137 device_get_nameunit(bus), oldaddr & 0xff);
138 }
139
140 return (retval);
141}
142
142static int
143iicbb_print_child(device_t bus, device_t dev)
144{
145 int error;
146 int retval = 0;
147 u_char oldaddr;
148
149 retval += bus_print_child_header(bus, dev);

--- 8 unchanged lines hidden (view full) ---

158
159 retval += printf(" on %s addr 0x%x\n",
160 device_get_nameunit(bus), oldaddr & 0xff);
161 }
162
163 return (retval);
164}
165
143#define I2C_SET(dev,ctrl,data) \
144 IICBB_SETLINES(device_get_parent(dev), ctrl, data)
166#define IIC_DELAY 10
145
167
146#define I2C_GET(dev) (IICBB_GETDATALINE(device_get_parent(dev)))
168#define I2C_SETSDA(dev,val) do { \
169 IICBB_SETSDA(device_get_parent(dev), val); \
170 DELAY(IIC_DELAY); \
171 } while (0)
147
172
173#define I2C_SETSCL(dev,val) do { \
174 iicbb_setscl(dev, val, 100); \
175 } while (0)
176
177#define I2C_SET(dev,ctrl,data) do { \
178 I2C_SETSCL(dev, ctrl); \
179 I2C_SETSDA(dev, data); \
180 } while (0)
181
182#define I2C_GETSDA(dev) (IICBB_GETSDA(device_get_parent(dev)))
183
184#define I2C_GETSCL(dev) (IICBB_GETSCL(device_get_parent(dev)))
185
148static int i2c_debug = 0;
186static int i2c_debug = 0;
149#define I2C_DEBUG(x) if (i2c_debug) (x)
187#define I2C_DEBUG(x) do { \
188 if (i2c_debug) (x); \
189 } while (0)
150
190
151static void iicbb_one(device_t dev)
191#define I2C_LOG(format,args...) do { \
192 printf(format, args); \
193 } while (0)
194
195static void iicbb_setscl(device_t dev, int val, int timeout)
152{
196{
197 int k = 0;
198
199 IICBB_SETSCL(device_get_parent(dev), val);
200 DELAY(IIC_DELAY);
201
202 while (val && !I2C_GETSCL(dev) && k++ < timeout) {
203 IICBB_SETSCL(device_get_parent(dev), val);
204 DELAY(IIC_DELAY);
205 }
206
207 return;
208}
209
210static void iicbb_one(device_t dev, int timeout)
211{
153 I2C_SET(dev,0,1);
154 I2C_SET(dev,1,1);
155 I2C_SET(dev,0,1);
156 return;
157}
158
212 I2C_SET(dev,0,1);
213 I2C_SET(dev,1,1);
214 I2C_SET(dev,0,1);
215 return;
216}
217
159static void iicbb_zero(device_t dev)
218static void iicbb_zero(device_t dev, int timeout)
160{
161 I2C_SET(dev,0,0);
162 I2C_SET(dev,1,0);
163 I2C_SET(dev,0,0);
164 return;
165}
166
167/*

--- 8 unchanged lines hidden (view full) ---

176 * nothing.
177 *
178 * When the SLAVE has pulled this line low the MASTER will take the CLOCK
179 * line low and then the SLAVE will release the SDA (data) line.
180 */
181static int iicbb_ack(device_t dev, int timeout)
182{
183 int noack;
219{
220 I2C_SET(dev,0,0);
221 I2C_SET(dev,1,0);
222 I2C_SET(dev,0,0);
223 return;
224}
225
226/*

--- 8 unchanged lines hidden (view full) ---

235 * nothing.
236 *
237 * When the SLAVE has pulled this line low the MASTER will take the CLOCK
238 * line low and then the SLAVE will release the SDA (data) line.
239 */
240static int iicbb_ack(device_t dev, int timeout)
241{
242 int noack;
184 int k = timeout/10;
243 int k = 0;
185
186 I2C_SET(dev,0,1);
187 I2C_SET(dev,1,1);
244
245 I2C_SET(dev,0,1);
246 I2C_SET(dev,1,1);
188
189 do {
247 do {
190 noack = I2C_GET(dev);
248 noack = I2C_GETSDA(dev);
191 if (!noack)
192 break;
249 if (!noack)
250 break;
193 DELAY(10); /* XXX wait 10us */
194 } while (k--);
251 DELAY(10);
252 k += 10;
253 } while (k < timeout);
195
196 I2C_SET(dev,0,1);
197 I2C_DEBUG(printf("%c ",noack?'-':'+'));
198
199 return (noack);
200}
201
254
255 I2C_SET(dev,0,1);
256 I2C_DEBUG(printf("%c ",noack?'-':'+'));
257
258 return (noack);
259}
260
202static void iicbb_sendbyte(device_t dev, u_char data)
261static void iicbb_sendbyte(device_t dev, u_char data, int timeout)
203{
204 int i;
205
262{
263 int i;
264
206 I2C_SET(dev,0,0);
207 for (i=7; i>=0; i--)
208 (data&(1<<i)) ? iicbb_one(dev) : iicbb_zero(dev);
265 for (i=7; i>=0; i--) {
266 if (data&(1<<i)) {
267 iicbb_one(dev, timeout);
268 } else {
269 iicbb_zero(dev, timeout);
270 }
271 }
209 I2C_DEBUG(printf("w%02x",(int)data));
210 return;
211}
212
272 I2C_DEBUG(printf("w%02x",(int)data));
273 return;
274}
275
213static u_char iicbb_readbyte(device_t dev, int last)
276static u_char iicbb_readbyte(device_t dev, int last, int timeout)
214{
215 int i;
216 unsigned char data=0;
217
218 I2C_SET(dev,0,1);
219 for (i=7; i>=0; i--)
220 {
221 I2C_SET(dev,1,1);
277{
278 int i;
279 unsigned char data=0;
280
281 I2C_SET(dev,0,1);
282 for (i=7; i>=0; i--)
283 {
284 I2C_SET(dev,1,1);
222 if (I2C_GET(dev))
285 if (I2C_GETSDA(dev))
223 data |= (1<<i);
224 I2C_SET(dev,0,1);
225 }
286 data |= (1<<i);
287 I2C_SET(dev,0,1);
288 }
226 last ? iicbb_one(dev) : iicbb_zero(dev);
289 if (last) {
290 iicbb_one(dev, timeout);
291 } else {
292 iicbb_zero(dev, timeout);
293 }
227 I2C_DEBUG(printf("r%02x%c ",(int)data,last?'-':'+'));
228 return data;
229}
230
231static int iicbb_callback(device_t dev, int index, caddr_t data)
232{
233 return (IICBB_CALLBACK(device_get_parent(dev), index, data));
234}

--- 4 unchanged lines hidden (view full) ---

239}
240
241static int iicbb_start(device_t dev, u_char slave, int timeout)
242{
243 int error;
244
245 I2C_DEBUG(printf("<"));
246
294 I2C_DEBUG(printf("r%02x%c ",(int)data,last?'-':'+'));
295 return data;
296}
297
298static int iicbb_callback(device_t dev, int index, caddr_t data)
299{
300 return (IICBB_CALLBACK(device_get_parent(dev), index, data));
301}

--- 4 unchanged lines hidden (view full) ---

306}
307
308static int iicbb_start(device_t dev, u_char slave, int timeout)
309{
310 int error;
311
312 I2C_DEBUG(printf("<"));
313
247 I2C_SET(dev,0,1);
248 I2C_SET(dev,1,1);
249 I2C_SET(dev,1,0);
250 I2C_SET(dev,0,0);
251
252 /* send address */
314 I2C_SET(dev,1,1);
315 I2C_SET(dev,1,0);
316 I2C_SET(dev,0,0);
317
318 /* send address */
253 iicbb_sendbyte(dev, slave);
319 iicbb_sendbyte(dev, slave, timeout);
254
255 /* check for ack */
256 if (iicbb_ack(dev, timeout)) {
257 error = IIC_ENOACK;
258 goto error;
259 }
260
261 return(0);

--- 15 unchanged lines hidden (view full) ---

277static int iicbb_write(device_t dev, char * buf, int len, int *sent,
278 int timeout)
279{
280 int bytes, error = 0;
281
282 bytes = 0;
283 while (len) {
284 /* send byte */
320
321 /* check for ack */
322 if (iicbb_ack(dev, timeout)) {
323 error = IIC_ENOACK;
324 goto error;
325 }
326
327 return(0);

--- 15 unchanged lines hidden (view full) ---

343static int iicbb_write(device_t dev, char * buf, int len, int *sent,
344 int timeout)
345{
346 int bytes, error = 0;
347
348 bytes = 0;
349 while (len) {
350 /* send byte */
285 iicbb_sendbyte(dev,(u_char)*buf++);
351 iicbb_sendbyte(dev,(u_char)*buf++, timeout);
286
287 /* check for ack */
288 if (iicbb_ack(dev, timeout)) {
289 error = IIC_ENOACK;
290 goto error;
291 }
292 bytes ++;
293 len --;

--- 7 unchanged lines hidden (view full) ---

301static int iicbb_read(device_t dev, char * buf, int len, int *read,
302 int last, int delay)
303{
304 int bytes;
305
306 bytes = 0;
307 while (len) {
308 /* XXX should insert delay here */
352
353 /* check for ack */
354 if (iicbb_ack(dev, timeout)) {
355 error = IIC_ENOACK;
356 goto error;
357 }
358 bytes ++;
359 len --;

--- 7 unchanged lines hidden (view full) ---

367static int iicbb_read(device_t dev, char * buf, int len, int *read,
368 int last, int delay)
369{
370 int bytes;
371
372 bytes = 0;
373 while (len) {
374 /* XXX should insert delay here */
309 *buf++ = (char)iicbb_readbyte(dev, (len == 1) ? last : 0);
375 *buf++ = (char)iicbb_readbyte(dev, (len == 1) ? last : 0, delay);
310
311 bytes ++;
312 len --;
313 }
314
315 *read = bytes;
316 return (0);
317}
318
376
377 bytes ++;
378 len --;
379 }
380
381 *read = bytes;
382 return (0);
383}
384
319DRIVER_MODULE(iicbb, bti2c, iicbb_driver, iicbb_devclass, 0, 0);
385DRIVER_MODULE(iicbb, bktr, iicbb_driver, iicbb_devclass, 0, 0);
320DRIVER_MODULE(iicbb, lpbb, iicbb_driver, iicbb_devclass, 0, 0);
386DRIVER_MODULE(iicbb, lpbb, iicbb_driver, iicbb_devclass, 0, 0);
387DRIVER_MODULE(iicbb, viapm, iicbb_driver, iicbb_devclass, 0, 0);
388
389MODULE_DEPEND(iicbb, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
390MODULE_VERSION(iicbb, IICBB_MODVER);