iicbb.c revision 302408
1/*-
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
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
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
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/11/sys/dev/iicbus/iicbb.c 289657 2015-10-20 19:52:59Z dumbbell $");
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 */
45
46#include "opt_platform.h"
47
48#include <sys/param.h>
49#include <sys/kernel.h>
50#include <sys/systm.h>
51#include <sys/module.h>
52#include <sys/bus.h>
53#include <sys/uio.h>
54
55#ifdef FDT
56#include <dev/ofw/ofw_bus.h>
57#include <dev/ofw/ofw_bus_subr.h>
58#include <dev/fdt/fdt_common.h>
59#endif
60
61#include <dev/iicbus/iiconf.h>
62#include <dev/iicbus/iicbus.h>
63
64#include <dev/smbus/smbconf.h>
65
66#include "iicbus_if.h"
67#include "iicbb_if.h"
68
69struct iicbb_softc {
70	device_t iicbus;
71	int udelay;		/* signal toggle delay in usec */
72};
73
74static int iicbb_attach(device_t);
75static void iicbb_child_detached(device_t, device_t);
76static int iicbb_detach(device_t);
77static int iicbb_print_child(device_t, device_t);
78static int iicbb_probe(device_t);
79
80static int iicbb_callback(device_t, int, caddr_t);
81static int iicbb_start(device_t, u_char, int);
82static int iicbb_stop(device_t);
83static int iicbb_write(device_t, const char *, int, int *, int);
84static int iicbb_read(device_t, char *, int, int *, int, int);
85static int iicbb_reset(device_t, u_char, u_char, u_char *);
86static int iicbb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs);
87#ifdef FDT
88static phandle_t iicbb_get_node(device_t, device_t);
89#endif
90
91static device_method_t iicbb_methods[] = {
92	/* device interface */
93	DEVMETHOD(device_probe,		iicbb_probe),
94	DEVMETHOD(device_attach,	iicbb_attach),
95	DEVMETHOD(device_detach,	iicbb_detach),
96
97	/* bus interface */
98	DEVMETHOD(bus_child_detached,	iicbb_child_detached),
99	DEVMETHOD(bus_print_child,	iicbb_print_child),
100
101	/* iicbus interface */
102	DEVMETHOD(iicbus_callback,	iicbb_callback),
103	DEVMETHOD(iicbus_start,		iicbb_start),
104	DEVMETHOD(iicbus_repeated_start, iicbb_start),
105	DEVMETHOD(iicbus_stop,		iicbb_stop),
106	DEVMETHOD(iicbus_write,		iicbb_write),
107	DEVMETHOD(iicbus_read,		iicbb_read),
108	DEVMETHOD(iicbus_reset,		iicbb_reset),
109	DEVMETHOD(iicbus_transfer,	iicbb_transfer),
110
111#ifdef FDT
112	/* ofw_bus interface */
113	DEVMETHOD(ofw_bus_get_node,	iicbb_get_node),
114#endif
115
116	{ 0, 0 }
117};
118
119driver_t iicbb_driver = {
120	"iicbb",
121	iicbb_methods,
122	sizeof(struct iicbb_softc),
123};
124
125devclass_t iicbb_devclass;
126
127static int
128iicbb_probe(device_t dev)
129{
130	device_set_desc(dev, "I2C bit-banging driver");
131
132	return (0);
133}
134
135static int
136iicbb_attach(device_t dev)
137{
138	struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
139
140	sc->iicbus = device_add_child(dev, "iicbus", -1);
141	if (!sc->iicbus)
142		return (ENXIO);
143	sc->udelay = 10;		/* 10 uS default */
144	bus_generic_attach(dev);
145
146	return (0);
147}
148
149static int
150iicbb_detach(device_t dev)
151{
152
153	bus_generic_detach(dev);
154	device_delete_children(dev);
155
156	return (0);
157}
158
159#ifdef FDT
160static phandle_t
161iicbb_get_node(device_t bus, device_t dev)
162{
163
164	/* We only have one child, the I2C bus, which needs our own node. */
165	return (ofw_bus_get_node(bus));
166}
167#endif
168
169static void
170iicbb_child_detached( device_t dev, device_t child )
171{
172	struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
173
174	if (child == sc->iicbus)
175		sc->iicbus = NULL;
176}
177
178static int
179iicbb_print_child(device_t bus, device_t dev)
180{
181	int error;
182	int retval = 0;
183	u_char oldaddr;
184
185	retval += bus_print_child_header(bus, dev);
186	/* retrieve the interface I2C address */
187	error = IICBB_RESET(device_get_parent(bus), IIC_FASTEST, 0, &oldaddr);
188	if (error == IIC_ENOADDR) {
189		retval += printf(" on %s master-only\n",
190				 device_get_nameunit(bus));
191	} else {
192		/* restore the address */
193		IICBB_RESET(device_get_parent(bus), IIC_FASTEST, oldaddr, NULL);
194
195		retval += printf(" on %s addr 0x%x\n",
196				 device_get_nameunit(bus), oldaddr & 0xff);
197	}
198
199	return (retval);
200}
201
202#define I2C_SETSDA(sc,dev,val) do {			\
203	IICBB_SETSDA(device_get_parent(dev), val);	\
204	DELAY(sc->udelay);				\
205	} while (0)
206
207#define I2C_SETSCL(dev,val) do {			\
208	iicbb_setscl(dev, val, 100);			\
209	} while (0)
210
211#define I2C_SET(sc,dev,ctrl,data) do {			\
212	I2C_SETSCL(dev, ctrl);				\
213	I2C_SETSDA(sc, dev, data);			\
214	} while (0)
215
216#define I2C_GETSDA(dev) (IICBB_GETSDA(device_get_parent(dev)))
217
218#define I2C_GETSCL(dev) (IICBB_GETSCL(device_get_parent(dev)))
219
220static int i2c_debug = 0;
221#define I2C_DEBUG(x)	do {					\
222				if (i2c_debug) (x);		\
223			} while (0)
224
225#define I2C_LOG(format,args...)	do {				\
226					printf(format, args);	\
227				} while (0)
228
229static void
230iicbb_setscl(device_t dev, int val, int timeout)
231{
232	struct iicbb_softc *sc = device_get_softc(dev);
233	int k = 0;
234
235	IICBB_SETSCL(device_get_parent(dev), val);
236	DELAY(sc->udelay);
237
238	while (val && !I2C_GETSCL(dev) && k++ < timeout) {
239		IICBB_SETSCL(device_get_parent(dev), val);
240		DELAY(sc->udelay);
241	}
242
243	return;
244}
245
246static void
247iicbb_one(device_t dev, int timeout)
248{
249	struct iicbb_softc *sc = device_get_softc(dev);
250
251	I2C_SET(sc,dev,0,1);
252	I2C_SET(sc,dev,1,1);
253	I2C_SET(sc,dev,0,1);
254	return;
255}
256
257static void
258iicbb_zero(device_t dev, int timeout)
259{
260	struct iicbb_softc *sc = device_get_softc(dev);
261
262	I2C_SET(sc,dev,0,0);
263	I2C_SET(sc,dev,1,0);
264	I2C_SET(sc,dev,0,0);
265	return;
266}
267
268/*
269 * Waiting for ACKNOWLEDGE.
270 *
271 * When a chip is being addressed or has received data it will issue an
272 * ACKNOWLEDGE pulse. Therefore the MASTER must release the DATA line
273 * (set it to high level) and then release the CLOCK line.
274 * Now it must wait for the SLAVE to pull the DATA line low.
275 * Actually on the bus this looks like a START condition so nothing happens
276 * because of the fact that the IC's that have not been addressed are doing
277 * nothing.
278 *
279 * When the SLAVE has pulled this line low the MASTER will take the CLOCK
280 * line low and then the SLAVE will release the SDA (data) line.
281 */
282static int
283iicbb_ack(device_t dev, int timeout)
284{
285	struct iicbb_softc *sc = device_get_softc(dev);
286	int noack;
287	int k = 0;
288
289	I2C_SET(sc,dev,0,1);
290	I2C_SET(sc,dev,1,1);
291	do {
292		noack = I2C_GETSDA(dev);
293		if (!noack)
294			break;
295		DELAY(1);
296		k++;
297	} while (k < timeout);
298
299	I2C_SET(sc,dev,0,1);
300	I2C_DEBUG(printf("%c ",noack?'-':'+'));
301
302	return (noack);
303}
304
305static void
306iicbb_sendbyte(device_t dev, u_char data, int timeout)
307{
308	int i;
309
310	for (i=7; i>=0; i--) {
311		if (data&(1<<i)) {
312			iicbb_one(dev, timeout);
313		} else {
314			iicbb_zero(dev, timeout);
315		}
316	}
317	I2C_DEBUG(printf("w%02x",(int)data));
318	return;
319}
320
321static u_char
322iicbb_readbyte(device_t dev, int last, int timeout)
323{
324	struct iicbb_softc *sc = device_get_softc(dev);
325	int i;
326	unsigned char data=0;
327
328	I2C_SET(sc,dev,0,1);
329	for (i=7; i>=0; i--)
330	{
331		I2C_SET(sc,dev,1,1);
332		if (I2C_GETSDA(dev))
333			data |= (1<<i);
334		I2C_SET(sc,dev,0,1);
335	}
336	if (last) {
337		iicbb_one(dev, timeout);
338	} else {
339		iicbb_zero(dev, timeout);
340	}
341	I2C_DEBUG(printf("r%02x%c ",(int)data,last?'-':'+'));
342	return data;
343}
344
345static int
346iicbb_callback(device_t dev, int index, caddr_t data)
347{
348	return (IICBB_CALLBACK(device_get_parent(dev), index, data));
349}
350
351static int
352iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
353{
354	return (IICBB_RESET(device_get_parent(dev), speed, addr, oldaddr));
355}
356
357static int
358iicbb_start(device_t dev, u_char slave, int timeout)
359{
360	struct iicbb_softc *sc = device_get_softc(dev);
361	int error;
362
363	I2C_DEBUG(printf("<"));
364
365	I2C_SET(sc,dev,1,1);
366	I2C_SET(sc,dev,1,0);
367	I2C_SET(sc,dev,0,0);
368
369	/* send address */
370	iicbb_sendbyte(dev, slave, timeout);
371
372	/* check for ack */
373	if (iicbb_ack(dev, timeout)) {
374		error = IIC_ENOACK;
375		goto error;
376	}
377
378	return(0);
379
380error:
381	iicbb_stop(dev);
382	return (error);
383}
384
385static int
386iicbb_stop(device_t dev)
387{
388	struct iicbb_softc *sc = device_get_softc(dev);
389
390	I2C_SET(sc,dev,0,0);
391	I2C_SET(sc,dev,1,0);
392	I2C_SET(sc,dev,1,1);
393	I2C_DEBUG(printf(">"));
394	I2C_DEBUG(printf("\n"));
395	return (0);
396}
397
398static int
399iicbb_write(device_t dev, const char *buf, int len, int *sent, int timeout)
400{
401	int bytes, error = 0;
402
403	bytes = 0;
404	while (len) {
405		/* send byte */
406		iicbb_sendbyte(dev,(u_char)*buf++, timeout);
407
408		/* check for ack */
409		if (iicbb_ack(dev, timeout)) {
410			error = IIC_ENOACK;
411			goto error;
412		}
413		bytes ++;
414		len --;
415	}
416
417error:
418	*sent = bytes;
419	return (error);
420}
421
422static int
423iicbb_read(device_t dev, char * buf, int len, int *read, int last, int delay)
424{
425	int bytes;
426
427	bytes = 0;
428	while (len) {
429		/* XXX should insert delay here */
430		*buf++ = (char)iicbb_readbyte(dev, (len == 1) ? last : 0, delay);
431
432		bytes ++;
433		len --;
434	}
435
436	*read = bytes;
437	return (0);
438}
439
440static int
441iicbb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
442{
443	int error;
444
445	error = IICBB_PRE_XFER(device_get_parent(dev));
446	if (error)
447		return (error);
448
449	error = iicbus_transfer_gen(dev, msgs, nmsgs);
450
451	IICBB_POST_XFER(device_get_parent(dev));
452	return (error);
453}
454
455DRIVER_MODULE(iicbus, iicbb, iicbus_driver, iicbus_devclass, 0, 0);
456
457MODULE_DEPEND(iicbb, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
458MODULE_VERSION(iicbb, IICBB_MODVER);
459