Commit 8a3ec583 authored by Vinod Koul's avatar Vinod Koul

Merge branch 'topic/stm32-dma' into for-linus

parents 25036f2a 5df4eb45
...@@ -40,8 +40,7 @@ Example: ...@@ -40,8 +40,7 @@ Example:
DMA clients connected to the STM32 DMA controller must use the format DMA clients connected to the STM32 DMA controller must use the format
described in the dma.txt file, using a five-cell specifier for each described in the dma.txt file, using a five-cell specifier for each
channel: a phandle plus four integer cells. channel: a phandle to the DMA controller plus the following four integer cells:
The four cells in order are:
1. The channel id 1. The channel id
2. The request line number 2. The request line number
...@@ -61,7 +60,7 @@ The four cells in order are: ...@@ -61,7 +60,7 @@ The four cells in order are:
0x1: medium 0x1: medium
0x2: high 0x2: high
0x3: very high 0x3: very high
5. A 32bit mask specifying the DMA FIFO threshold configuration which are device 4. A 32bit mask specifying the DMA FIFO threshold configuration which are device
dependent: dependent:
-bit 0-1: Fifo threshold -bit 0-1: Fifo threshold
0x0: 1/4 full FIFO 0x0: 1/4 full FIFO
......
...@@ -458,7 +458,7 @@ config STM32_DMA ...@@ -458,7 +458,7 @@ config STM32_DMA
help help
Enable support for the on-chip DMA controller on STMicroelectronics Enable support for the on-chip DMA controller on STMicroelectronics
STM32 MCUs. STM32 MCUs.
If you have a board based on such a MCU and wish to use DMA say Y or M If you have a board based on such a MCU and wish to use DMA say Y
here. here.
config S3C24XX_DMAC config S3C24XX_DMAC
......
...@@ -114,6 +114,7 @@ ...@@ -114,6 +114,7 @@
#define STM32_DMA_MAX_CHANNELS 0x08 #define STM32_DMA_MAX_CHANNELS 0x08
#define STM32_DMA_MAX_REQUEST_ID 0x08 #define STM32_DMA_MAX_REQUEST_ID 0x08
#define STM32_DMA_MAX_DATA_PARAM 0x03 #define STM32_DMA_MAX_DATA_PARAM 0x03
#define STM32_DMA_MAX_BURST 16
enum stm32_dma_width { enum stm32_dma_width {
STM32_DMA_BYTE, STM32_DMA_BYTE,
...@@ -403,6 +404,13 @@ static int stm32_dma_terminate_all(struct dma_chan *c) ...@@ -403,6 +404,13 @@ static int stm32_dma_terminate_all(struct dma_chan *c)
return 0; return 0;
} }
static void stm32_dma_synchronize(struct dma_chan *c)
{
struct stm32_dma_chan *chan = to_stm32_dma_chan(c);
vchan_synchronize(&chan->vchan);
}
static void stm32_dma_dump_reg(struct stm32_dma_chan *chan) static void stm32_dma_dump_reg(struct stm32_dma_chan *chan)
{ {
struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
...@@ -421,7 +429,7 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan) ...@@ -421,7 +429,7 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan)
dev_dbg(chan2dev(chan), "SFCR: 0x%08x\n", sfcr); dev_dbg(chan2dev(chan), "SFCR: 0x%08x\n", sfcr);
} }
static int stm32_dma_start_transfer(struct stm32_dma_chan *chan) static void stm32_dma_start_transfer(struct stm32_dma_chan *chan)
{ {
struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
struct virt_dma_desc *vdesc; struct virt_dma_desc *vdesc;
...@@ -432,12 +440,12 @@ static int stm32_dma_start_transfer(struct stm32_dma_chan *chan) ...@@ -432,12 +440,12 @@ static int stm32_dma_start_transfer(struct stm32_dma_chan *chan)
ret = stm32_dma_disable_chan(chan); ret = stm32_dma_disable_chan(chan);
if (ret < 0) if (ret < 0)
return ret; return;
if (!chan->desc) { if (!chan->desc) {
vdesc = vchan_next_desc(&chan->vchan); vdesc = vchan_next_desc(&chan->vchan);
if (!vdesc) if (!vdesc)
return -EPERM; return;
chan->desc = to_stm32_dma_desc(vdesc); chan->desc = to_stm32_dma_desc(vdesc);
chan->next_sg = 0; chan->next_sg = 0;
...@@ -471,7 +479,7 @@ static int stm32_dma_start_transfer(struct stm32_dma_chan *chan) ...@@ -471,7 +479,7 @@ static int stm32_dma_start_transfer(struct stm32_dma_chan *chan)
chan->busy = true; chan->busy = true;
return 0; dev_dbg(chan2dev(chan), "vchan %p: started\n", &chan->vchan);
} }
static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan)
...@@ -500,8 +508,6 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) ...@@ -500,8 +508,6 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan)
dev_dbg(chan2dev(chan), "CT=0 <=> SM1AR: 0x%08x\n", dev_dbg(chan2dev(chan), "CT=0 <=> SM1AR: 0x%08x\n",
stm32_dma_read(dmadev, STM32_DMA_SM1AR(id))); stm32_dma_read(dmadev, STM32_DMA_SM1AR(id)));
} }
chan->next_sg++;
} }
} }
...@@ -510,6 +516,7 @@ static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan) ...@@ -510,6 +516,7 @@ static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan)
if (chan->desc) { if (chan->desc) {
if (chan->desc->cyclic) { if (chan->desc->cyclic) {
vchan_cyclic_callback(&chan->desc->vdesc); vchan_cyclic_callback(&chan->desc->vdesc);
chan->next_sg++;
stm32_dma_configure_next_sg(chan); stm32_dma_configure_next_sg(chan);
} else { } else {
chan->busy = false; chan->busy = false;
...@@ -552,15 +559,13 @@ static void stm32_dma_issue_pending(struct dma_chan *c) ...@@ -552,15 +559,13 @@ static void stm32_dma_issue_pending(struct dma_chan *c)
{ {
struct stm32_dma_chan *chan = to_stm32_dma_chan(c); struct stm32_dma_chan *chan = to_stm32_dma_chan(c);
unsigned long flags; unsigned long flags;
int ret;
spin_lock_irqsave(&chan->vchan.lock, flags); spin_lock_irqsave(&chan->vchan.lock, flags);
if (!chan->busy) { if (vchan_issue_pending(&chan->vchan) && !chan->desc && !chan->busy) {
if (vchan_issue_pending(&chan->vchan) && !chan->desc) { dev_dbg(chan2dev(chan), "vchan %p: issued\n", &chan->vchan);
ret = stm32_dma_start_transfer(chan); stm32_dma_start_transfer(chan);
if ((!ret) && (chan->desc->cyclic)) if (chan->desc->cyclic)
stm32_dma_configure_next_sg(chan); stm32_dma_configure_next_sg(chan);
}
} }
spin_unlock_irqrestore(&chan->vchan.lock, flags); spin_unlock_irqrestore(&chan->vchan.lock, flags);
} }
...@@ -848,26 +853,40 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy( ...@@ -848,26 +853,40 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
} }
static u32 stm32_dma_get_remaining_bytes(struct stm32_dma_chan *chan)
{
u32 dma_scr, width, ndtr;
struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id));
width = STM32_DMA_SCR_PSIZE_GET(dma_scr);
ndtr = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id));
return ndtr << width;
}
static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan,
struct stm32_dma_desc *desc, struct stm32_dma_desc *desc,
u32 next_sg) u32 next_sg)
{ {
struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); u32 residue = 0;
u32 dma_scr, width, residue, count;
int i; int i;
residue = 0; /*
* In cyclic mode, for the last period, residue = remaining bytes from
* NDTR
*/
if (chan->desc->cyclic && next_sg == 0)
return stm32_dma_get_remaining_bytes(chan);
/*
* For all other periods in cyclic mode, and in sg mode,
* residue = remaining bytes from NDTR + remaining periods/sg to be
* transferred
*/
for (i = next_sg; i < desc->num_sgs; i++) for (i = next_sg; i < desc->num_sgs; i++)
residue += desc->sg_req[i].len; residue += desc->sg_req[i].len;
residue += stm32_dma_get_remaining_bytes(chan);
if (next_sg != 0) {
dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id));
width = STM32_DMA_SCR_PSIZE_GET(dma_scr);
count = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id));
residue += count << width;
}
return residue; return residue;
} }
...@@ -968,30 +987,36 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec, ...@@ -968,30 +987,36 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma) struct of_dma *ofdma)
{ {
struct stm32_dma_device *dmadev = ofdma->of_dma_data; struct stm32_dma_device *dmadev = ofdma->of_dma_data;
struct device *dev = dmadev->ddev.dev;
struct stm32_dma_cfg cfg; struct stm32_dma_cfg cfg;
struct stm32_dma_chan *chan; struct stm32_dma_chan *chan;
struct dma_chan *c; struct dma_chan *c;
if (dma_spec->args_count < 3) if (dma_spec->args_count < 4) {
dev_err(dev, "Bad number of cells\n");
return NULL; return NULL;
}
cfg.channel_id = dma_spec->args[0]; cfg.channel_id = dma_spec->args[0];
cfg.request_line = dma_spec->args[1]; cfg.request_line = dma_spec->args[1];
cfg.stream_config = dma_spec->args[2]; cfg.stream_config = dma_spec->args[2];
cfg.threshold = 0; cfg.threshold = dma_spec->args[3];
if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >= if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) ||
STM32_DMA_MAX_REQUEST_ID)) (cfg.request_line >= STM32_DMA_MAX_REQUEST_ID)) {
dev_err(dev, "Bad channel and/or request id\n");
return NULL; return NULL;
}
if (dma_spec->args_count > 3)
cfg.threshold = dma_spec->args[3];
chan = &dmadev->chan[cfg.channel_id]; chan = &dmadev->chan[cfg.channel_id];
c = dma_get_slave_channel(&chan->vchan.chan); c = dma_get_slave_channel(&chan->vchan.chan);
if (c) if (!c) {
stm32_dma_set_config(chan, &cfg); dev_err(dev, "No more channel avalaible\n");
return NULL;
}
stm32_dma_set_config(chan, &cfg);
return c; return c;
} }
...@@ -1055,6 +1080,7 @@ static int stm32_dma_probe(struct platform_device *pdev) ...@@ -1055,6 +1080,7 @@ static int stm32_dma_probe(struct platform_device *pdev)
dd->device_prep_dma_cyclic = stm32_dma_prep_dma_cyclic; dd->device_prep_dma_cyclic = stm32_dma_prep_dma_cyclic;
dd->device_config = stm32_dma_slave_config; dd->device_config = stm32_dma_slave_config;
dd->device_terminate_all = stm32_dma_terminate_all; dd->device_terminate_all = stm32_dma_terminate_all;
dd->device_synchronize = stm32_dma_synchronize;
dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
...@@ -1063,6 +1089,7 @@ static int stm32_dma_probe(struct platform_device *pdev) ...@@ -1063,6 +1089,7 @@ static int stm32_dma_probe(struct platform_device *pdev)
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
dd->max_burst = STM32_DMA_MAX_BURST;
dd->dev = &pdev->dev; dd->dev = &pdev->dev;
INIT_LIST_HEAD(&dd->channels); INIT_LIST_HEAD(&dd->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