diff options
author | Kishon Vijay Abraham I <kishon@ti.com> | 2012-05-14 15:22:02 -0500 |
---|---|---|
committer | Xavier Boudet <x-boudet@ti.com> | 2012-07-10 17:26:53 +0200 |
commit | cf4e4320ee093c4aa97c930953e81c17d3b66715 (patch) | |
tree | 817edc3d33168552233f2c4c9aec5a0decf3e270 | |
parent | f0398d213ee8464a8e65a6103fe8894cfcddccb9 (diff) |
HWMOD: Fix to disable dma to allow system to go to OFF
During _reset of the (hwmod)device, the dmadisable is set so that it
does not prevent idling of the system. (NOTE: having dmadisable to 0,
prevents the system to idle)
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Huzefa Kankroliwala <huzefank@ti.com>
Signed-off-by: Praneeth Bajjuri <praneeth@ti.com>
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 39 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_54xx_data.c | 56 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_common_data.c | 1 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap_hwmod.h | 5 |
4 files changed, 98 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 632344c9a791..2223b6a2342b 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -347,6 +347,44 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v) return 0; } + /** + * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v + * @oh: struct omap_hwmod * + * + * Set the DMADISABLE bit in @v for hwmod @oh. Returns -EINVAL upon + * error or 0 upon success. + */ +static int _set_dmadisable(struct omap_hwmod *oh) +{ + u32 v; + u32 dmadisable_mask; + + if (!oh->class->sysc || + !(oh->class->sysc->sysc_flags & SYSC_HAS_DMADISABLE)) + return -EINVAL; + + if (!oh->class->sysc->sysc_fields) { + WARN(1, "omap_hwmod: %s: offset struct for sysconfig not provided in class\n", oh->name); + return -EINVAL; + } + + /* clocks must be on for this operation */ + if (oh->_state != _HWMOD_STATE_ENABLED) { + pr_warning("omap_hwmod: %s: dma can be disabled only from enabled state\n", oh->name); + return -EINVAL; + } + + pr_info("omap_hwmod: %s: setting DMADISABLE\n", oh->name); + + v = oh->_sysc_cache; + dmadisable_mask = + (0x1 << oh->class->sysc->sysc_fields->dmadisable_shift); + v |= dmadisable_mask; + _write_sysconfig(v, oh); + + return 0; +} + /** * _set_module_autoidle: set the OCP_SYSCONFIG AUTOIDLE field in @v * @oh: struct omap_hwmod * @@ -1488,6 +1526,7 @@ static int _reset(struct omap_hwmod *oh) pr_debug("omap_hwmod: %s: resetting\n", oh->name); ret = (oh->class->reset) ? oh->class->reset(oh) : _ocp_softreset(oh); + _set_dmadisable(oh); if (oh->class->sysc) { _update_sysc_cache(oh); diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c index 34bab6bfbc5c..651e983da25c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c @@ -2871,7 +2871,7 @@ static struct omap_hwmod omap54xx_hsi_hwmod = { * multimaster high-speed i2c controller */ -static struct omap_i2c_dev_attr i2c_dev_attr = { +static struct omap_i2c_dev_attr i2c_dev_attr = { .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE | OMAP_I2C_FLAG_RESET_REGS_POSTIDLE, }; @@ -6320,6 +6320,56 @@ static struct omap_hwmod omap54xx_usb_host_hs_hwmod = { * Don't use smart standby; use only force standby, * hence HWMOD_SWSUP_MSTANDBY */ +static struct omap_hwmod_class_sysconfig omap54xx_usb_otg_ss_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE + | SYSC_HAS_DMADISABLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO | + MSTANDBY_SMART | MSTANDBY_SMART_WKUP), + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +static struct omap_hwmod_class omap54xx_usb_otg_ss_hwmod_class = { + .name = "usb_otg_ss", + .sysc = &omap54xx_usb_otg_ss_sysc, +}; + +/* usb_otg_ss */ +static struct omap_hwmod_irq_info omap54xx_usb_otg_ss_irqs[] = { + { .name = "core", .irq = 92 + OMAP54XX_IRQ_GIC_START }, + { .name = "wrp", .irq = 93 + OMAP54XX_IRQ_GIC_START }, + { .irq = -1 } +}; + +/* usb_otg_ss master ports */ +static struct omap_hwmod_ocp_if *omap54xx_usb_otg_ss_masters[] = { + &omap54xx_usb_otg_ss__l3_main_2, +}; + +static struct omap_hwmod_addr_space omap54xx_usb_otg_ss_addrs[] = { + { + .pa_start = 0x4a020000, + .pa_end = 0x4a03ffff, + .flags = ADDR_TYPE_RT + }, + { } +}; + +/* l4_cfg -> usb_otg_ss */ +static struct omap_hwmod_ocp_if omap54xx_l4_cfg__usb_otg_ss = { + .master = &omap54xx_l4_cfg_hwmod, + .slave = &omap54xx_usb_otg_ss_hwmod, + .clk = "l4_div_ck", + .addr = omap54xx_usb_otg_ss_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* usb_otg_ss slave ports */ +static struct omap_hwmod_ocp_if *omap54xx_usb_otg_ss_slaves[] = { + &omap54xx_l4_cfg__usb_otg_ss, +}; /* During system boot; If the hwmod framework resets the module * the module will have smart idle settings; which can lead to deadlock @@ -6586,7 +6636,7 @@ static __initdata struct omap_hwmod *omap54xx_hwmods[] = { /* dsp class */ #ifndef CONFIG_OMAP_PM_STANDALONE &omap54xx_dsp_hwmod, - &omap54xx_dsp_c0_hwmod, + &omap54xx_dsp_c0_hwmod, #endif /* dss class */ @@ -6636,7 +6686,7 @@ static __initdata struct omap_hwmod *omap54xx_hwmods[] = { #ifndef CONFIG_OMAP_PM_STANDALONE /* ipu class */ &omap54xx_ipu_hwmod, - &omap54xx_ipu_c0_hwmod, + &omap54xx_ipu_c0_hwmod, &omap54xx_ipu_c1_hwmod, #endif diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c index 4863240d2678..d2947e74c678 100644 --- a/arch/arm/mach-omap2/omap_hwmod_common_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c @@ -47,6 +47,7 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = { .midle_shift = SYSC_TYPE2_MIDLEMODE_SHIFT, .sidle_shift = SYSC_TYPE2_SIDLEMODE_SHIFT, .srst_shift = SYSC_TYPE2_SOFTRESET_SHIFT, + .dmadisable_shift = SYSC_TYPE2_DMADISABLE_SHIFT, }; struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = { diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 739188e03cf6..ac722e62a077 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -70,6 +70,8 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_custom; #define SYSC_TYPE2_SIDLEMODE_MASK (0x3 << SYSC_TYPE2_SIDLEMODE_SHIFT) #define SYSC_TYPE2_MIDLEMODE_SHIFT 4 #define SYSC_TYPE2_MIDLEMODE_MASK (0x3 << SYSC_TYPE2_MIDLEMODE_SHIFT) +#define SYSC_TYPE2_DMADISABLE_SHIFT 16 +#define SYSC_TYPE2_DMADISABLE_MASK (0x1 << SYSC_TYPE2_DMADISABLE_SHIFT) /* OCP SYSSTATUS bit shifts/masks */ #define SYSS_RESETDONE_SHIFT 0 @@ -276,6 +278,7 @@ struct omap_hwmod_ocp_if { #define SYSS_HAS_RESET_STATUS (1 << 7) #define SYSC_NO_CACHE (1 << 8) /* XXX SW flag, belongs elsewhere */ #define SYSC_HAS_RESET_STATUS (1 << 9) +#define SYSC_HAS_DMADISABLE (1 << 10) /* omap_hwmod_sysconfig.clockact flags */ #define CLOCKACT_TEST_BOTH 0x0 @@ -291,6 +294,7 @@ struct omap_hwmod_ocp_if { * @enwkup_shift: Offset of the enawakeup bit * @srst_shift: Offset of the softreset bit * @autoidle_shift: Offset of the autoidle bit + * @dmadisable_shift: Offset of the dmadisable bit */ struct omap_hwmod_sysc_fields { u8 midle_shift; @@ -299,6 +303,7 @@ struct omap_hwmod_sysc_fields { u8 enwkup_shift; u8 srst_shift; u8 autoidle_shift; + u8 dmadisable_shift; }; /** |