aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/coh901318.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/dma/coh901318.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/dma/coh901318.c')
-rw-r--r--drivers/dma/coh901318.c136
1 files changed, 93 insertions, 43 deletions
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index aa384e53b7a..4234f416ef1 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -24,7 +24,6 @@
24#include <mach/coh901318.h> 24#include <mach/coh901318.h>
25 25
26#include "coh901318_lli.h" 26#include "coh901318_lli.h"
27#include "dmaengine.h"
28 27
29#define COHC_2_DEV(cohc) (&cohc->chan.dev->device) 28#define COHC_2_DEV(cohc) (&cohc->chan.dev->device)
30 29
@@ -40,7 +39,7 @@ struct coh901318_desc {
40 struct scatterlist *sg; 39 struct scatterlist *sg;
41 unsigned int sg_len; 40 unsigned int sg_len;
42 struct coh901318_lli *lli; 41 struct coh901318_lli *lli;
43 enum dma_transfer_direction dir; 42 enum dma_data_direction dir;
44 unsigned long flags; 43 unsigned long flags;
45 u32 head_config; 44 u32 head_config;
46 u32 head_ctrl; 45 u32 head_ctrl;
@@ -60,6 +59,7 @@ struct coh901318_base {
60struct coh901318_chan { 59struct coh901318_chan {
61 spinlock_t lock; 60 spinlock_t lock;
62 int allocated; 61 int allocated;
62 int completed;
63 int id; 63 int id;
64 int stopped; 64 int stopped;
65 65
@@ -104,6 +104,13 @@ static void coh901318_list_print(struct coh901318_chan *cohc,
104static struct coh901318_base *debugfs_dma_base; 104static struct coh901318_base *debugfs_dma_base;
105static struct dentry *dma_dentry; 105static struct dentry *dma_dentry;
106 106
107static int coh901318_debugfs_open(struct inode *inode, struct file *file)
108{
109
110 file->private_data = inode->i_private;
111 return 0;
112}
113
107static int coh901318_debugfs_read(struct file *file, char __user *buf, 114static int coh901318_debugfs_read(struct file *file, char __user *buf,
108 size_t count, loff_t *f_pos) 115 size_t count, loff_t *f_pos)
109{ 116{
@@ -151,7 +158,7 @@ static int coh901318_debugfs_read(struct file *file, char __user *buf,
151 158
152static const struct file_operations coh901318_debugfs_status_operations = { 159static const struct file_operations coh901318_debugfs_status_operations = {
153 .owner = THIS_MODULE, 160 .owner = THIS_MODULE,
154 .open = simple_open, 161 .open = coh901318_debugfs_open,
155 .read = coh901318_debugfs_read, 162 .read = coh901318_debugfs_read,
156 .llseek = default_llseek, 163 .llseek = default_llseek,
157}; 164};
@@ -311,6 +318,20 @@ static int coh901318_prep_linked_list(struct coh901318_chan *cohc,
311 318
312 return 0; 319 return 0;
313} 320}
321static dma_cookie_t
322coh901318_assign_cookie(struct coh901318_chan *cohc,
323 struct coh901318_desc *cohd)
324{
325 dma_cookie_t cookie = cohc->chan.cookie;
326
327 if (++cookie < 0)
328 cookie = 1;
329
330 cohc->chan.cookie = cookie;
331 cohd->desc.cookie = cookie;
332
333 return cookie;
334}
314 335
315static struct coh901318_desc * 336static struct coh901318_desc *
316coh901318_desc_get(struct coh901318_chan *cohc) 337coh901318_desc_get(struct coh901318_chan *cohc)
@@ -684,7 +705,7 @@ static void dma_tasklet(unsigned long data)
684 callback_param = cohd_fin->desc.callback_param; 705 callback_param = cohd_fin->desc.callback_param;
685 706
686 /* sign this job as completed on the channel */ 707 /* sign this job as completed on the channel */
687 dma_cookie_complete(&cohd_fin->desc); 708 cohc->completed = cohd_fin->desc.cookie;
688 709
689 /* release the lli allocation and remove the descriptor */ 710 /* release the lli allocation and remove the descriptor */
690 coh901318_lli_free(&cohc->base->pool, &cohd_fin->lli); 711 coh901318_lli_free(&cohc->base->pool, &cohd_fin->lli);
@@ -908,7 +929,7 @@ static int coh901318_alloc_chan_resources(struct dma_chan *chan)
908 coh901318_config(cohc, NULL); 929 coh901318_config(cohc, NULL);
909 930
910 cohc->allocated = 1; 931 cohc->allocated = 1;
911 dma_cookie_init(chan); 932 cohc->completed = chan->cookie = 1;
912 933
913 spin_unlock_irqrestore(&cohc->lock, flags); 934 spin_unlock_irqrestore(&cohc->lock, flags);
914 935
@@ -945,16 +966,16 @@ coh901318_tx_submit(struct dma_async_tx_descriptor *tx)
945 desc); 966 desc);
946 struct coh901318_chan *cohc = to_coh901318_chan(tx->chan); 967 struct coh901318_chan *cohc = to_coh901318_chan(tx->chan);
947 unsigned long flags; 968 unsigned long flags;
948 dma_cookie_t cookie;
949 969
950 spin_lock_irqsave(&cohc->lock, flags); 970 spin_lock_irqsave(&cohc->lock, flags);
951 cookie = dma_cookie_assign(tx); 971
972 tx->cookie = coh901318_assign_cookie(cohc, cohd);
952 973
953 coh901318_desc_queue(cohc, cohd); 974 coh901318_desc_queue(cohc, cohd);
954 975
955 spin_unlock_irqrestore(&cohc->lock, flags); 976 spin_unlock_irqrestore(&cohc->lock, flags);
956 977
957 return cookie; 978 return tx->cookie;
958} 979}
959 980
960static struct dma_async_tx_descriptor * 981static struct dma_async_tx_descriptor *
@@ -1013,8 +1034,8 @@ coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
1013 1034
1014static struct dma_async_tx_descriptor * 1035static struct dma_async_tx_descriptor *
1015coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, 1036coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
1016 unsigned int sg_len, enum dma_transfer_direction direction, 1037 unsigned int sg_len, enum dma_data_direction direction,
1017 unsigned long flags, void *context) 1038 unsigned long flags)
1018{ 1039{
1019 struct coh901318_chan *cohc = to_coh901318_chan(chan); 1040 struct coh901318_chan *cohc = to_coh901318_chan(chan);
1020 struct coh901318_lli *lli; 1041 struct coh901318_lli *lli;
@@ -1033,7 +1054,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
1033 1054
1034 if (!sgl) 1055 if (!sgl)
1035 goto out; 1056 goto out;
1036 if (sg_dma_len(sgl) == 0) 1057 if (sgl->length == 0)
1037 goto out; 1058 goto out;
1038 1059
1039 spin_lock_irqsave(&cohc->lock, flg); 1060 spin_lock_irqsave(&cohc->lock, flg);
@@ -1056,7 +1077,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
1056 ctrl_last |= cohc->runtime_ctrl; 1077 ctrl_last |= cohc->runtime_ctrl;
1057 ctrl |= cohc->runtime_ctrl; 1078 ctrl |= cohc->runtime_ctrl;
1058 1079
1059 if (direction == DMA_MEM_TO_DEV) { 1080 if (direction == DMA_TO_DEVICE) {
1060 u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE | 1081 u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE |
1061 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE; 1082 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE;
1062 1083
@@ -1064,7 +1085,7 @@ coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
1064 ctrl_chained |= tx_flags; 1085 ctrl_chained |= tx_flags;
1065 ctrl_last |= tx_flags; 1086 ctrl_last |= tx_flags;
1066 ctrl |= tx_flags; 1087 ctrl |= tx_flags;
1067 } else if (direction == DMA_DEV_TO_MEM) { 1088 } else if (direction == DMA_FROM_DEVICE) {
1068 u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST | 1089 u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST |
1069 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE; 1090 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE;
1070 1091
@@ -1144,12 +1165,17 @@ coh901318_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
1144 struct dma_tx_state *txstate) 1165 struct dma_tx_state *txstate)
1145{ 1166{
1146 struct coh901318_chan *cohc = to_coh901318_chan(chan); 1167 struct coh901318_chan *cohc = to_coh901318_chan(chan);
1147 enum dma_status ret; 1168 dma_cookie_t last_used;
1169 dma_cookie_t last_complete;
1170 int ret;
1148 1171
1149 ret = dma_cookie_status(chan, cookie, txstate); 1172 last_complete = cohc->completed;
1150 /* FIXME: should be conditional on ret != DMA_SUCCESS? */ 1173 last_used = chan->cookie;
1151 dma_set_residue(txstate, coh901318_get_bytes_left(chan));
1152 1174
1175 ret = dma_async_is_complete(cookie, last_complete, last_used);
1176
1177 dma_set_tx_state(txstate, last_complete, last_used,
1178 coh901318_get_bytes_left(chan));
1153 if (ret == DMA_IN_PROGRESS && cohc->stopped) 1179 if (ret == DMA_IN_PROGRESS && cohc->stopped)
1154 ret = DMA_PAUSED; 1180 ret = DMA_PAUSED;
1155 1181
@@ -1248,11 +1274,11 @@ static void coh901318_dma_set_runtimeconfig(struct dma_chan *chan,
1248 int i = 0; 1274 int i = 0;
1249 1275
1250 /* We only support mem to per or per to mem transfers */ 1276 /* We only support mem to per or per to mem transfers */
1251 if (config->direction == DMA_DEV_TO_MEM) { 1277 if (config->direction == DMA_FROM_DEVICE) {
1252 addr = config->src_addr; 1278 addr = config->src_addr;
1253 addr_width = config->src_addr_width; 1279 addr_width = config->src_addr_width;
1254 maxburst = config->src_maxburst; 1280 maxburst = config->src_maxburst;
1255 } else if (config->direction == DMA_MEM_TO_DEV) { 1281 } else if (config->direction == DMA_TO_DEVICE) {
1256 addr = config->dst_addr; 1282 addr = config->dst_addr;
1257 addr_width = config->dst_addr_width; 1283 addr_width = config->dst_addr_width;
1258 maxburst = config->dst_maxburst; 1284 maxburst = config->dst_maxburst;
@@ -1438,32 +1464,34 @@ static int __init coh901318_probe(struct platform_device *pdev)
1438 1464
1439 io = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1465 io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1440 if (!io) 1466 if (!io)
1441 return -ENODEV; 1467 goto err_get_resource;
1442 1468
1443 /* Map DMA controller registers to virtual memory */ 1469 /* Map DMA controller registers to virtual memory */
1444 if (devm_request_mem_region(&pdev->dev, 1470 if (request_mem_region(io->start,
1445 io->start, 1471 resource_size(io),
1446 resource_size(io), 1472 pdev->dev.driver->name) == NULL) {
1447 pdev->dev.driver->name) == NULL) 1473 err = -EBUSY;
1448 return -ENOMEM; 1474 goto err_request_mem;
1475 }
1449 1476
1450 pdata = pdev->dev.platform_data; 1477 pdata = pdev->dev.platform_data;
1451 if (!pdata) 1478 if (!pdata)
1452 return -ENODEV; 1479 goto err_no_platformdata;
1453 1480
1454 base = devm_kzalloc(&pdev->dev, 1481 base = kmalloc(ALIGN(sizeof(struct coh901318_base), 4) +
1455 ALIGN(sizeof(struct coh901318_base), 4) + 1482 pdata->max_channels *
1456 pdata->max_channels * 1483 sizeof(struct coh901318_chan),
1457 sizeof(struct coh901318_chan), 1484 GFP_KERNEL);
1458 GFP_KERNEL);
1459 if (!base) 1485 if (!base)
1460 return -ENOMEM; 1486 goto err_alloc_coh_dma_channels;
1461 1487
1462 base->chans = ((void *)base) + ALIGN(sizeof(struct coh901318_base), 4); 1488 base->chans = ((void *)base) + ALIGN(sizeof(struct coh901318_base), 4);
1463 1489
1464 base->virtbase = devm_ioremap(&pdev->dev, io->start, resource_size(io)); 1490 base->virtbase = ioremap(io->start, resource_size(io));
1465 if (!base->virtbase) 1491 if (!base->virtbase) {
1466 return -ENOMEM; 1492 err = -ENOMEM;
1493 goto err_no_ioremap;
1494 }
1467 1495
1468 base->dev = &pdev->dev; 1496 base->dev = &pdev->dev;
1469 base->platform = pdata; 1497 base->platform = pdata;
@@ -1472,20 +1500,25 @@ static int __init coh901318_probe(struct platform_device *pdev)
1472 1500
1473 COH901318_DEBUGFS_ASSIGN(debugfs_dma_base, base); 1501 COH901318_DEBUGFS_ASSIGN(debugfs_dma_base, base);
1474 1502
1503 platform_set_drvdata(pdev, base);
1504
1475 irq = platform_get_irq(pdev, 0); 1505 irq = platform_get_irq(pdev, 0);
1476 if (irq < 0) 1506 if (irq < 0)
1477 return irq; 1507 goto err_no_irq;
1478 1508
1479 err = devm_request_irq(&pdev->dev, irq, dma_irq_handler, IRQF_DISABLED, 1509 err = request_irq(irq, dma_irq_handler, IRQF_DISABLED,
1480 "coh901318", base); 1510 "coh901318", base);
1481 if (err) 1511 if (err) {
1482 return err; 1512 dev_crit(&pdev->dev,
1513 "Cannot allocate IRQ for DMA controller!\n");
1514 goto err_request_irq;
1515 }
1483 1516
1484 err = coh901318_pool_create(&base->pool, &pdev->dev, 1517 err = coh901318_pool_create(&base->pool, &pdev->dev,
1485 sizeof(struct coh901318_lli), 1518 sizeof(struct coh901318_lli),
1486 32); 1519 32);
1487 if (err) 1520 if (err)
1488 return err; 1521 goto err_pool_create;
1489 1522
1490 /* init channels for device transfers */ 1523 /* init channels for device transfers */
1491 coh901318_base_init(&base->dma_slave, base->platform->chans_slave, 1524 coh901318_base_init(&base->dma_slave, base->platform->chans_slave,
@@ -1531,7 +1564,6 @@ static int __init coh901318_probe(struct platform_device *pdev)
1531 if (err) 1564 if (err)
1532 goto err_register_memcpy; 1565 goto err_register_memcpy;
1533 1566
1534 platform_set_drvdata(pdev, base);
1535 dev_info(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n", 1567 dev_info(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n",
1536 (u32) base->virtbase); 1568 (u32) base->virtbase);
1537 1569
@@ -1541,6 +1573,19 @@ static int __init coh901318_probe(struct platform_device *pdev)
1541 dma_async_device_unregister(&base->dma_slave); 1573 dma_async_device_unregister(&base->dma_slave);
1542 err_register_slave: 1574 err_register_slave:
1543 coh901318_pool_destroy(&base->pool); 1575 coh901318_pool_destroy(&base->pool);
1576 err_pool_create:
1577 free_irq(platform_get_irq(pdev, 0), base);
1578 err_request_irq:
1579 err_no_irq:
1580 iounmap(base->virtbase);
1581 err_no_ioremap:
1582 kfree(base);
1583 err_alloc_coh_dma_channels:
1584 err_no_platformdata:
1585 release_mem_region(pdev->resource->start,
1586 resource_size(pdev->resource));
1587 err_request_mem:
1588 err_get_resource:
1544 return err; 1589 return err;
1545} 1590}
1546 1591
@@ -1551,6 +1596,11 @@ static int __exit coh901318_remove(struct platform_device *pdev)
1551 dma_async_device_unregister(&base->dma_memcpy); 1596 dma_async_device_unregister(&base->dma_memcpy);
1552 dma_async_device_unregister(&base->dma_slave); 1597 dma_async_device_unregister(&base->dma_slave);
1553 coh901318_pool_destroy(&base->pool); 1598 coh901318_pool_destroy(&base->pool);
1599 free_irq(platform_get_irq(pdev, 0), base);
1600 iounmap(base->virtbase);
1601 kfree(base);
1602 release_mem_region(pdev->resource->start,
1603 resource_size(pdev->resource));
1554 return 0; 1604 return 0;
1555} 1605}
1556 1606