예제 #1
0
static int
at91_usart_requires_rts0_workaround(struct uart_softc *sc)
{
	int value;
	int unit;

	unit = device_get_unit(sc->sc_dev);

	/*
	 * On the rm9200 chips, the PA21/RTS0 pin is not correctly wired to the
	 * usart device interally (so-called 'erratum 39', but it's 41.14 in rev
	 * I of the manual).  This prevents use of the hardware flow control
	 * feature in the usart itself.  It also means that if we are to
	 * implement RTS/CTS flow via the tty layer logic, we must use pin PA21
	 * as a gpio and manually manipulate it in at91_usart_bus_setsig().  We
	 * can only safely do so if we've been given permission via a hint,
	 * otherwise we might manipulate a pin that's attached to who-knows-what
	 * and Bad Things could happen.
	 */
	if (at91_is_rm92() && unit == 1) {
		value = 0;
		resource_int_value(device_get_name(sc->sc_dev), unit,
		    "use_rts0_workaround", &value);
		if (value != 0) {
			at91_pio_use_gpio(AT91RM92_PIOA_BASE, AT91C_PIO_PA21);
			at91_pio_gpio_output(AT91RM92_PIOA_BASE, 
			    AT91C_PIO_PA21, 1);
			at91_pio_use_periph_a(AT91RM92_PIOA_BASE, 
			    AT91C_PIO_PA20, 0);
			return (1);
		}
	}
	return (0);
}
예제 #2
0
static int
at91_mci_attach(device_t dev)
{
	struct at91_mci_softc *sc = device_get_softc(dev);
	struct sysctl_ctx_list *sctx;
	struct sysctl_oid *soid;
	device_t child;
	int err, i;

	sctx = device_get_sysctl_ctx(dev);
	soid = device_get_sysctl_tree(dev);

	sc->dev = dev;
	sc->sc_cap = 0;
	if (at91_is_rm92())
		sc->sc_cap |= CAP_NEEDS_BYTESWAP;
	/*
	 * MCI1 Rev 2 controllers need some workarounds, flag if so.
	 */
	if (at91_mci_is_mci1rev2xx())
		sc->sc_cap |= CAP_MCI1_REV2XX;

	err = at91_mci_activate(dev);
	if (err)
		goto out;

	AT91_MCI_LOCK_INIT(sc);

	at91_mci_fini(dev);
	at91_mci_init(dev);

	/*
	 * Allocate DMA tags and maps and bounce buffers.
	 *
	 * The parms in the tag_create call cause the dmamem_alloc call to
	 * create each bounce buffer as a single contiguous buffer of BBSIZE
	 * bytes aligned to a 4096 byte boundary.
	 *
	 * Do not use DMA_COHERENT for these buffers because that maps the
	 * memory as non-cachable, which prevents cache line burst fills/writes,
	 * which is something we need since we're trying to overlap the
	 * byte-swapping with the DMA operations.
	 */
	err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
	    BBSIZE, 1, BBSIZE, 0, NULL, NULL, &sc->dmatag);
	if (err != 0)
		goto out;

	for (i = 0; i < BBCOUNT; ++i) {
		err = bus_dmamem_alloc(sc->dmatag, (void **)&sc->bbuf_vaddr[i],
		    BUS_DMA_NOWAIT, &sc->bbuf_map[i]);
		if (err != 0)
			goto out;
	}

	/*
	 * Activate the interrupt
	 */
	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, at91_mci_intr, sc, &sc->intrhand);
	if (err) {
		AT91_MCI_LOCK_DESTROY(sc);
		goto out;
	}

	/*
	 * Allow 4-wire to be initially set via #define.
	 * Allow a device hint to override that.
	 * Allow a sysctl to override that.
	 */
#if defined(AT91_MCI_HAS_4WIRE) && AT91_MCI_HAS_4WIRE != 0
	sc->has_4wire = 1;
#endif
	resource_int_value(device_get_name(dev), device_get_unit(dev),
			   "4wire", &sc->has_4wire);
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "4wire",
	    CTLFLAG_RW, &sc->has_4wire, 0, "has 4 wire SD Card bus");
	if (sc->has_4wire)
		sc->sc_cap |= CAP_HAS_4WIRE;

	sc->allow_overclock = AT91_MCI_ALLOW_OVERCLOCK;
	resource_int_value(device_get_name(dev), device_get_unit(dev),
			   "allow_overclock", &sc->allow_overclock);
	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "allow_overclock",
	    CTLFLAG_RW, &sc->allow_overclock, 0,
	    "Allow up to 30MHz clock for 25MHz request when next highest speed 15MHz or less.");

	/*
	 * Our real min freq is master_clock/512, but upper driver layers are
	 * going to set the min speed during card discovery, and the right speed
	 * for that is 400kHz, so advertise a safe value just under that.
	 *
	 * For max speed, while the rm9200 manual says the max is 50mhz, it also
	 * says it supports only the SD v1.0 spec, which means the real limit is
	 * 25mhz. On the other hand, historical use has been to slightly violate
	 * the standard by running the bus at 30MHz.  For more information on
	 * that, see the comments at the top of this file.
	 */
	sc->host.f_min = 375000;
	sc->host.f_max = at91_master_clock / 2;
	if (sc->host.f_max > 25000000)
		sc->host.f_max = 25000000;
	sc->host.host_ocr = MMC_OCR_320_330 | MMC_OCR_330_340;
	sc->host.caps = 0;
	if (sc->sc_cap & CAP_HAS_4WIRE)
		sc->host.caps |= MMC_CAP_4_BIT_DATA;

	child = device_add_child(dev, "mmc", 0);
	device_set_ivars(dev, &sc->host);
	err = bus_generic_attach(dev);
