diff options
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/dma.c | 297 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_2420_data.c | 86 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_2430_data.c | 86 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 97 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 102 |
6 files changed, 669 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index b86b062..cdfb5fa 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -4,7 +4,7 @@ # Common support obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \ - common.o gpio.o + common.o gpio.o dma.o omap-2-3-common = irq.o sdrc.o prm2xxx_3xxx.o hwmod-common = omap_hwmod.o \ diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c new file mode 100644 index 0000000..d2f15f5 --- /dev/null +++ b/arch/arm/mach-omap2/dma.c @@ -0,0 +1,297 @@ +/* + * OMAP2+ DMA driver + * + * Copyright (C) 2003 - 2008 Nokia Corporation + * Author: Juha Yrjölä <juha.yrjola@nokia.com> + * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> + * Graphics DMA and LCD DMA graphics tranformations + * by Imre Deak <imre.deak@nokia.com> + * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc. + * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. + * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Converted DMA library into platform driver + * - G, Manjunath Kondaiah <manjugk@ti.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/err.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/device.h> + +#include <plat/omap_hwmod.h> +#include <plat/omap_device.h> +#include <plat/dma.h> + +#define OMAP2_DMA_STRIDE 0x60 + +static u32 errata; +static u8 dma_stride; + +static struct omap_dma_dev_attr *d; + +static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; + +static u16 reg_map[] = { + [REVISION] = 0x00, + [GCR] = 0x78, + [IRQSTATUS_L0] = 0x08, + [IRQSTATUS_L1] = 0x0c, + [IRQSTATUS_L2] = 0x10, + [IRQSTATUS_L3] = 0x14, + [IRQENABLE_L0] = 0x18, + [IRQENABLE_L1] = 0x1c, + [IRQENABLE_L2] = 0x20, + [IRQENABLE_L3] = 0x24, + [SYSSTATUS] = 0x28, + [OCP_SYSCONFIG] = 0x2c, + [CAPS_0] = 0x64, + [CAPS_2] = 0x6c, + [CAPS_3] = 0x70, + [CAPS_4] = 0x74, + + /* Common register offsets */ + [CCR] = 0x80, + [CLNK_CTRL] = 0x84, + [CICR] = 0x88, + [CSR] = 0x8c, + [CSDP] = 0x90, + [CEN] = 0x94, + [CFN] = 0x98, + [CSEI] = 0xa4, + [CSFI] = 0xa8, + [CDEI] = 0xac, + [CDFI] = 0xb0, + [CSAC] = 0xb4, + [CDAC] = 0xb8, + + /* Channel specific register offsets */ + [CSSA] = 0x9c, + [CDSA] = 0xa0, + [CCEN] = 0xbc, + [CCFN] = 0xc0, + [COLOR] = 0xc4, + + /* OMAP4 specific registers */ + [CDP] = 0xd0, + [CNDP] = 0xd4, + [CCDN] = 0xd8, +}; + +static struct omap_device_pm_latency omap2_dma_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +static void __iomem *dma_base; +static inline void dma_write(u32 val, int reg, int lch) +{ + u8 stride; + u32 offset; + + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + __raw_writel(val, dma_base + offset); +} + +static inline u32 dma_read(int reg, int lch) +{ + u8 stride; + u32 offset, val; + + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + val = __raw_readl(dma_base + offset); + return val; +} + +static inline void omap2_disable_irq_lch(int lch) +{ + u32 val; + + val = dma_read(IRQENABLE_L0, lch); + val &= ~(1 << lch); + dma_write(val, IRQENABLE_L0, lch); +} + +static void omap2_clear_dma(int lch) +{ + int i = dma_common_ch_start; + + for (; i <= dma_common_ch_end; i += 1) + dma_write(0, i, lch); +} + +static void omap2_show_dma_caps(void) +{ + u8 revision = dma_read(REVISION, 0) & 0xff; + printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", + revision >> 4, revision & 0xf); + return; +} + +static u32 configure_dma_errata(void) +{ + + /* + * Errata applicable for OMAP2430ES1.0 and all omap2420 + * + * I. + * Erratum ID: Not Available + * Inter Frame DMA buffering issue DMA will wrongly + * buffer elements if packing and bursting is enabled. This might + * result in data gets stalled in FIFO at the end of the block. + * Workaround: DMA channels must have BUFFERING_DISABLED bit set to + * guarantee no data will stay in the DMA FIFO in case inter frame + * buffering occurs + * + * II. + * Erratum ID: Not Available + * DMA may hang when several channels are used in parallel + * In the following configuration, DMA channel hanging can occur: + * a. Channel i, hardware synchronized, is enabled + * b. Another channel (Channel x), software synchronized, is enabled. + * c. Channel i is disabled before end of transfer + * d. Channel i is reenabled. + * e. Steps 1 to 4 are repeated a certain number of times. + * f. A third channel (Channel y), software synchronized, is enabled. + * Channel x and Channel y may hang immediately after step 'f'. + * Workaround: + * For any channel used - make sure NextLCH_ID is set to the value j. + */ + if (cpu_is_omap2420() || (cpu_is_omap2430() && + (omap_type() == OMAP2430_REV_ES1_0))) { + + SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING); + SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS); + } + + /* + * Erratum ID: i378: OMAP2+: sDMA Channel is not disabled + * after a transaction error. + * Workaround: SW should explicitely disable the channel. + */ + if (cpu_class_is_omap2()) + SET_DMA_ERRATA(DMA_ERRATA_i378); + + /* + * Erratum ID: i541: sDMA FIFO draining does not finish + * If sDMA channel is disabled on the fly, sDMA enters standby even + * through FIFO Drain is still in progress + * Workaround: Put sDMA in NoStandby more before a logical channel is + * disabled, then put it back to SmartStandby right after the channel + * finishes FIFO draining. + */ + if (cpu_is_omap34xx()) + SET_DMA_ERRATA(DMA_ERRATA_i541); + + /* + * Erratum ID: i88 : Special programming model needed to disable DMA + * before end of block. + * Workaround: software must ensure that the DMA is configured in No + * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01") + */ + if (omap_type() == OMAP3430_REV_ES1_0) + SET_DMA_ERRATA(DMA_ERRATA_i88); + + /* + * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is + * read before the DMA controller finished disabling the channel. + */ + SET_DMA_ERRATA(DMA_ERRATA_3_3); + + /* + * Erratum ID: Not Available + * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared + * after secure sram context save and restore. + * Work around: Hence we need to manually clear those IRQs to avoid + * spurious interrupts. This affects only secure devices. + */ + if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) + SET_DMA_ERRATA(DMA_ROMCODE_BUG); + + return errata; +} + +/* One time initializations */ +static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) +{ + struct omap_device *od; + struct omap_system_dma_plat_info *p; + struct resource *mem; + char *name = "omap_dma_system"; + + dma_stride = OMAP2_DMA_STRIDE; + dma_common_ch_start = CSDP; + if (cpu_is_omap3630() || cpu_is_omap4430()) + dma_common_ch_end = CCDN; + else + dma_common_ch_end = CCFN; + + p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); + if (!p) { + pr_err("%s: Unable to allocate pdata for %s:%s\n", + __func__, name, oh->name); + return -ENOMEM; + } + + p->dma_attr = (struct omap_dma_dev_attr *)oh->dev_attr; + p->disable_irq_lch = omap2_disable_irq_lch; + p->show_dma_caps = omap2_show_dma_caps; + p->clear_dma = omap2_clear_dma; + p->dma_write = dma_write; + p->dma_read = dma_read; + + p->clear_lch_regs = NULL; + + p->errata = configure_dma_errata(); + + od = omap_device_build(name, 0, oh, p, sizeof(*p), + omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0); + kfree(p); + if (IS_ERR(od)) { + pr_err("%s: Cant build omap_device for %s:%s.\n", + __func__, name, oh->name); + return IS_ERR(od); + } + + mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(&od->pdev.dev, "%s: no mem resource\n", __func__); + return -EINVAL; + } + dma_base = ioremap(mem->start, resource_size(mem)); + if (!dma_base) { + dev_err(&od->pdev.dev, "%s: ioremap fail\n", __func__); + return -ENOMEM; + } + + d = oh->dev_attr; + d->chan = kzalloc(sizeof(struct omap_dma_lch) * + (d->lch_count), GFP_KERNEL); + + if (!d->chan) { + dev_err(&od->pdev.dev, "%s: kzalloc fail\n", __func__); + return -ENOMEM; + } + return 0; +} + +static int __init omap2_system_dma_init(void) +{ + return omap_hwmod_for_each_by_class("dma", + omap2_system_dma_init_dev, NULL); +} +arch_initcall(omap2_system_dma_init); diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index d953425..42606f6 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -42,6 +42,7 @@ static struct omap_hwmod omap2420_gpio1_hwmod; static struct omap_hwmod omap2420_gpio2_hwmod; static struct omap_hwmod omap2420_gpio3_hwmod; static struct omap_hwmod omap2420_gpio4_hwmod; +static struct omap_hwmod omap2420_dma_system_hwmod; /* L3 -> L4_CORE interface */ static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = { @@ -779,6 +780,88 @@ static struct omap_hwmod omap2420_gpio4_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), }; +/* system dma */ +static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x002c, + .syss_offs = 0x0028, + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE | + SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE | + SYSC_HAS_AUTOIDLE), + .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2420_dma_hwmod_class = { + .name = "dma", + .sysc = &omap2420_dma_sysc, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { + .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | + IS_CSSA_32 | IS_CDSA_32, + .lch_count = 32, +}; + +static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = { + { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */ + { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */ + { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */ + { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */ +}; + +static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = { + { + .pa_start = 0x48056000, + .pa_end = 0x4a0560ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* dma_system -> L3 */ +static struct omap_hwmod_ocp_if omap2420_dma_system__l3 = { + .master = &omap2420_dma_system_hwmod, + .slave = &omap2420_l3_main_hwmod, + .clk = "core_l3_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap2420_dma_system_masters[] = { + &omap2420_dma_system__l3, +}; + +/* l4_core -> dma_system */ +static struct omap_hwmod_ocp_if omap2420_l4_core__dma_system = { + .master = &omap2420_l4_core_hwmod, + .slave = &omap2420_dma_system_hwmod, + .clk = "sdma_ick", + .addr = omap2420_dma_system_addrs, + .addr_cnt = ARRAY_SIZE(omap2420_dma_system_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap2420_dma_system_slaves[] = { + &omap2420_l4_core__dma_system, +}; + +static struct omap_hwmod omap2420_dma_system_hwmod = { + .name = "dma", + .class = &omap2420_dma_hwmod_class, + .mpu_irqs = omap2420_dma_system_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap2420_dma_system_irqs), + .main_clk = "core_l3_ck", + .slaves = omap2420_dma_system_slaves, + .slaves_cnt = ARRAY_SIZE(omap2420_dma_system_slaves), + .masters = omap2420_dma_system_masters, + .masters_cnt = ARRAY_SIZE(omap2420_dma_system_masters), + .dev_attr = &dma_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), + .flags = HWMOD_NO_IDLEST, +}; + static __initdata struct omap_hwmod *omap2420_hwmods[] = { &omap2420_l3_main_hwmod, &omap2420_l4_core_hwmod, @@ -797,6 +880,9 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = { &omap2420_gpio2_hwmod, &omap2420_gpio3_hwmod, &omap2420_gpio4_hwmod, + + /* dma_system class*/ + &omap2420_dma_system_hwmod, NULL, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index ab1d662..3315d24 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -43,6 +43,7 @@ static struct omap_hwmod omap2430_gpio2_hwmod; static struct omap_hwmod omap2430_gpio3_hwmod; static struct omap_hwmod omap2430_gpio4_hwmod; static struct omap_hwmod omap2430_gpio5_hwmod; +static struct omap_hwmod omap2430_dma_system_hwmod; /* L3 -> L4_CORE interface */ static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = { @@ -838,6 +839,88 @@ static struct omap_hwmod omap2430_gpio5_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), }; +/* dma_system */ +static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x002c, + .syss_offs = 0x0028, + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE | + SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE | + SYSC_HAS_AUTOIDLE), + .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap2430_dma_hwmod_class = { + .name = "dma", + .sysc = &omap2430_dma_sysc, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { + .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | + IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY, + .lch_count = 32, +}; + +static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = { + { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */ + { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */ + { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */ + { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */ +}; + +static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = { + { + .pa_start = 0x48056000, + .pa_end = 0x4a0560ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* dma_system -> L3 */ +static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = { + .master = &omap2430_dma_system_hwmod, + .slave = &omap2430_l3_main_hwmod, + .clk = "core_l3_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap2430_dma_system_masters[] = { + &omap2430_dma_system__l3, +}; + +/* l4_core -> dma_system */ +static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = { + .master = &omap2430_l4_core_hwmod, + .slave = &omap2430_dma_system_hwmod, + .clk = "sdma_ick", + .addr = omap2430_dma_system_addrs, + .addr_cnt = ARRAY_SIZE(omap2430_dma_system_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = { + &omap2430_l4_core__dma_system, +}; + +static struct omap_hwmod omap2430_dma_system_hwmod = { + .name = "dma", + .class = &omap2430_dma_hwmod_class, + .mpu_irqs = omap2430_dma_system_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap2430_dma_system_irqs), + .main_clk = "core_l3_ck", + .slaves = omap2430_dma_system_slaves, + .slaves_cnt = ARRAY_SIZE(omap2430_dma_system_slaves), + .masters = omap2430_dma_system_masters, + .masters_cnt = ARRAY_SIZE(omap2430_dma_system_masters), + .dev_attr = &dma_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), + .flags = HWMOD_NO_IDLEST, +}; + static __initdata struct omap_hwmod *omap2430_hwmods[] = { &omap2430_l3_main_hwmod, &omap2430_l4_core_hwmod, @@ -857,6 +940,9 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = { &omap2430_gpio3_hwmod, &omap2430_gpio4_hwmod, &omap2430_gpio5_hwmod, + + /* dma_system class*/ + &omap2430_dma_system_hwmod, NULL, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 2687be1..d5acb63 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -52,6 +52,8 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod; static struct omap_hwmod omap3xxx_gpio5_hwmod; static struct omap_hwmod omap3xxx_gpio6_hwmod; +static struct omap_hwmod omap3xxx_dma_system_hwmod; + /* L3 -> L4_CORE interface */ static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = { .master = &omap3xxx_l3_main_hwmod, @@ -1090,6 +1092,98 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), }; +/* dma_system -> L3 */ +static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = { + .master = &omap3xxx_dma_system_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .clk = "core_l3_ick", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { + .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | + IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY, + .lch_count = 32, +}; + +static struct omap_hwmod_class_sysconfig omap3xxx_dma_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x002c, + .syss_offs = 0x0028, + .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY | + SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3xxx_dma_hwmod_class = { + .name = "dma", + .sysc = &omap3xxx_dma_sysc, +}; + +/* dma_system */ +static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = { + { .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */ + { .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */ + { .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */ + { .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */ +}; + +static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = { + { + .pa_start = 0x48056000, + .pa_end = 0x4a0560ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dma_system_masters[] = { + &omap3xxx_dma_system__l3, +}; + +/* l4_cfg -> dma_system */ +static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3xxx_dma_system_hwmod, + .clk = "core_l4_ick", + .addr = omap3xxx_dma_system_addrs, + .addr_cnt = ARRAY_SIZE(omap3xxx_dma_system_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = { + &omap3xxx_l4_core__dma_system, +}; + +static struct omap_hwmod omap3xxx_dma_system_hwmod = { + .name = "dma", + .class = &omap3xxx_dma_hwmod_class, + .mpu_irqs = omap3xxx_dma_system_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dma_system_irqs), + .main_clk = "core_l3_ick", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, + .prcm_reg_id = 1, + .module_bit = OMAP3430_ST_SDMA_SHIFT, + .idlest_reg_id = 1, + .idlest_idle_bit = OMAP3430_ST_SDMA_SHIFT, + }, + }, + .slaves = omap3xxx_dma_system_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_dma_system_slaves), + .masters = omap3xxx_dma_system_masters, + .masters_cnt = ARRAY_SIZE(omap3xxx_dma_system_masters), + .dev_attr = &dma_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .flags = HWMOD_NO_IDLEST, +}; + static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_l3_main_hwmod, &omap3xxx_l4_core_hwmod, @@ -1113,6 +1207,9 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_gpio4_hwmod, &omap3xxx_gpio5_hwmod, &omap3xxx_gpio6_hwmod, + + /* dma_system class*/ + &omap3xxx_dma_system_hwmod, NULL, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index d258936..f9778fb 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -23,6 +23,7 @@ #include <plat/omap_hwmod.h> #include <plat/cpu.h> #include <plat/gpio.h> +#include <plat/dma.h> #include "omap_hwmod_common_data.h" @@ -36,6 +37,7 @@ #define OMAP44XX_DMA_REQ_START 1 /* Backward references (IPs with Bus Master capability) */ +static struct omap_hwmod omap44xx_dma_system_hwmod; static struct omap_hwmod omap44xx_dmm_hwmod; static struct omap_hwmod omap44xx_emif_fw_hwmod; static struct omap_hwmod omap44xx_l3_instr_hwmod; @@ -216,6 +218,14 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* dma_system -> l3_main_2 */ +static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = { + .master = &omap44xx_dma_system_hwmod, + .slave = &omap44xx_l3_main_2_hwmod, + .clk = "l3_div_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* l4_cfg -> l3_main_2 */ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = { .master = &omap44xx_l4_cfg_hwmod, @@ -226,6 +236,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = { /* l3_main_2 slave ports */ static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = { + &omap44xx_dma_system__l3_main_2, &omap44xx_l3_main_1__l3_main_2, &omap44xx_l4_cfg__l3_main_2, }; @@ -1376,6 +1387,93 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_gpio6_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; + +/* + * 'dma' class + * dma controller for data exchange between memory to memory (i.e. internal or + * external memory) and gp peripherals to memory or memory to gp peripherals + */ + +static struct omap_hwmod_class_sysconfig omap44xx_dma_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x002c, + .syss_offs = 0x0028, + .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | + SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE | + SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | + SYSS_HAS_RESET_STATUS), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +/* dma attributes */ +static struct omap_dma_dev_attr dma_dev_attr = { + .dev_caps = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY | + IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY, + .lch_count = 32, +}; + +static struct omap_hwmod_class omap44xx_dma_hwmod_class = { + .name = "dma", + .sysc = &omap44xx_dma_sysc, +}; + +/* dma_system */ +static struct omap_hwmod_irq_info omap44xx_dma_system_irqs[] = { + { .name = "0", .irq = 12 + OMAP44XX_IRQ_GIC_START }, + { .name = "1", .irq = 13 + OMAP44XX_IRQ_GIC_START }, + { .name = "2", .irq = 14 + OMAP44XX_IRQ_GIC_START }, + { .name = "3", .irq = 15 + OMAP44XX_IRQ_GIC_START }, +}; + +/* dma_system master ports */ +static struct omap_hwmod_ocp_if *omap44xx_dma_system_masters[] = { + &omap44xx_dma_system__l3_main_2, +}; + +static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = { + { + .pa_start = 0x4a056000, + .pa_end = 0x4a0560ff, + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_cfg -> dma_system */ +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__dma_system = { + .master = &omap44xx_l4_cfg_hwmod, + .slave = &omap44xx_dma_system_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_dma_system_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_dma_system_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* dma_system slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_dma_system_slaves[] = { + &omap44xx_l4_cfg__dma_system, +}; + +static struct omap_hwmod omap44xx_dma_system_hwmod = { + .name = "dma_system", + .class = &omap44xx_dma_hwmod_class, + .mpu_irqs = omap44xx_dma_system_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dma_system_irqs), + .main_clk = "l3_div_ck", + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_SDMA_SDMA_CLKCTRL, + }, + }, + .slaves = omap44xx_dma_system_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_dma_system_slaves), + .masters = omap44xx_dma_system_masters, + .masters_cnt = ARRAY_SIZE(omap44xx_dma_system_masters), + .dev_attr = &dma_dev_attr, + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), +}; + static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* dmm class */ &omap44xx_dmm_hwmod, @@ -1391,6 +1489,10 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_l4_cfg_hwmod, &omap44xx_l4_per_hwmod, &omap44xx_l4_wkup_hwmod, + + /* dma class */ + &omap44xx_dma_system_hwmod, + /* i2c class */ &omap44xx_i2c1_hwmod, &omap44xx_i2c2_hwmod, |