* Re: [PATCH 0/2] ARM: mach-shmobile: clock-r8a7779: patches
From: Paul Mundt @ 2012-01-09 1:24 UTC (permalink / raw)
To: linux-sh
On Tue, Dec 20, 2011 at 12:46:56AM -0800, Kuninori Morimoto wrote:
> These are r8a7779 clock update patches which depends on Magnus's
> [ARM: mach-shmobile: r8a7779 and Marzen V2] patches
>
> Kuninori Morimoto (2):
> ARM: mach-shmobile: clock-r8a7779: add DIV4 clock support
> ARM: mach-shmobile: clock-r8a7779: clkz/clkzs support
>
Applied to rmobile/marzen, thanks.
^ permalink raw reply
* Re: [PATCH] ARM: mach-shmobile: Fix headsmp.S code to use CPUINIT
From: Paul Mundt @ 2012-01-09 1:38 UTC (permalink / raw)
To: linux-sh
On Wed, Dec 28, 2011 at 04:44:06PM +0900, Magnus Damm wrote:
> Convert the low level SMP assembly code for SH-Mobile ARM
> from using the INIT to the CPUINIT section. This unbreaks
> onlining of CPUs using the CPU hotplug interface:
>
> echo 1 > /sys/devices/system/cpu/cpu1/online
>
> Without this fix the reset vector code used by CPU hotplug
> will be freed as init section data and CPU cores cannot
> be brought online.
On Wed, Dec 28, 2011 at 04:47:16PM +0900, Magnus Damm wrote:
> Add the function shmobile_platform_kill_cpu() to allow
> SoC specific code to tie in their CPU shutdown code.
On Wed, Dec 28, 2011 at 04:53:16PM +0900, Magnus Damm wrote:
> Add cache flushing code to the SH-Mobile specific CPU hotplug
> implementation. While at it, add a cpu mask to make sure the
> cache flushing code is finished in platform_cpu_die() before
> letting the SoC-specific code in shmobile_platform_cpu_kill()
> proceed with turning off power.
>
> Without this code CPU hotplug offline fails when cache is
> enabled on Cortex-A9 based SoCs.
All applied, thanks.
^ permalink raw reply
* Re: [PATCH] ARM: mach-shmobile: r8a7779 SMP support V2
From: Paul Mundt @ 2012-01-09 1:44 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20111222081730.12133.61045.sendpatchset@w520>
On Wed, Dec 28, 2011 at 05:00:48PM +0900, Magnus Damm wrote:
> From: Magnus Damm <damm@opensource.se>
>
> This patch contains r8a7779 SMP support V2 - now including
> CPU hotplug offine and online support. The r8a7779 power
> domain code is tied together with SMP glue code which allows
> us to control the power domains via CPU hotplug.
>
> At this point the kernel boots with the 4 Cortex-A9 cores in
> SMP mode and all CPU cores except CPU0 can be hotplugged.
>
> Signed-off-by: Magnus Damm <damm@opensource.se>
> ---
>
> Depends on the r8a7779 base plus the power domain code:
> [PATCH] ARM: mach-shmobile: r8a7779 power domain support
>
Not sure how you want to handle this. I can take the power domain code
since it's the initial merge, or I can just push out the base stuff I
have now, Rafael can merge the power domain stuff on top, and then we can
add the SMP support at a later stage. There won't be a lot of time for
multiple merges this merge window, though.
In any event, I'm not entirely pleased with the direction the platsmp
code is going. Either layer in some function pointers that the CPU code
can set up, add some weak symbols, or move the small bit of common code
somewhere actually common rather than trying to shoe-horn everything in
and then relying on this absurd is_xxx() check (which in itself is
nothing but glorified ifdef abuse).
^ permalink raw reply
* Re: [RFC][PATCH 1/3] dmaengine: shdma: add .no_error_irq flag
From: Paul Mundt @ 2012-01-09 2:00 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4F0537F2.4080306@renesas.com>
On Fri, Jan 06, 2012 at 01:00:25PM +0900, Shimoda, Yoshihiro wrote:
> Hello Guennadi-san,
>
> Thank you very much for your review and suggestion.
> I think that your suggestion is very good.
>
> So, I could remove the no_error_irq flag using platform_get_irq_byname().
> My modified patch is the following. And, if it is no problem,
> I will submit it again:
> -------
> Subject: [PATCH] dmaengine: shdma: modify the DMAC Address Error registration
>
> The USB-DMAC/SUDMAC don't have the interrupt of DMAC Address Error.
> So, only when the resource has a name and it is "error_irq", the driver
> calls request_irq() for DMAC Address Error.
>
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
If we're going to do this it would be nice to adopt the same behaviour
for the generic DMAE IRQ, too (then we can finally get rid of those silly
CPU_SH4 || ARCH_SHMOBILE ifdefs).
This approach looks like an improvement to me at least.
^ permalink raw reply
* Re: [PATCH] sh: modify clock-sh7757 for renesas_usbhs
From: Paul Mundt @ 2012-01-09 3:09 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4F053033.5050805@renesas.com>
On Thu, Jan 05, 2012 at 02:08:03PM +0900, Shimoda, Yoshihiro wrote:
> The renesas_usbhs driver doesn't use the clk functions. So, even if we
> adds "CLKDEV_DEV_ID("renesas_usbhs.0", ...)" only, we cannot use the USB
> controller because clk_late_init() will disable the clock by "usb0".
> So, the patch also removes the "CLKDEV_CON_ID("usb0", ...)".
>
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
On Thu, Jan 05, 2012 at 02:08:12PM +0900, Shimoda, Yoshihiro wrote:
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> ---
> arch/sh/boards/board-sh7757lcr.c | 39 ++++++++++++++++++++++++++++++++++++++
> 1 files changed, 39 insertions(+), 0 deletions(-)
>
Both applied, thanks.
^ permalink raw reply
* [PATCH v3] sh: sh2a: Improve cache flush/invalidate functions
From: Phil Edworthy @ 2012-01-09 16:08 UTC (permalink / raw)
To: linux-sh
The cache functions lock out interrupts for long periods; this patch
reduces the impact when operating on large address ranges. In such
cases it will:
- Invalidate the entire cache rather than individual addresses.
- Do nothing when flushing the operand cache in write-through mode.
- When flushing the operand cache in write-back mdoe, index the
search for matching addresses on the cache entires instead of the
addresses to flush
Note: sh2a__flush_purge_region was only invalidating the operand
cache, this adds flush.
Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
v3:
1. Refactored code to make it readable and correct formatting.
2. Added code to handle flushing large address ranges in
write-back mode.
arch/sh/mm/cache-sh2a.c | 123 ++++++++++++++++++++++++++++++++---------------
1 files changed, 84 insertions(+), 39 deletions(-)
diff --git a/arch/sh/mm/cache-sh2a.c b/arch/sh/mm/cache-sh2a.c
index 1f51225..ae08cbb 100644
--- a/arch/sh/mm/cache-sh2a.c
+++ b/arch/sh/mm/cache-sh2a.c
@@ -15,35 +15,78 @@
#include <asm/cacheflush.h>
#include <asm/io.h>
+/*
+ * The maximum number of pages we support up to when doing ranged dcache
+ * flushing. Anything exceeding this will simply flush the dcache in its
+ * entirety.
+ */
+#define MAX_OCACHE_PAGES 32
+#define MAX_ICACHE_PAGES 32
+
+static void sh2a_flush_oc_line(unsigned long v, int way)
+{
+ unsigned long addr = (v & 0x000007f0) | (way << 11);
+ unsigned long data;
+
+ data = __raw_readl(CACHE_OC_ADDRESS_ARRAY | addr);
+ if ((data & CACHE_PHYSADDR_MASK) = (v & CACHE_PHYSADDR_MASK)) {
+ data &= ~SH_CACHE_UPDATED;
+ __raw_writel(data, CACHE_OC_ADDRESS_ARRAY | addr);
+ }
+}
+
+static void sh2a_invalidate_line(unsigned long cache_addr, unsigned long v)
+{
+ /* Set associative bit to hit all ways */
+ unsigned long addr = (v & 0x000007f0) | SH_CACHE_ASSOC;
+ __raw_writel((addr & CACHE_PHYSADDR_MASK), cache_addr | addr);
+}
+
+/*
+ * Write back the dirty D-caches, but not invalidate them.
+ */
static void sh2a__flush_wback_region(void *start, int size)
{
+#ifdef CONFIG_CACHE_WRITEBACK
unsigned long v;
unsigned long begin, end;
unsigned long flags;
+ int nr_ways;
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
+ nr_ways = current_cpu_data.dcache.ways;
local_irq_save(flags);
jump_to_uncached();
- for (v = begin; v < end; v+=L1_CACHE_BYTES) {
- unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0);
+ /* If there are too many pages then flush the entire cache */
+ if (((end - begin) >> PAGE_SHIFT) >= MAX_OCACHE_PAGES) {
+ begin = CACHE_OC_ADDRESS_ARRAY;
+ end = begin + (nr_ways * current_cpu_data.dcache.way_size);
+
+ for (v = begin; v < end; v += L1_CACHE_BYTES) {
+ unsigned long data = __raw_readl(v);
+ if (data & SH_CACHE_UPDATED)
+ __raw_writel(data & ~SH_CACHE_UPDATED, v);
+ }
+ } else {
int way;
- for (way = 0; way < 4; way++) {
- unsigned long data = __raw_readl(addr | (way << 11));
- if ((data & CACHE_PHYSADDR_MASK) = (v & CACHE_PHYSADDR_MASK)) {
- data &= ~SH_CACHE_UPDATED;
- __raw_writel(data, addr | (way << 11));
- }
+ for (way = 0; way < nr_ways; way++) {
+ for (v = begin; v < end; v += L1_CACHE_BYTES)
+ sh2a_flush_oc_line(v, way);
}
}
back_to_cached();
local_irq_restore(flags);
+#endif
}
+/*
+ * Write back the dirty D-caches and invalidate them.
+ */
static void sh2a__flush_purge_region(void *start, int size)
{
unsigned long v;
@@ -58,13 +101,22 @@ static void sh2a__flush_purge_region(void *start, int size)
jump_to_uncached();
for (v = begin; v < end; v+=L1_CACHE_BYTES) {
- __raw_writel((v & CACHE_PHYSADDR_MASK),
- CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
+#ifdef CONFIG_CACHE_WRITEBACK
+ int way;
+ int nr_ways = current_cpu_data.dcache.ways;
+ for (way = 0; way < nr_ways; way++)
+ sh2a_flush_oc_line(v, way);
+#endif
+ sh2a_invalidate_line(CACHE_OC_ADDRESS_ARRAY, v);
}
+
back_to_cached();
local_irq_restore(flags);
}
+/*
+ * Invalidate the D-caches, but no write back please
+ */
static void sh2a__flush_invalidate_region(void *start, int size)
{
unsigned long v;
@@ -74,29 +126,25 @@ static void sh2a__flush_invalidate_region(void *start, int size)
begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
& ~(L1_CACHE_BYTES-1);
+
local_irq_save(flags);
jump_to_uncached();
-#ifdef CONFIG_CACHE_WRITEBACK
- __raw_writel(__raw_readl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
- /* I-cache invalidate */
- for (v = begin; v < end; v+=L1_CACHE_BYTES) {
- __raw_writel((v & CACHE_PHYSADDR_MASK),
- CACHE_IC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
- }
-#else
- for (v = begin; v < end; v+=L1_CACHE_BYTES) {
- __raw_writel((v & CACHE_PHYSADDR_MASK),
- CACHE_IC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
- __raw_writel((v & CACHE_PHYSADDR_MASK),
- CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0) | 0x00000008);
+ /* If there are too many pages then just blow the cache */
+ if (((end - begin) >> PAGE_SHIFT) >= MAX_OCACHE_PAGES) {
+ __raw_writel(__raw_readl(CCR) | CCR_OCACHE_INVALIDATE, CCR);
+ } else {
+ for (v = begin; v < end; v += L1_CACHE_BYTES)
+ sh2a_invalidate_line(CACHE_OC_ADDRESS_ARRAY, v);
}
-#endif
+
back_to_cached();
local_irq_restore(flags);
}
-/* WBack O-Cache and flush I-Cache */
+/*
+ * Write back the range of D-cache, and purge the I-cache.
+ */
static void sh2a_flush_icache_range(void *args)
{
struct flusher_data *data = args;
@@ -107,23 +155,20 @@ static void sh2a_flush_icache_range(void *args)
start = data->addr1 & ~(L1_CACHE_BYTES-1);
end = (data->addr2 + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1);
+#ifdef CONFIG_CACHE_WRITEBACK
+ sh2a__flush_wback_region((void *)start, end-start);
+#endif
+
local_irq_save(flags);
jump_to_uncached();
- for (v = start; v < end; v+=L1_CACHE_BYTES) {
- unsigned long addr = (v & 0x000007f0);
- int way;
- /* O-Cache writeback */
- for (way = 0; way < 4; way++) {
- unsigned long data = __raw_readl(CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
- if ((data & CACHE_PHYSADDR_MASK) = (v & CACHE_PHYSADDR_MASK)) {
- data &= ~SH_CACHE_UPDATED;
- __raw_writel(data, CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));
- }
- }
- /* I-Cache invalidate */
- __raw_writel(addr,
- CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);
+ /* I-Cache invalidate */
+ /* If there are too many pages then just blow the cache */
+ if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
+ __raw_writel(__raw_readl(CCR) | CCR_ICACHE_INVALIDATE, CCR);
+ } else {
+ for (v = start; v < end; v += L1_CACHE_BYTES)
+ sh2a_invalidate_line(CACHE_IC_ADDRESS_ARRAY, v);
}
back_to_cached();
--
1.7.0.4
^ permalink raw reply related
* Re: [RFC][PATCH 1/3] dmaengine: shdma: add .no_error_irq flag
From: Shimoda, Yoshihiro @ 2012-01-10 0:47 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4F0537F2.4080306@renesas.com>
2012/01/09 11:00, Paul Mundt wrote:
> On Fri, Jan 06, 2012 at 01:00:25PM +0900, Shimoda, Yoshihiro wrote:
>> -------
>> Subject: [PATCH] dmaengine: shdma: modify the DMAC Address Error registration
>>
>> The USB-DMAC/SUDMAC don't have the interrupt of DMAC Address Error.
>> So, only when the resource has a name and it is "error_irq", the driver
>> calls request_irq() for DMAC Address Error.
>>
>> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
>
> If we're going to do this it would be nice to adopt the same behaviour
> for the generic DMAE IRQ, too (then we can finally get rid of those silly
> CPU_SH4 || ARCH_SHMOBILE ifdefs).
>
> This approach looks like an improvement to me at least.
>
Thank you very much for your comment.
I will get rid of the "CPU_SH4 || ARCH_SHMOBILE" ifdefs.
Best regards,
Yoshihiro Shimoda
^ permalink raw reply
* [PATCH v2 1/3] dmaengine: shdma: modify the DMAC Address Error
From: Shimoda, Yoshihiro @ 2012-01-10 5:20 UTC (permalink / raw)
To: linux-sh
The USB-DMAC/SUDMAC don't have the interrupt of DMAC Address Error.
So, only when the resource has a name and it is "error_irq", the driver
calls request_irq() for DMAC Address Error.
This patch is also useful for the generic DMAC which doesn't have
DMAC Address Error. So, we can get rid of the "CPU_SH4 || ARCH_SHMOBILE"
ifdefs.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
about v2:
- use a resource name for the registration.
- rid of the "CPU_SH4 || ARCH_SHMOBILE" ifdefs.
drivers/dma/shdma.c | 74 ++++++++++++++++++++++++++------------------------
1 files changed, 38 insertions(+), 36 deletions(-)
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 81809c2..4fff02b 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -1151,10 +1151,10 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
unsigned long irqflags = IRQF_DISABLED,
chan_flag[SH_DMAC_MAX_CHANNELS] = {};
- int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
+ int errirq = 0, chan_irq[SH_DMAC_MAX_CHANNELS];
int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0;
struct sh_dmae_device *shdev;
- struct resource *chan, *dmars, *errirq_res, *chanirq_res;
+ struct resource *chan, *dmars, *errirq_res, *irq_res, *chanirq_res;
/* get platform data */
if (!pdata || !pdata->channel_num)
@@ -1179,8 +1179,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
* specify IORESOURCE_IRQ_SHAREABLE in their resources, they will be
* requested with the IRQF_SHARED flag
*/
- errirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!chan || !errirq_res)
+ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!chan || !irq_res)
return -ENODEV;
if (!request_mem_region(chan->start, resource_size(chan), pdev->name)) {
@@ -1258,33 +1258,35 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
/* Default transfer size of 32 bytes requires 32-byte alignment */
shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
- chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-
- if (!chanirq_res)
- chanirq_res = errirq_res;
- else
- irqres++;
-
- if (chanirq_res = errirq_res ||
- (errirq_res->flags & IORESOURCE_BITS) = IORESOURCE_IRQ_SHAREABLE)
- irqflags = IRQF_SHARED;
-
- errirq = errirq_res->start;
-
- err = request_irq(errirq, sh_dmae_err, irqflags,
- "DMAC Address Error", shdev);
- if (err) {
- dev_err(&pdev->dev,
- "DMA failed requesting irq #%d, error %d\n",
- errirq, err);
- goto eirq_err;
+ errirq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+ "error_irq");
+ if (errirq_res) {
+ chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+
+ if (!chanirq_res)
+ chanirq_res = errirq_res;
+ else
+ irqres++;
+
+ if (chanirq_res = errirq_res ||
+ (errirq_res->flags & IORESOURCE_BITS) =
+ IORESOURCE_IRQ_SHAREABLE)
+ irqflags = IRQF_SHARED;
+
+ errirq = errirq_res->start;
+
+ err = request_irq(errirq, sh_dmae_err, irqflags,
+ "DMAC Address Error", shdev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "DMA failed requesting irq #%d, error %d\n",
+ errirq, err);
+ goto eirq_err;
+ }
+ } else {
+ chanirq_res = irq_res;
}
-#else
- chanirq_res = errirq_res;
-#endif /* CONFIG_CPU_SH4 || CONFIG_ARCH_SHMOBILE */
-
if (chanirq_res->start = chanirq_res->end &&
!platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
/* Special case - all multiplexed */
@@ -1305,7 +1307,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
break;
}
- if ((errirq_res->flags & IORESOURCE_BITS) =
+ if ((irq_res->flags & IORESOURCE_BITS) =
IORESOURCE_IRQ_SHAREABLE)
chan_flag[irq_cnt] = IRQF_SHARED;
else
@@ -1345,10 +1347,9 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
chan_probe_err:
sh_dmae_chan_remove(shdev);
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
- free_irq(errirq, shdev);
+ if (errirq_res)
+ free_irq(errirq, shdev);
eirq_err:
-#endif
rst_err:
spin_lock_irq(&sh_dmae_lock);
list_del_rcu(&shdev->node);
@@ -1379,12 +1380,13 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
{
struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
struct resource *res;
- int errirq = platform_get_irq(pdev, 0);
+ struct resource *errirq_res = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "error_irq");
dma_async_device_unregister(&shdev->common);
- if (errirq > 0)
- free_irq(errirq, shdev);
+ if (errirq_res)
+ free_irq(errirq_res->start, shdev);
spin_lock_irq(&sh_dmae_lock);
list_del_rcu(&shdev->node);
--
1.7.1
^ permalink raw reply related
* [PATCH v2 2/3] dmaengine: shdma: use sh_dmae_writel/readl in
From: Shimoda, Yoshihiro @ 2012-01-10 5:20 UTC (permalink / raw)
To: linux-sh
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
about v2
- No change
drivers/dma/shdma.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 4fff02b..ccc3028 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -92,14 +92,14 @@ static void chcr_write(struct sh_dmae_chan *sh_dc, u32 data)
{
struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
- __raw_writel(data, sh_dc->base + shdev->chcr_offset / sizeof(u32));
+ sh_dmae_writel(sh_dc, data, shdev->chcr_offset);
}
static u32 chcr_read(struct sh_dmae_chan *sh_dc)
{
struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
- return __raw_readl(sh_dc->base + shdev->chcr_offset / sizeof(u32));
+ return sh_dmae_readl(sh_dc, shdev->chcr_offset);
}
/*
--
1.7.1
^ permalink raw reply related
* [PATCH v2 3/3] dmaengine: shdma: add support for SUDMAC
From: Shimoda, Yoshihiro @ 2012-01-10 5:20 UTC (permalink / raw)
To: linux-sh
The SH7757's USB module has SUDMAC. The SUDMAC's registers are imcompatible
with SH DMAC. However, since the SUDMAC is a very simple module, we can
reuse the shdma driver for SUDMAC by a few modification.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
about v2
- a minor change by "modify the DMAC Address Error registration"
drivers/dma/shdma.c | 102 +++++++++++++++++++++++++++++++++++++++++++-----
include/linux/sh_dma.h | 46 +++++++++++++++++++++
2 files changed, 138 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index ccc3028..7daed8d 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -58,6 +58,11 @@ static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
+static int sh_dmae_is_sudmac(struct sh_dmae_device *shdev)
+{
+ return shdev->pdata->sudmac;
+}
+
static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
{
__raw_writel(data, sh_dc->base + reg / sizeof(u32));
@@ -68,6 +73,39 @@ static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
return __raw_readl(sh_dc->base + reg / sizeof(u32));
}
+static void sh_dmae_sudmac_chcr_write(struct sh_dmae_chan *sh_dc, u32 data)
+{
+ struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+
+ if (!(data & CHCR_TE)) /* clear interrupt status only */
+ sh_dmae_writel(sh_dc, CH0ENDC, DINTSTSCLR);
+
+ if (data & shdev->chcr_ie_bit)
+ sh_dmae_writel(sh_dc, CH0ENDE, DINTCTRL);
+ else
+ sh_dmae_writel(sh_dc, 0, DINTCTRL);
+
+ if (data & CHCR_DE)
+ sh_dmae_writel(sh_dc, DEN, CH0DEN);
+ else
+ sh_dmae_writel(sh_dc, 0, CH0DEN);
+}
+
+static u32 sh_dmae_sudmac_chcr_read(struct sh_dmae_chan *sh_dc)
+{
+ struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+ u32 chcr = 0;
+
+ if (sh_dmae_readl(sh_dc, DINTSTS) & CH0ENDS)
+ chcr |= CHCR_TE;
+ if (sh_dmae_readl(sh_dc, DINTCTRL) & CH0ENDE)
+ chcr |= shdev->chcr_ie_bit;
+ if (sh_dmae_readl(sh_dc, CH0DEN) & DEN)
+ chcr |= CHCR_DE;
+
+ return chcr;
+}
+
static u16 dmaor_read(struct sh_dmae_device *shdev)
{
u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32);
@@ -92,14 +130,20 @@ static void chcr_write(struct sh_dmae_chan *sh_dc, u32 data)
{
struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
- sh_dmae_writel(sh_dc, data, shdev->chcr_offset);
+ if (sh_dmae_is_sudmac(shdev))
+ sh_dmae_sudmac_chcr_write(sh_dc, data);
+ else
+ sh_dmae_writel(sh_dc, data, shdev->chcr_offset);
}
static u32 chcr_read(struct sh_dmae_chan *sh_dc)
{
struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
- return sh_dmae_readl(sh_dc, shdev->chcr_offset);
+ if (sh_dmae_is_sudmac(shdev))
+ return sh_dmae_sudmac_chcr_read(sh_dc);
+ else
+ return sh_dmae_readl(sh_dc, shdev->chcr_offset);
}
/*
@@ -112,6 +156,9 @@ static void sh_dmae_ctl_stop(struct sh_dmae_device *shdev)
unsigned short dmaor;
unsigned long flags;
+ if (sh_dmae_is_sudmac(shdev))
+ return;
+
spin_lock_irqsave(&sh_dmae_lock, flags);
dmaor = dmaor_read(shdev);
@@ -125,6 +172,9 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
unsigned short dmaor;
unsigned long flags;
+ if (sh_dmae_is_sudmac(shdev))
+ return 0;
+
spin_lock_irqsave(&sh_dmae_lock, flags);
dmaor = dmaor_read(shdev) & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME);
@@ -159,6 +209,9 @@ static unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan, u32 chcr)
int cnt = ((chcr & pdata->ts_low_mask) >> pdata->ts_low_shift) |
((chcr & pdata->ts_high_mask) >> pdata->ts_high_shift);
+ if (sh_dmae_is_sudmac(shdev))
+ return 0;
+
if (cnt >= pdata->ts_shift_num)
cnt = 0;
@@ -171,6 +224,9 @@ static u32 log2size_to_chcr(struct sh_dmae_chan *sh_chan, int l2size)
struct sh_dmae_pdata *pdata = shdev->pdata;
int i;
+ if (sh_dmae_is_sudmac(shdev))
+ return 0;
+
for (i = 0; i < pdata->ts_shift_num; i++)
if (pdata->ts_shift[i] = l2size)
break;
@@ -184,9 +240,17 @@ static u32 log2size_to_chcr(struct sh_dmae_chan *sh_chan, int l2size)
static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
{
- sh_dmae_writel(sh_chan, hw->sar, SAR);
- sh_dmae_writel(sh_chan, hw->dar, DAR);
- sh_dmae_writel(sh_chan, hw->tcr >> sh_chan->xmit_shift, TCR);
+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+
+ if (sh_dmae_is_sudmac(shdev)) {
+ sh_dmae_writel(sh_chan, LBA_WAIT | RCVENDM, CH0CFG);
+ sh_dmae_writel(sh_chan, hw->sar, CH0BA);
+ sh_dmae_writel(sh_chan, hw->tcr, CH0BBC);
+ } else {
+ sh_dmae_writel(sh_chan, hw->sar, SAR);
+ sh_dmae_writel(sh_chan, hw->dar, DAR);
+ sh_dmae_writel(sh_chan, hw->tcr >> sh_chan->xmit_shift, TCR);
+ }
}
static void dmae_start(struct sh_dmae_chan *sh_chan)
@@ -493,6 +557,7 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len,
struct sh_desc **first, enum dma_data_direction direction)
{
+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
struct sh_desc *new;
size_t copy_size;
@@ -508,7 +573,14 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
copy_size = min(*len, (size_t)SH_DMA_TCR_MAX + 1);
- new->hw.sar = *src;
+ /*
+ * SUDMAC has a CHnBA register only. So, the driver uses "hw.sar"
+ * even if transfer direction is DMA_FROM_DEVICE.
+ */
+ if (sh_dmae_is_sudmac(shdev) && direction = DMA_FROM_DEVICE)
+ new->hw.sar = *dest;
+ else
+ new->hw.sar = *src;
new->hw.dar = *dest;
new->hw.tcr = copy_size;
@@ -701,8 +773,10 @@ static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
/* Record partial transfer */
struct sh_desc *desc = list_entry(sh_chan->ld_queue.next,
struct sh_desc, node);
- desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
- sh_chan->xmit_shift;
+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+ if (!sh_dmae_is_sudmac(shdev))
+ desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan,
+ TCR)) << sh_chan->xmit_shift;
}
spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
@@ -989,9 +1063,17 @@ static irqreturn_t sh_dmae_err(int irq, void *data)
static void dmae_do_tasklet(unsigned long data)
{
struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;
+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
struct sh_desc *desc;
- u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
- u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
+ u32 sar_buf, dar_buf;
+
+ if (sh_dmae_is_sudmac(shdev)) {
+ sar_buf = sh_dmae_readl(sh_chan, CH0CA);
+ dar_buf = sh_dmae_readl(sh_chan, CH0CA);
+ } else {
+ sar_buf = sh_dmae_readl(sh_chan, SAR);
+ dar_buf = sh_dmae_readl(sh_chan, DAR);
+ }
spin_lock_irq(&sh_chan->desc_lock);
list_for_each_entry(desc, &sh_chan->ld_queue, node) {
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index cb2dd11..9997445 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -68,6 +68,7 @@ struct sh_dmae_pdata {
unsigned int dmaor_is_32bit:1;
unsigned int needs_tend_set:1;
unsigned int no_dmars:1;
+ unsigned int sudmac:1;
};
/* DMA register */
@@ -107,4 +108,49 @@ struct sh_dmae_pdata {
#define CHCR_TE 0x00000002
#define CHCR_IE 0x00000004
+/* SUDMAC register */
+#define CH0CFG 0x00
+#define CH1CFG 0x04
+#define CH0BA 0x10
+#define CH1BA 0x14
+#define CH0BBC 0x18
+#define CH1BBC 0x1C
+#define CH0CA 0x20
+#define CH1CA 0x24
+#define CH0CBC 0x28
+#define CH1CBC 0x2C
+#define CH0DEN 0x30
+#define CH1DEN 0x34
+#define DSTSCLR 0x38
+#define DBUFCTRL 0x3C
+#define DINTCTRL 0x40
+#define DINTSTS 0x44
+#define DINTSTSCLR 0x48
+#define CH0SHCTRL 0x50
+#define CH1SHCTRL 0x54
+
+/* Definitions for the SUDMAC */
+#define SENDBUFM 0x1000 /* b12: Transmit Buffer Mode */
+#define RCVENDM 0x0100 /* b8: Receive Data Transfer End Mode */
+#define LBA_WAIT 0x0030 /* b5-4: Local Bus Access Wait */
+#define DEN 0x0001 /* b0: DMA Transfer Enable */
+#define CH1STCLR 0x0002 /* b1: Ch1 DMA Status Clear */
+#define CH0STCLR 0x0001 /* b0: Ch0 DMA Status Clear */
+#define CH1BUFW 0x0200 /* b9: Ch1 DMA Buffer Data Transfer Enable */
+#define CH0BUFW 0x0100 /* b8: Ch0 DMA Buffer Data Transfer Enable */
+#define CH1BUFS 0x0002 /* b1: Ch1 DMA Buffer Data Status */
+#define CH0BUFS 0x0001 /* b0: Ch0 DMA Buffer Data Status */
+#define CH1ERRE 0x0200 /* b9: Ch1 SHwy Res Err Detect Int Enable */
+#define CH0ERRE 0x0100 /* b8: Ch0 SHwy Res Err Detect Int Enable */
+#define CH1ENDE 0x0002 /* b1: Ch1 DMA Transfer End Int Enable */
+#define CH0ENDE 0x0001 /* b0: Ch0 DMA Transfer End Int Enable */
+#define CH1ERRS 0x0200 /* b9: Ch1 SHwy Res Err Detect Int Status */
+#define CH0ERRS 0x0100 /* b8: Ch0 SHwy Res Err Detect Int Status */
+#define CH1ENDS 0x0002 /* b1: Ch1 DMA Transfer End Int Status */
+#define CH0ENDS 0x0001 /* b0: Ch0 DMA Transfer End Int Status */
+#define CH1ERRC 0x0200 /* b9: Ch1 SHwy Res Err Detect Int Stat Clear */
+#define CH0ERRC 0x0100 /* b8: Ch0 SHwy Res Err Detect Int Stat Clear */
+#define CH1ENDC 0x0002 /* b1: Ch1 DMA Transfer End Int Stat Clear */
+#define CH0ENDC 0x0001 /* b0: Ch0 DMA Transfer End Int Stat Clear */
+
#endif
--
1.7.1
^ permalink raw reply related
* [PATCH v2 1/3] sh: add a resource name for shdma
From: Shimoda, Yoshihiro @ 2012-01-10 5:20 UTC (permalink / raw)
To: linux-sh
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
about v2:
- This patch is the first version, but I named v2
- for a modification of shdma driver
arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 2 +-
arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 4 ++--
arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 7 ++++---
arch/sh/kernel/cpu/sh4a/setup-sh7780.c | 2 ++
arch/sh/kernel/cpu/sh4a/setup-sh7785.c | 2 ++
arch/sh/kernel/cpu/sh4a/setup-sh7786.c | 2 +-
6 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 278a0e5..27af277 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -146,7 +146,7 @@ static struct resource sh7722_dmae_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error IRQ */
+ .name = "error_irq",
.start = 78,
.end = 78,
.flags = IORESOURCE_IRQ,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index a37dd72..8d8a551 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -214,7 +214,7 @@ static struct resource sh7724_dmae0_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error IRQ */
+ .name = "error_irq",
.start = 78,
.end = 78,
.flags = IORESOURCE_IRQ,
@@ -248,7 +248,7 @@ static struct resource sh7724_dmae1_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error IRQ */
+ .name = "error_irq",
.start = 74,
.end = 74,
.flags = IORESOURCE_IRQ,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index 0555929..a7b2da6 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -465,6 +465,7 @@ static struct resource sh7757_dmae0_resources[] = {
.flags = IORESOURCE_MEM,
},
{
+ .name = "error_irq",
.start = 34,
.end = 34,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
@@ -486,7 +487,7 @@ static struct resource sh7757_dmae1_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error */
+ .name = "error_irq",
.start = 34,
.end = 34,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
@@ -556,7 +557,7 @@ static struct resource sh7757_dmae2_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error */
+ .name = "error_irq",
.start = 323,
.end = 323,
.flags = IORESOURCE_IRQ,
@@ -590,7 +591,7 @@ static struct resource sh7757_dmae3_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error */
+ .name = "error_irq",
.start = 324,
.end = 324,
.flags = IORESOURCE_IRQ,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index 3d4d207..d431b00 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -322,6 +322,7 @@ static struct resource sh7780_dmae0_resources[] = {
},
{
/* Real DMA error IRQ is 38, and channel IRQs are 34-37, 44-45 */
+ .name = "error_irq",
.start = 34,
.end = 34,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
@@ -338,6 +339,7 @@ static struct resource sh7780_dmae1_resources[] = {
/* DMAC1 has no DMARS */
{
/* Real DMA error IRQ is 38, and channel IRQs are 46-47, 92-95 */
+ .name = "error_irq",
.start = 46,
.end = 46,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index b29e634..81588ef 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -376,6 +376,7 @@ static struct resource sh7785_dmae0_resources[] = {
},
{
/* Real DMA error IRQ is 39, and channel IRQs are 33-38 */
+ .name = "error_irq",
.start = 33,
.end = 33,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
@@ -392,6 +393,7 @@ static struct resource sh7785_dmae1_resources[] = {
/* DMAC1 has no DMARS */
{
/* Real DMA error IRQ is 58, and channel IRQs are 52-57 */
+ .name = "error_irq",
.start = 52,
.end = 52,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
index dd5e709..599022d 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -518,7 +518,7 @@ static struct resource dmac0_resources[] = {
.end = 0xfe00900b,
.flags = IORESOURCE_MEM,
}, {
- /* DMA error IRQ */
+ .name = "error_irq",
.start = evt2irq(0x5c0),
.end = evt2irq(0x5c0),
.flags = IORESOURCE_IRQ,
--
1.7.1
^ permalink raw reply related
* [PATCH v2 2/3] sh: add platform_device for SUDMAC in setup-sh7757
From: Shimoda, Yoshihiro @ 2012-01-10 5:21 UTC (permalink / raw)
To: linux-sh
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
about v2:
- No need the .no_error_irq flag.
arch/sh/include/cpu-sh4/cpu/sh7757.h | 1 +
arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 49 ++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7757.h b/arch/sh/include/cpu-sh4/cpu/sh7757.h
index 41f9f8b..f9be40a 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7757.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7757.h
@@ -283,5 +283,6 @@ enum {
SHDMA_SLAVE_RIIC8_RX,
SHDMA_SLAVE_RIIC9_TX,
SHDMA_SLAVE_RIIC9_RX,
+ SHDMA_SLAVE_SUDMAC00,
};
#endif /* __ASM_SH7757_H__ */
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index a7b2da6..bb9324a 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -650,6 +650,54 @@ static struct platform_device dma3_device = {
},
};
+/* SUDMAC */
+static const struct sh_dmae_channel sh7757_sudmac_channel[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }
+};
+
+static const struct sh_dmae_slave_config sh7757_sudmac00_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_SUDMAC00,
+ .addr = 0xfe451000,
+ },
+};
+
+static struct sh_dmae_pdata sudmac00_platform_data = {
+ .slave = sh7757_sudmac00_slaves,
+ .slave_num = ARRAY_SIZE(sh7757_sudmac00_slaves),
+ .channel = sh7757_sudmac_channel,
+ .channel_num = 1,
+ .no_dmars = 1,
+ .sudmac = 1,
+};
+
+static struct resource sh7757_sudmac00_resources[] = {
+ [0] = {
+ .start = 0xfe451000,
+ .end = 0xfe451000,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 50,
+ .end = 50,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+static struct platform_device sudmac00_device = {
+ .name = "sh-dma-engine",
+ .id = 4,
+ .resource = sh7757_sudmac00_resources,
+ .num_resources = ARRAY_SIZE(sh7757_sudmac00_resources),
+ .dev = {
+ .platform_data = &sudmac00_platform_data,
+ },
+};
+
static struct platform_device spi0_device = {
.name = "sh_spi",
.id = 0,
@@ -719,6 +767,7 @@ static struct platform_device *sh7757_devices[] __initdata = {
&dma1_device,
&dma2_device,
&dma3_device,
+ &sudmac00_device,
&spi0_device,
&usb_ehci_device,
&usb_ohci_device,
--
1.7.1
^ permalink raw reply related
* [PATCH v2 3/3] sh: enable the SUDMAC of renesas_usbhs in
From: Shimoda, Yoshihiro @ 2012-01-10 5:21 UTC (permalink / raw)
To: linux-sh
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
about v2:
- No change
arch/sh/boards/board-sh7757lcr.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c
index 0838154..40872e8 100644
--- a/arch/sh/boards/board-sh7757lcr.c
+++ b/arch/sh/boards/board-sh7757lcr.c
@@ -276,6 +276,8 @@ static struct renesas_usbhs_platform_info usb0_data = {
},
.driver_param = {
.buswait_bwait = 5,
+ .d0_tx_id = SHDMA_SLAVE_SUDMAC00,
+ .has_sudmac = 1,
}
};
@@ -288,7 +290,7 @@ static struct resource usb0_resources[] = {
[1] = {
.start = 50,
.end = 50,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
};
--
1.7.1
^ permalink raw reply related
* [PATCH] arm: mach-shmobile: add a resource name for shdma
From: Shimoda, Yoshihiro @ 2012-01-10 5:21 UTC (permalink / raw)
To: linux-sh
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
This patch depends on the following patch:
- dmaengine: shdma: modify the DMAC Address Error registration
arch/arm/mach-shmobile/setup-sh7372.c | 6 +++---
arch/arm/mach-shmobile/setup-sh73a0.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 2380389..dad4d09 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -504,7 +504,7 @@ static struct resource sh7372_dmae0_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error IRQ */
+ .name = "error_irq",
.start = evt2irq(0x20c0),
.end = evt2irq(0x20c0),
.flags = IORESOURCE_IRQ,
@@ -532,7 +532,7 @@ static struct resource sh7372_dmae1_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error IRQ */
+ .name = "error_irq",
.start = evt2irq(0x21c0),
.end = evt2irq(0x21c0),
.flags = IORESOURCE_IRQ,
@@ -560,7 +560,7 @@ static struct resource sh7372_dmae2_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error IRQ */
+ .name = "error_irq",
.start = evt2irq(0x22c0),
.end = evt2irq(0x22c0),
.flags = IORESOURCE_IRQ,
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index e46821c..20e71e5 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -607,7 +607,7 @@ static struct resource sh73a0_dmae_resources[] = {
.flags = IORESOURCE_MEM,
},
{
- /* DMA error IRQ */
+ .name = "error_irq",
.start = gic_spi(129),
.end = gic_spi(129),
.flags = IORESOURCE_IRQ,
--
1.7.1
^ permalink raw reply related
* Re: [PATCH v2 1/3] dmaengine: shdma: modify the DMAC Address Error registration
From: Paul Mundt @ 2012-01-10 5:33 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4F0BCA90.3050508@renesas.com>
On Tue, Jan 10, 2012 at 02:20:16PM +0900, Shimoda, Yoshihiro wrote:
> + if (chanirq_res = errirq_res ||
> + (errirq_res->flags & IORESOURCE_BITS) =
> + IORESOURCE_IRQ_SHAREABLE)
> + irqflags = IRQF_SHARED;
> +
While not your fault, it seems that there are a few of these cases in
which the irqflags are clobbered rather than added to. Is there some
particular reason why we aren't doing |= IRQF_SHARED on top of the
default IRQF_DISABLED case?
^ permalink raw reply
* Re: [PATCH v2 1/3] dmaengine: shdma: modify the DMAC Address Error
From: Shimoda, Yoshihiro @ 2012-01-10 5:56 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4F0BCA90.3050508@renesas.com>
2012/01/10 14:33, Paul Mundt wrote:
> On Tue, Jan 10, 2012 at 02:20:16PM +0900, Shimoda, Yoshihiro wrote:
>> + if (chanirq_res = errirq_res ||
>> + (errirq_res->flags & IORESOURCE_BITS) =
>> + IORESOURCE_IRQ_SHAREABLE)
>> + irqflags = IRQF_SHARED;
>> +
> While not your fault, it seems that there are a few of these cases in
> which the irqflags are clobbered rather than added to. Is there some
> particular reason why we aren't doing |= IRQF_SHARED on top of the
> default IRQF_DISABLED case?
>
I guess that old kernel (before the commit of 6932bf37 "genirq: Remove IRQF_DISABLED from
core code") output some warning in request_irq() when irqflags is set to
"IRQF_DISABLED | IRQF_SHARED".
By the way, according to the "feature-removal-schedule.txt", the IRQF_DISABLED will remove.
So, we can remove the IRQF_DISABLED in the shdma driver, I think.
Best regards,
Yoshihiro Shimoda
^ permalink raw reply
* Re: [PATCH v2 1/3] dmaengine: shdma: modify the DMAC Address Error registration
From: Paul Mundt @ 2012-01-10 6:01 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4F0BCA90.3050508@renesas.com>
On Tue, Jan 10, 2012 at 02:56:33PM +0900, Shimoda, Yoshihiro wrote:
> 2012/01/10 14:33, Paul Mundt wrote:
> > On Tue, Jan 10, 2012 at 02:20:16PM +0900, Shimoda, Yoshihiro wrote:
> >> + if (chanirq_res = errirq_res ||
> >> + (errirq_res->flags & IORESOURCE_BITS) =
> >> + IORESOURCE_IRQ_SHAREABLE)
> >> + irqflags = IRQF_SHARED;
> >> +
> > While not your fault, it seems that there are a few of these cases in
> > which the irqflags are clobbered rather than added to. Is there some
> > particular reason why we aren't doing |= IRQF_SHARED on top of the
> > default IRQF_DISABLED case?
> >
>
> I guess that old kernel (before the commit of 6932bf37 "genirq: Remove IRQF_DISABLED from
> core code") output some warning in request_irq() when irqflags is set to
> "IRQF_DISABLED | IRQF_SHARED".
>
> By the way, according to the "feature-removal-schedule.txt", the IRQF_DISABLED will remove.
> So, we can remove the IRQF_DISABLED in the shdma driver, I think.
>
Yes, it's deprecated now, so there's no need to keep it around. The
non-shared case can just be 0.
^ permalink raw reply
* Re: [PATCH v2 1/3] dmaengine: shdma: modify the DMAC Address Error
From: Shimoda, Yoshihiro @ 2012-01-10 6:19 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4F0BCA90.3050508@renesas.com>
2012/01/10 15:01, Paul Mundt wrote:
> On Tue, Jan 10, 2012 at 02:56:33PM +0900, Shimoda, Yoshihiro wrote:
>> 2012/01/10 14:33, Paul Mundt wrote:
>>> On Tue, Jan 10, 2012 at 02:20:16PM +0900, Shimoda, Yoshihiro wrote:
>>>> + if (chanirq_res = errirq_res ||
>>>> + (errirq_res->flags & IORESOURCE_BITS) =
>>>> + IORESOURCE_IRQ_SHAREABLE)
>>>> + irqflags = IRQF_SHARED;
>>>> +
>>> While not your fault, it seems that there are a few of these cases in
>>> which the irqflags are clobbered rather than added to. Is there some
>>> particular reason why we aren't doing |= IRQF_SHARED on top of the
>>> default IRQF_DISABLED case?
>>>
>>
>> I guess that old kernel (before the commit of 6932bf37 "genirq: Remove IRQF_DISABLED from
>> core code") output some warning in request_irq() when irqflags is set to
>> "IRQF_DISABLED | IRQF_SHARED".
>>
>> By the way, according to the "feature-removal-schedule.txt", the IRQF_DISABLED will remove.
>> So, we can remove the IRQF_DISABLED in the shdma driver, I think.
>>
> Yes, it's deprecated now, so there's no need to keep it around. The
> non-shared case can just be 0.
>
OK, I will modify the patch and submit it again.
Best regards,
Yoshihiro Shimoda
^ permalink raw reply
* [PATCH v3 1/3] dmaengine: shdma: modify the DMAC Address Error
From: Shimoda, Yoshihiro @ 2012-01-10 6:38 UTC (permalink / raw)
To: linux-sh
The USB-DMAC/SUDMAC don't have the interrupt of DMAC Address Error.
So, only when the resource has a name and it is "error_irq", the driver
calls request_irq() for DMAC Address Error.
This patch is also useful for the generic DMAC which doesn't have
DMAC Address Error. So, we can get rid of the "CPU_SH4 || ARCH_SHMOBILE"
ifdefs.
This patch also changes the IRQF_DISABLED to 0.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
about v3:
- changes the IRQF_DISABLED to 0.
drivers/dma/shdma.c | 78 ++++++++++++++++++++++++++-------------------------
1 files changed, 40 insertions(+), 38 deletions(-)
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 81809c2..55149ed 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -1149,12 +1149,12 @@ static void sh_dmae_chan_remove(struct sh_dmae_device *shdev)
static int __init sh_dmae_probe(struct platform_device *pdev)
{
struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
- unsigned long irqflags = IRQF_DISABLED,
+ unsigned long irqflags = 0,
chan_flag[SH_DMAC_MAX_CHANNELS] = {};
- int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
+ int errirq = 0, chan_irq[SH_DMAC_MAX_CHANNELS];
int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0;
struct sh_dmae_device *shdev;
- struct resource *chan, *dmars, *errirq_res, *chanirq_res;
+ struct resource *chan, *dmars, *errirq_res, *irq_res, *chanirq_res;
/* get platform data */
if (!pdata || !pdata->channel_num)
@@ -1179,8 +1179,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
* specify IORESOURCE_IRQ_SHAREABLE in their resources, they will be
* requested with the IRQF_SHARED flag
*/
- errirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!chan || !errirq_res)
+ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!chan || !irq_res)
return -ENODEV;
if (!request_mem_region(chan->start, resource_size(chan), pdev->name)) {
@@ -1258,33 +1258,35 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
/* Default transfer size of 32 bytes requires 32-byte alignment */
shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
- chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-
- if (!chanirq_res)
- chanirq_res = errirq_res;
- else
- irqres++;
-
- if (chanirq_res = errirq_res ||
- (errirq_res->flags & IORESOURCE_BITS) = IORESOURCE_IRQ_SHAREABLE)
- irqflags = IRQF_SHARED;
-
- errirq = errirq_res->start;
-
- err = request_irq(errirq, sh_dmae_err, irqflags,
- "DMAC Address Error", shdev);
- if (err) {
- dev_err(&pdev->dev,
- "DMA failed requesting irq #%d, error %d\n",
- errirq, err);
- goto eirq_err;
+ errirq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+ "error_irq");
+ if (errirq_res) {
+ chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+
+ if (!chanirq_res)
+ chanirq_res = errirq_res;
+ else
+ irqres++;
+
+ if (chanirq_res = errirq_res ||
+ (errirq_res->flags & IORESOURCE_BITS) =
+ IORESOURCE_IRQ_SHAREABLE)
+ irqflags = IRQF_SHARED;
+
+ errirq = errirq_res->start;
+
+ err = request_irq(errirq, sh_dmae_err, irqflags,
+ "DMAC Address Error", shdev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "DMA failed requesting irq #%d, error %d\n",
+ errirq, err);
+ goto eirq_err;
+ }
+ } else {
+ chanirq_res = irq_res;
}
-#else
- chanirq_res = errirq_res;
-#endif /* CONFIG_CPU_SH4 || CONFIG_ARCH_SHMOBILE */
-
if (chanirq_res->start = chanirq_res->end &&
!platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
/* Special case - all multiplexed */
@@ -1305,11 +1307,11 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
break;
}
- if ((errirq_res->flags & IORESOURCE_BITS) =
+ if ((irq_res->flags & IORESOURCE_BITS) =
IORESOURCE_IRQ_SHAREABLE)
chan_flag[irq_cnt] = IRQF_SHARED;
else
- chan_flag[irq_cnt] = IRQF_DISABLED;
+ chan_flag[irq_cnt] = 0;
dev_dbg(&pdev->dev,
"Found IRQ %d for channel %d\n",
i, irq_cnt);
@@ -1345,10 +1347,9 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
chan_probe_err:
sh_dmae_chan_remove(shdev);
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
- free_irq(errirq, shdev);
+ if (errirq_res)
+ free_irq(errirq, shdev);
eirq_err:
-#endif
rst_err:
spin_lock_irq(&sh_dmae_lock);
list_del_rcu(&shdev->node);
@@ -1379,12 +1380,13 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
{
struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
struct resource *res;
- int errirq = platform_get_irq(pdev, 0);
+ struct resource *errirq_res = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "error_irq");
dma_async_device_unregister(&shdev->common);
- if (errirq > 0)
- free_irq(errirq, shdev);
+ if (errirq_res)
+ free_irq(errirq_res->start, shdev);
spin_lock_irq(&sh_dmae_lock);
list_del_rcu(&shdev->node);
--
1.7.1
^ permalink raw reply related
* [PATCH v3 2/3] dmaengine: shdma: use sh_dmae_writel/readl in
From: Shimoda, Yoshihiro @ 2012-01-10 6:38 UTC (permalink / raw)
To: linux-sh
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
about v3:
- No change
drivers/dma/shdma.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 55149ed..4e0ddd6 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -92,14 +92,14 @@ static void chcr_write(struct sh_dmae_chan *sh_dc, u32 data)
{
struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
- __raw_writel(data, sh_dc->base + shdev->chcr_offset / sizeof(u32));
+ sh_dmae_writel(sh_dc, data, shdev->chcr_offset);
}
static u32 chcr_read(struct sh_dmae_chan *sh_dc)
{
struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
- return __raw_readl(sh_dc->base + shdev->chcr_offset / sizeof(u32));
+ return sh_dmae_readl(sh_dc, shdev->chcr_offset);
}
/*
--
1.7.1
^ permalink raw reply related
* [PATCH v3 3/3] dmaengine: shdma: add support for SUDMAC
From: Shimoda, Yoshihiro @ 2012-01-10 6:38 UTC (permalink / raw)
To: linux-sh
The SH7757's USB module has SUDMAC. The SUDMAC's registers are imcompatible
with SH DMAC. However, since the SUDMAC is a very simple module, we can
reuse the shdma driver for SUDMAC by a few modification.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
about v3:
- No change
drivers/dma/shdma.c | 102 +++++++++++++++++++++++++++++++++++++++++++-----
include/linux/sh_dma.h | 46 +++++++++++++++++++++
2 files changed, 138 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 4e0ddd6..4ca8921 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -58,6 +58,11 @@ static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
+static int sh_dmae_is_sudmac(struct sh_dmae_device *shdev)
+{
+ return shdev->pdata->sudmac;
+}
+
static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
{
__raw_writel(data, sh_dc->base + reg / sizeof(u32));
@@ -68,6 +73,39 @@ static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
return __raw_readl(sh_dc->base + reg / sizeof(u32));
}
+static void sh_dmae_sudmac_chcr_write(struct sh_dmae_chan *sh_dc, u32 data)
+{
+ struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+
+ if (!(data & CHCR_TE)) /* clear interrupt status only */
+ sh_dmae_writel(sh_dc, CH0ENDC, DINTSTSCLR);
+
+ if (data & shdev->chcr_ie_bit)
+ sh_dmae_writel(sh_dc, CH0ENDE, DINTCTRL);
+ else
+ sh_dmae_writel(sh_dc, 0, DINTCTRL);
+
+ if (data & CHCR_DE)
+ sh_dmae_writel(sh_dc, DEN, CH0DEN);
+ else
+ sh_dmae_writel(sh_dc, 0, CH0DEN);
+}
+
+static u32 sh_dmae_sudmac_chcr_read(struct sh_dmae_chan *sh_dc)
+{
+ struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+ u32 chcr = 0;
+
+ if (sh_dmae_readl(sh_dc, DINTSTS) & CH0ENDS)
+ chcr |= CHCR_TE;
+ if (sh_dmae_readl(sh_dc, DINTCTRL) & CH0ENDE)
+ chcr |= shdev->chcr_ie_bit;
+ if (sh_dmae_readl(sh_dc, CH0DEN) & DEN)
+ chcr |= CHCR_DE;
+
+ return chcr;
+}
+
static u16 dmaor_read(struct sh_dmae_device *shdev)
{
u32 __iomem *addr = shdev->chan_reg + DMAOR / sizeof(u32);
@@ -92,14 +130,20 @@ static void chcr_write(struct sh_dmae_chan *sh_dc, u32 data)
{
struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
- sh_dmae_writel(sh_dc, data, shdev->chcr_offset);
+ if (sh_dmae_is_sudmac(shdev))
+ sh_dmae_sudmac_chcr_write(sh_dc, data);
+ else
+ sh_dmae_writel(sh_dc, data, shdev->chcr_offset);
}
static u32 chcr_read(struct sh_dmae_chan *sh_dc)
{
struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
- return sh_dmae_readl(sh_dc, shdev->chcr_offset);
+ if (sh_dmae_is_sudmac(shdev))
+ return sh_dmae_sudmac_chcr_read(sh_dc);
+ else
+ return sh_dmae_readl(sh_dc, shdev->chcr_offset);
}
/*
@@ -112,6 +156,9 @@ static void sh_dmae_ctl_stop(struct sh_dmae_device *shdev)
unsigned short dmaor;
unsigned long flags;
+ if (sh_dmae_is_sudmac(shdev))
+ return;
+
spin_lock_irqsave(&sh_dmae_lock, flags);
dmaor = dmaor_read(shdev);
@@ -125,6 +172,9 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
unsigned short dmaor;
unsigned long flags;
+ if (sh_dmae_is_sudmac(shdev))
+ return 0;
+
spin_lock_irqsave(&sh_dmae_lock, flags);
dmaor = dmaor_read(shdev) & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME);
@@ -159,6 +209,9 @@ static unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan, u32 chcr)
int cnt = ((chcr & pdata->ts_low_mask) >> pdata->ts_low_shift) |
((chcr & pdata->ts_high_mask) >> pdata->ts_high_shift);
+ if (sh_dmae_is_sudmac(shdev))
+ return 0;
+
if (cnt >= pdata->ts_shift_num)
cnt = 0;
@@ -171,6 +224,9 @@ static u32 log2size_to_chcr(struct sh_dmae_chan *sh_chan, int l2size)
struct sh_dmae_pdata *pdata = shdev->pdata;
int i;
+ if (sh_dmae_is_sudmac(shdev))
+ return 0;
+
for (i = 0; i < pdata->ts_shift_num; i++)
if (pdata->ts_shift[i] = l2size)
break;
@@ -184,9 +240,17 @@ static u32 log2size_to_chcr(struct sh_dmae_chan *sh_chan, int l2size)
static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
{
- sh_dmae_writel(sh_chan, hw->sar, SAR);
- sh_dmae_writel(sh_chan, hw->dar, DAR);
- sh_dmae_writel(sh_chan, hw->tcr >> sh_chan->xmit_shift, TCR);
+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+
+ if (sh_dmae_is_sudmac(shdev)) {
+ sh_dmae_writel(sh_chan, LBA_WAIT | RCVENDM, CH0CFG);
+ sh_dmae_writel(sh_chan, hw->sar, CH0BA);
+ sh_dmae_writel(sh_chan, hw->tcr, CH0BBC);
+ } else {
+ sh_dmae_writel(sh_chan, hw->sar, SAR);
+ sh_dmae_writel(sh_chan, hw->dar, DAR);
+ sh_dmae_writel(sh_chan, hw->tcr >> sh_chan->xmit_shift, TCR);
+ }
}
static void dmae_start(struct sh_dmae_chan *sh_chan)
@@ -493,6 +557,7 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len,
struct sh_desc **first, enum dma_data_direction direction)
{
+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
struct sh_desc *new;
size_t copy_size;
@@ -508,7 +573,14 @@ static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
copy_size = min(*len, (size_t)SH_DMA_TCR_MAX + 1);
- new->hw.sar = *src;
+ /*
+ * SUDMAC has a CHnBA register only. So, the driver uses "hw.sar"
+ * even if transfer direction is DMA_FROM_DEVICE.
+ */
+ if (sh_dmae_is_sudmac(shdev) && direction = DMA_FROM_DEVICE)
+ new->hw.sar = *dest;
+ else
+ new->hw.sar = *src;
new->hw.dar = *dest;
new->hw.tcr = copy_size;
@@ -701,8 +773,10 @@ static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
/* Record partial transfer */
struct sh_desc *desc = list_entry(sh_chan->ld_queue.next,
struct sh_desc, node);
- desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
- sh_chan->xmit_shift;
+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+ if (!sh_dmae_is_sudmac(shdev))
+ desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan,
+ TCR)) << sh_chan->xmit_shift;
}
spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
@@ -989,9 +1063,17 @@ static irqreturn_t sh_dmae_err(int irq, void *data)
static void dmae_do_tasklet(unsigned long data)
{
struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;
+ struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
struct sh_desc *desc;
- u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
- u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
+ u32 sar_buf, dar_buf;
+
+ if (sh_dmae_is_sudmac(shdev)) {
+ sar_buf = sh_dmae_readl(sh_chan, CH0CA);
+ dar_buf = sh_dmae_readl(sh_chan, CH0CA);
+ } else {
+ sar_buf = sh_dmae_readl(sh_chan, SAR);
+ dar_buf = sh_dmae_readl(sh_chan, DAR);
+ }
spin_lock_irq(&sh_chan->desc_lock);
list_for_each_entry(desc, &sh_chan->ld_queue, node) {
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index cb2dd11..9997445 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -68,6 +68,7 @@ struct sh_dmae_pdata {
unsigned int dmaor_is_32bit:1;
unsigned int needs_tend_set:1;
unsigned int no_dmars:1;
+ unsigned int sudmac:1;
};
/* DMA register */
@@ -107,4 +108,49 @@ struct sh_dmae_pdata {
#define CHCR_TE 0x00000002
#define CHCR_IE 0x00000004
+/* SUDMAC register */
+#define CH0CFG 0x00
+#define CH1CFG 0x04
+#define CH0BA 0x10
+#define CH1BA 0x14
+#define CH0BBC 0x18
+#define CH1BBC 0x1C
+#define CH0CA 0x20
+#define CH1CA 0x24
+#define CH0CBC 0x28
+#define CH1CBC 0x2C
+#define CH0DEN 0x30
+#define CH1DEN 0x34
+#define DSTSCLR 0x38
+#define DBUFCTRL 0x3C
+#define DINTCTRL 0x40
+#define DINTSTS 0x44
+#define DINTSTSCLR 0x48
+#define CH0SHCTRL 0x50
+#define CH1SHCTRL 0x54
+
+/* Definitions for the SUDMAC */
+#define SENDBUFM 0x1000 /* b12: Transmit Buffer Mode */
+#define RCVENDM 0x0100 /* b8: Receive Data Transfer End Mode */
+#define LBA_WAIT 0x0030 /* b5-4: Local Bus Access Wait */
+#define DEN 0x0001 /* b0: DMA Transfer Enable */
+#define CH1STCLR 0x0002 /* b1: Ch1 DMA Status Clear */
+#define CH0STCLR 0x0001 /* b0: Ch0 DMA Status Clear */
+#define CH1BUFW 0x0200 /* b9: Ch1 DMA Buffer Data Transfer Enable */
+#define CH0BUFW 0x0100 /* b8: Ch0 DMA Buffer Data Transfer Enable */
+#define CH1BUFS 0x0002 /* b1: Ch1 DMA Buffer Data Status */
+#define CH0BUFS 0x0001 /* b0: Ch0 DMA Buffer Data Status */
+#define CH1ERRE 0x0200 /* b9: Ch1 SHwy Res Err Detect Int Enable */
+#define CH0ERRE 0x0100 /* b8: Ch0 SHwy Res Err Detect Int Enable */
+#define CH1ENDE 0x0002 /* b1: Ch1 DMA Transfer End Int Enable */
+#define CH0ENDE 0x0001 /* b0: Ch0 DMA Transfer End Int Enable */
+#define CH1ERRS 0x0200 /* b9: Ch1 SHwy Res Err Detect Int Status */
+#define CH0ERRS 0x0100 /* b8: Ch0 SHwy Res Err Detect Int Status */
+#define CH1ENDS 0x0002 /* b1: Ch1 DMA Transfer End Int Status */
+#define CH0ENDS 0x0001 /* b0: Ch0 DMA Transfer End Int Status */
+#define CH1ERRC 0x0200 /* b9: Ch1 SHwy Res Err Detect Int Stat Clear */
+#define CH0ERRC 0x0100 /* b8: Ch0 SHwy Res Err Detect Int Stat Clear */
+#define CH1ENDC 0x0002 /* b1: Ch1 DMA Transfer End Int Stat Clear */
+#define CH0ENDC 0x0001 /* b0: Ch0 DMA Transfer End Int Stat Clear */
+
#endif
--
1.7.1
^ permalink raw reply related
* [PATCH] ARM: mach-shmobile: r8a7779 power domain support V2
From: Magnus Damm @ 2012-01-10 6:50 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20111222081204.12120.92511.sendpatchset@w520>
From: Magnus Damm <damm@opensource.se>
Add power domain control support for the r8a7779 SoC V2.
This adds support for 4 power domains for I/O Devices
together with code that can be used for CPU cores as well.
The only out of the ordinary experience is the need for
ioremap() of SYSC registers. Because of that we need to
execute some init function before setting up the domains.
Signed-off-by: Magnus Damm <damm@opensource.se>
---
Built on top of linux-sh git rmobile/marzen branch.
Changes since V1:
- updated to fit on top of linux-pm changes already pulled by Linus
Suitable for merge through the linux-sh git tree.
arch/arm/mach-shmobile/Makefile | 1
arch/arm/mach-shmobile/include/mach/common.h | 1
arch/arm/mach-shmobile/include/mach/r8a7779.h | 35 +++
arch/arm/mach-shmobile/pm-r8a7779.c | 235 +++++++++++++++++++++++++
arch/arm/mach-shmobile/setup-r8a7779.c | 8
5 files changed, 280 insertions(+)
--- 0001/arch/arm/mach-shmobile/Makefile
+++ work/arch/arm/mach-shmobile/Makefile 2012-01-10 15:30:18.000000000 +0900
@@ -38,6 +38,7 @@ obj-$(CONFIG_ARCH_R8A7740) += entry-intc
obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o
+obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o
# Board objects
obj-$(CONFIG_MACH_G3EVM) += board-g3evm.o
--- 0001/arch/arm/mach-shmobile/include/mach/common.h
+++ work/arch/arm/mach-shmobile/include/mach/common.h 2012-01-10 15:30:18.000000000 +0900
@@ -66,5 +66,6 @@ extern void r8a7779_add_early_devices(vo
extern void r8a7779_add_standard_devices(void);
extern void r8a7779_clock_init(void);
extern void r8a7779_pinmux_init(void);
+extern void r8a7779_pm_init(void);
#endif /* __ARCH_MACH_COMMON_H */
--- 0001/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ work/arch/arm/mach-shmobile/include/mach/r8a7779.h 2012-01-10 15:30:18.000000000 +0900
@@ -1,6 +1,9 @@
#ifndef __ASM_R8A7779_H__
#define __ASM_R8A7779_H__
+#include <linux/sh_clk.h>
+#include <linux/pm_domain.h>
+
/* Pin Function Controller:
* GPIO_FN_xx - GPIO used to select pin function
* GPIO_GP_x_x - GPIO mapped to real I/O pin on CPU
@@ -322,4 +325,36 @@ enum {
GPIO_FN_GPS_MAG, GPIO_FN_FCE, GPIO_FN_SCK4_B,
};
+struct platform_device;
+
+struct r8a7779_pm_ch {
+ unsigned long chan_offs;
+ unsigned int chan_bit;
+ unsigned int isr_bit;
+};
+
+struct r8a7779_pm_domain {
+ struct generic_pm_domain genpd;
+ struct r8a7779_pm_ch ch;
+};
+
+static inline struct r8a7779_pm_ch *to_r8a7779_ch(struct generic_pm_domain *d)
+{
+ return &container_of(d, struct r8a7779_pm_domain, genpd)->ch;
+}
+
+#ifdef CONFIG_PM
+extern struct r8a7779_pm_domain r8a7779_sh4a;
+extern struct r8a7779_pm_domain r8a7779_sgx;
+extern struct r8a7779_pm_domain r8a7779_vdp1;
+extern struct r8a7779_pm_domain r8a7779_impx3;
+
+extern void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd);
+extern void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd,
+ struct platform_device *pdev);
+#else
+#define r8a7779_init_pm_domain(pd) do { } while (0)
+#define r8a7779_add_device_to_domain(pd, pdev) do { } while (0)
+#endif /* CONFIG_PM */
+
#endif /* __ASM_R8A7779_H__ */
--- /dev/null
+++ work/arch/arm/mach-shmobile/pm-r8a7779.c 2012-01-10 15:36:24.000000000 +0900
@@ -0,0 +1,235 @@
+/*
+ * r8a7779 Power management support
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ * Copyright (C) 2011 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/err.h>
+#include <linux/pm_clock.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/console.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <mach/common.h>
+#include <mach/r8a7779.h>
+
+static void __iomem *r8a7779_sysc_base;
+
+/* SYSC */
+#define SYSCSR 0x00
+#define SYSCISR 0x04
+#define SYSCISCR 0x08
+#define SYSCIER 0x0c
+#define SYSCIMR 0x10
+#define PWRSR0 0x40
+#define PWRSR1 0x80
+#define PWRSR2 0xc0
+#define PWRSR3 0x100
+#define PWRSR4 0x140
+
+#define PWRSR_OFFS 0x00
+#define PWROFFCR_OFFS 0x04
+#define PWRONCR_OFFS 0x0c
+#define PWRER_OFFS 0x14
+
+#define SYSCSR_RETRIES 100
+#define SYSCSR_DELAY_US 1
+
+#define SYSCISR_RETRIES 1000
+#define SYSCISR_DELAY_US 1
+
+#ifdef CONFIG_PM
+
+static int r8a7779_sysc_pwr_on_off(struct r8a7779_pm_ch *r8a7779_ch,
+ int sr_bit, int reg_offs)
+{
+ int k;
+
+ for (k = 0; k < SYSCSR_RETRIES; k++) {
+ if (ioread32(r8a7779_sysc_base + SYSCSR) & (1 << sr_bit))
+ break;
+ udelay(SYSCSR_DELAY_US);
+ }
+
+ if (k = SYSCSR_RETRIES)
+ return -EAGAIN;
+
+ iowrite32(1 << r8a7779_ch->chan_bit,
+ r8a7779_sysc_base + r8a7779_ch->chan_offs + reg_offs);
+
+ return 0;
+}
+
+static int r8a7779_sysc_pwr_off(struct r8a7779_pm_ch *r8a7779_ch)
+{
+ return r8a7779_sysc_pwr_on_off(r8a7779_ch, 0, PWROFFCR_OFFS);
+}
+
+static int r8a7779_sysc_pwr_on(struct r8a7779_pm_ch *r8a7779_ch)
+{
+ return r8a7779_sysc_pwr_on_off(r8a7779_ch, 1, PWRONCR_OFFS);
+}
+
+static int r8a7779_sysc_update(struct r8a7779_pm_ch *r8a7779_ch,
+ int (*on_off_fn)(struct r8a7779_pm_ch *))
+{
+ unsigned int isr_mask = 1 << r8a7779_ch->isr_bit;
+ unsigned int chan_mask = 1 << r8a7779_ch->chan_bit;
+ unsigned int status;
+ int ret = 0;
+ int k;
+
+ iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
+
+ do {
+ ret = on_off_fn(r8a7779_ch);
+ if (ret)
+ goto out;
+
+ status = ioread32(r8a7779_sysc_base +
+ r8a7779_ch->chan_offs + PWRER_OFFS);
+ } while (status & chan_mask);
+
+ for (k = 0; k < SYSCISR_RETRIES; k++) {
+ if (ioread32(r8a7779_sysc_base + SYSCISR) & isr_mask)
+ break;
+ udelay(SYSCISR_DELAY_US);
+ }
+
+ if (k = SYSCISR_RETRIES)
+ ret = -EIO;
+
+ iowrite32(isr_mask, r8a7779_sysc_base + SYSCISCR);
+
+ out:
+ pr_debug("r8a7779 power domain %d: %02x %02x %02x %02x %02x -> %d\n",
+ r8a7779_ch->isr_bit, ioread32(r8a7779_sysc_base + PWRSR0),
+ ioread32(r8a7779_sysc_base + PWRSR1),
+ ioread32(r8a7779_sysc_base + PWRSR2),
+ ioread32(r8a7779_sysc_base + PWRSR3),
+ ioread32(r8a7779_sysc_base + PWRSR4), ret);
+ return ret;
+}
+
+static int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch)
+{
+ return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_off);
+}
+
+static int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch)
+{
+ return r8a7779_sysc_update(r8a7779_ch, r8a7779_sysc_pwr_on);
+}
+
+static void __init r8a7779_sysc_init(void)
+{
+ r8a7779_sysc_base = ioremap_nocache(0xffd85000, PAGE_SIZE);
+ if (!r8a7779_sysc_base)
+ panic("unable to ioremap r8a7779 SYSC hardware block\n");
+
+ /* enable all interrupt sources, but do not use interrupt handler */
+ iowrite32(0x0131000e, r8a7779_sysc_base + SYSCIER);
+ iowrite32(0, r8a7779_sysc_base + SYSCIMR);
+}
+
+static int pd_power_down(struct generic_pm_domain *genpd)
+{
+ return r8a7779_sysc_power_down(to_r8a7779_ch(genpd));
+}
+
+static int pd_power_up(struct generic_pm_domain *genpd)
+{
+ return r8a7779_sysc_power_up(to_r8a7779_ch(genpd));
+}
+
+static bool pd_is_off(struct generic_pm_domain *genpd)
+{
+ struct r8a7779_pm_ch *r8a7779_ch = to_r8a7779_ch(genpd);
+ unsigned int st;
+
+ st = ioread32(r8a7779_sysc_base + r8a7779_ch->chan_offs + PWRSR_OFFS);
+ if (st & (1 << r8a7779_ch->chan_bit))
+ return true;
+
+ return false;
+}
+
+static bool pd_active_wakeup(struct device *dev)
+{
+ return true;
+}
+
+void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
+{
+ struct generic_pm_domain *genpd = &r8a7779_pd->genpd;
+
+ pm_genpd_init(genpd, NULL, false);
+ genpd->dev_ops.stop = pm_clk_suspend;
+ genpd->dev_ops.start = pm_clk_resume;
+ genpd->dev_ops.active_wakeup = pd_active_wakeup;
+ genpd->dev_irq_safe = true;
+ genpd->power_off = pd_power_down;
+ genpd->power_on = pd_power_up;
+
+ if (pd_is_off(&r8a7779_pd->genpd))
+ pd_power_up(&r8a7779_pd->genpd);
+}
+
+void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd,
+ struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+
+ pm_genpd_add_device(&r8a7779_pd->genpd, dev);
+ if (pm_clk_no_clocks(dev))
+ pm_clk_add(dev, NULL);
+}
+
+struct r8a7779_pm_domain r8a7779_sh4a = {
+ .ch = {
+ .chan_offs = 0x80, /* PWRSR1 .. PWRER1 */
+ .isr_bit = 16, /* SH4A */
+ }
+};
+
+struct r8a7779_pm_domain r8a7779_sgx = {
+ .ch = {
+ .chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */
+ .isr_bit = 20, /* SGX */
+ }
+};
+
+struct r8a7779_pm_domain r8a7779_vdp1 = {
+ .ch = {
+ .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
+ .isr_bit = 21, /* VDP */
+ }
+};
+
+struct r8a7779_pm_domain r8a7779_impx3 = {
+ .ch = {
+ .chan_offs = 0x140, /* PWRSR4 .. PWRER4 */
+ .isr_bit = 24, /* IMP */
+ }
+};
+
+#else /* CONFIG_PM */
+
+static inline void r8a7779_sysc_init(void) {}
+
+#endif /* CONFIG_PM */
+
+void __init r8a7779_pm_init(void)
+{
+ r8a7779_sysc_init();
+}
--- 0001/arch/arm/mach-shmobile/setup-r8a7779.c
+++ work/arch/arm/mach-shmobile/setup-r8a7779.c 2012-01-10 15:30:18.000000000 +0900
@@ -30,6 +30,7 @@
#include <linux/sh_timer.h>
#include <mach/hardware.h>
#include <mach/r8a7779.h>
+#include <mach/common.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -218,6 +219,13 @@ static struct platform_device *r8a7779_l
void __init r8a7779_add_standard_devices(void)
{
+ r8a7779_pm_init();
+
+ r8a7779_init_pm_domain(&r8a7779_sh4a);
+ r8a7779_init_pm_domain(&r8a7779_sgx);
+ r8a7779_init_pm_domain(&r8a7779_vdp1);
+ r8a7779_init_pm_domain(&r8a7779_impx3);
+
platform_add_devices(r8a7779_early_devices,
ARRAY_SIZE(r8a7779_early_devices));
platform_add_devices(r8a7779_late_devices,
^ permalink raw reply
* Re: [PATCH v3 1/3] dmaengine: shdma: modify the DMAC Address Error registration
From: Paul Mundt @ 2012-01-10 7:18 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4F0BDCD5.9020603@renesas.com>
On Tue, Jan 10, 2012 at 03:38:13PM +0900, Shimoda, Yoshihiro wrote:
> The USB-DMAC/SUDMAC don't have the interrupt of DMAC Address Error.
> So, only when the resource has a name and it is "error_irq", the driver
> calls request_irq() for DMAC Address Error.
>
> This patch is also useful for the generic DMAC which doesn't have
> DMAC Address Error. So, we can get rid of the "CPU_SH4 || ARCH_SHMOBILE"
> ifdefs.
> This patch also changes the IRQF_DISABLED to 0.
>
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> ---
> about v3:
> - changes the IRQF_DISABLED to 0.
>
> drivers/dma/shdma.c | 78 ++++++++++++++++++++++++++-------------------------
> 1 files changed, 40 insertions(+), 38 deletions(-)
>
The updated patches look fine to me, thanks for fixing them up. I'll let
Vinod pick them up.
Acked-by: Paul Mundt <lethal@linux-sh.org>
^ permalink raw reply
* Re: [PATCH] arm: mach-shmobile: add a resource name for shdma
From: Paul Mundt @ 2012-01-10 7:43 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <4F0BCADB.8010709@renesas.com>
On Tue, Jan 10, 2012 at 02:21:31PM +0900, Shimoda, Yoshihiro wrote:
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> ---
> This patch depends on the following patch:
> - dmaengine: shdma: modify the DMAC Address Error registration
>
What exactly does it depend on? If it's just wiring up the string, we can
merge that at any time, and the earlier the better. Setting the string
doesn't introduce any different behaviour in the driver as it is now
without the change in registration.
^ permalink raw reply
* Re: [PATCH] ARM: mach-shmobile: r8a7779 power domain support V2
From: Paul Mundt @ 2012-01-10 8:12 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20111222081204.12120.92511.sendpatchset@w520>
On Tue, Jan 10, 2012 at 03:50:01PM +0900, Magnus Damm wrote:
> Add power domain control support for the r8a7779 SoC V2.
>
> This adds support for 4 power domains for I/O Devices
> together with code that can be used for CPU cores as well.
>
> The only out of the ordinary experience is the need for
> ioremap() of SYSC registers. Because of that we need to
> execute some init function before setting up the domains.
Applied, thanks.
> Built on top of linux-sh git rmobile/marzen branch.
>
I've now merged rmobile/marzen in to rmobile-latest, so hopefully that
will be it for the merge window.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox