Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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);
}