static int pcf_probe(device_t pcfdev) { struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); device_t parent = device_get_parent(pcfdev); uintptr_t base; device_set_desc(pcfdev, "PCF8584 I2C bus controller"); bzero(pcf, sizeof(struct pcf_softc)); pcf->rid_irq = pcf->rid_ioport = 0; pcf->res_irq = pcf->res_ioport = NULL; /* IO port is mandatory */ pcf->res_ioport = bus_alloc_resource(pcfdev, SYS_RES_IOPORT, &pcf->rid_ioport, 0ul, ~0ul, IO_PCFSIZE, RF_ACTIVE); if (pcf->res_ioport == NULL) { device_printf(pcfdev, "cannot reserve I/O port range\n"); goto error; } BUS_READ_IVAR(parent, pcfdev, ISA_IVAR_PORT, &base); pcf->pcf_base = base; pcf->pcf_flags = device_get_flags(pcfdev); if (!(pcf->pcf_flags & IIC_POLLED)) { pcf->res_irq = bus_alloc_resource(pcfdev, SYS_RES_IRQ, &pcf->rid_irq, 0ul, ~0ul, 1, RF_ACTIVE); if (pcf->res_irq == NULL) { device_printf(pcfdev, "can't reserve irq, polled mode.\n"); pcf->pcf_flags |= IIC_POLLED; } } /* reset the chip */ pcf_rst_card(pcfdev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL); return (0); error: if (pcf->res_ioport != NULL) { bus_deactivate_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport, pcf->res_ioport); bus_release_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport, pcf->res_ioport); } return (ENXIO); }
static int pcf_ebus_attach(device_t dev) { struct pcf_softc *sc; int rv = ENXIO; phandle_t node; uint64_t own_addr; sc = DEVTOSOFTC(dev); bzero(sc, sizeof(struct pcf_softc)); /* get OFW node of the pcf */ if ((node = ofw_bus_get_node(dev)) <= 0) { device_printf(dev, "cannot get OFW node\n"); goto error; } /* IO port is mandatory */ sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid_ioport, RF_ACTIVE); if (sc->res_ioport == 0) { device_printf(dev, "cannot reserve I/O port range\n"); goto error; } sc->bt_ioport = rman_get_bustag(sc->res_ioport); sc->bh_ioport = rman_get_bushandle(sc->res_ioport); sc->pcf_flags = device_get_flags(dev); /* * XXX use poll-mode property? */ if (!(sc->pcf_flags & IIC_POLLED)) { sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rid_irq, RF_ACTIVE); if (sc->res_irq == 0) { device_printf(dev, "can't reserve irq, polled mode.\n"); sc->pcf_flags |= IIC_POLLED; } } /* * XXX on AXmp there's probably a second IRQ which is the fan fail * interrupt genererated by the PCF8574 at 0x78. */ /* get address of the pcf */ if (OF_getprop(node, "own-address", &own_addr, sizeof(own_addr)) == -1) { device_printf(dev, "cannot get own address\n"); goto error; } if (bootverbose) device_printf(dev, "PCF8584 address: 0x%08llx\n", (unsigned long long)own_addr); /* reset the chip */ pcf_rst_card(dev, IIC_FASTEST, own_addr, NULL); if (sc->res_irq) { rv = bus_setup_intr(dev, sc->res_irq, INTR_TYPE_NET /* | INTR_ENTROPY */, NULL, 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"); /* probe and attach the iicbus */ bus_generic_attach(dev); return (0); error: if (sc->res_irq != 0) { bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq); } if (sc->res_ioport != 0) { bus_release_resource(dev, SYS_RES_MEMORY, sc->rid_ioport, sc->res_ioport); } return (rv); }
static int pcf_isa_attach(device_t dev) { struct pcf_softc *sc; int rv = ENXIO; sc = DEVTOSOFTC(dev); mtx_init(&sc->pcf_lock, device_get_nameunit(dev), "pcf", MTX_DEF); /* IO port is mandatory */ sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->rid_ioport, RF_ACTIVE); if (sc->res_ioport == 0) { device_printf(dev, "cannot reserve I/O port range\n"); goto error; } sc->pcf_flags = device_get_flags(dev); if (!(sc->pcf_flags & IIC_POLLED)) { sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rid_irq, RF_ACTIVE); if (sc->res_irq == 0) { device_printf(dev, "can't reserve irq, polled mode.\n"); sc->pcf_flags |= IIC_POLLED; } } /* reset the chip */ pcf_rst_card(dev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL); if (sc->res_irq) { rv = bus_setup_intr(dev, sc->res_irq, INTR_TYPE_NET /* | INTR_ENTROPY */, NULL, 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"); /* probe and attach the iicbus */ bus_generic_attach(dev); return (0); error: if (sc->res_irq != 0) { bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq); } if (sc->res_ioport != 0) { bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, sc->res_ioport); } mtx_destroy(&sc->pcf_lock); return (rv); }
static int envctrl_attach(device_t dev) { struct pcf_softc *sc; int rv = ENXIO; sc = DEVTOSOFTC(dev); bzero(sc, sizeof(struct pcf_softc)); /* IO port is mandatory */ sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->rid_ioport, RF_ACTIVE); if (sc->res_ioport == 0) { device_printf(dev, "cannot reserve I/O port range\n"); goto error; } sc->bt_ioport = rman_get_bustag(sc->res_ioport); sc->bh_ioport = rman_get_bushandle(sc->res_ioport); sc->pcf_flags = device_get_flags(dev); if (!(sc->pcf_flags & IIC_POLLED)) { sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rid_irq, RF_ACTIVE); if (sc->res_irq == 0) { device_printf(dev, "can't reserve irq, polled mode.\n"); sc->pcf_flags |= IIC_POLLED; } } /* 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->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) device_printf(dev, "could not allocate iicbus instance\n"); /* probe and attach the iicbus */ bus_generic_attach(dev); return (0); error: if (sc->res_irq != 0) { bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq); bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq); } if (sc->res_ioport != 0) { bus_deactivate_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, sc->res_ioport); bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, sc->res_ioport); } return (rv); }