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