Constify iicbus_write()'s buf argument.
[dragonfly.git] / sys / bus / iicbus / i386 / pcf.c
blobbb75dd5b261be699966eabf0340fcf01582b4054
1 /*-
2 * Copyright (c) 1998 Nicolas Souchu, Marc Bouget
3 * All rights reserved.
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.
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.
26 * $FreeBSD: src/sys/i386/isa/pcf.c,v 1.14 2000/01/14 00:18:05 nsouch Exp $
27 * $DragonFly: src/sys/bus/iicbus/i386/pcf.c,v 1.11 2008/08/02 01:14:38 dillon Exp $
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/bus.h>
35 #include <sys/malloc.h>
37 #include <machine/clock.h>
38 #include <sys/rman.h>
40 #include <bus/isa/isareg.h>
41 #include <bus/isa/isavar.h>
43 #include <bus/isa/isa_device.h>
45 #include "../iiconf.h"
46 #include "iicbus_if.h"
48 #define IO_PCFSIZE 2
50 #define TIMEOUT 9999 /* XXX */
52 /* Status bits of S1 register (read only) */
53 #define nBB 0x01 /* busy when low set/reset by STOP/START*/
54 #define LAB 0x02 /* lost arbitration bit in multi-master mode */
55 #define AAS 0x04 /* addressed as slave */
56 #define LRB 0x08 /* last received byte when not AAS */
57 #define AD0 0x08 /* general call received when AAS */
58 #define BER 0x10 /* bus error, misplaced START or STOP */
59 #define STS 0x20 /* STOP detected in slave receiver mode */
60 #define PIN 0x80 /* pending interrupt not (r/w) */
62 /* Control bits of S1 register (write only) */
63 #define ACK 0x01
64 #define STO 0x02
65 #define STA 0x04
66 #define ENI 0x08
67 #define ES2 0x10
68 #define ES1 0x20
69 #define ES0 0x40
71 #define BUFSIZE 2048
73 #define SLAVE_TRANSMITTER 0x1
74 #define SLAVE_RECEIVER 0x2
76 #define PCF_DEFAULT_ADDR 0xaa
78 struct pcf_softc {
80 int pcf_base; /* isa port */
81 int pcf_flags;
82 u_char pcf_addr; /* interface I2C address */
84 int pcf_slave_mode; /* receiver or transmitter */
85 int pcf_started; /* 1 if start condition sent */
87 device_t iicbus; /* the corresponding iicbus */
89 int rid_irq, rid_ioport;
90 struct resource *res_irq, *res_ioport;
91 void *intr_cookie;
94 static int pcf_probe(device_t);
95 static int pcf_attach(device_t);
96 static void pcfintr(void *arg);
98 static int pcf_print_child(device_t, device_t);
100 static int pcf_repeated_start(device_t, u_char, int);
101 static int pcf_start(device_t, u_char, int);
102 static int pcf_stop(device_t);
103 static int pcf_write(device_t, const char *, int, int *, int);
104 static int pcf_read(device_t, char *, int, int *, int, int);
105 static int pcf_rst_card(device_t, u_char, u_char, u_char *);
107 static device_method_t pcf_methods[] = {
108 /* device interface */
109 DEVMETHOD(device_probe, pcf_probe),
110 DEVMETHOD(device_attach, pcf_attach),
112 /* bus interface */
113 DEVMETHOD(bus_print_child, pcf_print_child),
115 /* iicbus interface */
116 DEVMETHOD(iicbus_callback, iicbus_null_callback),
117 DEVMETHOD(iicbus_repeated_start, pcf_repeated_start),
118 DEVMETHOD(iicbus_start, pcf_start),
119 DEVMETHOD(iicbus_stop, pcf_stop),
120 DEVMETHOD(iicbus_write, pcf_write),
121 DEVMETHOD(iicbus_read, pcf_read),
122 DEVMETHOD(iicbus_reset, pcf_rst_card),
124 { 0, 0 }
127 static driver_t pcf_driver = {
128 "pcf",
129 pcf_methods,
130 sizeof(struct pcf_softc),
133 static devclass_t pcf_devclass;
135 #define DEVTOSOFTC(dev) ((struct pcf_softc *)device_get_softc(dev))
137 static int
138 pcf_probe(device_t pcfdev)
140 struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
141 device_t parent = device_get_parent(pcfdev);
143 device_set_desc(pcfdev, "PCF8584 I2C bus controller");
145 bzero(pcf, sizeof(struct pcf_softc));
147 pcf->rid_irq = pcf->rid_ioport = 0;
148 pcf->res_irq = pcf->res_ioport = 0;
150 /* IO port is mandatory */
151 pcf->res_ioport = bus_alloc_resource(pcfdev, SYS_RES_IOPORT,
152 &pcf->rid_ioport, 0ul, ~0ul,
153 IO_PCFSIZE, RF_ACTIVE);
154 if (pcf->res_ioport == 0) {
155 device_printf(pcfdev, "cannot reserve I/O port range\n");
156 goto error;
158 BUS_READ_IVAR(parent, pcfdev, ISA_IVAR_PORT, &pcf->pcf_base);
160 pcf->pcf_flags = device_get_flags(pcfdev);
162 if (!(pcf->pcf_flags & IIC_POLLED)) {
163 pcf->res_irq = bus_alloc_resource(pcfdev, SYS_RES_IRQ, &pcf->rid_irq,
164 0ul, ~0ul, 1, RF_ACTIVE);
165 if (pcf->res_irq == 0) {
166 device_printf(pcfdev, "can't reserve irq, polled mode.\n");
167 pcf->pcf_flags |= IIC_POLLED;
171 /* reset the chip */
172 pcf_rst_card(pcfdev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL);
174 return (0);
175 error:
176 if (pcf->res_ioport != 0) {
177 bus_deactivate_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport,
178 pcf->res_ioport);
179 bus_release_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport,
180 pcf->res_ioport);
182 return (ENXIO);
185 static int
186 pcf_attach(device_t pcfdev)
188 struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
189 device_t parent = device_get_parent(pcfdev);
190 int error = 0;
192 if (pcf->res_irq) {
193 /* default to the tty mask for registration */ /* XXX */
194 error = BUS_SETUP_INTR(parent, pcfdev, pcf->res_irq,
195 0, pcfintr, pcfdev,
196 &pcf->intr_cookie, NULL);
197 if (error)
198 return (error);
201 pcf->iicbus = iicbus_alloc_bus(pcfdev);
203 /* probe and attach the iicbus */
204 device_probe_and_attach(pcf->iicbus);
206 return (0);
209 static int
210 pcf_print_child(device_t bus, device_t dev)
212 struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(bus);
213 int retval = 0;
215 retval += bus_print_child_header(bus, dev);
216 retval += kprintf(" on %s addr 0x%x\n", device_get_nameunit(bus),
217 (int)pcf->pcf_addr);
219 return (retval);
223 * PCF8584 datasheet : when operate at 8 MHz or more, a minimun time of
224 * 6 clocks cycles must be left between two consecutives access
226 #define pcf_nops() DELAY(10)
228 #define dummy_read(pcf) PCF_GET_S0(pcf)
229 #define dummy_write(pcf) PCF_SET_S0(pcf, 0)
232 * Specific register access to PCF8584
234 static void
235 PCF_SET_S0(struct pcf_softc *pcf, int data)
237 outb(pcf->pcf_base, data);
238 pcf_nops();
241 static void
242 PCF_SET_S1(struct pcf_softc *pcf, int data)
244 outb(pcf->pcf_base+1, data);
245 pcf_nops();
248 static char
249 PCF_GET_S0(struct pcf_softc *pcf)
251 char data;
253 data = inb(pcf->pcf_base);
254 pcf_nops();
256 return (data);
259 static char
260 PCF_GET_S1(struct pcf_softc *pcf)
262 char data;
264 data = inb(pcf->pcf_base+1);
265 pcf_nops();
267 return (data);
271 * Polling mode for master operations wait for a new
272 * byte incomming or outgoing
274 static int
275 pcf_wait_byte(struct pcf_softc *pcf)
277 int counter = TIMEOUT;
279 while (counter--) {
281 if ((PCF_GET_S1(pcf) & PIN) == 0)
282 return (0);
285 return (IIC_ETIMEOUT);
288 static int
289 pcf_stop(device_t pcfdev)
291 struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
294 * Send STOP condition iff the START condition was previously sent.
295 * STOP is sent only once even if a iicbus_stop() is called after
296 * an iicbus_read()... see pcf_read(): the pcf needs to send the stop
297 * before the last char is read.
299 if (pcf->pcf_started) {
300 /* set stop condition and enable IT */
301 PCF_SET_S1(pcf, PIN|ES0|ENI|STO|ACK);
303 pcf->pcf_started = 0;
306 return (0);
310 static int
311 pcf_noack(struct pcf_softc *pcf, int timeout)
313 int noack;
314 int k = timeout/10;
316 do {
317 noack = PCF_GET_S1(pcf) & LRB;
318 if (!noack)
319 break;
320 DELAY(10); /* XXX wait 10 us */
321 } while (k--);
323 return (noack);
326 static int
327 pcf_repeated_start(device_t pcfdev, u_char slave, int timeout)
329 struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
330 int error = 0;
332 /* repeated start */
333 PCF_SET_S1(pcf, ES0|STA|STO|ACK);
335 /* set slave address to PCF. Last bit (LSB) must be set correctly
336 * according to transfer direction */
337 PCF_SET_S0(pcf, slave);
339 /* wait for address sent, polling */
340 if ((error = pcf_wait_byte(pcf)))
341 goto error;
343 /* check for ack */
344 if (pcf_noack(pcf, timeout)) {
345 error = IIC_ENOACK;
346 goto error;
349 return (0);
351 error:
352 pcf_stop(pcfdev);
353 return (error);
356 static int
357 pcf_start(device_t pcfdev, u_char slave, int timeout)
359 struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
360 int error = 0;
362 if ((PCF_GET_S1(pcf) & nBB) == 0)
363 return (IIC_EBUSBSY);
365 /* set slave address to PCF. Last bit (LSB) must be set correctly
366 * according to transfer direction */
367 PCF_SET_S0(pcf, slave);
369 /* START only */
370 PCF_SET_S1(pcf, PIN|ES0|STA|ACK);
372 pcf->pcf_started = 1;
374 /* wait for address sent, polling */
375 if ((error = pcf_wait_byte(pcf)))
376 goto error;
378 /* check for ACK */
379 if (pcf_noack(pcf, timeout)) {
380 error = IIC_ENOACK;
381 goto error;
384 return (0);
386 error:
387 pcf_stop(pcfdev);
388 return (error);
391 static void
392 pcfintr(void *arg)
394 device_t pcfdev = (device_t)arg;
395 struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
397 char data, status, addr;
398 char error = 0;
400 status = PCF_GET_S1(pcf);
402 if (status & PIN) {
403 device_printf(pcfdev, "spurious interrupt, status=0x%x\n", status & 0xff);
405 goto error;
408 if (status & LAB)
409 device_printf(pcfdev, "bus arbitration lost!\n");
411 if (status & BER) {
412 error = IIC_EBUSERR;
413 iicbus_intr(pcf->iicbus, INTR_ERROR, &error);
415 goto error;
418 do {
419 status = PCF_GET_S1(pcf);
421 switch(pcf->pcf_slave_mode) {
423 case SLAVE_TRANSMITTER:
424 if (status & LRB) {
425 /* ack interrupt line */
426 dummy_write(pcf);
428 /* no ack, don't send anymore */
429 pcf->pcf_slave_mode = SLAVE_RECEIVER;
431 iicbus_intr(pcf->iicbus, INTR_NOACK, NULL);
432 break;
435 /* get data from upper code */
436 iicbus_intr(pcf->iicbus, INTR_TRANSMIT, &data);
438 PCF_SET_S0(pcf, data);
439 break;
441 case SLAVE_RECEIVER:
442 if (status & AAS) {
443 addr = PCF_GET_S0(pcf);
445 if (status & AD0)
446 iicbus_intr(pcf->iicbus, INTR_GENERAL, &addr);
447 else
448 iicbus_intr(pcf->iicbus, INTR_START, &addr);
450 if (addr & LSB) {
451 pcf->pcf_slave_mode = SLAVE_TRANSMITTER;
453 /* get the first char from upper code */
454 iicbus_intr(pcf->iicbus, INTR_TRANSMIT, &data);
456 /* send first data byte */
457 PCF_SET_S0(pcf, data);
460 break;
463 /* stop condition received? */
464 if (status & STS) {
465 /* ack interrupt line */
466 dummy_read(pcf);
468 /* emulate intr stop condition */
469 iicbus_intr(pcf->iicbus, INTR_STOP, NULL);
471 } else {
472 /* get data, ack interrupt line */
473 data = PCF_GET_S0(pcf);
475 /* deliver the character */
476 iicbus_intr(pcf->iicbus, INTR_RECEIVE, &data);
478 break;
480 default:
481 panic("%s: unknown slave mode (%d)!", __func__,
482 pcf->pcf_slave_mode);
485 } while ((PCF_GET_S1(pcf) & PIN) == 0);
487 return;
489 error:
490 /* unknown event on bus...reset PCF */
491 PCF_SET_S1(pcf, PIN|ES0|ENI|ACK);
493 pcf->pcf_slave_mode = SLAVE_RECEIVER;
495 return;
498 static int
499 pcf_rst_card(device_t pcfdev, u_char speed, u_char addr, u_char *oldaddr)
501 struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
503 if (oldaddr)
504 *oldaddr = pcf->pcf_addr;
506 /* retrieve own address from bus level */
507 if (!addr)
508 pcf->pcf_addr = PCF_DEFAULT_ADDR;
509 else
510 pcf->pcf_addr = addr;
512 PCF_SET_S1(pcf, PIN); /* initialize S1 */
514 /* own address S'O<>0 */
515 PCF_SET_S0(pcf, pcf->pcf_addr >> 1);
517 /* select clock register */
518 PCF_SET_S1(pcf, PIN|ES1);
520 /* select bus speed : 18=90kb, 19=45kb, 1A=11kb, 1B=1.5kb */
521 switch (speed) {
522 case IIC_SLOW:
523 PCF_SET_S0(pcf, 0x1b);
524 break;
526 case IIC_FAST:
527 PCF_SET_S0(pcf, 0x19);
528 break;
530 case IIC_UNKNOWN:
531 case IIC_FASTEST:
532 default:
533 PCF_SET_S0(pcf, 0x18);
534 break;
537 /* set bus on, ack=yes, INT=yes */
538 PCF_SET_S1(pcf, PIN|ES0|ENI|ACK);
540 pcf->pcf_slave_mode = SLAVE_RECEIVER;
542 return (0);
545 static int
546 pcf_write(device_t pcfdev, const char *buf, int len, int *sent,
547 int timeout /* us */)
549 struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
550 int bytes, error = 0;
552 #ifdef PCFDEBUG
553 kprintf("pcf%d: >> writing %d bytes\n", device_get_unit(pcfdev), len);
554 #endif
556 bytes = 0;
557 while (len) {
559 PCF_SET_S0(pcf, *buf++);
561 /* wait for the byte to be send */
562 if ((error = pcf_wait_byte(pcf)))
563 goto error;
565 /* check if ack received */
566 if (pcf_noack(pcf, timeout)) {
567 error = IIC_ENOACK;
568 goto error;
571 len --;
572 bytes ++;
575 error:
576 *sent = bytes;
578 #ifdef PCFDEBUG
579 kprintf("pcf%d: >> %d bytes written (%d)\n",
580 device_get_unit(pcfdev), bytes, error);
581 #endif
583 return (error);
586 static int
587 pcf_read(device_t pcfdev, char *buf, int len, int *read, int last,
588 int delay /* us */)
590 struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
591 int bytes, error = 0;
593 #ifdef PCFDEBUG
594 kprintf("pcf%d: << reading %d bytes\n", device_get_unit(pcfdev), len);
595 #endif
597 /* trig the bus to get the first data byte in S0 */
598 if (len) {
599 if (len == 1 && last)
600 /* just one byte to read */
601 PCF_SET_S1(pcf, ES0); /* no ack */
603 dummy_read(pcf);
606 bytes = 0;
607 while (len) {
609 /* XXX delay needed here */
611 /* wait for trigged byte */
612 if ((error = pcf_wait_byte(pcf))) {
613 pcf_stop(pcfdev);
614 goto error;
617 if (len == 1 && last)
618 /* ok, last data byte already in S0, no I2C activity
619 * on next PCF_GET_S0() */
620 pcf_stop(pcfdev);
622 else if (len == 2 && last)
623 /* next trigged byte with no ack */
624 PCF_SET_S1(pcf, ES0);
626 /* receive byte, trig next byte */
627 *buf++ = PCF_GET_S0(pcf);
629 len --;
630 bytes ++;
633 error:
634 *read = bytes;
636 #ifdef PCFDEBUG
637 kprintf("pcf%d: << %d bytes read (%d)\n",
638 device_get_unit(pcfdev), bytes, error);
639 #endif
641 return (error);
644 DRIVER_MODULE(pcf, isa, pcf_driver, pcf_devclass, 0, 0);