#define DBG(x...) do { } while (0)
#endif
-#define DRIVER_NAME "pxa2xx-mci"
-
-#define NR_SG 1
-
struct pxamci_host {
struct mmc_host *mmc;
spinlock_t lock;
dma_addr_t sg_dma;
struct pxa_dma_desc *sg_cpu;
- unsigned int dma_len;
+ dma_addr_t dma_buf;
+ unsigned int dma_size;
unsigned int dma_dir;
};
+/*
+ * The base MMC clock rate
+ */
+#define CLOCKRATE 20000000
+
static inline unsigned int ns_to_clocks(unsigned int ns)
{
return (ns * (CLOCKRATE / 1000000) + 999) / 1000;
static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
{
unsigned int nob = data->blocks;
- unsigned int timeout;
+ unsigned int timeout, size;
+ dma_addr_t dma;
u32 dcmd;
int i;
dcmd |= DCMD_BURST32 | DCMD_WIDTH1;
- host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- host->dma_dir);
+ host->dma_size = data->blocks << data->blksz_bits;
+ host->dma_buf = dma_map_single(mmc_dev(host->mmc), data->req->buffer,
+ host->dma_size, host->dma_dir);
+
+ for (i = 0, size = host->dma_size, dma = host->dma_buf; size; i++) {
+ u32 len = size;
+
+ if (len > DCMD_LENGTH)
+ len = 0x1000;
- for (i = 0; i < host->dma_len; i++) {
if (data->flags & MMC_DATA_READ) {
host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO;
- host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]);
+ host->sg_cpu[i].dtadr = dma;
} else {
- host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]);
+ host->sg_cpu[i].dsadr = dma;
host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO;
}
- host->sg_cpu[i].dcmd = dcmd | sg_dma_len(&data->sg[i]);
- host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
- sizeof(struct pxa_dma_desc);
+ host->sg_cpu[i].dcmd = dcmd | len;
+
+ dma += len;
+ size -= len;
+
+ if (size) {
+ host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
+ sizeof(struct pxa_dma_desc);
+ } else {
+ host->sg_cpu[i].ddadr = DDADR_STOP;
+ }
}
- host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP;
wmb();
DDADR(host->dma) = host->sg_dma;
if (stat & STAT_TIME_OUT_RESPONSE) {
cmd->error = MMC_ERR_TIMEOUT;
} else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
-#ifdef CONFIG_PXA27x
- /*
- * workaround for erratum #42:
- * Intel PXA27x Family Processor Specification Update Rev 001
- */
- if (cmd->opcode == MMC_ALL_SEND_CID ||
- cmd->opcode == MMC_SEND_CSD ||
- cmd->opcode == MMC_SEND_CID) {
- /* a bogus CRC error can appear if the msb of
- the 15 byte response is a one */
- if ((cmd->resp[0] & 0x80000000) == 0)
- cmd->error = MMC_ERR_BADCRC;
- } else {
- DBG("ignoring CRC from command %d - *risky*\n",cmd->opcode);
- }
-#else
cmd->error = MMC_ERR_BADCRC;
-#endif
}
pxamci_disable_irq(host, END_CMD_RES);
return 0;
DCSR(host->dma) = 0;
- dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
- host->dma_dir);
+ dma_unmap_single(mmc_dev(host->mmc), host->dma_buf, host->dma_size,
+ host->dma_dir);
if (stat & STAT_READ_TIME_OUT)
data->error = MMC_ERR_TIMEOUT;
if (CLOCKRATE / clk > ios->clock)
clk <<= 1;
host->clkrt = fls(clk) - 1;
- pxa_set_cken(CKEN12_MMC, 1);
/*
* we write clkrt on the next command
*/
- } else {
- pxamci_stop_clock(host);
- pxa_set_cken(CKEN12_MMC, 0);
+ } else if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
+ /*
+ * Ensure that the clock is off.
+ */
+ writel(STOP_CLOCK, host->base + MMC_STRPCL);
}
if (host->power_mode != ios->power_mode) {
if (!r || irq == NO_IRQ)
return -ENXIO;
- r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);
+ r = request_mem_region(r->start, SZ_4K, "PXAMCI");
if (!r)
return -EBUSY;
}
mmc->ops = &pxamci_ops;
- mmc->f_min = CLOCKRATE_MIN;
- mmc->f_max = CLOCKRATE_MAX;
-
- /*
- * We can do SG-DMA, but we don't because we never know how much
- * data we successfully wrote to the card.
- */
- mmc->max_phys_segs = NR_SG;
-
- /*
- * Our hardware DMA can handle a maximum of one page per SG entry.
- */
- mmc->max_seg_size = PAGE_SIZE;
+ mmc->f_min = 312500;
+ mmc->f_max = 20000000;
host = mmc_priv(mmc);
host->mmc = mmc;
spin_lock_init(&host->lock);
host->res = r;
host->irq = irq;
- host->imask = MMC_I_MASK_ALL;
+ host->imask = TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|
+ END_CMD_RES|PRG_DONE|DATA_TRAN_DONE;
host->base = ioremap(r->start, SZ_4K);
if (!host->base) {
writel(64, host->base + MMC_RESTO);
writel(host->imask, host->base + MMC_I_MASK);
- host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW,
- pxamci_dma_irq, host);
+ pxa_gpio_mode(GPIO6_MMCCLK_MD);
+ pxa_gpio_mode(GPIO8_MMCCS0_MD);
+ pxa_set_cken(CKEN12_MMC, 1);
+
+ host->dma = pxa_request_dma("PXAMCI", DMA_PRIO_LOW, pxamci_dma_irq, host);
if (host->dma < 0) {
ret = -EBUSY;
goto out;
}
- ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);
+ ret = request_irq(host->irq, pxamci_irq, 0, "PXAMCI", host);
if (ret)
goto out;
END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,
host->base + MMC_I_MASK);
- DRCMRRXMMC = 0;
- DRCMRTXMMC = 0;
+ pxa_set_cken(CKEN12_MMC, 0);
free_irq(host->irq, host);
pxa_free_dma(host->dma);
iounmap(host->base);
dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+ pxa_set_cken(CKEN12_MMC, 0);
+
release_resource(host->res);
mmc_free_host(mmc);
#endif
static struct device_driver pxamci_driver = {
- .name = DRIVER_NAME,
+ .name = "pxa2xx-mci",
.bus = &platform_bus_type,
.probe = pxamci_probe,
.remove = pxamci_remove,