out:
	if (err)
		at91_mci_deactivate(dev);
	return (err);
}
예제 #3
0
static int
at91_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
{
	struct at91_spi_softc *sc;
	bus_addr_t addr;
	int err, i, j, mode[4];

	KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
	    ("%s: TX/RX command sizes should be equal", __func__));
	KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
	    ("%s: TX/RX data sizes should be equal", __func__));

	sc = device_get_softc(dev);
	i = 0;

	sx_xlock(&sc->xfer_mtx);

	/*
	 * Disable transfers while we set things up.
	 */
	WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS);

#ifdef SPI_CHIPSEL_SUPPORT
	if (cmd->cs < 0 || cmd->cs > 3) {
		device_printf(dev,
		    "Invalid chip select %d requested by %s\n", cmd->cs,
		    device_get_nameunit(child));
		err = EINVAL;
		goto out;
	}
#ifdef SPI_CHIP_SELECT_HIGH_SUPPORT
	if (at91_is_rm92() && cmd->cs == 0 &&
	    (cmd->flags & SPI_CHIP_SELECT_HIGH) != 0) {
		device_printf(dev,
		    "Invalid chip select high requested by %s\n",
		    device_get_nameunit(child));
		err = EINVAL;
		goto out;
	}
#endif
	WR4(sc, SPI_MR, (RD4(sc, SPI_MR) & ~0x000f0000) | CS_TO_MR(cmd->cs));
#endif

	/*
	 * Set up the TX side of the transfer.
	 */
	if ((err = bus_dmamap_load(sc->dmatag, sc->map[i], cmd->tx_cmd,
	    cmd->tx_cmd_sz, at91_getaddr, &addr, 0)) != 0)
		goto out;
	WR4(sc, PDC_TPR, addr);
	WR4(sc, PDC_TCR, cmd->tx_cmd_sz);
	bus_dmamap_sync(sc->dmatag, sc->map[i], BUS_DMASYNC_PREWRITE);
	mode[i++] = BUS_DMASYNC_POSTWRITE;
	if (cmd->tx_data_sz > 0) {
		if ((err = bus_dmamap_load(sc->dmatag, sc->map[i],
		    cmd->tx_data, cmd->tx_data_sz, at91_getaddr, &addr, 0)) !=
		    0)
			goto out;
		WR4(sc, PDC_TNPR, addr);
		WR4(sc, PDC_TNCR, cmd->tx_data_sz);
		bus_dmamap_sync(sc->dmatag, sc->map[i], BUS_DMASYNC_PREWRITE);
		mode[i++] = BUS_DMASYNC_POSTWRITE;
	}

	/*
	 * Set up the RX side of the transfer.
	 */
	if ((err = bus_dmamap_load(sc->dmatag, sc->map[i], cmd->rx_cmd,
	    cmd->rx_cmd_sz, at91_getaddr, &addr, 0)) != 0)
		goto out;
	WR4(sc, PDC_RPR, addr);
	WR4(sc, PDC_RCR, cmd->rx_cmd_sz);
	bus_dmamap_sync(sc->dmatag, sc->map[i], BUS_DMASYNC_PREREAD);
	mode[i++] = BUS_DMASYNC_POSTREAD;
	if (cmd->rx_data_sz > 0) {
		if ((err = bus_dmamap_load(sc->dmatag, sc->map[i],
		    cmd->rx_data, cmd->rx_data_sz, at91_getaddr, &addr, 0)) !=
		    0)
			goto out;
		WR4(sc, PDC_RNPR, addr);
		WR4(sc, PDC_RNCR, cmd->rx_data_sz);
		bus_dmamap_sync(sc->dmatag, sc->map[i], BUS_DMASYNC_PREREAD);
		mode[i++] = BUS_DMASYNC_POSTREAD;
	}

	/*
	 * Start the transfer, wait for it to complete.
	 */
	sc->xfer_done = 0;
	WR4(sc, SPI_IER, SPI_SR_RXBUFF);
	WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN | PDC_PTCR_RXTEN);
	do
		err = tsleep(&sc->xfer_done, PCATCH | PZERO, "at91_spi", hz);
	while (sc->xfer_done == 0 && err != EINTR);

	/*
	 * Stop the transfer and clean things up.
	 */
	WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS);
	if (err == 0)
		for (j = 0; j < i; j++)
			bus_dmamap_sync(sc->dmatag, sc->map[j], mode[j]);
out:
	for (j = 0; j < i; j++)
		bus_dmamap_unload(sc->dmatag, sc->map[j]);

	sx_xunlock(&sc->xfer_mtx);

	return (err);
}