diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2010-05-04 14:07:15 +0000 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-05-31 13:18:51 +0900 |
commit | 69bf6f451febe8dd07ccedf0ba3279c0f3f7fc3a (patch) | |
tree | b3ff66a5903c7ebc7a281d2870693aef8ec952fb /arch/arm/mach-shmobile | |
parent | d5b732b17ca2fc74f370bdba5aae6c804fac8c35 (diff) | |
download | talos-op-linux-69bf6f451febe8dd07ccedf0ba3279c0f3f7fc3a.tar.gz talos-op-linux-69bf6f451febe8dd07ccedf0ba3279c0f3f7fc3a.zip |
ARM: add DMA support to sh7372, enable DMA for SDHI
This adds DMA support for the sh7372 sh-mobile ARM core, using the shdma
dmaengine driver, and uses DMA for the SDHI SD-card controller on this SoC.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r-- | arch/arm/mach-shmobile/board-ap4evb.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/sh7372.h | 10 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/setup-sh7372.c | 223 |
3 files changed, 242 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 353ff8d120b1..5c41b958e022 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -24,6 +24,7 @@ #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/delay.h> +#include <linux/mfd/sh_mobile_sdhi.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> @@ -231,6 +232,11 @@ static struct platform_device keysc_device = { }; /* SDHI0 */ +static struct sh_mobile_sdhi_info sdhi0_info = { + .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, + .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, +}; + static struct resource sdhi0_resources[] = { [0] = { .name = "SDHI0", @@ -249,6 +255,9 @@ static struct platform_device sdhi0_device = { .num_resources = ARRAY_SIZE(sdhi0_resources), .resource = sdhi0_resources, .id = 0, + .dev = { + .platform_data = &sdhi0_info, + }, }; /* USB1 */ diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index dc34f00c56b8..57e033a1e529 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h @@ -431,4 +431,14 @@ enum { GPIO_FN_SDENC_DV_CLKI, }; +/* DMA slave IDs */ +enum { + SHDMA_SLAVE_SDHI0_RX, + SHDMA_SLAVE_SDHI0_TX, + SHDMA_SLAVE_SDHI1_RX, + SHDMA_SLAVE_SDHI1_TX, + SHDMA_SLAVE_SDHI2_RX, + SHDMA_SLAVE_SDHI2_TX, +}; + #endif /* __ASM_SH7372_H__ */ diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index d1a8095a19eb..bf6974b4afd0 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -26,9 +26,11 @@ #include <linux/input.h> #include <linux/io.h> #include <linux/serial_sci.h> +#include <linux/sh_dma.h> #include <linux/sh_intc.h> #include <linux/sh_timer.h> #include <mach/hardware.h> +#include <mach/sh7372.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -227,6 +229,224 @@ static struct platform_device iic1_device = { .resource = iic1_resources, }; +/* DMA */ +/* Transmit sizes and respective CHCR register values */ +enum { + XMIT_SZ_8BIT = 0, + XMIT_SZ_16BIT = 1, + XMIT_SZ_32BIT = 2, + XMIT_SZ_64BIT = 7, + XMIT_SZ_128BIT = 3, + XMIT_SZ_256BIT = 4, + XMIT_SZ_512BIT = 5, +}; + +/* log2(size / 8) - used to calculate number of transfers */ +#define TS_SHIFT { \ + [XMIT_SZ_8BIT] = 0, \ + [XMIT_SZ_16BIT] = 1, \ + [XMIT_SZ_32BIT] = 2, \ + [XMIT_SZ_64BIT] = 3, \ + [XMIT_SZ_128BIT] = 4, \ + [XMIT_SZ_256BIT] = 5, \ + [XMIT_SZ_512BIT] = 6, \ +} + +#define TS_INDEX2VAL(i) ((((i) & 3) << 3) | \ + (((i) & 0xc) << (20 - 2))) + +static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = { + { + .slave_id = SHDMA_SLAVE_SDHI0_TX, + .addr = 0xe6850030, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .mid_rid = 0xc1, + }, { + .slave_id = SHDMA_SLAVE_SDHI0_RX, + .addr = 0xe6850030, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .mid_rid = 0xc2, + }, { + .slave_id = SHDMA_SLAVE_SDHI1_TX, + .addr = 0xe6860030, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .mid_rid = 0xc9, + }, { + .slave_id = SHDMA_SLAVE_SDHI1_RX, + .addr = 0xe6860030, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .mid_rid = 0xca, + }, { + .slave_id = SHDMA_SLAVE_SDHI2_TX, + .addr = 0xe6870030, + .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .mid_rid = 0xcd, + }, { + .slave_id = SHDMA_SLAVE_SDHI2_RX, + .addr = 0xe6870030, + .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .mid_rid = 0xce, + }, +}; + +static const struct sh_dmae_channel sh7372_dmae_channels[] = { + { + .offset = 0, + .dmars = 0, + .dmars_bit = 0, + }, { + .offset = 0x10, + .dmars = 0, + .dmars_bit = 8, + }, { + .offset = 0x20, + .dmars = 4, + .dmars_bit = 0, + }, { + .offset = 0x30, + .dmars = 4, + .dmars_bit = 8, + }, { + .offset = 0x50, + .dmars = 8, + .dmars_bit = 0, + }, { + .offset = 0x60, + .dmars = 8, + .dmars_bit = 8, + } +}; + +static const unsigned int ts_shift[] = TS_SHIFT; + +static struct sh_dmae_pdata dma_platform_data = { + .slave = sh7372_dmae_slaves, + .slave_num = ARRAY_SIZE(sh7372_dmae_slaves), + .channel = sh7372_dmae_channels, + .channel_num = ARRAY_SIZE(sh7372_dmae_channels), + .ts_low_shift = 3, + .ts_low_mask = 0x18, + .ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */ + .ts_high_mask = 0x00300000, + .ts_shift = ts_shift, + .ts_shift_num = ARRAY_SIZE(ts_shift), + .dmaor_init = DMAOR_DME, +}; + +/* Resource order important! */ +static struct resource sh7372_dmae0_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xfe008020, + .end = 0xfe00808f, + .flags = IORESOURCE_MEM, + }, + { + /* DMARSx */ + .start = 0xfe009000, + .end = 0xfe00900b, + .flags = IORESOURCE_MEM, + }, + { + /* DMA error IRQ */ + .start = 246, + .end = 246, + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 0-5 */ + .start = 240, + .end = 245, + .flags = IORESOURCE_IRQ, + }, +}; + +/* Resource order important! */ +static struct resource sh7372_dmae1_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xfe018020, + .end = 0xfe01808f, + .flags = IORESOURCE_MEM, + }, + { + /* DMARSx */ + .start = 0xfe019000, + .end = 0xfe01900b, + .flags = IORESOURCE_MEM, + }, + { + /* DMA error IRQ */ + .start = 254, + .end = 254, + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 0-5 */ + .start = 248, + .end = 253, + .flags = IORESOURCE_IRQ, + }, +}; + +/* Resource order important! */ +static struct resource sh7372_dmae2_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xfe028020, + .end = 0xfe02808f, + .flags = IORESOURCE_MEM, + }, + { + /* DMARSx */ + .start = 0xfe029000, + .end = 0xfe02900b, + .flags = IORESOURCE_MEM, + }, + { + /* DMA error IRQ */ + .start = 262, + .end = 262, + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 0-5 */ + .start = 256, + .end = 261, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dma0_device = { + .name = "sh-dma-engine", + .id = 0, + .resource = sh7372_dmae0_resources, + .num_resources = ARRAY_SIZE(sh7372_dmae0_resources), + .dev = { + .platform_data = &dma_platform_data, + }, +}; + +static struct platform_device dma1_device = { + .name = "sh-dma-engine", + .id = 1, + .resource = sh7372_dmae1_resources, + .num_resources = ARRAY_SIZE(sh7372_dmae1_resources), + .dev = { + .platform_data = &dma_platform_data, + }, +}; + +static struct platform_device dma2_device = { + .name = "sh-dma-engine", + .id = 2, + .resource = sh7372_dmae2_resources, + .num_resources = ARRAY_SIZE(sh7372_dmae2_resources), + .dev = { + .platform_data = &dma_platform_data, + }, +}; + static struct platform_device *sh7372_early_devices[] __initdata = { &scif0_device, &scif1_device, @@ -238,6 +458,9 @@ static struct platform_device *sh7372_early_devices[] __initdata = { &cmt10_device, &iic0_device, &iic1_device, + &dma0_device, + &dma1_device, + &dma2_device, }; void __init sh7372_add_standard_devices(void) |