pcf.c revision 129893
1/*-
2 * Copyright (c) 1998 Nicolas Souchu, Marc Bouget
3 * Copyright (c) 2004 Joerg Wunsch
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/dev/pcf/pcf.c 129893 2004-05-31 14:24:21Z nsouch $");
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/kernel.h>
34#include <sys/module.h>
35#include <sys/bus.h>
36
37#include <machine/bus.h>
38#include <machine/resource.h>
39
40#include <sys/rman.h>
41
42#include <dev/iicbus/iiconf.h>
43#include <dev/pcf/pcfvar.h>
44#include "iicbus_if.h"
45
46/* Not so official debugging option. */
47/* #define PCFDEBUG */
48
49static int pcf_wait_byte(struct pcf_softc *pcf);
50static int pcf_noack(struct pcf_softc *pcf, int timeout);
51
52/*
53 * Polling mode for master operations wait for a new
54 * byte incomming or outgoing
55 */
56int
57pcf_wait_byte(struct pcf_softc *sc)
58{
59	int counter = TIMEOUT;
60
61	while (counter--) {
62
63		if ((pcf_get_S1(sc) & PIN) == 0)
64			return (0);
65	}
66
67#ifdef PCFDEBUG
68	printf("pcf: timeout!\n");
69#endif
70
71	return (IIC_ETIMEOUT);
72}
73
74int
75pcf_stop(device_t dev)
76{
77	struct pcf_softc *sc = DEVTOSOFTC(dev);
78
79#ifdef PCFDEBUG
80	device_printf(dev, " >> stop\n");
81#endif
82	/*
83	 * Send STOP condition iff the START condition was previously sent.
84	 * STOP is sent only once even if an iicbus_stop() is called after
85	 * an iicbus_read()... see pcf_read(): the PCF needs to send the stop
86	 * before the last char is read.
87	 */
88	if (sc->pcf_started) {
89		/* set stop condition and enable IT */
90		pcf_set_S1(sc, PIN|ESO|ENI|STO|ACK);
91
92		sc->pcf_started = 0;
93	}
94
95	return (0);
96}
97
98
99int
100pcf_noack(struct pcf_softc *sc, int timeout)
101{
102	int noack;
103	int k = timeout/10;
104
105	do {
106		noack = pcf_get_S1(sc) & LRB;
107		if (!noack)
108			break;
109		DELAY(10);				/* XXX wait 10 us */
110	} while (k--);
111
112	return (noack);
113}
114
115int
116pcf_repeated_start(device_t dev, u_char slave, int timeout)
117{
118	struct pcf_softc *sc = DEVTOSOFTC(dev);
119	int error = 0;
120
121#ifdef PCFDEBUG
122	device_printf(dev, " >> repeated start for slave %#x\n",
123		      (unsigned)slave);
124#endif
125	/* repeated start */
126	pcf_set_S1(sc, ESO|STA|STO|ACK);
127
128	/* set slave address to PCF. Last bit (LSB) must be set correctly
129	 * according to transfer direction */
130	pcf_set_S0(sc, slave);
131
132	/* wait for address sent, polling */
133	if ((error = pcf_wait_byte(sc)))
134		goto error;
135
136	/* check for ack */
137	if (pcf_noack(sc, timeout)) {
138		error = IIC_ENOACK;
139#ifdef PCFDEBUG
140		printf("pcf: no ack on repeated_start!\n");
141#endif
142		goto error;
143	}
144
145	return (0);
146
147error:
148	pcf_stop(dev);
149	return (error);
150}
151
152int
153pcf_start(device_t dev, u_char slave, int timeout)
154{
155	struct pcf_softc *sc = DEVTOSOFTC(dev);
156	int error = 0;
157
158#ifdef PCFDEBUG
159	device_printf(dev, " >> start for slave %#x\n", (unsigned)slave);
160#endif
161	if ((pcf_get_S1(sc) & nBB) == 0) {
162#ifdef PCFDEBUG
163		printf("pcf: busy!\n");
164#endif
165		return (IIC_EBUSBSY);
166	}
167
168	/* set slave address to PCF. Last bit (LSB) must be set correctly
169	 * according to transfer direction */
170	pcf_set_S0(sc, slave);
171
172	/* START only */
173	pcf_set_S1(sc, PIN|ESO|STA|ACK);
174
175	sc->pcf_started = 1;
176
177	/* wait for address sent, polling */
178	if ((error = pcf_wait_byte(sc)))
179		goto error;
180
181	/* check for ACK */
182	if (pcf_noack(sc, timeout)) {
183		error = IIC_ENOACK;
184#ifdef PCFDEBUG
185		printf("pcf: no ack on start!\n");
186#endif
187		goto error;
188	}
189
190	return (0);
191
192error:
193	pcf_stop(dev);
194	return (error);
195}
196
197void
198pcf_intr(void *arg)
199{
200	struct pcf_softc *sc = arg;
201	char data, status, addr;
202	char error = 0;
203
204	status = pcf_get_S1(sc);
205
206	if (status & PIN) {
207		printf("pcf: spurious interrupt, status=0x%x\n",
208		       status & 0xff);
209
210		goto error;
211	}
212
213	if (status & LAB)
214		printf("pcf: bus arbitration lost!\n");
215
216	if (status & BER) {
217		error = IIC_EBUSERR;
218		iicbus_intr(sc->iicbus, INTR_ERROR, &error);
219
220		goto error;
221	}
222
223	do {
224		status = pcf_get_S1(sc);
225
226		switch(sc->pcf_slave_mode) {
227
228		case SLAVE_TRANSMITTER:
229			if (status & LRB) {
230				/* ack interrupt line */
231				dummy_write(sc);
232
233				/* no ack, don't send anymore */
234				sc->pcf_slave_mode = SLAVE_RECEIVER;
235
236				iicbus_intr(sc->iicbus, INTR_NOACK, NULL);
237				break;
238			}
239
240			/* get data from upper code */
241			iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data);
242
243			pcf_set_S0(sc, data);
244			break;
245
246		case SLAVE_RECEIVER:
247			if (status & AAS) {
248				addr = pcf_get_S0(sc);
249
250				if (status & AD0)
251					iicbus_intr(sc->iicbus, INTR_GENERAL, &addr);
252				else
253					iicbus_intr(sc->iicbus, INTR_START, &addr);
254
255				if (addr & LSB) {
256					sc->pcf_slave_mode = SLAVE_TRANSMITTER;
257
258					/* get the first char from upper code */
259					iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data);
260
261					/* send first data byte */
262					pcf_set_S0(sc, data);
263				}
264
265				break;
266			}
267
268			/* stop condition received? */
269			if (status & STS) {
270				/* ack interrupt line */
271				dummy_read(sc);
272
273				/* emulate intr stop condition */
274				iicbus_intr(sc->iicbus, INTR_STOP, NULL);
275
276			} else {
277				/* get data, ack interrupt line */
278				data = pcf_get_S0(sc);
279
280				/* deliver the character */
281				iicbus_intr(sc->iicbus, INTR_RECEIVE, &data);
282			}
283			break;
284
285		    default:
286			panic("%s: unknown slave mode (%d)!", __func__,
287				sc->pcf_slave_mode);
288		    }
289
290	} while ((pcf_get_S1(sc) & PIN) == 0);
291
292	return;
293
294error:
295	/* unknown event on bus...reset PCF */
296	pcf_set_S1(sc, PIN|ESO|ENI|ACK);
297
298	sc->pcf_slave_mode = SLAVE_RECEIVER;
299
300	return;
301}
302
303int
304pcf_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
305{
306	struct pcf_softc *sc = DEVTOSOFTC(dev);
307
308	if (oldaddr)
309		*oldaddr = sc->pcf_addr;
310
311	/* retrieve own address from bus level */
312	if (!addr)
313		sc->pcf_addr = PCF_DEFAULT_ADDR;
314	else
315		sc->pcf_addr = addr;
316
317	pcf_set_S1(sc, PIN);				/* initialize S1 */
318
319	/* own address S'O<>0 */
320	pcf_set_S0(sc, sc->pcf_addr >> 1);
321
322	/* select clock register */
323	pcf_set_S1(sc, PIN|ES1);
324
325	/* select bus speed : 18=90kb, 19=45kb, 1A=11kb, 1B=1.5kb */
326	switch (speed) {
327	case IIC_SLOW:
328		pcf_set_S0(sc,  0x1b); /* XXX Sun uses 0x1f */
329		break;
330
331	case IIC_FAST:
332		pcf_set_S0(sc,  0x19); /* XXX Sun: 0x1d */
333		break;
334
335	case IIC_UNKNOWN:
336	case IIC_FASTEST:
337	default:
338		pcf_set_S0(sc,  0x18); /* XXX Sun: 0x1c */
339		break;
340	}
341
342	/* set bus on, ack=yes, INT=yes */
343	pcf_set_S1(sc, PIN|ESO|ENI|ACK);
344
345	sc->pcf_slave_mode = SLAVE_RECEIVER;
346
347	return (0);
348}
349
350int
351pcf_write(device_t dev, char *buf, int len, int *sent, int timeout /* us */)
352{
353	struct pcf_softc *sc = DEVTOSOFTC(dev);
354	int bytes, error = 0;
355
356#ifdef PCFDEBUG
357	device_printf(dev, " >> writing %d bytes: %#x%s\n", len,
358		      (unsigned)buf[0], len > 1? "...": "");
359#endif
360
361	bytes = 0;
362	while (len) {
363
364		pcf_set_S0(sc, *buf++);
365
366		/* wait for the byte to be send */
367		if ((error = pcf_wait_byte(sc)))
368			goto error;
369
370		/* check if ack received */
371		if (pcf_noack(sc, timeout)) {
372			error = IIC_ENOACK;
373			goto error;
374		}
375
376		len --;
377		bytes ++;
378	}
379
380error:
381	*sent = bytes;
382
383#ifdef PCFDEBUG
384	device_printf(dev, " >> %d bytes written (%d)\n", bytes, error);
385#endif
386
387	return (error);
388}
389
390int
391pcf_read(device_t dev, char *buf, int len, int *read, int last,
392	 int delay /* us */)
393{
394	struct pcf_softc *sc = DEVTOSOFTC(dev);
395	int bytes, error = 0;
396#ifdef PCFDEBUG
397	char *obuf = buf;
398
399	device_printf(dev, " << reading %d bytes\n", len);
400#endif
401
402	/* trig the bus to get the first data byte in S0 */
403	if (len) {
404		if (len == 1 && last)
405			/* just one byte to read */
406			pcf_set_S1(sc, ESO);		/* no ack */
407
408		dummy_read(sc);
409	}
410
411	bytes = 0;
412	while (len) {
413
414		/* XXX delay needed here */
415
416		/* wait for trigged byte */
417		if ((error = pcf_wait_byte(sc))) {
418			pcf_stop(dev);
419			goto error;
420		}
421
422		if (len == 1 && last)
423			/* ok, last data byte already in S0, no I2C activity
424			 * on next pcf_get_S0() */
425			pcf_stop(dev);
426
427		else if (len == 2 && last)
428			/* next trigged byte with no ack */
429			pcf_set_S1(sc, ESO);
430
431		/* receive byte, trig next byte */
432		*buf++ = pcf_get_S0(sc);
433
434		len --;
435		bytes ++;
436	};
437
438error:
439	*read = bytes;
440
441#ifdef PCFDEBUG
442	device_printf(dev, " << %d bytes read (%d): %#x%s\n", bytes, error,
443		      (unsigned)obuf[0], bytes > 1? "...": "");
444#endif
445
446	return (error);
447}
448