diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-25 15:33:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-25 15:33:25 -0700 |
commit | 4e8a780ed6e1fdb8af203f61718212d5739bc4a0 (patch) | |
tree | 2f3b28f400932d72c3940ff360a1be1fed8b0f87 /drivers | |
parent | 90ff1f30c0f401e325d6b2747618b7e3a0addaf8 (diff) | |
parent | 66ee3bef3ce0bab155de082805388bd6ec2785f8 (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.c | 42 | ||||
-rw-r--r-- | drivers/dma/shdma.h | 2 |
2 files changed, 32 insertions, 12 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index dcc1b2139ff..636e40925b1 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 3f9d3cd0658..5ae9fc51218 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 */ |