static void cs_activate(struct atmel_spi *as, struct spi_device *spi) { unsigned gpio = (unsigned) spi->controller_data; unsigned active = spi->mode & SPI_CS_HIGH; u32 mr; int i; u32 csr; u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; /* Make sure clock polarity is correct */ for (i = 0; i < spi->master->num_chipselect; i++) { csr = spi_readl(as, CSR0 + 4 * i); if ((csr ^ cpol) & SPI_BIT(CPOL)) spi_writel(as, CSR0 + 4 * i, csr ^ SPI_BIT(CPOL)); } mr = spi_readl(as, MR); mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr); dev_dbg(&spi->dev, "activate %u%s, mr %08x\n", gpio, active ? " (high)" : "", mr); if (!(cpu_is_at91rm9200() && spi->chip_select == 0)) gpio_set_value(gpio, active); spi_writel(as, MR, mr); }
/* * Handle after a dma read */ static void at91_mci_post_dma_read(struct at91mci_host *host) { struct mmc_command *cmd; struct mmc_data *data; pr_debug("post dma read\n"); cmd = host->cmd; if (!cmd) { pr_debug("no command\n"); return; } data = cmd->data; if (!data) { pr_debug("no data\n"); return; } while (host->in_use_index < host->transfer_index) { struct scatterlist *sg; pr_debug("finishing index %d\n", host->in_use_index); sg = &data->sg[host->in_use_index++]; pr_debug("Unmapping page %08X\n", sg->dma_address); dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE); data->bytes_xfered += sg->length; if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ unsigned int *buffer; int index; /* Swap the contents of the buffer */ buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; pr_debug("buffer = %p, length = %d\n", buffer, sg->length); for (index = 0; index < (sg->length / 4); index++) buffer[index] = swab32(buffer[index]); kunmap_atomic(buffer, KM_BIO_SRC_IRQ); } flush_dcache_page(sg_page(sg)); } /* Is there another transfer to trigger? */ if (host->transfer_index < data->sg_len) at91_mci_pre_dma_read(host); else { at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX); at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF); } pr_debug("post dma read done\n"); }
static void at91_mci_post_dma_read(struct at91mci_host *host) { struct mmc_command *cmd; struct mmc_data *data; unsigned int len, i, size; unsigned *dmabuf = host->buffer; pr_debug("post dma read\n"); cmd = host->cmd; if (!cmd) { pr_debug("no command\n"); return; } data = cmd->data; if (!data) { pr_debug("no data\n"); return; } size = data->blksz * data->blocks; len = data->sg_len; at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX); at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF); for (i = 0; i < len; i++) { struct scatterlist *sg; int amount; unsigned int *sgbuffer; sg = &data->sg[i]; sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset; amount = min(size, sg->length); size -= amount; if (cpu_is_at91rm9200()) { int index; for (index = 0; index < (amount / 4); index++) sgbuffer[index] = swab32(*dmabuf++); } else { char *tmpv = (char *)dmabuf; memcpy(sgbuffer, tmpv, amount); tmpv += amount; dmabuf = (unsigned *)tmpv; } flush_kernel_dcache_page(sg_page(sg)); kunmap_atomic(sgbuffer); data->bytes_xfered += amount; if (size == 0) break; } pr_debug("post dma read done\n"); }
/* * Copy from sg to a dma block - used for transfers */ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data) { unsigned int len, i, size; unsigned *dmabuf = host->buffer; size = data->blksz * data->blocks; len = data->sg_len; /* MCI1 rev2xx Data Write Operation and number of bytes erratum */ if (at91mci_is_mci1rev2xx()) if (host->total_length == 12) memset(dmabuf, 0, 12); /* * Just loop through all entries. Size might not * be the entire list though so make sure that * we do not transfer too much. */ for (i = 0; i < len; i++) { struct scatterlist *sg; int amount; unsigned int *sgbuffer; sg = &data->sg[i]; sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; amount = min(size, sg->length); size -= amount; if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ int index; for (index = 0; index < (amount / 4); index++) *dmabuf++ = swab32(sgbuffer[index]); } else { char *tmpv = (char *)dmabuf; memcpy(tmpv, sgbuffer, amount); tmpv += amount; dmabuf = (unsigned *)tmpv; } kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); if (size == 0) break; } /* * Check that we didn't get a request to transfer * more data than can fit into the SG list. */ BUG_ON(size != 0); }
static void at91_mci_process_next(struct at91mci_host *host) { if (!(host->flags & FL_SENT_COMMAND)) { host->flags |= FL_SENT_COMMAND; at91_mci_send_command(host, host->request->cmd); } else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) { host->flags |= FL_SENT_STOP; at91_mci_send_command(host, host->request->stop); } else { del_timer(&host->timer); if (cpu_is_at91rm9200()) at91_reset_host(host); mmc_request_done(host->mmc, host->request); } }
static int __init at91_pm_init(void) { #ifdef CONFIG_AT91_SLOW_CLOCK slow_clock = (void *) (AT91_IO_VIRT_BASE - at91_slow_clock_sz); #endif pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : "")); /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */ if (cpu_is_at91rm9200()) at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0); suspend_set_ops(&at91_pm_ops); show_reset_status(); return 0; }
static void cs_activate(struct atmel_spi *as, struct spi_device *spi) { unsigned gpio = (unsigned) spi->controller_data; unsigned active = spi->mode & SPI_CS_HIGH; u32 mr; mr = spi_readl(as, MR); mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr); dev_dbg(&spi->dev, "activate %u%s, mr %08x\n", gpio, active ? " (high)" : "", mr); if (!(cpu_is_at91rm9200() && spi->chip_select == 0)) gpio_set_value(gpio, active); spi_writel(as, MR, mr); }
/* * Copy from sg to a dma block - used for transfers */ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data) { unsigned int len, i, size; unsigned *dmabuf = host->buffer; size = host->total_length; len = data->sg_len; /* * Just loop through all entries. Size might not * be the entire list though so make sure that * we do not transfer too much. */ for (i = 0; i < len; i++) { struct scatterlist *sg; int amount; unsigned int *sgbuffer; sg = &data->sg[i]; sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; amount = min(size, sg->length); size -= amount; if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ int index; for (index = 0; index < (amount / 4); index++) *dmabuf++ = swab32(sgbuffer[index]); } else memcpy(dmabuf, sgbuffer, amount); kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); if (size == 0) break; } /* * Check that we didn't get a request to transfer * more data than can fit into the SG list. */ BUG_ON(size != 0); }
static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data) { unsigned int len, i, size; unsigned *dmabuf = host->buffer; size = data->blksz * data->blocks; len = data->sg_len; if (at91mci_is_mci1rev2xx()) if (host->total_length == 12) memset(dmabuf, 0, 12); for (i = 0; i < len; i++) { struct scatterlist *sg; int amount; unsigned int *sgbuffer; sg = &data->sg[i]; sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset; amount = min(size, sg->length); size -= amount; if (cpu_is_at91rm9200()) { int index; for (index = 0; index < (amount / 4); index++) *dmabuf++ = swab32(sgbuffer[index]); } else { char *tmpv = (char *)dmabuf; memcpy(tmpv, sgbuffer, amount); tmpv += amount; dmabuf = (unsigned *)tmpv; } kunmap_atomic(sgbuffer); if (size == 0) break; } BUG_ON(size != 0); }
static int at91_pm_verify_clocks(void) { unsigned long scsr; int i; scsr = at91_sys_read(AT91_PMC_SCSR); /* USB must not be using PLLB */ if (cpu_is_at91rm9200()) { if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) { pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); return 0; } } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20() || cpu_is_at91sam9g10()) { if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) { pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); return 0; } } else if (cpu_is_at91cap9()) { if ((scsr & AT91CAP9_PMC_UHP) != 0) { pr_err("AT91: PM - Suspend-to-RAM with USB still active\n"); return 0; } } #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS /* PCK0..PCK3 must be disabled, or configured to use clk32k */ for (i = 0; i < 4; i++) { u32 css; if ((scsr & (AT91_PMC_PCK0 << i)) == 0) continue; css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS; if (css != AT91_PMC_CSS_SLOW) { pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); return 0; } } #endif return 1; }
/* * Process the next step in the request */ static void at91_mci_process_next(struct at91mci_host *host) { if (!(host->flags & FL_SENT_COMMAND)) { host->flags |= FL_SENT_COMMAND; at91_mci_send_command(host, host->request->cmd); } else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) { host->flags |= FL_SENT_STOP; at91_mci_send_command(host, host->request->stop); } else { del_timer(&host->timer); /* the at91rm9200 mci controller hangs after some transfers, * and the workaround is to reset it after each transfer. */ if (cpu_is_at91rm9200()) at91_reset_host(host); mmc_request_done(host->mmc, host->request); } }
/* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { if (cpu_is_at91rm9200()) at91rm9200_standby(); else if (cpu_is_at91sam9g45()) at91sam9g45_standby(); else if (cpu_is_at91sam9263()) at91sam9263_standby(); else if (cpu_is_at91sam9x5() || cpu_is_at91sam9n12() || cpu_is_sama5d3() || cpu_is_sama5d4()) at91sam_ddrc_standby(); else at91sam9_standby(); return index; }
/* * Set state of the modem control output lines */ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) { unsigned int control = 0; unsigned int mode; #ifdef CONFIG_ARCH_AT91RM9200 if (cpu_is_at91rm9200()) { /* * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21. * We need to drive the pin manually. */ if (port->mapbase == AT91RM9200_BASE_US0) { if (mctrl & TIOCM_RTS) at91_set_gpio_value(AT91_PIN_PA21, 0); else at91_set_gpio_value(AT91_PIN_PA21, 1); } } #endif if (mctrl & TIOCM_RTS) control |= ATMEL_US_RTSEN; else control |= ATMEL_US_RTSDIS; if (mctrl & TIOCM_DTR) control |= ATMEL_US_DTREN; else control |= ATMEL_US_DTRDIS; UART_PUT_CR(port, control); /* Local loopback mode? */ mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE; if (mctrl & TIOCM_LOOP) mode |= ATMEL_US_CHMODE_LOC_LOOP; else mode |= ATMEL_US_CHMODE_NORMAL; UART_PUT_MR(port, mode); }
static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) { unsigned gpio = (unsigned) spi->controller_data; unsigned active = spi->mode & SPI_CS_HIGH; u32 mr; /* only deactivate *this* device; sometimes transfers to * another device may be active when this routine is called. */ mr = spi_readl(as, MR); if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) { mr = SPI_BFINS(PCS, 0xf, mr); spi_writel(as, MR, mr); } dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n", gpio, active ? " (low)" : "", mr); if (!(cpu_is_at91rm9200() && spi->chip_select == 0)) gpio_set_value(gpio, !active); }
static int at91_pm_enter(suspend_state_t state) { if (of_have_populated_dt()) at91_pinctrl_gpio_suspend(); else at91_gpio_suspend(); at91_irq_suspend(); pr_debug("AT91: PM - wake mask %08x, pm state %d\n", /* remember all the always-wake irqs */ (at91_pmc_read(AT91_PMC_PCSR) | (1 << AT91_ID_FIQ) | (1 << AT91_ID_SYS) | (at91_get_extern_irq())) & at91_aic_read(AT91_AIC_IMR), state); switch (state) { /* * Suspend-to-RAM is like STANDBY plus slow clock mode, so * drivers must suspend more deeply: only the master clock * controller may be using the main oscillator. */ case PM_SUSPEND_MEM: /* * Ensure that clocks are in a valid state. */ if (!at91_pm_verify_clocks()) goto error; /* * Enter slow clock mode by switching over to clk32k and * turning off the main oscillator; reverse on wakeup. */ if (slow_clock) { int memctrl = AT91_MEMCTRL_SDRAMC; if (cpu_is_at91rm9200()) memctrl = AT91_MEMCTRL_MC; else if (cpu_is_at91sam9g45()) memctrl = AT91_MEMCTRL_DDRSDR; #ifdef CONFIG_AT91_SLOW_CLOCK /* copy slow_clock handler to SRAM, and call it */ memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz); #endif slow_clock(at91_pmc_base, at91_ramc_base[0], at91_ramc_base[1], memctrl); break; } else { pr_info("AT91: PM - no slow clock mode enabled ...\n"); /* FALLTHROUGH leaving master clock alone */ } /* * STANDBY mode has *all* drivers suspended; ignores irqs not * marked as 'wakeup' event sources; and reduces DRAM power. * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and * nothing fancy done with main or cpu clocks. */ case PM_SUSPEND_STANDBY: /* * NOTE: the Wait-for-Interrupt instruction needs to be * in icache so no SDRAM accesses are needed until the * wakeup IRQ occurs and self-refresh is terminated. * For ARM 926 based chips, this requirement is weaker * as at91sam9 can access a RAM in self-refresh mode. */ if (at91_pm_standby) at91_pm_standby(); break; case PM_SUSPEND_ON: cpu_do_idle(); break; default: pr_debug("AT91: PM - bogus suspend state %d\n", state); goto error; } pr_debug("AT91: PM - wakeup %08x\n", at91_aic_read(AT91_AIC_IPR) & at91_aic_read(AT91_AIC_IMR)); error: target_state = PM_SUSPEND_ON; at91_irq_resume(); if (of_have_populated_dt()) at91_pinctrl_gpio_resume(); else at91_gpio_resume(); return 0; }
/* * Version 2 of the SPI controller has * - CR.LASTXFER * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero) * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs) * - SPI_CSRx.CSAAT * - SPI_CSRx.SBCR allows faster clocking * * We can determine the controller version by reading the VERSION * register, but I haven't checked that it exists on all chips, and * this is cheaper anyway. */ static bool atmel_spi_is_v2(void) { return !cpu_is_at91rm9200(); }
static int at91_pm_enter(suspend_state_t state) { at91_gpio_suspend(); at91_irq_suspend(); pr_debug("AT91: PM - wake mask %08x, pm state %d\n", /* */ (at91_pmc_read(AT91_PMC_PCSR) | (1 << AT91_ID_FIQ) | (1 << AT91_ID_SYS) | (at91_extern_irq)) & at91_aic_read(AT91_AIC_IMR), state); switch (state) { /* */ case PM_SUSPEND_MEM: /* */ if (!at91_pm_verify_clocks()) goto error; /* */ if (slow_clock) { int memctrl = AT91_MEMCTRL_SDRAMC; if (cpu_is_at91rm9200()) memctrl = AT91_MEMCTRL_MC; else if (cpu_is_at91sam9g45()) memctrl = AT91_MEMCTRL_DDRSDR; #ifdef CONFIG_AT91_SLOW_CLOCK /* */ memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz); #endif slow_clock(at91_pmc_base, at91_ramc_base[0], at91_ramc_base[1], memctrl); break; } else { pr_info("AT91: PM - no slow clock mode enabled ...\n"); /* */ } /* */ case PM_SUSPEND_STANDBY: /* */ at91_standby(); break; case PM_SUSPEND_ON: cpu_do_idle(); break; default: pr_debug("AT91: PM - bogus suspend state %d\n", state); goto error; } pr_debug("AT91: PM - wakeup %08x\n", at91_aic_read(AT91_AIC_IPR) & at91_aic_read(AT91_AIC_IMR)); error: target_state = PM_SUSPEND_ON; at91_irq_resume(); at91_gpio_resume(); return 0; }
static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd) { unsigned int cmdr, mr; unsigned int block_length; struct mmc_data *data = cmd->data; unsigned int blocks; unsigned int ier = 0; host->cmd = cmd; if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { pr_debug("Clearing timeout\n"); at91_mci_write(host, AT91_MCI_ARGR, 0); at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD); while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) { pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR)); } } cmdr = cmd->opcode; if (mmc_resp_type(cmd) == MMC_RSP_NONE) cmdr |= AT91_MCI_RSPTYP_NONE; else { cmdr |= AT91_MCI_MAXLAT; if (mmc_resp_type(cmd) == MMC_RSP_R2) cmdr |= AT91_MCI_RSPTYP_136; else cmdr |= AT91_MCI_RSPTYP_48; } if (data) { if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) { if (data->blksz & 0x3) { pr_debug("Unsupported block size\n"); cmd->error = -EINVAL; mmc_request_done(host->mmc, host->request); return; } if (data->flags & MMC_DATA_STREAM) { pr_debug("Stream commands not supported\n"); cmd->error = -EINVAL; mmc_request_done(host->mmc, host->request); return; } } block_length = data->blksz; blocks = data->blocks; if (data->flags & MMC_DATA_READ) cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START); else if (data->flags & MMC_DATA_WRITE) cmdr |= AT91_MCI_TRCMD_START; if (cmd->opcode == SD_IO_RW_EXTENDED) { cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK; } else { if (data->flags & MMC_DATA_STREAM) cmdr |= AT91_MCI_TRTYP_STREAM; if (data->blocks > 1) cmdr |= AT91_MCI_TRTYP_MULTIPLE; } } else { block_length = 0; blocks = 0; } if (host->flags & FL_SENT_STOP) cmdr |= AT91_MCI_TRCMD_STOP; if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) cmdr |= AT91_MCI_OPDCMD; pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n", cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR)); if (!data) { at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS); at91_mci_write(host, ATMEL_PDC_RPR, 0); at91_mci_write(host, ATMEL_PDC_RCR, 0); at91_mci_write(host, ATMEL_PDC_RNPR, 0); at91_mci_write(host, ATMEL_PDC_RNCR, 0); at91_mci_write(host, ATMEL_PDC_TPR, 0); at91_mci_write(host, ATMEL_PDC_TCR, 0); at91_mci_write(host, ATMEL_PDC_TNPR, 0); at91_mci_write(host, ATMEL_PDC_TNCR, 0); ier = AT91_MCI_CMDRDY; } else { mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff; mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0; mr |= (block_length << 16); mr |= AT91_MCI_PDCMODE; at91_mci_write(host, AT91_MCI_MR, mr); if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261())) at91_mci_write(host, AT91_MCI_BLKR, AT91_MCI_BLKR_BCNT(blocks) | AT91_MCI_BLKR_BLKLEN(block_length)); at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); if (cmdr & AT91_MCI_TRCMD_START) { data->bytes_xfered = 0; host->transfer_index = 0; host->in_use_index = 0; if (cmdr & AT91_MCI_TRDIR) { host->total_length = 0; at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address); at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? (blocks * block_length) : (blocks * block_length) / 4); at91_mci_write(host, ATMEL_PDC_RNPR, 0); at91_mci_write(host, ATMEL_PDC_RNCR, 0); ier = AT91_MCI_ENDRX ; } else { host->total_length = block_length * blocks; if (at91mci_is_mci1rev2xx()) if (host->total_length < 12) host->total_length = 12; at91_mci_sg_to_dma(host, data); pr_debug("Transmitting %d bytes\n", host->total_length); at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ? host->total_length : host->total_length / 4); ier = AT91_MCI_CMDRDY; } } } at91_mci_write(host, AT91_MCI_ARGR, cmd->arg); at91_mci_write(host, AT91_MCI_CMDR, cmdr); if (cmdr & AT91_MCI_TRCMD_START) { if (cmdr & AT91_MCI_TRDIR) at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN); } at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier); }
/* * Send a command */ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd) { unsigned int cmdr, mr; unsigned int block_length; struct mmc_data *data = cmd->data; unsigned int blocks; unsigned int ier = 0; host->cmd = cmd; /* Needed for leaving busy state before CMD1 */ if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { pr_debug("Clearing timeout\n"); at91_mci_write(host, AT91_MCI_ARGR, 0); at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD); while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) { /* spin */ pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR)); } } cmdr = cmd->opcode; if (mmc_resp_type(cmd) == MMC_RSP_NONE) cmdr |= AT91_MCI_RSPTYP_NONE; else { /* if a response is expected then allow maximum response latancy */ cmdr |= AT91_MCI_MAXLAT; /* set 136 bit response for R2, 48 bit response otherwise */ if (mmc_resp_type(cmd) == MMC_RSP_R2) cmdr |= AT91_MCI_RSPTYP_136; else cmdr |= AT91_MCI_RSPTYP_48; } if (data) { if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) { if (data->blksz & 0x3) { pr_debug("Unsupported block size\n"); cmd->error = -EINVAL; mmc_request_done(host->mmc, host->request); return; } if (data->flags & MMC_DATA_STREAM) { pr_debug("Stream commands not supported\n"); cmd->error = -EINVAL; mmc_request_done(host->mmc, host->request); return; } } block_length = data->blksz; blocks = data->blocks; /* always set data start - also set direction flag for read */ if (data->flags & MMC_DATA_READ) cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START); else if (data->flags & MMC_DATA_WRITE) cmdr |= AT91_MCI_TRCMD_START; if (cmd->opcode == SD_IO_RW_EXTENDED) { cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK; } else { if (data->flags & MMC_DATA_STREAM) cmdr |= AT91_MCI_TRTYP_STREAM; if (data->blocks > 1) cmdr |= AT91_MCI_TRTYP_MULTIPLE; } } else { block_length = 0; blocks = 0; } if (host->flags & FL_SENT_STOP) cmdr |= AT91_MCI_TRCMD_STOP; if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) cmdr |= AT91_MCI_OPDCMD; /* * Set the arguments and send the command */ pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n", cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR)); if (!data) { at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS); at91_mci_write(host, ATMEL_PDC_RPR, 0); at91_mci_write(host, ATMEL_PDC_RCR, 0); at91_mci_write(host, ATMEL_PDC_RNPR, 0); at91_mci_write(host, ATMEL_PDC_RNCR, 0); at91_mci_write(host, ATMEL_PDC_TPR, 0); at91_mci_write(host, ATMEL_PDC_TCR, 0); at91_mci_write(host, ATMEL_PDC_TNPR, 0); at91_mci_write(host, ATMEL_PDC_TNCR, 0); ier = AT91_MCI_CMDRDY; } else { /* zero block length and PDC mode */ mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff; mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0; mr |= (block_length << 16); mr |= AT91_MCI_PDCMODE; at91_mci_write(host, AT91_MCI_MR, mr); if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261())) at91_mci_write(host, AT91_MCI_BLKR, AT91_MCI_BLKR_BCNT(blocks) | AT91_MCI_BLKR_BLKLEN(block_length)); /* * Disable the PDC controller */ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS); if (cmdr & AT91_MCI_TRCMD_START) { data->bytes_xfered = 0; host->transfer_index = 0; host->in_use_index = 0; if (cmdr & AT91_MCI_TRDIR) { /* * Handle a read */ host->total_length = 0; at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address); at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? (blocks * block_length) : (blocks * block_length) / 4); at91_mci_write(host, ATMEL_PDC_RNPR, 0); at91_mci_write(host, ATMEL_PDC_RNCR, 0); ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */; } else { /* * Handle a write */ host->total_length = block_length * blocks; /* * MCI1 rev2xx Data Write Operation and * number of bytes erratum */ if (at91mci_is_mci1rev2xx()) if (host->total_length < 12) host->total_length = 12; at91_mci_sg_to_dma(host, data); pr_debug("Transmitting %d bytes\n", host->total_length); at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ? host->total_length : host->total_length / 4); ier = AT91_MCI_CMDRDY; } } } /* * Send the command and then enable the PDC - not the other way round as * the data sheet says */ at91_mci_write(host, AT91_MCI_ARGR, cmd->arg); at91_mci_write(host, AT91_MCI_CMDR, cmdr); if (cmdr & AT91_MCI_TRCMD_START) { if (cmdr & AT91_MCI_TRDIR) at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN); } /* Enable selected interrupts */ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier); }