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