Commit b0a59076 authored by Russell King's avatar Russell King

[MMC] Switch PXAMCI to use supplied scatterlist.

This converts the PXA MCI driver to use the supplied scatter list
rather than accessing the struct request directly, thereby making
this host driver independent of the block layer.

We also clean up the driver to use a consistent driver name for
resources.
parent f49bc65a
...@@ -44,6 +44,10 @@ ...@@ -44,6 +44,10 @@
#define DBG(x...) do { } while (0) #define DBG(x...) do { } while (0)
#endif #endif
#define DRIVER_NAME "pxa2xx-mci"
#define NR_SG 1
struct pxamci_host { struct pxamci_host {
struct mmc_host *mmc; struct mmc_host *mmc;
spinlock_t lock; spinlock_t lock;
...@@ -63,9 +67,8 @@ struct pxamci_host { ...@@ -63,9 +67,8 @@ struct pxamci_host {
dma_addr_t sg_dma; dma_addr_t sg_dma;
struct pxa_dma_desc *sg_cpu; struct pxa_dma_desc *sg_cpu;
unsigned int dma_len;
dma_addr_t dma_buf;
unsigned int dma_size;
unsigned int dma_dir; unsigned int dma_dir;
}; };
...@@ -122,10 +125,9 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask) ...@@ -122,10 +125,9 @@ static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
{ {
unsigned int nob = data->blocks; unsigned int nob = data->blocks;
unsigned int timeout, size; unsigned int timeout;
dma_addr_t dma;
u32 dcmd; u32 dcmd;
int i; int i, len;
host->data = data; host->data = data;
...@@ -152,35 +154,22 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) ...@@ -152,35 +154,22 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
dcmd |= DCMD_BURST32 | DCMD_WIDTH1; dcmd |= DCMD_BURST32 | DCMD_WIDTH1;
host->dma_size = data->blocks << data->blksz_bits; host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
host->dma_buf = dma_map_single(mmc_dev(host->mmc), data->req->buffer, host->dma_dir);
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) { if (data->flags & MMC_DATA_READ) {
host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO; host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO;
host->sg_cpu[i].dtadr = dma; host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]);
} else { } else {
host->sg_cpu[i].dsadr = dma; host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]);
host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO; host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO;
} }
host->sg_cpu[i].dcmd = dcmd | len; host->sg_cpu[i].dcmd = dcmd | sg_dma_len(&data->sg[i]);
host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
dma += len; sizeof(struct pxa_dma_desc);
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(); wmb();
DDADR(host->dma) = host->sg_dma; DDADR(host->dma) = host->sg_dma;
...@@ -276,8 +265,8 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) ...@@ -276,8 +265,8 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
return 0; return 0;
DCSR(host->dma) = 0; DCSR(host->dma) = 0;
dma_unmap_single(mmc_dev(host->mmc), host->dma_buf, host->dma_size, dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
host->dma_dir); host->dma_dir);
if (stat & STAT_READ_TIME_OUT) if (stat & STAT_READ_TIME_OUT)
data->error = MMC_ERR_TIMEOUT; data->error = MMC_ERR_TIMEOUT;
...@@ -429,7 +418,7 @@ static int pxamci_probe(struct device *dev) ...@@ -429,7 +418,7 @@ static int pxamci_probe(struct device *dev)
if (!r || irq == NO_IRQ) if (!r || irq == NO_IRQ)
return -ENXIO; return -ENXIO;
r = request_mem_region(r->start, SZ_4K, "PXAMCI"); r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);
if (!r) if (!r)
return -EBUSY; return -EBUSY;
...@@ -443,6 +432,17 @@ static int pxamci_probe(struct device *dev) ...@@ -443,6 +432,17 @@ static int pxamci_probe(struct device *dev)
mmc->f_min = 312500; mmc->f_min = 312500;
mmc->f_max = 20000000; mmc->f_max = 20000000;
/*
* 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;
host = mmc_priv(mmc); host = mmc_priv(mmc);
host->mmc = mmc; host->mmc = mmc;
host->dma = -1; host->dma = -1;
...@@ -482,13 +482,14 @@ static int pxamci_probe(struct device *dev) ...@@ -482,13 +482,14 @@ static int pxamci_probe(struct device *dev)
pxa_gpio_mode(GPIO8_MMCCS0_MD); pxa_gpio_mode(GPIO8_MMCCS0_MD);
pxa_set_cken(CKEN12_MMC, 1); pxa_set_cken(CKEN12_MMC, 1);
host->dma = pxa_request_dma("PXAMCI", DMA_PRIO_LOW, pxamci_dma_irq, host); host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW,
pxamci_dma_irq, host);
if (host->dma < 0) { if (host->dma < 0) {
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
ret = request_irq(host->irq, pxamci_irq, 0, "PXAMCI", host); ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);
if (ret) if (ret)
goto out; goto out;
...@@ -579,7 +580,7 @@ static int pxamci_resume(struct device *dev, u32 level) ...@@ -579,7 +580,7 @@ static int pxamci_resume(struct device *dev, u32 level)
#endif #endif
static struct device_driver pxamci_driver = { static struct device_driver pxamci_driver = {
.name = "pxa2xx-mci", .name = DRIVER_NAME,
.bus = &platform_bus_type, .bus = &platform_bus_type,
.probe = pxamci_probe, .probe = pxamci_probe,
.remove = pxamci_remove, .remove = pxamci_remove,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment