From 3673d1ef5dc94d8b942c33fe1895a0ff52efbc3c Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 16:06:46 -0700 Subject: [PATCH 01/62] OMAP: powerdomain: remove unused func declaration Trivial fix to remove the unused function declaration from the powerdomain header. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/powerdomain.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index c66431edfeb7..0b7a357cb38e 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -165,7 +165,6 @@ struct pwrdm_ops { int (*pwrdm_wait_transition)(struct powerdomain *pwrdm); }; -void pwrdm_fw_init(void); void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs); struct powerdomain *pwrdm_lookup(const char *name); From 32d4034eea9c5c2b2edc365e1a0787c8f5b84c3c Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 16:06:47 -0700 Subject: [PATCH 02/62] OMAP: clockdomain: Infrastructure to put arch specific code Put infrastructure in place, so arch specific func pointers can be hooked up to the platform-independent part of the framework. This is in preparation of splitting the clockdomain framework into platform-independent part (for all omaps) and platform-specific parts. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomain.c | 10 ++++- arch/arm/mach-omap2/clockdomain.h | 37 ++++++++++++++++++- .../mach-omap2/clockdomains2xxx_3xxx_data.c | 2 +- arch/arm/mach-omap2/clockdomains44xx_data.c | 2 +- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 58e42f76603f..f70b06ae8664 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -44,6 +44,7 @@ static LIST_HEAD(clkdm_list); /* array of clockdomain deps to be added/removed when clkdm in hwsup mode */ static struct clkdm_autodep *autodeps; +static struct clkdm_ops *arch_clkdm; /* Private functions */ @@ -292,6 +293,7 @@ static void _disable_hwsup(struct clockdomain *clkdm) * clkdm_init - set up the clockdomain layer * @clkdms: optional pointer to an array of clockdomains to register * @init_autodeps: optional pointer to an array of autodeps to register + * @custom_funcs: func pointers for arch specfic implementations * * Set up internal state. If a pointer to an array of clockdomains * @clkdms was supplied, loop through the list of clockdomains, @@ -300,12 +302,18 @@ static void _disable_hwsup(struct clockdomain *clkdm) * @init_autodeps was provided, register those. No return value. */ void clkdm_init(struct clockdomain **clkdms, - struct clkdm_autodep *init_autodeps) + struct clkdm_autodep *init_autodeps, + struct clkdm_ops *custom_funcs) { struct clockdomain **c = NULL; struct clockdomain *clkdm; struct clkdm_autodep *autodep = NULL; + if (!custom_funcs) + WARN(1, "No custom clkdm functions registered\n"); + else + arch_clkdm = custom_funcs; + if (clkdms) for (c = clkdms; *c; c++) _clkdm_register(*c); diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 9b459c26fb85..71ad265cf133 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -116,7 +116,42 @@ struct clockdomain { struct list_head node; }; -void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps); +/** + * struct clkdm_ops - Arch specfic function implementations + * @clkdm_add_wkdep: Add a wakeup dependency between clk domains + * @clkdm_del_wkdep: Delete a wakeup dependency between clk domains + * @clkdm_read_wkdep: Read wakeup dependency state between clk domains + * @clkdm_clear_all_wkdeps: Remove all wakeup dependencies from the clk domain + * @clkdm_add_sleepdep: Add a sleep dependency between clk domains + * @clkdm_del_sleepdep: Delete a sleep dependency between clk domains + * @clkdm_read_sleepdep: Read sleep dependency state between clk domains + * @clkdm_clear_all_sleepdeps: Remove all sleep dependencies from the clk domain + * @clkdm_sleep: Force a clockdomain to sleep + * @clkdm_wakeup: Force a clockdomain to wakeup + * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain + * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain + * @clkdm_clk_enable: Put the clkdm in right state for a clock enable + * @clkdm_clk_disable: Put the clkdm in right state for a clock disable + */ +struct clkdm_ops { + int (*clkdm_add_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); + int (*clkdm_del_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); + int (*clkdm_read_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); + int (*clkdm_clear_all_wkdeps)(struct clockdomain *clkdm); + int (*clkdm_add_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); + int (*clkdm_del_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); + int (*clkdm_read_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); + int (*clkdm_clear_all_sleepdeps)(struct clockdomain *clkdm); + int (*clkdm_sleep)(struct clockdomain *clkdm); + int (*clkdm_wakeup)(struct clockdomain *clkdm); + void (*clkdm_allow_idle)(struct clockdomain *clkdm); + void (*clkdm_deny_idle)(struct clockdomain *clkdm); + int (*clkdm_clk_enable)(struct clockdomain *clkdm); + int (*clkdm_clk_disable)(struct clockdomain *clkdm); +}; + +void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps, + struct clkdm_ops *custom_funcs); struct clockdomain *clkdm_lookup(const char *name); int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c index e6f0d18d5e8d..e2a959eab312 100644 --- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c +++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c @@ -856,5 +856,5 @@ static struct clockdomain *clockdomains_omap2[] __initdata = { void __init omap2_clockdomains_init(void) { - clkdm_init(clockdomains_omap2, clkdm_autodeps); + clkdm_init(clockdomains_omap2, clkdm_autodeps, NULL); } diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index 10622c914abc..a5000d473d45 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -305,5 +305,5 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = { void __init omap44xx_clockdomains_init(void) { - clkdm_init(clockdomains_omap44xx, NULL); + clkdm_init(clockdomains_omap44xx, NULL, NULL); } From 4aef7a2a5aad52b60ac1a2f3cee055b8271b70d5 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 16:06:47 -0700 Subject: [PATCH 03/62] OMAP: clockdomain: Arch specific funcs to handle deps Define the following architecture specific funtions for omap2/3 .clkdm_add_wkdep .clkdm_del_wkdep .clkdm_read_wkdep .clkdm_clear_all_wkdeps .clkdm_add_sleepdep .clkdm_del_sleepdep .clkdm_read_sleepdep .clkdm_clear_all_sleepdeps Convert the platform-independent framework to call these functions. With this also move the clkdm lookups for all wkdep_srcs and sleepdep_srcs at clkdm_init. Signed-off-by: Rajendra Nayak [paul@pwsan.com: fixed loop termination conditions in omap*_clkdm_clear_all_*(); thanks to Kevin Hilman for finding and helping fix those bugs; also avoid re-resolving clockdomains during init; abstracted out clkdm_dep walk] Cc: Kevin Hilman Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 2 + arch/arm/mach-omap2/clockdomain.c | 177 ++++++++++-------- arch/arm/mach-omap2/clockdomain.h | 6 +- arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 130 +++++++++++++ .../mach-omap2/clockdomains2xxx_3xxx_data.c | 9 +- arch/arm/mach-omap2/io.c | 6 +- 6 files changed, 246 insertions(+), 84 deletions(-) create mode 100644 arch/arm/mach-omap2/clockdomain2xxx_3xxx.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index ee72a9787bf1..759d9ebd79c6 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -102,8 +102,10 @@ obj-$(CONFIG_ARCH_OMAP4) += $(powerdomain-common) \ # PRCM clockdomain control obj-$(CONFIG_ARCH_OMAP2) += clockdomain.o \ + clockdomain2xxx_3xxx.o \ clockdomains2xxx_3xxx_data.o obj-$(CONFIG_ARCH_OMAP3) += clockdomain.o \ + clockdomain2xxx_3xxx.o \ clockdomains2xxx_3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += clockdomain.o \ clockdomains44xx_data.o diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index f70b06ae8664..895c153c18e0 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -287,6 +287,32 @@ static void _disable_hwsup(struct clockdomain *clkdm) BUG(); } +/** + * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms + * @clkdm: clockdomain that we are resolving dependencies for + * @clkdm_deps: ptr to array of struct clkdm_deps to resolve + * + * Iterates through @clkdm_deps, looking up the struct clockdomain named by + * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep. + * No return value. + */ +static void _resolve_clkdm_deps(struct clockdomain *clkdm, + struct clkdm_dep *clkdm_deps) +{ + struct clkdm_dep *cd; + + for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) { + if (!omap_chip_is(cd->omap_chip)) + continue; + if (cd->clkdm) + continue; + cd->clkdm = _clkdm_lookup(cd->clkdm_name); + + WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen", + clkdm->name, cd->clkdm_name); + } +} + /* Public functions */ /** @@ -333,7 +359,10 @@ void clkdm_init(struct clockdomain **clkdms, else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO) omap2_clkdm_deny_idle(clkdm); + _resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs); clkdm_clear_all_wkdeps(clkdm); + + _resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs); clkdm_clear_all_sleepdeps(clkdm); } } @@ -430,6 +459,7 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm) int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; + int ret = 0; if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { pr_err("clockdomain: %s/%s: %s: not yet implemented\n", @@ -441,21 +471,26 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) return -EINVAL; cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); - if (IS_ERR(cd)) { + if (IS_ERR(cd)) + ret = PTR_ERR(cd); + + if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep) + ret = -EINVAL; + + if (ret) { pr_debug("clockdomain: hardware cannot set/clear wake up of " "%s when %s wakes up\n", clkdm1->name, clkdm2->name); - return PTR_ERR(cd); + return ret; } if (atomic_inc_return(&cd->wkdep_usecount) == 1) { pr_debug("clockdomain: hardware will wake up %s when %s wakes " "up\n", clkdm1->name, clkdm2->name); - omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit), - clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); + ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2); } - return 0; + return ret; } /** @@ -471,6 +506,7 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; + int ret = 0; if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { pr_err("clockdomain: %s/%s: %s: not yet implemented\n", @@ -482,21 +518,26 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) return -EINVAL; cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); - if (IS_ERR(cd)) { + if (IS_ERR(cd)) + ret = PTR_ERR(cd); + + if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep) + ret = -EINVAL; + + if (ret) { pr_debug("clockdomain: hardware cannot set/clear wake up of " "%s when %s wakes up\n", clkdm1->name, clkdm2->name); - return PTR_ERR(cd); + return ret; } if (atomic_dec_return(&cd->wkdep_usecount) == 0) { pr_debug("clockdomain: hardware will no longer wake up %s " "after %s wakes up\n", clkdm1->name, clkdm2->name); - omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), - clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); + ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2); } - return 0; + return ret; } /** @@ -516,6 +557,7 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; + int ret = 0; if (!clkdm1 || !clkdm2) return -EINVAL; @@ -527,15 +569,20 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) } cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); - if (IS_ERR(cd)) { + if (IS_ERR(cd)) + ret = PTR_ERR(cd); + + if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep) + ret = -EINVAL; + + if (ret) { pr_debug("clockdomain: hardware cannot set/clear wake up of " "%s when %s wakes up\n", clkdm1->name, clkdm2->name); - return PTR_ERR(cd); + return ret; } /* XXX It's faster to return the atomic wkdep_usecount */ - return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP, - (1 << clkdm2->dep_bit)); + return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2); } /** @@ -550,9 +597,6 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) */ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) { - struct clkdm_dep *cd; - u32 mask = 0; - if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { pr_err("clockdomain: %s: %s: not yet implemented\n", clkdm->name, __func__); @@ -562,21 +606,10 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) if (!clkdm) return -EINVAL; - for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { - if (!omap_chip_is(cd->omap_chip)) - continue; + if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps) + return -EINVAL; - if (!cd->clkdm && cd->clkdm_name) - cd->clkdm = _clkdm_lookup(cd->clkdm_name); - - /* PRM accesses are slow, so minimize them */ - mask |= 1 << cd->clkdm->dep_bit; - atomic_set(&cd->wkdep_usecount, 0); - } - - omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP); - - return 0; + return arch_clkdm->clkdm_clear_all_wkdeps(clkdm); } /** @@ -594,31 +627,33 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; - - if (!cpu_is_omap34xx()) - return -EINVAL; + int ret = 0; if (!clkdm1 || !clkdm2) return -EINVAL; cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); - if (IS_ERR(cd)) { + if (IS_ERR(cd)) + ret = PTR_ERR(cd); + + if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep) + ret = -EINVAL; + + if (ret) { pr_debug("clockdomain: hardware cannot set/clear sleep " "dependency affecting %s from %s\n", clkdm1->name, clkdm2->name); - return PTR_ERR(cd); + return ret; } if (atomic_inc_return(&cd->sleepdep_usecount) == 1) { pr_debug("clockdomain: will prevent %s from sleeping if %s " "is active\n", clkdm1->name, clkdm2->name); - omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit), - clkdm1->pwrdm.ptr->prcm_offs, - OMAP3430_CM_SLEEPDEP); + ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2); } - return 0; + return ret; } /** @@ -636,19 +671,23 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; - - if (!cpu_is_omap34xx()) - return -EINVAL; + int ret = 0; if (!clkdm1 || !clkdm2) return -EINVAL; cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); - if (IS_ERR(cd)) { + if (IS_ERR(cd)) + ret = PTR_ERR(cd); + + if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep) + ret = -EINVAL; + + if (ret) { pr_debug("clockdomain: hardware cannot set/clear sleep " "dependency affecting %s from %s\n", clkdm1->name, clkdm2->name); - return PTR_ERR(cd); + return ret; } if (atomic_dec_return(&cd->sleepdep_usecount) == 0) { @@ -656,12 +695,10 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) "sleeping if %s is active\n", clkdm1->name, clkdm2->name); - omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), - clkdm1->pwrdm.ptr->prcm_offs, - OMAP3430_CM_SLEEPDEP); + ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2); } - return 0; + return ret; } /** @@ -683,25 +720,27 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; - - if (!cpu_is_omap34xx()) - return -EINVAL; + int ret = 0; if (!clkdm1 || !clkdm2) return -EINVAL; cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs); - if (IS_ERR(cd)) { + if (IS_ERR(cd)) + ret = PTR_ERR(cd); + + if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep) + ret = -EINVAL; + + if (ret) { pr_debug("clockdomain: hardware cannot set/clear sleep " "dependency affecting %s from %s\n", clkdm1->name, clkdm2->name); - return PTR_ERR(cd); + return ret; } /* XXX It's faster to return the atomic sleepdep_usecount */ - return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, - OMAP3430_CM_SLEEPDEP, - (1 << clkdm2->dep_bit)); + return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2); } /** @@ -716,31 +755,13 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) */ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) { - struct clkdm_dep *cd; - u32 mask = 0; - - if (!cpu_is_omap34xx()) - return -EINVAL; - if (!clkdm) return -EINVAL; - for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) { - if (!omap_chip_is(cd->omap_chip)) - continue; + if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps) + return -EINVAL; - if (!cd->clkdm && cd->clkdm_name) - cd->clkdm = _clkdm_lookup(cd->clkdm_name); - - /* PRM accesses are slow, so minimize them */ - mask |= 1 << cd->clkdm->dep_bit; - atomic_set(&cd->sleepdep_usecount, 0); - } - - omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, - OMAP3430_CM_SLEEPDEP); - - return 0; + return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm); } /** diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 71ad265cf133..90b6d6a50862 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -176,7 +176,11 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm); int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); -extern void __init omap2_clockdomains_init(void); +extern void __init omap2xxx_clockdomains_init(void); +extern void __init omap3xxx_clockdomains_init(void); extern void __init omap44xx_clockdomains_init(void); +extern struct clkdm_ops omap2_clkdm_operations; +extern struct clkdm_ops omap3_clkdm_operations; + #endif diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c new file mode 100644 index 000000000000..a1fd6fd5a466 --- /dev/null +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -0,0 +1,130 @@ +/* + * OMAP2 and OMAP3 clockdomain control + * + * Copyright (C) 2008-2010 Texas Instruments, Inc. + * Copyright (C) 2008-2010 Nokia Corporation + * + * Derived from mach-omap2/clockdomain.c written by Paul Walmsley + * Rajendra Nayak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include "prm.h" +#include "prm2xxx_3xxx.h" +#include "cm.h" +#include "cm2xxx_3xxx.h" +#include "cm-regbits-24xx.h" +#include "cm-regbits-34xx.h" +#include "clockdomain.h" + +static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit), + clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); + return 0; +} + +static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit), + clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); + return 0; +} + +static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, + PM_WKDEP, (1 << clkdm2->dep_bit)); +} + +static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm) +{ + struct clkdm_dep *cd; + u32 mask = 0; + + for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { + if (!omap_chip_is(cd->omap_chip)) + continue; + if (!cd->clkdm) + continue; /* only happens if data is erroneous */ + + /* PRM accesses are slow, so minimize them */ + mask |= 1 << cd->clkdm->dep_bit; + atomic_set(&cd->wkdep_usecount, 0); + } + + omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, + PM_WKDEP); + return 0; +} + +static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit), + clkdm1->pwrdm.ptr->prcm_offs, + OMAP3430_CM_SLEEPDEP); + return 0; +} + +static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), + clkdm1->pwrdm.ptr->prcm_offs, + OMAP3430_CM_SLEEPDEP); + return 0; +} + +static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, + OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit)); +} + +static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) +{ + struct clkdm_dep *cd; + u32 mask = 0; + + for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) { + if (!omap_chip_is(cd->omap_chip)) + continue; + if (!cd->clkdm) + continue; /* only happens if data is erroneous */ + + /* PRM accesses are slow, so minimize them */ + mask |= 1 << cd->clkdm->dep_bit; + atomic_set(&cd->sleepdep_usecount, 0); + } + omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, + OMAP3430_CM_SLEEPDEP); + return 0; +} + +struct clkdm_ops omap2_clkdm_operations = { + .clkdm_add_wkdep = omap2_clkdm_add_wkdep, + .clkdm_del_wkdep = omap2_clkdm_del_wkdep, + .clkdm_read_wkdep = omap2_clkdm_read_wkdep, + .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps, +}; + +struct clkdm_ops omap3_clkdm_operations = { + .clkdm_add_wkdep = omap2_clkdm_add_wkdep, + .clkdm_del_wkdep = omap2_clkdm_del_wkdep, + .clkdm_read_wkdep = omap2_clkdm_read_wkdep, + .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps, + .clkdm_add_sleepdep = omap3_clkdm_add_sleepdep, + .clkdm_del_sleepdep = omap3_clkdm_del_sleepdep, + .clkdm_read_sleepdep = omap3_clkdm_read_sleepdep, + .clkdm_clear_all_sleepdeps = omap3_clkdm_clear_all_sleepdeps, +}; diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c index e2a959eab312..ffdfe54f3264 100644 --- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c +++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c @@ -854,7 +854,12 @@ static struct clockdomain *clockdomains_omap2[] __initdata = { NULL, }; -void __init omap2_clockdomains_init(void) +void __init omap2xxx_clockdomains_init(void) { - clkdm_init(clockdomains_omap2, clkdm_autodeps, NULL); + clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap2_clkdm_operations); +} + +void __init omap3xxx_clockdomains_init(void) +{ + clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap3_clkdm_operations); } diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index b8b49e4ae928..03f71ec3cd82 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -357,15 +357,15 @@ void __init omap2_init_common_infrastructure(void) if (cpu_is_omap242x()) { omap2xxx_powerdomains_init(); - omap2_clockdomains_init(); + omap2xxx_clockdomains_init(); omap2420_hwmod_init(); } else if (cpu_is_omap243x()) { omap2xxx_powerdomains_init(); - omap2_clockdomains_init(); + omap2xxx_clockdomains_init(); omap2430_hwmod_init(); } else if (cpu_is_omap34xx()) { omap3xxx_powerdomains_init(); - omap2_clockdomains_init(); + omap3xxx_clockdomains_init(); omap3xxx_hwmod_init(); } else if (cpu_is_omap44xx()) { omap44xx_powerdomains_init(); From 68b921ad7f35e0323ce0d9fe94e5701a112f257c Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 16:06:47 -0700 Subject: [PATCH 04/62] OMAP: clockdomain: Arch specific funcs for sleep/wakeup of clkdm Define the following architecture specific funtions for omap2/3/4 .clkdm_sleep .clkdm_wakeup Convert the platform-independent framework to call these functions. Also rename the api's by removing the omap2_ preamble. Hence call omap2_clkdm_wakeup as clkdm_wakeup and omap2_clkdm_sleep as clkdm_sleep. Signed-off-by: Rajendra Nayak [paul@pwsan.com: fixed omap3_clkdm_clear_all_sleepdeps() and omap2_clkdm_clear_all_wkdeps() to test against the correct loop termination condition; thanks to Kevin Hilman for finding and helping fix] Cc: Kevin Hilman Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 1 + arch/arm/mach-omap2/clockdomain.c | 64 +++++---------------- arch/arm/mach-omap2/clockdomain.h | 5 +- arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 35 +++++++++++ arch/arm/mach-omap2/clockdomain44xx.c | 35 +++++++++++ arch/arm/mach-omap2/clockdomains44xx_data.c | 2 +- arch/arm/mach-omap2/pm.c | 4 +- arch/arm/mach-omap2/pm24xx.c | 6 +- arch/arm/mach-omap2/pm34xx.c | 2 +- 9 files changed, 96 insertions(+), 58 deletions(-) create mode 100644 arch/arm/mach-omap2/clockdomain44xx.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 759d9ebd79c6..10c3c8f16eaa 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_ARCH_OMAP3) += clockdomain.o \ clockdomain2xxx_3xxx.o \ clockdomains2xxx_3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += clockdomain.o \ + clockdomain44xx.o \ clockdomains44xx_data.o # Clock framework obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o \ diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 895c153c18e0..3035eb9eec36 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -355,7 +355,7 @@ void clkdm_init(struct clockdomain **clkdms, */ list_for_each_entry(clkdm, &clkdm_list, node) { if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) - omap2_clkdm_wakeup(clkdm); + clkdm_wakeup(clkdm); else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO) omap2_clkdm_deny_idle(clkdm); @@ -765,7 +765,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) } /** - * omap2_clkdm_sleep - force clockdomain sleep transition + * clkdm_sleep - force clockdomain sleep transition * @clkdm: struct clockdomain * * * Instruct the CM to force a sleep transition on the specified @@ -773,7 +773,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) * clockdomain does not support software-initiated sleep; 0 upon * success. */ -int omap2_clkdm_sleep(struct clockdomain *clkdm) +int clkdm_sleep(struct clockdomain *clkdm) { if (!clkdm) return -EINVAL; @@ -784,33 +784,16 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm) return -EINVAL; } + if (!arch_clkdm || !arch_clkdm->clkdm_sleep) + return -EINVAL; + pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name); - if (cpu_is_omap24xx()) { - - omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, - clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL); - - } else if (cpu_is_omap34xx()) { - - omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - - } else if (cpu_is_omap44xx()) { - - omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition, - clkdm->cm_inst, - clkdm->clkdm_offs); - - } else { - BUG(); - }; - - return 0; + return arch_clkdm->clkdm_sleep(clkdm); } /** - * omap2_clkdm_wakeup - force clockdomain wakeup transition + * clkdm_wakeup - force clockdomain wakeup transition * @clkdm: struct clockdomain * * * Instruct the CM to force a wakeup transition on the specified @@ -818,7 +801,7 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm) * clockdomain does not support software-controlled wakeup; 0 upon * success. */ -int omap2_clkdm_wakeup(struct clockdomain *clkdm) +int clkdm_wakeup(struct clockdomain *clkdm) { if (!clkdm) return -EINVAL; @@ -829,29 +812,12 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) return -EINVAL; } + if (!arch_clkdm || !arch_clkdm->clkdm_wakeup) + return -EINVAL; + pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name); - if (cpu_is_omap24xx()) { - - omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, - clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL); - - } else if (cpu_is_omap34xx()) { - - omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - - } else if (cpu_is_omap44xx()) { - - omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition, - clkdm->cm_inst, - clkdm->clkdm_offs); - - } else { - BUG(); - }; - - return 0; + return arch_clkdm->clkdm_wakeup(clkdm); } /** @@ -990,7 +956,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) _clkdm_add_autodeps(clkdm); _enable_hwsup(clkdm); } else { - omap2_clkdm_wakeup(clkdm); + clkdm_wakeup(clkdm); } pwrdm_wait_transition(clkdm->pwrdm.ptr); @@ -1062,7 +1028,7 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) _clkdm_del_autodeps(clkdm); _enable_hwsup(clkdm); } else { - omap2_clkdm_sleep(clkdm); + clkdm_sleep(clkdm); } pwrdm_clkdm_state_switch(clkdm); diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 90b6d6a50862..7a5cb5cf9949 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -170,8 +170,8 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); void omap2_clkdm_allow_idle(struct clockdomain *clkdm); void omap2_clkdm_deny_idle(struct clockdomain *clkdm); -int omap2_clkdm_wakeup(struct clockdomain *clkdm); -int omap2_clkdm_sleep(struct clockdomain *clkdm); +int clkdm_wakeup(struct clockdomain *clkdm); +int clkdm_sleep(struct clockdomain *clkdm); int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); @@ -182,5 +182,6 @@ extern void __init omap44xx_clockdomains_init(void); extern struct clkdm_ops omap2_clkdm_operations; extern struct clkdm_ops omap3_clkdm_operations; +extern struct clkdm_ops omap4_clkdm_operations; #endif diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index a1fd6fd5a466..08c87fe3da12 100644 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -20,6 +20,7 @@ #include "cm2xxx_3xxx.h" #include "cm-regbits-24xx.h" #include "cm-regbits-34xx.h" +#include "prm-regbits-24xx.h" #include "clockdomain.h" static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1, @@ -111,11 +112,43 @@ static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm) return 0; } +static int omap2_clkdm_sleep(struct clockdomain *clkdm) +{ + omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, + clkdm->pwrdm.ptr->prcm_offs, + OMAP2_PM_PWSTCTRL); + return 0; +} + +static int omap2_clkdm_wakeup(struct clockdomain *clkdm) +{ + omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, + clkdm->pwrdm.ptr->prcm_offs, + OMAP2_PM_PWSTCTRL); + return 0; +} + +static int omap3_clkdm_sleep(struct clockdomain *clkdm) +{ + omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + return 0; +} + +static int omap3_clkdm_wakeup(struct clockdomain *clkdm) +{ + omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + return 0; +} + struct clkdm_ops omap2_clkdm_operations = { .clkdm_add_wkdep = omap2_clkdm_add_wkdep, .clkdm_del_wkdep = omap2_clkdm_del_wkdep, .clkdm_read_wkdep = omap2_clkdm_read_wkdep, .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps, + .clkdm_sleep = omap2_clkdm_sleep, + .clkdm_wakeup = omap2_clkdm_wakeup, }; struct clkdm_ops omap3_clkdm_operations = { @@ -127,4 +160,6 @@ struct clkdm_ops omap3_clkdm_operations = { .clkdm_del_sleepdep = omap3_clkdm_del_sleepdep, .clkdm_read_sleepdep = omap3_clkdm_read_sleepdep, .clkdm_clear_all_sleepdeps = omap3_clkdm_clear_all_sleepdeps, + .clkdm_sleep = omap3_clkdm_sleep, + .clkdm_wakeup = omap3_clkdm_wakeup, }; diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c new file mode 100644 index 000000000000..9ccb406cf54f --- /dev/null +++ b/arch/arm/mach-omap2/clockdomain44xx.c @@ -0,0 +1,35 @@ +/* + * OMAP4 clockdomain control + * + * Copyright (C) 2008-2010 Texas Instruments, Inc. + * Copyright (C) 2008-2010 Nokia Corporation + * + * Derived from mach-omap2/clockdomain.c written by Paul Walmsley + * Rajendra Nayak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "clockdomain.h" +#include "cminst44xx.h" + +static int omap4_clkdm_sleep(struct clockdomain *clkdm) +{ + omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition, + clkdm->cm_inst, clkdm->clkdm_offs); + return 0; +} + +static int omap4_clkdm_wakeup(struct clockdomain *clkdm) +{ + omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition, + clkdm->cm_inst, clkdm->clkdm_offs); + return 0; +} + +struct clkdm_ops omap4_clkdm_operations = { + .clkdm_sleep = omap4_clkdm_sleep, + .clkdm_wakeup = omap4_clkdm_wakeup, +}; diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index a5000d473d45..eea6f8e40289 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -305,5 +305,5 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = { void __init omap44xx_clockdomains_init(void) { - clkdm_init(clockdomains_omap44xx, NULL, NULL); + clkdm_init(clockdomains_omap44xx, NULL, &omap4_clkdm_operations); } diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index d5a102c71989..74c31008079c 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -124,7 +124,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { sleep_switch = LOWPOWERSTATE_SWITCH; } else { - omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); + clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); pwrdm_wait_transition(pwrdm); sleep_switch = FORCEWAKEUP_SWITCH; } @@ -142,7 +142,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO) omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); else - omap2_clkdm_sleep(pwrdm->pwrdm_clkdms[0]); + clkdm_sleep(pwrdm->pwrdm_clkdms[0]); break; case LOWPOWERSTATE_SWITCH: pwrdm_set_lowpwrstchange(pwrdm); diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 97feb3ab6a69..4125621bf591 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -370,7 +370,7 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) omap2_clkdm_allow_idle(clkdm); else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && atomic_read(&clkdm->usecount) == 0) - omap2_clkdm_sleep(clkdm); + clkdm_sleep(clkdm); return 0; } @@ -405,11 +405,11 @@ static void __init prcm_setup_regs(void) pwrdm = clkdm_get_pwrdm(dsp_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); - omap2_clkdm_sleep(dsp_clkdm); + clkdm_sleep(dsp_clkdm); pwrdm = clkdm_get_pwrdm(gfx_clkdm); pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); - omap2_clkdm_sleep(gfx_clkdm); + clkdm_sleep(gfx_clkdm); /* * Clear clockdomain wakeup dependencies and enable diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 2f864e4b085d..81df2b169a56 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -993,7 +993,7 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) omap2_clkdm_allow_idle(clkdm); else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && atomic_read(&clkdm->usecount) == 0) - omap2_clkdm_sleep(clkdm); + clkdm_sleep(clkdm); return 0; } From 5cd1937b6d5990fe5d5287d925f05afd38e9fb02 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 16:06:48 -0700 Subject: [PATCH 05/62] OMAP: clockdomain: Arch specific funcs for hwsup control of clkdm Define the following architecture specific funtions for omap2/3/4 .clkdm_allow_idle .clkdm_deny_idle Convert the platform-independent framework to call these functions. Also rename the api's by removing the omap2_ preamble. Hence call omap2_clkdm_allow_idle as clkdm_allow_idle and omap2_clkdm_deny_idle as clkdm_deny_idle. Make the _clkdm_add_autodeps and _clkdm_del_autodeps as non-static so they can be accessed from OMAP2/3 platform specific code. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomain.c | 47 +++++++--------------- arch/arm/mach-omap2/clockdomain.h | 6 ++- arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 40 ++++++++++++++++++ arch/arm/mach-omap2/clockdomain44xx.c | 14 +++++++ arch/arm/mach-omap2/cpuidle34xx.c | 4 +- arch/arm/mach-omap2/pm.c | 2 +- arch/arm/mach-omap2/pm24xx.c | 2 +- arch/arm/mach-omap2/pm34xx.c | 4 +- 8 files changed, 79 insertions(+), 40 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 3035eb9eec36..44664e7cc2a6 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -178,7 +178,7 @@ static void _autodep_lookup(struct clkdm_autodep *autodep) * XXX autodeps are deprecated and should be removed at the earliest * opportunity */ -static void _clkdm_add_autodeps(struct clockdomain *clkdm) +void _clkdm_add_autodeps(struct clockdomain *clkdm) { struct clkdm_autodep *autodep; @@ -212,7 +212,7 @@ static void _clkdm_add_autodeps(struct clockdomain *clkdm) * XXX autodeps are deprecated and should be removed at the earliest * opportunity */ -static void _clkdm_del_autodeps(struct clockdomain *clkdm) +void _clkdm_del_autodeps(struct clockdomain *clkdm) { struct clkdm_autodep *autodep; @@ -357,7 +357,7 @@ void clkdm_init(struct clockdomain **clkdms, if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) clkdm_wakeup(clkdm); else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO) - omap2_clkdm_deny_idle(clkdm); + clkdm_deny_idle(clkdm); _resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs); clkdm_clear_all_wkdeps(clkdm); @@ -821,7 +821,7 @@ int clkdm_wakeup(struct clockdomain *clkdm) } /** - * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm + * clkdm_allow_idle - enable hwsup idle transitions for clkdm * @clkdm: struct clockdomain * * * Allow the hardware to automatically switch the clockdomain @clkdm into @@ -830,7 +830,7 @@ int clkdm_wakeup(struct clockdomain *clkdm) * framework, wkdep/sleepdep autodependencies are added; this is so * device drivers can read and write to the device. No return value. */ -void omap2_clkdm_allow_idle(struct clockdomain *clkdm) +void clkdm_allow_idle(struct clockdomain *clkdm) { if (!clkdm) return; @@ -841,27 +841,18 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) return; } + if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle) + return; + pr_debug("clockdomain: enabling automatic idle transitions for %s\n", clkdm->name); - /* - * XXX This should be removed once TI adds wakeup/sleep - * dependency code and data for OMAP4. - */ - if (cpu_is_omap44xx()) { - pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name); - } else { - if (atomic_read(&clkdm->usecount) > 0) - _clkdm_add_autodeps(clkdm); - } - - _enable_hwsup(clkdm); - + arch_clkdm->clkdm_allow_idle(clkdm); pwrdm_clkdm_state_switch(clkdm); } /** - * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm + * clkdm_deny_idle - disable hwsup idle transitions for clkdm * @clkdm: struct clockdomain * * * Prevent the hardware from automatically switching the clockdomain @@ -869,7 +860,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) * downstream clocks enabled in the clock framework, wkdep/sleepdep * autodependencies are removed. No return value. */ -void omap2_clkdm_deny_idle(struct clockdomain *clkdm) +void clkdm_deny_idle(struct clockdomain *clkdm) { if (!clkdm) return; @@ -880,21 +871,13 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) return; } + if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle) + return; + pr_debug("clockdomain: disabling automatic idle transitions for %s\n", clkdm->name); - _disable_hwsup(clkdm); - - /* - * XXX This should be removed once TI adds wakeup/sleep - * dependency code and data for OMAP4. - */ - if (cpu_is_omap44xx()) { - pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name); - } else { - if (atomic_read(&clkdm->usecount) > 0) - _clkdm_del_autodeps(clkdm); - } + arch_clkdm->clkdm_deny_idle(clkdm); } diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 7a5cb5cf9949..7126658d9ae1 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -167,8 +167,8 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); -void omap2_clkdm_allow_idle(struct clockdomain *clkdm); -void omap2_clkdm_deny_idle(struct clockdomain *clkdm); +void clkdm_allow_idle(struct clockdomain *clkdm); +void clkdm_deny_idle(struct clockdomain *clkdm); int clkdm_wakeup(struct clockdomain *clkdm); int clkdm_sleep(struct clockdomain *clkdm); @@ -179,6 +179,8 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); extern void __init omap2xxx_clockdomains_init(void); extern void __init omap3xxx_clockdomains_init(void); extern void __init omap44xx_clockdomains_init(void); +extern void _clkdm_add_autodeps(struct clockdomain *clkdm); +extern void _clkdm_del_autodeps(struct clockdomain *clkdm); extern struct clkdm_ops omap2_clkdm_operations; extern struct clkdm_ops omap3_clkdm_operations; diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index 08c87fe3da12..25c27a5c722f 100644 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -128,6 +128,24 @@ static int omap2_clkdm_wakeup(struct clockdomain *clkdm) return 0; } +static void omap2_clkdm_allow_idle(struct clockdomain *clkdm) +{ + if (atomic_read(&clkdm->usecount) > 0) + _clkdm_add_autodeps(clkdm); + + omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); +} + +static void omap2_clkdm_deny_idle(struct clockdomain *clkdm) +{ + omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + + if (atomic_read(&clkdm->usecount) > 0) + _clkdm_del_autodeps(clkdm); +} + static int omap3_clkdm_sleep(struct clockdomain *clkdm) { omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs, @@ -142,6 +160,24 @@ static int omap3_clkdm_wakeup(struct clockdomain *clkdm) return 0; } +static void omap3_clkdm_allow_idle(struct clockdomain *clkdm) +{ + if (atomic_read(&clkdm->usecount) > 0) + _clkdm_add_autodeps(clkdm); + + omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); +} + +static void omap3_clkdm_deny_idle(struct clockdomain *clkdm) +{ + omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + + if (atomic_read(&clkdm->usecount) > 0) + _clkdm_del_autodeps(clkdm); +} + struct clkdm_ops omap2_clkdm_operations = { .clkdm_add_wkdep = omap2_clkdm_add_wkdep, .clkdm_del_wkdep = omap2_clkdm_del_wkdep, @@ -149,6 +185,8 @@ struct clkdm_ops omap2_clkdm_operations = { .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps, .clkdm_sleep = omap2_clkdm_sleep, .clkdm_wakeup = omap2_clkdm_wakeup, + .clkdm_allow_idle = omap2_clkdm_allow_idle, + .clkdm_deny_idle = omap2_clkdm_deny_idle, }; struct clkdm_ops omap3_clkdm_operations = { @@ -162,4 +200,6 @@ struct clkdm_ops omap3_clkdm_operations = { .clkdm_clear_all_sleepdeps = omap3_clkdm_clear_all_sleepdeps, .clkdm_sleep = omap3_clkdm_sleep, .clkdm_wakeup = omap3_clkdm_wakeup, + .clkdm_allow_idle = omap3_clkdm_allow_idle, + .clkdm_deny_idle = omap3_clkdm_deny_idle, }; diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c index 9ccb406cf54f..a46125f15454 100644 --- a/arch/arm/mach-omap2/clockdomain44xx.c +++ b/arch/arm/mach-omap2/clockdomain44xx.c @@ -29,7 +29,21 @@ static int omap4_clkdm_wakeup(struct clockdomain *clkdm) return 0; } +static void omap4_clkdm_allow_idle(struct clockdomain *clkdm) +{ + omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, + clkdm->cm_inst, clkdm->clkdm_offs); +} + +static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) +{ + omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition, + clkdm->cm_inst, clkdm->clkdm_offs); +} + struct clkdm_ops omap4_clkdm_operations = { .clkdm_sleep = omap4_clkdm_sleep, .clkdm_wakeup = omap4_clkdm_wakeup, + .clkdm_allow_idle = omap4_clkdm_allow_idle, + .clkdm_deny_idle = omap4_clkdm_deny_idle, }; diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index f7b22a16f385..7cc80715ef12 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -99,14 +99,14 @@ static int omap3_idle_bm_check(void) static int _cpuidle_allow_idle(struct powerdomain *pwrdm, struct clockdomain *clkdm) { - omap2_clkdm_allow_idle(clkdm); + clkdm_allow_idle(clkdm); return 0; } static int _cpuidle_deny_idle(struct powerdomain *pwrdm, struct clockdomain *clkdm) { - omap2_clkdm_deny_idle(clkdm); + clkdm_deny_idle(clkdm); return 0; } diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 74c31008079c..7bb64d8121a7 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -140,7 +140,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) switch (sleep_switch) { case FORCEWAKEUP_SWITCH: if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO) - omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); + clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); else clkdm_sleep(pwrdm->pwrdm_clkdms[0]); break; diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 4125621bf591..e983c8301f55 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -367,7 +367,7 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) clkdm_clear_all_sleepdeps(clkdm); if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO) - omap2_clkdm_allow_idle(clkdm); + clkdm_allow_idle(clkdm); else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && atomic_read(&clkdm->usecount) == 0) clkdm_sleep(clkdm); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 81df2b169a56..eda9a4e99a89 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -496,7 +496,7 @@ console_still_active: pwrdm_post_transition(); - omap2_clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); + clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); } int omap3_can_sleep(void) @@ -990,7 +990,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) { if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO) - omap2_clkdm_allow_idle(clkdm); + clkdm_allow_idle(clkdm); else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && atomic_read(&clkdm->usecount) == 0) clkdm_sleep(clkdm); From 4da71ae607fc657075286abd2774041ff4d00fe5 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 16:06:48 -0700 Subject: [PATCH 06/62] OMAP: clockdomain: Arch specific funcs for clkdm_clk_enable/disable Define the following architecture specific funtions for omap2/3/4 .clkdm_clk_enable .clkdm_clk_disable Convert the platform-independent framework to call these functions. Also rename the api's by removing the omap2_ preamble. Hence call omap2_clkdm_k_enable as clkdm_clk_enable and omap2_clkdm_clk_disable as clkdm_clk_disable.a Remove unused functions (_enable/_disable_hwsup) and unsed headers from clockdomain.c file. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock.c | 6 +- arch/arm/mach-omap2/clockdomain.c | 131 ++------------------- arch/arm/mach-omap2/clockdomain.h | 4 +- arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 69 +++++++++++ arch/arm/mach-omap2/clockdomain44xx.c | 28 +++++ 5 files changed, 114 insertions(+), 124 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 2a2f15213add..e9625fcf6390 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -264,7 +264,7 @@ void omap2_clk_disable(struct clk *clk) clk->ops->disable(clk); if (clk->clkdm) - omap2_clkdm_clk_disable(clk->clkdm, clk); + clkdm_clk_disable(clk->clkdm, clk); if (clk->parent) omap2_clk_disable(clk->parent); @@ -304,7 +304,7 @@ int omap2_clk_enable(struct clk *clk) } if (clk->clkdm) { - ret = omap2_clkdm_clk_enable(clk->clkdm, clk); + ret = clkdm_clk_enable(clk->clkdm, clk); if (ret) { WARN(1, "clock: %s: could not enable clockdomain %s: " "%d\n", clk->name, clk->clkdm->name, ret); @@ -322,7 +322,7 @@ int omap2_clk_enable(struct clk *clk) oce_err3: if (clk->clkdm) - omap2_clkdm_clk_disable(clk->clkdm, clk); + clkdm_clk_disable(clk->clkdm, clk); oce_err2: if (clk->parent) omap2_clk_disable(clk->parent); diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 44664e7cc2a6..70d242007e0b 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -26,17 +26,8 @@ #include -#include "prm2xxx_3xxx.h" -#include "prm-regbits-24xx.h" -#include "cm2xxx_3xxx.h" -#include "cm-regbits-24xx.h" -#include "cminst44xx.h" -#include "prcm44xx.h" - #include -#include "powerdomain.h" #include "clockdomain.h" -#include /* clkdm_list contains all registered struct clockdomains */ static LIST_HEAD(clkdm_list); @@ -235,58 +226,6 @@ void _clkdm_del_autodeps(struct clockdomain *clkdm) } } -/** - * _enable_hwsup - place a clockdomain into hardware-supervised idle - * @clkdm: struct clockdomain * - * - * Place the clockdomain into hardware-supervised idle mode. No return - * value. - * - * XXX Should this return an error if the clockdomain does not support - * hardware-supervised idle mode? - */ -static void _enable_hwsup(struct clockdomain *clkdm) -{ - if (cpu_is_omap24xx()) - omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - else if (cpu_is_omap34xx()) - omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - else if (cpu_is_omap44xx()) - return omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, - clkdm->cm_inst, - clkdm->clkdm_offs); - else - BUG(); -} - -/** - * _disable_hwsup - place a clockdomain into software-supervised idle - * @clkdm: struct clockdomain * - * - * Place the clockdomain @clkdm into software-supervised idle mode. - * No return value. - * - * XXX Should this return an error if the clockdomain does not support - * software-supervised idle mode? - */ -static void _disable_hwsup(struct clockdomain *clkdm) -{ - if (cpu_is_omap24xx()) - omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - else if (cpu_is_omap34xx()) - omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - else if (cpu_is_omap44xx()) - return omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition, - clkdm->cm_inst, - clkdm->clkdm_offs); - else - BUG(); -} - /** * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms * @clkdm: clockdomain that we are resolving dependencies for @@ -884,7 +823,7 @@ void clkdm_deny_idle(struct clockdomain *clkdm) /* Clockdomain-to-clock framework interface code */ /** - * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm + * clkdm_clk_enable - add an enabled downstream clock to this clkdm * @clkdm: struct clockdomain * * @clk: struct clk * of the enabled downstream clock * @@ -897,10 +836,8 @@ void clkdm_deny_idle(struct clockdomain *clkdm) * by on-chip processors. Returns -EINVAL if passed null pointers; * returns 0 upon success or if the clockdomain is in hwsup idle mode. */ -int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) +int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) { - bool hwsup = false; - /* * XXX Rewrite this code to maintain a list of enabled * downstream clocks for debugging purposes? @@ -909,6 +846,9 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) if (!clkdm || !clk) return -EINVAL; + if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable) + return -EINVAL; + if (atomic_inc_return(&clkdm->usecount) > 1) return 0; @@ -917,31 +857,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name, clk->name); - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - - if (!clkdm->clktrctrl_mask) - return 0; - - hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - - } else if (cpu_is_omap44xx()) { - - hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, - clkdm->cm_inst, - clkdm->clkdm_offs); - - } - - if (hwsup) { - /* Disable HW transitions when we are changing deps */ - _disable_hwsup(clkdm); - _clkdm_add_autodeps(clkdm); - _enable_hwsup(clkdm); - } else { - clkdm_wakeup(clkdm); - } - + arch_clkdm->clkdm_clk_enable(clkdm); pwrdm_wait_transition(clkdm->pwrdm.ptr); pwrdm_clkdm_state_switch(clkdm); @@ -949,7 +865,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) } /** - * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm + * clkdm_clk_disable - remove an enabled downstream clock from this clkdm * @clkdm: struct clockdomain * * @clk: struct clk * of the disabled downstream clock * @@ -962,10 +878,8 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) * is enabled; or returns 0 upon success or if the clockdomain is in * hwsup idle mode. */ -int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) +int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) { - bool hwsup = false; - /* * XXX Rewrite this code to maintain a list of enabled * downstream clocks for debugging purposes? @@ -974,6 +888,9 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) if (!clkdm || !clk) return -EINVAL; + if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable) + return -EINVAL; + #ifdef DEBUG if (atomic_read(&clkdm->usecount) == 0) { WARN_ON(1); /* underflow */ @@ -989,31 +906,7 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name, clk->name); - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - - if (!clkdm->clktrctrl_mask) - return 0; - - hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, - clkdm->clktrctrl_mask); - - } else if (cpu_is_omap44xx()) { - - hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, - clkdm->cm_inst, - clkdm->clkdm_offs); - - } - - if (hwsup) { - /* Disable HW transitions when we are changing deps */ - _disable_hwsup(clkdm); - _clkdm_del_autodeps(clkdm); - _enable_hwsup(clkdm); - } else { - clkdm_sleep(clkdm); - } - + arch_clkdm->clkdm_clk_disable(clkdm); pwrdm_clkdm_state_switch(clkdm); return 0; diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 7126658d9ae1..de52f059f9e2 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -173,8 +173,8 @@ void clkdm_deny_idle(struct clockdomain *clkdm); int clkdm_wakeup(struct clockdomain *clkdm); int clkdm_sleep(struct clockdomain *clkdm); -int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); -int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); +int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); +int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); extern void __init omap2xxx_clockdomains_init(void); extern void __init omap3xxx_clockdomains_init(void); diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index 25c27a5c722f..48d0db7e6069 100644 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -146,6 +146,71 @@ static void omap2_clkdm_deny_idle(struct clockdomain *clkdm) _clkdm_del_autodeps(clkdm); } +static void _enable_hwsup(struct clockdomain *clkdm) +{ + if (cpu_is_omap24xx()) + omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + else if (cpu_is_omap34xx()) + omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); +} + +static void _disable_hwsup(struct clockdomain *clkdm) +{ + if (cpu_is_omap24xx()) + omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + else if (cpu_is_omap34xx()) + omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); +} + + +static int omap2_clkdm_clk_enable(struct clockdomain *clkdm) +{ + bool hwsup = false; + + if (!clkdm->clktrctrl_mask) + return 0; + + hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + + if (hwsup) { + /* Disable HW transitions when we are changing deps */ + _disable_hwsup(clkdm); + _clkdm_add_autodeps(clkdm); + _enable_hwsup(clkdm); + } else { + clkdm_wakeup(clkdm); + } + + return 0; +} + +static int omap2_clkdm_clk_disable(struct clockdomain *clkdm) +{ + bool hwsup = false; + + if (!clkdm->clktrctrl_mask) + return 0; + + hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); + + if (hwsup) { + /* Disable HW transitions when we are changing deps */ + _disable_hwsup(clkdm); + _clkdm_del_autodeps(clkdm); + _enable_hwsup(clkdm); + } else { + clkdm_sleep(clkdm); + } + + return 0; +} + static int omap3_clkdm_sleep(struct clockdomain *clkdm) { omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs, @@ -187,6 +252,8 @@ struct clkdm_ops omap2_clkdm_operations = { .clkdm_wakeup = omap2_clkdm_wakeup, .clkdm_allow_idle = omap2_clkdm_allow_idle, .clkdm_deny_idle = omap2_clkdm_deny_idle, + .clkdm_clk_enable = omap2_clkdm_clk_enable, + .clkdm_clk_disable = omap2_clkdm_clk_disable, }; struct clkdm_ops omap3_clkdm_operations = { @@ -202,4 +269,6 @@ struct clkdm_ops omap3_clkdm_operations = { .clkdm_wakeup = omap3_clkdm_wakeup, .clkdm_allow_idle = omap3_clkdm_allow_idle, .clkdm_deny_idle = omap3_clkdm_deny_idle, + .clkdm_clk_enable = omap2_clkdm_clk_enable, + .clkdm_clk_disable = omap2_clkdm_clk_disable, }; diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c index a46125f15454..c0ccc4701646 100644 --- a/arch/arm/mach-omap2/clockdomain44xx.c +++ b/arch/arm/mach-omap2/clockdomain44xx.c @@ -41,9 +41,37 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) clkdm->cm_inst, clkdm->clkdm_offs); } +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); + + return 0; +} + +static int omap4_clkdm_clk_disable(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_sleep(clkdm); + + return 0; +} + struct clkdm_ops omap4_clkdm_operations = { .clkdm_sleep = omap4_clkdm_sleep, .clkdm_wakeup = omap4_clkdm_wakeup, .clkdm_allow_idle = omap4_clkdm_allow_idle, .clkdm_deny_idle = omap4_clkdm_deny_idle, + .clkdm_clk_enable = omap4_clkdm_clk_enable, + .clkdm_clk_disable = omap4_clkdm_clk_disable, }; From 514c5948b2b5a3f9f9ebc344fc03073f3bd481b4 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:48:13 -0700 Subject: [PATCH 07/62] OMAP4: clockdomain: Add clkdm static dependency srcs OMAP4 supports static dependencies and dynamic dependencies between clock domains. Static dependencies imply both wakeup as well as sleep dependencies. Generate all clockdomain static dependency sources. (Dynamic dependency sources are hardwired and cannot to controlled from software). The autogen scripts are updated to generate the contents of this patch. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomains44xx_data.c | 390 +++++++++++++++++++- 1 file changed, 385 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index eea6f8e40289..f53258acd1da 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -18,11 +18,6 @@ * published by the Free Software Foundation. */ -/* - * To-Do List - * -> Populate the Sleep/Wakeup dependencies for the domains - */ - #include #include @@ -35,6 +30,355 @@ #include "prcm44xx.h" #include "prcm_mpu44xx.h" +/* Static Dependencies for OMAP4 Clock Domains */ + +static struct clkdm_dep ducati_wkup_sleep_deps[] = { + { + .clkdm_name = "abe_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "ivahd_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_1_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_2_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_dss_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_gfx_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_init_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_cfg_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_per_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_secure_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_wkup_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "tesla_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep iss_wkup_sleep_deps[] = { + { + .clkdm_name = "ivahd_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_1_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep ivahd_wkup_sleep_deps[] = { + { + .clkdm_name = "l3_1_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep l3_d2d_wkup_sleep_deps[] = { + { + .clkdm_name = "abe_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "ivahd_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_1_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_2_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_init_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_cfg_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_per_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep l3_dma_wkup_sleep_deps[] = { + { + .clkdm_name = "abe_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "ducati_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "ivahd_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_1_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_dss_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_init_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_cfg_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_per_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_secure_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_wkup_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep l3_dss_wkup_sleep_deps[] = { + { + .clkdm_name = "ivahd_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_2_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep l3_gfx_wkup_sleep_deps[] = { + { + .clkdm_name = "ivahd_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_1_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep l3_init_wkup_sleep_deps[] = { + { + .clkdm_name = "abe_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "ivahd_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_cfg_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_per_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_secure_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_wkup_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep l4_secure_wkup_sleep_deps[] = { + { + .clkdm_name = "l3_1_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_per_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep mpuss_wkup_sleep_deps[] = { + { + .clkdm_name = "abe_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "ducati_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "ivahd_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_1_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_2_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_dss_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_gfx_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_init_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_cfg_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_per_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_secure_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_wkup_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "tesla_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; + +static struct clkdm_dep tesla_wkup_sleep_deps[] = { + { + .clkdm_name = "abe_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "ivahd_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_1_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_2_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_emif_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l3_init_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_cfg_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_per_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { + .clkdm_name = "l4_wkup_clkdm", + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430) + }, + { NULL }, +}; static struct clockdomain l4_cefuse_44xx_clkdm = { .name = "l4_cefuse_clkdm", @@ -52,6 +396,7 @@ static struct clockdomain l4_cfg_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_CORE_INST, .clkdm_offs = OMAP4430_CM2_CORE_L4CFG_CDOFFS, + .dep_bit = OMAP4430_L4CFG_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -62,6 +407,9 @@ static struct clockdomain tesla_44xx_clkdm = { .prcm_partition = OMAP4430_CM1_PARTITION, .cm_inst = OMAP4430_CM1_TESLA_INST, .clkdm_offs = OMAP4430_CM1_TESLA_TESLA_CDOFFS, + .dep_bit = OMAP4430_TESLA_STATDEP_SHIFT, + .wkdep_srcs = tesla_wkup_sleep_deps, + .sleepdep_srcs = tesla_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -72,6 +420,9 @@ static struct clockdomain l3_gfx_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_GFX_INST, .clkdm_offs = OMAP4430_CM2_GFX_GFX_CDOFFS, + .dep_bit = OMAP4430_GFX_STATDEP_SHIFT, + .wkdep_srcs = l3_gfx_wkup_sleep_deps, + .sleepdep_srcs = l3_gfx_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -82,6 +433,9 @@ static struct clockdomain ivahd_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_IVAHD_INST, .clkdm_offs = OMAP4430_CM2_IVAHD_IVAHD_CDOFFS, + .dep_bit = OMAP4430_IVAHD_STATDEP_SHIFT, + .wkdep_srcs = ivahd_wkup_sleep_deps, + .sleepdep_srcs = ivahd_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -92,6 +446,9 @@ static struct clockdomain l4_secure_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_L4PER_INST, .clkdm_offs = OMAP4430_CM2_L4PER_L4SEC_CDOFFS, + .dep_bit = OMAP4430_L4SEC_STATDEP_SHIFT, + .wkdep_srcs = l4_secure_wkup_sleep_deps, + .sleepdep_srcs = l4_secure_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -102,6 +459,7 @@ static struct clockdomain l4_per_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_L4PER_INST, .clkdm_offs = OMAP4430_CM2_L4PER_L4PER_CDOFFS, + .dep_bit = OMAP4430_L4PER_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -112,6 +470,7 @@ static struct clockdomain abe_44xx_clkdm = { .prcm_partition = OMAP4430_CM1_PARTITION, .cm_inst = OMAP4430_CM1_ABE_INST, .clkdm_offs = OMAP4430_CM1_ABE_ABE_CDOFFS, + .dep_bit = OMAP4430_ABE_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -131,6 +490,9 @@ static struct clockdomain l3_init_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_L3INIT_INST, .clkdm_offs = OMAP4430_CM2_L3INIT_L3INIT_CDOFFS, + .dep_bit = OMAP4430_L3INIT_STATDEP_SHIFT, + .wkdep_srcs = l3_init_wkup_sleep_deps, + .sleepdep_srcs = l3_init_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -141,6 +503,8 @@ static struct clockdomain mpuss_44xx_clkdm = { .prcm_partition = OMAP4430_CM1_PARTITION, .cm_inst = OMAP4430_CM1_MPU_INST, .clkdm_offs = OMAP4430_CM1_MPU_MPU_CDOFFS, + .wkdep_srcs = mpuss_wkup_sleep_deps, + .sleepdep_srcs = mpuss_wkup_sleep_deps, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -171,6 +535,7 @@ static struct clockdomain l3_emif_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_CORE_INST, .clkdm_offs = OMAP4430_CM2_CORE_MEMIF_CDOFFS, + .dep_bit = OMAP4430_MEMIF_STATDEP_SHIFT, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -191,6 +556,9 @@ static struct clockdomain ducati_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_CORE_INST, .clkdm_offs = OMAP4430_CM2_CORE_DUCATI_CDOFFS, + .dep_bit = OMAP4430_DUCATI_STATDEP_SHIFT, + .wkdep_srcs = ducati_wkup_sleep_deps, + .sleepdep_srcs = ducati_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -201,6 +569,7 @@ static struct clockdomain l3_2_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_CORE_INST, .clkdm_offs = OMAP4430_CM2_CORE_L3_2_CDOFFS, + .dep_bit = OMAP4430_L3_2_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -211,6 +580,7 @@ static struct clockdomain l3_1_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_CORE_INST, .clkdm_offs = OMAP4430_CM2_CORE_L3_1_CDOFFS, + .dep_bit = OMAP4430_L3_1_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -221,6 +591,8 @@ static struct clockdomain l3_d2d_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_CORE_INST, .clkdm_offs = OMAP4430_CM2_CORE_D2D_CDOFFS, + .wkdep_srcs = l3_d2d_wkup_sleep_deps, + .sleepdep_srcs = l3_d2d_wkup_sleep_deps, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -231,6 +603,8 @@ static struct clockdomain iss_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_CAM_INST, .clkdm_offs = OMAP4430_CM2_CAM_CAM_CDOFFS, + .wkdep_srcs = iss_wkup_sleep_deps, + .sleepdep_srcs = iss_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -241,6 +615,9 @@ static struct clockdomain l3_dss_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_DSS_INST, .clkdm_offs = OMAP4430_CM2_DSS_DSS_CDOFFS, + .dep_bit = OMAP4430_DSS_STATDEP_SHIFT, + .wkdep_srcs = l3_dss_wkup_sleep_deps, + .sleepdep_srcs = l3_dss_wkup_sleep_deps, .flags = CLKDM_CAN_HWSUP_SWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -251,6 +628,7 @@ static struct clockdomain l4_wkup_44xx_clkdm = { .prcm_partition = OMAP4430_PRM_PARTITION, .cm_inst = OMAP4430_PRM_WKUP_CM_INST, .clkdm_offs = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS, + .dep_bit = OMAP4430_L4WKUP_STATDEP_SHIFT, .flags = CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -271,6 +649,8 @@ static struct clockdomain l3_dma_44xx_clkdm = { .prcm_partition = OMAP4430_CM2_PARTITION, .cm_inst = OMAP4430_CM2_CORE_INST, .clkdm_offs = OMAP4430_CM2_CORE_SDMA_CDOFFS, + .wkdep_srcs = l3_dma_wkup_sleep_deps, + .sleepdep_srcs = l3_dma_wkup_sleep_deps, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; From 04eb7773d803bd0a8249c5bba37f81c496253ea1 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:48:14 -0700 Subject: [PATCH 08/62] OMAP4: CM: Add CM accesor api for bitwise control Add new OMAP4 CM accesor apis to set/clear and read bitfields (based on mask) from CM registers. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/cminst44xx.c | 21 +++++++++++++++++++++ arch/arm/mach-omap2/cminst44xx.h | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index c04bbbea17a5..a482bfa0a954 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -73,6 +73,27 @@ u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst, return v; } +u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx) +{ + return omap4_cminst_rmw_inst_reg_bits(bits, bits, part, inst, idx); +} + +u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx) +{ + return omap4_cminst_rmw_inst_reg_bits(bits, 0x0, part, inst, idx); +} + +u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, u32 mask) +{ + u32 v; + + v = omap4_cminst_read_inst_reg(part, inst, idx); + v &= mask; + v >>= __ffs(mask); + + return v; +} + /* * */ diff --git a/arch/arm/mach-omap2/cminst44xx.h b/arch/arm/mach-omap2/cminst44xx.h index a6abd0a8cb82..2b32c181a2ee 100644 --- a/arch/arm/mach-omap2/cminst44xx.h +++ b/arch/arm/mach-omap2/cminst44xx.h @@ -25,6 +25,12 @@ extern u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx); extern void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx); extern u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst, s16 idx); +extern u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst, + s16 idx); +extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst, + s16 idx); +extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, + u32 mask); extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg); From 15b08d930f0b1a65a20e042046bd99ed7f75556b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:48:14 -0700 Subject: [PATCH 09/62] OMAP4: clockdomain: Add wkup/sleep dependency support Add OMAP4 platform specific implementation to support clkdm wkup and sleep dependencies a.k.a static dependencies. Signed-off-by: Rajendra Nayak [paul@pwsan.com: removed comment about PRM; zero-prefixed STATICDEP register offset; fixed loop termination condition in omap4_clkdm_clear_all_wkup_sleep_deps(); thanks to Kevin Hilman for finding and helping fix this bug] Cc: Kevin Hilman Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomain44xx.c | 60 +++++++++++++++++++++++++++ arch/arm/mach-omap2/cm44xx.h | 1 + 2 files changed, 61 insertions(+) diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c index c0ccc4701646..a1a4ecd26544 100644 --- a/arch/arm/mach-omap2/clockdomain44xx.c +++ b/arch/arm/mach-omap2/clockdomain44xx.c @@ -12,8 +12,60 @@ * published by the Free Software Foundation. */ +#include #include "clockdomain.h" #include "cminst44xx.h" +#include "cm44xx.h" + +static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit), + clkdm1->prcm_partition, + clkdm1->cm_inst, clkdm1->clkdm_offs + + OMAP4_CM_STATICDEP); + return 0; +} + +static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit), + clkdm1->prcm_partition, + clkdm1->cm_inst, clkdm1->clkdm_offs + + OMAP4_CM_STATICDEP); + return 0; +} + +static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1, + struct clockdomain *clkdm2) +{ + return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition, + clkdm1->cm_inst, clkdm1->clkdm_offs + + OMAP4_CM_STATICDEP, + (1 << clkdm2->dep_bit)); +} + +static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm) +{ + struct clkdm_dep *cd; + u32 mask = 0; + + for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { + if (!omap_chip_is(cd->omap_chip)) + continue; + if (!cd->clkdm) + continue; /* only happens if data is erroneous */ + + mask |= 1 << cd->clkdm->dep_bit; + atomic_set(&cd->wkdep_usecount, 0); + } + + omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition, + clkdm->cm_inst, clkdm->clkdm_offs + + OMAP4_CM_STATICDEP); + return 0; +} static int omap4_clkdm_sleep(struct clockdomain *clkdm) { @@ -68,6 +120,14 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm) } struct clkdm_ops omap4_clkdm_operations = { + .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep, + .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep, + .clkdm_read_wkdep = omap4_clkdm_read_wkup_sleep_dep, + .clkdm_clear_all_wkdeps = omap4_clkdm_clear_all_wkup_sleep_deps, + .clkdm_add_sleepdep = omap4_clkdm_add_wkup_sleep_dep, + .clkdm_del_sleepdep = omap4_clkdm_del_wkup_sleep_dep, + .clkdm_read_sleepdep = omap4_clkdm_read_wkup_sleep_dep, + .clkdm_clear_all_sleepdeps = omap4_clkdm_clear_all_wkup_sleep_deps, .clkdm_sleep = omap4_clkdm_sleep, .clkdm_wakeup = omap4_clkdm_wakeup, .clkdm_allow_idle = omap4_clkdm_allow_idle, diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h index 48fc3f426fbd..0b87ec82b41c 100644 --- a/arch/arm/mach-omap2/cm44xx.h +++ b/arch/arm/mach-omap2/cm44xx.h @@ -21,6 +21,7 @@ #include "cm.h" #define OMAP4_CM_CLKSTCTRL 0x0000 +#define OMAP4_CM_STATICDEP 0x0004 /* Function prototypes */ # ifndef __ASSEMBLER__ From 5f8662ba3da6e410eb771b5d8751a1e02d87513f Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:48:14 -0700 Subject: [PATCH 10/62] OMAP4: clockdomain: Remove pr_errs' stating unsupported wkdep Now that wkup and sleep dependencies are supported (in the form of static deps) for OMAP4, remove all instances of pr_errs' stating dependencies are still unsupported on OMAP4. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomain.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 70d242007e0b..a0341dee1c3a 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -400,12 +400,6 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) struct clkdm_dep *cd; int ret = 0; - if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { - pr_err("clockdomain: %s/%s: %s: not yet implemented\n", - clkdm1->name, clkdm2->name, __func__); - return -EINVAL; - } - if (!clkdm1 || !clkdm2) return -EINVAL; @@ -447,12 +441,6 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) struct clkdm_dep *cd; int ret = 0; - if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { - pr_err("clockdomain: %s/%s: %s: not yet implemented\n", - clkdm1->name, clkdm2->name, __func__); - return -EINVAL; - } - if (!clkdm1 || !clkdm2) return -EINVAL; @@ -501,12 +489,6 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) if (!clkdm1 || !clkdm2) return -EINVAL; - if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { - pr_err("clockdomain: %s/%s: %s: not yet implemented\n", - clkdm1->name, clkdm2->name, __func__); - return -EINVAL; - } - cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); if (IS_ERR(cd)) ret = PTR_ERR(cd); @@ -536,12 +518,6 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) */ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) { - if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { - pr_err("clockdomain: %s: %s: not yet implemented\n", - clkdm->name, __func__); - return -EINVAL; - } - if (!clkdm) return -EINVAL; From 6c52f32dcf1d76a95bda3a12d6be9a3102a2693c Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:48:36 -0700 Subject: [PATCH 11/62] omap: clock: Check for enable/disable ops support Check if enable/disable operations are supported for a given clock node before attempting to call them. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index e9625fcf6390..b1875965bb51 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -261,7 +261,8 @@ void omap2_clk_disable(struct clk *clk) pr_debug("clock: %s: disabling in hardware\n", clk->name); - clk->ops->disable(clk); + if (clk->ops && clk->ops->disable) + clk->ops->disable(clk); if (clk->clkdm) clkdm_clk_disable(clk->clkdm, clk); @@ -312,10 +313,13 @@ int omap2_clk_enable(struct clk *clk) } } - ret = clk->ops->enable(clk); - if (ret) { - WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret); - goto oce_err3; + if (clk->ops && clk->ops->enable) { + ret = clk->ops->enable(clk); + if (ret) { + WARN(1, "clock: %s: could not enable: %d\n", + clk->name, ret); + goto oce_err3; + } } return 0; From 5a2926b8805bc697d47a243dbf2f20de68abe14c Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:48:37 -0700 Subject: [PATCH 12/62] omap3: dpll: Populate clkops for dpll1_ck DPLL1 on omap3 is very similar to the rest of the non-core dpll's. Hence populate clkops_omap3_noncore_dpll_ops as the clkops for it, instead of the currently populated clkops_null. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock3xxx_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index f14d986f0b5d..0cdb8343d658 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -296,7 +296,7 @@ static struct dpll_data dpll1_dd = { static struct clk dpll1_ck = { .name = "dpll1_ck", - .ops = &clkops_null, + .ops = &clkops_omap3_noncore_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll1_dd, .round_rate = &omap2_dpll_round_rate, From 58e846fe7870d0ba22f8eeb1d522fbae37e80cbf Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:49:00 -0700 Subject: [PATCH 13/62] OMAP: clock: Add allow_idle/deny_idle support in clkops On OMAP various clock nodes (dpll's, mx post dividers, interface clocks) support hardware level autogating which can be controlled from software. Support such functionality by adding two new function pointer allow_idle and deny_idle in the clkops structure. These function pointers can be populated for any clock node which supports hardware level autogating. Also add 2 new functions (omap_clk_enable_autoidle_all and omap_clk_disable_autoidle_all) which can be called from architecture specific PM core code, if hardware level autogating (for all supported clock nodes) is to be enabled or disabled. Signed-off-by: Rajendra Nayak [paul@pwsan.com: use spinlock rather than mutex due to race; renamed functions; functions now return ints] Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/clock.c | 32 +++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/clock.h | 6 +++++ 2 files changed, 38 insertions(+) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index fc62fb5fc20b..0ae0eae01fd1 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -335,6 +335,38 @@ struct clk *omap_clk_get_by_name(const char *name) return ret; } +int omap_clk_enable_autoidle_all(void) +{ + struct clk *c; + unsigned long flags; + + spin_lock_irqsave(&clockfw_lock, flags); + + list_for_each_entry(c, &clocks, node) + if (c->ops->allow_idle) + c->ops->allow_idle(c); + + spin_unlock_irqrestore(&clockfw_lock, flags); + + return 0; +} + +int omap_clk_disable_autoidle_all(void) +{ + struct clk *c; + unsigned long flags; + + spin_lock_irqsave(&clockfw_lock, flags); + + list_for_each_entry(c, &clocks, node) + if (c->ops->deny_idle) + c->ops->deny_idle(c); + + spin_unlock_irqrestore(&clockfw_lock, flags); + + return 0; +} + /* * Low level helpers */ diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index d43e6234dbbb..be69f5cac32d 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -25,6 +25,8 @@ struct clockdomain; * @disable: fn ptr that enables the current clock in hardware * @find_idlest: function returning the IDLEST register for the clock's IP blk * @find_companion: function returning the "companion" clk reg for the clock + * @allow_idle: fn ptr that enables autoidle for the current clock in hardware + * @deny_idle: fn ptr that disables autoidle for the current clock in hardware * * A "companion" clk is an accompanying clock to the one being queried * that must be enabled for the IP module connected to the clock to @@ -42,6 +44,8 @@ struct clkops { u8 *, u8 *); void (*find_companion)(struct clk *, void __iomem **, u8 *); + void (*allow_idle)(struct clk *); + void (*deny_idle)(struct clk *); }; #ifdef CONFIG_ARCH_OMAP2PLUS @@ -293,6 +297,8 @@ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table); extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table); #endif extern struct clk *omap_clk_get_by_name(const char *name); +extern int omap_clk_enable_autoidle_all(void); +extern int omap_clk_disable_autoidle_all(void); extern const struct clkops clkops_null; From 6c6f5a7437955cec637c00ab1d09b8f70fc0ab3a Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:49:00 -0700 Subject: [PATCH 14/62] OMAP3/4: DPLL: Add allow_idle/deny_idle support for all DPLL's All OMAP3/4 dpll's support hardware level autogating. Populate allow_idle/deny_idle function pointers for all DPLL's in clkops. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock.c | 8 +++++++- arch/arm/mach-omap2/clock.h | 1 + arch/arm/mach-omap2/clock3xxx_data.c | 2 +- arch/arm/mach-omap2/clock44xx_data.c | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index b1875965bb51..46d03ccc2806 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -377,11 +377,17 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) const struct clkops clkops_omap3_noncore_dpll_ops = { .enable = omap3_noncore_dpll_enable, .disable = omap3_noncore_dpll_disable, + .allow_idle = omap3_dpll_allow_idle, + .deny_idle = omap3_dpll_deny_idle, +}; + +const struct clkops clkops_omap3_core_dpll_ops = { + .allow_idle = omap3_dpll_allow_idle, + .deny_idle = omap3_dpll_deny_idle, }; #endif - /* * OMAP2+ clock reset and init functions */ diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 896584e3c4ab..2a939e5ec6a2 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -146,5 +146,6 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) #endif extern const struct clkops clkops_omap3_noncore_dpll_ops; +extern const struct clkops clkops_omap3_core_dpll_ops; #endif diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 0cdb8343d658..78ea7997686b 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -429,7 +429,7 @@ static struct dpll_data dpll3_dd = { static struct clk dpll3_ck = { .name = "dpll3_ck", - .ops = &clkops_null, + .ops = &clkops_omap3_core_dpll_ops, .parent = &sys_ck, .dpll_data = &dpll3_dd, .round_rate = &omap2_dpll_round_rate, diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index de9ec8ddd2ae..b843b6e5976c 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -443,7 +443,7 @@ static struct clk dpll_core_ck = { .parent = &sys_clkin_ck, .dpll_data = &dpll_core_dd, .init = &omap2_init_dpll_parent, - .ops = &clkops_null, + .ops = &clkops_omap3_core_dpll_ops, .recalc = &omap3_dpll_recalc, }; From b80b956dc56c6a3cb77b97e2abff48fb7ebc2119 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:49:01 -0700 Subject: [PATCH 15/62] OMAP2+: clock: autoidle as many clocks as possible if CONFIG_OMAP_RESET_CLOCKS Attempt to enable autoidle for as many clocks as possible in the OMAP2+-common CONFIG_OMAP_RESET_CLOCKS code. Currently, this only enables DPLL autoidle for OMAP3/4 DPLLs; but future patches will enable autoidle for other clocks and the OMAP2 DPLL/APLLs. In the long run, we should probably get rid of CONFIG_OMAP_RESET_CLOCKS, and unconditionally run the code that it selects. Otherwise, the state of the clock tree won't match the hardware state - this could result in clocks being enabled or disabled unpredictably. Based on a patch by Rajendra Nayak that did this in the pm34xx.c/pm44xx.c code. Signed-off-by: Paul Walmsley Cc: Rajendra Nayak --- arch/arm/mach-omap2/pm34xx.c | 17 ----------------- arch/arm/plat-omap/clock.c | 1 + 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index eda9a4e99a89..a99f296bdbfd 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -813,23 +813,6 @@ static void __init prcm_setup_regs(void) omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG); - /* - * Set all plls to autoidle. This is needed until autoidle is - * enabled by clockfw - */ - omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT, - OMAP3430_IVA2_MOD, CM_AUTOIDLE2); - omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT, - MPU_MOD, - CM_AUTOIDLE2); - omap2_cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) | - (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT), - PLL_MOD, - CM_AUTOIDLE); - omap2_cm_write_mod_reg(1 << OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT, - PLL_MOD, - CM_AUTOIDLE2); - /* * Enable control of expternal oscillator through * sys_clkreq. In the long run clock framework should diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 0ae0eae01fd1..2770dddd72c0 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -446,6 +446,7 @@ static int __init clk_disable_unused(void) return 0; } late_initcall(clk_disable_unused); +late_initcall(omap_clk_enable_autoidle_all); #endif int __init clk_init(struct clk_functions * custom_clocks) From 97f678989afe5dd1584a0877dfd8b0d2e124b73a Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:49:01 -0700 Subject: [PATCH 16/62] OMAP4: DPLL: Add dpll api to control GATE_CTRL On OMAP4, the dpll post divider outputs (MX outputs) along with clockout_x2 output provide a way to allow/deny hardware level autogating. Allowing autoidle would mean that the hw would autogate this clock when there is no dependency for it. Denying idle would mean that this clock output will be forced to stay enabled. Add dpll api's to read/allow/deny idle control for these dpll mx postdividers. NOTE: The gatectrl bit set to 0 allows gatectrl, and the bit set to 1 denies gatectrl. Signed-off-by: Rajendra Nayak [paul@pwsan.com: moved OMAP4-specific DPLL control code to mach-omap2/dpll44xx.c; added some documentation for CLOCK_CLKOUTX2] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/Makefile | 2 +- arch/arm/mach-omap2/clock.h | 3 + arch/arm/mach-omap2/dpll44xx.c | 78 +++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/clock.h | 14 ++++- 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-omap2/dpll44xx.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 10c3c8f16eaa..89274a9f0357 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -123,7 +123,7 @@ obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o \ clock3517.o clock36xx.o \ dpll3xxx.o clock3xxx_data.o obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) clock44xx_data.o \ - dpll3xxx.o + dpll3xxx.o dpll44xx.o # OMAP2 clock rate set data (old "OPP" data) obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 2a939e5ec6a2..c450d69a0dce 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -65,6 +65,9 @@ u32 omap3_dpll_autoidle_read(struct clk *clk); int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate); int omap3_noncore_dpll_enable(struct clk *clk); void omap3_noncore_dpll_disable(struct clk *clk); +int omap4_dpllmx_gatectrl_read(struct clk *clk); +void omap4_dpllmx_allow_gatectrl(struct clk *clk); +void omap4_dpllmx_deny_gatectrl(struct clk *clk); #ifdef CONFIG_OMAP_RESET_CLOCKS void omap2_clk_disable_unused(struct clk *clk); diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c new file mode 100644 index 000000000000..94a3592cd54c --- /dev/null +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -0,0 +1,78 @@ +/* + * OMAP4-specific DPLL control functions + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Rajendra Nayak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "clock.h" +#include "cm-regbits-44xx.h" + +/* Supported only on OMAP4 */ +int omap4_dpllmx_gatectrl_read(struct clk *clk) +{ + u32 v; + u32 mask; + + if (!clk || !clk->clksel_reg || !cpu_is_omap44xx()) + return -EINVAL; + + mask = clk->flags & CLOCK_CLKOUTX2 ? + OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : + OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; + + v = __raw_readl(clk->clksel_reg); + v &= mask; + v >>= __ffs(mask); + + return v; +} + +void omap4_dpllmx_allow_gatectrl(struct clk *clk) +{ + u32 v; + u32 mask; + + if (!clk || !clk->clksel_reg || !cpu_is_omap44xx()) + return; + + mask = clk->flags & CLOCK_CLKOUTX2 ? + OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : + OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; + + v = __raw_readl(clk->clksel_reg); + /* Clear the bit to allow gatectrl */ + v &= ~mask; + __raw_writel(v, clk->clksel_reg); +} + +void omap4_dpllmx_deny_gatectrl(struct clk *clk) +{ + u32 v; + u32 mask; + + if (!clk || !clk->clksel_reg || !cpu_is_omap44xx()) + return; + + mask = clk->flags & CLOCK_CLKOUTX2 ? + OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : + OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; + + v = __raw_readl(clk->clksel_reg); + /* Set the bit to deny gatectrl */ + v |= mask; + __raw_writel(v, clk->clksel_reg); +} diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index be69f5cac32d..dcd7bb81420d 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -176,12 +176,24 @@ struct dpll_data { #endif -/* struct clk.flags possibilities */ +/* + * struct clk.flags possibilities + * + * XXX document the rest of the clock flags here + * + * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL + * bits share the same register. This flag allows the + * omap4_dpllmx*() code to determine which GATE_CTRL bit field + * should be used. This is a temporary solution - a better approach + * would be to associate clock type-specific data with the clock, + * similar to the struct dpll_data approach. + */ #define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */ #define CLOCK_IDLE_CONTROL (1 << 1) #define CLOCK_NO_IDLE_PARENT (1 << 2) #define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */ #define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ +#define CLOCK_CLKOUTX2 (1 << 5) /** * struct clk - OMAP struct clk From 70db8a6273692fdf5226c007c9882a10b3203963 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:49:02 -0700 Subject: [PATCH 17/62] omap4: dpll: Enable auto gate control for all MX postdividers Enable hardware gate control for all dpll MX and X2 postdividers. This requires the allow_idle/deny_idle functions to be populated for all clock nodes (mx/x2 post dividers) in clkops. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock.h | 1 + arch/arm/mach-omap2/clock44xx_data.c | 52 ++++++++++++++++------------ arch/arm/mach-omap2/dpll44xx.c | 6 ++++ 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index c450d69a0dce..0725a6ad8b46 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -150,5 +150,6 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) extern const struct clkops clkops_omap3_noncore_dpll_ops; extern const struct clkops clkops_omap3_core_dpll_ops; +extern const struct clkops clkops_omap4_dpllmx_ops; #endif diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index b843b6e5976c..dcbe10571a0f 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -278,8 +278,10 @@ static struct clk dpll_abe_ck = { static struct clk dpll_abe_x2_ck = { .name = "dpll_abe_x2_ck", .parent = &dpll_abe_ck, - .ops = &clkops_null, + .flags = CLOCK_CLKOUTX2, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap3_clkoutx2_recalc, + .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE, }; static const struct clksel_rate div31_1to31_rates[] = { @@ -328,7 +330,7 @@ static struct clk dpll_abe_m2x2_ck = { .clksel = dpll_abe_m2x2_div, .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE, .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -395,7 +397,7 @@ static struct clk dpll_abe_m3x2_ck = { .clksel = dpll_abe_m2x2_div, .clksel_reg = OMAP4430_CM_DIV_M3_DPLL_ABE, .clksel_mask = OMAP4430_DPLL_CLKOUTHIF_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -450,6 +452,7 @@ static struct clk dpll_core_ck = { static struct clk dpll_core_x2_ck = { .name = "dpll_core_x2_ck", .parent = &dpll_core_ck, + .flags = CLOCK_CLKOUTX2, .ops = &clkops_null, .recalc = &omap3_clkoutx2_recalc, }; @@ -465,7 +468,7 @@ static struct clk dpll_core_m6x2_ck = { .clksel = dpll_core_m6x2_div, .clksel_reg = OMAP4430_CM_DIV_M6_DPLL_CORE, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -495,7 +498,7 @@ static struct clk dpll_core_m2_ck = { .clksel = dpll_core_m2_div, .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_CORE, .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -515,7 +518,7 @@ static struct clk dpll_core_m5x2_ck = { .clksel = dpll_core_m6x2_div, .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_CORE, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -581,7 +584,7 @@ static struct clk dpll_core_m4x2_ck = { .clksel = dpll_core_m6x2_div, .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_CORE, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -606,7 +609,7 @@ static struct clk dpll_abe_m2_ck = { .clksel = dpll_abe_m2_div, .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_ABE, .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -632,7 +635,7 @@ static struct clk dpll_core_m7x2_ck = { .clksel = dpll_core_m6x2_div, .clksel_reg = OMAP4430_CM_DIV_M7_DPLL_CORE, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -689,6 +692,7 @@ static struct clk dpll_iva_ck = { static struct clk dpll_iva_x2_ck = { .name = "dpll_iva_x2_ck", .parent = &dpll_iva_ck, + .flags = CLOCK_CLKOUTX2, .ops = &clkops_null, .recalc = &omap3_clkoutx2_recalc, }; @@ -704,7 +708,7 @@ static struct clk dpll_iva_m4x2_ck = { .clksel = dpll_iva_m4x2_div, .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_IVA, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -716,7 +720,7 @@ static struct clk dpll_iva_m5x2_ck = { .clksel = dpll_iva_m4x2_div, .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_IVA, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -764,7 +768,7 @@ static struct clk dpll_mpu_m2_ck = { .clksel = dpll_mpu_m2_div, .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_MPU, .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -837,7 +841,7 @@ static struct clk dpll_per_m2_ck = { .clksel = dpll_per_m2_div, .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER, .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -846,8 +850,10 @@ static struct clk dpll_per_m2_ck = { static struct clk dpll_per_x2_ck = { .name = "dpll_per_x2_ck", .parent = &dpll_per_ck, - .ops = &clkops_null, + .flags = CLOCK_CLKOUTX2, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap3_clkoutx2_recalc, + .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER, }; static const struct clksel dpll_per_m2x2_div[] = { @@ -861,7 +867,7 @@ static struct clk dpll_per_m2x2_ck = { .clksel = dpll_per_m2x2_div, .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_PER, .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -887,7 +893,7 @@ static struct clk dpll_per_m4x2_ck = { .clksel = dpll_per_m2x2_div, .clksel_reg = OMAP4430_CM_DIV_M4_DPLL_PER, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -899,7 +905,7 @@ static struct clk dpll_per_m5x2_ck = { .clksel = dpll_per_m2x2_div, .clksel_reg = OMAP4430_CM_DIV_M5_DPLL_PER, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -911,7 +917,7 @@ static struct clk dpll_per_m6x2_ck = { .clksel = dpll_per_m2x2_div, .clksel_reg = OMAP4430_CM_DIV_M6_DPLL_PER, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -923,7 +929,7 @@ static struct clk dpll_per_m7x2_ck = { .clksel = dpll_per_m2x2_div, .clksel_reg = OMAP4430_CM_DIV_M7_DPLL_PER, .clksel_mask = OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -964,6 +970,7 @@ static struct clk dpll_unipro_ck = { static struct clk dpll_unipro_x2_ck = { .name = "dpll_unipro_x2_ck", .parent = &dpll_unipro_ck, + .flags = CLOCK_CLKOUTX2, .ops = &clkops_null, .recalc = &omap3_clkoutx2_recalc, }; @@ -979,7 +986,7 @@ static struct clk dpll_unipro_m2x2_ck = { .clksel = dpll_unipro_m2x2_div, .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_UNIPRO, .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, @@ -1028,7 +1035,8 @@ static struct clk dpll_usb_ck = { static struct clk dpll_usb_clkdcoldo_ck = { .name = "dpll_usb_clkdcoldo_ck", .parent = &dpll_usb_ck, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, + .clksel_reg = OMAP4430_CM_CLKDCOLDO_DPLL_USB, .recalc = &followparent_recalc, }; @@ -1043,7 +1051,7 @@ static struct clk dpll_usb_m2_ck = { .clksel = dpll_usb_m2_div, .clksel_reg = OMAP4430_CM_DIV_M2_DPLL_USB, .clksel_mask = OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK, - .ops = &clkops_null, + .ops = &clkops_omap4_dpllmx_ops, .recalc = &omap2_clksel_recalc, .round_rate = &omap2_clksel_round_rate, .set_rate = &omap2_clksel_set_rate, diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 94a3592cd54c..4e4da6160d05 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -76,3 +76,9 @@ void omap4_dpllmx_deny_gatectrl(struct clk *clk) v |= mask; __raw_writel(v, clk->clksel_reg); } + +const struct clkops clkops_omap4_dpllmx_ops = { + .allow_idle = omap4_dpllmx_allow_gatectrl, + .deny_idle = omap4_dpllmx_deny_gatectrl, +}; + From c6461f5c5970833cf28c5096cdfc7a095eb3bbb5 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:49:53 -0700 Subject: [PATCH 18/62] OMAP2+: clock: disable autoidle on all clocks during clock init Disable autoidle on all clocks during clock framework initialization. (If CONFIG_PM is set, autoidle is re-enabled for all clocks later in the boot process.) The principle behind this patch, and some similar patches, is that the kernel should start with all power management features disabled. Later in the boot process, the PM code, if compiled in with CONFIG_PM, enables or re-enables power management features. Signed-off-by: Paul Walmsley Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/clock2420_data.c | 3 +++ arch/arm/mach-omap2/clock2430_data.c | 3 +++ arch/arm/mach-omap2/clock3xxx.c | 3 --- arch/arm/mach-omap2/clock3xxx_data.c | 6 +++++- arch/arm/mach-omap2/clock44xx_data.c | 3 +++ 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 0a992bc8d0d8..ee73e14ac3c8 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1913,6 +1913,9 @@ int __init omap2420_clk_init(void) omap2_init_clk_clkdm(c->lk.clk); } + /* Disable autoidle on all clocks; let the PM code enable it later */ + omap_clk_disable_autoidle_all(); + /* Check the MPU rate set by bootloader */ clkrate = omap2xxx_clk_get_core_rate(&dpll_ck); for (prcm = rate_table; prcm->mpu_speed; prcm++) { diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index c047dcd007e5..a1298e55d915 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -2028,6 +2028,9 @@ int __init omap2430_clk_init(void) omap2_init_clk_clkdm(c->lk.clk); } + /* Disable autoidle on all clocks; let the PM code enable it later */ + omap_clk_disable_autoidle_all(); + /* Check the MPU rate set by bootloader */ clkrate = omap2xxx_clk_get_core_rate(&dpll_ck); for (prcm = rate_table; prcm->mpu_speed; prcm++) { diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c index e9f66b6dec18..952c3e01c9eb 100644 --- a/arch/arm/mach-omap2/clock3xxx.c +++ b/arch/arm/mach-omap2/clock3xxx.c @@ -65,9 +65,6 @@ void __init omap3_clk_lock_dpll5(void) clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST); clk_enable(dpll5_clk); - /* Enable autoidle to allow it to enter low power bypass */ - omap3_dpll_allow_idle(dpll5_clk); - /* Program dpll5_m2_clk divider for no division */ dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck"); clk_enable(dpll5_m2_clk); diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 78ea7997686b..65b79e6afb53 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -3538,6 +3538,9 @@ int __init omap3xxx_clk_init(void) omap2_init_clk_clkdm(c->lk.clk); } + /* Disable autoidle on all clocks; let the PM code enable it later */ + omap_clk_disable_autoidle_all(); + recalculate_root_clocks(); pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n", @@ -3551,7 +3554,8 @@ int __init omap3xxx_clk_init(void) clk_enable_init_clocks(); /* - * Lock DPLL5 and put it in autoidle. + * Lock DPLL5 -- here only until other device init code can + * handle this */ if (!cpu_is_ti816x() && (omap_rev() >= OMAP3430_REV_ES2_0)) omap3_clk_lock_dpll5(); diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index dcbe10571a0f..279534240fc3 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3309,6 +3309,9 @@ int __init omap4xxx_clk_init(void) omap2_init_clk_clkdm(c->lk.clk); } + /* Disable autoidle on all clocks; let the PM code enable it later */ + omap_clk_disable_autoidle_all(); + recalculate_root_clocks(); /* From 1a9f5e89d67855385ed42b7b71167e2d3a39507a Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Tue, 8 Feb 2011 14:30:31 -0700 Subject: [PATCH 19/62] omap4: clockdomain: Fix the CPUx domain name The register naming convention for clock domain control inside power domain instance is: OMAPXXXX____CDOFFS Both CPU0 and CPU1 use MPU as clock domain name instead of CPU0 and CPU1. Change the name to stick to the convention. The autogen scripts are updated accordingly. Signed-off-by: Benoit Cousson Signed-off-by: Santosh Shilimkar Cc: Paul Walmsley Cc: Rajendra Nayak Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomains44xx_data.c | 4 ++-- arch/arm/mach-omap2/prcm_mpu44xx.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index 10622c914abc..3d1c06b1676c 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -150,7 +150,7 @@ static struct clockdomain mpu0_44xx_clkdm = { .pwrdm = { .name = "cpu0_pwrdm" }, .prcm_partition = OMAP4430_PRCM_MPU_PARTITION, .cm_inst = OMAP4430_PRCM_MPU_CPU0_INST, - .clkdm_offs = OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS, + .clkdm_offs = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; @@ -160,7 +160,7 @@ static struct clockdomain mpu1_44xx_clkdm = { .pwrdm = { .name = "cpu1_pwrdm" }, .prcm_partition = OMAP4430_PRCM_MPU_PARTITION, .cm_inst = OMAP4430_PRCM_MPU_CPU1_INST, - .clkdm_offs = OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS, + .clkdm_offs = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS, .flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.h b/arch/arm/mach-omap2/prcm_mpu44xx.h index 3300ff6e3cfe..d22d1b43bccd 100644 --- a/arch/arm/mach-omap2/prcm_mpu44xx.h +++ b/arch/arm/mach-omap2/prcm_mpu44xx.h @@ -38,8 +38,8 @@ #define OMAP4430_PRCM_MPU_CPU1_INST 0x0800 /* PRCM_MPU clockdomain register offsets (from instance start) */ -#define OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS 0x0018 -#define OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS 0x0018 +#define OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS 0x0018 +#define OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS 0x0018 /* From 3ed4566ed2146ff8ac1cbaf2babdf04e50b66648 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Fri, 25 Feb 2011 15:21:17 -0700 Subject: [PATCH 20/62] omap4: powerdomain: Use intended PWRSTS_* flags instead of values IVAHD and ABE power domain logic state is populated using directly value instead of the capability flags. Fix the same. Signed-off-by: Santosh Shilimkar [paul@pwsan.com: updated to apply at a different point on the tree] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/powerdomains44xx_data.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c index 26d7641076d7..226e01aac9eb 100644 --- a/arch/arm/mach-omap2/powerdomains44xx_data.c +++ b/arch/arm/mach-omap2/powerdomains44xx_data.c @@ -80,7 +80,7 @@ static struct powerdomain abe_44xx_pwrdm = { .prcm_partition = OMAP4430_PRM_PARTITION, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRDM_POWER_OFF, + .pwrsts_logic_ret = PWRSTS_OFF, .banks = 2, .pwrsts_mem_ret = { [0] = PWRDM_POWER_RET, /* aessmem */ @@ -227,7 +227,7 @@ static struct powerdomain ivahd_44xx_pwrdm = { .prcm_partition = OMAP4430_PRM_PARTITION, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRDM_POWER_OFF, + .pwrsts_logic_ret = PWRSTS_OFF, .banks = 4, .pwrsts_mem_ret = { [0] = PWRDM_POWER_OFF, /* hwa_mem */ From da0653fe01cd4c6ed402a94752b78be62cb39282 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 25 Feb 2011 15:40:21 -0700 Subject: [PATCH 21/62] OMAP2+: omap_device/clock: Do not expect an entry in clkdev for opt_clks The _add_optional_clock_alias function expects an entry already existing in the clkdev table in the form of which might not be the case always. Instead, just check if an entry already exists in clkdev in the form, else go ahead and add one. Remove any assumption of an entry already existing in clkdev table in any form. Since this means, adding a new entry in clkdev if it does not already exist, and not really adding an 'alias', also rename the function name (s/_add_optional_clock_alias/_add_optional_clock_clkdev) to reflect this. Signed-off-by: Rajendra Nayak Reported-by: Sumit Semwal Cc: Sumit Semwal Cc: Paul Walmsley Cc: Benoit Cousson Cc: Kevin Hilman Cc: Partha Basak Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/omap_device.c | 36 +++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index 57adb270767b..9bbda9acb73b 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -83,9 +83,11 @@ #include #include #include +#include #include #include +#include /* These parameters are passed to _omap_device_{de,}activate() */ #define USE_WAKEUP_LAT 0 @@ -239,12 +241,12 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev) } /** - * _add_optional_clock_alias - Add clock alias for hwmod optional clocks + * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks * @od: struct omap_device *od * * For every optional clock present per hwmod per omap_device, this function - * adds an entry in the clocks list of the form - * if an entry is already present in it with the form + * adds an entry in the clkdev table of the form + * if it does not exist already. * * The function is called from inside omap_device_build_ss(), after * omap_device_register. @@ -254,25 +256,39 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev) * * No return value. */ -static void _add_optional_clock_alias(struct omap_device *od, +static void _add_optional_clock_clkdev(struct omap_device *od, struct omap_hwmod *oh) { int i; for (i = 0; i < oh->opt_clks_cnt; i++) { struct omap_hwmod_opt_clk *oc; - int r; + struct clk *r; + struct clk_lookup *l; oc = &oh->opt_clks[i]; if (!oc->_clk) continue; - r = clk_add_alias(oc->role, dev_name(&od->pdev.dev), - (char *)oc->clk, &od->pdev.dev); - if (r) - pr_err("omap_device: %s: clk_add_alias for %s failed\n", + r = clk_get_sys(dev_name(&od->pdev.dev), oc->role); + if (!IS_ERR(r)) + continue; /* clkdev entry exists */ + + r = omap_clk_get_by_name((char *)oc->clk); + if (IS_ERR(r)) { + pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n", + dev_name(&od->pdev.dev), oc->clk); + continue; + } + + l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev)); + if (!l) { + pr_err("omap_device: %s: clkdev_alloc for %s failed\n", dev_name(&od->pdev.dev), oc->role); + return; + } + clkdev_add(l); } } @@ -480,7 +496,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, for (i = 0; i < oh_cnt; i++) { hwmods[i]->od = od; - _add_optional_clock_alias(od, hwmods[i]); + _add_optional_clock_clkdev(od, hwmods[i]); } if (ret) From a05dcdb98011a53d150d699ef8243754e2c9a61c Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 18:22:08 -0700 Subject: [PATCH 22/62] MMC: omap_hsmmc: enable interface clock before calling mmc_host_enable() The code path entered via mmc_host_enable() can include register accesses to the HSMMC IP block. For this to work, both the device interface clock and functional clock need to be enabled before mmc_host_enable() is called. However, omap_hsmmc_probe() calls mmc_host_enable() before enabling the device interface clock. Fix by calling mmc_host_enable() after the device interface clock is enabled. Signed-off-by: Paul Walmsley Cc: Madhusudhan Chikkature Rajashekar Cc: Adrian Hunter Cc: Kishore Kadiyala Cc: Tero Kristo Acked-by: Madhusudhan Chikkature Rajashekar --- drivers/mmc/host/omap_hsmmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 078fdf11af03..0cf0d89e4183 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2101,14 +2101,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) /* we start off in DISABLED state */ host->dpm_state = DISABLED; - if (mmc_host_enable(host->mmc) != 0) { + if (clk_enable(host->iclk) != 0) { clk_put(host->iclk); clk_put(host->fclk); goto err1; } - if (clk_enable(host->iclk) != 0) { - mmc_host_disable(host->mmc); + if (mmc_host_enable(host->mmc) != 0) { + clk_disable(host->iclk); clk_put(host->iclk); clk_put(host->fclk); goto err1; From cad7a34b3afcd02e8e6bef5007e4b12f6cc8ec24 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 7 Mar 2011 19:28:15 -0700 Subject: [PATCH 23/62] OMAP2/3: WKUP powerdomain: mark as being always on Mark the WKUP powerdomain as being always on -- at least, as long as the chip has power. This will be used to enable the powerdomain code to determine whether a given powerdomain is ever able to power off. While here, update the file copyright. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c index 5b4dd971320a..96cda1371e63 100644 --- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c @@ -2,7 +2,7 @@ * OMAP2/3 common powerdomain definitions * * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2010 Nokia Corporation + * Copyright (C) 2007-2011 Nokia Corporation * * Paul Walmsley, Jouni Högander * @@ -76,4 +76,5 @@ struct powerdomain wkup_omap2_pwrdm = { .name = "wkup_pwrdm", .prcm_offs = WKUP_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430), + .pwrsts = PWRSTS_ON, }; From 4cb49fec12e219ec174e04157f71c00f63eb4ce4 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 7 Mar 2011 19:28:15 -0700 Subject: [PATCH 24/62] OMAP2+: powerdomain: fix bank power state bitfields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bank power state bitfields in the powerdomain data are encoded incorrectly. These fields are intended to be bitfields, representing a set of power states that the memory banks support. However, when only one power state was supported by a given bank, the field was incorrectly set to the bit shift -- not the mask. While here, update some file copyrights. The OMAP4 autogeneration scripts have been updated accordingly. Signed-off-by: Paul Walmsley Cc: Benoît Cousson Cc: Rajendra Nayak Cc: Santosh Shilimkar --- .../mach-omap2/powerdomains2xxx_3xxx_data.c | 6 +- arch/arm/mach-omap2/powerdomains2xxx_data.c | 18 ++-- arch/arm/mach-omap2/powerdomains3xxx_data.c | 38 ++++----- arch/arm/mach-omap2/powerdomains44xx_data.c | 84 +++++++++---------- 4 files changed, 73 insertions(+), 73 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c index 96cda1371e63..4210c3399769 100644 --- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c @@ -62,13 +62,13 @@ struct powerdomain gfx_omap2_pwrdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430ES1), .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRDM_POWER_RET, + .pwrsts_logic_ret = PWRSTS_RET, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + [0] = PWRSTS_RET, /* MEMRETSTATE */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + [0] = PWRSTS_ON, /* MEMONSTATE */ }, }; diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c index 9b1a33500577..2bc1b6075e86 100644 --- a/arch/arm/mach-omap2/powerdomains2xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c @@ -2,7 +2,7 @@ * OMAP2XXX powerdomain definitions * * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2010 Nokia Corporation + * Copyright (C) 2007-2011 Nokia Corporation * * Paul Walmsley, Jouni Högander * @@ -30,13 +30,13 @@ static struct powerdomain dsp_pwrdm = { .prcm_offs = OMAP24XX_DSP_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX), .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRDM_POWER_RET, + .pwrsts_logic_ret = PWRSTS_RET, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, + [0] = PWRSTS_RET, }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, + [0] = PWRSTS_ON, }, }; @@ -48,10 +48,10 @@ static struct powerdomain mpu_24xx_pwrdm = { .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, + [0] = PWRSTS_RET, }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, + [0] = PWRSTS_ON, }, }; @@ -87,13 +87,13 @@ static struct powerdomain mdm_pwrdm = { .prcm_offs = OMAP2430_MDM_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRDM_POWER_RET, + .pwrsts_logic_ret = PWRSTS_RET, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + [0] = PWRSTS_RET, /* MEMRETSTATE */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + [0] = PWRSTS_ON, /* MEMONSTATE */ }, }; diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c index e1bec562625b..9c9c113788b9 100644 --- a/arch/arm/mach-omap2/powerdomains3xxx_data.c +++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c @@ -2,7 +2,7 @@ * OMAP3 powerdomain definitions * * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2010 Nokia Corporation + * Copyright (C) 2007-2011 Nokia Corporation * * Paul Walmsley, Jouni Högander * @@ -47,10 +47,10 @@ static struct powerdomain iva2_pwrdm = { [3] = PWRSTS_OFF_RET, }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, - [1] = PWRDM_POWER_ON, + [0] = PWRSTS_ON, + [1] = PWRSTS_ON, [2] = PWRSTS_OFF_ON, - [3] = PWRDM_POWER_ON, + [3] = PWRSTS_ON, }, }; @@ -128,13 +128,13 @@ static struct powerdomain dss_pwrdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), .prcm_offs = OMAP3430_DSS_MOD, .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRDM_POWER_RET, + .pwrsts_logic_ret = PWRSTS_RET, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + [0] = PWRSTS_RET, /* MEMRETSTATE */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + [0] = PWRSTS_ON, /* MEMONSTATE */ }, }; @@ -149,13 +149,13 @@ static struct powerdomain sgx_pwrdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), /* XXX This is accurate for 3430 SGX, but what about GFX? */ .pwrsts = PWRSTS_OFF_ON, - .pwrsts_logic_ret = PWRDM_POWER_RET, + .pwrsts_logic_ret = PWRSTS_RET, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + [0] = PWRSTS_RET, /* MEMRETSTATE */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + [0] = PWRSTS_ON, /* MEMONSTATE */ }, }; @@ -164,13 +164,13 @@ static struct powerdomain cam_pwrdm = { .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), .prcm_offs = OMAP3430_CAM_MOD, .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRDM_POWER_RET, + .pwrsts_logic_ret = PWRSTS_RET, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + [0] = PWRSTS_RET, /* MEMRETSTATE */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + [0] = PWRSTS_ON, /* MEMONSTATE */ }, }; @@ -182,10 +182,10 @@ static struct powerdomain per_pwrdm = { .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + [0] = PWRSTS_RET, /* MEMRETSTATE */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + [0] = PWRSTS_ON, /* MEMONSTATE */ }, }; @@ -200,7 +200,7 @@ static struct powerdomain neon_pwrdm = { .prcm_offs = OMAP3430_NEON_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRDM_POWER_RET, + .pwrsts_logic_ret = PWRSTS_RET, }; static struct powerdomain usbhost_pwrdm = { @@ -208,7 +208,7 @@ static struct powerdomain usbhost_pwrdm = { .prcm_offs = OMAP3430ES2_USBHOST_MOD, .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), .pwrsts = PWRSTS_OFF_RET_ON, - .pwrsts_logic_ret = PWRDM_POWER_RET, + .pwrsts_logic_ret = PWRSTS_RET, /* * REVISIT: Enabling usb host save and restore mechanism seems to * leave the usb host domain permanently in ACTIVE mode after @@ -218,10 +218,10 @@ static struct powerdomain usbhost_pwrdm = { /*.flags = PWRDM_HAS_HDWR_SAR,*/ /* for USBHOST ctrlr only */ .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ + [0] = PWRSTS_RET, /* MEMRETSTATE */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* MEMONSTATE */ + [0] = PWRSTS_ON, /* MEMONSTATE */ }, }; diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c index 226e01aac9eb..c4222c7036a5 100644 --- a/arch/arm/mach-omap2/powerdomains44xx_data.c +++ b/arch/arm/mach-omap2/powerdomains44xx_data.c @@ -2,7 +2,7 @@ * OMAP4 Power domains framework * * Copyright (C) 2009-2010 Texas Instruments, Inc. - * Copyright (C) 2009-2010 Nokia Corporation + * Copyright (C) 2009-2011 Nokia Corporation * * Abhijit Pagare (abhijitpagare@ti.com) * Benoit Cousson (b-cousson@ti.com) @@ -40,18 +40,18 @@ static struct powerdomain core_44xx_pwrdm = { .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 5, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_OFF, /* core_nret_bank */ + [0] = PWRSTS_OFF, /* core_nret_bank */ [1] = PWRSTS_OFF_RET, /* core_ocmram */ - [2] = PWRDM_POWER_RET, /* core_other_bank */ + [2] = PWRSTS_RET, /* core_other_bank */ [3] = PWRSTS_OFF_RET, /* ducati_l2ram */ [4] = PWRSTS_OFF_RET, /* ducati_unicache */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* core_nret_bank */ + [0] = PWRSTS_ON, /* core_nret_bank */ [1] = PWRSTS_OFF_RET, /* core_ocmram */ - [2] = PWRDM_POWER_ON, /* core_other_bank */ - [3] = PWRDM_POWER_ON, /* ducati_l2ram */ - [4] = PWRDM_POWER_ON, /* ducati_unicache */ + [2] = PWRSTS_ON, /* core_other_bank */ + [3] = PWRSTS_ON, /* ducati_l2ram */ + [4] = PWRSTS_ON, /* ducati_unicache */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -65,10 +65,10 @@ static struct powerdomain gfx_44xx_pwrdm = { .pwrsts = PWRSTS_OFF_ON, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_OFF, /* gfx_mem */ + [0] = PWRSTS_OFF, /* gfx_mem */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* gfx_mem */ + [0] = PWRSTS_ON, /* gfx_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -83,12 +83,12 @@ static struct powerdomain abe_44xx_pwrdm = { .pwrsts_logic_ret = PWRSTS_OFF, .banks = 2, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, /* aessmem */ - [1] = PWRDM_POWER_OFF, /* periphmem */ + [0] = PWRSTS_RET, /* aessmem */ + [1] = PWRSTS_OFF, /* periphmem */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* aessmem */ - [1] = PWRDM_POWER_ON, /* periphmem */ + [0] = PWRSTS_ON, /* aessmem */ + [1] = PWRSTS_ON, /* periphmem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -103,10 +103,10 @@ static struct powerdomain dss_44xx_pwrdm = { .pwrsts_logic_ret = PWRSTS_OFF, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_OFF, /* dss_mem */ + [0] = PWRSTS_OFF, /* dss_mem */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* dss_mem */ + [0] = PWRSTS_ON, /* dss_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -121,14 +121,14 @@ static struct powerdomain tesla_44xx_pwrdm = { .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 3, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_RET, /* tesla_edma */ + [0] = PWRSTS_RET, /* tesla_edma */ [1] = PWRSTS_OFF_RET, /* tesla_l1 */ [2] = PWRSTS_OFF_RET, /* tesla_l2 */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* tesla_edma */ - [1] = PWRDM_POWER_ON, /* tesla_l1 */ - [2] = PWRDM_POWER_ON, /* tesla_l2 */ + [0] = PWRSTS_ON, /* tesla_edma */ + [1] = PWRSTS_ON, /* tesla_l1 */ + [2] = PWRSTS_ON, /* tesla_l2 */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -142,10 +142,10 @@ static struct powerdomain wkup_44xx_pwrdm = { .pwrsts = PWRSTS_ON, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_OFF, /* wkup_bank */ + [0] = PWRSTS_OFF, /* wkup_bank */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* wkup_bank */ + [0] = PWRSTS_ON, /* wkup_bank */ }, }; @@ -162,7 +162,7 @@ static struct powerdomain cpu0_44xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* cpu0_l1 */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* cpu0_l1 */ + [0] = PWRSTS_ON, /* cpu0_l1 */ }, }; @@ -179,7 +179,7 @@ static struct powerdomain cpu1_44xx_pwrdm = { [0] = PWRSTS_OFF_RET, /* cpu1_l1 */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* cpu1_l1 */ + [0] = PWRSTS_ON, /* cpu1_l1 */ }, }; @@ -192,10 +192,10 @@ static struct powerdomain emu_44xx_pwrdm = { .pwrsts = PWRSTS_OFF_ON, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_OFF, /* emu_bank */ + [0] = PWRSTS_OFF, /* emu_bank */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* emu_bank */ + [0] = PWRSTS_ON, /* emu_bank */ }, }; @@ -211,12 +211,12 @@ static struct powerdomain mpu_44xx_pwrdm = { .pwrsts_mem_ret = { [0] = PWRSTS_OFF_RET, /* mpu_l1 */ [1] = PWRSTS_OFF_RET, /* mpu_l2 */ - [2] = PWRDM_POWER_RET, /* mpu_ram */ + [2] = PWRSTS_RET, /* mpu_ram */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* mpu_l1 */ - [1] = PWRDM_POWER_ON, /* mpu_l2 */ - [2] = PWRDM_POWER_ON, /* mpu_ram */ + [0] = PWRSTS_ON, /* mpu_l1 */ + [1] = PWRSTS_ON, /* mpu_l2 */ + [2] = PWRSTS_ON, /* mpu_ram */ }, }; @@ -230,16 +230,16 @@ static struct powerdomain ivahd_44xx_pwrdm = { .pwrsts_logic_ret = PWRSTS_OFF, .banks = 4, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_OFF, /* hwa_mem */ + [0] = PWRSTS_OFF, /* hwa_mem */ [1] = PWRSTS_OFF_RET, /* sl2_mem */ [2] = PWRSTS_OFF_RET, /* tcm1_mem */ [3] = PWRSTS_OFF_RET, /* tcm2_mem */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* hwa_mem */ - [1] = PWRDM_POWER_ON, /* sl2_mem */ - [2] = PWRDM_POWER_ON, /* tcm1_mem */ - [3] = PWRDM_POWER_ON, /* tcm2_mem */ + [0] = PWRSTS_ON, /* hwa_mem */ + [1] = PWRSTS_ON, /* sl2_mem */ + [2] = PWRSTS_ON, /* tcm1_mem */ + [3] = PWRSTS_ON, /* tcm2_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -253,10 +253,10 @@ static struct powerdomain cam_44xx_pwrdm = { .pwrsts = PWRSTS_OFF_ON, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_OFF, /* cam_mem */ + [0] = PWRSTS_OFF, /* cam_mem */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* cam_mem */ + [0] = PWRSTS_ON, /* cam_mem */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -271,10 +271,10 @@ static struct powerdomain l3init_44xx_pwrdm = { .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 1, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_OFF, /* l3init_bank1 */ + [0] = PWRSTS_OFF, /* l3init_bank1 */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* l3init_bank1 */ + [0] = PWRSTS_ON, /* l3init_bank1 */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; @@ -289,12 +289,12 @@ static struct powerdomain l4per_44xx_pwrdm = { .pwrsts_logic_ret = PWRSTS_OFF_RET, .banks = 2, .pwrsts_mem_ret = { - [0] = PWRDM_POWER_OFF, /* nonretained_bank */ - [1] = PWRDM_POWER_RET, /* retained_bank */ + [0] = PWRSTS_OFF, /* nonretained_bank */ + [1] = PWRSTS_RET, /* retained_bank */ }, .pwrsts_mem_on = { - [0] = PWRDM_POWER_ON, /* nonretained_bank */ - [1] = PWRDM_POWER_ON, /* retained_bank */ + [0] = PWRSTS_ON, /* nonretained_bank */ + [1] = PWRSTS_ON, /* retained_bank */ }, .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, }; From 694606c4ef54f596bfb2a7c1d4de8ac0e096a636 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Mon, 7 Mar 2011 19:28:15 -0700 Subject: [PATCH 25/62] OMAP2+: powerdomain: add pwrdm_can_ever_lose_context() Some drivers wish to know whether the device that they control can ever lose context, for example, when the device's enclosing powerdomain loses power. They can use this information to determine whether it is necessary to save and restore device context, or whether it can be skipped. Implement the powerdomain portion of this by adding the function pwrdm_can_ever_lose_context(). This is not for use directly from driver code, but instead is intended to be called from driver-subarch integration code (i.e., arch/arm/*omap* code). Currently, the result from this function should be passed into the driver code via struct platform_data, but at some point this should be part of some common or OMAP-specific device code. While here, update file copyrights. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/powerdomain.c | 43 ++++++++++++++++++++++++++++++- arch/arm/mach-omap2/powerdomain.h | 18 ++++++------- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index eaed0df16699..a11be81997c5 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -2,7 +2,7 @@ * OMAP powerdomain control * * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2009 Nokia Corporation + * Copyright (C) 2007-2011 Nokia Corporation * * Written by Paul Walmsley * Added OMAP4 specific support by Abhijit Pagare @@ -938,3 +938,44 @@ u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm) return count; } + +/** + * pwrdm_can_ever_lose_context - can this powerdomain ever lose context? + * @pwrdm: struct powerdomain * + * + * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain + * can lose either memory or logic context or if @pwrdm is invalid, or + * returns 0 otherwise. This function is not concerned with how the + * powerdomain registers are programmed (i.e., to go off or not); it's + * concerned with whether it's ever possible for this powerdomain to + * go off while some other part of the chip is active. This function + * assumes that every powerdomain can go to either ON or INACTIVE. + */ +bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm) +{ + int i; + + if (IS_ERR_OR_NULL(pwrdm)) { + pr_debug("powerdomain: %s: invalid powerdomain pointer\n", + __func__); + return 1; + } + + if (pwrdm->pwrsts & PWRSTS_OFF) + return 1; + + if (pwrdm->pwrsts & PWRSTS_RET) { + if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF) + return 1; + + for (i = 0; i < pwrdm->banks; i++) + if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF) + return 1; + } + + for (i = 0; i < pwrdm->banks; i++) + if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF) + return 1; + + return 0; +} diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index c66431edfeb7..af4f23c73c7a 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -2,7 +2,7 @@ * OMAP2/3/4 powerdomain control * * Copyright (C) 2007-2008, 2010 Texas Instruments, Inc. - * Copyright (C) 2007-2010 Nokia Corporation + * Copyright (C) 2007-2011 Nokia Corporation * * Paul Walmsley * @@ -34,17 +34,14 @@ /* Powerdomain allowable state bitfields */ #define PWRSTS_ON (1 << PWRDM_POWER_ON) +#define PWRSTS_INACTIVE (1 << PWRDM_POWER_INACTIVE) +#define PWRSTS_RET (1 << PWRDM_POWER_RET) #define PWRSTS_OFF (1 << PWRDM_POWER_OFF) -#define PWRSTS_OFF_ON ((1 << PWRDM_POWER_OFF) | \ - (1 << PWRDM_POWER_ON)) -#define PWRSTS_OFF_RET ((1 << PWRDM_POWER_OFF) | \ - (1 << PWRDM_POWER_RET)) - -#define PWRSTS_RET_ON ((1 << PWRDM_POWER_RET) | \ - (1 << PWRDM_POWER_ON)) - -#define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON)) +#define PWRSTS_OFF_ON (PWRSTS_OFF | PWRSTS_ON) +#define PWRSTS_OFF_RET (PWRSTS_OFF | PWRSTS_RET) +#define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON) +#define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | PWRSTS_ON) /* Powerdomain flags */ @@ -212,6 +209,7 @@ int pwrdm_pre_transition(void); int pwrdm_post_transition(void); int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm); +bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); extern void omap2xxx_powerdomains_init(void); extern void omap3xxx_powerdomains_init(void); From 0fd0c21be71293d8a54d9075b18b5a25a1868057 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:49:53 -0700 Subject: [PATCH 26/62] OMAP2: clock: add DPLL autoidle support Add the necessary code and data to allow the clock framework to enable and disable the OMAP2 DPLL autoidle state. This is so the direct register access can be moved out of the mach-omap2/pm24xx.c code, and other code that needs to control this (e.g., CPUIdle) can do so via an API. As part of this patch, remove the pm24xx.c code that formerly wrote directly to the autoidle bits. Signed-off-by: Paul Walmsley Cc: Kevin Hilman Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/Makefile | 3 +- arch/arm/mach-omap2/clkt2xxx_dpll.c | 63 ++++++++++++++++++++++++++++ arch/arm/mach-omap2/clock.h | 1 + arch/arm/mach-omap2/clock2420_data.c | 2 +- arch/arm/mach-omap2/clock2430_data.c | 2 +- arch/arm/mach-omap2/cm2xxx_3xxx.c | 27 ++++++++++++ arch/arm/mach-omap2/cm2xxx_3xxx.h | 3 ++ arch/arm/mach-omap2/pm24xx.c | 12 +++--- 8 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 arch/arm/mach-omap2/clkt2xxx_dpll.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 89274a9f0357..ae44645551c2 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -115,7 +115,8 @@ obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o \ clkt2xxx_sys.o \ clkt2xxx_dpllcore.o \ clkt2xxx_virt_prcm_set.o \ - clkt2xxx_apll.o clkt2xxx_osc.o + clkt2xxx_apll.o clkt2xxx_osc.o \ + clkt2xxx_dpll.o obj-$(CONFIG_SOC_OMAP2420) += clock2420_data.o obj-$(CONFIG_SOC_OMAP2430) += clock2430.o clock2430_data.o obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o \ diff --git a/arch/arm/mach-omap2/clkt2xxx_dpll.c b/arch/arm/mach-omap2/clkt2xxx_dpll.c new file mode 100644 index 000000000000..1502a7bc20bb --- /dev/null +++ b/arch/arm/mach-omap2/clkt2xxx_dpll.c @@ -0,0 +1,63 @@ +/* + * OMAP2-specific DPLL control functions + * + * Copyright (C) 2011 Nokia Corporation + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include + +#include "clock.h" +#include "cm2xxx_3xxx.h" +#include "cm-regbits-24xx.h" + +/* Private functions */ + +/** + * _allow_idle - enable DPLL autoidle bits + * @clk: struct clk * of the DPLL to operate on + * + * Enable DPLL automatic idle control. The DPLL will enter low-power + * stop when its downstream clocks are gated. No return value. + * REVISIT: DPLL can optionally enter low-power bypass by writing 0x1 + * instead. Add some mechanism to optionally enter this mode. + */ +static void _allow_idle(struct clk *clk) +{ + if (!clk || !clk->dpll_data) + return; + + omap2xxx_cm_set_dpll_auto_low_power_stop(); +} + +/** + * _deny_idle - prevent DPLL from automatically idling + * @clk: struct clk * of the DPLL to operate on + * + * Disable DPLL automatic idle control. No return value. + */ +static void _deny_idle(struct clk *clk) +{ + if (!clk || !clk->dpll_data) + return; + + omap2xxx_cm_set_dpll_disable_autoidle(); +} + + +/* Public data */ + +const struct clkops clkops_omap2xxx_dpll_ops = { + .allow_idle = _allow_idle, + .deny_idle = _deny_idle, +}; + diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 0725a6ad8b46..9972d892a4af 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -148,6 +148,7 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) #define omap2_clk_exit_cpufreq_table 0 #endif +extern const struct clkops clkops_omap2xxx_dpll_ops; extern const struct clkops clkops_omap3_noncore_dpll_ops; extern const struct clkops clkops_omap3_core_dpll_ops; extern const struct clkops clkops_omap4_dpllmx_ops; diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index ee73e14ac3c8..30fbcbd0ed81 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -125,7 +125,7 @@ static struct dpll_data dpll_dd = { */ static struct clk dpll_ck = { .name = "dpll_ck", - .ops = &clkops_null, + .ops = &clkops_omap2xxx_dpll_ops, .parent = &sys_ck, /* Can be func_32k also */ .dpll_data = &dpll_dd, .clkdm_name = "wkup_clkdm", diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index a1298e55d915..1ff150a0f304 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -125,7 +125,7 @@ static struct dpll_data dpll_dd = { */ static struct clk dpll_ck = { .name = "dpll_ck", - .ops = &clkops_null, + .ops = &clkops_omap2xxx_dpll_ops, .parent = &sys_ck, /* Can be func_32k also */ .dpll_data = &dpll_dd, .clkdm_name = "wkup_clkdm", diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c index 96954aa48671..6b0c7c85ef53 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c @@ -25,6 +25,10 @@ #include "cm-regbits-24xx.h" #include "cm-regbits-34xx.h" +/* CM_AUTOIDLE_PLL.AUTO_* bit values */ +#define DPLL_AUTOIDLE_DISABLE 0x0 +#define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP 0x3 + static const u8 cm_idlest_offs[] = { CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3 }; @@ -125,6 +129,29 @@ void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask) _write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask); } +/* + * DPLL autoidle control + */ + +static void _omap2xxx_set_dpll_autoidle(u8 m) +{ + u32 v; + + v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE); + v &= ~OMAP24XX_AUTO_DPLL_MASK; + v |= m << OMAP24XX_AUTO_DPLL_SHIFT; + omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE); +} + +void omap2xxx_cm_set_dpll_disable_autoidle(void) +{ + _omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP); +} + +void omap2xxx_cm_set_dpll_auto_low_power_stop(void) +{ + _omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE); +} /* * diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h index 5e9ea5bd60b9..5f4df1ceafad 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h @@ -122,6 +122,9 @@ extern void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask); extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask); extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask); +extern void omap2xxx_cm_set_dpll_disable_autoidle(void); +extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void); + #endif /* CM register bits shared between 24XX and 3430 */ diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index e983c8301f55..297bb21061b8 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -378,6 +378,7 @@ static void __init prcm_setup_regs(void) { int i, num_mem_banks; struct powerdomain *pwrdm; + u32 v; /* Enable autoidle */ omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD, @@ -468,11 +469,12 @@ static void __init prcm_setup_regs(void) omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD, CM_AUTOIDLE); - /* Put DPLL and both APLLs into autoidle mode */ - omap2_cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) | - (0x03 << OMAP24XX_AUTO_96M_SHIFT) | - (0x03 << OMAP24XX_AUTO_54M_SHIFT), - PLL_MOD, CM_AUTOIDLE); + /* Put both APLLs into autoidle mode */ + v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE); + v &= ~(OMAP24XX_AUTO_96M_MASK | OMAP24XX_AUTO_54M_SHIFT); + v |= (0x03 << OMAP24XX_AUTO_96M_SHIFT) | + (0x03 << OMAP24XX_AUTO_54M_SHIFT); + omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE); omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK | OMAP24XX_AUTO_WDT1_MASK | From 92618ff8b025419960e2e845983f0f49b0cb57a9 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:39:27 -0700 Subject: [PATCH 27/62] OMAP2xxx: clock: add clockfw autoidle support for APLLs OMAP2xxx devices have two on-chip APLLs. These APLLs can automatically enter idle when not in use. Connect the APLL autoidle code to the clock code, so that the clock framework can handle this process. As part of this patch, remove the code in mach-omap2/pm24xx.c that previously handled APLL autoidle control. Signed-off-by: Paul Walmsley Cc: Kevin Hilman Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/clkt2xxx_apll.c | 24 ++++++++++++++++ arch/arm/mach-omap2/cm2xxx_3xxx.c | 44 ++++++++++++++++++++++++++++- arch/arm/mach-omap2/cm2xxx_3xxx.h | 5 ++++ arch/arm/mach-omap2/pm24xx.c | 8 ------ 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c index f51cffd1fc53..b19a1f7234ae 100644 --- a/arch/arm/mach-omap2/clkt2xxx_apll.c +++ b/arch/arm/mach-omap2/clkt2xxx_apll.c @@ -78,6 +78,26 @@ static int omap2_clk_apll54_enable(struct clk *clk) return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL_MASK); } +static void _apll96_allow_idle(struct clk *clk) +{ + omap2xxx_cm_set_apll96_auto_low_power_stop(); +} + +static void _apll96_deny_idle(struct clk *clk) +{ + omap2xxx_cm_set_apll96_disable_autoidle(); +} + +static void _apll54_allow_idle(struct clk *clk) +{ + omap2xxx_cm_set_apll54_auto_low_power_stop(); +} + +static void _apll54_deny_idle(struct clk *clk) +{ + omap2xxx_cm_set_apll54_disable_autoidle(); +} + /* Stop APLL */ static void omap2_clk_apll_disable(struct clk *clk) { @@ -93,11 +113,15 @@ static void omap2_clk_apll_disable(struct clk *clk) const struct clkops clkops_apll96 = { .enable = omap2_clk_apll96_enable, .disable = omap2_clk_apll_disable, + .allow_idle = _apll96_allow_idle, + .deny_idle = _apll96_deny_idle, }; const struct clkops clkops_apll54 = { .enable = omap2_clk_apll54_enable, .disable = omap2_clk_apll_disable, + .allow_idle = _apll54_allow_idle, + .deny_idle = _apll54_deny_idle, }; /* Public functions */ diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c index 6b0c7c85ef53..9d0dec806e92 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c @@ -25,10 +25,14 @@ #include "cm-regbits-24xx.h" #include "cm-regbits-34xx.h" -/* CM_AUTOIDLE_PLL.AUTO_* bit values */ +/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */ #define DPLL_AUTOIDLE_DISABLE 0x0 #define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP 0x3 +/* CM_AUTOIDLE_PLL.AUTO_* bit values for APLLs (OMAP2xxx only) */ +#define OMAP2XXX_APLL_AUTOIDLE_DISABLE 0x0 +#define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP 0x3 + static const u8 cm_idlest_offs[] = { CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3 }; @@ -153,6 +157,44 @@ void omap2xxx_cm_set_dpll_auto_low_power_stop(void) _omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE); } +/* + * APLL autoidle control + */ + +static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask) +{ + u32 v; + + v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE); + v &= ~mask; + v |= m << __ffs(mask); + omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE); +} + +void omap2xxx_cm_set_apll54_disable_autoidle(void) +{ + _omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP, + OMAP24XX_AUTO_54M_MASK); +} + +void omap2xxx_cm_set_apll54_auto_low_power_stop(void) +{ + _omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE, + OMAP24XX_AUTO_54M_MASK); +} + +void omap2xxx_cm_set_apll96_disable_autoidle(void) +{ + _omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP, + OMAP24XX_AUTO_96M_MASK); +} + +void omap2xxx_cm_set_apll96_auto_low_power_stop(void) +{ + _omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE, + OMAP24XX_AUTO_96M_MASK); +} + /* * */ diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h index 5f4df1ceafad..088bbad73db5 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h @@ -125,6 +125,11 @@ extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask); extern void omap2xxx_cm_set_dpll_disable_autoidle(void); extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void); +extern void omap2xxx_cm_set_apll54_disable_autoidle(void); +extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void); +extern void omap2xxx_cm_set_apll96_disable_autoidle(void); +extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void); + #endif /* CM register bits shared between 24XX and 3430 */ diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 297bb21061b8..abe08f49b2ec 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -378,7 +378,6 @@ static void __init prcm_setup_regs(void) { int i, num_mem_banks; struct powerdomain *pwrdm; - u32 v; /* Enable autoidle */ omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD, @@ -469,13 +468,6 @@ static void __init prcm_setup_regs(void) omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD, CM_AUTOIDLE); - /* Put both APLLs into autoidle mode */ - v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE); - v &= ~(OMAP24XX_AUTO_96M_MASK | OMAP24XX_AUTO_54M_SHIFT); - v |= (0x03 << OMAP24XX_AUTO_96M_SHIFT) | - (0x03 << OMAP24XX_AUTO_54M_SHIFT); - omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE); - omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK | OMAP24XX_AUTO_WDT1_MASK | OMAP24XX_AUTO_MPU_WDT_MASK | From cc1d230cfbc1622be4bf16568f468054be8c5d2e Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:39:27 -0700 Subject: [PATCH 28/62] OMAP2+: clock: comment that osc_ck/osc_sys_ck should use clockfw autoidle control Place some comments in the OMAP oscillator clock control code to note that its autoidle mode should eventually be controlled via the new OMAP clockfw autoidle control interface. Signed-off-by: Paul Walmsley Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/clkt2xxx_osc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/mach-omap2/clkt2xxx_osc.c b/arch/arm/mach-omap2/clkt2xxx_osc.c index df7b80506483..c3460928b5e0 100644 --- a/arch/arm/mach-omap2/clkt2xxx_osc.c +++ b/arch/arm/mach-omap2/clkt2xxx_osc.c @@ -30,6 +30,13 @@ #include "prm2xxx_3xxx.h" #include "prm-regbits-24xx.h" +/* + * XXX This does not actually enable the osc_ck, since the osc_ck must + * be running for this function to be called. Instead, this function + * is used to disable an autoidle mode on the osc_ck. The existing + * clk_enable/clk_disable()-based usecounting for osc_ck should be + * replaced with autoidle-based usecounting. + */ static int omap2_enable_osc_ck(struct clk *clk) { u32 pcc; @@ -41,6 +48,13 @@ static int omap2_enable_osc_ck(struct clk *clk) return 0; } +/* + * XXX This does not actually disable the osc_ck, since doing so would + * immediately halt the system. Instead, this function is used to + * enable an autoidle mode on the osc_ck. The existing + * clk_enable/clk_disable()-based usecounting for osc_ck should be + * replaced with autoidle-based usecounting. + */ static void omap2_disable_osc_ck(struct clk *clk) { u32 pcc; From 530e544fdadb934470c5c2b0e8d60c3d5386c161 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:39:28 -0700 Subject: [PATCH 29/62] OMAP2+: clock: add interface clock type code with autoidle support Add interface clock type code with autoidle enable/disable support. The clkops structures created in this file will be used for all OMAP2/3 interface clocks with autoidle support. They will enable the clock framework to control interface clock autoidle directly. Signed-off-by: Paul Walmsley Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/Makefile | 6 ++- arch/arm/mach-omap2/clkt_iclk.c | 73 +++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/clock.h | 9 +++- 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-omap2/clkt_iclk.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index ae44645551c2..c5b1be9b7328 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -110,19 +110,21 @@ obj-$(CONFIG_ARCH_OMAP3) += clockdomain.o \ obj-$(CONFIG_ARCH_OMAP4) += clockdomain.o \ clockdomain44xx.o \ clockdomains44xx_data.o + # Clock framework obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o \ clkt2xxx_sys.o \ clkt2xxx_dpllcore.o \ clkt2xxx_virt_prcm_set.o \ clkt2xxx_apll.o clkt2xxx_osc.o \ - clkt2xxx_dpll.o + clkt2xxx_dpll.o clkt_iclk.o obj-$(CONFIG_SOC_OMAP2420) += clock2420_data.o obj-$(CONFIG_SOC_OMAP2430) += clock2430.o clock2430_data.o obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o \ clock34xx.o clkt34xx_dpll3m2.o \ clock3517.o clock36xx.o \ - dpll3xxx.o clock3xxx_data.o + dpll3xxx.o clock3xxx_data.o \ + clkt_iclk.o obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) clock44xx_data.o \ dpll3xxx.o dpll44xx.o diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c new file mode 100644 index 000000000000..dd8a6d3dc011 --- /dev/null +++ b/arch/arm/mach-omap2/clkt_iclk.c @@ -0,0 +1,73 @@ +/* + * OMAP2/3 interface clock control + * + * Copyright (C) 2011 Nokia Corporation + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#undef DEBUG + +#include +#include +#include + +#include +#include + +#include "clock.h" +#include "clock2xxx.h" +#include "cm2xxx_3xxx.h" +#include "cm-regbits-24xx.h" + +/* Private functions */ + +/* XXX */ +void omap2_clkt_iclk_allow_idle(struct clk *clk) +{ + u32 v, r; + + r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN)); + + v = __raw_readl((__force void __iomem *)r); + v |= (1 << clk->enable_bit); + __raw_writel(v, (__force void __iomem *)r); +} + +/* XXX */ +void omap2_clkt_iclk_deny_idle(struct clk *clk) +{ + u32 v, r; + + r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN)); + + v = __raw_readl((__force void __iomem *)r); + v &= ~(1 << clk->enable_bit); + __raw_writel(v, (__force void __iomem *)r); +} + +/* Public data */ + +const struct clkops clkops_omap2_iclk_dflt_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_companion = omap2_clk_dflt_find_companion, + .find_idlest = omap2_clk_dflt_find_idlest, + .allow_idle = omap2_clkt_iclk_allow_idle, + .deny_idle = omap2_clkt_iclk_deny_idle, +}; + +const struct clkops clkops_omap2_iclk_dflt = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .allow_idle = omap2_clkt_iclk_allow_idle, + .deny_idle = omap2_clkt_iclk_deny_idle, +}; + +const struct clkops clkops_omap2_iclk_idle_only = { + .allow_idle = omap2_clkt_iclk_allow_idle, + .deny_idle = omap2_clkt_iclk_deny_idle, +}; + diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 9972d892a4af..5008f14448ef 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -2,7 +2,7 @@ * linux/arch/arm/mach-omap2/clock.h * * Copyright (C) 2005-2009 Texas Instruments, Inc. - * Copyright (C) 2004-2009 Nokia Corporation + * Copyright (C) 2004-2011 Nokia Corporation * * Contacts: * Richard Woodruff @@ -86,6 +86,10 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate); int omap2_clksel_set_rate(struct clk *clk, unsigned long rate); int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent); +/* clkt_iclk.c public functions */ +extern void omap2_clkt_iclk_allow_idle(struct clk *clk); +extern void omap2_clkt_iclk_deny_idle(struct clk *clk); + u32 omap2_get_dpll_rate(struct clk *clk); void omap2_init_dpll_parent(struct clk *clk); @@ -148,6 +152,9 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) #define omap2_clk_exit_cpufreq_table 0 #endif +extern const struct clkops clkops_omap2_iclk_dflt_wait; +extern const struct clkops clkops_omap2_iclk_dflt; +extern const struct clkops clkops_omap2_iclk_idle_only; extern const struct clkops clkops_omap2xxx_dpll_ops; extern const struct clkops clkops_omap3_noncore_dpll_ops; extern const struct clkops clkops_omap3_core_dpll_ops; From a56d9ea865e42a6bf6393fc3d3a143553dbf68c5 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:39:29 -0700 Subject: [PATCH 30/62] OMAP2420: clock: add sdrc_ick Add sdrc_ick to the OMAP2420 clock data so the clock code can control the CM_AUTOIDLE bit associated with this clock. Signed-off-by: Paul Walmsley Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/clock2420_data.c | 16 ++++++++++++++++ arch/arm/mach-omap2/cm-regbits-24xx.h | 1 + 2 files changed, 17 insertions(+) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 30fbcbd0ed81..63ed4816b920 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1608,6 +1608,21 @@ static struct clk sdma_ick = { .recalc = &followparent_recalc, }; +/* + * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE + * accesses derived from this data. + */ +static struct clk sdrc_ick = { + .name = "sdrc_ick", + .ops = &clkops_omap2_iclk_idle_only, + .parent = &core_l3_ck, + .flags = ENABLE_ON_INIT, + .clkdm_name = "core_l3_clkdm", + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), + .enable_bit = OMAP24XX_AUTO_SDRC_SHIFT, + .recalc = &followparent_recalc, +}; + static struct clk vlynq_ick = { .name = "vlynq_ick", .ops = &clkops_omap2_dflt_wait, @@ -1869,6 +1884,7 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "gpmc_fck", &gpmc_fck, CK_242X), CLK(NULL, "sdma_fck", &sdma_fck, CK_242X), CLK(NULL, "sdma_ick", &sdma_ick, CK_242X), + CLK(NULL, "sdrc_ick", &sdrc_ick, CK_242X), CLK(NULL, "vlynq_ick", &vlynq_ick, CK_242X), CLK(NULL, "vlynq_fck", &vlynq_fck, CK_242X), CLK(NULL, "des_ick", &des_ick, CK_242X), diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h index d70660e82fe6..409c813eb2e2 100644 --- a/arch/arm/mach-omap2/cm-regbits-24xx.h +++ b/arch/arm/mach-omap2/cm-regbits-24xx.h @@ -210,6 +210,7 @@ #define OMAP24XX_AUTO_USB_MASK (1 << 0) /* CM_AUTOIDLE3_CORE */ +#define OMAP24XX_AUTO_SDRC_SHIFT 2 #define OMAP24XX_AUTO_SDRC_MASK (1 << 2) #define OMAP24XX_AUTO_GPMC_MASK (1 << 1) #define OMAP24XX_AUTO_SDMA_MASK (1 << 0) From 6ae690da1b6315f34ab7312bd2a02d49a606ccf7 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:39:29 -0700 Subject: [PATCH 31/62] OMAP2420: clock: use autoidle clkops for all autoidle-controllable interface clocks Mark each interface clock with a corresponding CM_AUTOIDLE bit with a clkops that has the allow_idle/deny_idle function pointers populated. This allows the OMAP clock framework to enable and disable autoidle for these clocks. Signed-off-by: Paul Walmsley Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/clock2420_data.c | 109 ++++++++++++++------------ arch/arm/mach-omap2/cm-regbits-24xx.h | 2 + 2 files changed, 63 insertions(+), 48 deletions(-) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 63ed4816b920..68c03691e56a 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -2,7 +2,7 @@ * linux/arch/arm/mach-omap2/clock2420_data.c * * Copyright (C) 2005-2009 Texas Instruments, Inc. - * Copyright (C) 2004-2010 Nokia Corporation + * Copyright (C) 2004-2011 Nokia Corporation * * Contacts: * Richard Woodruff @@ -481,7 +481,7 @@ static struct clk dsp_irate_ick = { /* 2420 only */ static struct clk dsp_ick = { .name = "dsp_ick", /* apparently ipi and isp */ - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &dsp_irate_ick, .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN), .enable_bit = OMAP2420_EN_DSP_IPI_SHIFT, /* for ipi */ @@ -579,7 +579,7 @@ static const struct clksel usb_l4_ick_clksel[] = { /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */ static struct clk usb_l4_ick = { /* FS-USB interface clock */ .name = "usb_l4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l3_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -661,7 +661,7 @@ static struct clk ssi_ssr_sst_fck = { */ static struct clk ssi_l4_ick = { .name = "ssi_l4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -716,6 +716,7 @@ static struct clk gfx_2d_fck = { .recalc = &omap2_clksel_recalc, }; +/* This interface clock does not have a CM_AUTOIDLE bit */ static struct clk gfx_ick = { .name = "gfx_ick", /* From l3 */ .ops = &clkops_omap2_dflt_wait, @@ -763,7 +764,7 @@ static const struct clksel dss1_fck_clksel[] = { static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */ .name = "dss_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap2_iclk_dflt, .parent = &l4_ck, /* really both l3 and l4 */ .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -845,7 +846,7 @@ static const struct clksel omap24xx_gpt_clksel[] = { static struct clk gpt1_ick = { .name = "gpt1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), @@ -871,7 +872,7 @@ static struct clk gpt1_fck = { static struct clk gpt2_ick = { .name = "gpt2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -895,7 +896,7 @@ static struct clk gpt2_fck = { static struct clk gpt3_ick = { .name = "gpt3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -919,7 +920,7 @@ static struct clk gpt3_fck = { static struct clk gpt4_ick = { .name = "gpt4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -943,7 +944,7 @@ static struct clk gpt4_fck = { static struct clk gpt5_ick = { .name = "gpt5_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -967,7 +968,7 @@ static struct clk gpt5_fck = { static struct clk gpt6_ick = { .name = "gpt6_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -991,7 +992,7 @@ static struct clk gpt6_fck = { static struct clk gpt7_ick = { .name = "gpt7_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT7_SHIFT, @@ -1014,7 +1015,7 @@ static struct clk gpt7_fck = { static struct clk gpt8_ick = { .name = "gpt8_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1038,7 +1039,7 @@ static struct clk gpt8_fck = { static struct clk gpt9_ick = { .name = "gpt9_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1062,7 +1063,7 @@ static struct clk gpt9_fck = { static struct clk gpt10_ick = { .name = "gpt10_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1086,7 +1087,7 @@ static struct clk gpt10_fck = { static struct clk gpt11_ick = { .name = "gpt11_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1110,7 +1111,7 @@ static struct clk gpt11_fck = { static struct clk gpt12_ick = { .name = "gpt12_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1134,7 +1135,7 @@ static struct clk gpt12_fck = { static struct clk mcbsp1_ick = { .name = "mcbsp1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1174,7 +1175,7 @@ static struct clk mcbsp1_fck = { static struct clk mcbsp2_ick = { .name = "mcbsp2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1198,7 +1199,7 @@ static struct clk mcbsp2_fck = { static struct clk mcspi1_ick = { .name = "mcspi1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1218,7 +1219,7 @@ static struct clk mcspi1_fck = { static struct clk mcspi2_ick = { .name = "mcspi2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1238,7 +1239,7 @@ static struct clk mcspi2_fck = { static struct clk uart1_ick = { .name = "uart1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1258,7 +1259,7 @@ static struct clk uart1_fck = { static struct clk uart2_ick = { .name = "uart2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1278,7 +1279,7 @@ static struct clk uart2_fck = { static struct clk uart3_ick = { .name = "uart3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1298,7 +1299,7 @@ static struct clk uart3_fck = { static struct clk gpios_ick = { .name = "gpios_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), @@ -1318,7 +1319,7 @@ static struct clk gpios_fck = { static struct clk mpu_wdt_ick = { .name = "mpu_wdt_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), @@ -1338,7 +1339,7 @@ static struct clk mpu_wdt_fck = { static struct clk sync_32k_ick = { .name = "sync_32k_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .flags = ENABLE_ON_INIT, .clkdm_name = "core_l4_clkdm", @@ -1349,7 +1350,7 @@ static struct clk sync_32k_ick = { static struct clk wdt1_ick = { .name = "wdt1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), @@ -1359,7 +1360,7 @@ static struct clk wdt1_ick = { static struct clk omapctrl_ick = { .name = "omapctrl_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .flags = ENABLE_ON_INIT, .clkdm_name = "core_l4_clkdm", @@ -1370,7 +1371,7 @@ static struct clk omapctrl_ick = { static struct clk cam_ick = { .name = "cam_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap2_iclk_dflt, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1395,7 +1396,7 @@ static struct clk cam_fck = { static struct clk mailboxes_ick = { .name = "mailboxes_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1405,7 +1406,7 @@ static struct clk mailboxes_ick = { static struct clk wdt4_ick = { .name = "wdt4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1425,7 +1426,7 @@ static struct clk wdt4_fck = { static struct clk wdt3_ick = { .name = "wdt3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1445,7 +1446,7 @@ static struct clk wdt3_fck = { static struct clk mspro_ick = { .name = "mspro_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1465,7 +1466,7 @@ static struct clk mspro_fck = { static struct clk mmc_ick = { .name = "mmc_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1485,7 +1486,7 @@ static struct clk mmc_fck = { static struct clk fac_ick = { .name = "fac_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1505,7 +1506,7 @@ static struct clk fac_fck = { static struct clk eac_ick = { .name = "eac_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1525,7 +1526,7 @@ static struct clk eac_fck = { static struct clk hdq_ick = { .name = "hdq_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1545,7 +1546,7 @@ static struct clk hdq_fck = { static struct clk i2c2_ick = { .name = "i2c2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1565,7 +1566,7 @@ static struct clk i2c2_fck = { static struct clk i2c1_ick = { .name = "i2c1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1583,12 +1584,18 @@ static struct clk i2c1_fck = { .recalc = &followparent_recalc, }; +/* + * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE + * accesses derived from this data. + */ static struct clk gpmc_fck = { .name = "gpmc_fck", - .ops = &clkops_null, /* RMK: missing? */ + .ops = &clkops_omap2_iclk_idle_only, .parent = &core_l3_ck, .flags = ENABLE_ON_INIT, .clkdm_name = "core_l3_clkdm", + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), + .enable_bit = OMAP24XX_AUTO_GPMC_SHIFT, .recalc = &followparent_recalc, }; @@ -1600,11 +1607,17 @@ static struct clk sdma_fck = { .recalc = &followparent_recalc, }; +/* + * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE + * accesses derived from this data. + */ static struct clk sdma_ick = { .name = "sdma_ick", - .ops = &clkops_null, /* RMK: missing? */ + .ops = &clkops_omap2_iclk_idle_only, .parent = &l4_ck, .clkdm_name = "core_l3_clkdm", + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), + .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT, .recalc = &followparent_recalc, }; @@ -1625,7 +1638,7 @@ static struct clk sdrc_ick = { static struct clk vlynq_ick = { .name = "vlynq_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l3_ck, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1674,7 +1687,7 @@ static struct clk vlynq_fck = { static struct clk des_ick = { .name = "des_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), @@ -1684,7 +1697,7 @@ static struct clk des_ick = { static struct clk sha_ick = { .name = "sha_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), @@ -1694,7 +1707,7 @@ static struct clk sha_ick = { static struct clk rng_ick = { .name = "rng_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), @@ -1704,7 +1717,7 @@ static struct clk rng_ick = { static struct clk aes_ick = { .name = "aes_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), @@ -1714,7 +1727,7 @@ static struct clk aes_ick = { static struct clk pka_ick = { .name = "pka_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h index 409c813eb2e2..686290437568 100644 --- a/arch/arm/mach-omap2/cm-regbits-24xx.h +++ b/arch/arm/mach-omap2/cm-regbits-24xx.h @@ -212,7 +212,9 @@ /* CM_AUTOIDLE3_CORE */ #define OMAP24XX_AUTO_SDRC_SHIFT 2 #define OMAP24XX_AUTO_SDRC_MASK (1 << 2) +#define OMAP24XX_AUTO_GPMC_SHIFT 1 #define OMAP24XX_AUTO_GPMC_MASK (1 << 1) +#define OMAP24XX_AUTO_SDMA_SHIFT 0 #define OMAP24XX_AUTO_SDMA_MASK (1 << 0) /* CM_AUTOIDLE4_CORE */ From e892b2528b8dc9eef8ca3f9af7b5b650b4e90bea Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:39:29 -0700 Subject: [PATCH 32/62] OMAP2430/3xxx: clock: add modem clock autoidle support OMAP2430 and OMAP3xxx have modem autoidle bits that are actually attached to clocks with CM_FCLKEN bits; add the code and data to handle these. Signed-off-by: Paul Walmsley Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/clkt_iclk.c | 9 +++++++++ arch/arm/mach-omap2/clock.h | 1 + 2 files changed, 10 insertions(+) diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c index dd8a6d3dc011..3d43fba2542f 100644 --- a/arch/arm/mach-omap2/clkt_iclk.c +++ b/arch/arm/mach-omap2/clkt_iclk.c @@ -71,3 +71,12 @@ const struct clkops clkops_omap2_iclk_idle_only = { .deny_idle = omap2_clkt_iclk_deny_idle, }; +const struct clkops clkops_omap2_mdmclk_dflt_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_companion = omap2_clk_dflt_find_companion, + .find_idlest = omap2_clk_dflt_find_idlest, + .allow_idle = omap2_clkt_iclk_allow_idle, + .deny_idle = omap2_clkt_iclk_deny_idle, +}; + diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 5008f14448ef..70f8b073e69f 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -155,6 +155,7 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) extern const struct clkops clkops_omap2_iclk_dflt_wait; extern const struct clkops clkops_omap2_iclk_dflt; extern const struct clkops clkops_omap2_iclk_idle_only; +extern const struct clkops clkops_omap2_mdmclk_dflt_wait; extern const struct clkops clkops_omap2xxx_dpll_ops; extern const struct clkops clkops_omap3_noncore_dpll_ops; extern const struct clkops clkops_omap3_core_dpll_ops; From a1d5562315a1e911c8448b7fac33c966f9cb6294 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:39:30 -0700 Subject: [PATCH 33/62] OMAP2430: clock: use autoidle clkops for all autoidle-controllable interface clocks Mark each interface clock with a corresponding CM_AUTOIDLE bit with a clkops that has the allow_idle/deny_idle function pointers populated. This allows the OMAP clock framework to enable and disable autoidle for these clocks. Signed-off-by: Paul Walmsley Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/clock2430_data.c | 125 +++++++++++++++------------ 1 file changed, 69 insertions(+), 56 deletions(-) diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 1ff150a0f304..34daed9cd56f 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -2,7 +2,7 @@ * linux/arch/arm/mach-omap2/clock2430_data.c * * Copyright (C) 2005-2009 Texas Instruments, Inc. - * Copyright (C) 2004-2010 Nokia Corporation + * Copyright (C) 2004-2011 Nokia Corporation * * Contacts: * Richard Woodruff @@ -525,7 +525,7 @@ static const struct clksel usb_l4_ick_clksel[] = { /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */ static struct clk usb_l4_ick = { /* FS-USB interface clock */ .name = "usb_l4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l3_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -606,7 +606,7 @@ static struct clk ssi_ssr_sst_fck = { */ static struct clk ssi_l4_ick = { .name = "ssi_l4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -661,6 +661,7 @@ static struct clk gfx_2d_fck = { .recalc = &omap2_clksel_recalc, }; +/* This interface clock does not have a CM_AUTOIDLE bit */ static struct clk gfx_ick = { .name = "gfx_ick", /* From l3 */ .ops = &clkops_omap2_dflt_wait, @@ -693,7 +694,7 @@ static const struct clksel mdm_ick_clksel[] = { static struct clk mdm_ick = { /* used both as a ick and fck */ .name = "mdm_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_ck, .clkdm_name = "mdm_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN), @@ -706,7 +707,7 @@ static struct clk mdm_ick = { /* used both as a ick and fck */ static struct clk mdm_osc_ck = { .name = "mdm_osc_ck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_mdmclk_dflt_wait, .parent = &osc_ck, .clkdm_name = "mdm_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN), @@ -751,7 +752,7 @@ static const struct clksel dss1_fck_clksel[] = { static struct clk dss_ick = { /* Enables both L3,L4 ICLK's */ .name = "dss_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap2_iclk_dflt, .parent = &l4_ck, /* really both l3 and l4 */ .clkdm_name = "dss_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -833,7 +834,7 @@ static const struct clksel omap24xx_gpt_clksel[] = { static struct clk gpt1_ick = { .name = "gpt1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), @@ -859,7 +860,7 @@ static struct clk gpt1_fck = { static struct clk gpt2_ick = { .name = "gpt2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -883,7 +884,7 @@ static struct clk gpt2_fck = { static struct clk gpt3_ick = { .name = "gpt3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -907,7 +908,7 @@ static struct clk gpt3_fck = { static struct clk gpt4_ick = { .name = "gpt4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -931,7 +932,7 @@ static struct clk gpt4_fck = { static struct clk gpt5_ick = { .name = "gpt5_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -955,7 +956,7 @@ static struct clk gpt5_fck = { static struct clk gpt6_ick = { .name = "gpt6_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -979,7 +980,7 @@ static struct clk gpt6_fck = { static struct clk gpt7_ick = { .name = "gpt7_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT7_SHIFT, @@ -1002,7 +1003,7 @@ static struct clk gpt7_fck = { static struct clk gpt8_ick = { .name = "gpt8_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1026,7 +1027,7 @@ static struct clk gpt8_fck = { static struct clk gpt9_ick = { .name = "gpt9_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1050,7 +1051,7 @@ static struct clk gpt9_fck = { static struct clk gpt10_ick = { .name = "gpt10_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1074,7 +1075,7 @@ static struct clk gpt10_fck = { static struct clk gpt11_ick = { .name = "gpt11_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1098,7 +1099,7 @@ static struct clk gpt11_fck = { static struct clk gpt12_ick = { .name = "gpt12_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1122,7 +1123,7 @@ static struct clk gpt12_fck = { static struct clk mcbsp1_ick = { .name = "mcbsp1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1162,7 +1163,7 @@ static struct clk mcbsp1_fck = { static struct clk mcbsp2_ick = { .name = "mcbsp2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1186,7 +1187,7 @@ static struct clk mcbsp2_fck = { static struct clk mcbsp3_ick = { .name = "mcbsp3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1210,7 +1211,7 @@ static struct clk mcbsp3_fck = { static struct clk mcbsp4_ick = { .name = "mcbsp4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1234,7 +1235,7 @@ static struct clk mcbsp4_fck = { static struct clk mcbsp5_ick = { .name = "mcbsp5_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1258,7 +1259,7 @@ static struct clk mcbsp5_fck = { static struct clk mcspi1_ick = { .name = "mcspi1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1278,7 +1279,7 @@ static struct clk mcspi1_fck = { static struct clk mcspi2_ick = { .name = "mcspi2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1298,7 +1299,7 @@ static struct clk mcspi2_fck = { static struct clk mcspi3_ick = { .name = "mcspi3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1318,7 +1319,7 @@ static struct clk mcspi3_fck = { static struct clk uart1_ick = { .name = "uart1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1338,7 +1339,7 @@ static struct clk uart1_fck = { static struct clk uart2_ick = { .name = "uart2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1358,7 +1359,7 @@ static struct clk uart2_fck = { static struct clk uart3_ick = { .name = "uart3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1378,7 +1379,7 @@ static struct clk uart3_fck = { static struct clk gpios_ick = { .name = "gpios_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), @@ -1398,7 +1399,7 @@ static struct clk gpios_fck = { static struct clk mpu_wdt_ick = { .name = "mpu_wdt_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), @@ -1418,7 +1419,7 @@ static struct clk mpu_wdt_fck = { static struct clk sync_32k_ick = { .name = "sync_32k_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .flags = ENABLE_ON_INIT, .clkdm_name = "core_l4_clkdm", @@ -1429,7 +1430,7 @@ static struct clk sync_32k_ick = { static struct clk wdt1_ick = { .name = "wdt1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), @@ -1439,7 +1440,7 @@ static struct clk wdt1_ick = { static struct clk omapctrl_ick = { .name = "omapctrl_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .flags = ENABLE_ON_INIT, .clkdm_name = "core_l4_clkdm", @@ -1450,7 +1451,7 @@ static struct clk omapctrl_ick = { static struct clk icr_ick = { .name = "icr_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), @@ -1460,7 +1461,7 @@ static struct clk icr_ick = { static struct clk cam_ick = { .name = "cam_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap2_iclk_dflt, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1485,7 +1486,7 @@ static struct clk cam_fck = { static struct clk mailboxes_ick = { .name = "mailboxes_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1495,7 +1496,7 @@ static struct clk mailboxes_ick = { static struct clk wdt4_ick = { .name = "wdt4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1515,7 +1516,7 @@ static struct clk wdt4_fck = { static struct clk mspro_ick = { .name = "mspro_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1535,7 +1536,7 @@ static struct clk mspro_fck = { static struct clk fac_ick = { .name = "fac_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1555,7 +1556,7 @@ static struct clk fac_fck = { static struct clk hdq_ick = { .name = "hdq_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1579,7 +1580,7 @@ static struct clk hdq_fck = { */ static struct clk i2c2_ick = { .name = "i2c2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1603,7 +1604,7 @@ static struct clk i2chs2_fck = { */ static struct clk i2c1_ick = { .name = "i2c1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -1621,12 +1622,18 @@ static struct clk i2chs1_fck = { .recalc = &followparent_recalc, }; +/* + * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE + * accesses derived from this data. + */ static struct clk gpmc_fck = { .name = "gpmc_fck", - .ops = &clkops_null, /* RMK: missing? */ + .ops = &clkops_omap2_iclk_idle_only, .parent = &core_l3_ck, .flags = ENABLE_ON_INIT, .clkdm_name = "core_l3_clkdm", + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), + .enable_bit = OMAP24XX_AUTO_GPMC_SHIFT, .recalc = &followparent_recalc, }; @@ -1638,17 +1645,23 @@ static struct clk sdma_fck = { .recalc = &followparent_recalc, }; +/* + * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE + * accesses derived from this data. + */ static struct clk sdma_ick = { .name = "sdma_ick", - .ops = &clkops_null, /* RMK: missing? */ + .ops = &clkops_omap2_iclk_idle_only, .parent = &l4_ck, .clkdm_name = "core_l3_clkdm", + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), + .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT, .recalc = &followparent_recalc, }; static struct clk sdrc_ick = { .name = "sdrc_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_idle_only, .parent = &l4_ck, .flags = ENABLE_ON_INIT, .clkdm_name = "core_l4_clkdm", @@ -1659,7 +1672,7 @@ static struct clk sdrc_ick = { static struct clk des_ick = { .name = "des_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), @@ -1669,7 +1682,7 @@ static struct clk des_ick = { static struct clk sha_ick = { .name = "sha_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), @@ -1679,7 +1692,7 @@ static struct clk sha_ick = { static struct clk rng_ick = { .name = "rng_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), @@ -1689,7 +1702,7 @@ static struct clk rng_ick = { static struct clk aes_ick = { .name = "aes_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), @@ -1699,7 +1712,7 @@ static struct clk aes_ick = { static struct clk pka_ick = { .name = "pka_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4), @@ -1719,7 +1732,7 @@ static struct clk usb_fck = { static struct clk usbhs_ick = { .name = "usbhs_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l3_ck, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1729,7 +1742,7 @@ static struct clk usbhs_ick = { static struct clk mmchs1_ick = { .name = "mmchs1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1749,7 +1762,7 @@ static struct clk mmchs1_fck = { static struct clk mmchs2_ick = { .name = "mmchs2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1768,7 +1781,7 @@ static struct clk mmchs2_fck = { static struct clk gpio5_ick = { .name = "gpio5_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), @@ -1788,7 +1801,7 @@ static struct clk gpio5_fck = { static struct clk mdm_intc_ick = { .name = "mdm_intc_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), From ec538e30f7eded2c4af8d9184619a3de65bc378e Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:39:30 -0700 Subject: [PATCH 34/62] OMAP3: clock: use autoidle clkops for all autoidle-controllable interface clocks Mark each interface clock with a corresponding CM_AUTOIDLE bit with a clkops that has the allow_idle/deny_idle function pointers populated. This allows the OMAP clock framework to enable and disable autoidle for these clocks. Signed-off-by: Paul Walmsley Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/clock34xx.c | 29 +++++- arch/arm/mach-omap2/clock34xx.h | 5 +- arch/arm/mach-omap2/clock3517.c | 4 +- arch/arm/mach-omap2/clock3xxx_data.c | 149 ++++++++++++++------------- 4 files changed, 112 insertions(+), 75 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 287abc480924..1fc96b9ee330 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -2,7 +2,7 @@ * OMAP3-specific clock framework functions * * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2010 Nokia Corporation + * Copyright (C) 2007-2011 Nokia Corporation * * Paul Walmsley * Jouni Högander @@ -59,6 +59,15 @@ const struct clkops clkops_omap3430es2_ssi_wait = { .find_companion = omap2_clk_dflt_find_companion, }; +const struct clkops clkops_omap3430es2_iclk_ssi_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = omap3430es2_clk_ssi_find_idlest, + .find_companion = omap2_clk_dflt_find_companion, + .allow_idle = omap2_clkt_iclk_allow_idle, + .deny_idle = omap2_clkt_iclk_deny_idle, +}; + /** * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST * @clk: struct clk * being enabled @@ -94,6 +103,15 @@ const struct clkops clkops_omap3430es2_dss_usbhost_wait = { .find_companion = omap2_clk_dflt_find_companion, }; +const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest, + .find_companion = omap2_clk_dflt_find_companion, + .allow_idle = omap2_clkt_iclk_allow_idle, + .deny_idle = omap2_clkt_iclk_deny_idle, +}; + /** * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB * @clk: struct clk * being enabled @@ -124,3 +142,12 @@ const struct clkops clkops_omap3430es2_hsotgusb_wait = { .find_idlest = omap3430es2_clk_hsotgusb_find_idlest, .find_companion = omap2_clk_dflt_find_companion, }; + +const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait = { + .enable = omap2_dflt_clk_enable, + .disable = omap2_dflt_clk_disable, + .find_idlest = omap3430es2_clk_hsotgusb_find_idlest, + .find_companion = omap2_clk_dflt_find_companion, + .allow_idle = omap2_clkt_iclk_allow_idle, + .deny_idle = omap2_clkt_iclk_deny_idle, +}; diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 628e8de57680..084ba71b2b31 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -2,14 +2,17 @@ * OMAP34xx clock function prototypes and macros * * Copyright (C) 2007-2010 Texas Instruments, Inc. - * Copyright (C) 2007-2010 Nokia Corporation + * Copyright (C) 2007-2011 Nokia Corporation */ #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H #define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H extern const struct clkops clkops_omap3430es2_ssi_wait; +extern const struct clkops clkops_omap3430es2_iclk_ssi_wait; extern const struct clkops clkops_omap3430es2_hsotgusb_wait; +extern const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait; extern const struct clkops clkops_omap3430es2_dss_usbhost_wait; +extern const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait; #endif diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c index 74116a3cf099..2e97d08f0e56 100644 --- a/arch/arm/mach-omap2/clock3517.c +++ b/arch/arm/mach-omap2/clock3517.c @@ -2,7 +2,7 @@ * OMAP3517/3505-specific clock framework functions * * Copyright (C) 2010 Texas Instruments, Inc. - * Copyright (C) 2010 Nokia Corporation + * Copyright (C) 2011 Nokia Corporation * * Ranjith Lohithakshan * Paul Walmsley @@ -119,6 +119,8 @@ const struct clkops clkops_am35xx_ipss_wait = { .disable = omap2_dflt_clk_disable, .find_idlest = am35xx_clk_ipss_find_idlest, .find_companion = omap2_clk_dflt_find_companion, + .allow_idle = omap2_clkt_iclk_allow_idle, + .deny_idle = omap2_clkt_iclk_deny_idle, }; diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 65b79e6afb53..305b5f75c44f 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -2,7 +2,7 @@ * OMAP3 clock data * * Copyright (C) 2007-2010 Texas Instruments, Inc. - * Copyright (C) 2007-2010 Nokia Corporation + * Copyright (C) 2007-2011 Nokia Corporation * * Written by Paul Walmsley * With many device clock fixes by Kevin Hilman and Jouni Högander @@ -1205,7 +1205,10 @@ static const struct clksel gfx_l3_clksel[] = { { .parent = NULL } }; -/* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */ +/* + * Virtual parent clock for gfx_l3_ick and gfx_l3_fck + * This interface clock does not have a CM_AUTOIDLE bit + */ static struct clk gfx_l3_ck = { .name = "gfx_l3_ck", .ops = &clkops_omap2_dflt_wait, @@ -1304,6 +1307,7 @@ static struct clk sgx_fck = { .round_rate = &omap2_clksel_round_rate }; +/* This interface clock does not have a CM_AUTOIDLE bit */ static struct clk sgx_ick = { .name = "sgx_ick", .ops = &clkops_omap2_dflt_wait, @@ -1328,7 +1332,7 @@ static struct clk d2d_26m_fck = { static struct clk modem_fck = { .name = "modem_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_mdmclk_dflt_wait, .parent = &sys_ck, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP3430_EN_MODEM_SHIFT, @@ -1338,7 +1342,7 @@ static struct clk modem_fck = { static struct clk sad2d_ick = { .name = "sad2d_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SAD2D_SHIFT, @@ -1348,7 +1352,7 @@ static struct clk sad2d_ick = { static struct clk mad2d_ick = { .name = "mad2d_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP3430_EN_MAD2D_SHIFT, @@ -1718,7 +1722,7 @@ static struct clk core_l3_ick = { static struct clk hsotgusb_ick_3430es1 = { .name = "hsotgusb_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap2_iclk_dflt, .parent = &core_l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT, @@ -1728,7 +1732,7 @@ static struct clk hsotgusb_ick_3430es1 = { static struct clk hsotgusb_ick_3430es2 = { .name = "hsotgusb_ick", - .ops = &clkops_omap3430es2_hsotgusb_wait, + .ops = &clkops_omap3430es2_iclk_hsotgusb_wait, .parent = &core_l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_HSOTGUSB_SHIFT, @@ -1736,6 +1740,7 @@ static struct clk hsotgusb_ick_3430es2 = { .recalc = &followparent_recalc, }; +/* This interface clock does not have a CM_AUTOIDLE bit */ static struct clk sdrc_ick = { .name = "sdrc_ick", .ops = &clkops_omap2_dflt_wait, @@ -1767,7 +1772,7 @@ static struct clk security_l3_ick = { static struct clk pka_ick = { .name = "pka_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &security_l3_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_PKA_SHIFT, @@ -1786,7 +1791,7 @@ static struct clk core_l4_ick = { static struct clk usbtll_ick = { .name = "usbtll_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT, @@ -1796,7 +1801,7 @@ static struct clk usbtll_ick = { static struct clk mmchs3_ick = { .name = "mmchs3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, @@ -1807,7 +1812,7 @@ static struct clk mmchs3_ick = { /* Intersystem Communication Registers - chassis mode only */ static struct clk icr_ick = { .name = "icr_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_ICR_SHIFT, @@ -1817,7 +1822,7 @@ static struct clk icr_ick = { static struct clk aes2_ick = { .name = "aes2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_AES2_SHIFT, @@ -1827,7 +1832,7 @@ static struct clk aes2_ick = { static struct clk sha12_ick = { .name = "sha12_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SHA12_SHIFT, @@ -1837,7 +1842,7 @@ static struct clk sha12_ick = { static struct clk des2_ick = { .name = "des2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_DES2_SHIFT, @@ -1847,7 +1852,7 @@ static struct clk des2_ick = { static struct clk mmchs2_ick = { .name = "mmchs2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MMC2_SHIFT, @@ -1857,7 +1862,7 @@ static struct clk mmchs2_ick = { static struct clk mmchs1_ick = { .name = "mmchs1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MMC1_SHIFT, @@ -1867,7 +1872,7 @@ static struct clk mmchs1_ick = { static struct clk mspro_ick = { .name = "mspro_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MSPRO_SHIFT, @@ -1877,7 +1882,7 @@ static struct clk mspro_ick = { static struct clk hdq_ick = { .name = "hdq_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_HDQ_SHIFT, @@ -1887,7 +1892,7 @@ static struct clk hdq_ick = { static struct clk mcspi4_ick = { .name = "mcspi4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI4_SHIFT, @@ -1897,7 +1902,7 @@ static struct clk mcspi4_ick = { static struct clk mcspi3_ick = { .name = "mcspi3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI3_SHIFT, @@ -1907,7 +1912,7 @@ static struct clk mcspi3_ick = { static struct clk mcspi2_ick = { .name = "mcspi2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI2_SHIFT, @@ -1917,7 +1922,7 @@ static struct clk mcspi2_ick = { static struct clk mcspi1_ick = { .name = "mcspi1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCSPI1_SHIFT, @@ -1927,7 +1932,7 @@ static struct clk mcspi1_ick = { static struct clk i2c3_ick = { .name = "i2c3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_I2C3_SHIFT, @@ -1937,7 +1942,7 @@ static struct clk i2c3_ick = { static struct clk i2c2_ick = { .name = "i2c2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_I2C2_SHIFT, @@ -1947,7 +1952,7 @@ static struct clk i2c2_ick = { static struct clk i2c1_ick = { .name = "i2c1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_I2C1_SHIFT, @@ -1957,7 +1962,7 @@ static struct clk i2c1_ick = { static struct clk uart2_ick = { .name = "uart2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_UART2_SHIFT, @@ -1967,7 +1972,7 @@ static struct clk uart2_ick = { static struct clk uart1_ick = { .name = "uart1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_UART1_SHIFT, @@ -1977,7 +1982,7 @@ static struct clk uart1_ick = { static struct clk gpt11_ick = { .name = "gpt11_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_GPT11_SHIFT, @@ -1987,7 +1992,7 @@ static struct clk gpt11_ick = { static struct clk gpt10_ick = { .name = "gpt10_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_GPT10_SHIFT, @@ -1997,7 +2002,7 @@ static struct clk gpt10_ick = { static struct clk mcbsp5_ick = { .name = "mcbsp5_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCBSP5_SHIFT, @@ -2007,7 +2012,7 @@ static struct clk mcbsp5_ick = { static struct clk mcbsp1_ick = { .name = "mcbsp1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MCBSP1_SHIFT, @@ -2017,7 +2022,7 @@ static struct clk mcbsp1_ick = { static struct clk fac_ick = { .name = "fac_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430ES1_EN_FAC_SHIFT, @@ -2027,7 +2032,7 @@ static struct clk fac_ick = { static struct clk mailboxes_ick = { .name = "mailboxes_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_MAILBOXES_SHIFT, @@ -2037,7 +2042,7 @@ static struct clk mailboxes_ick = { static struct clk omapctrl_ick = { .name = "omapctrl_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT, @@ -2057,7 +2062,7 @@ static struct clk ssi_l4_ick = { static struct clk ssi_ick_3430es1 = { .name = "ssi_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap2_iclk_dflt, .parent = &ssi_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SSI_SHIFT, @@ -2067,7 +2072,7 @@ static struct clk ssi_ick_3430es1 = { static struct clk ssi_ick_3430es2 = { .name = "ssi_ick", - .ops = &clkops_omap3430es2_ssi_wait, + .ops = &clkops_omap3430es2_iclk_ssi_wait, .parent = &ssi_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP3430_EN_SSI_SHIFT, @@ -2085,7 +2090,7 @@ static const struct clksel usb_l4_clksel[] = { static struct clk usb_l4_ick = { .name = "usb_l4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ick, .init = &omap2_init_clksel_parent, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), @@ -2107,7 +2112,7 @@ static struct clk security_l4_ick2 = { static struct clk aes1_ick = { .name = "aes1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_AES1_SHIFT, @@ -2116,7 +2121,7 @@ static struct clk aes1_ick = { static struct clk rng_ick = { .name = "rng_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_RNG_SHIFT, @@ -2125,7 +2130,7 @@ static struct clk rng_ick = { static struct clk sha11_ick = { .name = "sha11_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_SHA11_SHIFT, @@ -2134,7 +2139,7 @@ static struct clk sha11_ick = { static struct clk des1_ick = { .name = "des1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &security_l4_ick2, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2), .enable_bit = OMAP3430_EN_DES1_SHIFT, @@ -2195,7 +2200,7 @@ static struct clk dss2_alwon_fck = { static struct clk dss_ick_3430es1 = { /* Handles both L3 and L4 clocks */ .name = "dss_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap2_iclk_dflt, .parent = &l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT, @@ -2206,7 +2211,7 @@ static struct clk dss_ick_3430es1 = { static struct clk dss_ick_3430es2 = { /* Handles both L3 and L4 clocks */ .name = "dss_ick", - .ops = &clkops_omap3430es2_dss_usbhost_wait, + .ops = &clkops_omap3430es2_iclk_dss_usbhost_wait, .parent = &l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN), .enable_bit = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT, @@ -2229,7 +2234,7 @@ static struct clk cam_mclk = { static struct clk cam_ick = { /* Handles both L3 and L4 clocks */ .name = "cam_ick", - .ops = &clkops_omap2_dflt, + .ops = &clkops_omap2_iclk_dflt, .parent = &l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_CAM_SHIFT, @@ -2272,7 +2277,7 @@ static struct clk usbhost_48m_fck = { static struct clk usbhost_ick = { /* Handles both L3 and L4 clocks */ .name = "usbhost_ick", - .ops = &clkops_omap3430es2_dss_usbhost_wait, + .ops = &clkops_omap3430es2_iclk_dss_usbhost_wait, .parent = &l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_USBHOST_SHIFT, @@ -2372,7 +2377,7 @@ static struct clk wkup_l4_ick = { /* Never specifically named in the TRM, so we have to infer a likely name */ static struct clk usim_ick = { .name = "usim_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430ES2_EN_USIMOCP_SHIFT, @@ -2382,7 +2387,7 @@ static struct clk usim_ick = { static struct clk wdt2_ick = { .name = "wdt2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT2_SHIFT, @@ -2392,7 +2397,7 @@ static struct clk wdt2_ick = { static struct clk wdt1_ick = { .name = "wdt1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT1_SHIFT, @@ -2402,7 +2407,7 @@ static struct clk wdt1_ick = { static struct clk gpio1_ick = { .name = "gpio1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO1_SHIFT, @@ -2412,7 +2417,7 @@ static struct clk gpio1_ick = { static struct clk omap_32ksync_ick = { .name = "omap_32ksync_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_32KSYNC_SHIFT, @@ -2423,7 +2428,7 @@ static struct clk omap_32ksync_ick = { /* XXX This clock no longer exists in 3430 TRM rev F */ static struct clk gpt12_ick = { .name = "gpt12_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT12_SHIFT, @@ -2433,7 +2438,7 @@ static struct clk gpt12_ick = { static struct clk gpt1_ick = { .name = "gpt1_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &wkup_l4_ick, .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT1_SHIFT, @@ -2663,7 +2668,7 @@ static struct clk per_l4_ick = { static struct clk gpio6_ick = { .name = "gpio6_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO6_SHIFT, @@ -2673,7 +2678,7 @@ static struct clk gpio6_ick = { static struct clk gpio5_ick = { .name = "gpio5_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO5_SHIFT, @@ -2683,7 +2688,7 @@ static struct clk gpio5_ick = { static struct clk gpio4_ick = { .name = "gpio4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO4_SHIFT, @@ -2693,7 +2698,7 @@ static struct clk gpio4_ick = { static struct clk gpio3_ick = { .name = "gpio3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO3_SHIFT, @@ -2703,7 +2708,7 @@ static struct clk gpio3_ick = { static struct clk gpio2_ick = { .name = "gpio2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPIO2_SHIFT, @@ -2713,7 +2718,7 @@ static struct clk gpio2_ick = { static struct clk wdt3_ick = { .name = "wdt3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_WDT3_SHIFT, @@ -2723,7 +2728,7 @@ static struct clk wdt3_ick = { static struct clk uart3_ick = { .name = "uart3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_UART3_SHIFT, @@ -2733,7 +2738,7 @@ static struct clk uart3_ick = { static struct clk uart4_ick = { .name = "uart4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3630_EN_UART4_SHIFT, @@ -2743,7 +2748,7 @@ static struct clk uart4_ick = { static struct clk gpt9_ick = { .name = "gpt9_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT9_SHIFT, @@ -2753,7 +2758,7 @@ static struct clk gpt9_ick = { static struct clk gpt8_ick = { .name = "gpt8_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT8_SHIFT, @@ -2763,7 +2768,7 @@ static struct clk gpt8_ick = { static struct clk gpt7_ick = { .name = "gpt7_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT7_SHIFT, @@ -2773,7 +2778,7 @@ static struct clk gpt7_ick = { static struct clk gpt6_ick = { .name = "gpt6_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT6_SHIFT, @@ -2783,7 +2788,7 @@ static struct clk gpt6_ick = { static struct clk gpt5_ick = { .name = "gpt5_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT5_SHIFT, @@ -2793,7 +2798,7 @@ static struct clk gpt5_ick = { static struct clk gpt4_ick = { .name = "gpt4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT4_SHIFT, @@ -2803,7 +2808,7 @@ static struct clk gpt4_ick = { static struct clk gpt3_ick = { .name = "gpt3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT3_SHIFT, @@ -2813,7 +2818,7 @@ static struct clk gpt3_ick = { static struct clk gpt2_ick = { .name = "gpt2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_GPT2_SHIFT, @@ -2823,7 +2828,7 @@ static struct clk gpt2_ick = { static struct clk mcbsp2_ick = { .name = "mcbsp2_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_MCBSP2_SHIFT, @@ -2833,7 +2838,7 @@ static struct clk mcbsp2_ick = { static struct clk mcbsp3_ick = { .name = "mcbsp3_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_MCBSP3_SHIFT, @@ -2843,7 +2848,7 @@ static struct clk mcbsp3_ick = { static struct clk mcbsp4_ick = { .name = "mcbsp4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &per_l4_ick, .enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN), .enable_bit = OMAP3430_EN_MCBSP4_SHIFT, @@ -3186,7 +3191,7 @@ static struct clk vpfe_fck = { */ static struct clk uart4_ick_am35xx = { .name = "uart4_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_iclk_dflt_wait, .parent = &core_l4_ick, .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = AM35XX_EN_UART4_SHIFT, From 4ef70c0694bf428d9f1d4722edaffa1dc5fa39e1 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:39:30 -0700 Subject: [PATCH 35/62] OMAP2/3: PM: remove manual CM_AUTOIDLE bit setting in mach-omap2/pm*xx.c These CM_AUTOIDLE bits are now set by the clock code via the common PM code in mach-omap2/pm.c. N.B.: The pm24xx.c code that this patch removes didn't ensure that the CM_AUTOIDLE bits were set for several 2430-only modules, such as GPIO5, MDM_INTC, MMCHS1/2, the modem oscillator clock, and USBHS. Similarly, the pm34xx.c code that this patch removes didn't ensure that the CM_AUTOIDLE bits were set for USIM and the AM3517 UART4. Those cases should now be handled. Signed-off-by: Paul Walmsley Cc: Kevin Hilman Tested-by: Rajendra Nayak Reviewed-by: Kevin Hilman --- arch/arm/mach-omap2/pm24xx.c | 63 ++------------------- arch/arm/mach-omap2/pm34xx.c | 105 +---------------------------------- 2 files changed, 5 insertions(+), 163 deletions(-) diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index abe08f49b2ec..96907da1910a 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -379,7 +379,10 @@ static void __init prcm_setup_regs(void) int i, num_mem_banks; struct powerdomain *pwrdm; - /* Enable autoidle */ + /* + * Enable autoidle + * XXX This should be handled by hwmod code or PRCM init code + */ omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD, OMAP2_PRCM_SYSCONFIG_OFFSET); @@ -418,64 +421,6 @@ static void __init prcm_setup_regs(void) clkdm_for_each(clkdms_setup, NULL); clkdm_add_wkdep(mpu_clkdm, wkup_clkdm); - /* Enable clock autoidle for all domains */ - omap2_cm_write_mod_reg(OMAP24XX_AUTO_CAM_MASK | - OMAP24XX_AUTO_MAILBOXES_MASK | - OMAP24XX_AUTO_WDT4_MASK | - OMAP2420_AUTO_WDT3_MASK | - OMAP24XX_AUTO_MSPRO_MASK | - OMAP2420_AUTO_MMC_MASK | - OMAP24XX_AUTO_FAC_MASK | - OMAP2420_AUTO_EAC_MASK | - OMAP24XX_AUTO_HDQ_MASK | - OMAP24XX_AUTO_UART2_MASK | - OMAP24XX_AUTO_UART1_MASK | - OMAP24XX_AUTO_I2C2_MASK | - OMAP24XX_AUTO_I2C1_MASK | - OMAP24XX_AUTO_MCSPI2_MASK | - OMAP24XX_AUTO_MCSPI1_MASK | - OMAP24XX_AUTO_MCBSP2_MASK | - OMAP24XX_AUTO_MCBSP1_MASK | - OMAP24XX_AUTO_GPT12_MASK | - OMAP24XX_AUTO_GPT11_MASK | - OMAP24XX_AUTO_GPT10_MASK | - OMAP24XX_AUTO_GPT9_MASK | - OMAP24XX_AUTO_GPT8_MASK | - OMAP24XX_AUTO_GPT7_MASK | - OMAP24XX_AUTO_GPT6_MASK | - OMAP24XX_AUTO_GPT5_MASK | - OMAP24XX_AUTO_GPT4_MASK | - OMAP24XX_AUTO_GPT3_MASK | - OMAP24XX_AUTO_GPT2_MASK | - OMAP2420_AUTO_VLYNQ_MASK | - OMAP24XX_AUTO_DSS_MASK, - CORE_MOD, CM_AUTOIDLE1); - omap2_cm_write_mod_reg(OMAP24XX_AUTO_UART3_MASK | - OMAP24XX_AUTO_SSI_MASK | - OMAP24XX_AUTO_USB_MASK, - CORE_MOD, CM_AUTOIDLE2); - omap2_cm_write_mod_reg(OMAP24XX_AUTO_SDRC_MASK | - OMAP24XX_AUTO_GPMC_MASK | - OMAP24XX_AUTO_SDMA_MASK, - CORE_MOD, CM_AUTOIDLE3); - omap2_cm_write_mod_reg(OMAP24XX_AUTO_PKA_MASK | - OMAP24XX_AUTO_AES_MASK | - OMAP24XX_AUTO_RNG_MASK | - OMAP24XX_AUTO_SHA_MASK | - OMAP24XX_AUTO_DES_MASK, - CORE_MOD, OMAP24XX_CM_AUTOIDLE4); - - omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD, - CM_AUTOIDLE); - - omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK | - OMAP24XX_AUTO_WDT1_MASK | - OMAP24XX_AUTO_MPU_WDT_MASK | - OMAP24XX_AUTO_GPIOS_MASK | - OMAP24XX_AUTO_32KSYNC_MASK | - OMAP24XX_AUTO_GPT1_MASK, - WKUP_MOD, CM_AUTOIDLE); - /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk * stabilisation */ omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index a99f296bdbfd..3d6a00e07a5b 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -688,14 +688,11 @@ static void __init omap3_d2d_idle(void) static void __init prcm_setup_regs(void) { - u32 omap3630_auto_uart4_mask = cpu_is_omap3630() ? - OMAP3630_AUTO_UART4_MASK : 0; u32 omap3630_en_uart4_mask = cpu_is_omap3630() ? OMAP3630_EN_UART4_MASK : 0; u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ? OMAP3630_GRPSEL_UART4_MASK : 0; - /* XXX Reset all wkdeps. This should be done when initializing * powerdomains */ omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP); @@ -710,107 +707,7 @@ static void __init prcm_setup_regs(void) } else omap2_prm_write_mod_reg(0, GFX_MOD, PM_WKDEP); - /* - * Enable interface clock autoidle for all modules. - * Note that in the long run this should be done by clockfw - */ - omap2_cm_write_mod_reg( - OMAP3430_AUTO_MODEM_MASK | - OMAP3430ES2_AUTO_MMC3_MASK | - OMAP3430ES2_AUTO_ICR_MASK | - OMAP3430_AUTO_AES2_MASK | - OMAP3430_AUTO_SHA12_MASK | - OMAP3430_AUTO_DES2_MASK | - OMAP3430_AUTO_MMC2_MASK | - OMAP3430_AUTO_MMC1_MASK | - OMAP3430_AUTO_MSPRO_MASK | - OMAP3430_AUTO_HDQ_MASK | - OMAP3430_AUTO_MCSPI4_MASK | - OMAP3430_AUTO_MCSPI3_MASK | - OMAP3430_AUTO_MCSPI2_MASK | - OMAP3430_AUTO_MCSPI1_MASK | - OMAP3430_AUTO_I2C3_MASK | - OMAP3430_AUTO_I2C2_MASK | - OMAP3430_AUTO_I2C1_MASK | - OMAP3430_AUTO_UART2_MASK | - OMAP3430_AUTO_UART1_MASK | - OMAP3430_AUTO_GPT11_MASK | - OMAP3430_AUTO_GPT10_MASK | - OMAP3430_AUTO_MCBSP5_MASK | - OMAP3430_AUTO_MCBSP1_MASK | - OMAP3430ES1_AUTO_FAC_MASK | /* This is es1 only */ - OMAP3430_AUTO_MAILBOXES_MASK | - OMAP3430_AUTO_OMAPCTRL_MASK | - OMAP3430ES1_AUTO_FSHOSTUSB_MASK | - OMAP3430_AUTO_HSOTGUSB_MASK | - OMAP3430_AUTO_SAD2D_MASK | - OMAP3430_AUTO_SSI_MASK, - CORE_MOD, CM_AUTOIDLE1); - - omap2_cm_write_mod_reg( - OMAP3430_AUTO_PKA_MASK | - OMAP3430_AUTO_AES1_MASK | - OMAP3430_AUTO_RNG_MASK | - OMAP3430_AUTO_SHA11_MASK | - OMAP3430_AUTO_DES1_MASK, - CORE_MOD, CM_AUTOIDLE2); - - if (omap_rev() > OMAP3430_REV_ES1_0) { - omap2_cm_write_mod_reg( - OMAP3430_AUTO_MAD2D_MASK | - OMAP3430ES2_AUTO_USBTLL_MASK, - CORE_MOD, CM_AUTOIDLE3); - } - - omap2_cm_write_mod_reg( - OMAP3430_AUTO_WDT2_MASK | - OMAP3430_AUTO_WDT1_MASK | - OMAP3430_AUTO_GPIO1_MASK | - OMAP3430_AUTO_32KSYNC_MASK | - OMAP3430_AUTO_GPT12_MASK | - OMAP3430_AUTO_GPT1_MASK, - WKUP_MOD, CM_AUTOIDLE); - - omap2_cm_write_mod_reg( - OMAP3430_AUTO_DSS_MASK, - OMAP3430_DSS_MOD, - CM_AUTOIDLE); - - omap2_cm_write_mod_reg( - OMAP3430_AUTO_CAM_MASK, - OMAP3430_CAM_MOD, - CM_AUTOIDLE); - - omap2_cm_write_mod_reg( - omap3630_auto_uart4_mask | - OMAP3430_AUTO_GPIO6_MASK | - OMAP3430_AUTO_GPIO5_MASK | - OMAP3430_AUTO_GPIO4_MASK | - OMAP3430_AUTO_GPIO3_MASK | - OMAP3430_AUTO_GPIO2_MASK | - OMAP3430_AUTO_WDT3_MASK | - OMAP3430_AUTO_UART3_MASK | - OMAP3430_AUTO_GPT9_MASK | - OMAP3430_AUTO_GPT8_MASK | - OMAP3430_AUTO_GPT7_MASK | - OMAP3430_AUTO_GPT6_MASK | - OMAP3430_AUTO_GPT5_MASK | - OMAP3430_AUTO_GPT4_MASK | - OMAP3430_AUTO_GPT3_MASK | - OMAP3430_AUTO_GPT2_MASK | - OMAP3430_AUTO_MCBSP4_MASK | - OMAP3430_AUTO_MCBSP3_MASK | - OMAP3430_AUTO_MCBSP2_MASK, - OMAP3430_PER_MOD, - CM_AUTOIDLE); - - if (omap_rev() > OMAP3430_REV_ES1_0) { - omap2_cm_write_mod_reg( - OMAP3430ES2_AUTO_USBHOST_MASK, - OMAP3430ES2_USBHOST_MOD, - CM_AUTOIDLE); - } - + /* XXX This should be handled by hwmod code or SCM init code */ omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG); /* From 7328ff4d72401835fa1aadfb9e574a2133bd952b Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:54:33 -0700 Subject: [PATCH 36/62] OMAP: smartreflex: move plat/smartreflex.h to mach-omap2/smartreflex.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no reason for this header file to be in plat-omap/include/plat/smartreflex.h. The hardware devices are in OMAP2+ SoCs only. Leaving this header file in plat-omap causes problems due to cross-dependencies with other header files that should live in mach-omap2/. Thanks to Benoît Cousson for suggesting the removal of the smartreflex.h include from the OMAP3xxx hwmod data. Signed-off-by: Paul Walmsley Cc: Benoît Cousson --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 1 - arch/arm/mach-omap2/smartreflex-class3.c | 2 +- arch/arm/mach-omap2/smartreflex.c | 2 +- arch/arm/{plat-omap/include/plat => mach-omap2}/smartreflex.h | 0 arch/arm/mach-omap2/sr_device.c | 2 +- 5 files changed, 3 insertions(+), 4 deletions(-) rename arch/arm/{plat-omap/include/plat => mach-omap2}/smartreflex.h (100%) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index e9d001228568..8de2de97c2a1 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include "omap_hwmod_common_data.h" diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c index 60e70552b4c5..f438cf4d847b 100644 --- a/arch/arm/mach-omap2/smartreflex-class3.c +++ b/arch/arm/mach-omap2/smartreflex-class3.c @@ -11,7 +11,7 @@ * published by the Free Software Foundation. */ -#include +#include "smartreflex.h" static int sr_class3_enable(struct voltagedomain *voltdm) { diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index c37e823266d3..077dfb6fd8fb 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -26,9 +26,9 @@ #include #include -#include #include "pm.h" +#include "smartreflex.h" #define SMARTREFLEX_NAME_LEN 16 #define NVALUE_NAME_LEN 40 diff --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h similarity index 100% rename from arch/arm/plat-omap/include/plat/smartreflex.h rename to arch/arm/mach-omap2/smartreflex.h diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index b1e0af18a26a..a636604961bc 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -23,9 +23,9 @@ #include #include -#include #include +#include "smartreflex.h" #include "control.h" #include "pm.h" From e1d6f4729e9fd46efa1029b6e806bb8b6c24e776 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:54:33 -0700 Subject: [PATCH 37/62] OMAP: voltage: move plat/voltage.h to mach-omap2/voltage.h At this point in time, there's no reason for this header file to be in plat-omap/include/plat/voltage.h. It should not be included by device drivers, and the code that uses it is currently all under mach-omap2/. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_twl.c | 2 +- arch/arm/mach-omap2/pm.c | 2 +- arch/arm/mach-omap2/smartreflex.h | 3 ++- arch/arm/mach-omap2/sr_device.c | 2 +- arch/arm/mach-omap2/voltage.c | 3 ++- arch/arm/{plat-omap/include/plat => mach-omap2}/voltage.h | 0 arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 - 7 files changed, 7 insertions(+), 6 deletions(-) rename arch/arm/{plat-omap/include/plat => mach-omap2}/voltage.h (100%) diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c index 00e1d2b53683..ad8c18a45ce1 100644 --- a/arch/arm/mach-omap2/omap_twl.c +++ b/arch/arm/mach-omap2/omap_twl.c @@ -18,7 +18,7 @@ #include #include -#include +#include "voltage.h" #include "pm.h" diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 7bb64d8121a7..2c3a2531e678 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -18,8 +18,8 @@ #include #include #include -#include +#include "voltage.h" #include "powerdomain.h" #include "clockdomain.h" #include "pm.h" diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h index 6568c885f37a..5f35b9e25556 100644 --- a/arch/arm/mach-omap2/smartreflex.h +++ b/arch/arm/mach-omap2/smartreflex.h @@ -21,7 +21,8 @@ #define __ASM_ARM_OMAP_SMARTREFLEX_H #include -#include + +#include "voltage.h" /* * Different Smartreflex IPs version. The v1 is the 65nm version used in diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index a636604961bc..10d3c5ee8018 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -23,9 +23,9 @@ #include #include -#include #include "smartreflex.h" +#include "voltage.h" #include "control.h" #include "pm.h" diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index 12be525b8df4..3c9bcdce612b 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -26,7 +26,6 @@ #include #include -#include #include "prm-regbits-34xx.h" #include "prm-regbits-44xx.h" @@ -35,6 +34,8 @@ #include "prminst44xx.h" #include "control.h" +#include "voltage.h" + #define VP_IDLE_TIMEOUT 200 #define VP_TRANXDONE_TIMEOUT 300 #define VOLTAGE_DIR_SIZE 16 diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/mach-omap2/voltage.h similarity index 100% rename from arch/arm/plat-omap/include/plat/voltage.h rename to arch/arm/mach-omap2/voltage.h diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index fedd82971c9e..82d79f011dcc 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -34,7 +34,6 @@ #include #include #include -#include struct omap_device; From a1fed577ddc0ca0ec7cf5e5ee033fe3df4192ebd Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:51:02 -0700 Subject: [PATCH 38/62] OMAP2xxx: clock: fix parents for L3-derived clocks Several clocks are listed as having the core L4 clock as their parent, when they are actually derived from the L3 clock. Fix these. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock2420_data.c | 2 +- arch/arm/mach-omap2/clock2430_data.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 68c03691e56a..693a0a84c33d 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1614,7 +1614,7 @@ static struct clk sdma_fck = { static struct clk sdma_ick = { .name = "sdma_ick", .ops = &clkops_omap2_iclk_idle_only, - .parent = &l4_ck, + .parent = &core_l3_ck, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT, diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 34daed9cd56f..f00f52ebfeaf 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -1652,7 +1652,7 @@ static struct clk sdma_fck = { static struct clk sdma_ick = { .name = "sdma_ick", .ops = &clkops_omap2_iclk_idle_only, - .parent = &l4_ck, + .parent = &core_l3_ck, .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP24XX_AUTO_SDMA_SHIFT, @@ -1662,9 +1662,9 @@ static struct clk sdma_ick = { static struct clk sdrc_ick = { .name = "sdrc_ick", .ops = &clkops_omap2_iclk_idle_only, - .parent = &l4_ck, + .parent = &core_l3_ck, .flags = ENABLE_ON_INIT, - .clkdm_name = "core_l4_clkdm", + .clkdm_name = "core_l3_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), .enable_bit = OMAP2430_EN_SDRC_SHIFT, .recalc = &followparent_recalc, From 3f9cfd3a47a07c93ff00a1a4ca067ada87e4076a Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 16 Feb 2011 15:38:38 -0700 Subject: [PATCH 39/62] OMAP2xxx: clock: fix low-frequency oscillator clock rate The OMAP2420/2430 external 32-kHz low-frequency oscillator is a 32768 Hz oscillator, not a 32,000 Hz oscillator[1][2]. Fix this in the clock tree. Signed-off-by: Paul Walmsley 1. OMAP2420/22 Multimedia Processor Data Manual, Version P [SWPS019P], section 5.1.4 "External 32-kHz CMOS Clock" (note that it refers to a "32.768-kHz" clock; this presumably should be "32.768-KHz") 2. OMAP2430 Multimedia Processor ES2.1 Data Manual, Version V [SWPS023V], section 5.1.4 "External 32-kHz CMOS Clock" (note that it refers to a "32.768-kHz" clock; this presumably should be "32.768-KHz") --- arch/arm/mach-omap2/clock2420_data.c | 2 +- arch/arm/mach-omap2/clock2430_data.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 693a0a84c33d..fd5ba90188be 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -55,7 +55,7 @@ static struct clk func_32k_ck = { .name = "func_32k_ck", .ops = &clkops_null, - .rate = 32000, + .rate = 32768, .clkdm_name = "wkup_clkdm", }; diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index f00f52ebfeaf..0d069ef49e2d 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -55,7 +55,7 @@ static struct clk func_32k_ck = { .name = "func_32k_ck", .ops = &clkops_null, - .rate = 32000, + .rate = 32768, .clkdm_name = "wkup_clkdm", }; From 19c1c0ce9ddc45fe8f84b6cf12ba9dbecd7b1aa1 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 16 Feb 2011 15:38:38 -0700 Subject: [PATCH 40/62] OMAP2xxx: clock: fix interface clocks and clockdomains for modules in the WKUP domain The parent of the interface clocks for GPTIMER1, MPU_WDT, SYNCTIMER_32K, SCM, WDT1, and the ICR (2430 only) were all listed as being l4_ck. This isn't accurate; these modules exist inside the WKUP domain, and the interface clock to these modules runs at the SYS_CLK rate rather than the CORE L4 rate. So, create a new clock "wu_l4_ick", similar to the OMAP3 "wkup_l4_ick", that serves as the parent for these clocks. Also, these clocks were listed as existing inside core_l4_clkdm; wkup_clkdm is probably more accurate. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock2420_data.c | 33 ++++++++++++++++--------- arch/arm/mach-omap2/clock2430_data.c | 37 +++++++++++++++++----------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index fd5ba90188be..6e9d20dc8649 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -826,6 +826,14 @@ static struct clk dss_54m_fck = { /* Alt clk used in power management */ .recalc = &followparent_recalc, }; +static struct clk wu_l4_ick = { + .name = "wu_l4_ick", + .ops = &clkops_null, + .parent = &sys_ck, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + /* * CORE power domain ICLK & FCLK defines. * Many of the these can have more than one possible parent. Entries @@ -847,8 +855,8 @@ static const struct clksel omap24xx_gpt_clksel[] = { static struct clk gpt1_ick = { .name = "gpt1_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_GPT1_SHIFT, .recalc = &followparent_recalc, @@ -1300,8 +1308,8 @@ static struct clk uart3_fck = { static struct clk gpios_ick = { .name = "gpios_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_GPIOS_SHIFT, .recalc = &followparent_recalc, @@ -1320,8 +1328,8 @@ static struct clk gpios_fck = { static struct clk mpu_wdt_ick = { .name = "mpu_wdt_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT, .recalc = &followparent_recalc, @@ -1340,9 +1348,9 @@ static struct clk mpu_wdt_fck = { static struct clk sync_32k_ick = { .name = "sync_32k_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .flags = ENABLE_ON_INIT, - .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT, .recalc = &followparent_recalc, @@ -1351,8 +1359,8 @@ static struct clk sync_32k_ick = { static struct clk wdt1_ick = { .name = "wdt1_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_WDT1_SHIFT, .recalc = &followparent_recalc, @@ -1361,9 +1369,9 @@ static struct clk wdt1_ick = { static struct clk omapctrl_ick = { .name = "omapctrl_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .flags = ENABLE_ON_INIT, - .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT, .recalc = &followparent_recalc, @@ -1825,6 +1833,7 @@ static struct omap_clk omap2420_clks[] = { /* L4 domain clocks */ CLK(NULL, "l4_ck", &l4_ck, CK_242X), CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_242X), + CLK(NULL, "wu_l4_ick", &wu_l4_ick, CK_242X), /* virtual meta-group clock */ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_242X), /* general l4 interface ck, multi-parent functional clk */ diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 0d069ef49e2d..3378dbf8bace 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -814,6 +814,14 @@ static struct clk dss_54m_fck = { /* Alt clk used in power management */ .recalc = &followparent_recalc, }; +static struct clk wu_l4_ick = { + .name = "wu_l4_ick", + .ops = &clkops_null, + .parent = &sys_ck, + .clkdm_name = "wkup_clkdm", + .recalc = &followparent_recalc, +}; + /* * CORE power domain ICLK & FCLK defines. * Many of the these can have more than one possible parent. Entries @@ -835,8 +843,8 @@ static const struct clksel omap24xx_gpt_clksel[] = { static struct clk gpt1_ick = { .name = "gpt1_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_GPT1_SHIFT, .recalc = &followparent_recalc, @@ -1380,8 +1388,8 @@ static struct clk uart3_fck = { static struct clk gpios_ick = { .name = "gpios_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_GPIOS_SHIFT, .recalc = &followparent_recalc, @@ -1400,8 +1408,8 @@ static struct clk gpios_fck = { static struct clk mpu_wdt_ick = { .name = "mpu_wdt_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_MPU_WDT_SHIFT, .recalc = &followparent_recalc, @@ -1420,9 +1428,9 @@ static struct clk mpu_wdt_fck = { static struct clk sync_32k_ick = { .name = "sync_32k_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, .flags = ENABLE_ON_INIT, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_32KSYNC_SHIFT, .recalc = &followparent_recalc, @@ -1431,8 +1439,8 @@ static struct clk sync_32k_ick = { static struct clk wdt1_ick = { .name = "wdt1_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_WDT1_SHIFT, .recalc = &followparent_recalc, @@ -1441,9 +1449,9 @@ static struct clk wdt1_ick = { static struct clk omapctrl_ick = { .name = "omapctrl_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, .flags = ENABLE_ON_INIT, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP24XX_EN_OMAPCTRL_SHIFT, .recalc = &followparent_recalc, @@ -1452,8 +1460,8 @@ static struct clk omapctrl_ick = { static struct clk icr_ick = { .name = "icr_ick", .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &l4_ck, - .clkdm_name = "core_l4_clkdm", + .parent = &wu_l4_ick, + .clkdm_name = "wkup_clkdm", .enable_reg = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN), .enable_bit = OMAP2430_EN_ICR_SHIFT, .recalc = &followparent_recalc, @@ -1914,6 +1922,7 @@ static struct omap_clk omap2430_clks[] = { /* L4 domain clocks */ CLK(NULL, "l4_ck", &l4_ck, CK_243X), CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_243X), + CLK(NULL, "wu_l4_ick", &wu_l4_ick, CK_243X), /* virtual meta-group clock */ CLK(NULL, "virt_prcm_set", &virt_prcm_set, CK_243X), /* general l4 interface ck, multi-parent functional clk */ From e07f469d284ca3d1f5dcf5438c22982be98bc071 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 16 Feb 2011 15:38:38 -0700 Subject: [PATCH 41/62] OMAP: clock: bail out early if arch_clock functions not implemented Bail out before we take the clockfw_lock spinlock if the corresponding OMAP1 or OMAP2+ clock function is not defined. The intention is to reduce and simplify the work that is done inside the spinlock. Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/clock.c | 66 ++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 2770dddd72c0..c9122dd6ee8d 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -37,14 +37,16 @@ static struct clk_functions *arch_clock; int clk_enable(struct clk *clk) { unsigned long flags; - int ret = 0; + int ret; if (clk == NULL || IS_ERR(clk)) return -EINVAL; + if (!arch_clock || !arch_clock->clk_enable) + return -EINVAL; + spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_enable) - ret = arch_clock->clk_enable(clk); + ret = arch_clock->clk_enable(clk); spin_unlock_irqrestore(&clockfw_lock, flags); return ret; @@ -58,6 +60,9 @@ void clk_disable(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return; + if (!arch_clock || !arch_clock->clk_disable) + return; + spin_lock_irqsave(&clockfw_lock, flags); if (clk->usecount == 0) { pr_err("Trying disable clock %s with 0 usecount\n", @@ -66,8 +71,7 @@ void clk_disable(struct clk *clk) goto out; } - if (arch_clock->clk_disable) - arch_clock->clk_disable(clk); + arch_clock->clk_disable(clk); out: spin_unlock_irqrestore(&clockfw_lock, flags); @@ -77,7 +81,7 @@ EXPORT_SYMBOL(clk_disable); unsigned long clk_get_rate(struct clk *clk) { unsigned long flags; - unsigned long ret = 0; + unsigned long ret; if (clk == NULL || IS_ERR(clk)) return 0; @@ -97,14 +101,16 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { unsigned long flags; - long ret = 0; + long ret; if (clk == NULL || IS_ERR(clk)) - return ret; + return 0; + + if (!arch_clock || !arch_clock->clk_round_rate) + return 0; spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_round_rate) - ret = arch_clock->clk_round_rate(clk, rate); + ret = arch_clock->clk_round_rate(clk, rate); spin_unlock_irqrestore(&clockfw_lock, flags); return ret; @@ -119,14 +125,13 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk == NULL || IS_ERR(clk)) return ret; + if (!arch_clock || !arch_clock->clk_set_rate) + return ret; + spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_set_rate) - ret = arch_clock->clk_set_rate(clk, rate); - if (ret == 0) { - if (clk->recalc) - clk->rate = clk->recalc(clk); + ret = arch_clock->clk_set_rate(clk, rate); + if (ret == 0) propagate_rate(clk); - } spin_unlock_irqrestore(&clockfw_lock, flags); return ret; @@ -141,15 +146,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent) if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent)) return ret; + if (!arch_clock || !arch_clock->clk_set_parent) + return ret; + spin_lock_irqsave(&clockfw_lock, flags); if (clk->usecount == 0) { - if (arch_clock->clk_set_parent) - ret = arch_clock->clk_set_parent(clk, parent); - if (ret == 0) { - if (clk->recalc) - clk->rate = clk->recalc(clk); + ret = arch_clock->clk_set_parent(clk, parent); + if (ret == 0) propagate_rate(clk); - } } else ret = -EBUSY; spin_unlock_irqrestore(&clockfw_lock, flags); @@ -399,9 +403,11 @@ void clk_init_cpufreq_table(struct cpufreq_frequency_table **table) { unsigned long flags; + if (!arch_clock || !arch_clock->clk_init_cpufreq_table) + return; + spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_init_cpufreq_table) - arch_clock->clk_init_cpufreq_table(table); + arch_clock->clk_init_cpufreq_table(table); spin_unlock_irqrestore(&clockfw_lock, flags); } @@ -409,9 +415,11 @@ void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) { unsigned long flags; + if (!arch_clock || !arch_clock->clk_exit_cpufreq_table) + return; + spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_exit_cpufreq_table) - arch_clock->clk_exit_cpufreq_table(table); + arch_clock->clk_exit_cpufreq_table(table); spin_unlock_irqrestore(&clockfw_lock, flags); } #endif @@ -429,6 +437,9 @@ static int __init clk_disable_unused(void) struct clk *ck; unsigned long flags; + if (!arch_clock || !arch_clock->clk_disable_unused) + return 0; + pr_info("clock: disabling unused clocks to save power\n"); list_for_each_entry(ck, &clocks, node) { if (ck->ops == &clkops_null) @@ -438,8 +449,7 @@ static int __init clk_disable_unused(void) continue; spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_disable_unused) - arch_clock->clk_disable_unused(ck); + arch_clock->clk_disable_unused(ck); spin_unlock_irqrestore(&clockfw_lock, flags); } From 241d3a8dca239610d3d991bf58d4fe38c2d86fd5 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 16 Feb 2011 15:38:39 -0700 Subject: [PATCH 42/62] OMAP2+: clock: remove the DPLL rate tolerance code Remove the DPLL rate tolerance code that is called during rate rounding. As far as I know, this code is never used, since it's been more important for callers of the DPLL round_rate()/set_rate() functions to obtain an exact rate than it is to save a relatively small amount of power. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clkt_dpll.c | 91 +++++++------------------ arch/arm/mach-omap2/clock.h | 4 -- arch/arm/mach-omap2/clock2420_data.c | 1 - arch/arm/mach-omap2/clock2430_data.c | 1 - arch/arm/mach-omap2/clock3xxx_data.c | 6 -- arch/arm/plat-omap/include/plat/clock.h | 7 +- 6 files changed, 24 insertions(+), 86 deletions(-) diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c index 337392c3f549..17735e7f47b1 100644 --- a/arch/arm/mach-omap2/clkt_dpll.c +++ b/arch/arm/mach-omap2/clkt_dpll.c @@ -178,12 +178,11 @@ void omap2_init_dpll_parent(struct clk *clk) if (!dd) return; - /* Return bypass rate if DPLL is bypassed */ v = __raw_readl(dd->control_reg); v &= dd->enable_mask; v >>= __ffs(dd->enable_mask); - /* Reparent in case the dpll is in bypass */ + /* Reparent the struct clk in case the dpll is in bypass */ if (cpu_is_omap24xx()) { if (v == OMAP2XXX_EN_DPLL_LPBYPASS || v == OMAP2XXX_EN_DPLL_FRBYPASS) @@ -259,51 +258,23 @@ u32 omap2_get_dpll_rate(struct clk *clk) /* DPLL rate rounding code */ -/** - * omap2_dpll_set_rate_tolerance: set the error tolerance during rate rounding - * @clk: struct clk * of the DPLL - * @tolerance: maximum rate error tolerance - * - * Set the maximum DPLL rate error tolerance for the rate rounding - * algorithm. The rate tolerance is an attempt to balance DPLL power - * saving (the least divider value "n") vs. rate fidelity (the least - * difference between the desired DPLL target rate and the rounded - * rate out of the algorithm). So, increasing the tolerance is likely - * to decrease DPLL power consumption and increase DPLL rate error. - * Returns -EINVAL if provided a null clock ptr or a clk that is not a - * DPLL; or 0 upon success. - */ -int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance) -{ - if (!clk || !clk->dpll_data) - return -EINVAL; - - clk->dpll_data->rate_tolerance = tolerance; - - return 0; -} - /** * omap2_dpll_round_rate - round a target rate for an OMAP DPLL * @clk: struct clk * for a DPLL * @target_rate: desired DPLL clock rate * - * Given a DPLL, a desired target rate, and a rate tolerance, round - * the target rate to a possible, programmable rate for this DPLL. - * Rate tolerance is assumed to be set by the caller before this - * function is called. Attempts to select the minimum possible n - * within the tolerance to reduce power consumption. Stores the - * computed (m, n) in the DPLL's dpll_data structure so set_rate() - * will not need to call this (expensive) function again. Returns ~0 - * if the target rate cannot be rounded, either because the rate is - * too low or because the rate tolerance is set too tightly; or the - * rounded rate upon success. + * Given a DPLL and a desired target rate, round the target rate to a + * possible, programmable rate for this DPLL. Attempts to select the + * minimum possible n. Stores the computed (m, n) in the DPLL's + * dpll_data structure so set_rate() will not need to call this + * (expensive) function again. Returns ~0 if the target rate cannot + * be rounded, or the rounded rate upon success. */ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) { - int m, n, r, e, scaled_max_m; - unsigned long scaled_rt_rp, new_rate; - int min_e = -1, min_e_m = -1, min_e_n = -1; + int m, n, r, scaled_max_m; + unsigned long scaled_rt_rp; + unsigned long new_rate = 0; struct dpll_data *dd; if (!clk || !clk->dpll_data) @@ -311,8 +282,8 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) dd = clk->dpll_data; - pr_debug("clock: starting DPLL round_rate for clock %s, target rate " - "%ld\n", clk->name, target_rate); + pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n", + clk->name, target_rate); scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR); scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR; @@ -347,39 +318,23 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) if (r == DPLL_MULT_UNDERFLOW) continue; - e = target_rate - new_rate; - pr_debug("clock: n = %d: m = %d: rate error is %d " - "(new_rate = %ld)\n", n, m, e, new_rate); + pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n", + clk->name, m, n, new_rate); - if (min_e == -1 || - min_e >= (int)(abs(e) - dd->rate_tolerance)) { - min_e = e; - min_e_m = m; - min_e_n = n; - - pr_debug("clock: found new least error %d\n", min_e); - - /* We found good settings -- bail out now */ - if (min_e <= dd->rate_tolerance) - break; + if (target_rate == new_rate) { + dd->last_rounded_m = m; + dd->last_rounded_n = n; + dd->last_rounded_rate = target_rate; + break; } } - if (min_e < 0) { - pr_debug("clock: error: target rate or tolerance too low\n"); + if (target_rate != new_rate) { + pr_debug("clock: %s: cannot round to rate %ld\n", clk->name, + target_rate); return ~0; } - dd->last_rounded_m = min_e_m; - dd->last_rounded_n = min_e_n; - dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->rate, - min_e_m, min_e_n); - - pr_debug("clock: final least error: e = %d, m = %d, n = %d\n", - min_e, min_e_m, min_e_n); - pr_debug("clock: final rate: %ld (target rate: %ld)\n", - dd->last_rounded_rate, target_rate); - - return dd->last_rounded_rate; + return target_rate; } diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 70f8b073e69f..62cfd6cc7461 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -18,9 +18,6 @@ #include -/* The maximum error between a target DPLL rate and the rounded rate in Hz */ -#define DEFAULT_DPLL_RATE_TOLERANCE 50000 - /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */ #define CORE_CLK_SRC_32K 0x0 #define CORE_CLK_SRC_DPLL 0x1 @@ -55,7 +52,6 @@ void omap2_clk_disable(struct clk *clk); long omap2_clk_round_rate(struct clk *clk, unsigned long rate); int omap2_clk_set_rate(struct clk *clk, unsigned long rate); int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent); -int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance); long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate); unsigned long omap3_dpll_recalc(struct clk *clk); unsigned long omap3_clkoutx2_recalc(struct clk *clk); diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 6e9d20dc8649..22eeafc89b9f 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -116,7 +116,6 @@ static struct dpll_data dpll_dd = { .max_multiplier = 1023, .min_divider = 1, .max_divider = 16, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; /* diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 3378dbf8bace..df4cac5fef06 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -116,7 +116,6 @@ static struct dpll_data dpll_dd = { .max_multiplier = 1023, .min_divider = 1, .max_divider = 16, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; /* diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 305b5f75c44f..3dbeb3a5813d 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -291,7 +291,6 @@ static struct dpll_data dpll1_dd = { .max_multiplier = OMAP3_MAX_DPLL_MULT, .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; static struct clk dpll1_ck = { @@ -364,7 +363,6 @@ static struct dpll_data dpll2_dd = { .max_multiplier = OMAP3_MAX_DPLL_MULT, .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; static struct clk dpll2_ck = { @@ -424,7 +422,6 @@ static struct dpll_data dpll3_dd = { .max_multiplier = OMAP3_MAX_DPLL_MULT, .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; static struct clk dpll3_ck = { @@ -583,7 +580,6 @@ static struct dpll_data dpll4_dd_34xx __initdata = { .max_multiplier = OMAP3_MAX_DPLL_MULT, .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; static struct dpll_data dpll4_dd_3630 __initdata = { @@ -607,7 +603,6 @@ static struct dpll_data dpll4_dd_3630 __initdata = { .max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT, .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE, .flags = DPLL_J_TYPE }; @@ -939,7 +934,6 @@ static struct dpll_data dpll5_dd = { .max_multiplier = OMAP3_MAX_DPLL_MULT, .min_divider = 1, .max_divider = OMAP3_MAX_DPLL_DIV, - .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE }; static struct clk dpll5_ck = { diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index dcd7bb81420d..006e599c6613 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -109,7 +109,6 @@ struct clksel { * @clk_ref: struct clk pointer to the clock's reference clock input * @control_reg: register containing the DPLL mode bitfield * @enable_mask: mask of the DPLL mode bitfield in @control_reg - * @rate_tolerance: maximum variance allowed from target rate (in Hz) * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate() * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate() * @max_multiplier: maximum valid non-bypass multiplier value (actual) @@ -135,12 +134,9 @@ struct clksel { * XXX Some DPLLs have multiple bypass inputs, so it's not technically * correct to only have one @clk_bypass pointer. * - * XXX @rate_tolerance should probably be deprecated - currently there - * don't seem to be any usecases for DPLL rounding that is not exact. - * * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m, * @last_rounded_n) should be separated from the runtime-fixed fields - * and placed into a differenct structure, so that the runtime-fixed data + * and placed into a different structure, so that the runtime-fixed data * can be placed into read-only space. */ struct dpll_data { @@ -151,7 +147,6 @@ struct dpll_data { struct clk *clk_ref; void __iomem *control_reg; u32 enable_mask; - unsigned int rate_tolerance; unsigned long last_rounded_rate; u16 last_rounded_m; u16 max_multiplier; From 224113969dc9cc7a55f69da4dde5dc3fd1bbeb76 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 15:52:04 -0700 Subject: [PATCH 43/62] OMAP2xxx: clock: remove dsp_irate_ick After commit 81b34fbecbfbf24ed95c2d80d5cb14149652408f ("OMAP2 clock: split OMAP2420, OMAP2430 clock data into their own files"), it's possible to remove dsp_irate_ick from the OMAP2420 and OMAP2430 clock files. It was originally only needed due to a 2420/2430 clock tree difference, and now that the data is in separate files, it's superfluous. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock.h | 1 + arch/arm/mach-omap2/clock2420_data.c | 31 +++++++------------------ arch/arm/mach-omap2/clock2430_data.c | 31 +++++++------------------ arch/arm/mach-omap2/clock_common_data.c | 6 +++++ 4 files changed, 23 insertions(+), 46 deletions(-) diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 62cfd6cc7461..e10ff2b54844 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -139,6 +139,7 @@ extern struct clk *vclk, *sclk; extern const struct clksel_rate gpt_32k_rates[]; extern const struct clksel_rate gpt_sys_rates[]; extern const struct clksel_rate gfx_l3_rates[]; +extern const struct clksel_rate dsp_ick_rates[]; #if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ) extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table); diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 22eeafc89b9f..53bd999c63ae 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -454,36 +454,22 @@ static struct clk dsp_fck = { .recalc = &omap2_clksel_recalc, }; -/* DSP interface clock */ -static const struct clksel_rate dsp_irate_ick_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_24XX }, - { .div = 2, .val = 2, .flags = RATE_IN_24XX }, - { .div = 0 }, -}; - -static const struct clksel dsp_irate_ick_clksel[] = { - { .parent = &dsp_fck, .rates = dsp_irate_ick_rates }, +static const struct clksel dsp_ick_clksel[] = { + { .parent = &dsp_fck, .rates = dsp_ick_rates }, { .parent = NULL } }; -/* This clock does not exist as such in the TRM. */ -static struct clk dsp_irate_ick = { - .name = "dsp_irate_ick", - .ops = &clkops_null, - .parent = &dsp_fck, - .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL), - .clksel_mask = OMAP24XX_CLKSEL_DSP_IF_MASK, - .clksel = dsp_irate_ick_clksel, - .recalc = &omap2_clksel_recalc, -}; - -/* 2420 only */ static struct clk dsp_ick = { .name = "dsp_ick", /* apparently ipi and isp */ .ops = &clkops_omap2_iclk_dflt_wait, - .parent = &dsp_irate_ick, + .parent = &dsp_fck, + .clkdm_name = "dsp_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN), .enable_bit = OMAP2420_EN_DSP_IPI_SHIFT, /* for ipi */ + .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL), + .clksel_mask = OMAP24XX_CLKSEL_DSP_IF_MASK, + .clksel = dsp_ick_clksel, + .recalc = &omap2_clksel_recalc, }; /* @@ -1812,7 +1798,6 @@ static struct omap_clk omap2420_clks[] = { CLK(NULL, "mpu_ck", &mpu_ck, CK_242X), /* dsp domain clocks */ CLK(NULL, "dsp_fck", &dsp_fck, CK_242X), - CLK(NULL, "dsp_irate_ick", &dsp_irate_ick, CK_242X), CLK(NULL, "dsp_ick", &dsp_ick, CK_242X), CLK(NULL, "iva1_ifck", &iva1_ifck, CK_242X), CLK(NULL, "iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X), diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index df4cac5fef06..36dde2635acb 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -433,37 +433,23 @@ static struct clk dsp_fck = { .recalc = &omap2_clksel_recalc, }; -/* DSP interface clock */ -static const struct clksel_rate dsp_irate_ick_rates[] = { - { .div = 1, .val = 1, .flags = RATE_IN_24XX }, - { .div = 2, .val = 2, .flags = RATE_IN_24XX }, - { .div = 3, .val = 3, .flags = RATE_IN_243X }, - { .div = 0 }, -}; - -static const struct clksel dsp_irate_ick_clksel[] = { - { .parent = &dsp_fck, .rates = dsp_irate_ick_rates }, +static const struct clksel dsp_ick_clksel[] = { + { .parent = &dsp_fck, .rates = dsp_ick_rates }, { .parent = NULL } }; -/* This clock does not exist as such in the TRM. */ -static struct clk dsp_irate_ick = { - .name = "dsp_irate_ick", - .ops = &clkops_null, - .parent = &dsp_fck, - .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL), - .clksel_mask = OMAP24XX_CLKSEL_DSP_IF_MASK, - .clksel = dsp_irate_ick_clksel, - .recalc = &omap2_clksel_recalc, -}; - /* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */ static struct clk iva2_1_ick = { .name = "iva2_1_ick", .ops = &clkops_omap2_dflt_wait, - .parent = &dsp_irate_ick, + .parent = &dsp_fck, + .clkdm_name = "dsp_clkdm", .enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN), .enable_bit = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT, + .clksel_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL), + .clksel_mask = OMAP24XX_CLKSEL_DSP_IF_MASK, + .clksel = dsp_ick_clksel, + .recalc = &omap2_clksel_recalc, }; /* @@ -1900,7 +1886,6 @@ static struct omap_clk omap2430_clks[] = { CLK(NULL, "mpu_ck", &mpu_ck, CK_243X), /* dsp domain clocks */ CLK(NULL, "dsp_fck", &dsp_fck, CK_243X), - CLK(NULL, "dsp_irate_ick", &dsp_irate_ick, CK_243X), CLK(NULL, "iva2_1_ick", &iva2_1_ick, CK_243X), /* GFX domain clocks */ CLK(NULL, "gfx_3d_fck", &gfx_3d_fck, CK_243X), diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c index 1cf8131205fa..6424d46be14a 100644 --- a/arch/arm/mach-omap2/clock_common_data.c +++ b/arch/arm/mach-omap2/clock_common_data.c @@ -37,3 +37,9 @@ const struct clksel_rate gfx_l3_rates[] = { { .div = 0 } }; +const struct clksel_rate dsp_ick_rates[] = { + { .div = 1, .val = 1, .flags = RATE_IN_24XX }, + { .div = 2, .val = 2, .flags = RATE_IN_24XX }, + { .div = 3, .val = 3, .flags = RATE_IN_243X }, + { .div = 0 }, +}; From 691abf525d3d215f2e4eab7a015ef2b6375c58a5 Mon Sep 17 00:00:00 2001 From: Sanjeev Premi Date: Fri, 11 Feb 2011 09:05:00 +0000 Subject: [PATCH 44/62] omap2/3: clockdomains: fix compile-time warnings This patch fixes these warnings when building kernel for OMAP3EVM only. CC arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.o arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c:95: warning: 'dsp_24xx_wkdeps' defined but not used arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c:119: warning: 'mpu_24xx_wkdeps' defined but not used arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c:147: warning: 'core_24xx_wkdeps' defined but not used The problem should be noticed when building for other OMAP3 platforms (only) as well. Signed-off-by: Sanjeev Premi Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c index ffdfe54f3264..13bde95b6790 100644 --- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c +++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c @@ -89,6 +89,8 @@ static struct clkdm_dep gfx_sgx_wkdeps[] = { /* 24XX-specific possible dependencies */ +#ifdef CONFIG_ARCH_OMAP2 + /* Wakeup dependency source arrays */ /* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */ @@ -168,6 +170,7 @@ static struct clkdm_dep core_24xx_wkdeps[] = { { NULL }, }; +#endif /* CONFIG_ARCH_OMAP2 */ /* 2430-specific possible wakeup dependencies */ From a4fc92748e969b1312f283b0d1baf657329f2907 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 14:53:40 -0700 Subject: [PATCH 45/62] OMAP2xxx: clock: fix clockdomains on gpt7_ick, 2430 mmchs2_fck clocks Add a clockdomain to the GPTIMER7 interface and 2430 HSMMC2 functional clocks - both were previously missing them. Also, the 2430 mmchs1_fck is in core_l3_clkdm, but should be in core_l4_clkdm; fix this. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock2420_data.c | 1 + arch/arm/mach-omap2/clock2430_data.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 53bd999c63ae..5e80d3dc274c 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -987,6 +987,7 @@ static struct clk gpt7_ick = { .name = "gpt7_ick", .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT7_SHIFT, .recalc = &followparent_recalc, diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 36dde2635acb..8957fc6f64e5 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -975,6 +975,7 @@ static struct clk gpt7_ick = { .name = "gpt7_ick", .ops = &clkops_omap2_iclk_dflt_wait, .parent = &l4_ck, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), .enable_bit = OMAP24XX_EN_GPT7_SHIFT, .recalc = &followparent_recalc, @@ -1747,7 +1748,7 @@ static struct clk mmchs1_fck = { .name = "mmchs1_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, - .clkdm_name = "core_l3_clkdm", + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MMCHS1_SHIFT, .recalc = &followparent_recalc, @@ -1767,6 +1768,7 @@ static struct clk mmchs2_fck = { .name = "mmchs2_fck", .ops = &clkops_omap2_dflt_wait, .parent = &func_96m_ck, + .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), .enable_bit = OMAP2430_EN_MMCHS2_SHIFT, .recalc = &followparent_recalc, From 8c810e7e14457d97706d4c6de4bb4847e3715d1b Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Fri, 25 Feb 2011 13:56:40 -0700 Subject: [PATCH 46/62] OMAP2xxx: clock data: clean up some comments Minor cleanup of some clock data comments. No functional changes. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock2420_data.c | 23 ++++++++++------------- arch/arm/mach-omap2/clock2430_data.c | 23 ++++++++++------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index 5e80d3dc274c..b6f65d4ac97d 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -1,12 +1,12 @@ /* - * linux/arch/arm/mach-omap2/clock2420_data.c + * OMAP2420 clock data * - * Copyright (C) 2005-2009 Texas Instruments, Inc. - * Copyright (C) 2004-2011 Nokia Corporation + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * Copyright (C) 2004-2011 Nokia Corporation * - * Contacts: - * Richard Woodruff - * Paul Walmsley + * Contacts: + * Richard Woodruff + * Paul Walmsley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -34,18 +34,15 @@ /* * 2420 clock tree. * - * NOTE:In many cases here we are assigning a 'default' parent. In many - * cases the parent is selectable. The get/set parent calls will also - * switch sources. - * - * Many some clocks say always_enabled, but they can be auto idled for - * power savings. They will always be available upon clock request. + * NOTE:In many cases here we are assigning a 'default' parent. In + * many cases the parent is selectable. The set parent calls will + * also switch sources. * * Several sources are given initial rates which may be wrong, this will * be fixed up in the init func. * * Things are broadly separated below by clock domains. It is - * noteworthy that most periferals have dependencies on multiple clock + * noteworthy that most peripherals have dependencies on multiple clock * domains. Many get their interface clocks from the L4 domain, but get * functional clocks from fixed sources or other core domain derived * clocks. diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index 8957fc6f64e5..5c2a075fd82c 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -1,12 +1,12 @@ /* - * linux/arch/arm/mach-omap2/clock2430_data.c + * OMAP2430 clock data * - * Copyright (C) 2005-2009 Texas Instruments, Inc. - * Copyright (C) 2004-2011 Nokia Corporation + * Copyright (C) 2005-2009 Texas Instruments, Inc. + * Copyright (C) 2004-2011 Nokia Corporation * - * Contacts: - * Richard Woodruff - * Paul Walmsley + * Contacts: + * Richard Woodruff + * Paul Walmsley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -34,18 +34,15 @@ /* * 2430 clock tree. * - * NOTE:In many cases here we are assigning a 'default' parent. In many - * cases the parent is selectable. The get/set parent calls will also - * switch sources. - * - * Many some clocks say always_enabled, but they can be auto idled for - * power savings. They will always be available upon clock request. + * NOTE:In many cases here we are assigning a 'default' parent. In + * many cases the parent is selectable. The set parent calls will + * also switch sources. * * Several sources are given initial rates which may be wrong, this will * be fixed up in the init func. * * Things are broadly separated below by clock domains. It is - * noteworthy that most periferals have dependencies on multiple clock + * noteworthy that most peripherals have dependencies on multiple clock * domains. Many get their interface clocks from the L4 domain, but get * functional clocks from fixed sources or other core domain derived * clocks. From b481cea34bb41f3731567c8c1be0625bf80d20b7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 9 Mar 2011 18:44:28 -0700 Subject: [PATCH 47/62] OMAP: clock: fix compile warning if building kernels without OMAP2 support, we will see a warning such as: arch/arm/mach-omap2/io.c: In function 'omap2_init_common_infrastructure': arch/arm/mach-omap2/io.c:389:3: warning: statement with no effect arch/arm/mach-omap2/io.c:391:3: warning: statement with no effect Signed-off-by: Felipe Balbi Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock2xxx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h index cc5c8d422c5b..cb6df8ca9e4a 100644 --- a/arch/arm/mach-omap2/clock2xxx.h +++ b/arch/arm/mach-omap2/clock2xxx.h @@ -23,13 +23,13 @@ void omap2xxx_clk_prepare_for_reboot(void); #ifdef CONFIG_SOC_OMAP2420 int omap2420_clk_init(void); #else -#define omap2420_clk_init() 0 +#define omap2420_clk_init() do { } while(0) #endif #ifdef CONFIG_SOC_OMAP2430 int omap2430_clk_init(void); #else -#define omap2430_clk_init() 0 +#define omap2430_clk_init() do { } while(0) #endif extern void __iomem *prcm_clksrc_ctrl, *cm_idlest_pll; From 692ab1f36b714250a9669e10e5acceba72707956 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Wed, 9 Mar 2011 18:44:28 -0700 Subject: [PATCH 48/62] MAINTAINERS: add entry for OMAP powerdomain/clockdomain per-SoC layer support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Rajendra Nayak and myself as maintainers for the OMAP powerdomain/clockdomain per-SoC layer code. Signed-off-by: Rajendra Nayak Signed-off-by: Kevin Hilman Signed-off-by: Paul Walmsley Signed-off-by: Benoît Cousson Signed-off-by: Tony Lindgren --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8afba6321e24..04ed9565ad85 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4496,6 +4496,16 @@ L: linux-omap@vger.kernel.org S: Maintained F: arch/arm/*omap*/*pm* +OMAP POWERDOMAIN/CLOCKDOMAIN SOC ADAPTATION LAYER SUPPORT +M: Rajendra Nayak +M: Paul Walmsley +L: linux-omap@vger.kernel.org +S: Maintained +F: arch/arm/mach-omap2/powerdomain2xxx_3xxx.c +F: arch/arm/mach-omap2/powerdomain44xx.c +F: arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +F: arch/arm/mach-omap2/clockdomain44xx.c + OMAP AUDIO SUPPORT M: Jarkko Nikula L: alsa-devel@alsa-project.org (subscribers-only) From b9ccf8afe2d2eafe18f90d2925f8464313fe0b56 Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Thu, 10 Mar 2011 10:53:15 +0100 Subject: [PATCH 49/62] OMAP3: hwmod data: Fix incorrect SmartReflex -> L4 CORE interconnect links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit d34427267186827dfd62bd8cf726601fffb22534 ("OMAP3: PM: Adding smartreflex hwmod data") added data that claims that the L4 CORE has two slave interfaces that originate from the SmartReflex modules, omap3_l4_core__sr1 and omap3_l4_core__sr2. But as those two data structure records show, it's L4 CORE that has a master port towards SR1 and SR2. Move the incorrect data from slaves list to master list. Based on a path by Paul Walmsley https://patchwork.kernel.org/patch/623171/ That is based on a patch by Benoît Cousson : https://patchwork.kernel.org/patch/590561/ Signed-off-by: Paul Walmsley Signed-off-by: Benoît Cousson Cc: Sanjeev Premi Cc: Thara Gopinath --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index c4ca005f8bb5..dec329ff0924 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -491,8 +491,6 @@ static struct omap_hwmod_ocp_if *am35xx_usbhsotg_slaves[] = { /* Slave interfaces on the L4_CORE interconnect */ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = { &omap3xxx_l3_main__l4_core, - &omap3_l4_core__sr1, - &omap3_l4_core__sr2, }; /* Master interfaces on the L4_CORE interconnect */ @@ -503,6 +501,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = { &omap3_l4_core__i2c1, &omap3_l4_core__i2c2, &omap3_l4_core__i2c3, + &omap3_l4_core__sr1, + &omap3_l4_core__sr2, }; /* L4 CORE */ From 478f478bc1a58f97f09fd2048488bafdfa9d8fce Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Fri, 25 Feb 2011 17:46:33 +0100 Subject: [PATCH 50/62] OMAP3: hwmod data: Remove masters port links for interconnects. Master ports from interconnect are generating some annoying circular references that become tricky to handle if we have to dynamically remove some IP on some variant platforms. Since they are not used for the moment, and since we can still build that relation using the reverse relation (slave port from the IP toward master port of the interconnect), let remove them for the moment like it is done on OMAP4. Signed-off-by: Benoit Cousson Cc: Paul Walmsley Cc: Sanjeev Premi --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 28 ---------------------- 1 file changed, 28 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index dec329ff0924..229eb94d3434 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -493,24 +493,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = { &omap3xxx_l3_main__l4_core, }; -/* Master interfaces on the L4_CORE interconnect */ -static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = { - &omap3xxx_l4_core__l4_wkup, - &omap3_l4_core__uart1, - &omap3_l4_core__uart2, - &omap3_l4_core__i2c1, - &omap3_l4_core__i2c2, - &omap3_l4_core__i2c3, - &omap3_l4_core__sr1, - &omap3_l4_core__sr2, -}; - /* L4 CORE */ static struct omap_hwmod omap3xxx_l4_core_hwmod = { .name = "l4_core", .class = &l4_hwmod_class, - .masters = omap3xxx_l4_core_masters, - .masters_cnt = ARRAY_SIZE(omap3xxx_l4_core_masters), .slaves = omap3xxx_l4_core_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_l4_core_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -522,18 +508,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_per_slaves[] = { &omap3xxx_l3_main__l4_per, }; -/* Master interfaces on the L4_PER interconnect */ -static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = { - &omap3_l4_per__uart3, - &omap3_l4_per__uart4, -}; - /* L4 PER */ static struct omap_hwmod omap3xxx_l4_per_hwmod = { .name = "l4_per", .class = &l4_hwmod_class, - .masters = omap3xxx_l4_per_masters, - .masters_cnt = ARRAY_SIZE(omap3xxx_l4_per_masters), .slaves = omap3xxx_l4_per_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_l4_per_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), @@ -545,16 +523,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_slaves[] = { &omap3xxx_l4_core__l4_wkup, }; -/* Master interfaces on the L4_WKUP interconnect */ -static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_masters[] = { -}; - /* L4 WKUP */ static struct omap_hwmod omap3xxx_l4_wkup_hwmod = { .name = "l4_wkup", .class = &l4_hwmod_class, - .masters = omap3xxx_l4_wkup_masters, - .masters_cnt = ARRAY_SIZE(omap3xxx_l4_wkup_masters), .slaves = omap3xxx_l4_wkup_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_l4_wkup_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), From 8985b63d072413f0446fd2d0d654795f2d683323 Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Thu, 3 Mar 2011 14:22:46 -0700 Subject: [PATCH 51/62] OMAP2+: hwmod: fix incorrect computation of autoidle_mask Autoidle is a single bit, TIOCP_CFG[0], setting on OMAP1/2/3/4 platforms. In _set_module_autoidle() I am seeing 0x3 value where the mask is computed. This should be 0x1. v2: (1) Modified the subject. (2) Modified the description with further specific information. Baseline: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git Tested Info: Boot tested on OMAP 1/2/3/4. Signed-off-by: Tarun Kanti DebBarma Acked-by: Rajendra Nayak Acked-by: Benoit Cousson Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index e282e35769fd..b18c36b1060f 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -373,7 +373,7 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, } autoidle_shift = oh->class->sysc->sysc_fields->autoidle_shift; - autoidle_mask = (0x3 << autoidle_shift); + autoidle_mask = (0x1 << autoidle_shift); *v &= ~autoidle_mask; *v |= autoidle << autoidle_shift; From d73d65fab1c29c3c0f9736aed9cb55ea53843b00 Mon Sep 17 00:00:00 2001 From: "Avinash.H.M" Date: Thu, 3 Mar 2011 14:22:46 -0700 Subject: [PATCH 52/62] omap: hwmod: add syss reset done flags to omap2, omap3 hwmods Some of the omap2, omap3 peripherals support software reset. This can be done through the softreset bit in sysconfig register. The reset status can be checked through resetdone bit of sysstatus register. syss_has_reset_status is added to the hwmod database of peripherals which have resetdone bit in sysstatus register. Cc: Rajendra Nayak Cc: Paul Walmsley Cc: Benoit Cousson Cc: Kevin Hilman Reviewed-by: Govindraj.R Signed-off-by: Avinash.H.M Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_2420_data.c | 11 ++++++----- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 12 +++++++----- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 13 ++++++++----- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index b85c630b64d6..e8046b4ec6a4 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -308,7 +308,7 @@ static struct omap_hwmod_class_sysconfig omap2420_wd_timer_sysc = { .sysc_offs = 0x0010, .syss_offs = 0x0014, .sysc_flags = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET | - SYSC_HAS_AUTOIDLE), + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -349,7 +349,7 @@ static struct omap_hwmod_class_sysconfig uart_sysc = { .syss_offs = 0x58, .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | - SYSC_HAS_AUTOIDLE), + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -475,7 +475,7 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = { .rev_offs = 0x00, .sysc_offs = 0x20, .syss_offs = 0x10, - .sysc_flags = SYSC_HAS_SOFTRESET, + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -647,7 +647,8 @@ static struct omap_hwmod_class_sysconfig omap242x_gpio_sysc = { .sysc_offs = 0x0010, .syss_offs = 0x0014, .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | + SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -789,7 +790,7 @@ static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = { .syss_offs = 0x0028, .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE | - SYSC_HAS_AUTOIDLE), + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 8ecfbcde13ba..115eed51b521 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -307,7 +307,7 @@ static struct omap_hwmod_class_sysconfig omap2430_wd_timer_sysc = { .sysc_offs = 0x0010, .syss_offs = 0x0014, .sysc_flags = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET | - SYSC_HAS_AUTOIDLE), + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -348,7 +348,7 @@ static struct omap_hwmod_class_sysconfig uart_sysc = { .syss_offs = 0x58, .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | - SYSC_HAS_AUTOIDLE), + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -474,7 +474,8 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = { .rev_offs = 0x00, .sysc_offs = 0x20, .syss_offs = 0x10, - .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | + SYSS_HAS_RESET_STATUS), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -672,7 +673,8 @@ static struct omap_hwmod_class_sysconfig omap243x_gpio_sysc = { .sysc_offs = 0x0010, .syss_offs = 0x0014, .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | + SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -844,7 +846,7 @@ static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = { .syss_offs = 0x0028, .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE | - SYSC_HAS_AUTOIDLE), + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 8d8181334f86..acf0d54024ab 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -447,7 +447,8 @@ static struct omap_hwmod_class_sysconfig omap3xxx_wd_timer_sysc = { .syss_offs = 0x0014, .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | - SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY), + SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | + SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -459,7 +460,7 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = { .syss_offs = 0x10, .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | - SYSC_HAS_AUTOIDLE), + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -501,7 +502,7 @@ static struct omap_hwmod_class_sysconfig uart_sysc = { .syss_offs = 0x58, .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | - SYSC_HAS_AUTOIDLE), + SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -902,7 +903,8 @@ static struct omap_hwmod_class_sysconfig omap3xxx_gpio_sysc = { .sysc_offs = 0x0010, .syss_offs = 0x0014, .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | - SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | + SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -1156,7 +1158,8 @@ static struct omap_hwmod_class_sysconfig omap3xxx_dma_sysc = { .syss_offs = 0x0028, .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY | - SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE), + SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE | + SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), .sysc_fields = &omap_hwmod_sysc_type1, From 09c35f2fee8a8633dde7b8b588b1cb496eb220a1 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Wed, 16 Feb 2011 12:11:24 +0000 Subject: [PATCH 53/62] OMAP2+: hwmod: Fix what _init_clock returns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _init_clock always returns 0 and does not propogate the error (in case of failure) back to the caller, causing _init_clocks to fail silently. Signed-off-by: Rajendra Nayak Acked-by: Benoît Cousson Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index b18c36b1060f..2146d9aa507a 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -926,7 +926,7 @@ static int _init_clocks(struct omap_hwmod *oh, void *data) if (!ret) oh->_state = _HWMOD_STATE_CLKS_INITED; - return 0; + return ret; } /** From 4d2274c543e78a267989da5f9b12e223cd87839f Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 3 Mar 2011 15:22:42 -0700 Subject: [PATCH 54/62] OMAP2+: hwmod: fix a documentation bug with HWMOD_NO_OCP_AUTOIDLE The documented name of the HWMOD_NO_OCP_AUTOIDLE flag was incorrect; fix it. Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 1eee85a8abb3..5924ecdfb95a 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -372,7 +372,7 @@ struct omap_hwmod_omap4_prcm { * SDRAM controller, etc. XXX probably belongs outside the main hwmod file * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM * controller, etc. XXX probably belongs outside the main hwmod file - * HWMOD_NO_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE) + * HWMOD_NO_OCP_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE) * when module is enabled, rather than the default, which is to * enable autoidle * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup From cc1226e7635011c7dd1e786770ed51ee751800f2 Mon Sep 17 00:00:00 2001 From: omar ramirez Date: Fri, 4 Mar 2011 13:32:44 -0700 Subject: [PATCH 55/62] OMAP2+: hwmod: use status bit info for reset line On OMAP2 and OMAP3 the reset ctrl shift doesn't match the status bit, as it does on OMAP4, when handling the reset lines. This patch adds a new member in the reset info structure, so now it can be added as part of hwmod data, and checked accordingly for OMAP2 or 3; otherwise, there could be cases when the shift masks doesn't match both of the registers, and a successful reset might throw an error message or vice versa. Signed-off-by: Omar Ramirez Luna [paul@pwsan.com: added a warning if st_shift used on OMAP4; renamed 'r' variable; improved some documentation] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 75 +++++++++++--------- arch/arm/mach-omap2/prm2xxx_3xxx.c | 18 ++--- arch/arm/mach-omap2/prm2xxx_3xxx.h | 5 +- arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 + 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 2146d9aa507a..005264779f8d 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -972,25 +972,29 @@ static int _wait_target_ready(struct omap_hwmod *oh) } /** - * _lookup_hardreset - return the register bit shift for this hwmod/reset line + * _lookup_hardreset - fill register bit info for this hwmod/reset line * @oh: struct omap_hwmod * * @name: name of the reset line in the context of this hwmod + * @ohri: struct omap_hwmod_rst_info * that this function will fill in * * Return the bit position of the reset line that match the * input name. Return -ENOENT if not found. */ -static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name) +static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name, + struct omap_hwmod_rst_info *ohri) { int i; for (i = 0; i < oh->rst_lines_cnt; i++) { const char *rst_line = oh->rst_lines[i].name; if (!strcmp(rst_line, name)) { - u8 shift = oh->rst_lines[i].rst_shift; - pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n", - oh->name, rst_line, shift); + ohri->rst_shift = oh->rst_lines[i].rst_shift; + ohri->st_shift = oh->rst_lines[i].st_shift; + pr_debug("omap_hwmod: %s: %s: %s: rst %d st %d\n", + oh->name, __func__, rst_line, ohri->rst_shift, + ohri->st_shift); - return shift; + return 0; } } @@ -1009,21 +1013,22 @@ static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name) */ static int _assert_hardreset(struct omap_hwmod *oh, const char *name) { - u8 shift; + struct omap_hwmod_rst_info ohri; + u8 ret; if (!oh) return -EINVAL; - shift = _lookup_hardreset(oh, name); - if (IS_ERR_VALUE(shift)) - return shift; + ret = _lookup_hardreset(oh, name, &ohri); + if (IS_ERR_VALUE(ret)) + return ret; if (cpu_is_omap24xx() || cpu_is_omap34xx()) return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs, - shift); + ohri.rst_shift); else if (cpu_is_omap44xx()) return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg, - shift); + ohri.rst_shift); else return -EINVAL; } @@ -1040,29 +1045,34 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name) */ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) { - u8 shift; - int r; + struct omap_hwmod_rst_info ohri; + int ret; if (!oh) return -EINVAL; - shift = _lookup_hardreset(oh, name); - if (IS_ERR_VALUE(shift)) - return shift; + ret = _lookup_hardreset(oh, name, &ohri); + if (IS_ERR_VALUE(ret)) + return ret; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs, - shift); - else if (cpu_is_omap44xx()) - r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg, - shift); - else + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { + ret = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs, + ohri.rst_shift, + ohri.st_shift); + } else if (cpu_is_omap44xx()) { + if (ohri.st_shift) + pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n", + oh->name, name); + ret = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg, + ohri.rst_shift); + } else { return -EINVAL; + } - if (r == -EBUSY) + if (ret == -EBUSY) pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name); - return r; + return ret; } /** @@ -1075,21 +1085,22 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name) */ static int _read_hardreset(struct omap_hwmod *oh, const char *name) { - u8 shift; + struct omap_hwmod_rst_info ohri; + u8 ret; if (!oh) return -EINVAL; - shift = _lookup_hardreset(oh, name); - if (IS_ERR_VALUE(shift)) - return shift; + ret = _lookup_hardreset(oh, name, &ohri); + if (IS_ERR_VALUE(ret)) + return ret; if (cpu_is_omap24xx() || cpu_is_omap34xx()) { return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs, - shift); + ohri.st_shift); } else if (cpu_is_omap44xx()) { return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg, - shift); + ohri.rst_shift); } else { return -EINVAL; } diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index ec0362574b5e..051213fbc346 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -118,7 +118,8 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift) /** * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait * @prm_mod: PRM submodule base (e.g. CORE_MOD) - * @shift: register bit shift corresponding to the reset line to deassert + * @rst_shift: register bit shift corresponding to the reset line to deassert + * @st_shift: register bit shift for the status of the deasserted submodule * * Some IPs like dsp or iva contain processors that require an HW * reset line to be asserted / deasserted in order to fully enable the @@ -129,27 +130,28 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift) * -EINVAL upon an argument error, -EEXIST if the submodule was already out * of reset, or -EBUSY if the submodule did not exit reset promptly. */ -int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift) +int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift) { - u32 mask; + u32 rst, st; int c; if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) return -EINVAL; - mask = 1 << shift; + rst = 1 << rst_shift; + st = 1 << st_shift; /* Check the current status to avoid de-asserting the line twice */ - if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0) + if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, rst) == 0) return -EEXIST; /* Clear the reset status by writing 1 to the status bit */ - omap2_prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST); + omap2_prm_rmw_mod_reg_bits(0xffffffff, st, prm_mod, OMAP2_RM_RSTST); /* de-assert the reset control line */ - omap2_prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL); + omap2_prm_rmw_mod_reg_bits(rst, 0, prm_mod, OMAP2_RM_RSTCTRL); /* wait the status to be set */ omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST, - mask), + st), MAX_MODULE_HARDRESET_WAIT, c); return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h index 49654c8d18f5..a1fc62a39dbb 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h @@ -282,7 +282,8 @@ static inline int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift) "not suppose to be used on omap4\n"); return 0; } -static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift) +static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, + u8 st_shift) { WARN(1, "prm: omap2xxx/omap3xxx specific function and " "not suppose to be used on omap4\n"); @@ -300,7 +301,7 @@ extern u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask); /* These omap2_ PRM functions apply to both OMAP2 and 3 */ extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift); extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift); -extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift); +extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift); #endif /* CONFIG_ARCH_OMAP4 */ #endif diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 5924ecdfb95a..78f1cc88ff06 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -124,6 +124,7 @@ struct omap_hwmod_dma_info { * struct omap_hwmod_rst_info - IPs reset lines use by hwmod * @name: name of the reset line (module local name) * @rst_shift: Offset of the reset bit + * @st_shift: Offset of the reset status bit (OMAP2/3 only) * * @name should be something short, e.g., "cpu0" or "rst". It is defined * locally to the hwmod. @@ -131,6 +132,7 @@ struct omap_hwmod_dma_info { struct omap_hwmod_rst_info { const char *name; u8 rst_shift; + u8 st_shift; }; /** From 43b01643355672a266b95c4719f47cd1abac4680 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 10 Mar 2011 03:50:07 -0700 Subject: [PATCH 56/62] OMAP2+: hwmod: allow board files to prevent devices from being reset upon init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some boards can't tolerate IP blocks being reset when they are initialized. Michael Büsch cites a case with the Nokia N810: http://www.spinics.net/lists/linux-omap/msg47277.html To allow such boards to continue working normally, allow board file maintainers to mark IP blocks to prevent them from being reset upon init. This is done via a hwmod function, omap_hwmod_no_setup_reset(). Signed-off-by: Paul Walmsley Cc: Michael Buesch --- arch/arm/mach-omap2/omap_hwmod.c | 26 ++++++++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index e282e35769fd..816aeb97ba28 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -2218,3 +2218,29 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh) return ret; } + +/** + * omap_hwmod_no_setup_reset - prevent a hwmod from being reset upon setup + * @oh: struct omap_hwmod * + * + * Prevent the hwmod @oh from being reset during the setup process. + * Intended for use by board-*.c files on boards with devices that + * cannot tolerate being reset. Must be called before the hwmod has + * been set up. Returns 0 upon success or negative error code upon + * failure. + */ +int omap_hwmod_no_setup_reset(struct omap_hwmod *oh) +{ + if (!oh) + return -EINVAL; + + if (oh->_state != _HWMOD_STATE_REGISTERED) { + pr_err("omap_hwmod: %s: cannot prevent setup reset; in wrong state\n", + oh->name); + return -EINVAL; + } + + oh->flags |= HWMOD_INIT_NO_RESET; + + return 0; +} diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 1eee85a8abb3..bba234337d00 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -589,6 +589,8 @@ int omap_hwmod_for_each_by_class(const char *classname, int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state); u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh); +int omap_hwmod_no_setup_reset(struct omap_hwmod *oh); + /* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out From 9599217a06da5f5a95794ca9192c14317d441187 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 10 Mar 2011 03:50:08 -0700 Subject: [PATCH 57/62] OMAP2+: hwmod: add API to handle autoidle mode Create a new API that forms a wrapper to _set_module_autoidle() to modify the AUTOIDLE bit. This API is intended to be used by drivers that requires direct manipulation of the AUTOIDLE bits in SYSCONFIG register. McBSP driver requires autoidle bit to be enabled/disabled while using sidetone feature. Signed-off-by: Kishon Vijay Abraham I Cc: Paul Walmsley Cc: Benoit Cousson [paul@pwsan.com: restrict the hwmod states that the autoidle bit can be changed in; changed function name; dropped "int" from "unsigned int long"] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 36 ++++++++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 + 2 files changed, 37 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 816aeb97ba28..a68a2cf1be34 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1287,6 +1287,42 @@ static int _idle(struct omap_hwmod *oh) return 0; } +/** + * omap_hwmod_set_ocp_autoidle - set the hwmod's OCP autoidle bit + * @oh: struct omap_hwmod * + * @autoidle: desired AUTOIDLE bitfield value (0 or 1) + * + * Sets the IP block's OCP autoidle bit in hardware, and updates our + * local copy. Intended to be used by drivers that require + * direct manipulation of the AUTOIDLE bits. + * Returns -EINVAL if @oh is null or is not in the ENABLED state, or passes + * along the return value from _set_module_autoidle(). + * + * Any users of this function should be scrutinized carefully. + */ +int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle) +{ + u32 v; + int retval = 0; + unsigned long flags; + + if (!oh || oh->_state != _HWMOD_STATE_ENABLED) + return -EINVAL; + + spin_lock_irqsave(&oh->_lock, flags); + + v = oh->_sysc_cache; + + retval = _set_module_autoidle(oh, autoidle, &v); + + if (!retval) + _write_sysconfig(v, oh); + + spin_unlock_irqrestore(&oh->_lock, flags); + + return retval; +} + /** * _shutdown - shutdown an omap_hwmod * @oh: struct omap_hwmod * diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index bba234337d00..98f7f618a91f 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -555,6 +555,7 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh); int omap_hwmod_disable_clocks(struct omap_hwmod *oh); int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode); +int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle); int omap_hwmod_reset(struct omap_hwmod *oh); void omap_hwmod_ocp_barrier(struct omap_hwmod *oh); From 570b54c7fae65b65320d5a7d4b2249c86eeaa497 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 10 Mar 2011 03:50:09 -0700 Subject: [PATCH 58/62] OMAP2+: clockdomain: add flag that will block autodeps from being added for a clockdomain Add a new clockdomain flag, CLKDM_NO_AUTODEPS, which, when marked on a clockdomain, will prevent "autodeps" from being associated with the clockdomain. ("Autodeps" are sleep dependencies and wakeup dependencies from/to processor modules that are automatically added to a clockdomain when it is in hardware-supervised idle mode. They are deprecated -- a relic from the old CDP trees -- but are still in use for OMAP3.) Also, prevent the hwmod code from adding or removing initiator dependencies for clockdomains with this flag set. This patch should allow others to test which clockdomains actually still need autodeps. Thanks to Kevin Hilman for noting that the original version should also modify the hwmod code. Signed-off-by: Paul Walmsley Cc: Kevin Hilman --- arch/arm/mach-omap2/clockdomain.c | 4 ++-- arch/arm/mach-omap2/clockdomain.h | 12 ++++++++++-- arch/arm/mach-omap2/omap_hwmod.c | 16 ++++++++++++---- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 58e42f76603f..2b4ab0beff48 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -181,7 +181,7 @@ static void _clkdm_add_autodeps(struct clockdomain *clkdm) { struct clkdm_autodep *autodep; - if (!autodeps) + if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS) return; for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { @@ -215,7 +215,7 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm) { struct clkdm_autodep *autodep; - if (!autodeps) + if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS) return; for (autodep = autodeps; autodep->clkdm.ptr; autodep++) { diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 9b459c26fb85..5add07169431 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -4,7 +4,7 @@ * OMAP2/3 clockdomain framework functions * * Copyright (C) 2008 Texas Instruments, Inc. - * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2008-2011 Nokia Corporation * * Paul Walmsley * @@ -22,11 +22,19 @@ #include #include -/* Clockdomain capability flags */ +/* + * Clockdomain flags + * + * XXX Document CLKDM_CAN_* flags + * + * CLKDM_NO_AUTODEPS: Prevent "autodeps" from being added/removed from this + * clockdomain. (Currently, this applies to OMAP3 clockdomains only.) + */ #define CLKDM_CAN_FORCE_SLEEP (1 << 0) #define CLKDM_CAN_FORCE_WAKEUP (1 << 1) #define CLKDM_CAN_ENABLE_AUTO (1 << 2) #define CLKDM_CAN_DISABLE_AUTO (1 << 3) +#define CLKDM_NO_AUTODEPS (1 << 4) #define CLKDM_CAN_HWSUP (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO) #define CLKDM_CAN_SWSUP (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index a68a2cf1be34..2dd1ea9859bc 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -460,14 +460,18 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v) * will be accessed by a particular initiator (e.g., if a module will * be accessed by the IVA, there should be a sleepdep between the IVA * initiator and the module). Only applies to modules in smart-idle - * mode. Returns -EINVAL upon error or passes along - * clkdm_add_sleepdep() value upon success. + * mode. If the clockdomain is marked as not needing autodeps, return + * 0 without doing anything. Otherwise, returns -EINVAL upon error or + * passes along clkdm_add_sleepdep() value upon success. */ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) { if (!oh->_clk) return -EINVAL; + if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS) + return 0; + return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); } @@ -480,14 +484,18 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) * be accessed by a particular initiator (e.g., if a module will not * be accessed by the IVA, there should be no sleepdep between the IVA * initiator and the module). Only applies to modules in smart-idle - * mode. Returns -EINVAL upon error or passes along - * clkdm_del_sleepdep() value upon success. + * mode. If the clockdomain is marked as not needing autodeps, return + * 0 without doing anything. Returns -EINVAL upon error or passes + * along clkdm_del_sleepdep() value upon success. */ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh) { if (!oh->_clk) return -EINVAL; + if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS) + return 0; + return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm); } From 4ce1e5e14c4ea43f971bd546934ef40b3ae4fcf3 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 10 Mar 2011 03:50:54 -0700 Subject: [PATCH 59/62] omap2/3: dmtimer: Enable autoidle This saves some power. OMAP4 version should check for GPT module ID, as autoidle is only supported on a subset of these. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/dmtimer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 1d706cf63ca0..ee9f6ebba29b 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -342,6 +342,10 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) l |= 0x02 << 3; /* Set to smart-idle mode */ l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */ + /* Enable autoidle on OMAP2 / OMAP3 */ + if (cpu_is_omap24xx() || cpu_is_omap34xx()) + l |= 0x1 << 0; + /* * Enable wake-up on OMAP2 CPUs. */ From c0718df4d666cc5fd8837ac93c82995a17bfdbf5 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 10 Mar 2011 22:17:45 -0700 Subject: [PATCH 60/62] OMAP2+: voltage: reorganize, split code from data This is a first pass at reorganizing mach-omap2/voltage.c: - Separate almost all of the data from the code of mach-omap2/voltage.c. The code remains in mach-omap2/voltage.c. The data goes into one of several places, depending on what type of data it is: - Silicon process/validation data: mach-omap2/opp*_data.c - VC (Voltage Controller) data: mach-omap2/vc*_data.c - VP (Voltage Processor) data: mach-omap2/vp*_data.c - Voltage domain data: mach-omap2/voltagedomains*_data.c The ultimate goal is for all this data to be autogenerated, the same way we autogenerate the rest of our data. - Separate VC and VP common data from VDD-specific VC and VP data. - Separate common voltage.c code from SoC-specific code; reuse common code. - Reorganize structures to avoid unnecessary memory loss due to unpacked fields. There is much left to be done. VC code and VP code should be separated out into vc*.c and vp*.c files. Many fields in the existing structures are superfluous, and should be removed. Some code in voltage.c seems to be duplicated; that code should be moved into functions of its own. Proper voltage domain code should be created, as was done with the powerdomain and clockdomains, and powerdomains should reference voltagedomains. Thanks to Shweta Gulati for comments. Thanks to Rajendra Nayak for finding and fixing some bugs that prevented OMAP4 from booting: https://patchwork.kernel.org/patch/587311/ His patch has been folded into this one to avoid breaking OMAP4 between patches. Thanks also to Kevin Hilman for finding and fixing a compile problem when !CONFIG_PM: http://www.spinics.net/lists/arm-kernel/msg118067.html His patch has also been folded into this one to avoid breaking !CONFIG_PM builds. Signed-off-by: Paul Walmsley Cc: Shweta Gulati Cc: Rajendra Nayak Cc: Kevin Hilman --- arch/arm/mach-omap2/Makefile | 22 +- arch/arm/mach-omap2/omap_opp_data.h | 24 + arch/arm/mach-omap2/opp3xxx_data.c | 66 +- arch/arm/mach-omap2/opp4xxx_data.c | 43 +- arch/arm/mach-omap2/vc.h | 83 ++ arch/arm/mach-omap2/vc3xxx_data.c | 63 + arch/arm/mach-omap2/vc44xx_data.c | 75 ++ arch/arm/mach-omap2/voltage.c | 1023 +++++------------ arch/arm/mach-omap2/voltage.h | 89 +- arch/arm/mach-omap2/voltagedomains3xxx_data.c | 95 ++ arch/arm/mach-omap2/voltagedomains44xx_data.c | 102 ++ arch/arm/mach-omap2/vp.h | 143 +++ arch/arm/mach-omap2/vp3xxx_data.c | 82 ++ arch/arm/mach-omap2/vp44xx_data.c | 100 ++ 14 files changed, 1229 insertions(+), 781 deletions(-) create mode 100644 arch/arm/mach-omap2/vc.h create mode 100644 arch/arm/mach-omap2/vc3xxx_data.c create mode 100644 arch/arm/mach-omap2/vc44xx_data.c create mode 100644 arch/arm/mach-omap2/voltagedomains3xxx_data.c create mode 100644 arch/arm/mach-omap2/voltagedomains44xx_data.c create mode 100644 arch/arm/mach-omap2/vp.h create mode 100644 arch/arm/mach-omap2/vp3xxx_data.c create mode 100644 arch/arm/mach-omap2/vp44xx_data.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index c5b1be9b7328..ea1e26f58b91 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -59,10 +59,10 @@ endif # Power Management ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o -obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o voltage.o -obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o voltage.o \ +obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o +obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \ cpuidle34xx.o pm_bus.o -obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o +obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o @@ -78,13 +78,25 @@ endif # PRCM obj-$(CONFIG_ARCH_OMAP2) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o -obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o +obj-$(CONFIG_ARCH_OMAP3) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \ + vc3xxx_data.o vp3xxx_data.o # XXX The presence of cm2xxx_3xxx.o on the line below is temporary and # will be removed once the OMAP4 part of the codebase is converted to # use OMAP4-specific PRCM functions. obj-$(CONFIG_ARCH_OMAP4) += prcm.o cm2xxx_3xxx.o cminst44xx.o \ cm44xx.o prcm_mpu44xx.o \ - prminst44xx.o + prminst44xx.o vc44xx_data.o \ + vp44xx_data.o + +# OMAP voltage domains +ifeq ($(CONFIG_PM),y) +voltagedomain-common := voltage.o +obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common) +obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common) \ + voltagedomains3xxx_data.o +obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common) \ + voltagedomains44xx_data.o +endif # OMAP powerdomain framework powerdomain-common += powerdomain.o powerdomain-common.o diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h index 46ac27dd6c84..c784c12f98a1 100644 --- a/arch/arm/mach-omap2/omap_opp_data.h +++ b/arch/arm/mach-omap2/omap_opp_data.h @@ -21,6 +21,8 @@ #include +#include "voltage.h" + /* * *BIG FAT WARNING*: * USE the following ONLY in opp data initialization common to an SoC. @@ -65,8 +67,30 @@ struct omap_opp_def { .u_volt = _uv, \ } +/* + * Initialization wrapper used to define SmartReflex process data + * XXX Is this needed? Just use C99 initializers in data files? + */ +#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain) \ +{ \ + .volt_nominal = _v_nom, \ + .sr_efuse_offs = _efuse_offs, \ + .sr_errminlimit = _errminlimit, \ + .vp_errgain = _errgain \ +} + /* Use this to initialize the default table */ extern int __init omap_init_opp_table(struct omap_opp_def *opp_def, u32 opp_def_size); + +extern struct omap_volt_data omap34xx_vddmpu_volt_data[]; +extern struct omap_volt_data omap34xx_vddcore_volt_data[]; +extern struct omap_volt_data omap36xx_vddmpu_volt_data[]; +extern struct omap_volt_data omap36xx_vddcore_volt_data[]; + +extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[]; +extern struct omap_volt_data omap44xx_vdd_iva_volt_data[]; +extern struct omap_volt_data omap44xx_vdd_core_volt_data[]; + #endif /* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */ diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c index 0486fce8a92c..3bba9204a174 100644 --- a/arch/arm/mach-omap2/opp3xxx_data.c +++ b/arch/arm/mach-omap2/opp3xxx_data.c @@ -4,8 +4,9 @@ * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/ * Nishanth Menon * Kevin Hilman - * Copyright (C) 2010 Nokia Corporation. + * Copyright (C) 2010-2011 Nokia Corporation. * Eduardo Valentin + * Paul Walmsley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -20,8 +21,71 @@ #include +#include "control.h" #include "omap_opp_data.h" +/* 34xx */ + +/* VDD1 */ + +#define OMAP3430_VDD_MPU_OPP1_UV 975000 +#define OMAP3430_VDD_MPU_OPP2_UV 1075000 +#define OMAP3430_VDD_MPU_OPP3_UV 1200000 +#define OMAP3430_VDD_MPU_OPP4_UV 1270000 +#define OMAP3430_VDD_MPU_OPP5_UV 1350000 + +struct omap_volt_data omap34xx_vddmpu_volt_data[] = { + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18), + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18), + VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +/* VDD2 */ + +#define OMAP3430_VDD_CORE_OPP1_UV 975000 +#define OMAP3430_VDD_CORE_OPP2_UV 1050000 +#define OMAP3430_VDD_CORE_OPP3_UV 1150000 + +struct omap_volt_data omap34xx_vddcore_volt_data[] = { + VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +/* 36xx */ + +/* VDD1 */ + +#define OMAP3630_VDD_MPU_OPP50_UV 1012500 +#define OMAP3630_VDD_MPU_OPP100_UV 1200000 +#define OMAP3630_VDD_MPU_OPP120_UV 1325000 +#define OMAP3630_VDD_MPU_OPP1G_UV 1375000 + +struct omap_volt_data omap36xx_vddmpu_volt_data[] = { + VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16), + VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23), + VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +/* VDD2 */ + +#define OMAP3630_VDD_CORE_OPP50_UV 1000000 +#define OMAP3630_VDD_CORE_OPP100_UV 1200000 + +struct omap_volt_data omap36xx_vddcore_volt_data[] = { + VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +/* OPP data */ + static struct omap_opp_def __initdata omap34xx_opp_def_list[] = { /* MPU OPP1 */ OPP_INITIALIZER("mpu", true, 125000000, 975000), diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c index a11fa566d8ee..fdee8d4186ab 100644 --- a/arch/arm/mach-omap2/opp4xxx_data.c +++ b/arch/arm/mach-omap2/opp4xxx_data.c @@ -5,8 +5,9 @@ * Nishanth Menon * Kevin Hilman * Thara Gopinath - * Copyright (C) 2010 Nokia Corporation. + * Copyright (C) 2010-2011 Nokia Corporation. * Eduardo Valentin + * Paul Walmsley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -21,8 +22,48 @@ #include +#include "control.h" #include "omap_opp_data.h" +/* + * Structures containing OMAP4430 voltage supported and various + * voltage dependent data for each VDD. + */ + +#define OMAP4430_VDD_MPU_OPP50_UV 930000 +#define OMAP4430_VDD_MPU_OPP100_UV 1100000 +#define OMAP4430_VDD_MPU_OPPTURBO_UV 1260000 +#define OMAP4430_VDD_MPU_OPPNITRO_UV 1350000 + +struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = { + VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16), + VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23), + VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +#define OMAP4430_VDD_IVA_OPP50_UV 930000 +#define OMAP4430_VDD_IVA_OPP100_UV 1100000 +#define OMAP4430_VDD_IVA_OPPTURBO_UV 1260000 + +struct omap_volt_data omap44xx_vdd_iva_volt_data[] = { + VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16), + VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + +#define OMAP4430_VDD_CORE_OPP50_UV 930000 +#define OMAP4430_VDD_CORE_OPP100_UV 1100000 + +struct omap_volt_data omap44xx_vdd_core_volt_data[] = { + VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c), + VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16), + VOLT_DATA_DEFINE(0, 0, 0, 0), +}; + + static struct omap_opp_def __initdata omap44xx_opp_def_list[] = { /* MPU OPP1 - OPP50 */ OPP_INITIALIZER("mpu", true, 300000000, 1100000), diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h new file mode 100644 index 000000000000..e7767771de49 --- /dev/null +++ b/arch/arm/mach-omap2/vc.h @@ -0,0 +1,83 @@ +/* + * OMAP3/4 Voltage Controller (VC) structure and macro definitions + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak + * Lesly A M + * Thara Gopinath + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ +#ifndef __ARCH_ARM_MACH_OMAP2_VC_H +#define __ARCH_ARM_MACH_OMAP2_VC_H + +#include + +/** + * struct omap_vc_common_data - per-VC register/bitfield data + * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register + * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register + * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start + * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start + * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start + * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register + * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register + * @regaddr_shift: REGADDR field shift in PRM_VC_BYPASS_VAL register + * @cmd_on_shift: ON field shift in PRM_VC_CMD_VAL_* register + * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register + * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register + * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register + * + * XXX One of cmd_on_mask and cmd_on_shift are not needed + * XXX VALID should probably be a shift, not a mask + */ +struct omap_vc_common_data { + u32 cmd_on_mask; + u32 valid; + u8 smps_sa_reg; + u8 smps_volra_reg; + u8 bypass_val_reg; + u8 data_shift; + u8 slaveaddr_shift; + u8 regaddr_shift; + u8 cmd_on_shift; + u8 cmd_onlp_shift; + u8 cmd_ret_shift; + u8 cmd_off_shift; +}; + +/** + * struct omap_vc_instance_data - VC per-instance data + * @vc_common: pointer to VC common data for this platform + * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register + * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register + * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register + * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register + * + * XXX It is not necessary to have both a *_mask and a *_shift - + * remove one + */ +struct omap_vc_instance_data { + const struct omap_vc_common_data *vc_common; + u32 smps_sa_mask; + u32 smps_volra_mask; + u8 cmdval_reg; + u8 smps_sa_shift; + u8 smps_volra_shift; +}; + +extern struct omap_vc_instance_data omap3_vc1_data; +extern struct omap_vc_instance_data omap3_vc2_data; + +extern struct omap_vc_instance_data omap4_vc_mpu_data; +extern struct omap_vc_instance_data omap4_vc_iva_data; +extern struct omap_vc_instance_data omap4_vc_core_data; + +#endif + diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c new file mode 100644 index 000000000000..f37dc4bc379a --- /dev/null +++ b/arch/arm/mach-omap2/vc3xxx_data.c @@ -0,0 +1,63 @@ +/* + * OMAP3 Voltage Controller (VC) data + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak + * Lesly A M + * Thara Gopinath + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +#include + +#include "prm-regbits-34xx.h" +#include "voltage.h" + +#include "vc.h" + +/* + * VC data common to 34xx/36xx chips + * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. + */ +static struct omap_vc_common_data omap3_vc_common = { + .smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET, + .smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET, + .bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET, + .data_shift = OMAP3430_DATA_SHIFT, + .slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT, + .regaddr_shift = OMAP3430_REGADDR_SHIFT, + .valid = OMAP3430_VALID_MASK, + .cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT, + .cmd_on_mask = OMAP3430_VC_CMD_ON_MASK, + .cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT, + .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT, + .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT, +}; + +struct omap_vc_instance_data omap3_vc1_data = { + .vc_common = &omap3_vc_common, + .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET, + .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT, + .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK, + .smps_volra_shift = OMAP3430_VOLRA0_SHIFT, + .smps_volra_mask = OMAP3430_VOLRA0_MASK, +}; + +struct omap_vc_instance_data omap3_vc2_data = { + .vc_common = &omap3_vc_common, + .cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET, + .smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT, + .smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK, + .smps_volra_shift = OMAP3430_VOLRA1_SHIFT, + .smps_volra_mask = OMAP3430_VOLRA1_MASK, +}; diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c new file mode 100644 index 000000000000..a98da8ddec52 --- /dev/null +++ b/arch/arm/mach-omap2/vc44xx_data.c @@ -0,0 +1,75 @@ +/* + * OMAP4 Voltage Controller (VC) data + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak + * Lesly A M + * Thara Gopinath + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +#include + +#include "prm44xx.h" +#include "prm-regbits-44xx.h" +#include "voltage.h" + +#include "vc.h" + +/* + * VC data common to 44xx chips + * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file. + */ +static const struct omap_vc_common_data omap4_vc_common = { + .smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET, + .smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET, + .bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET, + .data_shift = OMAP4430_DATA_SHIFT, + .slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT, + .regaddr_shift = OMAP4430_REGADDR_SHIFT, + .valid = OMAP4430_VALID_MASK, + .cmd_on_shift = OMAP4430_ON_SHIFT, + .cmd_on_mask = OMAP4430_ON_MASK, + .cmd_onlp_shift = OMAP4430_ONLP_SHIFT, + .cmd_ret_shift = OMAP4430_RET_SHIFT, + .cmd_off_shift = OMAP4430_OFF_SHIFT, +}; + +/* VC instance data for each controllable voltage line */ +struct omap_vc_instance_data omap4_vc_mpu_data = { + .vc_common = &omap4_vc_common, + .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET, + .smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT, + .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK, + .smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT, + .smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK, +}; + +struct omap_vc_instance_data omap4_vc_iva_data = { + .vc_common = &omap4_vc_common, + .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET, + .smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT, + .smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK, + .smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT, + .smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK, +}; + +struct omap_vc_instance_data omap4_vc_core_data = { + .vc_common = &omap4_vc_common, + .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET, + .smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT, + .smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK, + .smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT, + .smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK, +}; + diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index 3c9bcdce612b..c6facf7becf8 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -7,8 +7,9 @@ * Rajendra Nayak * Lesly A M * - * Copyright (C) 2008 Nokia Corporation + * Copyright (C) 2008, 2011 Nokia Corporation * Kalle Jokiniemi + * Paul Walmsley * * Copyright (C) 2010 Texas Instruments, Inc. * Thara Gopinath @@ -36,284 +37,28 @@ #include "voltage.h" -#define VP_IDLE_TIMEOUT 200 -#define VP_TRANXDONE_TIMEOUT 300 +#include "vc.h" +#include "vp.h" + #define VOLTAGE_DIR_SIZE 16 -/* Voltage processor register offsets */ -struct vp_reg_offs { - u8 vpconfig; - u8 vstepmin; - u8 vstepmax; - u8 vlimitto; - u8 vstatus; - u8 voltage; -}; -/* Voltage Processor bit field values, shifts and masks */ -struct vp_reg_val { - /* PRM module */ - u16 prm_mod; - /* VPx_VPCONFIG */ - u32 vpconfig_erroroffset; - u16 vpconfig_errorgain; - u32 vpconfig_errorgain_mask; - u8 vpconfig_errorgain_shift; - u32 vpconfig_initvoltage_mask; - u8 vpconfig_initvoltage_shift; - u32 vpconfig_timeouten; - u32 vpconfig_initvdd; - u32 vpconfig_forceupdate; - u32 vpconfig_vpenable; - /* VPx_VSTEPMIN */ - u8 vstepmin_stepmin; - u16 vstepmin_smpswaittimemin; - u8 vstepmin_stepmin_shift; - u8 vstepmin_smpswaittimemin_shift; - /* VPx_VSTEPMAX */ - u8 vstepmax_stepmax; - u16 vstepmax_smpswaittimemax; - u8 vstepmax_stepmax_shift; - u8 vstepmax_smpswaittimemax_shift; - /* VPx_VLIMITTO */ - u8 vlimitto_vddmin; - u8 vlimitto_vddmax; - u16 vlimitto_timeout; - u8 vlimitto_vddmin_shift; - u8 vlimitto_vddmax_shift; - u8 vlimitto_timeout_shift; - /* PRM_IRQSTATUS*/ - u32 tranxdone_status; -}; +static struct omap_vdd_info **vdd_info; -/* Voltage controller registers and offsets */ -struct vc_reg_info { - /* PRM module */ - u16 prm_mod; - /* VC register offsets */ - u8 smps_sa_reg; - u8 smps_volra_reg; - u8 bypass_val_reg; - u8 cmdval_reg; - u8 voltsetup_reg; - /*VC_SMPS_SA*/ - u8 smps_sa_shift; - u32 smps_sa_mask; - /* VC_SMPS_VOL_RA */ - u8 smps_volra_shift; - u32 smps_volra_mask; - /* VC_BYPASS_VAL */ - u8 data_shift; - u8 slaveaddr_shift; - u8 regaddr_shift; - u32 valid; - /* VC_CMD_VAL */ - u8 cmd_on_shift; - u8 cmd_onlp_shift; - u8 cmd_ret_shift; - u8 cmd_off_shift; - u32 cmd_on_mask; - /* PRM_VOLTSETUP */ - u8 voltsetup_shift; - u32 voltsetup_mask; -}; - -/** - * omap_vdd_info - Per Voltage Domain info - * - * @volt_data : voltage table having the distinct voltages supported - * by the domain and other associated per voltage data. - * @pmic_info : pmic specific parameters which should be populted by - * the pmic drivers. - * @vp_offs : structure containing the offsets for various - * vp registers - * @vp_reg : the register values, shifts, masks for various - * vp registers - * @vc_reg : structure containing various various vc registers, - * shifts, masks etc. - * @voltdm : pointer to the voltage domain structure - * @debug_dir : debug directory for this voltage domain. - * @curr_volt : current voltage for this vdd. - * @ocp_mod : The prm module for accessing the prm irqstatus reg. - * @prm_irqst_reg : prm irqstatus register. - * @vp_enabled : flag to keep track of whether vp is enabled or not - * @volt_scale : API to scale the voltage of the vdd. - */ -struct omap_vdd_info { - struct omap_volt_data *volt_data; - struct omap_volt_pmic_info *pmic_info; - struct vp_reg_offs vp_offs; - struct vp_reg_val vp_reg; - struct vc_reg_info vc_reg; - struct voltagedomain voltdm; - struct dentry *debug_dir; - u32 curr_volt; - u16 ocp_mod; - u8 prm_irqst_reg; - bool vp_enabled; - u32 (*read_reg) (u16 mod, u8 offset); - void (*write_reg) (u32 val, u16 mod, u8 offset); - int (*volt_scale) (struct omap_vdd_info *vdd, - unsigned long target_volt); -}; - -static struct omap_vdd_info *vdd_info; /* * Number of scalable voltage domains. */ static int nr_scalable_vdd; -/* OMAP3 VDD sturctures */ -static struct omap_vdd_info omap3_vdd_info[] = { - { - .vp_offs = { - .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET, - .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET, - .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET, - .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET, - .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET, - .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "mpu", - }, - }, - { - .vp_offs = { - .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET, - .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET, - .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET, - .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET, - .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET, - .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "core", - }, - }, -}; - -#define OMAP3_NR_SCALABLE_VDD ARRAY_SIZE(omap3_vdd_info) - -/* OMAP4 VDD sturctures */ -static struct omap_vdd_info omap4_vdd_info[] = { - { - .vp_offs = { - .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET, - .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET, - .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET, - .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET, - .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET, - .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "mpu", - }, - }, - { - .vp_offs = { - .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET, - .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET, - .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET, - .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET, - .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET, - .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "iva", - }, - }, - { - .vp_offs = { - .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET, - .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET, - .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET, - .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET, - .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET, - .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET, - }, - .voltdm = { - .name = "core", - }, - }, -}; - -#define OMAP4_NR_SCALABLE_VDD ARRAY_SIZE(omap4_vdd_info) - -/* - * Structures containing OMAP3430/OMAP3630 voltage supported and various - * voltage dependent data for each VDD. - */ -#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain) \ -{ \ - .volt_nominal = _v_nom, \ - .sr_efuse_offs = _efuse_offs, \ - .sr_errminlimit = _errminlimit, \ - .vp_errgain = _errgain \ -} - -/* VDD1 */ -static struct omap_volt_data omap34xx_vddmpu_volt_data[] = { - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18), - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18), - VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -static struct omap_volt_data omap36xx_vddmpu_volt_data[] = { - VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16), - VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23), - VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -/* VDD2 */ -static struct omap_volt_data omap34xx_vddcore_volt_data[] = { - VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -static struct omap_volt_data omap36xx_vddcore_volt_data[] = { - VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -/* - * Structures containing OMAP4430 voltage supported and various - * voltage dependent data for each VDD. - */ -static struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = { - VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16), - VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23), - VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -static struct omap_volt_data omap44xx_vdd_iva_volt_data[] = { - VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16), - VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; - -static struct omap_volt_data omap44xx_vdd_core_volt_data[] = { - VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c), - VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16), - VOLT_DATA_DEFINE(0, 0, 0, 0), -}; +/* XXX document */ +static s16 prm_mod_offs; +static s16 prm_irqst_ocp_mod_offs; static struct dentry *voltage_dir; /* Init function pointers */ -static void (*vc_init) (struct omap_vdd_info *vdd); -static int (*vdd_data_configure) (struct omap_vdd_info *vdd); +static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, + unsigned long target_volt); static u32 omap3_voltage_read_reg(u16 mod, u8 offset) { @@ -336,6 +81,62 @@ static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset) omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset); } +static int __init _config_common_vdd_data(struct omap_vdd_info *vdd) +{ + char *sys_ck_name; + struct clk *sys_ck; + u32 sys_clk_speed, timeout_val, waittime; + + /* + * XXX Clockfw should handle this, or this should be in a + * struct record + */ + if (cpu_is_omap24xx() || cpu_is_omap34xx()) + sys_ck_name = "sys_ck"; + else if (cpu_is_omap44xx()) + sys_ck_name = "sys_clkin_ck"; + else + return -EINVAL; + + /* + * Sys clk rate is require to calculate vp timeout value and + * smpswaittimemin and smpswaittimemax. + */ + sys_ck = clk_get(NULL, sys_ck_name); + if (IS_ERR(sys_ck)) { + pr_warning("%s: Could not get the sys clk to calculate" + "various vdd_%s params\n", __func__, vdd->voltdm.name); + return -EINVAL; + } + sys_clk_speed = clk_get_rate(sys_ck); + clk_put(sys_ck); + /* Divide to avoid overflow */ + sys_clk_speed /= 1000; + + /* Generic voltage parameters */ + vdd->curr_volt = 1200000; + vdd->volt_scale = vp_forceupdate_scale_voltage; + vdd->vp_enabled = false; + + vdd->vp_rt_data.vpconfig_erroroffset = + (vdd->pmic_info->vp_erroroffset << + vdd->vp_data->vp_common->vpconfig_erroroffset_shift); + + timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000; + vdd->vp_rt_data.vlimitto_timeout = timeout_val; + vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin; + vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax; + + waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) * + sys_clk_speed) / 1000; + vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime; + vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime; + vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin; + vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax; + + return 0; +} + /* Voltage debugfs support */ static int vp_volt_debug_get(void *data, u64 *val) { @@ -347,7 +148,7 @@ static int vp_volt_debug_get(void *data, u64 *val) return -EINVAL; } - vsel = vdd->read_reg(vdd->vp_reg.prm_mod, vdd->vp_offs.voltage); + vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); pr_notice("curr_vsel = %x\n", vsel); if (!vdd->pmic_info->vsel_to_uv) { @@ -380,7 +181,6 @@ DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL, static void vp_latch_vsel(struct omap_vdd_info *vdd) { u32 vpconfig; - u16 mod; unsigned long uvdc; char vsel; @@ -397,30 +197,27 @@ static void vp_latch_vsel(struct omap_vdd_info *vdd) return; } - mod = vdd->vp_reg.prm_mod; - vsel = vdd->pmic_info->uv_to_vsel(uvdc); - vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig); - vpconfig &= ~(vdd->vp_reg.vpconfig_initvoltage_mask | - vdd->vp_reg.vpconfig_initvdd); - vpconfig |= vsel << vdd->vp_reg.vpconfig_initvoltage_shift; + vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); + vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask | + vdd->vp_data->vp_common->vpconfig_initvdd); + vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift; - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); /* Trigger initVDD value copy to voltage processor */ - vdd->write_reg((vpconfig | vdd->vp_reg.vpconfig_initvdd), mod, - vdd->vp_offs.vpconfig); + vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd), + prm_mod_offs, vdd->vp_data->vpconfig); /* Clear initVDD copy trigger bit */ - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); } /* Generic voltage init functions */ static void __init vp_init(struct omap_vdd_info *vdd) { u32 vp_val; - u16 mod; if (!vdd->read_reg || !vdd->write_reg) { pr_err("%s: No read/write API for accessing vdd_%s regs\n", @@ -428,33 +225,31 @@ static void __init vp_init(struct omap_vdd_info *vdd) return; } - mod = vdd->vp_reg.prm_mod; + vp_val = vdd->vp_rt_data.vpconfig_erroroffset | + (vdd->vp_rt_data.vpconfig_errorgain << + vdd->vp_data->vp_common->vpconfig_errorgain_shift) | + vdd->vp_data->vp_common->vpconfig_timeouten; + vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vpconfig); - vp_val = vdd->vp_reg.vpconfig_erroroffset | - (vdd->vp_reg.vpconfig_errorgain << - vdd->vp_reg.vpconfig_errorgain_shift) | - vdd->vp_reg.vpconfig_timeouten; - vdd->write_reg(vp_val, mod, vdd->vp_offs.vpconfig); + vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin << + vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) | + (vdd->vp_rt_data.vstepmin_stepmin << + vdd->vp_data->vp_common->vstepmin_stepmin_shift)); + vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmin); - vp_val = ((vdd->vp_reg.vstepmin_smpswaittimemin << - vdd->vp_reg.vstepmin_smpswaittimemin_shift) | - (vdd->vp_reg.vstepmin_stepmin << - vdd->vp_reg.vstepmin_stepmin_shift)); - vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmin); + vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax << + vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) | + (vdd->vp_rt_data.vstepmax_stepmax << + vdd->vp_data->vp_common->vstepmax_stepmax_shift)); + vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmax); - vp_val = ((vdd->vp_reg.vstepmax_smpswaittimemax << - vdd->vp_reg.vstepmax_smpswaittimemax_shift) | - (vdd->vp_reg.vstepmax_stepmax << - vdd->vp_reg.vstepmax_stepmax_shift)); - vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmax); - - vp_val = ((vdd->vp_reg.vlimitto_vddmax << - vdd->vp_reg.vlimitto_vddmax_shift) | - (vdd->vp_reg.vlimitto_vddmin << - vdd->vp_reg.vlimitto_vddmin_shift) | - (vdd->vp_reg.vlimitto_timeout << - vdd->vp_reg.vlimitto_timeout_shift)); - vdd->write_reg(vp_val, mod, vdd->vp_offs.vlimitto); + vp_val = ((vdd->vp_rt_data.vlimitto_vddmax << + vdd->vp_data->vp_common->vlimitto_vddmax_shift) | + (vdd->vp_rt_data.vlimitto_vddmin << + vdd->vp_data->vp_common->vlimitto_vddmin_shift) | + (vdd->vp_rt_data.vlimitto_timeout << + vdd->vp_data->vp_common->vlimitto_timeout_shift)); + vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vlimitto); } static void __init vdd_debugfs_init(struct omap_vdd_info *vdd) @@ -481,23 +276,23 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd) } (void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir, - &(vdd->vp_reg.vpconfig_errorgain)); + &(vdd->vp_rt_data.vpconfig_errorgain)); (void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO, vdd->debug_dir, - &(vdd->vp_reg.vstepmin_smpswaittimemin)); + &(vdd->vp_rt_data.vstepmin_smpswaittimemin)); (void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir, - &(vdd->vp_reg.vstepmin_stepmin)); + &(vdd->vp_rt_data.vstepmin_stepmin)); (void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO, vdd->debug_dir, - &(vdd->vp_reg.vstepmax_smpswaittimemax)); + &(vdd->vp_rt_data.vstepmax_smpswaittimemax)); (void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir, - &(vdd->vp_reg.vstepmax_stepmax)); + &(vdd->vp_rt_data.vstepmax_stepmax)); (void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir, - &(vdd->vp_reg.vlimitto_vddmax)); + &(vdd->vp_rt_data.vlimitto_vddmax)); (void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir, - &(vdd->vp_reg.vlimitto_vddmin)); + &(vdd->vp_rt_data.vlimitto_vddmin)); (void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir, - &(vdd->vp_reg.vlimitto_timeout)); + &(vdd->vp_rt_data.vlimitto_timeout)); (void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir, (void *) vdd, &vp_volt_debug_fops); (void) debugfs_create_file("curr_nominal_volt", S_IRUGO, @@ -510,8 +305,12 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd, unsigned long target_volt, u8 *target_vsel, u8 *current_vsel) { struct omap_volt_data *volt_data; + const struct omap_vc_common_data *vc_common; + const struct omap_vp_common_data *vp_common; u32 vc_cmdval, vp_errgain_val; - u16 vp_mod, vc_mod; + + vc_common = vdd->vc_data->vc_common; + vp_common = vdd->vp_data->vp_common; /* Check if suffiecient pmic info is available for this vdd */ if (!vdd->pmic_info) { @@ -533,33 +332,30 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd, return -EINVAL; } - vp_mod = vdd->vp_reg.prm_mod; - vc_mod = vdd->vc_reg.prm_mod; - /* Get volt_data corresponding to target_volt */ volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt); if (IS_ERR(volt_data)) volt_data = NULL; *target_vsel = vdd->pmic_info->uv_to_vsel(target_volt); - *current_vsel = vdd->read_reg(vp_mod, vdd->vp_offs.voltage); + *current_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); /* Setting the ON voltage to the new target voltage */ - vc_cmdval = vdd->read_reg(vc_mod, vdd->vc_reg.cmdval_reg); - vc_cmdval &= ~vdd->vc_reg.cmd_on_mask; - vc_cmdval |= (*target_vsel << vdd->vc_reg.cmd_on_shift); - vdd->write_reg(vc_cmdval, vc_mod, vdd->vc_reg.cmdval_reg); + vc_cmdval = vdd->read_reg(prm_mod_offs, vdd->vc_data->cmdval_reg); + vc_cmdval &= ~vc_common->cmd_on_mask; + vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift); + vdd->write_reg(vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg); /* Setting vp errorgain based on the voltage */ if (volt_data) { - vp_errgain_val = vdd->read_reg(vp_mod, - vdd->vp_offs.vpconfig); - vdd->vp_reg.vpconfig_errorgain = volt_data->vp_errgain; - vp_errgain_val &= ~vdd->vp_reg.vpconfig_errorgain_mask; - vp_errgain_val |= vdd->vp_reg.vpconfig_errorgain << - vdd->vp_reg.vpconfig_errorgain_shift; - vdd->write_reg(vp_errgain_val, vp_mod, - vdd->vp_offs.vpconfig); + vp_errgain_val = vdd->read_reg(prm_mod_offs, + vdd->vp_data->vpconfig); + vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain; + vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask; + vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain << + vp_common->vpconfig_errorgain_shift; + vdd->write_reg(vp_errgain_val, prm_mod_offs, + vdd->vp_data->vpconfig); } return 0; @@ -585,7 +381,6 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd, { u32 loop_cnt = 0, retries_cnt = 0; u32 vc_valid, vc_bypass_val_reg, vc_bypass_value; - u16 mod; u8 target_vsel, current_vsel; int ret; @@ -593,20 +388,19 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd, if (ret) return ret; - mod = vdd->vc_reg.prm_mod; - - vc_valid = vdd->vc_reg.valid; - vc_bypass_val_reg = vdd->vc_reg.bypass_val_reg; - vc_bypass_value = (target_vsel << vdd->vc_reg.data_shift) | + vc_valid = vdd->vc_data->vc_common->valid; + vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg; + vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) | (vdd->pmic_info->pmic_reg << - vdd->vc_reg.regaddr_shift) | + vdd->vc_data->vc_common->regaddr_shift) | (vdd->pmic_info->i2c_slave_addr << - vdd->vc_reg.slaveaddr_shift); + vdd->vc_data->vc_common->slaveaddr_shift); - vdd->write_reg(vc_bypass_value, mod, vc_bypass_val_reg); - vdd->write_reg(vc_bypass_value | vc_valid, mod, vc_bypass_val_reg); + vdd->write_reg(vc_bypass_value, prm_mod_offs, vc_bypass_val_reg); + vdd->write_reg(vc_bypass_value | vc_valid, prm_mod_offs, + vc_bypass_val_reg); - vc_bypass_value = vdd->read_reg(mod, vc_bypass_val_reg); + vc_bypass_value = vdd->read_reg(prm_mod_offs, vc_bypass_val_reg); /* * Loop till the bypass command is acknowledged from the SMPS. * NOTE: This is legacy code. The loop count and retry count needs @@ -625,7 +419,8 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd, loop_cnt = 0; udelay(10); } - vc_bypass_value = vdd->read_reg(mod, vc_bypass_val_reg); + vc_bypass_value = vdd->read_reg(prm_mod_offs, + vc_bypass_val_reg); } _post_volt_scale(vdd, target_volt, target_vsel, current_vsel); @@ -637,7 +432,6 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, unsigned long target_volt) { u32 vpconfig; - u16 mod, ocp_mod; u8 target_vsel, current_vsel, prm_irqst_reg; int ret, timeout = 0; @@ -645,20 +439,18 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, if (ret) return ret; - mod = vdd->vp_reg.prm_mod; - ocp_mod = vdd->ocp_mod; - prm_irqst_reg = vdd->prm_irqst_reg; + prm_irqst_reg = vdd->vp_data->prm_irqst_data->prm_irqst_reg; /* * Clear all pending TransactionDone interrupt/status. Typical latency * is <3us */ while (timeout++ < VP_TRANXDONE_TIMEOUT) { - vdd->write_reg(vdd->vp_reg.tranxdone_status, - ocp_mod, prm_irqst_reg); - if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) & - vdd->vp_reg.tranxdone_status)) - break; + vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status, + prm_irqst_ocp_mod_offs, prm_irqst_reg); + if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) & + vdd->vp_data->prm_irqst_data->tranxdone_status)) + break; udelay(1); } if (timeout >= VP_TRANXDONE_TIMEOUT) { @@ -668,30 +460,30 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, } /* Configure for VP-Force Update */ - vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig); - vpconfig &= ~(vdd->vp_reg.vpconfig_initvdd | - vdd->vp_reg.vpconfig_forceupdate | - vdd->vp_reg.vpconfig_initvoltage_mask); + vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); + vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd | + vdd->vp_data->vp_common->vpconfig_forceupdate | + vdd->vp_data->vp_common->vpconfig_initvoltage_mask); vpconfig |= ((target_vsel << - vdd->vp_reg.vpconfig_initvoltage_shift)); - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vdd->vp_data->vp_common->vpconfig_initvoltage_shift)); + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); /* Trigger initVDD value copy to voltage processor */ - vpconfig |= vdd->vp_reg.vpconfig_initvdd; - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd; + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); /* Force update of voltage */ - vpconfig |= vdd->vp_reg.vpconfig_forceupdate; - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate; + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); /* * Wait for TransactionDone. Typical latency is <200us. * Depends on SMPSWAITTIMEMIN/MAX and voltage change */ timeout = 0; - omap_test_timeout((vdd->read_reg(ocp_mod, prm_irqst_reg) & - vdd->vp_reg.tranxdone_status), - VP_TRANXDONE_TIMEOUT, timeout); + omap_test_timeout((vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) & + vdd->vp_data->prm_irqst_data->tranxdone_status), + VP_TRANXDONE_TIMEOUT, timeout); if (timeout >= VP_TRANXDONE_TIMEOUT) pr_err("%s: vdd_%s TRANXDONE timeout exceeded." "TRANXDONE never got set after the voltage update\n", @@ -705,11 +497,11 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, */ timeout = 0; while (timeout++ < VP_TRANXDONE_TIMEOUT) { - vdd->write_reg(vdd->vp_reg.tranxdone_status, - ocp_mod, prm_irqst_reg); - if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) & - vdd->vp_reg.tranxdone_status)) - break; + vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status, + prm_irqst_ocp_mod_offs, prm_irqst_reg); + if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) & + vdd->vp_data->prm_irqst_data->tranxdone_status)) + break; udelay(1); } @@ -718,222 +510,95 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, "to clear the TRANXDONE status\n", __func__, vdd->voltdm.name); - vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig); + vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); /* Clear initVDD copy trigger bit */ - vpconfig &= ~vdd->vp_reg.vpconfig_initvdd;; - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd; + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); /* Clear force bit */ - vpconfig &= ~vdd->vp_reg.vpconfig_forceupdate; - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate; + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); return 0; } -/* OMAP3 specific voltage init functions */ +static void __init omap3_vfsm_init(struct omap_vdd_info *vdd) +{ + /* + * Voltage Manager FSM parameters init + * XXX This data should be passed in from the board file + */ + vdd->write_reg(OMAP3_CLKSETUP, prm_mod_offs, OMAP3_PRM_CLKSETUP_OFFSET); + vdd->write_reg(OMAP3_VOLTOFFSET, prm_mod_offs, + OMAP3_PRM_VOLTOFFSET_OFFSET); + vdd->write_reg(OMAP3_VOLTSETUP2, prm_mod_offs, + OMAP3_PRM_VOLTSETUP2_OFFSET); +} -/* - * Intializes the voltage controller registers with the PMIC and board - * specific parameters and voltage setup times for OMAP3. - */ static void __init omap3_vc_init(struct omap_vdd_info *vdd) { - u32 vc_val; - u16 mod; - u8 on_vsel, onlp_vsel, ret_vsel, off_vsel; static bool is_initialized; + u8 on_vsel, onlp_vsel, ret_vsel, off_vsel; + u32 vc_val; - if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) { - pr_err("%s: PMIC info requried to configure vc for" - "vdd_%s not populated.Hence cannot initialize vc\n", - __func__, vdd->voltdm.name); + if (is_initialized) return; - } - - if (!vdd->read_reg || !vdd->write_reg) { - pr_err("%s: No read/write API for accessing vdd_%s regs\n", - __func__, vdd->voltdm.name); - return; - } - - mod = vdd->vc_reg.prm_mod; - - /* Set up the SMPS_SA(i2c slave address in VC */ - vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg); - vc_val &= ~vdd->vc_reg.smps_sa_mask; - vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift; - vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg); - - /* Setup the VOLRA(pmic reg addr) in VC */ - vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg); - vc_val &= ~vdd->vc_reg.smps_volra_mask; - vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift; - vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg); - - /*Configure the setup times */ - vc_val = vdd->read_reg(mod, vdd->vc_reg.voltsetup_reg); - vc_val &= ~vdd->vc_reg.voltsetup_mask; - vc_val |= vdd->pmic_info->volt_setup_time << - vdd->vc_reg.voltsetup_shift; - vdd->write_reg(vc_val, mod, vdd->vc_reg.voltsetup_reg); /* Set up the on, inactive, retention and off voltage */ on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt); onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt); ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt); off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt); - vc_val = ((on_vsel << vdd->vc_reg.cmd_on_shift) | - (onlp_vsel << vdd->vc_reg.cmd_onlp_shift) | - (ret_vsel << vdd->vc_reg.cmd_ret_shift) | - (off_vsel << vdd->vc_reg.cmd_off_shift)); - vdd->write_reg(vc_val, mod, vdd->vc_reg.cmdval_reg); + vc_val = ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) | + (onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) | + (ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) | + (off_vsel << vdd->vc_data->vc_common->cmd_off_shift)); + vdd->write_reg(vc_val, prm_mod_offs, vdd->vc_data->cmdval_reg); - if (is_initialized) - return; - - /* Generic VC parameters init */ - vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, mod, + /* + * Generic VC parameters init + * XXX This data should be abstracted out + */ + vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, prm_mod_offs, OMAP3_PRM_VC_CH_CONF_OFFSET); - vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, mod, + vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, prm_mod_offs, OMAP3_PRM_VC_I2C_CFG_OFFSET); - vdd->write_reg(OMAP3_CLKSETUP, mod, OMAP3_PRM_CLKSETUP_OFFSET); - vdd->write_reg(OMAP3_VOLTOFFSET, mod, OMAP3_PRM_VOLTOFFSET_OFFSET); - vdd->write_reg(OMAP3_VOLTSETUP2, mod, OMAP3_PRM_VOLTSETUP2_OFFSET); + + omap3_vfsm_init(vdd); + is_initialized = true; } -/* Sets up all the VDD related info for OMAP3 */ -static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd) -{ - struct clk *sys_ck; - u32 sys_clk_speed, timeout_val, waittime; - - if (!vdd->pmic_info) { - pr_err("%s: PMIC info requried to configure vdd_%s not" - "populated.Hence cannot initialize vdd_%s\n", - __func__, vdd->voltdm.name, vdd->voltdm.name); - return -EINVAL; - } - - if (!strcmp(vdd->voltdm.name, "mpu")) { - if (cpu_is_omap3630()) - vdd->volt_data = omap36xx_vddmpu_volt_data; - else - vdd->volt_data = omap34xx_vddmpu_volt_data; - - vdd->vp_reg.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK; - vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET; - vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT; - vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK; - vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA0_SHIFT; - vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA0_MASK; - vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT; - vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK; - } else if (!strcmp(vdd->voltdm.name, "core")) { - if (cpu_is_omap3630()) - vdd->volt_data = omap36xx_vddcore_volt_data; - else - vdd->volt_data = omap34xx_vddcore_volt_data; - - vdd->vp_reg.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK; - vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET; - vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT; - vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK; - vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA1_SHIFT; - vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA1_MASK; - vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT; - vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK; - } else { - pr_warning("%s: vdd_%s does not exisit in OMAP3\n", - __func__, vdd->voltdm.name); - return -EINVAL; - } - - /* - * Sys clk rate is require to calculate vp timeout value and - * smpswaittimemin and smpswaittimemax. - */ - sys_ck = clk_get(NULL, "sys_ck"); - if (IS_ERR(sys_ck)) { - pr_warning("%s: Could not get the sys clk to calculate" - "various vdd_%s params\n", __func__, vdd->voltdm.name); - return -EINVAL; - } - sys_clk_speed = clk_get_rate(sys_ck); - clk_put(sys_ck); - /* Divide to avoid overflow */ - sys_clk_speed /= 1000; - - /* Generic voltage parameters */ - vdd->curr_volt = 1200000; - vdd->ocp_mod = OCP_MOD; - vdd->prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET; - vdd->read_reg = omap3_voltage_read_reg; - vdd->write_reg = omap3_voltage_write_reg; - vdd->volt_scale = vp_forceupdate_scale_voltage; - vdd->vp_enabled = false; - - /* VC parameters */ - vdd->vc_reg.prm_mod = OMAP3430_GR_MOD; - vdd->vc_reg.smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET; - vdd->vc_reg.smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET; - vdd->vc_reg.bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET; - vdd->vc_reg.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET; - vdd->vc_reg.data_shift = OMAP3430_DATA_SHIFT; - vdd->vc_reg.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT; - vdd->vc_reg.regaddr_shift = OMAP3430_REGADDR_SHIFT; - vdd->vc_reg.valid = OMAP3430_VALID_MASK; - vdd->vc_reg.cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT; - vdd->vc_reg.cmd_on_mask = OMAP3430_VC_CMD_ON_MASK; - vdd->vc_reg.cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT; - vdd->vc_reg.cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT; - vdd->vc_reg.cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT; - - vdd->vp_reg.prm_mod = OMAP3430_GR_MOD; - - /* VPCONFIG bit fields */ - vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset << - OMAP3430_ERROROFFSET_SHIFT); - vdd->vp_reg.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK; - vdd->vp_reg.vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT; - vdd->vp_reg.vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT; - vdd->vp_reg.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK; - vdd->vp_reg.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK; - vdd->vp_reg.vpconfig_initvdd = OMAP3430_INITVDD_MASK; - vdd->vp_reg.vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK; - vdd->vp_reg.vpconfig_vpenable = OMAP3430_VPENABLE_MASK; - - /* VSTEPMIN VSTEPMAX bit fields */ - waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) * - sys_clk_speed) / 1000; - vdd->vp_reg.vstepmin_smpswaittimemin = waittime; - vdd->vp_reg.vstepmax_smpswaittimemax = waittime; - vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin; - vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax; - vdd->vp_reg.vstepmin_smpswaittimemin_shift = - OMAP3430_SMPSWAITTIMEMIN_SHIFT; - vdd->vp_reg.vstepmax_smpswaittimemax_shift = - OMAP3430_SMPSWAITTIMEMAX_SHIFT; - vdd->vp_reg.vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT; - vdd->vp_reg.vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT; - - /* VLIMITTO bit fields */ - timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000; - vdd->vp_reg.vlimitto_timeout = timeout_val; - vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin; - vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax; - vdd->vp_reg.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT; - vdd->vp_reg.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT; - vdd->vp_reg.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT; - - return 0; -} /* OMAP4 specific voltage init functions */ static void __init omap4_vc_init(struct omap_vdd_info *vdd) { - u32 vc_val; - u16 mod; static bool is_initialized; + u32 vc_val; + + if (is_initialized) + return; + + /* TODO: Configure setup times and CMD_VAL values*/ + + /* + * Generic VC parameters init + * XXX This data should be abstracted out + */ + vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK | + OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK | + OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK); + vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET); + + /* XXX These are magic numbers and do not belong! */ + vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT); + vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET); + + is_initialized = true; +} + +static void __init omap_vc_init(struct omap_vdd_info *vdd) +{ + u32 vc_val; if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) { pr_err("%s: PMIC info requried to configure vc for" @@ -948,173 +613,61 @@ static void __init omap4_vc_init(struct omap_vdd_info *vdd) return; } - mod = vdd->vc_reg.prm_mod; - /* Set up the SMPS_SA(i2c slave address in VC */ - vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg); - vc_val &= ~vdd->vc_reg.smps_sa_mask; - vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift; - vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg); + vc_val = vdd->read_reg(prm_mod_offs, + vdd->vc_data->vc_common->smps_sa_reg); + vc_val &= ~vdd->vc_data->smps_sa_mask; + vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift; + vdd->write_reg(vc_val, prm_mod_offs, + vdd->vc_data->vc_common->smps_sa_reg); /* Setup the VOLRA(pmic reg addr) in VC */ - vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg); - vc_val &= ~vdd->vc_reg.smps_volra_mask; - vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift; - vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg); + vc_val = vdd->read_reg(prm_mod_offs, + vdd->vc_data->vc_common->smps_volra_reg); + vc_val &= ~vdd->vc_data->smps_volra_mask; + vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift; + vdd->write_reg(vc_val, prm_mod_offs, + vdd->vc_data->vc_common->smps_volra_reg); - /* TODO: Configure setup times and CMD_VAL values*/ + /* Configure the setup times */ + vc_val = vdd->read_reg(prm_mod_offs, vdd->vfsm->voltsetup_reg); + vc_val &= ~vdd->vfsm->voltsetup_mask; + vc_val |= vdd->pmic_info->volt_setup_time << + vdd->vfsm->voltsetup_shift; + vdd->write_reg(vc_val, prm_mod_offs, vdd->vfsm->voltsetup_reg); - if (is_initialized) - return; - - /* Generic VC parameters init */ - vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK | - OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK | - OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK); - vdd->write_reg(vc_val, mod, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET); - - vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT); - vdd->write_reg(vc_val, mod, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET); - - is_initialized = true; + if (cpu_is_omap34xx()) + omap3_vc_init(vdd); + else if (cpu_is_omap44xx()) + omap4_vc_init(vdd); } -/* Sets up all the VDD related info for OMAP4 */ -static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd) +static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd) { - struct clk *sys_ck; - u32 sys_clk_speed, timeout_val, waittime; + int ret = -EINVAL; if (!vdd->pmic_info) { pr_err("%s: PMIC info requried to configure vdd_%s not" "populated.Hence cannot initialize vdd_%s\n", __func__, vdd->voltdm.name, vdd->voltdm.name); - return -EINVAL; + goto ovdc_out; } - if (!strcmp(vdd->voltdm.name, "mpu")) { - vdd->volt_data = omap44xx_vdd_mpu_volt_data; - vdd->vp_reg.tranxdone_status = - OMAP4430_VP_MPU_TRANXDONE_ST_MASK; - vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET; - vdd->vc_reg.smps_sa_shift = - OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT; - vdd->vc_reg.smps_sa_mask = - OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK; - vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT; - vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK; - vdd->vc_reg.voltsetup_reg = - OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET; - vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET; - } else if (!strcmp(vdd->voltdm.name, "core")) { - vdd->volt_data = omap44xx_vdd_core_volt_data; - vdd->vp_reg.tranxdone_status = - OMAP4430_VP_CORE_TRANXDONE_ST_MASK; - vdd->vc_reg.cmdval_reg = - OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET; - vdd->vc_reg.smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT; - vdd->vc_reg.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK; - vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT; - vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK; - vdd->vc_reg.voltsetup_reg = - OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET; - vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET; - } else if (!strcmp(vdd->voltdm.name, "iva")) { - vdd->volt_data = omap44xx_vdd_iva_volt_data; - vdd->vp_reg.tranxdone_status = - OMAP4430_VP_IVA_TRANXDONE_ST_MASK; - vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET; - vdd->vc_reg.smps_sa_shift = - OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT; - vdd->vc_reg.smps_sa_mask = - OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK; - vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT; - vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK; - vdd->vc_reg.voltsetup_reg = - OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET; - vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET; - } else { - pr_warning("%s: vdd_%s does not exisit in OMAP4\n", - __func__, vdd->voltdm.name); - return -EINVAL; + if (IS_ERR_VALUE(_config_common_vdd_data(vdd))) + goto ovdc_out; + + if (cpu_is_omap34xx()) { + vdd->read_reg = omap3_voltage_read_reg; + vdd->write_reg = omap3_voltage_write_reg; + ret = 0; + } else if (cpu_is_omap44xx()) { + vdd->read_reg = omap4_voltage_read_reg; + vdd->write_reg = omap4_voltage_write_reg; + ret = 0; } - /* - * Sys clk rate is require to calculate vp timeout value and - * smpswaittimemin and smpswaittimemax. - */ - sys_ck = clk_get(NULL, "sys_clkin_ck"); - if (IS_ERR(sys_ck)) { - pr_warning("%s: Could not get the sys clk to calculate" - "various vdd_%s params\n", __func__, vdd->voltdm.name); - return -EINVAL; - } - sys_clk_speed = clk_get_rate(sys_ck); - clk_put(sys_ck); - /* Divide to avoid overflow */ - sys_clk_speed /= 1000; - - /* Generic voltage parameters */ - vdd->curr_volt = 1200000; - vdd->ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST; - vdd->read_reg = omap4_voltage_read_reg; - vdd->write_reg = omap4_voltage_write_reg; - vdd->volt_scale = vp_forceupdate_scale_voltage; - vdd->vp_enabled = false; - - /* VC parameters */ - vdd->vc_reg.prm_mod = OMAP4430_PRM_DEVICE_INST; - vdd->vc_reg.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET; - vdd->vc_reg.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET; - vdd->vc_reg.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET; - vdd->vc_reg.data_shift = OMAP4430_DATA_SHIFT; - vdd->vc_reg.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT; - vdd->vc_reg.regaddr_shift = OMAP4430_REGADDR_SHIFT; - vdd->vc_reg.valid = OMAP4430_VALID_MASK; - vdd->vc_reg.cmd_on_shift = OMAP4430_ON_SHIFT; - vdd->vc_reg.cmd_on_mask = OMAP4430_ON_MASK; - vdd->vc_reg.cmd_onlp_shift = OMAP4430_ONLP_SHIFT; - vdd->vc_reg.cmd_ret_shift = OMAP4430_RET_SHIFT; - vdd->vc_reg.cmd_off_shift = OMAP4430_OFF_SHIFT; - - vdd->vp_reg.prm_mod = OMAP4430_PRM_DEVICE_INST; - - /* VPCONFIG bit fields */ - vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset << - OMAP4430_ERROROFFSET_SHIFT); - vdd->vp_reg.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK; - vdd->vp_reg.vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT; - vdd->vp_reg.vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT; - vdd->vp_reg.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK; - vdd->vp_reg.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK; - vdd->vp_reg.vpconfig_initvdd = OMAP4430_INITVDD_MASK; - vdd->vp_reg.vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK; - vdd->vp_reg.vpconfig_vpenable = OMAP4430_VPENABLE_MASK; - - /* VSTEPMIN VSTEPMAX bit fields */ - waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) * - sys_clk_speed) / 1000; - vdd->vp_reg.vstepmin_smpswaittimemin = waittime; - vdd->vp_reg.vstepmax_smpswaittimemax = waittime; - vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin; - vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax; - vdd->vp_reg.vstepmin_smpswaittimemin_shift = - OMAP4430_SMPSWAITTIMEMIN_SHIFT; - vdd->vp_reg.vstepmax_smpswaittimemax_shift = - OMAP4430_SMPSWAITTIMEMAX_SHIFT; - vdd->vp_reg.vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT; - vdd->vp_reg.vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT; - - /* VLIMITTO bit fields */ - timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000; - vdd->vp_reg.vlimitto_timeout = timeout_val; - vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin; - vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax; - vdd->vp_reg.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT; - vdd->vp_reg.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT; - vdd->vp_reg.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT; - - return 0; +ovdc_out: + return ret; } /* Public functions */ @@ -1162,8 +715,7 @@ unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm) return 0; } - curr_vsel = vdd->read_reg(vdd->vp_reg.prm_mod, - vdd->vp_offs.voltage); + curr_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage); if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) { pr_warning("%s: PMIC function to convert vsel to voltage" @@ -1185,7 +737,6 @@ void omap_vp_enable(struct voltagedomain *voltdm) { struct omap_vdd_info *vdd; u32 vpconfig; - u16 mod; if (!voltdm || IS_ERR(voltdm)) { pr_warning("%s: VDD specified does not exist!\n", __func__); @@ -1199,8 +750,6 @@ void omap_vp_enable(struct voltagedomain *voltdm) return; } - mod = vdd->vp_reg.prm_mod; - /* If VP is already enabled, do nothing. Return */ if (vdd->vp_enabled) return; @@ -1208,9 +757,9 @@ void omap_vp_enable(struct voltagedomain *voltdm) vp_latch_vsel(vdd); /* Enable VP */ - vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig); - vpconfig |= vdd->vp_reg.vpconfig_vpenable; - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); + vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable; + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); vdd->vp_enabled = true; } @@ -1225,7 +774,6 @@ void omap_vp_disable(struct voltagedomain *voltdm) { struct omap_vdd_info *vdd; u32 vpconfig; - u16 mod; int timeout; if (!voltdm || IS_ERR(voltdm)) { @@ -1240,8 +788,6 @@ void omap_vp_disable(struct voltagedomain *voltdm) return; } - mod = vdd->vp_reg.prm_mod; - /* If VP is already disabled, do nothing. Return */ if (!vdd->vp_enabled) { pr_warning("%s: Trying to disable VP for vdd_%s when" @@ -1250,14 +796,14 @@ void omap_vp_disable(struct voltagedomain *voltdm) } /* Disable VP */ - vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig); - vpconfig &= ~vdd->vp_reg.vpconfig_vpenable; - vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig); + vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig); + vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable; + vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig); /* * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us */ - omap_test_timeout((vdd->read_reg(mod, vdd->vp_offs.vstatus)), + omap_test_timeout((vdd->read_reg(prm_mod_offs, vdd->vp_data->vstatus)), VP_IDLE_TIMEOUT, timeout); if (timeout >= VP_IDLE_TIMEOUT) @@ -1510,8 +1056,8 @@ struct voltagedomain *omap_voltage_domain_lookup(char *name) } for (i = 0; i < nr_scalable_vdd; i++) { - if (!(strcmp(name, vdd_info[i].voltdm.name))) - return &vdd_info[i].voltdm; + if (!(strcmp(name, vdd_info[i]->voltdm.name))) + return &vdd_info[i]->voltdm; } return ERR_PTR(-EINVAL); @@ -1539,35 +1085,24 @@ int __init omap_voltage_late_init(void) pr_err("%s: Unable to create voltage debugfs main dir\n", __func__); for (i = 0; i < nr_scalable_vdd; i++) { - if (vdd_data_configure(&vdd_info[i])) + if (omap_vdd_data_configure(vdd_info[i])) continue; - vc_init(&vdd_info[i]); - vp_init(&vdd_info[i]); - vdd_debugfs_init(&vdd_info[i]); + omap_vc_init(vdd_info[i]); + vp_init(vdd_info[i]); + vdd_debugfs_init(vdd_info[i]); } return 0; } -/** - * omap_voltage_early_init()- Volatage driver early init - */ -static int __init omap_voltage_early_init(void) +/* XXX document */ +int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_ocp_mod, + struct omap_vdd_info *omap_vdd_array[], + u8 omap_vdd_count) { - if (cpu_is_omap34xx()) { - vdd_info = omap3_vdd_info; - nr_scalable_vdd = OMAP3_NR_SCALABLE_VDD; - vc_init = omap3_vc_init; - vdd_data_configure = omap3_vdd_data_configure; - } else if (cpu_is_omap44xx()) { - vdd_info = omap4_vdd_info; - nr_scalable_vdd = OMAP4_NR_SCALABLE_VDD; - vc_init = omap4_vc_init; - vdd_data_configure = omap4_vdd_data_configure; - } else { - pr_warning("%s: voltage driver support not added\n", __func__); - } - + prm_mod_offs = prm_mod; + prm_irqst_ocp_mod_offs = prm_irqst_ocp_mod; + vdd_info = omap_vdd_array; + nr_scalable_vdd = omap_vdd_count; return 0; } -core_initcall(omap_voltage_early_init); diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h index 5bd204e55c32..e9f5408244e0 100644 --- a/arch/arm/mach-omap2/voltage.h +++ b/arch/arm/mach-omap2/voltage.h @@ -16,6 +16,10 @@ #include +#include "vc.h" +#include "vp.h" + +/* XXX document */ #define VOLTSCALE_VPFORCEUPDATE 1 #define VOLTSCALE_VCBYPASS 2 @@ -27,36 +31,22 @@ #define OMAP3_VOLTOFFSET 0xff #define OMAP3_VOLTSETUP2 0xff -/* Voltage value defines */ -#define OMAP3430_VDD_MPU_OPP1_UV 975000 -#define OMAP3430_VDD_MPU_OPP2_UV 1075000 -#define OMAP3430_VDD_MPU_OPP3_UV 1200000 -#define OMAP3430_VDD_MPU_OPP4_UV 1270000 -#define OMAP3430_VDD_MPU_OPP5_UV 1350000 - -#define OMAP3430_VDD_CORE_OPP1_UV 975000 -#define OMAP3430_VDD_CORE_OPP2_UV 1050000 -#define OMAP3430_VDD_CORE_OPP3_UV 1150000 - -#define OMAP3630_VDD_MPU_OPP50_UV 1012500 -#define OMAP3630_VDD_MPU_OPP100_UV 1200000 -#define OMAP3630_VDD_MPU_OPP120_UV 1325000 -#define OMAP3630_VDD_MPU_OPP1G_UV 1375000 - -#define OMAP3630_VDD_CORE_OPP50_UV 1000000 -#define OMAP3630_VDD_CORE_OPP100_UV 1200000 - -#define OMAP4430_VDD_MPU_OPP50_UV 930000 -#define OMAP4430_VDD_MPU_OPP100_UV 1100000 -#define OMAP4430_VDD_MPU_OPPTURBO_UV 1260000 -#define OMAP4430_VDD_MPU_OPPNITRO_UV 1350000 - -#define OMAP4430_VDD_IVA_OPP50_UV 930000 -#define OMAP4430_VDD_IVA_OPP100_UV 1100000 -#define OMAP4430_VDD_IVA_OPPTURBO_UV 1260000 - -#define OMAP4430_VDD_CORE_OPP50_UV 930000 -#define OMAP4430_VDD_CORE_OPP100_UV 1100000 +/** + * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield + * data + * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register + * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base + * @voltsetup_shift: SETUP_TIME* field shift in the PRM_VOLTSETUP* register + * + * XXX What about VOLTOFFSET/VOLTCTRL? + * XXX It is not necessary to have both a _mask and a _shift for the same + * bitfield - remove one! + */ +struct omap_vfsm_instance_data { + u32 voltsetup_mask; + u8 voltsetup_reg; + u8 voltsetup_shift; +}; /** * struct voltagedomain - omap voltage domain global structure. @@ -113,6 +103,42 @@ struct omap_volt_pmic_info { u8 (*uv_to_vsel) (unsigned long uV); }; +/** + * omap_vdd_info - Per Voltage Domain info + * + * @volt_data : voltage table having the distinct voltages supported + * by the domain and other associated per voltage data. + * @pmic_info : pmic specific parameters which should be populted by + * the pmic drivers. + * @vp_data : the register values, shifts, masks for various + * vp registers + * @vp_rt_data : VP data derived at runtime, not predefined + * @vc_data : structure containing various various vc registers, + * shifts, masks etc. + * @vfsm : voltage manager FSM data + * @voltdm : pointer to the voltage domain structure + * @debug_dir : debug directory for this voltage domain. + * @curr_volt : current voltage for this vdd. + * @vp_enabled : flag to keep track of whether vp is enabled or not + * @volt_scale : API to scale the voltage of the vdd. + */ +struct omap_vdd_info { + struct omap_volt_data *volt_data; + struct omap_volt_pmic_info *pmic_info; + struct omap_vp_instance_data *vp_data; + struct omap_vp_runtime_data vp_rt_data; + struct omap_vc_instance_data *vc_data; + const struct omap_vfsm_instance_data *vfsm; + struct voltagedomain voltdm; + struct dentry *debug_dir; + u32 curr_volt; + bool vp_enabled; + u32 (*read_reg) (u16 mod, u8 offset); + void (*write_reg) (u32 val, u16 mod, u8 offset); + int (*volt_scale) (struct omap_vdd_info *vdd, + unsigned long target_volt); +}; + unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm); void omap_vp_enable(struct voltagedomain *voltdm); void omap_vp_disable(struct voltagedomain *voltdm); @@ -125,6 +151,9 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, unsigned long volt); unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm); struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm); +int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod, + struct omap_vdd_info *omap_vdd_array[], + u8 omap_vdd_count); #ifdef CONFIG_PM int omap_voltage_register_pmic(struct voltagedomain *voltdm, struct omap_volt_pmic_info *pmic_info); diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c new file mode 100644 index 000000000000..def230fd2fde --- /dev/null +++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c @@ -0,0 +1,95 @@ +/* + * OMAP3 voltage domain data + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak + * Lesly A M + * Thara Gopinath + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +#include +#include + +#include "prm-regbits-34xx.h" +#include "omap_opp_data.h" +#include "voltage.h" +#include "vc.h" +#include "vp.h" + +/* + * VDD data + */ + +static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = { + .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET, + .voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT, + .voltsetup_mask = OMAP3430_SETUP_TIME1_MASK, +}; + +static struct omap_vdd_info omap3_vdd1_info = { + .vp_data = &omap3_vp1_data, + .vc_data = &omap3_vc1_data, + .vfsm = &omap3_vdd1_vfsm_data, + .voltdm = { + .name = "mpu", + }, +}; + +static const struct omap_vfsm_instance_data omap3_vdd2_vfsm_data = { + .voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET, + .voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT, + .voltsetup_mask = OMAP3430_SETUP_TIME2_MASK, +}; + +static struct omap_vdd_info omap3_vdd2_info = { + .vp_data = &omap3_vp2_data, + .vc_data = &omap3_vc2_data, + .vfsm = &omap3_vdd2_vfsm_data, + .voltdm = { + .name = "core", + }, +}; + +/* OMAP3 VDD structures */ +static struct omap_vdd_info *omap3_vdd_info[] = { + &omap3_vdd1_info, + &omap3_vdd2_info, +}; + +/* OMAP3 specific voltage init functions */ +static int __init omap3xxx_voltage_early_init(void) +{ + s16 prm_mod = OMAP3430_GR_MOD; + s16 prm_irqst_ocp_mod = OCP_MOD; + + if (!cpu_is_omap34xx()) + return 0; + + /* + * XXX Will depend on the process, validation, and binning + * for the currently-running IC + */ + if (cpu_is_omap3630()) { + omap3_vdd1_info.volt_data = omap36xx_vddmpu_volt_data; + omap3_vdd2_info.volt_data = omap36xx_vddcore_volt_data; + } else { + omap3_vdd1_info.volt_data = omap34xx_vddmpu_volt_data; + omap3_vdd2_info.volt_data = omap34xx_vddcore_volt_data; + } + + return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod, + omap3_vdd_info, + ARRAY_SIZE(omap3_vdd_info)); +}; +core_initcall(omap3xxx_voltage_early_init); diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c new file mode 100644 index 000000000000..cb64996de0e1 --- /dev/null +++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c @@ -0,0 +1,102 @@ +/* + * OMAP3/OMAP4 Voltage Management Routines + * + * Author: Thara Gopinath + * + * Copyright (C) 2007 Texas Instruments, Inc. + * Rajendra Nayak + * Lesly A M + * + * Copyright (C) 2008 Nokia Corporation + * Kalle Jokiniemi + * + * Copyright (C) 2010 Texas Instruments, Inc. + * Thara Gopinath + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +#include + +#include "prm-regbits-44xx.h" +#include "prm44xx.h" +#include "prcm44xx.h" +#include "prminst44xx.h" +#include "voltage.h" +#include "omap_opp_data.h" +#include "vc.h" +#include "vp.h" + +static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = { + .voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET, +}; + +static struct omap_vdd_info omap4_vdd_mpu_info = { + .vp_data = &omap4_vp_mpu_data, + .vc_data = &omap4_vc_mpu_data, + .vfsm = &omap4_vdd_mpu_vfsm_data, + .voltdm = { + .name = "mpu", + }, +}; + +static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = { + .voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET, +}; + +static struct omap_vdd_info omap4_vdd_iva_info = { + .vp_data = &omap4_vp_iva_data, + .vc_data = &omap4_vc_iva_data, + .vfsm = &omap4_vdd_iva_vfsm_data, + .voltdm = { + .name = "iva", + }, +}; + +static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = { + .voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET, +}; + +static struct omap_vdd_info omap4_vdd_core_info = { + .vp_data = &omap4_vp_core_data, + .vc_data = &omap4_vc_core_data, + .vfsm = &omap4_vdd_core_vfsm_data, + .voltdm = { + .name = "core", + }, +}; + +/* OMAP4 VDD structures */ +static struct omap_vdd_info *omap4_vdd_info[] = { + &omap4_vdd_mpu_info, + &omap4_vdd_iva_info, + &omap4_vdd_core_info, +}; + +/* OMAP4 specific voltage init functions */ +static int __init omap44xx_voltage_early_init(void) +{ + s16 prm_mod = OMAP4430_PRM_DEVICE_INST; + s16 prm_irqst_ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST; + + if (!cpu_is_omap44xx()) + return 0; + + /* + * XXX Will depend on the process, validation, and binning + * for the currently-running IC + */ + omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data; + omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data; + omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data; + + return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod, + omap4_vdd_info, + ARRAY_SIZE(omap4_vdd_info)); +}; +core_initcall(omap44xx_voltage_early_init); diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h new file mode 100644 index 000000000000..7ce134f7de79 --- /dev/null +++ b/arch/arm/mach-omap2/vp.h @@ -0,0 +1,143 @@ +/* + * OMAP3/4 Voltage Processor (VP) structure and macro definitions + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak + * Lesly A M + * Thara Gopinath + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ +#ifndef __ARCH_ARM_MACH_OMAP2_VP_H +#define __ARCH_ARM_MACH_OMAP2_VP_H + +#include + +/* XXX document */ +#define VP_IDLE_TIMEOUT 200 +#define VP_TRANXDONE_TIMEOUT 300 + + +/** + * struct omap_vp_common_data - register data common to all VDDs + * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg + * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg + * @vpconfig_timeouten_mask: TIMEOUT bitmask in the PRM_VP*_CONFIG reg + * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg + * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg + * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg + * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg + * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg + * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg + * @vpconfig_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg + * @vpconfig_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg + * @vpconfig_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg + * @vpconfig_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg + * @vpconfig_vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg + * @vpconfig_vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg + * @vpconfig_vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg + * + * XXX It it not necessary to have both a mask and a shift for the same + * bitfield - remove one + * XXX Many of these fields are wrongly named -- e.g., vpconfig_smps* -- fix! + */ +struct omap_vp_common_data { + u32 vpconfig_errorgain_mask; + u32 vpconfig_initvoltage_mask; + u32 vpconfig_timeouten; + u32 vpconfig_initvdd; + u32 vpconfig_forceupdate; + u32 vpconfig_vpenable; + u8 vpconfig_erroroffset_shift; + u8 vpconfig_errorgain_shift; + u8 vpconfig_initvoltage_shift; + u8 vstepmin_stepmin_shift; + u8 vstepmin_smpswaittimemin_shift; + u8 vstepmax_stepmax_shift; + u8 vstepmax_smpswaittimemax_shift; + u8 vlimitto_vddmin_shift; + u8 vlimitto_vddmax_shift; + u8 vlimitto_timeout_shift; +}; + +/** + * struct omap_vp_prm_irqst_data - PRM_IRQSTATUS_MPU.VP_TRANXDONE_ST data + * @prm_irqst_reg: reg offset for PRM_IRQSTATUS_MPU from top of PRM + * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg + * + * XXX prm_irqst_reg does not belong here + * XXX Note that on OMAP3, VP_TRANXDONE interrupt may not work due to a + * hardware bug + * XXX This structure is probably not needed + */ +struct omap_vp_prm_irqst_data { + u8 prm_irqst_reg; + u32 tranxdone_status; +}; + +/** + * struct omap_vp_instance_data - VP register offsets (per-VDD) + * @vp_common: pointer to struct omap_vp_common_data * for this SoC + * @prm_irqst_data: pointer to struct omap_vp_prm_irqst_data for this VDD + * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start + * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start + * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start + * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start + * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start + * + * XXX vp_common is probably not needed since it is per-SoC + */ +struct omap_vp_instance_data { + const struct omap_vp_common_data *vp_common; + const struct omap_vp_prm_irqst_data *prm_irqst_data; + u8 vpconfig; + u8 vstepmin; + u8 vstepmax; + u8 vlimitto; + u8 vstatus; + u8 voltage; +}; + +/** + * struct omap_vp_runtime_data - VP data populated at runtime by code + * @vpconfig_erroroffset: value of ERROROFFSET bitfield in PRM_VP*_CONFIG + * @vpconfig_errorgain: value of ERRORGAIN bitfield in PRM_VP*_CONFIG + * @vstepmin_smpswaittimemin: value of SMPSWAITTIMEMIN bitfield in PRM_VP*_VSTEPMIN + * @vstepmax_smpswaittimemax: value of SMPSWAITTIMEMAX bitfield in PRM_VP*_VSTEPMAX + * @vlimitto_timeout: value of TIMEOUT bitfield in PRM_VP*_VLIMITTO + * @vstepmin_stepmin: value of VSTEPMIN bitfield in PRM_VP*_VSTEPMIN + * @vstepmax_stepmax: value of VSTEPMAX bitfield in PRM_VP*_VSTEPMAX + * @vlimitto_vddmin: value of VDDMIN bitfield in PRM_VP*_VLIMITTO + * @vlimitto_vddmax: value of VDDMAX bitfield in PRM_VP*_VLIMITTO + * + * XXX Is this structure really needed? Why not just program the + * device directly? They are in PRM space, therefore in the WKUP + * powerdomain, so register contents should not be lost in off-mode. + * XXX Some of these fields are incorrectly named, e.g., vstep* + */ +struct omap_vp_runtime_data { + u32 vpconfig_erroroffset; + u16 vpconfig_errorgain; + u16 vstepmin_smpswaittimemin; + u16 vstepmax_smpswaittimemax; + u16 vlimitto_timeout; + u8 vstepmin_stepmin; + u8 vstepmax_stepmax; + u8 vlimitto_vddmin; + u8 vlimitto_vddmax; +}; + +extern struct omap_vp_instance_data omap3_vp1_data; +extern struct omap_vp_instance_data omap3_vp2_data; + +extern struct omap_vp_instance_data omap4_vp_mpu_data; +extern struct omap_vp_instance_data omap4_vp_iva_data; +extern struct omap_vp_instance_data omap4_vp_core_data; + +#endif diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c new file mode 100644 index 000000000000..645217094e51 --- /dev/null +++ b/arch/arm/mach-omap2/vp3xxx_data.c @@ -0,0 +1,82 @@ +/* + * OMAP3 Voltage Processor (VP) data + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak + * Lesly A M + * Thara Gopinath + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include + +#include "prm-regbits-34xx.h" +#include "voltage.h" + +#include "vp.h" + +/* + * VP data common to 34xx/36xx chips + * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file. + */ +static const struct omap_vp_common_data omap3_vp_common = { + .vpconfig_erroroffset_shift = OMAP3430_ERROROFFSET_SHIFT, + .vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK, + .vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT, + .vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT, + .vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK, + .vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK, + .vpconfig_initvdd = OMAP3430_INITVDD_MASK, + .vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK, + .vpconfig_vpenable = OMAP3430_VPENABLE_MASK, + .vstepmin_smpswaittimemin_shift = OMAP3430_SMPSWAITTIMEMIN_SHIFT, + .vstepmax_smpswaittimemax_shift = OMAP3430_SMPSWAITTIMEMAX_SHIFT, + .vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT, + .vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT, + .vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT, + .vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT, + .vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT, +}; + +static const struct omap_vp_prm_irqst_data omap3_vp1_prm_irqst_data = { + .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET, + .tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK, +}; + +struct omap_vp_instance_data omap3_vp1_data = { + .vp_common = &omap3_vp_common, + .vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET, + .vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET, + .vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET, + .vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET, + .vstatus = OMAP3_PRM_VP1_STATUS_OFFSET, + .voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET, + .prm_irqst_data = &omap3_vp1_prm_irqst_data, +}; + +static const struct omap_vp_prm_irqst_data omap3_vp2_prm_irqst_data = { + .prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET, + .tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK, +}; + +struct omap_vp_instance_data omap3_vp2_data = { + .vp_common = &omap3_vp_common, + .vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET, + .vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET, + .vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET, + .vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET, + .vstatus = OMAP3_PRM_VP2_STATUS_OFFSET, + .voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET, + .prm_irqst_data = &omap3_vp2_prm_irqst_data, +}; diff --git a/arch/arm/mach-omap2/vp44xx_data.c b/arch/arm/mach-omap2/vp44xx_data.c new file mode 100644 index 000000000000..65d1ad63800a --- /dev/null +++ b/arch/arm/mach-omap2/vp44xx_data.c @@ -0,0 +1,100 @@ +/* + * OMAP3 Voltage Processor (VP) data + * + * Copyright (C) 2007, 2010 Texas Instruments, Inc. + * Rajendra Nayak + * Lesly A M + * Thara Gopinath + * + * Copyright (C) 2008, 2011 Nokia Corporation + * Kalle Jokiniemi + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include + +#include "prm44xx.h" +#include "prm-regbits-44xx.h" +#include "voltage.h" + +#include "vp.h" + +/* + * VP data common to 44xx chips + * XXX This stuff presumably belongs in the vp44xx.c or vp.c file. + */ +static const struct omap_vp_common_data omap4_vp_common = { + .vpconfig_erroroffset_shift = OMAP4430_ERROROFFSET_SHIFT, + .vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK, + .vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT, + .vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT, + .vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK, + .vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK, + .vpconfig_initvdd = OMAP4430_INITVDD_MASK, + .vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK, + .vpconfig_vpenable = OMAP4430_VPENABLE_MASK, + .vstepmin_smpswaittimemin_shift = OMAP4430_SMPSWAITTIMEMIN_SHIFT, + .vstepmax_smpswaittimemax_shift = OMAP4430_SMPSWAITTIMEMAX_SHIFT, + .vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT, + .vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT, + .vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT, + .vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT, + .vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT, +}; + +static const struct omap_vp_prm_irqst_data omap4_vp_mpu_prm_irqst_data = { + .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET, + .tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK, +}; + +struct omap_vp_instance_data omap4_vp_mpu_data = { + .vp_common = &omap4_vp_common, + .vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET, + .vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET, + .vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET, + .vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET, + .vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET, + .voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET, + .prm_irqst_data = &omap4_vp_mpu_prm_irqst_data, +}; + +static const struct omap_vp_prm_irqst_data omap4_vp_iva_prm_irqst_data = { + .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, + .tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK, +}; + +struct omap_vp_instance_data omap4_vp_iva_data = { + .vp_common = &omap4_vp_common, + .vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET, + .vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET, + .vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET, + .vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET, + .vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET, + .voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET, + .prm_irqst_data = &omap4_vp_iva_prm_irqst_data, +}; + +static const struct omap_vp_prm_irqst_data omap4_vp_core_prm_irqst_data = { + .prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET, + .tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK, +}; + +struct omap_vp_instance_data omap4_vp_core_data = { + .vp_common = &omap4_vp_common, + .vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET, + .vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET, + .vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET, + .vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET, + .vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET, + .voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET, + .prm_irqst_data = &omap4_vp_core_prm_irqst_data, +}; + From 0503add9d251db22ba2f610fb8d9b7743a9786da Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 10 Mar 2011 22:40:05 -0700 Subject: [PATCH 61/62] Watchdog: omap_wdt: add fine grain runtime-pm The omap_wdt should only be in full active state when the registers are being accessed. Otherwise the device can be on lower power mode. This patch is based on a patch created by Kalle Jokiniemi: https://patchwork.kernel.org/patch/618231/ which is itself based on a patch created by Atal Shargorodsky: http://lkml.org/lkml/2009/3/10/266. Signed-off-by: Paul Walmsley Signed-off-by: Kalle Jokiniemi Tested-by: Kalle Jokiniemi Cc: Wim Van Sebroeck Acked-by: Wim Van Sebroeck Acked-by: Kevin Hilman --- drivers/watchdog/omap_wdt.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 3dd4971160ef..2b4acb86c191 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -124,6 +124,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) u32 pre_margin = GET_WLDR_VAL(timer_margin); void __iomem *base = wdev->base; + pm_runtime_get_sync(wdev->dev); + /* just count up at 32 KHz */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); @@ -131,6 +133,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) cpu_relax(); + + pm_runtime_put_sync(wdev->dev); } /* @@ -160,6 +164,8 @@ static int omap_wdt_open(struct inode *inode, struct file *file) omap_wdt_ping(wdev); /* trigger loading of new timeout value */ omap_wdt_enable(wdev); + pm_runtime_put_sync(wdev->dev); + return nonseekable_open(inode, file); } @@ -171,6 +177,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file) * Shut off the timer unless NOWAYOUT is defined. */ #ifndef CONFIG_WATCHDOG_NOWAYOUT + pm_runtime_get_sync(wdev->dev); omap_wdt_disable(wdev); @@ -190,9 +197,11 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, /* Refresh LOAD_TIME. */ if (len) { + pm_runtime_get_sync(wdev->dev); spin_lock(&wdt_lock); omap_wdt_ping(wdev); spin_unlock(&wdt_lock); + pm_runtime_put_sync(wdev->dev); } return len; } @@ -224,15 +233,18 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, return put_user(omap_prcm_get_reset_sources(), (int __user *)arg); case WDIOC_KEEPALIVE: + pm_runtime_get_sync(wdev->dev); spin_lock(&wdt_lock); omap_wdt_ping(wdev); spin_unlock(&wdt_lock); + pm_runtime_put_sync(wdev->dev); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_margin, (int __user *)arg)) return -EFAULT; omap_wdt_adjust_timeout(new_margin); + pm_runtime_get_sync(wdev->dev); spin_lock(&wdt_lock); omap_wdt_disable(wdev); omap_wdt_set_timeout(wdev); @@ -240,6 +252,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, omap_wdt_ping(wdev); spin_unlock(&wdt_lock); + pm_runtime_put_sync(wdev->dev); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timer_margin, (int __user *)arg); @@ -345,8 +358,11 @@ static void omap_wdt_shutdown(struct platform_device *pdev) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev->omap_wdt_users) + if (wdev->omap_wdt_users) { + pm_runtime_get_sync(wdev->dev); omap_wdt_disable(wdev); + pm_runtime_put_sync(wdev->dev); + } } static int __devexit omap_wdt_remove(struct platform_device *pdev) @@ -381,8 +397,11 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev->omap_wdt_users) + if (wdev->omap_wdt_users) { + pm_runtime_get_sync(wdev->dev); omap_wdt_disable(wdev); + pm_runtime_put_sync(wdev->dev); + } return 0; } @@ -392,8 +411,10 @@ static int omap_wdt_resume(struct platform_device *pdev) struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); if (wdev->omap_wdt_users) { + pm_runtime_get_sync(wdev->dev); omap_wdt_enable(wdev); omap_wdt_ping(wdev); + pm_runtime_put_sync(wdev->dev); } return 0; From 2f4dd595f6d60ec3ccbb68def73df457970cf671 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Thu, 10 Mar 2011 22:40:06 -0700 Subject: [PATCH 62/62] OMAP3: wdtimer: Fix CORE idle transition The HW superwised smart idle for wdtimer in OMAP3 prevents CORE power domain idle transitions. Disable it by swithing to SW supervised transitions. This could be a hardware bug in the OMAP3 wdtimer2 block. Signed-off-by: Kalle Jokiniemi Signed-off-by: Paul Walmsley Cc: Benoit Cousson Acked-by: Kevin Hilman --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index c4ca005f8bb5..477ba543b227 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1312,6 +1312,11 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = { .slaves = omap3xxx_wd_timer2_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_wd_timer2_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + /* + * XXX: Use software supervised mode, HW supervised smartidle seems to + * block CORE power domain idle transitions. Maybe a HW bug in wdt2? + */ + .flags = HWMOD_SWSUP_SIDLE, }; /* UART common */