* [PATCH 0/5] ARM: OMAP2+: hwmod/clk related fixes
@ 2016-06-30 13:14 Tero Kristo
2016-06-30 13:14 ` [PATCH 1/5] ARM: OMAP2+: omap_device: create clock alias purely from DT data Tero Kristo
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Tero Kristo @ 2016-06-30 13:14 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
These patches have been split out of the series here:
http://www.spinics.net/lists/arm-kernel/msg510985.html
Basically a few fixes to the hwmod / clk related functionality
under mach-omap2.
This split up series has been boot tested on following platforms:
: Board : Boot WRN version
1: am335x-evm : PASS 0 4.7.0-rc1-00005-g8238af6
2: am335x-evmsk : PASS 0 4.7.0-rc1-00005-g8238af6
3: am3517-evm : PASS 1 4.7.0-rc1-00005-g8238af6
4: am37x-evm : PASS 0 4.7.0-rc1-00005-g8238af6
5: am437x-sk : PASS 0 4.7.0-rc1-00005-g8238af6
6: am43x-epos-evm : PASS 0 4.7.0-rc1-00005-g8238af6
7: am437x-gp-evm : PASS 0 4.7.0-rc1-00005-g8238af6
8: am57xx-evm : PASS 3 4.7.0-rc1-00005-g8238af6
9: omap3-beagle-xm : PASS 0 4.7.0-rc1-00005-g8238af6
10: omap3-beagle : PASS 0 4.7.0-rc1-00005-g8238af6
11: am335x-boneblack: PASS 0 4.7.0-rc1-00005-g8238af6
12: am335x-bone : PASS 0 4.7.0-rc1-00005-g8238af6
13: craneboard : PASS 1 4.7.0-rc1-00005-g8238af6
14: dra72x-evm : FAIL 3 4.7.0-rc1-00005-g8238af6
15: dra7xx-evm : PASS 3 4.7.0-rc1-00005-g8238af6
16: ldp3430 : FAIL 0
17: omap3-n900 : PASS 0 4.7.0-rc1-00005-g8238af6
18: omap5-uevm : PASS 0 4.7.0-rc1-00005-g8238af6
19: omap4-panda-es : PASS 0 4.7.0-rc1-00005-g8238af6
20: omap4-panda : PASS 0 4.7.0-rc1-00005-g8238af6
21: omap2430-sdp : PASS 0 4.7.0-rc1-00005-g8238af6
22: omap3430-sdp : PASS 0 4.7.0-rc1-00005-g8238af6
23: omap4-sdp-es23plus: PASS 0 4.7.0-rc1-00005-g8238af6
TOTAL = 23 boards, Booted Boards = 21, No Boot boards = 2
Does not generate any new boot warnings, or other visible side effects.
The two failing boards seem to be broken in the farm in general, as they
fail with any kernel.
Patches also available here:
tree: https://github.com/t-kristo/linux-pm.git
branch: 4.7-rc1-hwmod-fixes
-Tero
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/5] ARM: OMAP2+: omap_device: create clock alias purely from DT data
2016-06-30 13:14 [PATCH 0/5] ARM: OMAP2+: hwmod/clk related fixes Tero Kristo
@ 2016-06-30 13:14 ` Tero Kristo
2016-06-30 13:15 ` [PATCH 2/5] ARM: OMAP2+: hwmod: fetch main_clk based on hwmod name Tero Kristo
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Tero Kristo @ 2016-06-30 13:14 UTC (permalink / raw)
To: linux-arm-kernel
This avoids the need to add most of the clock aliases under
drivers/clk/ti/clk-xyz.c files.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/omap_device.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index f7ff3b9..b32d7c8 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -63,7 +63,22 @@ static void _add_clkdev(struct omap_device *od, const char *clk_alias,
return;
}
- rc = clk_add_alias(clk_alias, dev_name(&od->pdev->dev), clk_name, NULL);
+ r = clk_get_sys(NULL, clk_name);
+
+ if (IS_ERR(r) && of_have_populated_dt()) {
+ struct of_phandle_args clkspec;
+
+ clkspec.np = of_find_node_by_name(NULL, clk_name);
+
+ r = of_clk_get_from_provider(&clkspec);
+
+ rc = clk_register_clkdev(r, clk_alias,
+ dev_name(&od->pdev->dev));
+ } else {
+ rc = clk_add_alias(clk_alias, dev_name(&od->pdev->dev),
+ clk_name, NULL);
+ }
+
if (rc) {
if (rc == -ENODEV || rc == -ENOMEM)
dev_err(&od->pdev->dev,
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/5] ARM: OMAP2+: hwmod: fetch main_clk based on hwmod name
2016-06-30 13:14 [PATCH 0/5] ARM: OMAP2+: hwmod/clk related fixes Tero Kristo
2016-06-30 13:14 ` [PATCH 1/5] ARM: OMAP2+: omap_device: create clock alias purely from DT data Tero Kristo
@ 2016-06-30 13:15 ` Tero Kristo
2016-07-04 6:54 ` Tony Lindgren
2016-06-30 13:15 ` [PATCH 3/5] ARM: OMAP2+: timer: change order of hwmod data handling Tero Kristo
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Tero Kristo @ 2016-06-30 13:15 UTC (permalink / raw)
To: linux-arm-kernel
With the transition to hwmod module clocks, all hwmods will have
their main clocks named <hwmod_name>_mod_ck. Use this info to
fetch main_clk, and use it if found.
Also, if a main_clk is found based on the hwmod name, disable
the direct PRCM modulemode access from hwmod.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/omap_hwmod.c | 49 ++++++++++++++++++++++++++++++++++++----
1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 83cb527..8adf1c1 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -200,6 +200,7 @@ struct omap_hwmod_soc_ops {
int (*init_clkdm)(struct omap_hwmod *oh);
void (*update_context_lost)(struct omap_hwmod *oh);
int (*get_context_lost)(struct omap_hwmod *oh);
+ int (*disable_direct_prcm)(struct omap_hwmod *oh);
};
/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
@@ -776,17 +777,34 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
* @oh: struct omap_hwmod *
*
* Called from _init_clocks(). Populates the @oh _clk (main
- * functional clock pointer) if a main_clk is present. Returns 0 on
- * success or -EINVAL on error.
+ * functional clock pointer) if a clock matching the hwmod name is found,
+ * or a main_clk is present. Returns 0 on success or -EINVAL on error.
*/
static int _init_main_clk(struct omap_hwmod *oh)
{
int ret = 0;
+ char name[32];
+ static int max_len;
+ struct clk *clk;
- if (!oh->main_clk)
- return 0;
+ strcpy(name, oh->name);
+ strcat(name, "_mod_ck");
+
+ if (strlen(name) > max_len)
+ max_len = strlen(name);
+
+ clk = clk_get(NULL, name);
+ if (!IS_ERR(clk)) {
+ oh->_clk = clk;
+ soc_ops.disable_direct_prcm(oh);
+ oh->main_clk = kstrdup(name, GFP_KERNEL);
+ } else {
+ if (!oh->main_clk)
+ return 0;
+
+ oh->_clk = clk_get(NULL, oh->main_clk);
+ }
- oh->_clk = clk_get(NULL, oh->main_clk);
if (IS_ERR(oh->_clk)) {
pr_warn("omap_hwmod: %s: cannot clk_get main_clk %s\n",
oh->name, oh->main_clk);
@@ -3091,6 +3109,25 @@ static int _omap4_is_hardreset_asserted(struct omap_hwmod *oh,
}
/**
+ * _omap4_disable_direct_prcm - disable direct PRCM control for hwmod
+ * @oh: struct omap_hwmod * to disable control for
+ *
+ * Disables direct PRCM clkctrl done by hwmod core. Instead, the hwmod
+ * will be using its main_clk to enable/disable the module. Returns
+ * 0 if successful.
+ */
+static int _omap4_disable_direct_prcm(struct omap_hwmod *oh)
+{
+ if (!oh)
+ return -EINVAL;
+
+ oh->prcm.omap4.clkctrl_offs = 0;
+ oh->prcm.omap4.modulemode = 0;
+
+ return 0;
+}
+
+/**
* _am33xx_deassert_hardreset - call AM33XX PRM hardreset fn with hwmod args
* @oh: struct omap_hwmod * to deassert hardreset
* @ohri: hardreset line data
@@ -3913,6 +3950,7 @@ void __init omap_hwmod_init(void)
soc_ops.init_clkdm = _init_clkdm;
soc_ops.update_context_lost = _omap4_update_context_lost;
soc_ops.get_context_lost = _omap4_get_context_lost;
+ soc_ops.disable_direct_prcm = _omap4_disable_direct_prcm;
} else if (cpu_is_ti814x() || cpu_is_ti816x() || soc_is_am33xx() ||
soc_is_am43xx()) {
soc_ops.enable_module = _omap4_enable_module;
@@ -3922,6 +3960,7 @@ void __init omap_hwmod_init(void)
soc_ops.deassert_hardreset = _am33xx_deassert_hardreset;
soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
soc_ops.init_clkdm = _init_clkdm;
+ soc_ops.disable_direct_prcm = _omap4_disable_direct_prcm;
} else {
WARN(1, "omap_hwmod: unknown SoC type\n");
}
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/5] ARM: OMAP2+: timer: change order of hwmod data handling
2016-06-30 13:14 [PATCH 0/5] ARM: OMAP2+: hwmod/clk related fixes Tero Kristo
2016-06-30 13:14 ` [PATCH 1/5] ARM: OMAP2+: omap_device: create clock alias purely from DT data Tero Kristo
2016-06-30 13:15 ` [PATCH 2/5] ARM: OMAP2+: hwmod: fetch main_clk based on hwmod name Tero Kristo
@ 2016-06-30 13:15 ` Tero Kristo
2016-06-30 13:15 ` [PATCH 4/5] ARM: OMAP2+: clockdomain: add usecounting support to autoidle APIs Tero Kristo
2016-06-30 13:15 ` [PATCH 5/5] ARM: AM33xx: fix module_wait_ready without clkctrl register Tero Kristo
4 siblings, 0 replies; 10+ messages in thread
From: Tero Kristo @ 2016-06-30 13:15 UTC (permalink / raw)
To: linux-arm-kernel
With the introduction of hwmod module clocks, the name of the hwmod
main clk may not be available before hwmod setup, as hwmod setup
may lookup the main clock dynamically based on the hwmod name.
Thus, change the order of hwmod setup and main clock handling for
the timer code, to make sure the main clock is going to be
available.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/timer.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 5b385bb..e7eccf6 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -289,6 +289,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
if (!timer->io_base)
return -ENXIO;
+ omap_hwmod_setup_one(oh_name);
+
/* After the dmtimer is using hwmod these clocks won't be needed */
timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
if (IS_ERR(timer->fclk))
@@ -303,7 +305,6 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
clk_put(src);
- omap_hwmod_setup_one(oh_name);
omap_hwmod_enable(oh);
__omap_dm_timer_init_regs(timer);
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/5] ARM: OMAP2+: clockdomain: add usecounting support to autoidle APIs
2016-06-30 13:14 [PATCH 0/5] ARM: OMAP2+: hwmod/clk related fixes Tero Kristo
` (2 preceding siblings ...)
2016-06-30 13:15 ` [PATCH 3/5] ARM: OMAP2+: timer: change order of hwmod data handling Tero Kristo
@ 2016-06-30 13:15 ` Tero Kristo
2016-06-30 13:15 ` [PATCH 5/5] ARM: AM33xx: fix module_wait_ready without clkctrl register Tero Kristo
4 siblings, 0 replies; 10+ messages in thread
From: Tero Kristo @ 2016-06-30 13:15 UTC (permalink / raw)
To: linux-arm-kernel
The previous implementation was racy in many locations, where the current
status of the clockdomain was read out, some operations were executed,
and the previous status info was used afterwards to decide next state
for the clockdomain. Instead, fix the implementation of the allow_idle /
deny_idle APIs to properly have usecounting support. This allows clean
handling internally within the clockdomain core, and simplifies the
usage also within hwmod.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/clockdomain.c | 36 ++++++++++++++++++++++++------------
arch/arm/mach-omap2/clockdomain.h | 2 ++
arch/arm/mach-omap2/cpuidle44xx.c | 2 +-
arch/arm/mach-omap2/omap-smp.c | 2 +-
arch/arm/mach-omap2/omap_hwmod.c | 27 ++++++++++++---------------
arch/arm/mach-omap2/pm.c | 8 +-------
arch/arm/mach-omap2/powerdomain.c | 20 ++++++--------------
7 files changed, 47 insertions(+), 50 deletions(-)
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 2da3b5e..b79b1ca 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -465,10 +465,7 @@ int clkdm_complete_init(void)
return -EACCES;
list_for_each_entry(clkdm, &clkdm_list, node) {
- if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
- clkdm_wakeup(clkdm);
- else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
- clkdm_deny_idle(clkdm);
+ clkdm_deny_idle(clkdm);
_resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs);
clkdm_clear_all_wkdeps(clkdm);
@@ -925,11 +922,20 @@ void clkdm_allow_idle_nolock(struct clockdomain *clkdm)
if (!clkdm)
return;
- if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) {
- pr_debug("clock: %s: automatic idle transitions cannot be enabled\n",
- clkdm->name);
+ if (!WARN_ON(!clkdm->forcewake_count))
+ clkdm->forcewake_count--;
+
+ if (clkdm->forcewake_count)
+ return;
+
+ if (!clkdm->usecount && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
+ clkdm_sleep_nolock(clkdm);
+
+ if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO))
+ return;
+
+ if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING)
return;
- }
if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle)
return;
@@ -974,11 +980,17 @@ void clkdm_deny_idle_nolock(struct clockdomain *clkdm)
if (!clkdm)
return;
- if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) {
- pr_debug("clockdomain: %s: automatic idle transitions cannot be disabled\n",
- clkdm->name);
+ if (clkdm->forcewake_count++)
+ return;
+
+ if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+ clkdm_wakeup_nolock(clkdm);
+
+ if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO))
+ return;
+
+ if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING)
return;
- }
if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle)
return;
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 2c398ce..24667a5 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -114,6 +114,7 @@ struct omap_hwmod;
* @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up
* @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact
* @usecount: Usecount tracking
+ * @forcewake_count: Usecount for forcing the domain active
* @node: list_head to link all clockdomains together
*
* @prcm_partition should be a macro from mach-omap2/prcm44xx.h (OMAP4 only)
@@ -138,6 +139,7 @@ struct clockdomain {
struct clkdm_dep *wkdep_srcs;
struct clkdm_dep *sleepdep_srcs;
int usecount;
+ int forcewake_count;
struct list_head node;
};
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 4b8e9f4..fa138d4 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -140,7 +140,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
mpuss_can_lose_context)
gic_dist_disable();
- clkdm_wakeup(cpu_clkdm[1]);
+ clkdm_deny_idle(cpu_clkdm[1]);
omap_set_pwrdm_state(cpu_pd[1], PWRDM_POWER_ON);
clkdm_allow_idle(cpu_clkdm[1]);
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index c625cc1..690bfa5 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -143,7 +143,7 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
* Ensure that CPU power state is set to ON to avoid CPU
* powerdomain transition on wfi
*/
- clkdm_wakeup_nolock(cpu1_clkdm);
+ clkdm_deny_idle_nolock(cpu1_clkdm);
pwrdm_set_next_pwrst(cpu1_pwrdm, PWRDM_POWER_ON);
clkdm_allow_idle_nolock(cpu1_clkdm);
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 8adf1c1..66809c2 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1696,7 +1696,6 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
{
struct omap_hwmod_rst_info ohri;
int ret = -EINVAL;
- int hwsup = 0;
if (!oh)
return -EINVAL;
@@ -1714,7 +1713,7 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
* might not be completed. The clockdomain can be set
* in HW_AUTO only when the module become ready.
*/
- hwsup = clkdm_in_hwsup(oh->clkdm);
+ clkdm_deny_idle(oh->clkdm);
ret = clkdm_hwmod_enable(oh->clkdm, oh);
if (ret) {
WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
@@ -1741,8 +1740,7 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
* Set the clockdomain to HW_AUTO, assuming that the
* previous state was HW_AUTO.
*/
- if (hwsup)
- clkdm_allow_idle(oh->clkdm);
+ clkdm_allow_idle(oh->clkdm);
clkdm_hwmod_disable(oh->clkdm, oh);
}
@@ -2096,7 +2094,6 @@ static int _enable_preprogram(struct omap_hwmod *oh)
static int _enable(struct omap_hwmod *oh)
{
int r;
- int hwsup = 0;
pr_debug("omap_hwmod: %s: enabling\n", oh->name);
@@ -2156,8 +2153,7 @@ static int _enable(struct omap_hwmod *oh)
* completely the module. The clockdomain can be set
* in HW_AUTO only when the module become ready.
*/
- hwsup = clkdm_in_hwsup(oh->clkdm) &&
- !clkdm_missing_idle_reporting(oh->clkdm);
+ clkdm_deny_idle(oh->clkdm);
r = clkdm_hwmod_enable(oh->clkdm, oh);
if (r) {
WARN(1, "omap_hwmod: %s: could not enable clockdomain %s: %d\n",
@@ -2177,14 +2173,10 @@ static int _enable(struct omap_hwmod *oh)
r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) :
-EINVAL;
- if (!r) {
- /*
- * Set the clockdomain to HW_AUTO only if the target is ready,
- * assuming that the previous state was HW_AUTO
- */
- if (oh->clkdm && hwsup)
- clkdm_allow_idle(oh->clkdm);
+ if (oh->clkdm)
+ clkdm_allow_idle(oh->clkdm);
+ if (!r) {
oh->_state = _HWMOD_STATE_ENABLED;
/* Access the sysconfig only if the target is ready */
@@ -2238,6 +2230,9 @@ static int _idle(struct omap_hwmod *oh)
_idle_sysc(oh);
_del_initiator_dep(oh, mpu_oh);
+ if (oh->clkdm)
+ clkdm_deny_idle(oh->clkdm);
+
if (oh->flags & HWMOD_BLOCK_WFI)
cpu_idle_poll_ctrl(false);
if (soc_ops.disable_module)
@@ -2250,8 +2245,10 @@ static int _idle(struct omap_hwmod *oh)
* transition to complete properly.
*/
_disable_clocks(oh);
- if (oh->clkdm)
+ if (oh->clkdm) {
+ clkdm_allow_idle(oh->clkdm);
clkdm_hwmod_disable(oh->clkdm, oh);
+ }
/* Mux pins for device idle if populated */
if (oh->mux && oh->mux->pads_dynamic) {
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 2f7b11d..678d2a3 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -110,13 +110,7 @@ static void __init omap2_init_processor_devices(void)
int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
{
- /* XXX The usecount test is racy */
- if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
- !(clkdm->flags & CLKDM_MISSING_IDLE_REPORTING))
- clkdm_allow_idle(clkdm);
- else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
- clkdm->usecount == 0)
- clkdm_sleep(clkdm);
+ clkdm_allow_idle(clkdm);
return 0;
}
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 78af6d8..be7a976 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -222,7 +222,6 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
* @pwrdm: struct powerdomain * to operate on
* @curr_pwrst: current power state of @pwrdm
* @pwrst: power state to switch to
- * @hwsup: ptr to a bool to return whether the clkdm is hardware-supervised
*
* Determine whether the powerdomain needs to be turned on before
* attempting to switch power states. Called by
@@ -233,8 +232,7 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
* "Types of sleep_switch" comment above).
*/
static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
- u8 curr_pwrst, u8 pwrst,
- bool *hwsup)
+ u8 curr_pwrst, u8 pwrst)
{
u8 sleep_switch;
@@ -244,8 +242,7 @@ static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
arch_pwrdm->pwrdm_set_lowpwrstchange) {
sleep_switch = LOWPOWERSTATE_SWITCH;
} else {
- *hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
- clkdm_wakeup_nolock(pwrdm->pwrdm_clkdms[0]);
+ clkdm_deny_idle_nolock(pwrdm->pwrdm_clkdms[0]);
sleep_switch = FORCEWAKEUP_SWITCH;
}
} else {
@@ -259,7 +256,6 @@ static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
* _pwrdm_restore_clkdm_state - restore the clkdm hwsup state after pwrst change
* @pwrdm: struct powerdomain * to operate on
* @sleep_switch: return value from _pwrdm_save_clkdm_state_and_activate()
- * @hwsup: should @pwrdm's first clockdomain be set to hardware-supervised mode?
*
* Restore the clockdomain state perturbed by
* _pwrdm_save_clkdm_state_and_activate(), and call the power state
@@ -270,14 +266,11 @@ static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
* software-supervised sleep. No return value.
*/
static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm,
- u8 sleep_switch, bool hwsup)
+ u8 sleep_switch)
{
switch (sleep_switch) {
case FORCEWAKEUP_SWITCH:
- if (hwsup)
- clkdm_allow_idle_nolock(pwrdm->pwrdm_clkdms[0]);
- else
- clkdm_sleep_nolock(pwrdm->pwrdm_clkdms[0]);
+ clkdm_allow_idle_nolock(pwrdm->pwrdm_clkdms[0]);
break;
case LOWPOWERSTATE_SWITCH:
if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
@@ -1092,7 +1085,6 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
u8 next_pwrst, sleep_switch;
int curr_pwrst;
int ret = 0;
- bool hwsup = false;
if (!pwrdm || IS_ERR(pwrdm))
return -EINVAL;
@@ -1116,14 +1108,14 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
goto osps_out;
sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, curr_pwrst,
- pwrst, &hwsup);
+ pwrst);
ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
if (ret)
pr_err("%s: unable to set power state of powerdomain: %s\n",
__func__, pwrdm->name);
- _pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
+ _pwrdm_restore_clkdm_state(pwrdm, sleep_switch);
osps_out:
pwrdm_unlock(pwrdm);
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/5] ARM: AM33xx: fix module_wait_ready without clkctrl register
2016-06-30 13:14 [PATCH 0/5] ARM: OMAP2+: hwmod/clk related fixes Tero Kristo
` (3 preceding siblings ...)
2016-06-30 13:15 ` [PATCH 4/5] ARM: OMAP2+: clockdomain: add usecounting support to autoidle APIs Tero Kristo
@ 2016-06-30 13:15 ` Tero Kristo
4 siblings, 0 replies; 10+ messages in thread
From: Tero Kristo @ 2016-06-30 13:15 UTC (permalink / raw)
To: linux-arm-kernel
If the module has no clkctrl register defined, module_wait_ready should
not try to access this. This can potentially cause an illegal register
access, and result in bad idle reporting also.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/cm33xx.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
index 7b181f9..c073fb5 100644
--- a/arch/arm/mach-omap2/cm33xx.c
+++ b/arch/arm/mach-omap2/cm33xx.c
@@ -220,6 +220,9 @@ static int am33xx_cm_wait_module_ready(u8 part, s16 inst, u16 clkctrl_offs,
{
int i = 0;
+ if (!clkctrl_offs)
+ return 0;
+
omap_test_timeout(_is_module_ready(inst, clkctrl_offs),
MAX_MODULE_READY_TIME, i);
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/5] ARM: OMAP2+: hwmod: fetch main_clk based on hwmod name
2016-06-30 13:15 ` [PATCH 2/5] ARM: OMAP2+: hwmod: fetch main_clk based on hwmod name Tero Kristo
@ 2016-07-04 6:54 ` Tony Lindgren
2016-07-04 9:17 ` Tero Kristo
2016-07-04 11:11 ` [PATCHv2 " Tero Kristo
0 siblings, 2 replies; 10+ messages in thread
From: Tony Lindgren @ 2016-07-04 6:54 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
* Tero Kristo <t-kristo@ti.com> [160630 06:18]:
> With the transition to hwmod module clocks, all hwmods will have
> their main clocks named <hwmod_name>_mod_ck. Use this info to
> fetch main_clk, and use it if found.
..
> static int _init_main_clk(struct omap_hwmod *oh)
> {
> int ret = 0;
> + char name[32];
> + static int max_len;
> + struct clk *clk;
>
> - if (!oh->main_clk)
> - return 0;
> + strcpy(name, oh->name);
> + strcat(name, "_mod_ck");
> +
> + if (strlen(name) > max_len)
> + max_len = strlen(name);
Just noticed that this needs some improvments to avoid nasty
bugs early on. You don't seem to have max_len defined, and
you should do a strncpy using #define MOD_CLK_MAX_LEN (32 + 7)
or something similar instead of the strcpy and leave room for
the strcat.
Care to update and repost just this one?
Regards,
Tony
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/5] ARM: OMAP2+: hwmod: fetch main_clk based on hwmod name
2016-07-04 6:54 ` Tony Lindgren
@ 2016-07-04 9:17 ` Tero Kristo
2016-07-04 11:11 ` [PATCHv2 " Tero Kristo
1 sibling, 0 replies; 10+ messages in thread
From: Tero Kristo @ 2016-07-04 9:17 UTC (permalink / raw)
To: linux-arm-kernel
On 04/07/16 09:54, Tony Lindgren wrote:
> Hi,
>
> * Tero Kristo <t-kristo@ti.com> [160630 06:18]:
>> With the transition to hwmod module clocks, all hwmods will have
>> their main clocks named <hwmod_name>_mod_ck. Use this info to
>> fetch main_clk, and use it if found.
> ..
>
>> static int _init_main_clk(struct omap_hwmod *oh)
>> {
>> int ret = 0;
>> + char name[32];
>> + static int max_len;
>> + struct clk *clk;
>>
>> - if (!oh->main_clk)
>> - return 0;
>> + strcpy(name, oh->name);
>> + strcat(name, "_mod_ck");
>> +
>> + if (strlen(name) > max_len)
>> + max_len = strlen(name);
>
> Just noticed that this needs some improvments to avoid nasty
> bugs early on. You don't seem to have max_len defined, and
> you should do a strncpy using #define MOD_CLK_MAX_LEN (32 + 7)
> or something similar instead of the strcpy and leave room for
> the strcat.
>
> Care to update and repost just this one?
Yeah, let me fix this and repost a bit later today.
-Tero
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCHv2 2/5] ARM: OMAP2+: hwmod: fetch main_clk based on hwmod name
2016-07-04 6:54 ` Tony Lindgren
2016-07-04 9:17 ` Tero Kristo
@ 2016-07-04 11:11 ` Tero Kristo
2016-07-04 14:32 ` Tony Lindgren
1 sibling, 1 reply; 10+ messages in thread
From: Tero Kristo @ 2016-07-04 11:11 UTC (permalink / raw)
To: linux-arm-kernel
With the transition to hwmod module clocks, all hwmods will have
their main clocks named <hwmod_name>_mod_ck. Use this info to
fetch main_clk, and use it if found.
Also, if a main_clk is found based on the hwmod name, disable
the direct PRCM modulemode access from hwmod.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
arch/arm/mach-omap2/omap_hwmod.c | 55 ++++++++++++++++++++++++++++++++++++----
1 file changed, 50 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index be77d05..5b70938 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -178,6 +178,11 @@
*/
#define OMAP4_RST_CTRL_ST_OFFSET 4
+/*
+ * Maximum length for module clock handle names
+ */
+#define MOD_CLK_MAX_NAME_LEN 32
+
/**
* struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations
* @enable_module: function to enable a module (via MODULEMODE)
@@ -200,6 +205,7 @@ struct omap_hwmod_soc_ops {
int (*init_clkdm)(struct omap_hwmod *oh);
void (*update_context_lost)(struct omap_hwmod *oh);
int (*get_context_lost)(struct omap_hwmod *oh);
+ int (*disable_direct_prcm)(struct omap_hwmod *oh);
};
/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
@@ -776,17 +782,35 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
* @oh: struct omap_hwmod *
*
* Called from _init_clocks(). Populates the @oh _clk (main
- * functional clock pointer) if a main_clk is present. Returns 0 on
- * success or -EINVAL on error.
+ * functional clock pointer) if a clock matching the hwmod name is found,
+ * or a main_clk is present. Returns 0 on success or -EINVAL on error.
*/
static int _init_main_clk(struct omap_hwmod *oh)
{
int ret = 0;
+ char name[MOD_CLK_MAX_NAME_LEN];
+ struct clk *clk;
- if (!oh->main_clk)
- return 0;
+ /* +7 magic comes from '_mod_ck' suffix */
+ if (strlen(oh->name) + 7 > MOD_CLK_MAX_NAME_LEN)
+ pr_warn("%s: warning: cropping name for %s\n", __func__,
+ oh->name);
+
+ strncpy(name, oh->name, MOD_CLK_MAX_NAME_LEN - 7);
+ strcat(name, "_mod_ck");
+
+ clk = clk_get(NULL, name);
+ if (!IS_ERR(clk)) {
+ oh->_clk = clk;
+ soc_ops.disable_direct_prcm(oh);
+ oh->main_clk = kstrdup(name, GFP_KERNEL);
+ } else {
+ if (!oh->main_clk)
+ return 0;
+
+ oh->_clk = clk_get(NULL, oh->main_clk);
+ }
- oh->_clk = clk_get(NULL, oh->main_clk);
if (IS_ERR(oh->_clk)) {
pr_warn("omap_hwmod: %s: cannot clk_get main_clk %s\n",
oh->name, oh->main_clk);
@@ -3088,6 +3112,25 @@ static int _omap4_is_hardreset_asserted(struct omap_hwmod *oh,
}
/**
+ * _omap4_disable_direct_prcm - disable direct PRCM control for hwmod
+ * @oh: struct omap_hwmod * to disable control for
+ *
+ * Disables direct PRCM clkctrl done by hwmod core. Instead, the hwmod
+ * will be using its main_clk to enable/disable the module. Returns
+ * 0 if successful.
+ */
+static int _omap4_disable_direct_prcm(struct omap_hwmod *oh)
+{
+ if (!oh)
+ return -EINVAL;
+
+ oh->prcm.omap4.clkctrl_offs = 0;
+ oh->prcm.omap4.modulemode = 0;
+
+ return 0;
+}
+
+/**
* _am33xx_deassert_hardreset - call AM33XX PRM hardreset fn with hwmod args
* @oh: struct omap_hwmod * to deassert hardreset
* @ohri: hardreset line data
@@ -3910,6 +3953,7 @@ void __init omap_hwmod_init(void)
soc_ops.init_clkdm = _init_clkdm;
soc_ops.update_context_lost = _omap4_update_context_lost;
soc_ops.get_context_lost = _omap4_get_context_lost;
+ soc_ops.disable_direct_prcm = _omap4_disable_direct_prcm;
} else if (cpu_is_ti814x() || cpu_is_ti816x() || soc_is_am33xx() ||
soc_is_am43xx()) {
soc_ops.enable_module = _omap4_enable_module;
@@ -3919,6 +3963,7 @@ void __init omap_hwmod_init(void)
soc_ops.deassert_hardreset = _am33xx_deassert_hardreset;
soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
soc_ops.init_clkdm = _init_clkdm;
+ soc_ops.disable_direct_prcm = _omap4_disable_direct_prcm;
} else {
WARN(1, "omap_hwmod: unknown SoC type\n");
}
--
1.9.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCHv2 2/5] ARM: OMAP2+: hwmod: fetch main_clk based on hwmod name
2016-07-04 11:11 ` [PATCHv2 " Tero Kristo
@ 2016-07-04 14:32 ` Tony Lindgren
0 siblings, 0 replies; 10+ messages in thread
From: Tony Lindgren @ 2016-07-04 14:32 UTC (permalink / raw)
To: linux-arm-kernel
* Tero Kristo <t-kristo@ti.com> [160704 04:14]:
> With the transition to hwmod module clocks, all hwmods will have
> their main clocks named <hwmod_name>_mod_ck. Use this info to
> fetch main_clk, and use it if found.
>
> Also, if a main_clk is found based on the hwmod name, disable
> the direct PRCM modulemode access from hwmod.
Thanks for updating this, applying all into omap-for-v4.8/soc.
Regards,
Tony
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2016-07-04 14:32 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-30 13:14 [PATCH 0/5] ARM: OMAP2+: hwmod/clk related fixes Tero Kristo
2016-06-30 13:14 ` [PATCH 1/5] ARM: OMAP2+: omap_device: create clock alias purely from DT data Tero Kristo
2016-06-30 13:15 ` [PATCH 2/5] ARM: OMAP2+: hwmod: fetch main_clk based on hwmod name Tero Kristo
2016-07-04 6:54 ` Tony Lindgren
2016-07-04 9:17 ` Tero Kristo
2016-07-04 11:11 ` [PATCHv2 " Tero Kristo
2016-07-04 14:32 ` Tony Lindgren
2016-06-30 13:15 ` [PATCH 3/5] ARM: OMAP2+: timer: change order of hwmod data handling Tero Kristo
2016-06-30 13:15 ` [PATCH 4/5] ARM: OMAP2+: clockdomain: add usecounting support to autoidle APIs Tero Kristo
2016-06-30 13:15 ` [PATCH 5/5] ARM: AM33xx: fix module_wait_ready without clkctrl register Tero Kristo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).