* [PATCH 0/8] OMAP3: Misc VDD2 DVFS fixes @ 2009-01-09 15:49 Tero Kristo 2009-01-09 15:49 ` [PATCH 1/8] OMAP3: PM: Fixed VDD2 control to work from both sysfs and SRF API Tero Kristo 2009-01-13 17:15 ` [PATCH 0/8] OMAP3: Misc VDD2 DVFS fixes Kevin Hilman 0 siblings, 2 replies; 10+ messages in thread From: Tero Kristo @ 2009-01-09 15:49 UTC (permalink / raw) To: linux-omap Applies on top of PM branch + base VDD2 DVFS support patches. ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/8] OMAP3: PM: Fixed VDD2 control to work from both sysfs and SRF API 2009-01-09 15:49 [PATCH 0/8] OMAP3: Misc VDD2 DVFS fixes Tero Kristo @ 2009-01-09 15:49 ` Tero Kristo 2009-01-09 15:49 ` [PATCH 2/8] OMAP3: PM: Added DVFS OPP locking interface for VDD1 and VDD2 Tero Kristo 2009-01-13 17:15 ` [PATCH 0/8] OMAP3: Misc VDD2 DVFS fixes Kevin Hilman 1 sibling, 1 reply; 10+ messages in thread From: Tero Kristo @ 2009-01-09 15:49 UTC (permalink / raw) To: linux-omap SRF API for setting throughput requirement attempted to use throughput values as parameter to set_opp() and sysfs was attempting to use OPP levels (1..3.) Signed-off-by: Tero Kristo <tero.kristo@nokia.com> --- arch/arm/mach-omap2/pm.c | 8 +-- arch/arm/mach-omap2/pm.h | 1 + arch/arm/mach-omap2/resource34xx.c | 70 +++++++++++++++++---------- arch/arm/plat-omap/include/mach/omap34xx.h | 4 ++ 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 3429531..d33eba8 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -62,7 +62,6 @@ static struct kobj_attribute voltage_off_while_idle_attr = __ATTR(voltage_off_while_idle, 0644, idle_show, idle_store); #ifdef CONFIG_OMAP_PM_SRF -static struct device dummy_sysfs_dev; static ssize_t vdd_opp_show(struct kobject *, struct kobj_attribute *, char *); static ssize_t vdd_opp_store(struct kobject *k, struct kobj_attribute *, const char *buf, size_t n); @@ -137,7 +136,6 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { unsigned short value; - unsigned long bus_tput; if (sscanf(buf, "%hu", &value) != 1) return -EINVAL; @@ -147,15 +145,13 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, printk(KERN_ERR "vdd_opp_store: Invalid value\n"); return -EINVAL; } - resource_request("vdd1_opp", &dummy_sysfs_dev, value); + set_opp_level(VDD1_OPP, value); } else if (attr == &vdd2_opp_attr) { if (value < 2 || value > 3) { printk(KERN_ERR "vdd_opp_store: Invalid value\n"); return -EINVAL; } - /* Convert OPP's requested to appr. bus throughtput in KiB/s */ - bus_tput = ((l3_opps + value)->rate/1000) * 4; - resource_request("vdd2_opp", &dummy_sysfs_dev, bus_tput); + set_opp_level(VDD2_OPP, value); } else { return -EINVAL; } diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index a209819..4c0052f 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -42,6 +42,7 @@ extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state); #define omap3_pm_set_suspend_state(pwrdm,state) do {} while (0); #endif extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state); +extern int set_opp_level(int res, u32 target_level); #ifdef CONFIG_PM_DEBUG extern void omap2_pm_dump(int mode, int resume, unsigned int us); diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c index cb9bff0..15e6d89 100644 --- a/arch/arm/mach-omap2/resource34xx.c +++ b/arch/arm/mach-omap2/resource34xx.c @@ -135,6 +135,8 @@ int set_pd_latency(struct shared_resource *resp, u32 latency) static struct clk *vdd1_clk; static struct clk *vdd2_clk; +static struct shared_resource *vdd1_resp; +static struct shared_resource *vdd2_resp; static struct device dummy_mpu_dev; static struct device dummy_dsp_dev; @@ -154,20 +156,29 @@ void init_opp(struct shared_resource *resp) if (strcmp(resp->name, "vdd1_opp") == 0) { resp->curr_level = curr_vdd1_prcm_set->opp_id; vdd1_clk = clk_get(NULL, "virt_vdd1_prcm_set"); + vdd1_resp = resp; } else if (strcmp(resp->name, "vdd2_opp") == 0) { resp->curr_level = curr_vdd2_prcm_set->opp_id; vdd2_clk = clk_get(NULL, "virt_vdd2_prcm_set"); + vdd2_resp = resp; } return; } static struct device vdd2_dev; -int set_opp(struct shared_resource *resp, u32 target_level) +int set_opp_level(int res, u32 target_level) { - unsigned long mpu_freq, mpu_old_freq, l3_freq, req_l3_freq, tput, t_opp; - int ind; + unsigned long mpu_freq, mpu_old_freq, l3_freq, req_l3_freq, t_opp; struct cpufreq_freqs freqs_notify; + struct shared_resource *resp; + + if (res == VDD1_OPP) + resp = vdd1_resp; + else if (res == VDD2_OPP) + resp = vdd2_resp; + else + return 0; if (resp->curr_level == target_level) return 0; @@ -175,7 +186,7 @@ int set_opp(struct shared_resource *resp, u32 target_level) if (!mpu_opps || !dsp_opps || !l3_opps) return 0; - if (strcmp(resp->name, "vdd1_opp") == 0) { + if (res == VDD1_OPP) { mpu_old_freq = get_freq(mpu_opps + MAX_VDD1_OPP, curr_vdd1_prcm_set->opp_id); mpu_freq = get_freq(mpu_opps + MAX_VDD1_OPP, @@ -222,28 +233,7 @@ int set_opp(struct shared_resource *resp, u32 target_level) /* Send a post notification to CPUFreq */ cpufreq_notify_transition(&freqs_notify, CPUFREQ_POSTCHANGE); #endif - } else if (strcmp(resp->name, "vdd2_opp") == 0) { - tput = target_level; - - /* Convert the tput in KiB/s to Bus frequency in Mhz*/ - req_l3_freq = (tput * 1000)/4; - - for (ind = 2; ind <= MAX_VDD2_OPP; ind++) { - if ((l3_opps + ind)->rate >= req_l3_freq) { - target_level = ind; - break; - } - } - - /* Set the highest OPP possible */ - if (ind > MAX_VDD2_OPP) - target_level = MAX_VDD2_OPP; - - if (resp->curr_level == target_level) - return 0; - - resp->curr_level = target_level; - + } else { l3_freq = get_freq(l3_opps + MAX_VDD2_OPP, target_level); t_opp = ID_VDD(PRCM_VDD2) | @@ -268,6 +258,34 @@ int set_opp(struct shared_resource *resp, u32 target_level) return 0; } +int set_opp(struct shared_resource *resp, u32 target_level) +{ + unsigned long tput; + unsigned long req_l3_freq; + int ind; + + if (resp == vdd1_resp) { + set_opp_level(VDD1_OPP, target_level); + } else if (resp == vdd2_resp) { + tput = target_level; + + /* Convert the tput in KiB/s to Bus frequency in MHz */ + req_l3_freq = (tput * 1000)/4; + + for (ind = 2; ind <= MAX_VDD2_OPP; ind++) + if ((l3_opps + ind)->rate >= req_l3_freq) { + target_level = ind; + break; + } + + /* Set the highest OPP possible */ + if (ind > MAX_VDD2_OPP) + target_level = ind-1; + set_opp_level(VDD2_OPP, target_level); + } + return 0; +} + /** * validate_opp - Validates if valid VDD1 OPP's are passed as the * target_level. diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 2e4e4ed..382e741 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -74,6 +74,10 @@ #define OMAP34XX_DSP_IPI_BASE (OMAP34XX_DSP_BASE + 0x1000000) #define OMAP34XX_DSP_MMU_BASE (OMAP34XX_DSP_BASE + 0x2000000) +/* VDD OPP identifiers */ +#define VDD1_OPP 0x1 +#define VDD2_OPP 0x2 + /* VDD1 OPPS */ #define VDD1_OPP1 0x1 #define VDD1_OPP2 0x2 -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/8] OMAP3: PM: Added DVFS OPP locking interface for VDD1 and VDD2 2009-01-09 15:49 ` [PATCH 1/8] OMAP3: PM: Fixed VDD2 control to work from both sysfs and SRF API Tero Kristo @ 2009-01-09 15:49 ` Tero Kristo 2009-01-09 15:49 ` [PATCH 3/8] OMAP3: Fix rate calculation bug in omap3_select_table_rate Tero Kristo 0 siblings, 1 reply; 10+ messages in thread From: Tero Kristo @ 2009-01-09 15:49 UTC (permalink / raw) To: linux-omap Added two new files under /sys/power for controlling OPP locks. vdd1_lock and vdd2_lock. You can write to these to select desired OPP level and it will be locked at that level. Lock can be cleared by writing 0 to the same file. Signed-off-by: Tero Kristo <tero.kristo@nokia.com> --- arch/arm/mach-omap2/pm.c | 55 ++++++++++++++++++++++++++++++++++- arch/arm/mach-omap2/pm.h | 8 ++++- arch/arm/mach-omap2/resource34xx.c | 24 +++++++++++++-- 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index d33eba8..186a0f0 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -44,6 +44,8 @@ unsigned short clocks_off_while_idle; unsigned short enable_off_mode; unsigned short voltage_off_while_idle; atomic_t sleep_block = ATOMIC_INIT(0); +static int vdd1_locked; +static int vdd2_locked; static ssize_t idle_show(struct kobject *, struct kobj_attribute *, char *); static ssize_t idle_store(struct kobject *k, struct kobj_attribute *, @@ -70,6 +72,11 @@ static struct kobj_attribute vdd1_opp_attr = static struct kobj_attribute vdd2_opp_attr = __ATTR(vdd2_opp, 0644, vdd_opp_show, vdd_opp_store); +static struct kobj_attribute vdd1_lock_attr = + __ATTR(vdd1_lock, 0644, vdd_opp_show, vdd_opp_store); +static struct kobj_attribute vdd2_lock_attr = + __ATTR(vdd2_lock, 0644, vdd_opp_show, vdd_opp_store); + #endif static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr, @@ -128,6 +135,10 @@ static ssize_t vdd_opp_show(struct kobject *kobj, struct kobj_attribute *attr, return sprintf(buf, "%hu\n", resource_get_level("vdd1_opp")); else if (attr == &vdd2_opp_attr) return sprintf(buf, "%hu\n", resource_get_level("vdd2_opp")); + else if (attr == &vdd1_lock_attr) + return sprintf(buf, "%hu\n", resource_get_opp_lock(VDD1_OPP)); + else if (attr == &vdd2_lock_attr) + return sprintf(buf, "%hu\n", resource_get_opp_lock(VDD2_OPP)); else return -EINVAL; } @@ -136,22 +147,50 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { unsigned short value; + int flags = 0; if (sscanf(buf, "%hu", &value) != 1) return -EINVAL; + /* Check locks */ + if (attr == &vdd1_lock_attr) { + flags = OPP_IGNORE_LOCK; + attr = &vdd1_opp_attr; + if (vdd1_locked && value == 0) { + resource_unlock_opp(VDD1_OPP); + vdd1_locked = 0; + return n; + } + if (vdd1_locked == 0 && value != 0) { + resource_lock_opp(VDD1_OPP); + vdd1_locked = 1; + } + } else if (attr == &vdd2_lock_attr) { + flags = OPP_IGNORE_LOCK; + attr = &vdd2_opp_attr; + if (vdd2_locked && value == 0) { + resource_unlock_opp(VDD2_OPP); + vdd2_locked = 0; + return n; + } + if (vdd2_locked == 0 && value != 0) { + resource_lock_opp(VDD2_OPP); + vdd2_locked = 1; + } + } + if (attr == &vdd1_opp_attr) { if (value < 1 || value > 5) { printk(KERN_ERR "vdd_opp_store: Invalid value\n"); return -EINVAL; } - set_opp_level(VDD1_OPP, value); + resource_set_opp_level(VDD1_OPP, value, flags); } else if (attr == &vdd2_opp_attr) { if (value < 2 || value > 3) { printk(KERN_ERR "vdd_opp_store: Invalid value\n"); return -EINVAL; } - set_opp_level(VDD2_OPP, value); + resource_set_opp_level(VDD2_OPP, value, flags); } else { return -EINVAL; } @@ -228,6 +267,18 @@ static int __init omap_pm_init(void) printk(KERN_ERR "sysfs_create_file failed: %d\n", error); return error; } + + error = sysfs_create_file(power_kobj, &vdd1_lock_attr.attr); + if (error) { + printk(KERN_ERR "sysfs_create_file failed: %d\n", error); + return error; + } + + error = sysfs_create_file(power_kobj, &vdd2_lock_attr.attr); + if (error) { + printk(KERN_ERR "sysfs_create_file failed: %d\n", error); + return error; + } #endif voltage_off_while_idle = 0; /* Going to 0V on anything under ES2.1 will eventually cause a crash */ diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 4c0052f..4f98c86 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -42,7 +42,13 @@ extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state); #define omap3_pm_set_suspend_state(pwrdm,state) do {} while (0); #endif extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state); -extern int set_opp_level(int res, u32 target_level); +extern int resource_set_opp_level(int res, u32 target_level, int flags); +extern int resource_access_opp_lock(int res, int delta); +#define resource_lock_opp(res) resource_access_opp_lock(res, 1) +#define resource_unlock_opp(res) resource_access_opp_lock(res, -1) +#define resource_get_opp_lock(res) resource_access_opp_lock(res, 0) + +#define OPP_IGNORE_LOCK 0x1 #ifdef CONFIG_PM_DEBUG extern void omap2_pm_dump(int mode, int resume, unsigned int us); diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c index 15e6d89..f862ee6 100644 --- a/arch/arm/mach-omap2/resource34xx.c +++ b/arch/arm/mach-omap2/resource34xx.c @@ -139,6 +139,8 @@ static struct shared_resource *vdd1_resp; static struct shared_resource *vdd2_resp; static struct device dummy_mpu_dev; static struct device dummy_dsp_dev; +static int vdd1_lock; +static int vdd2_lock; /** * init_opp - Initialize the OPP resource @@ -167,7 +169,19 @@ void init_opp(struct shared_resource *resp) static struct device vdd2_dev; -int set_opp_level(int res, u32 target_level) +int resource_access_opp_lock(int res, int delta) +{ + if (res == VDD1_OPP) { + vdd1_lock += delta; + return vdd1_lock; + } else if (res == VDD2_OPP) { + vdd2_lock += delta; + return vdd2_lock; + } + return -EINVAL; +} + +int resource_set_opp_level(int res, u32 target_level, int flags) { unsigned long mpu_freq, mpu_old_freq, l3_freq, req_l3_freq, t_opp; struct cpufreq_freqs freqs_notify; @@ -187,6 +201,8 @@ int set_opp_level(int res, u32 target_level) return 0; if (res == VDD1_OPP) { + if (flags != OPP_IGNORE_LOCK && vdd1_lock) + return 0; mpu_old_freq = get_freq(mpu_opps + MAX_VDD1_OPP, curr_vdd1_prcm_set->opp_id); mpu_freq = get_freq(mpu_opps + MAX_VDD1_OPP, @@ -234,6 +250,8 @@ int set_opp_level(int res, u32 target_level) cpufreq_notify_transition(&freqs_notify, CPUFREQ_POSTCHANGE); #endif } else { + if (flags != OPP_IGNORE_LOCK && vdd2_lock) + return 0; l3_freq = get_freq(l3_opps + MAX_VDD2_OPP, target_level); t_opp = ID_VDD(PRCM_VDD2) | @@ -265,7 +283,7 @@ int set_opp(struct shared_resource *resp, u32 target_level) int ind; if (resp == vdd1_resp) { - set_opp_level(VDD1_OPP, target_level); + resource_set_opp_level(VDD1_OPP, target_level, 0); } else if (resp == vdd2_resp) { tput = target_level; @@ -281,7 +299,7 @@ int set_opp(struct shared_resource *resp, u32 target_level) /* Set the highest OPP possible */ if (ind > MAX_VDD2_OPP) target_level = ind-1; - set_opp_level(VDD2_OPP, target_level); + resource_set_opp_level(VDD2_OPP, target_level, 0); } return 0; } -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/8] OMAP3: Fix rate calculation bug in omap3_select_table_rate 2009-01-09 15:49 ` [PATCH 2/8] OMAP3: PM: Added DVFS OPP locking interface for VDD1 and VDD2 Tero Kristo @ 2009-01-09 15:49 ` Tero Kristo 2009-01-09 15:49 ` [PATCH 4/8] OMAP3: PM: Prevented DVFS state switches when enabling off-mode Tero Kristo 0 siblings, 1 reply; 10+ messages in thread From: Tero Kristo @ 2009-01-09 15:49 UTC (permalink / raw) To: linux-omap L3 divisor is not taken into account when trying to set DPLL3 clock. Signed-off-by: Tero Kristo <tero.kristo@nokia.com> --- arch/arm/mach-omap2/clock34xx.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index b565ee6..8b375a9 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -959,6 +959,7 @@ static int omap3_select_table_rate(struct clk *clk, unsigned long rate) struct omap_opp *prcm_vdd = NULL; unsigned long found_speed = 0, curr_mpu_speed; int index = 0; + int l3_div; if ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set)) return -EINVAL; @@ -1000,7 +1001,9 @@ static int omap3_select_table_rate(struct clk *clk, unsigned long rate) curr_mpu_speed/1000, found_speed/1000); #endif } else { - clk_set_rate(dpll3_clk, prcm_vdd->rate); + l3_div = cm_read_mod_reg(CORE_MOD, CM_CLKSEL) & + OMAP3430_CLKSEL_L3_MASK; + clk_set_rate(dpll3_clk, prcm_vdd->rate * l3_div); curr_vdd2_prcm_set = prcm_vdd; } -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/8] OMAP3: PM: Prevented DVFS state switches when enabling off-mode 2009-01-09 15:49 ` [PATCH 3/8] OMAP3: Fix rate calculation bug in omap3_select_table_rate Tero Kristo @ 2009-01-09 15:49 ` Tero Kristo 2009-01-09 15:49 ` [PATCH 5/8] OMAP3: PM: Enable VDD2 OPP1 Tero Kristo 0 siblings, 1 reply; 10+ messages in thread From: Tero Kristo @ 2009-01-09 15:49 UTC (permalink / raw) To: linux-omap resource_refresh() call tried to refresh DVFS OPP levels also. This should eventually be fixed in a way that DVFS VDD2 level is actually governed by something. Signed-off-by: Tero Kristo <tero.kristo@nokia.com> --- arch/arm/mach-omap2/pm34xx.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 7879589..301963e 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -843,8 +843,12 @@ void omap3_pm_off_mode_enable(int enable) state = PWRDM_POWER_RET; #ifdef CONFIG_OMAP_PM_SRF + resource_lock_opp(VDD1_OPP); + resource_lock_opp(VDD2_OPP); if (resource_refresh()) printk(KERN_ERR "Error: could not refresh resources\n"); + resource_unlock_opp(VDD1_OPP); + resource_unlock_opp(VDD2_OPP); #endif list_for_each_entry(pwrst, &pwrst_list, node) { pwrst->next_state = state; -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/8] OMAP3: PM: Enable VDD2 OPP1 2009-01-09 15:49 ` [PATCH 4/8] OMAP3: PM: Prevented DVFS state switches when enabling off-mode Tero Kristo @ 2009-01-09 15:49 ` Tero Kristo 2009-01-09 15:49 ` [PATCH 6/8] OMAP3: PM: Fix linker error without CONFIG_PM option Tero Kristo 0 siblings, 1 reply; 10+ messages in thread From: Tero Kristo @ 2009-01-09 15:49 UTC (permalink / raw) To: linux-omap VDD2 OPP1 works at least with minimal kernel setup, there are some corner cases where it fails though, like when you use USB. Board setup should make sure and enable only working OPPs. Signed-off-by: Tero Kristo <tero.kristo@nokia.com> --- arch/arm/mach-omap2/pm.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 186a0f0..61c6dfb 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -186,7 +186,7 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, } resource_set_opp_level(VDD1_OPP, value, flags); } else if (attr == &vdd2_opp_attr) { - if (value < 2 || value > 3) { + if (value < 1 || value > 3) { printk(KERN_ERR "vdd_opp_store: Invalid value\n"); return -EINVAL; } -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/8] OMAP3: PM: Fix linker error without CONFIG_PM option 2009-01-09 15:49 ` [PATCH 5/8] OMAP3: PM: Enable VDD2 OPP1 Tero Kristo @ 2009-01-09 15:49 ` Tero Kristo 2009-01-09 15:49 ` [PATCH 7/8] PM: OMAP3: Removed a couple of unused variables from DVFS code Tero Kristo 0 siblings, 1 reply; 10+ messages in thread From: Tero Kristo @ 2009-01-09 15:49 UTC (permalink / raw) To: linux-omap omap3_save_scratchpad_contents() is not available without CONFIG_PM. Signed-off-by: Tero Kristo <tero.kristo@nokia.com> --- arch/arm/mach-omap2/clock34xx.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 8b375a9..6c5254c 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -1007,7 +1007,9 @@ static int omap3_select_table_rate(struct clk *clk, unsigned long rate) curr_vdd2_prcm_set = prcm_vdd; } +#ifdef CONFIG_PM omap3_save_scratchpad_contents(); +#endif return 0; } -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 7/8] PM: OMAP3: Removed a couple of unused variables from DVFS code 2009-01-09 15:49 ` [PATCH 6/8] OMAP3: PM: Fix linker error without CONFIG_PM option Tero Kristo @ 2009-01-09 15:49 ` Tero Kristo 2009-01-09 15:49 ` [PATCH 8/8] PM: OMAP3: Added support for possibly failing clk_set_rate to DVFS Tero Kristo 0 siblings, 1 reply; 10+ messages in thread From: Tero Kristo @ 2009-01-09 15:49 UTC (permalink / raw) To: linux-omap - freqs_notify is only used by CPU_FREQ => added compiler flags - req_l3_freq was a copy paste bug and was never used by this function => rm Signed-off-by: Tero Kristo <tero.kristo@nokia.com> --- arch/arm/mach-omap2/resource34xx.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c index f862ee6..aec2bcb 100644 --- a/arch/arm/mach-omap2/resource34xx.c +++ b/arch/arm/mach-omap2/resource34xx.c @@ -183,8 +183,10 @@ int resource_access_opp_lock(int res, int delta) int resource_set_opp_level(int res, u32 target_level, int flags) { - unsigned long mpu_freq, mpu_old_freq, l3_freq, req_l3_freq, t_opp; + unsigned long mpu_freq, mpu_old_freq, l3_freq, t_opp; +#ifdef CONFIG_CPU_FREQ struct cpufreq_freqs freqs_notify; +#endif struct shared_resource *resp; if (res == VDD1_OPP) -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 8/8] PM: OMAP3: Added support for possibly failing clk_set_rate to DVFS 2009-01-09 15:49 ` [PATCH 7/8] PM: OMAP3: Removed a couple of unused variables from DVFS code Tero Kristo @ 2009-01-09 15:49 ` Tero Kristo 0 siblings, 0 replies; 10+ messages in thread From: Tero Kristo @ 2009-01-09 15:49 UTC (permalink / raw) To: linux-omap clk_set_rate() can fail in a case where a driver denies frequency change, this can happen after Paul's clk notifier code has been applied. This patch makes DVFS VDD2 control handle this situation correctly. Signed-off-by: Tero Kristo <tero.kristo@nokia.com> --- arch/arm/mach-omap2/clock34xx.c | 5 ++++- arch/arm/mach-omap2/resource34xx.c | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 6c5254c..17102ba 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -960,6 +960,7 @@ static int omap3_select_table_rate(struct clk *clk, unsigned long rate) unsigned long found_speed = 0, curr_mpu_speed; int index = 0; int l3_div; + int ret; if ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set)) return -EINVAL; @@ -1003,7 +1004,9 @@ static int omap3_select_table_rate(struct clk *clk, unsigned long rate) } else { l3_div = cm_read_mod_reg(CORE_MOD, CM_CLKSEL) & OMAP3430_CLKSEL_L3_MASK; - clk_set_rate(dpll3_clk, prcm_vdd->rate * l3_div); + ret = clk_set_rate(dpll3_clk, prcm_vdd->rate * l3_div); + if (ret) + return ret; curr_vdd2_prcm_set = prcm_vdd; } diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c index aec2bcb..2328323 100644 --- a/arch/arm/mach-omap2/resource34xx.c +++ b/arch/arm/mach-omap2/resource34xx.c @@ -188,6 +188,7 @@ int resource_set_opp_level(int res, u32 target_level, int flags) struct cpufreq_freqs freqs_notify; #endif struct shared_resource *resp; + int ret; if (res == VDD1_OPP) resp = vdd1_resp; @@ -260,7 +261,9 @@ int resource_set_opp_level(int res, u32 target_level, int flags) ID_OPP_NO(l3_opps[target_level].opp_id); if (resp->curr_level > target_level) { /* Scale Frequency and then voltage */ - clk_set_rate(vdd2_clk, l3_freq); + ret = clk_set_rate(vdd2_clk, l3_freq); + if (ret) + return ret; #ifdef CONFIG_OMAP_SMARTREFLEX sr_voltagescale_vcbypass(t_opp, l3_opps[target_level].vsel); @@ -271,7 +274,18 @@ int resource_set_opp_level(int res, u32 target_level, int flags) sr_voltagescale_vcbypass(t_opp, l3_opps[target_level].vsel); #endif - clk_set_rate(vdd2_clk, l3_freq); + ret = clk_set_rate(vdd2_clk, l3_freq); + if (ret) { +#ifdef CONFIG_OMAP_SMARTREFLEX + /* Setting clock failed, revert voltage */ + t_opp = ID_VDD(PRCM_VDD2) | + ID_OPP_NO(l3_opps[resp->curr_level]. + opp_id); + sr_voltagescale_vcbypass(t_opp, + l3_opps[resp->curr_level].vsel); +#endif + return ret; + } } resp->curr_level = curr_vdd2_prcm_set->opp_id; } -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/8] OMAP3: Misc VDD2 DVFS fixes 2009-01-09 15:49 [PATCH 0/8] OMAP3: Misc VDD2 DVFS fixes Tero Kristo 2009-01-09 15:49 ` [PATCH 1/8] OMAP3: PM: Fixed VDD2 control to work from both sysfs and SRF API Tero Kristo @ 2009-01-13 17:15 ` Kevin Hilman 1 sibling, 0 replies; 10+ messages in thread From: Kevin Hilman @ 2009-01-13 17:15 UTC (permalink / raw) To: Tero Kristo; +Cc: linux-omap Tero Kristo <tero.kristo@nokia.com> writes: > Applies on top of PM branch + base VDD2 DVFS support patches. > Thanks, pulling into PM branch. Kevin ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-01-13 17:15 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-01-09 15:49 [PATCH 0/8] OMAP3: Misc VDD2 DVFS fixes Tero Kristo 2009-01-09 15:49 ` [PATCH 1/8] OMAP3: PM: Fixed VDD2 control to work from both sysfs and SRF API Tero Kristo 2009-01-09 15:49 ` [PATCH 2/8] OMAP3: PM: Added DVFS OPP locking interface for VDD1 and VDD2 Tero Kristo 2009-01-09 15:49 ` [PATCH 3/8] OMAP3: Fix rate calculation bug in omap3_select_table_rate Tero Kristo 2009-01-09 15:49 ` [PATCH 4/8] OMAP3: PM: Prevented DVFS state switches when enabling off-mode Tero Kristo 2009-01-09 15:49 ` [PATCH 5/8] OMAP3: PM: Enable VDD2 OPP1 Tero Kristo 2009-01-09 15:49 ` [PATCH 6/8] OMAP3: PM: Fix linker error without CONFIG_PM option Tero Kristo 2009-01-09 15:49 ` [PATCH 7/8] PM: OMAP3: Removed a couple of unused variables from DVFS code Tero Kristo 2009-01-09 15:49 ` [PATCH 8/8] PM: OMAP3: Added support for possibly failing clk_set_rate to DVFS Tero Kristo 2009-01-13 17:15 ` [PATCH 0/8] OMAP3: Misc VDD2 DVFS fixes Kevin Hilman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox