On Thu, 11 Mar 2010, Vishwanath BS wrote:
> From: Shweta Gulati <[email protected]>
>
> DSP usage at VDD1 OPP1 and OPP2 with Smartreflex enabled and any MM UCs
> running DSP codec was earlier restricted as DSP crashed.
> The root cause is wrong DPLL1/DPLL2 Bypass clock at VDD1 OPP1 and OPP2.
> The solution is to make sure DPLL1/DPLL2 bypass clock is always less than
> maximum supported frequency for the specific OPP
>
> Tested on 3630 ZOOM3.
>
> changes in V2 : Rebased to new OPP implementation
>
> Signed-off-by: Shweta Gulati <[email protected]>
> Signed-off-by: Vishwanath BS <[email protected]>
> ---
> arch/arm/mach-omap2/cm-regbits-34xx.h | 4 ++--
> arch/arm/mach-omap2/pm34xx.c | 23 +++++++++++++++++++++++
> arch/arm/mach-omap2/resource34xx.c | 28 +++++++++++++++++++++++++++-
> 3 files changed, 52 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h
> b/arch/arm/mach-omap2/cm-regbits-34xx.h
> index a3a3ca0..ee420ab 100644
> --- a/arch/arm/mach-omap2/cm-regbits-34xx.h
> +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
> @@ -81,7 +81,7 @@
>
> /* CM_CLKSEL1_PLL_IVA2 */
> #define OMAP3430_IVA2_CLK_SRC_SHIFT 19
> -#define OMAP3430_IVA2_CLK_SRC_MASK (0x3 << 19)
> +#define OMAP3430_IVA2_CLK_SRC_MASK (0x7 << 19)
This is an ES2+ only setting, so please change the original value to
OMAP3430ES1_IVA2_CLK_SRC_MASK and add a new macro here for
OMAP3430ES2_IVA2_CLK_SRC_MASK.
> #define OMAP3430_IVA2_DPLL_MULT_SHIFT 8
> #define OMAP3430_IVA2_DPLL_MULT_MASK (0x7ff << 8)
> #define OMAP3430_IVA2_DPLL_DIV_SHIFT 0
> @@ -126,7 +126,7 @@
>
> /* CM_CLKSEL1_PLL_MPU */
> #define OMAP3430_MPU_CLK_SRC_SHIFT 19
> -#define OMAP3430_MPU_CLK_SRC_MASK (0x3 << 19)
> +#define OMAP3430_MPU_CLK_SRC_MASK (0x7 << 19)
Presumably this is the same.
> #define OMAP3430_MPU_DPLL_MULT_SHIFT 8
> #define OMAP3430_MPU_DPLL_MULT_MASK (0x7ff << 8)
> #define OMAP3430_MPU_DPLL_DIV_SHIFT 0
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index b51b461..494e5e6
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -828,6 +828,29 @@ static void __init omap3_d2d_idle(void)
>
> static void __init prcm_setup_regs(void)
> {
> + u32 cm_clksel1_mpu, cm_clksel1_iva2;
> +
> + /*set Bypass clock dividers for MPU and IVA */
> + cm_clksel1_mpu = cm_read_mod_reg(MPU_MOD, CM_CLKSEL1);
> + cm_clksel1_iva2 = cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
> + if (cpu_is_omap3630()) {
> + cm_clksel1_iva2 = (cm_clksel1_iva2 &
> + ~(OMAP3430_IVA2_CLK_SRC_MASK)) |
> + (0x2 << OMAP3430_IVA2_CLK_SRC_SHIFT);
> + cm_clksel1_mpu = (cm_clksel1_mpu &
> + ~(OMAP3430_MPU_CLK_SRC_MASK)) |
> + (0x1 << OMAP3430_MPU_CLK_SRC_SHIFT);
> + } else if (cpu_is_omap34xx()) {
> + cm_clksel1_iva2 = (cm_clksel1_iva2 &
> + ~(OMAP3430_IVA2_CLK_SRC_MASK)) |
> + (0x4 << OMAP3430_IVA2_CLK_SRC_SHIFT);
> + cm_clksel1_mpu = (cm_clksel1_mpu &
> + ~(OMAP3430_MPU_CLK_SRC_MASK)) |
> + (0x2 << OMAP3430_MPU_CLK_SRC_SHIFT);
> + }
> + cm_write_mod_reg(cm_clksel1_iva2, OMAP3430_IVA2_MOD, CM_CLKSEL1);
This should use the clock framework. You should use clk_set_rate() on
dpll2_fck.
> + cm_write_mod_reg(cm_clksel1_mpu, MPU_MOD, CM_CLKSEL1);
This should use the clock framework. You should use clk_set_rate() on
dpll1_fck.
> +
> /* XXX Reset all wkdeps. This should be done when initializing
> * powerdomains */
> prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
> diff --git a/arch/arm/mach-omap2/resource34xx.c
> b/arch/arm/mach-omap2/resource34xx.c
> index c6cce8b..03d7fce
> --- a/arch/arm/mach-omap2/resource34xx.c
> +++ b/arch/arm/mach-omap2/resource34xx.c
> @@ -276,12 +276,13 @@ static unsigned long compute_lpj(unsigned long ref,
> u_int div, u_int mult)
>
> static int program_opp_freq(int res, int target_level, int current_level)
> {
> - int ret = 0, l3_div;
> + int ret = 0, l3_div, mpu_div, iva2_div;
> int *curr_opp;
> unsigned long mpu_freq, dsp_freq, l3_freq;
> #ifndef CONFIG_CPU_FREQ
> unsigned long mpu_cur_freq;
> #endif
> + u32 cm_clksel1_mpu, cm_clksel1_iva2, max_core_clk;
>
> /* Check if I can actually switch or not */
> if (res == VDD1_OPP) {
> @@ -299,6 +300,31 @@ static int program_opp_freq(int res, int target_level,
> int current_level)
>
> lock_scratchpad_sem();
> if (res == VDD1_OPP) {
> + /* adjust bypass clock diviers */
> + max_core_clk = ULONG_MAX;
> + opp_find_freq_floor(OPP_L3, &max_core_clk);
> + l3_div = cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
> + OMAP3430_CLKSEL_L3_MASK;
> +
> + max_core_clk *= l3_div;
> + mpu_div = 1 << (max_core_clk / mpu_freq);
> + iva2_div = 1 << (max_core_clk / dsp_freq);
> +
> + cm_clksel1_mpu = cm_read_mod_reg(MPU_MOD, CM_CLKSEL1);
> + cm_clksel1_iva2 =
> + cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
> +
> + cm_clksel1_iva2 = (cm_clksel1_iva2 &
> + ~(OMAP3430_IVA2_CLK_SRC_MASK)) |
> + (iva2_div << OMAP3430_IVA2_CLK_SRC_SHIFT);
> + cm_clksel1_mpu = (cm_clksel1_mpu &
> + ~(OMAP3430_MPU_CLK_SRC_MASK)) |
> + (mpu_div << OMAP3430_MPU_CLK_SRC_SHIFT);
> +
> + cm_write_mod_reg(cm_clksel1_iva2,
> + OMAP3430_IVA2_MOD, CM_CLKSEL1);
> + cm_write_mod_reg(cm_clksel1_mpu, MPU_MOD, CM_CLKSEL1);
> +
All this needs to use the clock framework (clk_* functions), unless there
is some good reason why it can't?
> curr_opp = &curr_vdd1_opp;
> clk_set_rate(dpll1_clk, mpu_freq);
> clk_set_rate(dpll2_clk, dsp_freq);
- Paul
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html