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); }
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); }
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); }