summaryrefslogtreecommitdiffstats
path: root/drivers/dma/pl330.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-29 23:27:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-29 23:27:23 -0500
commitca2a650f3dfdc30d71d21bcbb04d2d057779f3f9 (patch)
tree12e5f7f4dea5ba17cc82f2c633bbe9dbf725fb11 /drivers/dma/pl330.c
parente9e352e9100b98aed1a5fb9e33355c29fb07d5b1 (diff)
parent15cec530e4bc7bed3f51cde8404f96fd28a8c7c5 (diff)
Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma
Pull slave-dma updates from Vinod Koul: - new driver for BCM2835 used in R-pi - new driver for MOXA ART - dma_get_any_slave_channel API for DT based systems - minor fixes and updates spread acrooss driver [ The fsl-ssi dual fifo mode support addition clashed badly with the other changes to fsl-ssi that came in through the sound merge. I did a very rough cut at fixing up the conflict, but Nicolin Chen (author of both sides) will need to verify and check things ] * 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (36 commits) dmaengine: mmp_pdma: fix mismerge dma: pl08x: Export pl08x_filter_id acpi-dma: align documentation with kernel-doc format dma: fix vchan_cookie_complete() debug print DMA: dmatest: extend the "device" module parameter to 32 characters drivers/dma: fix error return code dma: omap: Set debug level to debugging messages dmaengine: fix kernel-doc style typos for few comments dma: tegra: add support for Tegra148/124 dma: dw: use %pad instead of casting dma_addr_t dma: dw: join split up messages dma: dw: fix style of multiline comment dmaengine: k3dma: fix sparse warnings dma: pl330: Use dma_get_slave_channel() in the of xlate callback dma: pl330: Differentiate between submitted and issued descriptors dmaengine: sirf: Add device_slave_caps interface DMA: Freescale: change BWC from 256 bytes to 1024 bytes dmaengine: Add MOXA ART DMA engine driver dmaengine: Add DMA_PRIVATE to BCM2835 driver dma: imx-sdma: Assign a default script number for ROM firmware cases ...
Diffstat (limited to 'drivers/dma/pl330.c')
-rw-r--r--drivers/dma/pl330.c65
1 files changed, 34 insertions, 31 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index c90edecee463..73fa9b7a10ab 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -543,7 +543,9 @@ struct dma_pl330_chan {
543 /* DMA-Engine Channel */ 543 /* DMA-Engine Channel */
544 struct dma_chan chan; 544 struct dma_chan chan;
545 545
546 /* List of to be xfered descriptors */ 546 /* List of submitted descriptors */
547 struct list_head submitted_list;
548 /* List of issued descriptors */
547 struct list_head work_list; 549 struct list_head work_list;
548 /* List of completed descriptors */ 550 /* List of completed descriptors */
549 struct list_head completed_list; 551 struct list_head completed_list;
@@ -578,12 +580,16 @@ struct dma_pl330_dmac {
578 /* DMA-Engine Device */ 580 /* DMA-Engine Device */
579 struct dma_device ddma; 581 struct dma_device ddma;
580 582
583 /* Holds info about sg limitations */
584 struct device_dma_parameters dma_parms;
585
581 /* Pool of descriptors available for the DMAC's channels */ 586 /* Pool of descriptors available for the DMAC's channels */
582 struct list_head desc_pool; 587 struct list_head desc_pool;
583 /* To protect desc_pool manipulation */ 588 /* To protect desc_pool manipulation */
584 spinlock_t pool_lock; 589 spinlock_t pool_lock;
585 590
586 /* Peripheral channels connected to this DMAC */ 591 /* Peripheral channels connected to this DMAC */
592 unsigned int num_peripherals;
587 struct dma_pl330_chan *peripherals; /* keep at end */ 593 struct dma_pl330_chan *peripherals; /* keep at end */
588}; 594};
589 595
@@ -606,11 +612,6 @@ struct dma_pl330_desc {
606 struct dma_pl330_chan *pchan; 612 struct dma_pl330_chan *pchan;
607}; 613};
608 614
609struct dma_pl330_filter_args {
610 struct dma_pl330_dmac *pdmac;
611 unsigned int chan_id;
612};
613
614static inline void _callback(struct pl330_req *r, enum pl330_op_err err) 615static inline void _callback(struct pl330_req *r, enum pl330_op_err err)
615{ 616{
616 if (r && r->xfer_cb) 617 if (r && r->xfer_cb)
@@ -2298,16 +2299,6 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
2298 tasklet_schedule(&pch->task); 2299 tasklet_schedule(&pch->task);
2299} 2300}
2300 2301
2301static bool pl330_dt_filter(struct dma_chan *chan, void *param)
2302{
2303 struct dma_pl330_filter_args *fargs = param;
2304
2305 if (chan->device != &fargs->pdmac->ddma)
2306 return false;
2307
2308 return (chan->chan_id == fargs->chan_id);
2309}
2310
2311bool pl330_filter(struct dma_chan *chan, void *param) 2302bool pl330_filter(struct dma_chan *chan, void *param)
2312{ 2303{
2313 u8 *peri_id; 2304 u8 *peri_id;
@@ -2325,23 +2316,16 @@ static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec,
2325{ 2316{
2326 int count = dma_spec->args_count; 2317 int count = dma_spec->args_count;
2327 struct dma_pl330_dmac *pdmac = ofdma->of_dma_data; 2318 struct dma_pl330_dmac *pdmac = ofdma->of_dma_data;
2328 struct dma_pl330_filter_args fargs; 2319 unsigned int chan_id;
2329 dma_cap_mask_t cap;
2330
2331 if (!pdmac)
2332 return NULL;
2333 2320
2334 if (count != 1) 2321 if (count != 1)
2335 return NULL; 2322 return NULL;
2336 2323
2337 fargs.pdmac = pdmac; 2324 chan_id = dma_spec->args[0];
2338 fargs.chan_id = dma_spec->args[0]; 2325 if (chan_id >= pdmac->num_peripherals)
2339 2326 return NULL;
2340 dma_cap_zero(cap);
2341 dma_cap_set(DMA_SLAVE, cap);
2342 dma_cap_set(DMA_CYCLIC, cap);
2343 2327
2344 return dma_request_channel(cap, pl330_dt_filter, &fargs); 2328 return dma_get_slave_channel(&pdmac->peripherals[chan_id].chan);
2345} 2329}
2346 2330
2347static int pl330_alloc_chan_resources(struct dma_chan *chan) 2331static int pl330_alloc_chan_resources(struct dma_chan *chan)
@@ -2385,6 +2369,11 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
2385 pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH); 2369 pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
2386 2370
2387 /* Mark all desc done */ 2371 /* Mark all desc done */
2372 list_for_each_entry(desc, &pch->submitted_list, node) {
2373 desc->status = FREE;
2374 dma_cookie_complete(&desc->txd);
2375 }
2376
2388 list_for_each_entry(desc, &pch->work_list , node) { 2377 list_for_each_entry(desc, &pch->work_list , node) {
2389 desc->status = FREE; 2378 desc->status = FREE;
2390 dma_cookie_complete(&desc->txd); 2379 dma_cookie_complete(&desc->txd);
@@ -2395,6 +2384,7 @@ static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned
2395 dma_cookie_complete(&desc->txd); 2384 dma_cookie_complete(&desc->txd);
2396 } 2385 }
2397 2386
2387 list_splice_tail_init(&pch->submitted_list, &pdmac->desc_pool);
2398 list_splice_tail_init(&pch->work_list, &pdmac->desc_pool); 2388 list_splice_tail_init(&pch->work_list, &pdmac->desc_pool);
2399 list_splice_tail_init(&pch->completed_list, &pdmac->desc_pool); 2389 list_splice_tail_init(&pch->completed_list, &pdmac->desc_pool);
2400 spin_unlock_irqrestore(&pch->lock, flags); 2390 spin_unlock_irqrestore(&pch->lock, flags);
@@ -2453,7 +2443,14 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
2453 2443
2454static void pl330_issue_pending(struct dma_chan *chan) 2444static void pl330_issue_pending(struct dma_chan *chan)
2455{ 2445{
2456 pl330_tasklet((unsigned long) to_pchan(chan)); 2446 struct dma_pl330_chan *pch = to_pchan(chan);
2447 unsigned long flags;
2448
2449 spin_lock_irqsave(&pch->lock, flags);
2450 list_splice_tail_init(&pch->submitted_list, &pch->work_list);
2451 spin_unlock_irqrestore(&pch->lock, flags);
2452
2453 pl330_tasklet((unsigned long)pch);
2457} 2454}
2458 2455
2459/* 2456/*
@@ -2480,11 +2477,11 @@ static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx)
2480 2477
2481 dma_cookie_assign(&desc->txd); 2478 dma_cookie_assign(&desc->txd);
2482 2479
2483 list_move_tail(&desc->node, &pch->work_list); 2480 list_move_tail(&desc->node, &pch->submitted_list);
2484 } 2481 }
2485 2482
2486 cookie = dma_cookie_assign(&last->txd); 2483 cookie = dma_cookie_assign(&last->txd);
2487 list_add_tail(&last->node, &pch->work_list); 2484 list_add_tail(&last->node, &pch->submitted_list);
2488 spin_unlock_irqrestore(&pch->lock, flags); 2485 spin_unlock_irqrestore(&pch->lock, flags);
2489 2486
2490 return cookie; 2487 return cookie;
@@ -2960,6 +2957,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2960 else 2957 else
2961 num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan); 2958 num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan);
2962 2959
2960 pdmac->num_peripherals = num_chan;
2961
2963 pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); 2962 pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
2964 if (!pdmac->peripherals) { 2963 if (!pdmac->peripherals) {
2965 ret = -ENOMEM; 2964 ret = -ENOMEM;
@@ -2974,6 +2973,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
2974 else 2973 else
2975 pch->chan.private = adev->dev.of_node; 2974 pch->chan.private = adev->dev.of_node;
2976 2975
2976 INIT_LIST_HEAD(&pch->submitted_list);
2977 INIT_LIST_HEAD(&pch->work_list); 2977 INIT_LIST_HEAD(&pch->work_list);
2978 INIT_LIST_HEAD(&pch->completed_list); 2978 INIT_LIST_HEAD(&pch->completed_list);
2979 spin_lock_init(&pch->lock); 2979 spin_lock_init(&pch->lock);
@@ -3021,6 +3021,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
3021 "unable to register DMA to the generic DT DMA helpers\n"); 3021 "unable to register DMA to the generic DT DMA helpers\n");
3022 } 3022 }
3023 } 3023 }
3024
3025 adev->dev.dma_parms = &pdmac->dma_parms;
3026
3024 /* 3027 /*
3025 * This is the limit for transfers with a buswidth of 1, larger 3028 * This is the limit for transfers with a buswidth of 1, larger
3026 * buswidths will have larger limits. 3029 * buswidths will have larger limits.