diff options
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 51 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap_hwmod.h | 5 |
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 | ||
549 | static 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 | |||
564 | static 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 | */ |
977 | static int _reset(struct omap_hwmod *oh) | 1007 | static 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 | |||
1060 | dis_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 |