summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2012-05-14 15:22:02 -0500
committerXavier Boudet <x-boudet@ti.com>2012-07-10 17:26:53 +0200
commitcf4e4320ee093c4aa97c930953e81c17d3b66715 (patch)
tree817edc3d33168552233f2c4c9aec5a0decf3e270
parentf0398d213ee8464a8e65a6103fe8894cfcddccb9 (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.c39
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_54xx_data.c56
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_common_data.c1
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h5
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;
};
/**