xref: /freebsd/sys/dev/pcf/pcf.c (revision a1a4f1a0d87b594d3f17a97dc0127eec1417e6f6)
1 /*-
2  * Copyright (c) 1998 Nicolas Souchu, Marc Bouget
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  * $FreeBSD$
27  *
28  */
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/module.h>
33 #include <sys/bus.h>
34 #include <sys/conf.h>
35 #include <sys/malloc.h>
36 
37 #include <machine/clock.h>
38 
39 #include <i386/isa/isa_device.h>
40 
41 #include <dev/iicbus/iiconf.h>
42 #include "iicbus_if.h"
43 
44 #define TIMEOUT	9999					/* XXX */
45 
46 /* Status bits of S1 register (read only) */
47 #define nBB	0x01		/* busy when low set/reset by STOP/START*/
48 #define LAB	0x02		/* lost arbitration bit in multi-master mode */
49 #define AAS	0x04		/* addressed as slave */
50 #define LRB	0x08		/* last received byte when not AAS */
51 #define AD0	0x08		/* general call received when AAS */
52 #define BER	0x10		/* bus error, misplaced START or STOP */
53 #define STS	0x20		/* STOP detected in slave receiver mode */
54 #define PIN	0x80		/* pending interrupt not (r/w) */
55 
56 /* Control bits of S1 register (write only) */
57 #define ACK	0x01
58 #define STO	0x02
59 #define STA	0x04
60 #define ENI	0x08
61 #define ES2	0x10
62 #define ES1	0x20
63 #define ES0	0x40
64 
65 #define BUFSIZE 2048
66 
67 #define SLAVE_TRANSMITTER	0x1
68 #define SLAVE_RECEIVER		0x2
69 
70 #define PCF_DEFAULT_ADDR	0xaa
71 
72 struct pcf_softc {
73 
74 	int pcf_base;			/* isa port */
75 	u_char pcf_addr;		/* interface I2C address */
76 
77 	int pcf_slave_mode;		/* receiver or transmitter */
78 	int pcf_started;		/* 1 if start condition sent */
79 
80 	device_t iicbus;		/* the corresponding iicbus */
81 };
82 
83 struct pcf_isa_softc {
84 
85 	int pcf_unit;			/* unit of the isa device */
86 	int pcf_base;			/* isa port */
87 	int pcf_irq;			/* isa irq or null if polled */
88 
89 	unsigned int pcf_flags;		/* boot flags */
90 };
91 
92 #define MAXPCF 2
93 
94 static struct pcf_isa_softc *pcfdata[MAXPCF];
95 static int npcf = 0;
96 
97 static int	pcfprobe_isa(struct isa_device *);
98 static int	pcfattach_isa(struct isa_device *);
99 
100 struct isa_driver pcfdriver = {
101 	pcfprobe_isa, pcfattach_isa, "pcf"
102 };
103 
104 static int pcf_probe(device_t);
105 static int pcf_attach(device_t);
106 static int pcf_print_child(device_t, device_t);
107 
108 static int pcf_repeated_start(device_t, u_char, int);
109 static int pcf_start(device_t, u_char, int);
110 static int pcf_stop(device_t);
111 static int pcf_write(device_t, char *, int, int *, int);
112 static int pcf_read(device_t, char *, int, int *, int, int);
113 static ointhand2_t pcfintr;
114 static int pcf_rst_card(device_t, u_char, u_char, u_char *);
115 
116 static device_method_t pcf_methods[] = {
117 	/* device interface */
118 	DEVMETHOD(device_probe,		pcf_probe),
119 	DEVMETHOD(device_attach,	pcf_attach),
120 
121 	/* bus interface */
122 	DEVMETHOD(bus_print_child,	pcf_print_child),
123 
124 	/* iicbus interface */
125 	DEVMETHOD(iicbus_callback,	iicbus_null_callback),
126 	DEVMETHOD(iicbus_repeated_start, pcf_repeated_start),
127 	DEVMETHOD(iicbus_start,		pcf_start),
128 	DEVMETHOD(iicbus_stop,		pcf_stop),
129 	DEVMETHOD(iicbus_write,		pcf_write),
130 	DEVMETHOD(iicbus_read,		pcf_read),
131 	DEVMETHOD(iicbus_reset,		pcf_rst_card),
132 
133 	{ 0, 0 }
134 };
135 
136 static driver_t pcf_driver = {
137 	"pcf",
138 	pcf_methods,
139 	sizeof(struct pcf_softc),
140 };
141 
142 static devclass_t pcf_devclass;
143 
144 #define DEVTOSOFTC(dev) ((struct pcf_softc *)device_get_softc(dev))
145 
146 static int
147 pcfprobe_isa(struct isa_device *dvp)
148 {
149 	device_t pcfdev;
150 	struct pcf_isa_softc *pcf;
151 
152 	if (npcf >= MAXPCF)
153 		return (0);
154 
155 	if ((pcf = (struct pcf_isa_softc *)malloc(sizeof(struct pcf_isa_softc),
156 			M_DEVBUF, M_NOWAIT)) == NULL)
157 		return (0);
158 
159 	pcf->pcf_base = dvp->id_iobase;		/* XXX should be ivars */
160 	pcf->pcf_unit = dvp->id_unit;
161 
162 	if (!(dvp->id_flags & IIC_POLLED))
163 		pcf->pcf_irq = (dvp->id_irq);
164 
165 	pcfdata[npcf++] = pcf;
166 
167 	/* XXX add the pcf device to the root_bus until isa bus exists */
168 	pcfdev = device_add_child(root_bus, "pcf", pcf->pcf_unit, NULL);
169 
170 	if (!pcfdev)
171 		goto error;
172 
173 	return (1);
174 
175 error:
176 	free(pcf, M_DEVBUF);
177 	return (0);
178 }
179 
180 static int
181 pcfattach_isa(struct isa_device *isdp)
182 {
183 	isdp->id_ointr = pcfintr;
184 	return (1);				/* ok */
185 }
186 
187 static int
188 pcf_probe(device_t pcfdev)
189 {
190 	struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev);
191 	int unit = device_get_unit(pcfdev);
192 
193 	/* retrieve base address from isa initialization
194 	 *
195 	 * XXX should use ivars with isabus
196 	 */
197 	pcf->pcf_base = pcfdata[unit]->pcf_base;
198 
199 	/* reset the chip */
200 	pcf_rst_card(pcfdev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL);
201 
202 	/* XXX try do detect chipset */
203 
204 	device_set_desc(pcfdev, "PCF8584 I2C bus controller");
205 
206 	return (0);
207 }
208 
209 static int
210 pcf_attach(device_t pcfdev)
211 {
212 	struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev);
213 
214 	pcf->iicbus = iicbus_alloc_bus(pcfdev);
215 
216 	/* probe and attach the iicbus */
217 	device_probe_and_attach(pcf->iicbus);
218 
219 	return (0);
220 }
221 
222 static int
223 pcf_print_child(device_t bus, device_t dev)
224 {
225 	struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(bus);
226 	int retval = 0;
227 
228 	retval += bus_print_child_header(bus, dev);
229 	retval += printf(" on %s addr 0x%x\n", device_get_nameunit(bus),
230 			 (int)pcf->pcf_addr);
231 
232 	return (retval);
233 }
234 
235 /*
236  * PCF8584 datasheet : when operate at 8 MHz or more, a minimun time of
237  * 6 clocks cycles must be left between two consecutives access
238  */
239 #define pcf_nops()	DELAY(10)
240 
241 #define dummy_read(pcf)		PCF_GET_S0(pcf)
242 #define dummy_write(pcf)	PCF_SET_S0(pcf, 0)
243 
244 /*
245  * Specific register access to PCF8584
246  */
247 static void PCF_SET_S0(struct pcf_softc *pcf, int data)
248 {
249 	outb(pcf->pcf_base, data);
250 	pcf_nops();
251 }
252 
253 static void PCF_SET_S1(struct pcf_softc *pcf, int data)
254 {
255 	outb(pcf->pcf_base+1, data);
256 	pcf_nops();
257 }
258 
259 static char PCF_GET_S0(struct pcf_softc *pcf)
260 {
261 	char data;
262 
263 	data = inb(pcf->pcf_base);
264 	pcf_nops();
265 
266 	return (data);
267 }
268 
269 static char PCF_GET_S1(struct pcf_softc *pcf)
270 {
271 	char data;
272 
273 	data = inb(pcf->pcf_base+1);
274 	pcf_nops();
275 
276 	return (data);
277 }
278 
279 /*
280  * Polling mode for master operations wait for a new
281  * byte incomming or outgoing
282  */
283 static int pcf_wait_byte(struct pcf_softc *pcf)
284 {
285 	int counter = TIMEOUT;
286 
287 	while (counter--) {
288 
289 		if ((PCF_GET_S1(pcf) & PIN) == 0)
290 			return (0);
291 	}
292 
293 	return (IIC_ETIMEOUT);
294 }
295 
296 static int pcf_stop(device_t pcfdev)
297 {
298 	struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
299 
300 	/*
301 	 * Send STOP condition iff the START condition was previously sent.
302 	 * STOP is sent only once even if a iicbus_stop() is called after
303 	 * an iicbus_read()... see pcf_read(): the pcf needs to send the stop
304 	 * before the last char is read.
305 	 */
306 	if (pcf->pcf_started) {
307 		/* set stop condition and enable IT */
308 		PCF_SET_S1(pcf, PIN|ES0|ENI|STO|ACK);
309 
310 		pcf->pcf_started = 0;
311 	}
312 
313 	return (0);
314 }
315 
316 
317 static int pcf_noack(struct pcf_softc *pcf, int timeout)
318 {
319 	int noack;
320 	int k = timeout/10;
321 
322 	do {
323 		noack = PCF_GET_S1(pcf) & LRB;
324 		if (!noack)
325 			break;
326 		DELAY(10);				/* XXX wait 10 us */
327 	} while (k--);
328 
329 	return (noack);
330 }
331 
332 static int pcf_repeated_start(device_t pcfdev, u_char slave, int timeout)
333 {
334 	struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
335 	int error = 0;
336 
337 	/* repeated start */
338 	PCF_SET_S1(pcf, ES0|STA|STO|ACK);
339 
340 	/* set slave address to PCF. Last bit (LSB) must be set correctly
341 	 * according to transfer direction */
342 	PCF_SET_S0(pcf, slave);
343 
344 	/* wait for address sent, polling */
345 	if ((error = pcf_wait_byte(pcf)))
346 		goto error;
347 
348 	/* check for ack */
349 	if (pcf_noack(pcf, timeout)) {
350 		error = IIC_ENOACK;
351 		goto error;
352 	}
353 
354 	return (0);
355 
356 error:
357 	pcf_stop(pcfdev);
358 	return (error);
359 }
360 
361 static int pcf_start(device_t pcfdev, u_char slave, int timeout)
362 {
363 	struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
364 	int error = 0;
365 
366 	if ((PCF_GET_S1(pcf) & nBB) == 0)
367 		return (IIC_EBUSBSY);
368 
369 	/* set slave address to PCF. Last bit (LSB) must be set correctly
370 	 * according to transfer direction */
371 	PCF_SET_S0(pcf, slave);
372 
373 	/* START only */
374 	PCF_SET_S1(pcf, PIN|ES0|STA|ACK);
375 
376 	pcf->pcf_started = 1;
377 
378 	/* wait for address sent, polling */
379 	if ((error = pcf_wait_byte(pcf)))
380 		goto error;
381 
382 	/* check for ACK */
383 	if (pcf_noack(pcf, timeout)) {
384 		error = IIC_ENOACK;
385 		goto error;
386 	}
387 
388 	return (0);
389 
390 error:
391 	pcf_stop(pcfdev);
392 	return (error);
393 }
394 
395 static void
396 pcfintr(unit)
397 {
398 	struct pcf_softc *pcf =
399 		(struct pcf_softc *)devclass_get_softc(pcf_devclass, unit);
400 
401 	char data, status, addr;
402 	char error = 0;
403 
404 	status = PCF_GET_S1(pcf);
405 
406 	if (status & PIN) {
407 		printf("pcf%d: spurious interrupt, status=0x%x\n", unit,
408 			status & 0xff);
409 
410 		goto error;
411 	}
412 
413 	if (status & LAB)
414 		printf("pcf%d: bus arbitration lost!\n", unit);
415 
416 	if (status & BER) {
417 		error = IIC_EBUSERR;
418 		iicbus_intr(pcf->iicbus, INTR_ERROR, &error);
419 
420 		goto error;
421 	}
422 
423 	do {
424 		status = PCF_GET_S1(pcf);
425 
426 		switch(pcf->pcf_slave_mode) {
427 
428 		case SLAVE_TRANSMITTER:
429 			if (status & LRB) {
430 				/* ack interrupt line */
431 				dummy_write(pcf);
432 
433 				/* no ack, don't send anymore */
434 				pcf->pcf_slave_mode = SLAVE_RECEIVER;
435 
436 				iicbus_intr(pcf->iicbus, INTR_NOACK, NULL);
437 				break;
438 			}
439 
440 			/* get data from upper code */
441 			iicbus_intr(pcf->iicbus, INTR_TRANSMIT, &data);
442 
443 			PCF_SET_S0(pcf, data);
444 			break;
445 
446 		case SLAVE_RECEIVER:
447 			if (status & AAS) {
448 				addr = PCF_GET_S0(pcf);
449 
450 				if (status & AD0)
451 					iicbus_intr(pcf->iicbus, INTR_GENERAL, &addr);
452 				else
453 					iicbus_intr(pcf->iicbus, INTR_START, &addr);
454 
455 				if (addr & LSB) {
456 					pcf->pcf_slave_mode = SLAVE_TRANSMITTER;
457 
458 					/* get the first char from upper code */
459 					iicbus_intr(pcf->iicbus, INTR_TRANSMIT, &data);
460 
461 					/* send first data byte */
462 					PCF_SET_S0(pcf, data);
463 				}
464 
465 				break;
466 			}
467 
468 			/* stop condition received? */
469 			if (status & STS) {
470 				/* ack interrupt line */
471 				dummy_read(pcf);
472 
473 				/* emulate intr stop condition */
474 				iicbus_intr(pcf->iicbus, INTR_STOP, NULL);
475 
476 			} else {
477 				/* get data, ack interrupt line */
478 				data = PCF_GET_S0(pcf);
479 
480 				/* deliver the character */
481 				iicbus_intr(pcf->iicbus, INTR_RECEIVE, &data);
482 			}
483 			break;
484 
485 		    default:
486 			panic("%s: unknown slave mode (%d)!", __FUNCTION__,
487 				pcf->pcf_slave_mode);
488 		    }
489 
490 	} while ((PCF_GET_S1(pcf) & PIN) == 0);
491 
492 	return;
493 
494 error:
495 	/* unknown event on bus...reset PCF */
496 	PCF_SET_S1(pcf, PIN|ES0|ENI|ACK);
497 
498 	pcf->pcf_slave_mode = SLAVE_RECEIVER;
499 
500 	return;
501 }
502 
503 static int pcf_rst_card(device_t pcfdev, u_char speed, u_char addr, u_char *oldaddr)
504 {
505 	struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
506 
507 	if (oldaddr)
508 		*oldaddr = pcf->pcf_addr;
509 
510 	/* retrieve own address from bus level */
511 	if (!addr)
512 		pcf->pcf_addr = PCF_DEFAULT_ADDR;
513 	else
514 		pcf->pcf_addr = addr;
515 
516 	PCF_SET_S1(pcf, PIN);				/* initialize S1 */
517 
518 	/* own address S'O<>0 */
519 	PCF_SET_S0(pcf, pcf->pcf_addr >> 1);
520 
521 	/* select clock register */
522 	PCF_SET_S1(pcf, PIN|ES1);
523 
524 	/* select bus speed : 18=90kb, 19=45kb, 1A=11kb, 1B=1.5kb */
525 	switch (speed) {
526 	case IIC_SLOW:
527 		PCF_SET_S0(pcf,  0x1b);
528 		break;
529 
530 	case IIC_FAST:
531 		PCF_SET_S0(pcf,  0x19);
532 		break;
533 
534 	case IIC_UNKNOWN:
535 	case IIC_FASTEST:
536 	default:
537 		PCF_SET_S0(pcf,  0x18);
538 		break;
539 	}
540 
541 	/* set bus on, ack=yes, INT=yes */
542 	PCF_SET_S1(pcf, PIN|ES0|ENI|ACK);
543 
544 	pcf->pcf_slave_mode = SLAVE_RECEIVER;
545 
546 	return (0);
547 }
548 
549 static int
550 pcf_write(device_t pcfdev, char *buf, int len, int *sent, int timeout /* us */)
551 {
552 	struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
553 	int bytes, error = 0;
554 
555 #ifdef PCFDEBUG
556 	printf("pcf%d: >> writing %d bytes\n", device_get_unit(pcfdev), len);
557 #endif
558 
559 	bytes = 0;
560 	while (len) {
561 
562 		PCF_SET_S0(pcf, *buf++);
563 
564 		/* wait for the byte to be send */
565 		if ((error = pcf_wait_byte(pcf)))
566 			goto error;
567 
568 		/* check if ack received */
569 		if (pcf_noack(pcf, timeout)) {
570 			error = IIC_ENOACK;
571 			goto error;
572 		}
573 
574 		len --;
575 		bytes ++;
576 	}
577 
578 error:
579 	*sent = bytes;
580 
581 #ifdef PCFDEBUG
582 	printf("pcf%d: >> %d bytes written (%d)\n",
583 		device_get_unit(pcfdev), bytes, error);
584 #endif
585 
586 	return (error);
587 }
588 
589 static int
590 pcf_read(device_t pcfdev, char *buf, int len, int *read, int last,
591 							int delay /* us */)
592 {
593 	struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
594 	int bytes, error = 0;
595 
596 #ifdef PCFDEBUG
597 	printf("pcf%d: << reading %d bytes\n", device_get_unit(pcfdev), len);
598 #endif
599 
600 	/* trig the bus to get the first data byte in S0 */
601 	if (len) {
602 		if (len == 1 && last)
603 			/* just one byte to read */
604 			PCF_SET_S1(pcf, ES0);		/* no ack */
605 
606 		dummy_read(pcf);
607 	}
608 
609 	bytes = 0;
610 	while (len) {
611 
612 		/* XXX delay needed here */
613 
614 		/* wait for trigged byte */
615 		if ((error = pcf_wait_byte(pcf))) {
616 			pcf_stop(pcfdev);
617 			goto error;
618 		}
619 
620 		if (len == 1 && last)
621 			/* ok, last data byte already in S0, no I2C activity
622 			 * on next PCF_GET_S0() */
623 			pcf_stop(pcfdev);
624 
625 		else if (len == 2 && last)
626 			/* next trigged byte with no ack */
627 			PCF_SET_S1(pcf, ES0);
628 
629 		/* receive byte, trig next byte */
630 		*buf++ = PCF_GET_S0(pcf);
631 
632 		len --;
633 		bytes ++;
634 	};
635 
636 error:
637 	*read = bytes;
638 
639 #ifdef PCFDEBUG
640 	printf("pcf%d: << %d bytes read (%d)\n",
641 		device_get_unit(pcfdev), bytes, error);
642 #endif
643 
644 	return (error);
645 }
646 
647 DRIVER_MODULE(pcf, root, pcf_driver, pcf_devclass, 0, 0);
648