Esempio n. 1
0
static int
bcm_spi_attach(device_t dev)
{
	struct bcm_spi_softc *sc;
	device_t gpio;
	int i, rid;

	if (device_get_unit(dev) != 0) {
		device_printf(dev, "only one SPI controller supported\n");
		return (ENXIO);
	}

	sc = device_get_softc(dev);
	sc->sc_dev = dev;

	/* Configure the GPIO pins to ALT0 function to enable SPI the pins. */
	gpio = devclass_get_device(devclass_find("gpio"), 0);
	if (!gpio) {
		device_printf(dev, "cannot find gpio0\n");
		return (ENXIO);
	}
	for (i = 0; i < nitems(bcm_spi_pins); i++)
		bcm_gpio_set_alternate(gpio, bcm_spi_pins[i], BCM_GPIO_ALT0);

	rid = 0;
	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->sc_mem_res) {
		device_printf(dev, "cannot allocate memory window\n");
		return (ENXIO);
	}

	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (!sc->sc_irq_res) {
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
		device_printf(dev, "cannot allocate interrupt\n");
		return (ENXIO);
	}

	/* Hook up our interrupt handler. */
	if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, bcm_spi_intr, sc, &sc->sc_intrhand)) {
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
		device_printf(dev, "cannot setup the interrupt handler\n");
		return (ENXIO);
	}

	mtx_init(&sc->sc_mtx, "bcm_spi", NULL, MTX_DEF);

	/* Add sysctl nodes. */
	bcm_spi_sysctl_init(sc);

#ifdef	BCM_SPI_DEBUG
	bcm_spi_printr(dev);
#endif

	/*
	 * Enable the SPI controller.  Clear the rx and tx FIFO.
	 * Defaults to SPI mode 0.
	 */
	BCM_SPI_WRITE(sc, SPI_CS, SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO);

	/* Set the SPI clock to 500Khz. */
	BCM_SPI_WRITE(sc, SPI_CLK, SPI_CORE_CLK / 500000);

#ifdef	BCM_SPI_DEBUG
	bcm_spi_printr(dev);
#endif

	device_add_child(dev, "spibus", -1);

	return (bus_generic_attach(dev));
}
Esempio n. 2
0
static int
bcm_bsc_attach(device_t dev)
{
    struct bcm_bsc_softc *sc;
    unsigned long start;
    device_t gpio;
    int i, rid;

    sc = device_get_softc(dev);
    sc->sc_dev = dev;

    rid = 0;
    sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
                                            RF_ACTIVE);
    if (!sc->sc_mem_res) {
        device_printf(dev, "cannot allocate memory window\n");
        return (ENXIO);
    }

    sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
    sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);

    /* Check the unit we are attaching by its base address. */
    start = rman_get_start(sc->sc_mem_res);
    for (i = 0; i < nitems(bcm_bsc_pins); i++) {
        if (bcm_bsc_pins[i].start == (start & BCM_BSC_BASE_MASK))
            break;
    }
    if (i == nitems(bcm_bsc_pins)) {
        device_printf(dev, "only bsc0 and bsc1 are supported\n");
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        return (ENXIO);
    }

    /*
     * Configure the GPIO pins to ALT0 function to enable BSC control
     * over the pins.
     */
    gpio = devclass_get_device(devclass_find("gpio"), 0);
    if (!gpio) {
        device_printf(dev, "cannot find gpio0\n");
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        return (ENXIO);
    }
    bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].sda, BCM_GPIO_ALT0);
    bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].scl, BCM_GPIO_ALT0);

    rid = 0;
    sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
                                            RF_ACTIVE | RF_SHAREABLE);
    if (!sc->sc_irq_res) {
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        device_printf(dev, "cannot allocate interrupt\n");
        return (ENXIO);
    }

    /* Hook up our interrupt handler. */
    if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
                       NULL, bcm_bsc_intr, sc, &sc->sc_intrhand)) {
        bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        device_printf(dev, "cannot setup the interrupt handler\n");
        return (ENXIO);
    }

    mtx_init(&sc->sc_mtx, "bcm_bsc", NULL, MTX_DEF);

    bcm_bsc_sysctl_init(sc);

    /* Enable the BSC controller.  Flush the FIFO. */
    BCM_BSC_LOCK(sc);
    bcm_bsc_reset(sc);
    BCM_BSC_UNLOCK(sc);

    sc->sc_iicbus = device_add_child(dev, "iicbus", -1);
    if (sc->sc_iicbus == NULL) {
        bcm_bsc_detach(dev);
        return (ENXIO);
    }

    return (bus_generic_attach(dev));
}