From f5dd3bb53ca45f3b47c6889e5920c562f5a37359 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Sat, 10 Nov 2012 16:58:41 -0700 Subject: ARM: OMAP: hwmod: Fix up hwmod based clkdm accesses hwmod uses deferencing the clk pointer to acccess the clkdm. With COMMON clk hwoever this will need to be deferenced through the clk_hw_omap pointer, so do the necessary changes. Signed-off-by: Rajendra Nayak Signed-off-by: Mike Turquette Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 70 ++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 14 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 139adca3bda1..f38e4cefa2a5 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -130,7 +130,11 @@ #include #include #include +#ifdef CONFIG_COMMON_CLK +#include +#else #include +#endif #include #include #include @@ -614,6 +618,23 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) return 0; } +static struct clockdomain *_get_clkdm(struct omap_hwmod *oh) +{ + if (oh->clkdm) { + return oh->clkdm; + } else if (oh->_clk) { +#ifdef CONFIG_COMMON_CLK + struct clk_hw_omap *clk; + + clk = to_clk_hw_omap(__clk_get_hw(oh->_clk)); + return clk->clkdm; +#else + return oh->_clk->clkdm; +#endif + } + return NULL; +} + /** * _add_initiator_dep: prevent @oh from smart-idling while @init_oh is active * @oh: struct omap_hwmod * @@ -629,13 +650,18 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) */ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) { - if (!oh->_clk) + struct clockdomain *clkdm, *init_clkdm; + + clkdm = _get_clkdm(oh); + init_clkdm = _get_clkdm(init_oh); + + if (!clkdm || !init_clkdm) return -EINVAL; - if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS) + if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS) return 0; - return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); + return clkdm_add_sleepdep(clkdm, init_clkdm); } /** @@ -653,13 +679,18 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) */ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) { - if (!oh->_clk) + struct clockdomain *clkdm, *init_clkdm; + + clkdm = _get_clkdm(oh); + init_clkdm = _get_clkdm(init_oh); + + if (!clkdm || !init_clkdm) return -EINVAL; - if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS) + if (clkdm && clkdm->flags & CLKDM_NO_AUTODEPS) return 0; - return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); + return clkdm_del_sleepdep(clkdm, init_clkdm); } /** @@ -693,7 +724,7 @@ static int _init_main_clk(struct omap_hwmod *oh) */ clk_prepare(oh->_clk); - if (!oh->_clk->clkdm) + if (!_get_clkdm(oh)) pr_debug("omap_hwmod: %s: missing clockdomain for %s.\n", oh->name, oh->main_clk); @@ -1276,6 +1307,7 @@ static void _enable_sysc(struct omap_hwmod *oh) u8 idlemode, sf; u32 v; bool clkdm_act; + struct clockdomain *clkdm; if (!oh->class->sysc) return; @@ -1283,11 +1315,9 @@ static void _enable_sysc(struct omap_hwmod *oh) v = oh->_sysc_cache; sf = oh->class->sysc->sysc_flags; + clkdm = _get_clkdm(oh); if (sf & SYSC_HAS_SIDLEMODE) { - clkdm_act = ((oh->clkdm && - oh->clkdm->flags & CLKDM_ACTIVE_WITH_MPU) || - (oh->_clk && oh->_clk->clkdm && - oh->_clk->clkdm->flags & CLKDM_ACTIVE_WITH_MPU)); + clkdm_act = (clkdm && clkdm->flags & CLKDM_ACTIVE_WITH_MPU); if (clkdm_act && !(oh->class->sysc->idlemodes & (SIDLE_SMART | SIDLE_SMART_WKUP))) idlemode = HWMOD_IDLEMODE_FORCE; @@ -3556,10 +3586,17 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh) { struct clk *c; struct omap_hwmod_ocp_if *oi; + struct clockdomain *clkdm; +#ifdef CONFIG_COMMON_CLK + struct clk_hw_omap *clk; +#endif if (!oh) return NULL; + if (oh->clkdm) + return oh->clkdm->pwrdm.ptr; + if (oh->_clk) { c = oh->_clk; } else { @@ -3569,11 +3606,16 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh) c = oi->_clk; } - if (!c->clkdm) +#ifdef CONFIG_COMMON_CLK + clk = to_clk_hw_omap(__clk_get_hw(c)); + clkdm = clk->clkdm; +#else + clkdm = c->clkdm; +#endif + if (!clkdm) return NULL; - return c->clkdm->pwrdm.ptr; - + return clkdm->pwrdm.ptr; } /** -- cgit v1.2.3 From b797be1d4c079e78a3cb4e95f4a74274a4aef9f5 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 9 Jul 2012 18:24:30 +0530 Subject: ARM: OMAP2+: hwmod: Invoke init_clkdm before other init functions Without this kernel would crash, since clkdm inside omap_hwmod is accessed in some of the init functions like, _init_main_clk. So call init_clkdm before _init_main_clk(). Signed-off-by: Vaibhav Hiremath Signed-off-by: Mike Turquette Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index f38e4cefa2a5..c3d3e62a5ac2 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1519,11 +1519,12 @@ static int _init_clocks(struct omap_hwmod *oh, void *data) pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name); + if (soc_ops.init_clkdm) + ret |= soc_ops.init_clkdm(oh); + ret |= _init_main_clk(oh); ret |= _init_interface_clks(oh); ret |= _init_opt_clks(oh); - if (soc_ops.init_clkdm) - ret |= soc_ops.init_clkdm(oh); if (!ret) oh->_state = _HWMOD_STATE_CLKS_INITED; -- cgit v1.2.3 From c4a1ea2c6229b18c10c5a49a0f8f4ad2c3e2355d Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 27 Apr 2012 16:32:53 +0530 Subject: ARM: OMAP: hwmod: Cleanup !CONFIG_COMMON_CLK parts Clean all #ifdef's added as part of fixing the clkdm accesses from hwmod. Signed-off-by: Rajendra Nayak Signed-off-by: Mike Turquette Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index c3d3e62a5ac2..68616b2b5b96 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -130,11 +130,7 @@ #include #include #include -#ifdef CONFIG_COMMON_CLK #include -#else -#include -#endif #include #include #include @@ -620,17 +616,13 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) static struct clockdomain *_get_clkdm(struct omap_hwmod *oh) { + struct clk_hw_omap *clk; + if (oh->clkdm) { return oh->clkdm; } else if (oh->_clk) { -#ifdef CONFIG_COMMON_CLK - struct clk_hw_omap *clk; - clk = to_clk_hw_omap(__clk_get_hw(oh->_clk)); return clk->clkdm; -#else - return oh->_clk->clkdm; -#endif } return NULL; } @@ -3588,9 +3580,7 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh) struct clk *c; struct omap_hwmod_ocp_if *oi; struct clockdomain *clkdm; -#ifdef CONFIG_COMMON_CLK struct clk_hw_omap *clk; -#endif if (!oh) return NULL; @@ -3607,12 +3597,8 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh) c = oi->_clk; } -#ifdef CONFIG_COMMON_CLK clk = to_clk_hw_omap(__clk_get_hw(c)); clkdm = clk->clkdm; -#else - clkdm = c->clkdm; -#endif if (!clkdm) return NULL; -- cgit v1.2.3 From e6d3a8b0bdcd8f323488a52927682190aee5488e Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Wed, 21 Nov 2012 16:15:17 -0700 Subject: ARM: OMAP2+: hwmod: Add support for per hwmod/module context lost count OMAP4 has module specific context lost registers which makes it now possible to have module level context loss count, instead of relying on the powerdomain level context count. Add 2 private hwmod api's to update/clear the hwmod/module specific context lost counters/register. Update the module specific context_lost_counter and clear the hardware bits just after enabling the module. omap_hwmod_get_context_loss_count() now returns the hwmod context loss count them on platforms where they exist (OMAP4), else fall back on the pwrdm level counters for older platforms. Signed-off-by: Rajendra Nayak [paul@pwsan.com: added function kerneldoc, fixed structure kerneldoc, rearranged structure to avoid memory waste, marked fns as OMAP4-specific, prevent fn entry on non-OMAP4 chips, reduced indentation, merged update and clear, merged patches] [t-kristo@ti.com: added support for arch specific hwmod ops, and changed the no context offset indicator to USHRT_MAX] Signed-off-by: Tero Kristo [paul@pwsan.com: use NO_CONTEXT_LOSS_BIT flag rather than USHRT_MAX; convert unsigned context lost counter to int to match the return type; get rid of hwmod_ops in favor of the existing soc_ops mechanism; move context loss low-level accesses to the PRM code] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 55 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 68616b2b5b96..083adbed0bfd 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -187,6 +187,8 @@ struct omap_hwmod_soc_ops { int (*is_hardreset_asserted)(struct omap_hwmod *oh, struct omap_hwmod_rst_info *ohri); int (*init_clkdm)(struct omap_hwmod *oh); + void (*update_context_lost)(struct omap_hwmod *oh); + int (*get_context_lost)(struct omap_hwmod *oh); }; /* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */ @@ -1982,6 +1984,42 @@ static void _reconfigure_io_chain(void) spin_unlock_irqrestore(&io_chain_lock, flags); } +/** + * _omap4_update_context_lost - increment hwmod context loss counter if + * hwmod context was lost, and clear hardware context loss reg + * @oh: hwmod to check for context loss + * + * If the PRCM indicates that the hwmod @oh lost context, increment + * our in-memory context loss counter, and clear the RM_*_CONTEXT + * bits. No return value. + */ +static void _omap4_update_context_lost(struct omap_hwmod *oh) +{ + if (oh->prcm.omap4.flags & HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT) + return; + + if (!prm_was_any_context_lost_old(oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.context_offs)) + return; + + oh->prcm.omap4.context_lost_counter++; + prm_clear_context_loss_flags_old(oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.context_offs); +} + +/** + * _omap4_get_context_lost - get context loss counter for a hwmod + * @oh: hwmod to get context loss counter for + * + * Returns the in-memory context loss counter for a hwmod. + */ +static int _omap4_get_context_lost(struct omap_hwmod *oh) +{ + return oh->prcm.omap4.context_lost_counter; +} + /** * _enable - enable an omap_hwmod * @oh: struct omap_hwmod * @@ -2065,6 +2103,9 @@ static int _enable(struct omap_hwmod *oh) if (soc_ops.enable_module) soc_ops.enable_module(oh); + if (soc_ops.update_context_lost) + soc_ops.update_context_lost(oh); + r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) : -EINVAL; if (!r) { @@ -3907,17 +3948,21 @@ ohsps_unlock: * omap_hwmod_get_context_loss_count - get lost context count * @oh: struct omap_hwmod * * - * Query the powerdomain of of @oh to get the context loss - * count for this device. + * Returns the context loss count of associated @oh + * upon success, or zero if no context loss data is available. * - * Returns the context loss count of the powerdomain assocated with @oh - * upon success, or zero if no powerdomain exists for @oh. + * On OMAP4, this queries the per-hwmod context loss register, + * assuming one exists. If not, or on OMAP2/3, this queries the + * enclosing powerdomain context loss count. */ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh) { struct powerdomain *pwrdm; int ret = 0; + if (soc_ops.get_context_lost) + return soc_ops.get_context_lost(oh); + pwrdm = omap_hwmod_get_pwrdm(oh); if (pwrdm) ret = pwrdm_get_context_loss_count(pwrdm); @@ -4032,6 +4077,8 @@ void __init omap_hwmod_init(void) soc_ops.deassert_hardreset = _omap4_deassert_hardreset; soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; soc_ops.init_clkdm = _init_clkdm; + soc_ops.update_context_lost = _omap4_update_context_lost; + soc_ops.get_context_lost = _omap4_get_context_lost; } else if (soc_is_am33xx()) { soc_ops.enable_module = _am33xx_enable_module; soc_ops.disable_module = _am33xx_disable_module; -- cgit v1.2.3 From dad4191d79bded6674529084bcf842c00e4d874a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 21 Nov 2012 16:15:17 -0700 Subject: ARM: OMAP2+: hwmod: Add possibility to count hwmod resources based on type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add flags parameter for omap_hwmod_count_resources() so users can tell which type of resources they are interested when counting them in hwmod database. Signed-off-by: Peter Ujfalusi Acked-by: BenoƮt Cousson [paul@pwsan.com: updated to apply] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'arch/arm/mach-omap2/omap_hwmod.c') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 083adbed0bfd..a8090907fe35 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3427,7 +3427,7 @@ int omap_hwmod_reset(struct omap_hwmod *oh) /** * omap_hwmod_count_resources - count number of struct resources needed by hwmod * @oh: struct omap_hwmod * - * @res: pointer to the first element of an array of struct resource to fill + * @flags: Type of resources to include when counting (IRQ/DMA/MEM) * * Count the number of struct resource array elements necessary to * contain omap_hwmod @oh resources. Intended to be called by code @@ -3440,20 +3440,25 @@ int omap_hwmod_reset(struct omap_hwmod *oh) * resource IDs. * */ -int omap_hwmod_count_resources(struct omap_hwmod *oh) +int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags) { - struct omap_hwmod_ocp_if *os; - struct list_head *p; - int ret; - int i = 0; + int ret = 0; - ret = _count_mpu_irqs(oh) + _count_sdma_reqs(oh); + if (flags & IORESOURCE_IRQ) + ret += _count_mpu_irqs(oh); - p = oh->slave_ports.next; + if (flags & IORESOURCE_DMA) + ret += _count_sdma_reqs(oh); - while (i < oh->slaves_cnt) { - os = _fetch_next_ocp_if(&p, &i); - ret += _count_ocp_if_addr_spaces(os); + if (flags & IORESOURCE_MEM) { + int i = 0; + struct omap_hwmod_ocp_if *os; + struct list_head *p = oh->slave_ports.next; + + while (i < oh->slaves_cnt) { + os = _fetch_next_ocp_if(&p, &i); + ret += _count_ocp_if_addr_spaces(os); + } } return ret; -- cgit v1.2.3