Fix crash on non-3430SDP platforms with DVFS/CPUFreq
Subsystems (5)
PATCH 1/1 Fix crash on non-3430SDP platforms with DVFS/CPUFreq
The SRF/DVFS + CPUFreq patches had issues booting on non-3430SDP platforms as reported by Kevin Hilman. This patch puts non-NULL checks in place for mpu_opps/dsp_opps /l3_opps before accessing them and fixes the issue.
This fix/patch can be applied on top of pm-20081119 branch
+ [PATCH 00/08] OMAP3 SRF: OPP and Frequency resources
+ [PATCH 00/03] OMAP3 PM: CPUFreq driver for OMAP3
--- arch/arm/mach-omap2/clock34xx.c | 33 ++++++++++++++++++++--------- arch/arm/mach-omap2/pm.h | 18 --------------- arch/arm/mach-omap2/resource34xx.c | 21 ++++++++++++++++++ arch/arm/plat-omap/cpu-omap.c | 6 +---- arch/arm/plat-omap/include/mach/omap34xx.h | 18 +++++++++++++++ 5 files changed, 64 insertions(+), 32 deletions(-)
arch/arm/mach-omap2/clock34xx.c +23 -10
@@ -666,6 +666,9 @@ void omap2_clk_init_cpufreq_table(structstruct omap_opp *prcm;int i =0 ; +if (!mpu_opps) +return ; +/* Avoid registering the 120% Overdrive with CPUFreq */ prcm = mpu_opps +MAX_VDD1_OPP -1 ;for (; prcm->rate; prcm--) {
@@ -798,20 +801,24 @@ int __init omap2_clk_init(void) dpll3_clk =clk_get (NULL ,"dpll3_m2_ck" ); mpu_speed = dpll1_clk->rate; - prcm_vdd = mpu_opps +MAX_VDD1_OPP ; -for (; prcm_vdd->rate; prcm_vdd--) { -if (prcm_vdd->rate <= mpu_speed) { - curr_vdd1_prcm_set = prcm_vdd; -break ; +if (mpu_opps) { + prcm_vdd = mpu_opps +MAX_VDD1_OPP ; +for (; prcm_vdd->rate; prcm_vdd--) { +if (prcm_vdd->rate <= mpu_speed) { + curr_vdd1_prcm_set = prcm_vdd; +break ; + } } } core_speed = dpll3_clk->rate; - prcm_vdd = l3_opps +MAX_VDD2_OPP ; -for (; prcm_vdd->rate; prcm_vdd--) { -if (prcm_vdd->rate <= core_speed) { - curr_vdd2_prcm_set = prcm_vdd; -break ; +if (l3_opps) { + prcm_vdd = l3_opps +MAX_VDD2_OPP ; +for (; prcm_vdd->rate; prcm_vdd--) { +if (prcm_vdd->rate <= core_speed) { + curr_vdd2_prcm_set = prcm_vdd; +break ; + } } }
@@ -878,6 +885,9 @@ static long omap3_round_to_table_rate(stif ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set))return -EINVAL ; +if (!mpu_opps || !dsp_opps || !l3_opps) +return -EINVAL ; + highest_rate = -EINVAL ;if (clk == &virt_vdd1_prcm_set)
@@ -904,6 +914,9 @@ static int omap3_select_table_rate(strucif ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set))return -EINVAL ; +if (!mpu_opps || !dsp_opps || !l3_opps) +return -EINVAL ; +if (clk == &virt_vdd1_prcm_set) { prcm_vdd = mpu_opps +MAX_VDD1_OPP ; index =MAX_VDD1_OPP ;
arch/arm/mach-omap2/pm.h +0 -18
@@ -39,24 +39,6 @@ extern void omap3_pm_off_mode_enable(int#endif extern int set_pwrdm_state (struct powerdomain *pwrdm,u32 state); - -/* VDD1 OPPS */ -#define VDD1_OPP1 0x1 -#define VDD1_OPP2 0x2 -#define VDD1_OPP3 0x3 -#define VDD1_OPP4 0x4 -#define VDD1_OPP5 0x5 - -/* VDD2 OPPS */ -#define VDD2_OPP1 0x1 -#define VDD2_OPP2 0x2 -#define VDD2_OPP3 0x3 - -#define MIN_VDD1_OPP VDD1_OPP1 -#define MAX_VDD1_OPP VDD1_OPP5 -#define MIN_VDD2_OPP VDD2_OPP1 -#define MAX_VDD2_OPP VDD2_OPP3 -#ifdef CONFIG_PM_DEBUG extern u32 omap2_read_32k_sync_counter (void );extern void omap2_pm_dump (int mode,int resume,unsigned int us);
arch/arm/mach-omap2/resource34xx.c +21 -0
@@ -144,6 +144,10 @@ static struct device dummy_dsp_dev;void init_opp (struct shared_resource *resp) { resp->no_of_users =0 ; + +if (!mpu_opps || !dsp_opps || !l3_opps) +return 0 ; +/* Initialize the current level of the OPP resource * to the opp set by u-boot. */
@@ -167,6 +171,9 @@ int set_opp(struct shared_resource *respif (resp->curr_level == target_level)return 0 ; +if (!mpu_opps || !dsp_opps || !l3_opps) +return 0 ; +if (strcmp (resp->name,"vdd1_opp" ) ==0 ) { mpu_old_freq =get_freq (mpu_opps +MAX_VDD1_OPP , curr_vdd1_prcm_set->opp_id);
@@ -184,12 +191,16 @@ int set_opp(struct shared_resource *respif (resp->curr_level > target_level) {/* Scale Frequency and then voltage */ clk_set_rate (vdd1_clk, mpu_freq); +#ifdef CONFIG_OMAP_SMARTREFLEX sr_voltagescale_vcbypass (t_opp, mpu_opps[target_level].vsel); +#endif }else { +#ifdef CONFIG_OMAP_SMARTREFLEX /* Scale Voltage and then frequency */ sr_voltagescale_vcbypass (t_opp, mpu_opps[target_level].vsel); +#endif clk_set_rate (vdd1_clk, mpu_freq); } resp->curr_level = curr_vdd1_prcm_set->opp_id;
@@ -221,12 +232,16 @@ int set_opp(struct shared_resource *respif (resp->curr_level > target_level) {/* Scale Frequency and then voltage */ clk_set_rate (vdd2_clk, l3_freq); +#ifdef CONFIG_OMAP_SMARTREFLEX sr_voltagescale_vcbypass (t_opp, l3_opps[target_level].vsel); +#endif }else { +#ifdef CONFIG_OMAP_SMARTREFLEX /* Scale Voltage and then frequency */ sr_voltagescale_vcbypass (t_opp, l3_opps[target_level].vsel); +#endif clk_set_rate (vdd2_clk, l3_freq); } resp->curr_level = curr_vdd2_prcm_set->opp_id;
@@ -253,6 +268,9 @@ void init_freq(struct shared_resource *rchar *linked_res_name; resp->no_of_users =0 ; +if (!mpu_opps || !dsp_opps) +return ; + linked_res_name = (char *)resp->resource_data;/* Initialize the current level of the Freq resource * to the frequency set by u-boot.
@@ -271,6 +289,9 @@ int set_freq(struct shared_resource *res {unsigned int vdd1_opp; +if (!mpu_opps || !dsp_opps) +return 0 ; +if (strcmp (resp->name,"mpu_freq" ) ==0 ) { vdd1_opp =get_opp (mpu_opps +MAX_VDD1_OPP , target_level);resource_request ("vdd1_opp" , &dummy_mpu_dev, vdd1_opp);
arch/arm/plat-omap/cpu-omap.c +2 -4
@@ -31,7 +31,6 @@#include <mach/clock.h> #if defined(CONFIG_ARCH_OMAP3 ) && !defined(CONFIG_OMAP_PM_NONE )#include <mach/omap-pm.h> -#include "../mach-omap2/pm.h" #endif #define VERY_HI_RATE 900000000
@@ -107,9 +106,8 @@ static int omap_target(struct cpufreq_po#endif ret =clk_set_rate (mpu_clk, freqs.new *1000 );cpufreq_notify_transition (&freqs,CPUFREQ_POSTCHANGE ); -#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)\ - && defined(CONFIG_MACH_OMAP_3430SDP) - { +#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) +if (mpu_opps) {int ind;for (ind =1 ; ind <=MAX_VDD1_OPP ; ind++) {if (mpu_opps[ind].rate/1000 >= freqs.new) {
arch/arm/plat-omap/include/mach/omap34xx.h +18 -0
@@ -71,5 +71,23 @@#define OMAP34XX_DSP_MEM_BASE (OMAP34XX_DSP_BASE + 0x0)#define OMAP34XX_DSP_IPI_BASE (OMAP34XX_DSP_BASE + 0x1000000)#define OMAP34XX_DSP_MMU_BASE (OMAP34XX_DSP_BASE + 0x2000000) + +/* VDD1 OPPS */ +#define VDD1_OPP1 0x1 +#define VDD1_OPP2 0x2 +#define VDD1_OPP3 0x3 +#define VDD1_OPP4 0x4 +#define VDD1_OPP5 0x5 + +/* VDD2 OPPS */ +#define VDD2_OPP1 0x1 +#define VDD2_OPP2 0x2 +#define VDD2_OPP3 0x3 + +#define MIN_VDD1_OPP VDD1_OPP1 +#define MAX_VDD1_OPP VDD1_OPP5 +#define MIN_VDD2_OPP VDD2_OPP1 +#define MAX_VDD2_OPP VDD2_OPP3 +#endif /* __ASM_ARCH_OMAP34XX_H */
Quoted 9 lines · Rajendra Nayak
The SRF/DVFS + CPUFreq patches had issues booting on non-3430SDP platforms as reported by Kevin Hilman. This patch puts non-NULL checks in place for mpu_opps/dsp_opps /l3_opps before accessing them and fixes the issue.
This fix/patch can be applied on top of pm-20081119 branch
+ [PATCH 00/08] OMAP3 SRF: OPP and Frequency resources
+ [PATCH 00/03] OMAP3 PM: CPUFreq driver for OMAP3
Thanks, I'll pull this fix along with the above two series into the next PM branch (which should be out later today.)
Kevin
Quoted 238 lines
Signed-off-by Rajendra Nayak <[email protected]>--- arch/arm/mach-omap2/clock34xx.c | 33 ++++++++++++++++++++--------- arch/arm/mach-omap2/pm.h | 18 --------------- arch/arm/mach-omap2/resource34xx.c | 21 ++++++++++++++++++ arch/arm/plat-omap/cpu-omap.c | 6 +---- arch/arm/plat-omap/include/mach/omap34xx.h | 18 +++++++++++++++ 5 files changed, 64 insertions(+), 32 deletions(-)Index:
linux-omap-2.6/arch/arm/mach-omap2/clock34xx.c
===================================================================arch/arm/mach-omap2/clock34xx.c +23
-10@@ -666,6 +666,9 @@ void omap2_clk_init_cpufreq_table(structstruct omap_opp *prcm;int i =0 ; +if (!mpu_opps) +return ; +/* Avoid registering the 120% Overdrive with CPUFreq */ prcm = mpu_opps +MAX_VDD1_OPP -1 ;for (; prcm->rate; prcm--) {@@ -798,20 +801,24 @@ int __init omap2_clk_init(void) dpll3_clk =clk_get (NULL ,"dpll3_m2_ck" ); mpu_speed = dpll1_clk->rate; - prcm_vdd = mpu_opps +MAX_VDD1_OPP ; -for (; prcm_vdd->rate; prcm_vdd--) { -if (prcm_vdd->rate <= mpu_speed) { - curr_vdd1_prcm_set = prcm_vdd; -break ; +if (mpu_opps) { + prcm_vdd = mpu_opps +MAX_VDD1_OPP ; +for (; prcm_vdd->rate; prcm_vdd--) { +if (prcm_vdd->rate <= mpu_speed) { + curr_vdd1_prcm_set = prcm_vdd; +break ; + } } } core_speed = dpll3_clk->rate; - prcm_vdd = l3_opps +MAX_VDD2_OPP ; -for (; prcm_vdd->rate; prcm_vdd--) { -if (prcm_vdd->rate <= core_speed) { - curr_vdd2_prcm_set = prcm_vdd; -break ; +if (l3_opps) { + prcm_vdd = l3_opps +MAX_VDD2_OPP ; +for (; prcm_vdd->rate; prcm_vdd--) { +if (prcm_vdd->rate <= core_speed) { + curr_vdd2_prcm_set = prcm_vdd; +break ; + } } }@@ -878,6 +885,9 @@ static long omap3_round_to_table_rate(stif ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set))return -EINVAL ; +if (!mpu_opps || !dsp_opps || !l3_opps) +return -EINVAL ; + highest_rate = -EINVAL ;if (clk == &virt_vdd1_prcm_set)@@ -904,6 +914,9 @@ static int omap3_select_table_rate(strucif ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set))return -EINVAL ; +if (!mpu_opps || !dsp_opps || !l3_opps) +return -EINVAL ; +if (clk == &virt_vdd1_prcm_set) { prcm_vdd = mpu_opps +MAX_VDD1_OPP ; index =MAX_VDD1_OPP ;Index:
linux-omap-2.6/arch/arm/mach-omap2/pm.h
===================================================================arch/arm/mach-omap2/pm.h +0
-18@@ -39,24 +39,6 @@ extern void omap3_pm_off_mode_enable(int#endif extern int set_pwrdm_state (struct powerdomain *pwrdm,u32 state); - -/* VDD1 OPPS */ -#define VDD1_OPP1 0x1 -#define VDD1_OPP2 0x2 -#define VDD1_OPP3 0x3 -#define VDD1_OPP4 0x4 -#define VDD1_OPP5 0x5 - -/* VDD2 OPPS */ -#define VDD2_OPP1 0x1 -#define VDD2_OPP2 0x2 -#define VDD2_OPP3 0x3 - -#define MIN_VDD1_OPP VDD1_OPP1 -#define MAX_VDD1_OPP VDD1_OPP5 -#define MIN_VDD2_OPP VDD2_OPP1 -#define MAX_VDD2_OPP VDD2_OPP3 -#ifdef CONFIG_PM_DEBUG extern u32 omap2_read_32k_sync_counter (void );extern void omap2_pm_dump (int mode,int resume,unsigned int us);Index:
linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c
===================================================================arch/arm/mach-omap2/resource34xx.c +21
-0@@ -144,6 +144,10 @@ static struct device dummy_dsp_dev;void init_opp (struct shared_resource *resp) { resp->no_of_users =0 ; + +if (!mpu_opps || !dsp_opps || !l3_opps) +return 0 ; +/* Initialize the current level of the OPP resource * to the opp set by u-boot. */ @@ -167,6 +171,9 @@ int set_opp(struct shared_resource *respif (resp->curr_level == target_level)return 0 ; +if (!mpu_opps || !dsp_opps || !l3_opps) +return 0 ; +if (strcmp (resp->name,"vdd1_opp" ) ==0 ) { mpu_old_freq =get_freq (mpu_opps +MAX_VDD1_OPP , curr_vdd1_prcm_set->opp_id);@@ -184,12 +191,16 @@ int set_opp(struct shared_resource *respif (resp->curr_level > target_level) {/* Scale Frequency and then voltage */ clk_set_rate (vdd1_clk, mpu_freq); +#ifdef CONFIG_OMAP_SMARTREFLEX sr_voltagescale_vcbypass (t_opp, mpu_opps[target_level].vsel); +#endif }else { +#ifdef CONFIG_OMAP_SMARTREFLEX /* Scale Voltage and then frequency */ sr_voltagescale_vcbypass (t_opp, mpu_opps[target_level].vsel); +#endif clk_set_rate (vdd1_clk, mpu_freq); } resp->curr_level = curr_vdd1_prcm_set->opp_id;@@ -221,12 +232,16 @@ int set_opp(struct shared_resource *respif (resp->curr_level > target_level) {/* Scale Frequency and then voltage */ clk_set_rate (vdd2_clk, l3_freq); +#ifdef CONFIG_OMAP_SMARTREFLEX sr_voltagescale_vcbypass (t_opp, l3_opps[target_level].vsel); +#endif }else { +#ifdef CONFIG_OMAP_SMARTREFLEX /* Scale Voltage and then frequency */ sr_voltagescale_vcbypass (t_opp, l3_opps[target_level].vsel); +#endif clk_set_rate (vdd2_clk, l3_freq); } resp->curr_level = curr_vdd2_prcm_set->opp_id;@@ -253,6 +268,9 @@ void init_freq(struct shared_resource *rchar *linked_res_name; resp->no_of_users =0 ; +if (!mpu_opps || !dsp_opps) +return ; + linked_res_name = (char *)resp->resource_data;/* Initialize the current level of the Freq resource * to the frequency set by u-boot. @@ -271,6 +289,9 @@ int set_freq(struct shared_resource *res {unsigned int vdd1_opp; +if (!mpu_opps || !dsp_opps) +return 0 ; +if (strcmp (resp->name,"mpu_freq" ) ==0 ) { vdd1_opp =get_opp (mpu_opps +MAX_VDD1_OPP , target_level);resource_request ("vdd1_opp" , &dummy_mpu_dev, vdd1_opp);Index:
linux-omap-2.6/arch/arm/plat-omap/cpu-omap.c
===================================================================arch/arm/plat-omap/cpu-omap.c +2
-4@@ -31,7 +31,6 @@#include <mach/clock.h> #if defined(CONFIG_ARCH_OMAP3 ) && !defined(CONFIG_OMAP_PM_NONE )#include <mach/omap-pm.h> -#include "../mach-omap2/pm.h" #endif #define VERY_HI_RATE 900000000@@ -107,9 +106,8 @@ static int omap_target(struct cpufreq_po#endif ret =clk_set_rate (mpu_clk, freqs.new *1000 );cpufreq_notify_transition (&freqs,CPUFREQ_POSTCHANGE ); -#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)\ - && defined(CONFIG_MACH_OMAP_3430SDP) - { +#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE) +if (mpu_opps) {int ind;for (ind =1 ; ind <=MAX_VDD1_OPP ; ind++) {if (mpu_opps[ind].rate/1000 >= freqs.new) {Index:
linux-omap-2.6/arch/arm/plat-omap/include/mach/omap34xx.h
===================================================================arch/arm/plat-omap/include/mach/omap34xx.h +18
-0@@ -71,5 +71,23 @@#define OMAP34XX_DSP_MEM_BASE (OMAP34XX_DSP_BASE + 0x0)#define OMAP34XX_DSP_IPI_BASE (OMAP34XX_DSP_BASE + 0x1000000)#define OMAP34XX_DSP_MMU_BASE (OMAP34XX_DSP_BASE + 0x2000000) + +/* VDD1 OPPS */ +#define VDD1_OPP1 0x1 +#define VDD1_OPP2 0x2 +#define VDD1_OPP3 0x3 +#define VDD1_OPP4 0x4 +#define VDD1_OPP5 0x5 + +/* VDD2 OPPS */ +#define VDD2_OPP1 0x1 +#define VDD2_OPP2 0x2 +#define VDD2_OPP3 0x3 + +#define MIN_VDD1_OPP VDD1_OPP1 +#define MAX_VDD1_OPP VDD1_OPP5 +#define MIN_VDD2_OPP VDD2_OPP1 +#define MAX_VDD2_OPP VDD2_OPP3 +#endif /* __ASM_ARCH_OMAP34XX_H */