aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2012-04-21 17:35:42 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-07-31 07:06:23 -0400
commit3451c06754b5777d227aa99f85c35bdfabac3ca0 (patch)
treec2767908557ff53952c0b85cb5191a8214965c9e /drivers/mmc/host
parent26b88520b80695a6fa5fd95b5d97c03f4daf87e0 (diff)
mmc: omap: add DMA engine support
Add DMA engine support to the OMAP driver. This supplements the private DMA API implementation contained within this driver, and the driver can be switched at build time between using DMA engine and the private DMA API. Tested-by: Tony Lindgren <tony@atomide.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/omap.c199
-rw-r--r--drivers/mmc/host/omap_hsmmc.c3
2 files changed, 190 insertions, 12 deletions
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 3e8dcf8d2e05..25e7efee5733 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -17,10 +17,12 @@
17#include <linux/ioport.h> 17#include <linux/ioport.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/dmaengine.h>
20#include <linux/dma-mapping.h> 21#include <linux/dma-mapping.h>
21#include <linux/delay.h> 22#include <linux/delay.h>
22#include <linux/spinlock.h> 23#include <linux/spinlock.h>
23#include <linux/timer.h> 24#include <linux/timer.h>
25#include <linux/omap-dma.h>
24#include <linux/mmc/host.h> 26#include <linux/mmc/host.h>
25#include <linux/mmc/card.h> 27#include <linux/mmc/card.h>
26#include <linux/clk.h> 28#include <linux/clk.h>
@@ -99,6 +101,8 @@
99 101
100struct mmc_omap_host; 102struct mmc_omap_host;
101 103
104#define USE_DMA_PRIVATE
105
102struct mmc_omap_slot { 106struct mmc_omap_slot {
103 int id; 107 int id;
104 unsigned int vdd; 108 unsigned int vdd;
@@ -128,6 +132,10 @@ struct mmc_omap_host {
128 unsigned char id; /* 16xx chips have 2 MMC blocks */ 132 unsigned char id; /* 16xx chips have 2 MMC blocks */
129 struct clk * iclk; 133 struct clk * iclk;
130 struct clk * fclk; 134 struct clk * fclk;
135 struct dma_chan *dma_rx;
136 u32 dma_rx_burst;
137 struct dma_chan *dma_tx;
138 u32 dma_tx_burst;
131 struct resource *mem_res; 139 struct resource *mem_res;
132 void __iomem *virt_base; 140 void __iomem *virt_base;
133 unsigned int phys_base; 141 unsigned int phys_base;
@@ -153,12 +161,14 @@ struct mmc_omap_host {
153 161
154 unsigned use_dma:1; 162 unsigned use_dma:1;
155 unsigned brs_received:1, dma_done:1; 163 unsigned brs_received:1, dma_done:1;
156 unsigned dma_is_read:1;
157 unsigned dma_in_use:1; 164 unsigned dma_in_use:1;
165#ifdef USE_DMA_PRIVATE
166 unsigned dma_is_read:1;
158 int dma_ch; 167 int dma_ch;
159 spinlock_t dma_lock;
160 struct timer_list dma_timer; 168 struct timer_list dma_timer;
161 unsigned dma_len; 169 unsigned dma_len;
170#endif
171 spinlock_t dma_lock;
162 172
163 struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS]; 173 struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS];
164 struct mmc_omap_slot *current_slot; 174 struct mmc_omap_slot *current_slot;
@@ -406,18 +416,32 @@ mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data,
406 int abort) 416 int abort)
407{ 417{
408 enum dma_data_direction dma_data_dir; 418 enum dma_data_direction dma_data_dir;
419 struct device *dev = mmc_dev(host->mmc);
420 struct dma_chan *c;
409 421
422#ifdef USE_DMA_PRIVATE
410 BUG_ON(host->dma_ch < 0); 423 BUG_ON(host->dma_ch < 0);
411 if (data->error) 424 if (data->error)
412 omap_stop_dma(host->dma_ch); 425 omap_stop_dma(host->dma_ch);
413 /* Release DMA channel lazily */ 426 /* Release DMA channel lazily */
414 mod_timer(&host->dma_timer, jiffies + HZ); 427 mod_timer(&host->dma_timer, jiffies + HZ);
415 if (data->flags & MMC_DATA_WRITE) 428#endif
429 if (data->flags & MMC_DATA_WRITE) {
416 dma_data_dir = DMA_TO_DEVICE; 430 dma_data_dir = DMA_TO_DEVICE;
417 else 431 c = host->dma_tx;
432 } else {
418 dma_data_dir = DMA_FROM_DEVICE; 433 dma_data_dir = DMA_FROM_DEVICE;
419 dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len, 434 c = host->dma_rx;
420 dma_data_dir); 435 }
436 if (c) {
437 if (data->error) {
438 dmaengine_terminate_all(c);
439 /* Claim nothing transferred on error... */
440 data->bytes_xfered = 0;
441 }
442 dev = c->device->dev;
443 }
444 dma_unmap_sg(dev, data->sg, host->sg_len, dma_data_dir);
421} 445}
422 446
423static void mmc_omap_send_stop_work(struct work_struct *work) 447static void mmc_omap_send_stop_work(struct work_struct *work)
@@ -524,6 +548,7 @@ mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data)
524 mmc_omap_xfer_done(host, data); 548 mmc_omap_xfer_done(host, data);
525} 549}
526 550
551#ifdef USE_DMA_PRIVATE
527static void 552static void
528mmc_omap_dma_timer(unsigned long data) 553mmc_omap_dma_timer(unsigned long data)
529{ 554{
@@ -533,6 +558,7 @@ mmc_omap_dma_timer(unsigned long data)
533 omap_free_dma(host->dma_ch); 558 omap_free_dma(host->dma_ch);
534 host->dma_ch = -1; 559 host->dma_ch = -1;
535} 560}
561#endif
536 562
537static void 563static void
538mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data) 564mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data)
@@ -891,6 +917,18 @@ static void mmc_omap_cover_handler(unsigned long param)
891 jiffies + msecs_to_jiffies(OMAP_MMC_COVER_POLL_DELAY)); 917 jiffies + msecs_to_jiffies(OMAP_MMC_COVER_POLL_DELAY));
892} 918}
893 919
920static void mmc_omap_dma_callback(void *priv)
921{
922 struct mmc_omap_host *host = priv;
923 struct mmc_data *data = host->data;
924
925 /* If we got to the end of DMA, assume everything went well */
926 data->bytes_xfered += data->blocks * data->blksz;
927
928 mmc_omap_dma_done(host, data);
929}
930
931#ifdef USE_DMA_PRIVATE
894/* Prepare to transfer the next segment of a scatterlist */ 932/* Prepare to transfer the next segment of a scatterlist */
895static void 933static void
896mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) 934mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data)
@@ -1045,6 +1083,7 @@ static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data
1045 1083
1046 return 0; 1084 return 0;
1047} 1085}
1086#endif
1048 1087
1049static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req) 1088static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req)
1050{ 1089{
@@ -1118,6 +1157,80 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
1118 1157
1119 host->sg_idx = 0; 1158 host->sg_idx = 0;
1120 if (use_dma) { 1159 if (use_dma) {
1160 enum dma_data_direction dma_data_dir;
1161 struct dma_async_tx_descriptor *tx;
1162 struct dma_chan *c;
1163 u32 burst, *bp;
1164 u16 buf;
1165
1166 /*
1167 * FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx
1168 * and 24xx. Use 16 or 32 word frames when the
1169 * blocksize is at least that large. Blocksize is
1170 * usually 512 bytes; but not for some SD reads.
1171 */
1172 burst = cpu_is_omap15xx() ? 32 : 64;
1173 if (burst > data->blksz)
1174 burst = data->blksz;
1175
1176 burst >>= 1;
1177
1178 if (data->flags & MMC_DATA_WRITE) {
1179 c = host->dma_tx;
1180 bp = &host->dma_tx_burst;
1181 buf = 0x0f80 | (burst - 1) << 0;
1182 dma_data_dir = DMA_TO_DEVICE;
1183 } else {
1184 c = host->dma_rx;
1185 bp = &host->dma_rx_burst;
1186 buf = 0x800f | (burst - 1) << 8;
1187 dma_data_dir = DMA_FROM_DEVICE;
1188 }
1189
1190 if (!c)
1191 goto use_pio;
1192
1193 /* Only reconfigure if we have a different burst size */
1194 if (*bp != burst) {
1195 struct dma_slave_config cfg;
1196
1197 cfg.src_addr = host->phys_base + OMAP_MMC_REG(host, DATA);
1198 cfg.dst_addr = host->phys_base + OMAP_MMC_REG(host, DATA);
1199 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
1200 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
1201 cfg.src_maxburst = burst;
1202 cfg.dst_maxburst = burst;
1203
1204 if (dmaengine_slave_config(c, &cfg))
1205 goto use_pio;
1206
1207 *bp = burst;
1208 }
1209
1210 host->sg_len = dma_map_sg(c->device->dev, data->sg, sg_len,
1211 dma_data_dir);
1212 if (host->sg_len == 0)
1213 goto use_pio;
1214
1215 tx = dmaengine_prep_slave_sg(c, data->sg, host->sg_len,
1216 data->flags & MMC_DATA_WRITE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
1217 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
1218 if (!tx)
1219 goto use_pio;
1220
1221 OMAP_MMC_WRITE(host, BUF, buf);
1222
1223 tx->callback = mmc_omap_dma_callback;
1224 tx->callback_param = host;
1225 dmaengine_submit(tx);
1226 host->brs_received = 0;
1227 host->dma_done = 0;
1228 host->dma_in_use = 1;
1229 return;
1230 }
1231 use_pio:
1232#ifdef USE_DMA_PRIVATE
1233 if (use_dma) {
1121 if (mmc_omap_get_dma_channel(host, data) == 0) { 1234 if (mmc_omap_get_dma_channel(host, data) == 0) {
1122 enum dma_data_direction dma_data_dir; 1235 enum dma_data_direction dma_data_dir;
1123 1236
@@ -1136,6 +1249,9 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
1136 } else 1249 } else
1137 use_dma = 0; 1250 use_dma = 0;
1138 } 1251 }
1252#else
1253 use_dma = 0;
1254#endif
1139 1255
1140 /* Revert to PIO? */ 1256 /* Revert to PIO? */
1141 if (!use_dma) { 1257 if (!use_dma) {
@@ -1157,8 +1273,17 @@ static void mmc_omap_start_request(struct mmc_omap_host *host,
1157 /* only touch fifo AFTER the controller readies it */ 1273 /* only touch fifo AFTER the controller readies it */
1158 mmc_omap_prepare_data(host, req); 1274 mmc_omap_prepare_data(host, req);
1159 mmc_omap_start_command(host, req->cmd); 1275 mmc_omap_start_command(host, req->cmd);
1160 if (host->dma_in_use) 1276 if (host->dma_in_use) {
1161 omap_start_dma(host->dma_ch); 1277 struct dma_chan *c = host->data->flags & MMC_DATA_WRITE ?
1278 host->dma_tx : host->dma_rx;
1279
1280 if (c)
1281 dma_async_issue_pending(c);
1282#ifdef USE_DMA_PRIVATE
1283 else
1284 omap_start_dma(host->dma_ch);
1285#endif
1286 }
1162} 1287}
1163 1288
1164static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req) 1289static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req)
@@ -1400,6 +1525,8 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
1400 struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; 1525 struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
1401 struct mmc_omap_host *host = NULL; 1526 struct mmc_omap_host *host = NULL;
1402 struct resource *res; 1527 struct resource *res;
1528 dma_cap_mask_t mask;
1529 unsigned sig;
1403 int i, ret = 0; 1530 int i, ret = 0;
1404 int irq; 1531 int irq;
1405 1532
@@ -1439,7 +1566,9 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
1439 setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host); 1566 setup_timer(&host->clk_timer, mmc_omap_clk_timer, (unsigned long) host);
1440 1567
1441 spin_lock_init(&host->dma_lock); 1568 spin_lock_init(&host->dma_lock);
1569#ifdef USE_DMA_PRIVATE
1442 setup_timer(&host->dma_timer, mmc_omap_dma_timer, (unsigned long) host); 1570 setup_timer(&host->dma_timer, mmc_omap_dma_timer, (unsigned long) host);
1571#endif
1443 spin_lock_init(&host->slot_lock); 1572 spin_lock_init(&host->slot_lock);
1444 init_waitqueue_head(&host->slot_wq); 1573 init_waitqueue_head(&host->slot_wq);
1445 1574
@@ -1452,8 +1581,10 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
1452 host->irq = irq; 1581 host->irq = irq;
1453 1582
1454 host->use_dma = 1; 1583 host->use_dma = 1;
1584#ifdef USE_DMA_PRIVATE
1455 host->dev->dma_mask = &pdata->dma_mask; 1585 host->dev->dma_mask = &pdata->dma_mask;
1456 host->dma_ch = -1; 1586 host->dma_ch = -1;
1587#endif
1457 1588
1458 host->irq = irq; 1589 host->irq = irq;
1459 host->phys_base = host->mem_res->start; 1590 host->phys_base = host->mem_res->start;
@@ -1474,9 +1605,48 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
1474 goto err_free_iclk; 1605 goto err_free_iclk;
1475 } 1606 }
1476 1607
1608 dma_cap_zero(mask);
1609 dma_cap_set(DMA_SLAVE, mask);
1610
1611 host->dma_tx_burst = -1;
1612 host->dma_rx_burst = -1;
1613
1614 if (cpu_is_omap24xx())
1615 sig = host->id == 0 ? OMAP24XX_DMA_MMC1_TX : OMAP24XX_DMA_MMC2_TX;
1616 else
1617 sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX;
1618 host->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
1619#if 0
1620 if (!host->dma_tx) {
1621 dev_err(host->dev, "unable to obtain TX DMA engine channel %u\n",
1622 sig);
1623 goto err_dma;
1624 }
1625#else
1626 if (!host->dma_tx)
1627 dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n",
1628 sig);
1629#endif
1630 if (cpu_is_omap24xx())
1631 sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX;
1632 else
1633 sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX;
1634 host->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
1635#if 0
1636 if (!host->dma_rx) {
1637 dev_err(host->dev, "unable to obtain RX DMA engine channel %u\n",
1638 sig);
1639 goto err_dma;
1640 }
1641#else
1642 if (!host->dma_rx)
1643 dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n",
1644 sig);
1645#endif
1646
1477 ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); 1647 ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
1478 if (ret) 1648 if (ret)
1479 goto err_free_fclk; 1649 goto err_free_dma;
1480 1650
1481 if (pdata->init != NULL) { 1651 if (pdata->init != NULL) {
1482 ret = pdata->init(&pdev->dev); 1652 ret = pdata->init(&pdev->dev);
@@ -1510,7 +1680,11 @@ err_plat_cleanup:
1510 pdata->cleanup(&pdev->dev); 1680 pdata->cleanup(&pdev->dev);
1511err_free_irq: 1681err_free_irq:
1512 free_irq(host->irq, host); 1682 free_irq(host->irq, host);
1513err_free_fclk: 1683err_free_dma:
1684 if (host->dma_tx)
1685 dma_release_channel(host->dma_tx);
1686 if (host->dma_rx)
1687 dma_release_channel(host->dma_rx);
1514 clk_put(host->fclk); 1688 clk_put(host->fclk);
1515err_free_iclk: 1689err_free_iclk:
1516 clk_disable(host->iclk); 1690 clk_disable(host->iclk);
@@ -1545,6 +1719,11 @@ static int __devexit mmc_omap_remove(struct platform_device *pdev)
1545 clk_disable(host->iclk); 1719 clk_disable(host->iclk);
1546 clk_put(host->iclk); 1720 clk_put(host->iclk);
1547 1721
1722 if (host->dma_tx)
1723 dma_release_channel(host->dma_tx);
1724 if (host->dma_rx)
1725 dma_release_channel(host->dma_rx);
1726
1548 iounmap(host->virt_base); 1727 iounmap(host->virt_base);
1549 release_mem_region(pdev->resource[0].start, 1728 release_mem_region(pdev->resource[0].start,
1550 pdev->resource[0].end - pdev->resource[0].start + 1); 1729 pdev->resource[0].end - pdev->resource[0].start + 1);
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 2b2c98773f15..2338703746a4 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -30,6 +30,7 @@
30#include <linux/of.h> 30#include <linux/of.h>
31#include <linux/of_gpio.h> 31#include <linux/of_gpio.h>
32#include <linux/of_device.h> 32#include <linux/of_device.h>
33#include <linux/omap-dma.h>
33#include <linux/mmc/host.h> 34#include <linux/mmc/host.h>
34#include <linux/mmc/core.h> 35#include <linux/mmc/core.h>
35#include <linux/mmc/mmc.h> 36#include <linux/mmc/mmc.h>
@@ -1766,8 +1767,6 @@ static inline struct omap_mmc_platform_data
1766} 1767}
1767#endif 1768#endif
1768 1769
1769extern bool omap_dma_filter_fn(struct dma_chan *chan, void *param);
1770
1771static int __devinit omap_hsmmc_probe(struct platform_device *pdev) 1770static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
1772{ 1771{
1773 struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; 1772 struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;