Commit 3edc8502 authored by Vinod Koul's avatar Vinod Koul

Merge branch 'topic/rcar' into for-linus

parents 2e76eba5 33cb0880
...@@ -30,8 +30,9 @@ Required Properties: ...@@ -30,8 +30,9 @@ Required Properties:
- interrupts: interrupt specifiers for the DMAC, one for each entry in - interrupts: interrupt specifiers for the DMAC, one for each entry in
interrupt-names. interrupt-names.
- interrupt-names: one entry per channel, named "ch%u", where %u is the - interrupt-names: one entry for the error interrupt, named "error", plus one
channel number ranging from zero to the number of channels minus one. entry per channel, named "ch%u", where %u is the channel number ranging from
zero to the number of channels minus one.
- clock-names: "fck" for the functional clock - clock-names: "fck" for the functional clock
- clocks: a list of phandle + clock-specifier pairs, one for each entry - clocks: a list of phandle + clock-specifier pairs, one for each entry
......
* SHDMA Device Tree bindings * SHDMA Device Tree bindings
Sh-/r-mobile and r-car systems often have multiple identical DMA controller Sh-/r-mobile and R-Car systems often have multiple identical DMA controller
instances, capable of serving any of a common set of DMA slave devices, using instances, capable of serving any of a common set of DMA slave devices, using
the same configuration. To describe this topology we require all compatible the same configuration. To describe this topology we require all compatible
SHDMA DT nodes to be placed under a DMA multiplexer node. All such compatible SHDMA DT nodes to be placed under a DMA multiplexer node. All such compatible
......
...@@ -144,6 +144,7 @@ struct rcar_dmac_chan_map { ...@@ -144,6 +144,7 @@ struct rcar_dmac_chan_map {
* @chan: base DMA channel object * @chan: base DMA channel object
* @iomem: channel I/O memory base * @iomem: channel I/O memory base
* @index: index of this channel in the controller * @index: index of this channel in the controller
* @irq: channel IRQ
* @src: slave memory address and size on the source side * @src: slave memory address and size on the source side
* @dst: slave memory address and size on the destination side * @dst: slave memory address and size on the destination side
* @mid_rid: hardware MID/RID for the DMA client using this channel * @mid_rid: hardware MID/RID for the DMA client using this channel
...@@ -161,6 +162,7 @@ struct rcar_dmac_chan { ...@@ -161,6 +162,7 @@ struct rcar_dmac_chan {
struct dma_chan chan; struct dma_chan chan;
void __iomem *iomem; void __iomem *iomem;
unsigned int index; unsigned int index;
int irq;
struct rcar_dmac_chan_slave src; struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst; struct rcar_dmac_chan_slave dst;
...@@ -1008,7 +1010,11 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan) ...@@ -1008,7 +1010,11 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
rcar_dmac_chan_halt(rchan); rcar_dmac_chan_halt(rchan);
spin_unlock_irq(&rchan->lock); spin_unlock_irq(&rchan->lock);
/* Now no new interrupts will occur */ /*
* Now no new interrupts will occur, but one might already be
* running. Wait for it to finish before freeing resources.
*/
synchronize_irq(rchan->irq);
if (rchan->mid_rid >= 0) { if (rchan->mid_rid >= 0) {
/* The caller is holding dma_list_mutex */ /* The caller is holding dma_list_mutex */
...@@ -1363,6 +1369,13 @@ static void rcar_dmac_issue_pending(struct dma_chan *chan) ...@@ -1363,6 +1369,13 @@ static void rcar_dmac_issue_pending(struct dma_chan *chan)
spin_unlock_irqrestore(&rchan->lock, flags); spin_unlock_irqrestore(&rchan->lock, flags);
} }
static void rcar_dmac_device_synchronize(struct dma_chan *chan)
{
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
synchronize_irq(rchan->irq);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* IRQ handling * IRQ handling
*/ */
...@@ -1647,7 +1660,6 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, ...@@ -1647,7 +1660,6 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac,
struct dma_chan *chan = &rchan->chan; struct dma_chan *chan = &rchan->chan;
char pdev_irqname[5]; char pdev_irqname[5];
char *irqname; char *irqname;
int irq;
int ret; int ret;
rchan->index = index; rchan->index = index;
...@@ -1664,8 +1676,8 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, ...@@ -1664,8 +1676,8 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac,
/* Request the channel interrupt. */ /* Request the channel interrupt. */
sprintf(pdev_irqname, "ch%u", index); sprintf(pdev_irqname, "ch%u", index);
irq = platform_get_irq_byname(pdev, pdev_irqname); rchan->irq = platform_get_irq_byname(pdev, pdev_irqname);
if (irq < 0) { if (rchan->irq < 0) {
dev_err(dmac->dev, "no IRQ specified for channel %u\n", index); dev_err(dmac->dev, "no IRQ specified for channel %u\n", index);
return -ENODEV; return -ENODEV;
} }
...@@ -1675,11 +1687,13 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, ...@@ -1675,11 +1687,13 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac,
if (!irqname) if (!irqname)
return -ENOMEM; return -ENOMEM;
ret = devm_request_threaded_irq(dmac->dev, irq, rcar_dmac_isr_channel, ret = devm_request_threaded_irq(dmac->dev, rchan->irq,
rcar_dmac_isr_channel,
rcar_dmac_isr_channel_thread, 0, rcar_dmac_isr_channel_thread, 0,
irqname, rchan); irqname, rchan);
if (ret) { if (ret) {
dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", irq, ret); dev_err(dmac->dev, "failed to request IRQ %u (%d)\n",
rchan->irq, ret);
return ret; return ret;
} }
...@@ -1843,6 +1857,7 @@ static int rcar_dmac_probe(struct platform_device *pdev) ...@@ -1843,6 +1857,7 @@ static int rcar_dmac_probe(struct platform_device *pdev)
engine->device_terminate_all = rcar_dmac_chan_terminate_all; engine->device_terminate_all = rcar_dmac_chan_terminate_all;
engine->device_tx_status = rcar_dmac_tx_status; engine->device_tx_status = rcar_dmac_tx_status;
engine->device_issue_pending = rcar_dmac_issue_pending; engine->device_issue_pending = rcar_dmac_issue_pending;
engine->device_synchronize = rcar_dmac_device_synchronize;
ret = dma_async_device_register(engine); ret = dma_async_device_register(engine);
if (ret < 0) if (ret < 0)
......
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