summaryrefslogtreecommitdiffstats
path: root/drivers/dma/edma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/edma.c')
-rw-r--r--drivers/dma/edma.c79
1 files changed, 43 insertions, 36 deletions
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index fcb4680efed7..53d48b2a700d 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -119,6 +119,7 @@ struct edma_chan {
};
struct edma_cc {
+ struct edma *cc;
int ctlr;
struct dma_device dma_slave;
struct edma_chan slave_chans[EDMA_CHANS];
@@ -150,6 +151,7 @@ static void edma_desc_free(struct virt_dma_desc *vdesc)
/* Dispatch a queued descriptor to the controller (caller holds lock) */
static void edma_execute(struct edma_chan *echan)
{
+ struct edma *cc = echan->ecc->cc;
struct virt_dma_desc *vdesc;
struct edma_desc *edesc;
struct device *dev = echan->vchan.chan.device->dev;
@@ -174,7 +176,7 @@ static void edma_execute(struct edma_chan *echan)
/* Write descriptor PaRAM set(s) */
for (i = 0; i < nslots; i++) {
j = i + edesc->processed;
- edma_write_slot(echan->slot[i], &edesc->pset[j].param);
+ edma_write_slot(cc, echan->slot[i], &edesc->pset[j].param);
edesc->sg_len += edesc->pset[j].len;
dev_vdbg(echan->vchan.chan.device->dev,
"\n pset[%d]:\n"
@@ -199,7 +201,7 @@ static void edma_execute(struct edma_chan *echan)
edesc->pset[j].param.link_bcntrld);
/* Link to the previous slot if not the last set */
if (i != (nslots - 1))
- edma_link(echan->slot[i], echan->slot[i+1]);
+ edma_link(cc, echan->slot[i], echan->slot[i+1]);
}
edesc->processed += nslots;
@@ -211,9 +213,9 @@ static void edma_execute(struct edma_chan *echan)
*/
if (edesc->processed == edesc->pset_nr) {
if (edesc->cyclic)
- edma_link(echan->slot[nslots-1], echan->slot[1]);
+ edma_link(cc, echan->slot[nslots-1], echan->slot[1]);
else
- edma_link(echan->slot[nslots-1],
+ edma_link(cc, echan->slot[nslots-1],
echan->ecc->dummy_slot);
}
@@ -224,19 +226,19 @@ static void edma_execute(struct edma_chan *echan)
* transfers of MAX_NR_SG
*/
dev_dbg(dev, "missed event on channel %d\n", echan->ch_num);
- edma_clean_channel(echan->ch_num);
- edma_stop(echan->ch_num);
- edma_start(echan->ch_num);
- edma_trigger_channel(echan->ch_num);
+ edma_clean_channel(cc, echan->ch_num);
+ edma_stop(cc, echan->ch_num);
+ edma_start(cc, echan->ch_num);
+ edma_trigger_channel(cc, echan->ch_num);
echan->missed = 0;
} else if (edesc->processed <= MAX_NR_SG) {
dev_dbg(dev, "first transfer starting on channel %d\n",
echan->ch_num);
- edma_start(echan->ch_num);
+ edma_start(cc, echan->ch_num);
} else {
dev_dbg(dev, "chan: %d: completed %d elements, resuming\n",
echan->ch_num, edesc->processed);
- edma_resume(echan->ch_num);
+ edma_resume(cc, echan->ch_num);
}
}
@@ -254,10 +256,11 @@ static int edma_terminate_all(struct dma_chan *chan)
* echan->edesc is NULL and exit.)
*/
if (echan->edesc) {
- edma_stop(echan->ch_num);
+ edma_stop(echan->ecc->cc, echan->ch_num);
/* Move the cyclic channel back to default queue */
if (echan->edesc->cyclic)
- edma_assign_channel_eventq(echan->ch_num,
+ edma_assign_channel_eventq(echan->ecc->cc,
+ echan->ch_num,
EVENTQ_DEFAULT);
/*
* free the running request descriptor
@@ -295,7 +298,7 @@ static int edma_dma_pause(struct dma_chan *chan)
if (!echan->edesc)
return -EINVAL;
- edma_pause(echan->ch_num);
+ edma_pause(echan->ecc->cc, echan->ch_num);
return 0;
}
@@ -303,7 +306,7 @@ static int edma_dma_resume(struct dma_chan *chan)
{
struct edma_chan *echan = to_edma_chan(chan);
- edma_resume(echan->ch_num);
+ edma_resume(echan->ecc->cc, echan->ch_num);
return 0;
}
@@ -485,8 +488,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
for (i = 0; i < nslots; i++) {
if (echan->slot[i] < 0) {
echan->slot[i] =
- edma_alloc_slot(EDMA_CTLR(echan->ch_num),
- EDMA_SLOT_ANY);
+ edma_alloc_slot(echan->ecc->cc, EDMA_SLOT_ANY);
if (echan->slot[i] < 0) {
kfree(edesc);
dev_err(dev, "%s: Failed to allocate slot\n",
@@ -641,8 +643,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
/* Allocate a PaRAM slot, if needed */
if (echan->slot[i] < 0) {
echan->slot[i] =
- edma_alloc_slot(EDMA_CTLR(echan->ch_num),
- EDMA_SLOT_ANY);
+ edma_alloc_slot(echan->ecc->cc, EDMA_SLOT_ANY);
if (echan->slot[i] < 0) {
kfree(edesc);
dev_err(dev, "%s: Failed to allocate slot\n",
@@ -703,7 +704,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
}
/* Place the cyclic channel to highest priority queue */
- edma_assign_channel_eventq(echan->ch_num, EVENTQ_0);
+ edma_assign_channel_eventq(echan->ecc->cc, echan->ch_num, EVENTQ_0);
return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
}
@@ -711,6 +712,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
{
struct edma_chan *echan = data;
+ struct edma *cc = echan->ecc->cc;
struct device *dev = echan->vchan.chan.device->dev;
struct edma_desc *edesc;
struct edmacc_param p;
@@ -727,13 +729,13 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
} else if (edesc->processed == edesc->pset_nr) {
dev_dbg(dev, "Transfer complete, stopping channel %d\n", ch_num);
edesc->residue = 0;
- edma_stop(echan->ch_num);
+ edma_stop(cc, echan->ch_num);
vchan_cookie_complete(&edesc->vdesc);
echan->edesc = NULL;
} else {
dev_dbg(dev, "Intermediate transfer complete on channel %d\n", ch_num);
- edma_pause(echan->ch_num);
+ edma_pause(cc, echan->ch_num);
/* Update statistics for tx_status */
edesc->residue -= edesc->sg_len;
@@ -744,7 +746,7 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
}
break;
case EDMA_DMA_CC_ERROR:
- edma_read_slot(EDMA_CHAN_SLOT(echan->slot[0]), &p);
+ edma_read_slot(cc, echan->slot[0], &p);
/*
* Issue later based on missed flag which will be sure
@@ -767,10 +769,10 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
* missed, so its safe to issue it here.
*/
dev_dbg(dev, "Error occurred but slot is non-null, TRIGGERING\n");
- edma_clean_channel(echan->ch_num);
- edma_stop(echan->ch_num);
- edma_start(echan->ch_num);
- edma_trigger_channel(echan->ch_num);
+ edma_clean_channel(cc, echan->ch_num);
+ edma_stop(cc, echan->ch_num);
+ edma_start(cc, echan->ch_num);
+ edma_trigger_channel(cc, echan->ch_num);
}
break;
default:
@@ -789,8 +791,8 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
int a_ch_num;
LIST_HEAD(descs);
- a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
- echan, EVENTQ_DEFAULT);
+ a_ch_num = edma_alloc_channel(echan->ecc->cc, echan->ch_num,
+ edma_callback, echan, EVENTQ_DEFAULT);
if (a_ch_num < 0) {
ret = -ENODEV;
@@ -814,7 +816,7 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
return 0;
err_wrong_chan:
- edma_free_channel(a_ch_num);
+ edma_free_channel(echan->ecc->cc, a_ch_num);
err_no_chan:
return ret;
}
@@ -827,21 +829,21 @@ static void edma_free_chan_resources(struct dma_chan *chan)
int i;
/* Terminate transfers */
- edma_stop(echan->ch_num);
+ edma_stop(echan->ecc->cc, echan->ch_num);
vchan_free_chan_resources(&echan->vchan);
/* Free EDMA PaRAM slots */
for (i = 1; i < EDMA_MAX_SLOTS; i++) {
if (echan->slot[i] >= 0) {
- edma_free_slot(echan->slot[i]);
+ edma_free_slot(echan->ecc->cc, echan->slot[i]);
echan->slot[i] = -1;
}
}
/* Free EDMA channel */
if (echan->alloced) {
- edma_free_channel(echan->ch_num);
+ edma_free_channel(echan->ecc->cc, echan->ch_num);
echan->alloced = false;
}
@@ -871,7 +873,8 @@ static u32 edma_residue(struct edma_desc *edesc)
* We always read the dst/src position from the first RamPar
* pset. That's the one which is active now.
*/
- pos = edma_get_position(edesc->echan->slot[0], dst);
+ pos = edma_get_position(edesc->echan->ecc->cc, edesc->echan->slot[0],
+ dst);
/*
* Cyclic is simple. Just subtract pset[0].addr from pos.
@@ -1008,8 +1011,12 @@ static int edma_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ ecc->cc = edma_get_data(pdev->dev.parent);
+ if (!ecc->cc)
+ return -ENODEV;
+
ecc->ctlr = pdev->id;
- ecc->dummy_slot = edma_alloc_slot(ecc->ctlr, EDMA_SLOT_ANY);
+ ecc->dummy_slot = edma_alloc_slot(ecc->cc, EDMA_SLOT_ANY);
if (ecc->dummy_slot < 0) {
dev_err(&pdev->dev, "Can't allocate PaRAM dummy slot\n");
return ecc->dummy_slot;
@@ -1042,7 +1049,7 @@ static int edma_probe(struct platform_device *pdev)
return 0;
err_reg1:
- edma_free_slot(ecc->dummy_slot);
+ edma_free_slot(ecc->cc, ecc->dummy_slot);
return ret;
}
@@ -1055,7 +1062,7 @@ static int edma_remove(struct platform_device *pdev)
if (parent_node)
of_dma_controller_free(parent_node);
dma_async_device_unregister(&ecc->dma_slave);
- edma_free_slot(ecc->dummy_slot);
+ edma_free_slot(ecc->cc, ecc->dummy_slot);
return 0;
}
OpenPOWER on IntegriCloud