summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-25 15:33:25 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-25 15:33:25 -0700
commit4e8a780ed6e1fdb8af203f61718212d5739bc4a0 (patch)
tree2f3b28f400932d72c3940ff360a1be1fed8b0f87 /drivers
parent90ff1f30c0f401e325d6b2747618b7e3a0addaf8 (diff)
parent66ee3bef3ce0bab155de082805388bd6ec2785f8 (diff)
Merge branch 'rmobile-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
* 'rmobile-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (34 commits) ARM: mach-shmobile: mackerel: add renesas_usbhs support for USB1 ARM: mach-shmobile: Correct the G4EVM SDHI0 I/O range. ARM: arch-shmobile: sh7372: add renesas_usbhs irq support ARM: mach-shmobile: sh73a0: mark DMA slave ID 0 as invalid ARM: mach-shmobile: mark DMA slave ID 0 as invalid ARM: mach-shmobile: Enable DMAEngine for SDHI on AG5EVM ARM: mach-shmobile: Enable DMAEngine for MMCIF on AG5EVM ARM: mach-shmobile: sh73a0 DMA Engine support for SY-DMAC dmaengine: shdma: Update SH_DMAC_MAX_CHANNELS to 20 dmaengine: shdma: Fix SH_DMAC_MAX_CHANNELS handling dmaengine: shdma: Make second memory window optional ARM: mach-shmobile: Tidy up after SH7372 pm changes. ARM: mach-shmobile: sh7372 Core Standby CPUIdle ARM: mach-shmobile: CPUIdle support ARM: mach-shmobile: sh7372 Core Standby Suspend-to-RAM ARM: mach-shmobile: Suspend-to-RAM support mailmap: Add entry for Damian Hobson-Garcia. ARM: switch mackerel to dynamically manage the platform camera ARM: mach-shmobile: Add SDHI support for AG5EVM and sh73a0 ARM: arch-shmobile: Use multiple irq vectors for SDHI ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/shdma.c42
-rw-r--r--drivers/dma/shdma.h2
2 files changed, 32 insertions, 12 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index dcc1b2139fff..636e40925b16 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -213,12 +213,17 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
struct sh_dmae_device, common);
struct sh_dmae_pdata *pdata = shdev->pdata;
const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
- u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16);
+ u16 __iomem *addr = shdev->dmars;
int shift = chan_pdata->dmars_bit;
if (dmae_is_busy(sh_chan))
return -EBUSY;
+ /* in the case of a missing DMARS resource use first memory window */
+ if (!addr)
+ addr = (u16 __iomem *)shdev->chan_reg;
+ addr += chan_pdata->dmars / sizeof(u16);
+
__raw_writew((__raw_readw(addr) & (0xff00 >> shift)) | (val << shift),
addr);
@@ -1078,7 +1083,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
unsigned long irqflags = IRQF_DISABLED,
chan_flag[SH_DMAC_MAX_CHANNELS] = {};
int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
- int err, i, irq_cnt = 0, irqres = 0;
+ int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0;
struct sh_dmae_device *shdev;
struct resource *chan, *dmars, *errirq_res, *chanirq_res;
@@ -1087,7 +1092,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
return -ENODEV;
chan = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- /* DMARS area is optional, if absent, this controller cannot do slave DMA */
+ /* DMARS area is optional */
dmars = platform_get_resource(pdev, IORESOURCE_MEM, 1);
/*
* IRQ resources:
@@ -1154,7 +1159,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&shdev->common.channels);
dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
- if (dmars)
+ if (pdata->slave && pdata->slave_num)
dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
shdev->common.device_alloc_chan_resources
@@ -1203,8 +1208,13 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
!platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
/* Special case - all multiplexed */
for (; irq_cnt < pdata->channel_num; irq_cnt++) {
- chan_irq[irq_cnt] = chanirq_res->start;
- chan_flag[irq_cnt] = IRQF_SHARED;
+ if (irq_cnt < SH_DMAC_MAX_CHANNELS) {
+ chan_irq[irq_cnt] = chanirq_res->start;
+ chan_flag[irq_cnt] = IRQF_SHARED;
+ } else {
+ irq_cap = 1;
+ break;
+ }
}
} else {
do {
@@ -1218,22 +1228,32 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
"Found IRQ %d for channel %d\n",
i, irq_cnt);
chan_irq[irq_cnt++] = i;
+
+ if (irq_cnt >= SH_DMAC_MAX_CHANNELS)
+ break;
+ }
+
+ if (irq_cnt >= SH_DMAC_MAX_CHANNELS) {
+ irq_cap = 1;
+ break;
}
chanirq_res = platform_get_resource(pdev,
IORESOURCE_IRQ, ++irqres);
} while (irq_cnt < pdata->channel_num && chanirq_res);
}
- if (irq_cnt < pdata->channel_num)
- goto eirqres;
-
/* Create DMA Channel */
- for (i = 0; i < pdata->channel_num; i++) {
+ for (i = 0; i < irq_cnt; i++) {
err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]);
if (err)
goto chan_probe_err;
}
+ if (irq_cap)
+ dev_notice(&pdev->dev, "Attempting to register %d DMA "
+ "channels when a maximum of %d are supported.\n",
+ pdata->channel_num, SH_DMAC_MAX_CHANNELS);
+
pm_runtime_put(&pdev->dev);
platform_set_drvdata(pdev, shdev);
@@ -1243,7 +1263,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
chan_probe_err:
sh_dmae_chan_remove(shdev);
-eirqres:
+
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
free_irq(errirq, shdev);
eirq_err:
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h
index 3f9d3cd06584..5ae9fc512180 100644
--- a/drivers/dma/shdma.h
+++ b/drivers/dma/shdma.h
@@ -17,7 +17,7 @@
#include <linux/interrupt.h>
#include <linux/list.h>
-#define SH_DMAC_MAX_CHANNELS 6
+#define SH_DMAC_MAX_CHANNELS 20
#define SH_DMA_SLAVE_NUMBER 256
#define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */