From a5122ff8ceb2b1f207965a3608d3da3af832e513 Mon Sep 17 00:00:00 2001 From: Vaibhav Bedia Date: Sun, 10 Jul 2011 05:56:53 -0600 Subject: OMAP: clockdomain: Remove redundant call to pwrdm_wait_transition() The call to pwrdm_wait_transition() in clkdm_clk_enable() is redundant since the function pwrdm_clkdm_state_switch() which is called next also does the same thing. Signed-off-by: Vaibhav Bedia Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomain.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/arm/mach-omap2/clockdomain.c') diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 6cb6c03293df..4fbbbfcc9ba2 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -834,7 +834,6 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) clk->name); arch_clkdm->clkdm_clk_enable(clkdm); - pwrdm_wait_transition(clkdm->pwrdm.ptr); pwrdm_clkdm_state_switch(clkdm); return 0; -- cgit v1.2.3 From 113a74137f5c85f2c7914e78350f70247ef9447c Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Sun, 10 Jul 2011 05:56:54 -0600 Subject: OMAP2+: clockdomain: Add 2 APIs to control clockdomain from hwmod framework Duplicate the existing API for clockdomain enable from clock to enable a clock domain from hwmod framework. This will be needed when the hwmod framework will move from the current clock centric approach to the module based approach. These APIs are returning 0 for the moment for OMAP2 and OMAP3 until their hwmods are updated with the clksm attribute. Signed-off-by: Benoit Cousson Cc: Kevin Hilman Cc: Paul Walmsley Cc: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomain.c | 142 ++++++++++++++++++++++++++++---------- arch/arm/mach-omap2/clockdomain.h | 3 + 2 files changed, 109 insertions(+), 36 deletions(-) (limited to 'arch/arm/mach-omap2/clockdomain.c') diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 4fbbbfcc9ba2..5a57de563b30 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -796,7 +796,50 @@ void clkdm_deny_idle(struct clockdomain *clkdm) } -/* Clockdomain-to-clock framework interface code */ +/* Clockdomain-to-clock/hwmod framework interface code */ + +static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) +{ + if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable) + return -EINVAL; + + /* + * For arch's with no autodeps, clkcm_clk_enable + * should be called for every clock instance or hwmod that is + * enabled, so the clkdm can be force woken up. + */ + if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) + return 0; + + arch_clkdm->clkdm_clk_enable(clkdm); + pwrdm_wait_transition(clkdm->pwrdm.ptr); + pwrdm_clkdm_state_switch(clkdm); + + pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name); + + return 0; +} + +static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm) +{ + if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) + return -EINVAL; + + if (atomic_read(&clkdm->usecount) == 0) { + WARN_ON(1); /* underflow */ + return -ERANGE; + } + + if (atomic_dec_return(&clkdm->usecount) > 0) + return 0; + + arch_clkdm->clkdm_clk_disable(clkdm); + pwrdm_clkdm_state_switch(clkdm); + + pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name); + + return 0; +} /** * clkdm_clk_enable - add an enabled downstream clock to this clkdm @@ -819,24 +862,10 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) * downstream clocks for debugging purposes? */ - if (!clkdm || !clk) + if (!clk) return -EINVAL; - if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable) - return -EINVAL; - - if (atomic_inc_return(&clkdm->usecount) > 1) - return 0; - - /* Clockdomain now has one enabled downstream clock */ - - pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name, - clk->name); - - arch_clkdm->clkdm_clk_enable(clkdm); - pwrdm_clkdm_state_switch(clkdm); - - return 0; + return _clkdm_clk_hwmod_enable(clkdm); } /** @@ -849,9 +878,8 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) * clockdomain usecount goes to 0, put the clockdomain to sleep * (software-supervised mode) or remove the clkdm autodependencies * (hardware-supervised mode). Returns -EINVAL if passed null - * pointers; -ERANGE if the @clkdm usecount underflows and debugging - * is enabled; or returns 0 upon success or if the clockdomain is in - * hwsup idle mode. + * pointers; -ERANGE if the @clkdm usecount underflows; or returns 0 + * upon success or if the clockdomain is in hwsup idle mode. */ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) { @@ -860,30 +888,72 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) * downstream clocks for debugging purposes? */ - if (!clkdm || !clk) + if (!clk) return -EINVAL; - if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable) + return _clkdm_clk_hwmod_disable(clkdm); +} + +/** + * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm + * @clkdm: struct clockdomain * + * @oh: struct omap_hwmod * of the enabled downstream hwmod + * + * Increment the usecount of the clockdomain @clkdm and ensure that it + * is awake before @oh is enabled. Intended to be called by + * module_enable() code. + * If the clockdomain is in software-supervised idle mode, force the + * clockdomain to wake. If the clockdomain is in hardware-supervised idle + * mode, add clkdm-pwrdm autodependencies, to ensure that devices in the + * clockdomain can be read from/written to by on-chip processors. + * Returns -EINVAL if passed null pointers; + * returns 0 upon success or if the clockdomain is in hwsup idle mode. + */ +int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh) +{ + /* The clkdm attribute does not exist yet prior OMAP4 */ + if (cpu_is_omap24xx() || cpu_is_omap34xx()) + return 0; + + /* + * XXX Rewrite this code to maintain a list of enabled + * downstream hwmods for debugging purposes? + */ + + if (!oh) return -EINVAL; -#ifdef DEBUG - if (atomic_read(&clkdm->usecount) == 0) { - WARN_ON(1); /* underflow */ - return -ERANGE; - } -#endif + return _clkdm_clk_hwmod_enable(clkdm); +} - if (atomic_dec_return(&clkdm->usecount) > 0) +/** + * clkdm_hwmod_disable - remove an enabled downstream hwmod from this clkdm + * @clkdm: struct clockdomain * + * @oh: struct omap_hwmod * of the disabled downstream hwmod + * + * Decrement the usecount of this clockdomain @clkdm when @oh is + * disabled. Intended to be called by module_disable() code. + * If the clockdomain usecount goes to 0, put the clockdomain to sleep + * (software-supervised mode) or remove the clkdm autodependencies + * (hardware-supervised mode). + * Returns -EINVAL if passed null pointers; -ERANGE if the @clkdm usecount + * underflows; or returns 0 upon success or if the clockdomain is in hwsup + * idle mode. + */ +int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh) +{ + /* The clkdm attribute does not exist yet prior OMAP4 */ + if (cpu_is_omap24xx() || cpu_is_omap34xx()) return 0; - /* All downstream clocks of this clockdomain are now disabled */ - - pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name, - clk->name); + /* + * XXX Rewrite this code to maintain a list of enabled + * downstream hwmods for debugging purposes? + */ - arch_clkdm->clkdm_clk_disable(clkdm); - pwrdm_clkdm_state_switch(clkdm); + if (!oh) + return -EINVAL; - return 0; + return _clkdm_clk_hwmod_disable(clkdm); } diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 5823584d9cd7..8e0da642355c 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -20,6 +20,7 @@ #include "powerdomain.h" #include +#include #include /* @@ -183,6 +184,8 @@ int clkdm_sleep(struct clockdomain *clkdm); int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); +int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh); +int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh); extern void __init omap2xxx_clockdomains_init(void); extern void __init omap3xxx_clockdomains_init(void); -- cgit v1.2.3 From 32a363c0f5b44cb4e9adfe238dfc4efa9270f7ae Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Sun, 10 Jul 2011 05:56:54 -0600 Subject: OMAP2+: clockdomain: add clkdm_in_hwsup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new function, clkdm_in_hwsup(), that returns true if a clockdomain is configured for hardware-supervised idle. It does not actually read the hardware; rather, it checks an internal flag in the struct clockdomain, which is changed when the clockdomain is switched in and out of hardware-supervised idle. This should be safe, since all changes to the idle mode should pass through the clockdomain code. Based on a set of patches by Rajendra Nayak which do the same thing by checking the hardware bits. This approach should be faster and more compact. Signed-off-by: Paul Walmsley Cc: Rajendra Nayak Cc: Todd Poynor Cc: Benoît Cousson --- arch/arm/mach-omap2/clockdomain.c | 30 ++++++++++++++++++++++++++++-- arch/arm/mach-omap2/clockdomain.h | 6 ++++++ 2 files changed, 34 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-omap2/clockdomain.c') diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 5a57de563b30..239b558853f5 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -1,8 +1,8 @@ /* * OMAP2/3/4 clockdomain framework functions * - * Copyright (C) 2008-2010 Texas Instruments, Inc. - * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2008-2011 Texas Instruments, Inc. + * Copyright (C) 2008-2011 Nokia Corporation * * Written by Paul Walmsley and Jouni Högander * Added OMAP4 specific support by Abhijit Pagare @@ -704,6 +704,8 @@ int clkdm_sleep(struct clockdomain *clkdm) pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name); + clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; + return arch_clkdm->clkdm_sleep(clkdm); } @@ -732,6 +734,8 @@ int clkdm_wakeup(struct clockdomain *clkdm) pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name); + clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; + return arch_clkdm->clkdm_wakeup(clkdm); } @@ -762,6 +766,8 @@ void clkdm_allow_idle(struct clockdomain *clkdm) pr_debug("clockdomain: enabling automatic idle transitions for %s\n", clkdm->name); + clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED; + arch_clkdm->clkdm_allow_idle(clkdm); pwrdm_clkdm_state_switch(clkdm); } @@ -792,9 +798,29 @@ void clkdm_deny_idle(struct clockdomain *clkdm) pr_debug("clockdomain: disabling automatic idle transitions for %s\n", clkdm->name); + clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; + arch_clkdm->clkdm_deny_idle(clkdm); } +/** + * clkdm_in_hwsup - is clockdomain @clkdm have hardware-supervised idle enabled? + * @clkdm: struct clockdomain * + * + * Returns true if clockdomain @clkdm currently has + * hardware-supervised idle enabled, or false if it does not or if + * @clkdm is NULL. It is only valid to call this function after + * clkdm_init() has been called. This function does not actually read + * bits from the hardware; it instead tests an in-memory flag that is + * changed whenever the clockdomain code changes the auto-idle mode. + */ +bool clkdm_in_hwsup(struct clockdomain *clkdm) +{ + if (!clkdm) + return false; + + return (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false; +} /* Clockdomain-to-clock/hwmod framework interface code */ diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 8e0da642355c..8782a5cadfa6 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -83,6 +83,9 @@ struct clkdm_dep { const struct omap_chip_id omap_chip; }; +/* Possible flags for struct clockdomain._flags */ +#define _CLKDM_FLAG_HWSUP_ENABLED BIT(0) + /** * struct clockdomain - OMAP clockdomain * @name: clockdomain name @@ -90,6 +93,7 @@ struct clkdm_dep { * @clktrctrl_reg: CLKSTCTRL reg for the given clock domain * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg * @flags: Clockdomain capability flags + * @_flags: Flags for use only by internal clockdomain code * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit * @prcm_partition: (OMAP4 only) PRCM partition ID for this clkdm's registers * @cm_inst: (OMAP4 only) CM instance register offset @@ -114,6 +118,7 @@ struct clockdomain { } pwrdm; const u16 clktrctrl_mask; const u8 flags; + u8 _flags; const u8 dep_bit; const u8 prcm_partition; const s16 cm_inst; @@ -178,6 +183,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); void clkdm_allow_idle(struct clockdomain *clkdm); void clkdm_deny_idle(struct clockdomain *clkdm); +bool clkdm_in_hwsup(struct clockdomain *clkdm); int clkdm_wakeup(struct clockdomain *clkdm); int clkdm_sleep(struct clockdomain *clkdm); -- cgit v1.2.3 From 555e74ea08bfc04a0136f976cbaa200addf1ba87 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Sun, 10 Jul 2011 05:56:55 -0600 Subject: OMAP2+: clockdomain: Add per clkdm lock to prevent concurrent state programming Since the clkdm state programming is now done from within the hwmod framework (which uses a per-hwmod lock) instead of the being done from the clock framework (which used a global lock), there is now a need to have per-clkdm locking to prevent races between different hwmods/modules belonging to the same clock domain concurrently programming the clkdm state. Signed-off-by: Rajendra Nayak Signed-off-by: Benoit Cousson Cc: Paul Walmsley Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomain.c | 47 +++++++++++++++++++++++++----- arch/arm/mach-omap2/clockdomain.h | 2 ++ arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 6 ++-- arch/arm/mach-omap2/clockdomain44xx.c | 13 +++------ 4 files changed, 50 insertions(+), 18 deletions(-) (limited to 'arch/arm/mach-omap2/clockdomain.c') diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 239b558853f5..ab7db083f97f 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -92,6 +92,8 @@ static int _clkdm_register(struct clockdomain *clkdm) pwrdm_add_clkdm(pwrdm, clkdm); + spin_lock_init(&clkdm->lock); + pr_debug("clockdomain: registered %s\n", clkdm->name); return 0; @@ -690,6 +692,9 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) */ int clkdm_sleep(struct clockdomain *clkdm) { + int ret; + unsigned long flags; + if (!clkdm) return -EINVAL; @@ -704,9 +709,11 @@ int clkdm_sleep(struct clockdomain *clkdm) pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name); + spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; - - return arch_clkdm->clkdm_sleep(clkdm); + ret = arch_clkdm->clkdm_sleep(clkdm); + spin_unlock_irqrestore(&clkdm->lock, flags); + return ret; } /** @@ -720,6 +727,9 @@ int clkdm_sleep(struct clockdomain *clkdm) */ int clkdm_wakeup(struct clockdomain *clkdm) { + int ret; + unsigned long flags; + if (!clkdm) return -EINVAL; @@ -734,9 +744,11 @@ int clkdm_wakeup(struct clockdomain *clkdm) pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name); + spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; - - return arch_clkdm->clkdm_wakeup(clkdm); + ret = arch_clkdm->clkdm_wakeup(clkdm); + spin_unlock_irqrestore(&clkdm->lock, flags); + return ret; } /** @@ -751,6 +763,8 @@ int clkdm_wakeup(struct clockdomain *clkdm) */ void clkdm_allow_idle(struct clockdomain *clkdm) { + unsigned long flags; + if (!clkdm) return; @@ -766,10 +780,11 @@ void clkdm_allow_idle(struct clockdomain *clkdm) pr_debug("clockdomain: enabling automatic idle transitions for %s\n", clkdm->name); + spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED; - arch_clkdm->clkdm_allow_idle(clkdm); pwrdm_clkdm_state_switch(clkdm); + spin_unlock_irqrestore(&clkdm->lock, flags); } /** @@ -783,6 +798,8 @@ void clkdm_allow_idle(struct clockdomain *clkdm) */ void clkdm_deny_idle(struct clockdomain *clkdm) { + unsigned long flags; + if (!clkdm) return; @@ -798,9 +815,10 @@ void clkdm_deny_idle(struct clockdomain *clkdm) pr_debug("clockdomain: disabling automatic idle transitions for %s\n", clkdm->name); + spin_lock_irqsave(&clkdm->lock, flags); clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED; - arch_clkdm->clkdm_deny_idle(clkdm); + spin_unlock_irqrestore(&clkdm->lock, flags); } /** @@ -816,16 +834,25 @@ void clkdm_deny_idle(struct clockdomain *clkdm) */ bool clkdm_in_hwsup(struct clockdomain *clkdm) { + bool ret; + unsigned long flags; + if (!clkdm) return false; - return (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false; + spin_lock_irqsave(&clkdm->lock, flags); + ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false; + spin_unlock_irqrestore(&clkdm->lock, flags); + + return ret; } /* Clockdomain-to-clock/hwmod framework interface code */ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) { + unsigned long flags; + if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable) return -EINVAL; @@ -837,9 +864,11 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) return 0; + spin_lock_irqsave(&clkdm->lock, flags); arch_clkdm->clkdm_clk_enable(clkdm); pwrdm_wait_transition(clkdm->pwrdm.ptr); pwrdm_clkdm_state_switch(clkdm); + spin_unlock_irqrestore(&clkdm->lock, flags); pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name); @@ -848,6 +877,8 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm) { + unsigned long flags; + if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) return -EINVAL; @@ -859,8 +890,10 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm) if (atomic_dec_return(&clkdm->usecount) > 0) return 0; + spin_lock_irqsave(&clkdm->lock, flags); arch_clkdm->clkdm_clk_disable(clkdm); pwrdm_clkdm_state_switch(clkdm); + spin_unlock_irqrestore(&clkdm->lock, flags); pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name); diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 8782a5cadfa6..1e50c88b8a07 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -17,6 +17,7 @@ #define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H #include +#include #include "powerdomain.h" #include @@ -128,6 +129,7 @@ struct clockdomain { const struct omap_chip_id omap_chip; atomic_t usecount; struct list_head node; + spinlock_t lock; }; /** diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index 48d0db7e6069..f740edb111f4 100644 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -183,7 +183,8 @@ static int omap2_clkdm_clk_enable(struct clockdomain *clkdm) _clkdm_add_autodeps(clkdm); _enable_hwsup(clkdm); } else { - clkdm_wakeup(clkdm); + if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) + omap2_clkdm_wakeup(clkdm); } return 0; @@ -205,7 +206,8 @@ static int omap2_clkdm_clk_disable(struct clockdomain *clkdm) _clkdm_del_autodeps(clkdm); _enable_hwsup(clkdm); } else { - clkdm_sleep(clkdm); + if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP) + omap2_clkdm_sleep(clkdm); } return 0; diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c index a1a4ecd26544..b43706aa08bd 100644 --- a/arch/arm/mach-omap2/clockdomain44xx.c +++ b/arch/arm/mach-omap2/clockdomain44xx.c @@ -95,13 +95,8 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) { - bool hwsup = false; - - hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, - clkdm->cm_inst, clkdm->clkdm_offs); - - if (!hwsup) - clkdm_wakeup(clkdm); + if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) + return omap4_clkdm_wakeup(clkdm); return 0; } @@ -113,8 +108,8 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm) hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, clkdm->cm_inst, clkdm->clkdm_offs); - if (!hwsup) - clkdm_sleep(clkdm); + if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) + omap4_clkdm_sleep(clkdm); return 0; } -- cgit v1.2.3