Commit 2e76eba5 authored by Vinod Koul's avatar Vinod Koul

Merge branch 'topic/pl330' into for-linus

parents 98cd085e d43674ec
...@@ -443,7 +443,10 @@ struct dma_pl330_chan { ...@@ -443,7 +443,10 @@ struct dma_pl330_chan {
/* For D-to-M and M-to-D channels */ /* For D-to-M and M-to-D channels */
int burst_sz; /* the peripheral fifo width */ int burst_sz; /* the peripheral fifo width */
int burst_len; /* the number of burst */ int burst_len; /* the number of burst */
dma_addr_t fifo_addr; phys_addr_t fifo_addr;
/* DMA-mapped view of the FIFO; may differ if an IOMMU is present */
dma_addr_t fifo_dma;
enum dma_data_direction dir;
/* for cyclic capability */ /* for cyclic capability */
bool cyclic; bool cyclic;
...@@ -538,11 +541,6 @@ struct _xfer_spec { ...@@ -538,11 +541,6 @@ struct _xfer_spec {
struct dma_pl330_desc *desc; struct dma_pl330_desc *desc;
}; };
static inline bool _queue_empty(struct pl330_thread *thrd)
{
return thrd->req[0].desc == NULL && thrd->req[1].desc == NULL;
}
static inline bool _queue_full(struct pl330_thread *thrd) static inline bool _queue_full(struct pl330_thread *thrd)
{ {
return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL; return thrd->req[0].desc != NULL && thrd->req[1].desc != NULL;
...@@ -564,23 +562,6 @@ static inline u32 get_revision(u32 periph_id) ...@@ -564,23 +562,6 @@ static inline u32 get_revision(u32 periph_id)
return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK; return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
} }
static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
enum pl330_dst da, u16 val)
{
if (dry_run)
return SZ_DMAADDH;
buf[0] = CMD_DMAADDH;
buf[0] |= (da << 1);
buf[1] = val;
buf[2] = val >> 8;
PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
da == 1 ? "DA" : "SA", val);
return SZ_DMAADDH;
}
static inline u32 _emit_END(unsigned dry_run, u8 buf[]) static inline u32 _emit_END(unsigned dry_run, u8 buf[])
{ {
if (dry_run) if (dry_run)
...@@ -738,18 +719,6 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[], ...@@ -738,18 +719,6 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
return SZ_DMAMOV; return SZ_DMAMOV;
} }
static inline u32 _emit_NOP(unsigned dry_run, u8 buf[])
{
if (dry_run)
return SZ_DMANOP;
buf[0] = CMD_DMANOP;
PL330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n");
return SZ_DMANOP;
}
static inline u32 _emit_RMB(unsigned dry_run, u8 buf[]) static inline u32 _emit_RMB(unsigned dry_run, u8 buf[])
{ {
if (dry_run) if (dry_run)
...@@ -817,39 +786,6 @@ static inline u32 _emit_STP(unsigned dry_run, u8 buf[], ...@@ -817,39 +786,6 @@ static inline u32 _emit_STP(unsigned dry_run, u8 buf[],
return SZ_DMASTP; return SZ_DMASTP;
} }
static inline u32 _emit_STZ(unsigned dry_run, u8 buf[])
{
if (dry_run)
return SZ_DMASTZ;
buf[0] = CMD_DMASTZ;
PL330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n");
return SZ_DMASTZ;
}
static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev,
unsigned invalidate)
{
if (dry_run)
return SZ_DMAWFE;
buf[0] = CMD_DMAWFE;
ev &= 0x1f;
ev <<= 3;
buf[1] = ev;
if (invalidate)
buf[1] |= (1 << 1);
PL330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n",
ev >> 3, invalidate ? ", I" : "");
return SZ_DMAWFE;
}
static inline u32 _emit_WFP(unsigned dry_run, u8 buf[], static inline u32 _emit_WFP(unsigned dry_run, u8 buf[],
enum pl330_cond cond, u8 peri) enum pl330_cond cond, u8 peri)
{ {
...@@ -2120,11 +2056,60 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) ...@@ -2120,11 +2056,60 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
return 1; return 1;
} }
/*
* We need the data direction between the DMAC (the dma-mapping "device") and
* the FIFO (the dmaengine "dev"), from the FIFO's point of view. Confusing!
*/
static enum dma_data_direction
pl330_dma_slave_map_dir(enum dma_transfer_direction dir)
{
switch (dir) {
case DMA_MEM_TO_DEV:
return DMA_FROM_DEVICE;
case DMA_DEV_TO_MEM:
return DMA_TO_DEVICE;
case DMA_DEV_TO_DEV:
return DMA_BIDIRECTIONAL;
default:
return DMA_NONE;
}
}
static void pl330_unprep_slave_fifo(struct dma_pl330_chan *pch)
{
if (pch->dir != DMA_NONE)
dma_unmap_resource(pch->chan.device->dev, pch->fifo_dma,
1 << pch->burst_sz, pch->dir, 0);
pch->dir = DMA_NONE;
}
static bool pl330_prep_slave_fifo(struct dma_pl330_chan *pch,
enum dma_transfer_direction dir)
{
struct device *dev = pch->chan.device->dev;
enum dma_data_direction dma_dir = pl330_dma_slave_map_dir(dir);
/* Already mapped for this config? */
if (pch->dir == dma_dir)
return true;
pl330_unprep_slave_fifo(pch);
pch->fifo_dma = dma_map_resource(dev, pch->fifo_addr,
1 << pch->burst_sz, dma_dir, 0);
if (dma_mapping_error(dev, pch->fifo_dma))
return false;
pch->dir = dma_dir;
return true;
}
static int pl330_config(struct dma_chan *chan, static int pl330_config(struct dma_chan *chan,
struct dma_slave_config *slave_config) struct dma_slave_config *slave_config)
{ {
struct dma_pl330_chan *pch = to_pchan(chan); struct dma_pl330_chan *pch = to_pchan(chan);
pl330_unprep_slave_fifo(pch);
if (slave_config->direction == DMA_MEM_TO_DEV) { if (slave_config->direction == DMA_MEM_TO_DEV) {
if (slave_config->dst_addr) if (slave_config->dst_addr)
pch->fifo_addr = slave_config->dst_addr; pch->fifo_addr = slave_config->dst_addr;
...@@ -2235,6 +2220,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan) ...@@ -2235,6 +2220,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
spin_unlock_irqrestore(&pl330->lock, flags); spin_unlock_irqrestore(&pl330->lock, flags);
pm_runtime_mark_last_busy(pch->dmac->ddma.dev); pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
pm_runtime_put_autosuspend(pch->dmac->ddma.dev); pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
pl330_unprep_slave_fifo(pch);
} }
static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch, static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
...@@ -2564,6 +2550,9 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( ...@@ -2564,6 +2550,9 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
return NULL; return NULL;
} }
if (!pl330_prep_slave_fifo(pch, direction))
return NULL;
for (i = 0; i < len / period_len; i++) { for (i = 0; i < len / period_len; i++) {
desc = pl330_get_desc(pch); desc = pl330_get_desc(pch);
if (!desc) { if (!desc) {
...@@ -2593,12 +2582,12 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( ...@@ -2593,12 +2582,12 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
desc->rqcfg.src_inc = 1; desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0; desc->rqcfg.dst_inc = 0;
src = dma_addr; src = dma_addr;
dst = pch->fifo_addr; dst = pch->fifo_dma;
break; break;
case DMA_DEV_TO_MEM: case DMA_DEV_TO_MEM:
desc->rqcfg.src_inc = 0; desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1; desc->rqcfg.dst_inc = 1;
src = pch->fifo_addr; src = pch->fifo_dma;
dst = dma_addr; dst = dma_addr;
break; break;
default: default:
...@@ -2711,12 +2700,12 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ...@@ -2711,12 +2700,12 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
struct dma_pl330_chan *pch = to_pchan(chan); struct dma_pl330_chan *pch = to_pchan(chan);
struct scatterlist *sg; struct scatterlist *sg;
int i; int i;
dma_addr_t addr;
if (unlikely(!pch || !sgl || !sg_len)) if (unlikely(!pch || !sgl || !sg_len))
return NULL; return NULL;
addr = pch->fifo_addr; if (!pl330_prep_slave_fifo(pch, direction))
return NULL;
first = NULL; first = NULL;
...@@ -2742,13 +2731,13 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ...@@ -2742,13 +2731,13 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
if (direction == DMA_MEM_TO_DEV) { if (direction == DMA_MEM_TO_DEV) {
desc->rqcfg.src_inc = 1; desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0; desc->rqcfg.dst_inc = 0;
fill_px(&desc->px, fill_px(&desc->px, pch->fifo_dma, sg_dma_address(sg),
addr, sg_dma_address(sg), sg_dma_len(sg)); sg_dma_len(sg));
} else { } else {
desc->rqcfg.src_inc = 0; desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1; desc->rqcfg.dst_inc = 1;
fill_px(&desc->px, fill_px(&desc->px, sg_dma_address(sg), pch->fifo_dma,
sg_dma_address(sg), addr, sg_dma_len(sg)); sg_dma_len(sg));
} }
desc->rqcfg.brst_size = pch->burst_sz; desc->rqcfg.brst_size = pch->burst_sz;
...@@ -2906,6 +2895,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -2906,6 +2895,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
pch->thread = NULL; pch->thread = NULL;
pch->chan.device = pd; pch->chan.device = pd;
pch->dmac = pl330; pch->dmac = pl330;
pch->dir = DMA_NONE;
/* Add the channel to the DMAC list */ /* Add the channel to the DMAC list */
list_add_tail(&pch->chan.device_node, &pd->channels); list_add_tail(&pch->chan.device_node, &pd->channels);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment