|
@@ -82,7 +82,7 @@ struct dma_pl330_dmac {
|
|
|
spinlock_t pool_lock;
|
|
|
|
|
|
/* Peripheral channels connected to this DMAC */
|
|
|
- struct dma_pl330_chan peripherals[0]; /* keep at end */
|
|
|
+ struct dma_pl330_chan *peripherals; /* keep at end */
|
|
|
};
|
|
|
|
|
|
struct dma_pl330_desc {
|
|
@@ -451,8 +451,13 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
|
|
|
desc->txd.cookie = 0;
|
|
|
async_tx_ack(&desc->txd);
|
|
|
|
|
|
- desc->req.rqtype = peri->rqtype;
|
|
|
- desc->req.peri = peri->peri_id;
|
|
|
+ if (peri) {
|
|
|
+ desc->req.rqtype = peri->rqtype;
|
|
|
+ desc->req.peri = peri->peri_id;
|
|
|
+ } else {
|
|
|
+ desc->req.rqtype = MEMTOMEM;
|
|
|
+ desc->req.peri = 0;
|
|
|
+ }
|
|
|
|
|
|
dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
|
|
|
|
|
@@ -529,10 +534,10 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
|
|
|
struct pl330_info *pi;
|
|
|
int burst;
|
|
|
|
|
|
- if (unlikely(!pch || !len || !peri))
|
|
|
+ if (unlikely(!pch || !len))
|
|
|
return NULL;
|
|
|
|
|
|
- if (peri->rqtype != MEMTOMEM)
|
|
|
+ if (peri && peri->rqtype != MEMTOMEM)
|
|
|
return NULL;
|
|
|
|
|
|
pi = &pch->dmac->pif;
|
|
@@ -577,7 +582,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
|
|
int i, burst_size;
|
|
|
dma_addr_t addr;
|
|
|
|
|
|
- if (unlikely(!pch || !sgl || !sg_len))
|
|
|
+ if (unlikely(!pch || !sgl || !sg_len || !peri))
|
|
|
return NULL;
|
|
|
|
|
|
/* Make sure the direction is consistent */
|
|
@@ -666,17 +671,12 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|
|
struct dma_device *pd;
|
|
|
struct resource *res;
|
|
|
int i, ret, irq;
|
|
|
+ int num_chan;
|
|
|
|
|
|
pdat = adev->dev.platform_data;
|
|
|
|
|
|
- if (!pdat || !pdat->nr_valid_peri) {
|
|
|
- dev_err(&adev->dev, "platform data missing\n");
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
-
|
|
|
/* Allocate a new DMAC and its Channels */
|
|
|
- pdmac = kzalloc(pdat->nr_valid_peri * sizeof(*pch)
|
|
|
- + sizeof(*pdmac), GFP_KERNEL);
|
|
|
+ pdmac = kzalloc(sizeof(*pdmac), GFP_KERNEL);
|
|
|
if (!pdmac) {
|
|
|
dev_err(&adev->dev, "unable to allocate mem\n");
|
|
|
return -ENOMEM;
|
|
@@ -685,7 +685,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|
|
pi = &pdmac->pif;
|
|
|
pi->dev = &adev->dev;
|
|
|
pi->pl330_data = NULL;
|
|
|
- pi->mcbufsz = pdat->mcbuf_sz;
|
|
|
+ pi->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
|
|
|
|
|
|
res = &adev->res;
|
|
|
request_mem_region(res->start, resource_size(res), "dma-pl330");
|
|
@@ -717,27 +717,35 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|
|
INIT_LIST_HEAD(&pd->channels);
|
|
|
|
|
|
/* Initialize channel parameters */
|
|
|
- for (i = 0; i < pdat->nr_valid_peri; i++) {
|
|
|
- struct dma_pl330_peri *peri = &pdat->peri[i];
|
|
|
- pch = &pdmac->peripherals[i];
|
|
|
+ num_chan = max(pdat ? pdat->nr_valid_peri : 0, (u8)pi->pcfg.num_chan);
|
|
|
+ pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
|
|
|
|
|
|
- switch (peri->rqtype) {
|
|
|
- case MEMTOMEM:
|
|
|
+ for (i = 0; i < num_chan; i++) {
|
|
|
+ pch = &pdmac->peripherals[i];
|
|
|
+ if (pdat) {
|
|
|
+ struct dma_pl330_peri *peri = &pdat->peri[i];
|
|
|
+
|
|
|
+ switch (peri->rqtype) {
|
|
|
+ case MEMTOMEM:
|
|
|
+ dma_cap_set(DMA_MEMCPY, pd->cap_mask);
|
|
|
+ break;
|
|
|
+ case MEMTODEV:
|
|
|
+ case DEVTOMEM:
|
|
|
+ dma_cap_set(DMA_SLAVE, pd->cap_mask);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ dev_err(&adev->dev, "DEVTODEV Not Supported\n");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ pch->chan.private = peri;
|
|
|
+ } else {
|
|
|
dma_cap_set(DMA_MEMCPY, pd->cap_mask);
|
|
|
- break;
|
|
|
- case MEMTODEV:
|
|
|
- case DEVTOMEM:
|
|
|
- dma_cap_set(DMA_SLAVE, pd->cap_mask);
|
|
|
- break;
|
|
|
- default:
|
|
|
- dev_err(&adev->dev, "DEVTODEV Not Supported\n");
|
|
|
- continue;
|
|
|
+ pch->chan.private = NULL;
|
|
|
}
|
|
|
|
|
|
INIT_LIST_HEAD(&pch->work_list);
|
|
|
spin_lock_init(&pch->lock);
|
|
|
pch->pl330_chid = NULL;
|
|
|
- pch->chan.private = peri;
|
|
|
pch->chan.device = pd;
|
|
|
pch->chan.chan_id = i;
|
|
|
pch->dmac = pdmac;
|