xref: /freebsd/sys/dev/pcf/pcf.c (revision d7d962ead0b6e5e8a39202d0590022082bf5bfb6)
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 		if ((pcf_get_S1(sc) & PIN) == 0)
70 			return (0);
71 	}
72 
73 #ifdef PCFDEBUG
74 	printf("pcf: timeout!\n");
75 #endif
76 
77 	return (IIC_ETIMEOUT);
78 }
79 
80 static void
81 pcf_stop_locked(struct pcf_softc *sc)
82 {
83 
84 	PCF_ASSERT_LOCKED(sc);
85 #ifdef PCFDEBUG
86 	device_printf(dev, " >> stop\n");
87 #endif
88 	/*
89 	 * Send STOP condition iff the START condition was previously sent.
90 	 * STOP is sent only once even if an iicbus_stop() is called after
91 	 * an iicbus_read()... see pcf_read(): the PCF needs to send the stop
92 	 * before the last char is read.
93 	 */
94 	if (sc->pcf_started) {
95 		/* set stop condition and enable IT */
96 		pcf_set_S1(sc, PIN|ESO|ENI|STO|ACK);
97 
98 		sc->pcf_started = 0;
99 	}
100 }
101 
102 static int
103 pcf_noack(struct pcf_softc *sc, int timeout)
104 {
105 	int noack;
106 	int k = timeout/10;
107 
108 	PCF_ASSERT_LOCKED(sc);
109 	do {
110 		noack = pcf_get_S1(sc) & LRB;
111 		if (!noack)
112 			break;
113 		DELAY(10);				/* XXX wait 10 us */
114 	} while (k--);
115 
116 	return (noack);
117 }
118 
119 int
120 pcf_repeated_start(device_t dev, u_char slave, int timeout)
121 {
122 	struct pcf_softc *sc = DEVTOSOFTC(dev);
123 	int error = 0;
124 
125 	PCF_LOCK(sc);
126 #ifdef PCFDEBUG
127 	device_printf(dev, " >> repeated start for slave %#x\n",
128 		      (unsigned)slave);
129 #endif
130 	/* repeated start */
131 	pcf_set_S1(sc, ESO|STA|STO|ACK);
132 
133 	/* set slave address to PCF. Last bit (LSB) must be set correctly
134 	 * according to transfer direction */
135 	pcf_set_S0(sc, slave);
136 
137 	/* wait for address sent, polling */
138 	if ((error = pcf_wait_byte(sc)))
139 		goto error;
140 
141 	/* check for ack */
142 	if (pcf_noack(sc, timeout)) {
143 		error = IIC_ENOACK;
144 #ifdef PCFDEBUG
145 		printf("pcf: no ack on repeated_start!\n");
146 #endif
147 		goto error;
148 	}
149 
150 	PCF_UNLOCK(sc);
151 	return (0);
152 
153 error:
154 	pcf_stop_locked(sc);
155 	PCF_UNLOCK(sc);
156 	return (error);
157 }
158 
159 int
160 pcf_start(device_t dev, u_char slave, int timeout)
161 {
162 	struct pcf_softc *sc = DEVTOSOFTC(dev);
163 	int error = 0;
164 
165 	PCF_LOCK(sc);
166 #ifdef PCFDEBUG
167 	device_printf(dev, " >> start for slave %#x\n", (unsigned)slave);
168 #endif
169 	if ((pcf_get_S1(sc) & nBB) == 0) {
170 #ifdef PCFDEBUG
171 		printf("pcf: busy!\n");
172 #endif
173 		PCF_UNLOCK(sc);
174 		return (IIC_EBUSERR);
175 	}
176 
177 	/* set slave address to PCF. Last bit (LSB) must be set correctly
178 	 * according to transfer direction */
179 	pcf_set_S0(sc, slave);
180 
181 	/* START only */
182 	pcf_set_S1(sc, PIN|ESO|STA|ACK);
183 
184 	sc->pcf_started = 1;
185 
186 	/* wait for address sent, polling */
187 	if ((error = pcf_wait_byte(sc)))
188 		goto error;
189 
190 	/* check for ACK */
191 	if (pcf_noack(sc, timeout)) {
192 		error = IIC_ENOACK;
193 #ifdef PCFDEBUG
194 		printf("pcf: no ack on start!\n");
195 #endif
196 		goto error;
197 	}
198 
199 	PCF_UNLOCK(sc);
200 	return (0);
201 
202 error:
203 	pcf_stop_locked(sc);
204 	PCF_UNLOCK(sc);
205 	return (error);
206 }
207 
208 int
209 pcf_stop(device_t dev)
210 {
211 	struct pcf_softc *sc = DEVTOSOFTC(dev);
212 
213 #ifdef PCFDEBUG
214 	device_printf(dev, " >> stop\n");
215 #endif
216 	PCF_LOCK(sc);
217 	pcf_stop_locked(sc);
218 	PCF_UNLOCK(sc);
219 
220 	return (0);
221 }
222 
223 void
224 pcf_intr(void *arg)
225 {
226 	struct pcf_softc *sc = arg;
227 	char data, status, addr;
228 	char error = 0;
229 
230 	PCF_LOCK(sc);
231 	status = pcf_get_S1(sc);
232 
233 	if (status & PIN) {
234 		printf("pcf: spurious interrupt, status=0x%x\n",
235 		       status & 0xff);
236 
237 		goto error;
238 	}
239 
240 	if (status & LAB)
241 		printf("pcf: bus arbitration lost!\n");
242 
243 	if (status & BER) {
244 		error = IIC_EBUSERR;
245 		iicbus_intr(sc->iicbus, INTR_ERROR, &error);
246 
247 		goto error;
248 	}
249 
250 	do {
251 		status = pcf_get_S1(sc);
252 
253 		switch(sc->pcf_slave_mode) {
254 		case SLAVE_TRANSMITTER:
255 			if (status & LRB) {
256 				/* ack interrupt line */
257 				dummy_write(sc);
258 
259 				/* no ack, don't send anymore */
260 				sc->pcf_slave_mode = SLAVE_RECEIVER;
261 
262 				iicbus_intr(sc->iicbus, INTR_NOACK, NULL);
263 				break;
264 			}
265 
266 			/* get data from upper code */
267 			iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data);
268 
269 			pcf_set_S0(sc, data);
270 			break;
271 
272 		case SLAVE_RECEIVER:
273 			if (status & AAS) {
274 				addr = pcf_get_S0(sc);
275 
276 				if (status & AD0)
277 					iicbus_intr(sc->iicbus, INTR_GENERAL, &addr);
278 				else
279 					iicbus_intr(sc->iicbus, INTR_START, &addr);
280 
281 				if (addr & LSB) {
282 					sc->pcf_slave_mode = SLAVE_TRANSMITTER;
283 
284 					/* get the first char from upper code */
285 					iicbus_intr(sc->iicbus, INTR_TRANSMIT, &data);
286 
287 					/* send first data byte */
288 					pcf_set_S0(sc, data);
289 				}
290 
291 				break;
292 			}
293 
294 			/* stop condition received? */
295 			if (status & STS) {
296 				/* ack interrupt line */
297 				dummy_read(sc);
298 
299 				/* emulate intr stop condition */
300 				iicbus_intr(sc->iicbus, INTR_STOP, NULL);
301 
302 			} else {
303 				/* get data, ack interrupt line */
304 				data = pcf_get_S0(sc);
305 
306 				/* deliver the character */
307 				iicbus_intr(sc->iicbus, INTR_RECEIVE, &data);
308 			}
309 			break;
310 
311 		    default:
312 			panic("%s: unknown slave mode (%d)!", __func__,
313 				sc->pcf_slave_mode);
314 		    }
315 
316 	} while ((pcf_get_S1(sc) & PIN) == 0);
317 	PCF_UNLOCK(sc);
318 
319 	return;
320 
321 error:
322 	/* unknown event on bus...reset PCF */
323 	pcf_set_S1(sc, PIN|ESO|ENI|ACK);
324 
325 	sc->pcf_slave_mode = SLAVE_RECEIVER;
326 	PCF_UNLOCK(sc);
327 
328 	return;
329 }
330 
331 int
332 pcf_rst_card(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
333 {
334 	struct pcf_softc *sc = DEVTOSOFTC(dev);
335 
336 	PCF_LOCK(sc);
337 	if (oldaddr)
338 		*oldaddr = sc->pcf_addr;
339 
340 	/* retrieve own address from bus level */
341 	if (!addr)
342 		sc->pcf_addr = PCF_DEFAULT_ADDR;
343 	else
344 		sc->pcf_addr = addr;
345 
346 	pcf_set_S1(sc, PIN);				/* initialize S1 */
347 
348 	/* own address S'O<>0 */
349 	pcf_set_S0(sc, sc->pcf_addr >> 1);
350 
351 	/* select clock register */
352 	pcf_set_S1(sc, PIN|ES1);
353 
354 	/* select bus speed : 18=90kb, 19=45kb, 1A=11kb, 1B=1.5kb */
355 	switch (speed) {
356 	case IIC_SLOW:
357 		pcf_set_S0(sc,  0x1b); /* XXX Sun uses 0x1f */
358 		break;
359 
360 	case IIC_FAST:
361 		pcf_set_S0(sc,  0x19); /* XXX Sun: 0x1d */
362 		break;
363 
364 	case IIC_UNKNOWN:
365 	case IIC_FASTEST:
366 	default:
367 		pcf_set_S0(sc,  0x18); /* XXX Sun: 0x1c */
368 		break;
369 	}
370 
371 	/* set bus on, ack=yes, INT=yes */
372 	pcf_set_S1(sc, PIN|ESO|ENI|ACK);
373 
374 	sc->pcf_slave_mode = SLAVE_RECEIVER;
375 	PCF_UNLOCK(sc);
376 
377 	return (0);
378 }
379 
380 int
381 pcf_write(device_t dev, const char *buf, int len, int *sent, int timeout /* us */)
382 {
383 	struct pcf_softc *sc = DEVTOSOFTC(dev);
384 	int bytes, error = 0;
385 
386 #ifdef PCFDEBUG
387 	device_printf(dev, " >> writing %d bytes: %#x%s\n", len,
388 		      (unsigned)buf[0], len > 1? "...": "");
389 #endif
390 
391 	bytes = 0;
392 	PCF_LOCK(sc);
393 	while (len) {
394 		pcf_set_S0(sc, *buf++);
395 
396 		/* wait for the byte to be send */
397 		if ((error = pcf_wait_byte(sc)))
398 			goto error;
399 
400 		/* check if ack received */
401 		if (pcf_noack(sc, timeout)) {
402 			error = IIC_ENOACK;
403 			goto error;
404 		}
405 
406 		len --;
407 		bytes ++;
408 	}
409 
410 error:
411 	*sent = bytes;
412 	PCF_UNLOCK(sc);
413 
414 #ifdef PCFDEBUG
415 	device_printf(dev, " >> %d bytes written (%d)\n", bytes, error);
416 #endif
417 
418 	return (error);
419 }
420 
421 int
422 pcf_read(device_t dev, char *buf, int len, int *read, int last,
423 	 int delay /* us */)
424 {
425 	struct pcf_softc *sc = DEVTOSOFTC(dev);
426 	int bytes, error = 0;
427 #ifdef PCFDEBUG
428 	char *obuf = buf;
429 
430 	device_printf(dev, " << reading %d bytes\n", len);
431 #endif
432 
433 	PCF_LOCK(sc);
434 	/* trig the bus to get the first data byte in S0 */
435 	if (len) {
436 		if (len == 1 && last)
437 			/* just one byte to read */
438 			pcf_set_S1(sc, ESO);		/* no ack */
439 
440 		dummy_read(sc);
441 	}
442 
443 	bytes = 0;
444 	while (len) {
445 		/* XXX delay needed here */
446 
447 		/* wait for trigged byte */
448 		if ((error = pcf_wait_byte(sc))) {
449 			pcf_stop_locked(sc);
450 			goto error;
451 		}
452 
453 		if (len == 1 && last)
454 			/* ok, last data byte already in S0, no I2C activity
455 			 * on next pcf_get_S0() */
456 			pcf_stop_locked(sc);
457 
458 		else if (len == 2 && last)
459 			/* next trigged byte with no ack */
460 			pcf_set_S1(sc, ESO);
461 
462 		/* receive byte, trig next byte */
463 		*buf++ = pcf_get_S0(sc);
464 
465 		len --;
466 		bytes ++;
467 	}
468 
469 error:
470 	*read = bytes;
471 	PCF_UNLOCK(sc);
472 
473 #ifdef PCFDEBUG
474 	device_printf(dev, " << %d bytes read (%d): %#x%s\n", bytes, error,
475 		      (unsigned)obuf[0], bytes > 1? "...": "");
476 #endif
477 
478 	return (error);
479 }
480 
481 DRIVER_MODULE(iicbus, pcf, iicbus_driver, iicbus_devclass, 0, 0);
482 MODULE_DEPEND(pcf, iicbus, PCF_MINVER, PCF_PREFVER, PCF_MAXVER);
483 MODULE_VERSION(pcf, PCF_MODVER);
484