From a1d2a459f7092cac4925c251d6076dad3739ff46 Mon Sep 17 00:00:00 2001 From: nsouch Date: Mon, 31 May 2004 14:24:21 +0000 Subject: Necessary modifications do get pcf working again for ISA. Tested with my Elektor card. Note that the hints are necessary to specify the IO base of the pcf chip. This enables to check the IO base when the probe routine is called during ISA enumeration. The interrupt driven code is mixed with polled mode, which is wrong and produces supposed spurious interrupts at each access. I still have to work on it. --- sys/dev/pcf/pcf.c | 26 +++++++++++++++++++------- sys/dev/pcf/pcf_isa.c | 44 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 15 deletions(-) (limited to 'sys') diff --git a/sys/dev/pcf/pcf.c b/sys/dev/pcf/pcf.c index 08b088f..0320958 100644 --- a/sys/dev/pcf/pcf.c +++ b/sys/dev/pcf/pcf.c @@ -64,6 +64,10 @@ pcf_wait_byte(struct pcf_softc *sc) return (0); } +#ifdef PCFDEBUG + printf("pcf: timeout!\n"); +#endif + return (IIC_ETIMEOUT); } @@ -132,6 +136,9 @@ pcf_repeated_start(device_t dev, u_char slave, int timeout) /* check for ack */ if (pcf_noack(sc, timeout)) { error = IIC_ENOACK; +#ifdef PCFDEBUG + printf("pcf: no ack on repeated_start!\n"); +#endif goto error; } @@ -151,8 +158,12 @@ pcf_start(device_t dev, u_char slave, int timeout) #ifdef PCFDEBUG device_printf(dev, " >> start for slave %#x\n", (unsigned)slave); #endif - if ((pcf_get_S1(sc) & nBB) == 0) + if ((pcf_get_S1(sc) & nBB) == 0) { +#ifdef PCFDEBUG + printf("pcf: busy!\n"); +#endif return (IIC_EBUSBSY); + } /* set slave address to PCF. Last bit (LSB) must be set correctly * according to transfer direction */ @@ -170,6 +181,9 @@ pcf_start(device_t dev, u_char slave, int timeout) /* check for ACK */ if (pcf_noack(sc, timeout)) { error = IIC_ENOACK; +#ifdef PCFDEBUG + printf("pcf: no ack on start!\n"); +#endif goto error; } @@ -183,23 +197,21 @@ error: void pcf_intr(void *arg) { - device_t dev = (device_t)arg; - struct pcf_softc *sc = DEVTOSOFTC(dev); - + struct pcf_softc *sc = arg; char data, status, addr; char error = 0; status = pcf_get_S1(sc); if (status & PIN) { - device_printf(dev, "spurious interrupt, status=0x%x\n", - status & 0xff); + printf("pcf: spurious interrupt, status=0x%x\n", + status & 0xff); goto error; } if (status & LAB) - device_printf(dev, "bus arbitration lost!\n"); + printf("pcf: bus arbitration lost!\n"); if (status & BER) { error = IIC_EBUSERR; diff --git a/sys/dev/pcf/pcf_isa.c b/sys/dev/pcf/pcf_isa.c index 0b0968a..b4a99e8 100644 --- a/sys/dev/pcf/pcf_isa.c +++ b/sys/dev/pcf/pcf_isa.c @@ -53,12 +53,16 @@ __FBSDID("$FreeBSD$"); #include #include "iicbus_if.h" +#define PCF_NAME "pcf" + +static void pcf_identify(driver_t *, device_t); static int pcf_probe(device_t); static int pcf_attach(device_t); static int pcf_detach(device_t); static device_method_t pcf_methods[] = { /* device interface */ + DEVMETHOD(device_identify, pcf_identify), DEVMETHOD(device_probe, pcf_probe), DEVMETHOD(device_attach, pcf_attach), DEVMETHOD(device_detach, pcf_detach), @@ -77,16 +81,37 @@ static device_method_t pcf_methods[] = { static devclass_t pcf_devclass; static driver_t pcf_driver = { - "pcf", + PCF_NAME, pcf_methods, sizeof(struct pcf_softc), }; +static void +pcf_identify(driver_t *driver, device_t parent) +{ + BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, PCF_NAME, 0); + + return; +} + static int pcf_probe(device_t dev) { + u_long start, count; + u_int rid = 0, port, error; + + bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count); + + /* The port address must be explicitly specified */ + if ((error = resource_int_value(PCF_NAME, 0, "port", &port) != 0)) + return (error); + + /* Probe is only successfull for the specified base io */ + if (port != (u_int)start) + return (ENXIO); device_set_desc(dev, "PCF8584 I2C bus controller"); + return (0); } @@ -121,14 +146,16 @@ pcf_attach(device_t dev) /* reset the chip */ pcf_rst_card(dev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL); - rv = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->res_irq, - INTR_TYPE_NET /* | INTR_ENTROPY */, - pcf_intr, sc, &sc->intr_cookie); - if (rv) { - device_printf(dev, "could not setup IRQ\n"); - goto error; + if (sc->res_irq) { + rv = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->res_irq, + INTR_TYPE_NET /* | INTR_ENTROPY */, + pcf_intr, sc, &sc->intr_cookie); + if (rv) { + device_printf(dev, "could not setup IRQ\n"); + goto error; + } } - + if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) device_printf(dev, "could not allocate iicbus instance\n"); @@ -181,5 +208,6 @@ pcf_detach(device_t dev) } DRIVER_MODULE(pcf, ebus, pcf_driver, pcf_devclass, 0, 0); +DRIVER_MODULE(pcf, isa, pcf_driver, pcf_devclass, 0, 0); MODULE_DEPEND(pcf, iicbus, PCF_MINVER, PCF_PREFVER, PCF_MAXVER); MODULE_VERSION(pcf, PCF_MODVER); -- cgit v1.1