aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c51
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h5
2 files changed, 51 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 5027879b062f..f320cfb911d5 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -546,6 +546,36 @@ static int _disable_clocks(struct omap_hwmod *oh)
546 return 0; 546 return 0;
547} 547}
548 548
549static void _enable_optional_clocks(struct omap_hwmod *oh)
550{
551 struct omap_hwmod_opt_clk *oc;
552 int i;
553
554 pr_debug("omap_hwmod: %s: enabling optional clocks\n", oh->name);
555
556 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
557 if (oc->_clk) {
558 pr_debug("omap_hwmod: enable %s:%s\n", oc->role,
559 oc->_clk->name);
560 clk_enable(oc->_clk);
561 }
562}
563
564static void _disable_optional_clocks(struct omap_hwmod *oh)
565{
566 struct omap_hwmod_opt_clk *oc;
567 int i;
568
569 pr_debug("omap_hwmod: %s: disabling optional clocks\n", oh->name);
570
571 for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
572 if (oc->_clk) {
573 pr_debug("omap_hwmod: disable %s:%s\n", oc->role,
574 oc->_clk->name);
575 clk_disable(oc->_clk);
576 }
577}
578
549/** 579/**
550 * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use 580 * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
551 * @oh: struct omap_hwmod * 581 * @oh: struct omap_hwmod *
@@ -976,8 +1006,9 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
976 */ 1006 */
977static int _reset(struct omap_hwmod *oh) 1007static int _reset(struct omap_hwmod *oh)
978{ 1008{
979 u32 r, v; 1009 u32 v;
980 int c = 0; 1010 int c = 0;
1011 int ret = 0;
981 1012
982 if (!oh->class->sysc || 1013 if (!oh->class->sysc ||
983 !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET)) 1014 !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
@@ -990,12 +1021,16 @@ static int _reset(struct omap_hwmod *oh)
990 return -EINVAL; 1021 return -EINVAL;
991 } 1022 }
992 1023
1024 /* For some modules, all optionnal clocks need to be enabled as well */
1025 if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
1026 _enable_optional_clocks(oh);
1027
993 pr_debug("omap_hwmod: %s: resetting\n", oh->name); 1028 pr_debug("omap_hwmod: %s: resetting\n", oh->name);
994 1029
995 v = oh->_sysc_cache; 1030 v = oh->_sysc_cache;
996 r = _set_softreset(oh, &v); 1031 ret = _set_softreset(oh, &v);
997 if (r) 1032 if (ret)
998 return r; 1033 goto dis_opt_clks;
999 _write_sysconfig(v, oh); 1034 _write_sysconfig(v, oh);
1000 1035
1001 if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS) 1036 if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
@@ -1020,7 +1055,13 @@ static int _reset(struct omap_hwmod *oh)
1020 * _wait_target_ready() or _reset() 1055 * _wait_target_ready() or _reset()
1021 */ 1056 */
1022 1057
1023 return (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0; 1058 ret = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
1059
1060dis_opt_clks:
1061 if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
1062 _disable_optional_clocks(oh);
1063
1064 return ret;
1024} 1065}
1025 1066
1026/** 1067/**
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index faa08273b1e4..ee53758e1f49 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -369,6 +369,10 @@ struct omap_hwmod_omap4_prcm {
369 * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup 369 * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
370 * HWMOD_NO_IDLEST : this module does not have idle status - this is the case 370 * HWMOD_NO_IDLEST : this module does not have idle status - this is the case
371 * only for few initiator modules on OMAP2 & 3. 371 * only for few initiator modules on OMAP2 & 3.
372 * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
373 * This is needed for devices like DSS that require optional clocks enabled
374 * in order to complete the reset. Optional clocks will be disabled
375 * again after the reset.
372 */ 376 */
373#define HWMOD_SWSUP_SIDLE (1 << 0) 377#define HWMOD_SWSUP_SIDLE (1 << 0)
374#define HWMOD_SWSUP_MSTANDBY (1 << 1) 378#define HWMOD_SWSUP_MSTANDBY (1 << 1)
@@ -377,6 +381,7 @@ struct omap_hwmod_omap4_prcm {
377#define HWMOD_NO_OCP_AUTOIDLE (1 << 4) 381#define HWMOD_NO_OCP_AUTOIDLE (1 << 4)
378#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5) 382#define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5)
379#define HWMOD_NO_IDLEST (1 << 6) 383#define HWMOD_NO_IDLEST (1 << 6)
384#define HWMOD_CONTROL_OPT_CLKS_IN_RESET (1 << 7)
380 385
381/* 386/*
382 * omap_hwmod._int_flags definitions 387 * omap_hwmod._int_flags definitions