xref: /freebsd/sys/dev/pcf/pcf.c (revision 732a02b4e77866604a120a275c082bb6221bd2ff)
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$");
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 
54 static int pcf_wait_byte(struct pcf_softc *pcf);
55 static int pcf_noack(struct pcf_softc *pcf, int timeout);
56 static 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  */
62 static int
63 pcf_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 
81 static void
82 pcf_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 
103 static int
104 pcf_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 
120 int
121 pcf_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 
154 error:
155 	pcf_stop_locked(sc);
156 	PCF_UNLOCK(sc);
157 	return (error);
158 }
159 
160 int
161 pcf_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 
203 error:
204 	pcf_stop_locked(sc);
205 	PCF_UNLOCK(sc);
206 	return (error);
207 }
208 
209 int
210 pcf_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 
224 void
225 pcf_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 
323 error:
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 
333 int
334 pcf_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 
382 int
383 pcf_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 
413 error:
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 
424 int
425 pcf_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 
473 error:
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 
485 DRIVER_MODULE(iicbus, pcf, iicbus_driver, iicbus_devclass, 0, 0);
486 MODULE_DEPEND(pcf, iicbus, PCF_MINVER, PCF_PREFVER, PCF_MAXVER);
487 MODULE_VERSION(pcf, PCF_MODVER);
488