clk: ti: omap5+: dpll: implement errata i810
Subsystems (6)
PATCH 1/1 clk: ti: omap5+: dpll: implement errata i810
Errata i810 states that DPLL controller can get stuck while transitioning to a power saving state, while its M/N ratio is being re-programmed.
As a workaround, before re-programming the M/N ratio, SW has to ensure the DPLL cannot start an idle state transition. SW can disable DPLL idling by setting the DPLL AUTO_DPLL_MODE=0 or keeping a clock request active by setting a dependent clock domain in SW_WKUP.
This errata impacts OMAP5 and DRA7 chips, so enable the errata for these.
--- arch/arm/mach-omap2/clock.c | 4 ++++ drivers/clk/ti/dpll3xxx.c | 25 ++++++++++++++++++++++++- include/linux/clk/ti.h | 1 + 3 files changed, 29 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/clock.c +4 -0
@@ -225,5 +225,9 @@ void __init ti_clk_init_features(void)if (omap_rev () ==OMAP3430_REV_ES1_0 ) features.flags |=TI_CLK_DPLL4_DENY_REPROGRAM ; +/* Errata I810 for omap5 / dra7 */ +if (soc_is_omap54xx () ||soc_is_dra7xx ()) + features.flags |=TI_CLK_ERRATA_I810 ; +ti_clk_setup_features (&features); }
drivers/clk/ti/dpll3xxx.c +24 -1
@@ -305,8 +305,9 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)static int omap3_noncore_dpll_program (struct clk_hw_omap *clk,u16 freqsel) {struct dpll_data *dd = clk->dpll_data; -u8 dco, sd_div; +u8 dco, sd_div, ai =0 ;u32 v; +bool errata_i810;/* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */ _omap3_noncore_dpll_bypass (clk);
@@ -350,6 +351,25 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) v |= sd_div <<__ffs (dd->sddiv_mask); } +/* +* Errata i810 - DPLL controller can get stuck while transitioning +* to a power saving state. Software must ensure the DPLL can not +* transition to a low power state while changing M/N values. +* Easiest way to accomplish this is to prevent DPLL autoidle +* before doing the M/N re-program. +*/ + errata_i810 =ti_clk_get_features ()->flags &TI_CLK_ERRATA_I810 ; + +if (errata_i810) { + ai =omap3_dpll_autoidle_read (clk); +if (ai) { +omap3_dpll_deny_idle (clk); + +/* OCP barrier */ +omap3_dpll_autoidle_read (clk); + } + } + ti_clk_ll_ops->clk_writel (v, dd->mult_div1_reg);/* Set 4X multiplier and low-power mode */
@@ -379,6 +399,9 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)_omap3_noncore_dpll_lock (clk); +if (errata_i810 && ai) +omap3_dpll_allow_idle (clk); +return 0 ; }
include/linux/clk/ti.h +1 -0
@@ -286,6 +286,7 @@ struct ti_clk_features {#define TI_CLK_DPLL_HAS_FREQSEL BIT(0)#define TI_CLK_DPLL4_DENY_REPROGRAM BIT(1)#define TI_CLK_DISABLE_CLKDM_CONTROL BIT(2) +#define TI_CLK_ERRATA_I810 BIT(3)void ti_clk_setup_features (struct ti_clk_features *features);const struct ti_clk_features *ti_clk_get_features (void );
Signature · 1 line
1.7.9.5
PATCH 1/1 clk: ti: omap5+: dpll: implement errata i810
Quoted 8 lines · Tero Kristo
Errata i810 states that DPLL controller can get stuck while transitioning to a power saving state, while its M/N ratio is being re-programmed.
As a workaround, before re-programming the M/N ratio, SW has to ensure the DPLL cannot start an idle state transition. SW can disable DPLL idling by setting the DPLL AUTO_DPLL_MODE=0 or keeping a clock request active by setting a dependent clock domain in
SW_WKUP.
Quoted 4 lines
This errata impacts OMAP5 and DRA7 chips, so enable the errata for these.
Signed-off-by Tero Kristo <[email protected]>---
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Tony Lindgren
maintainerPATCH 1/1 clk: ti: omap5+: dpll: implement errata i810
In reply to Tero KristoQuoted 8 lines · Tero Kristo
drivers/clk/ti/dpll3xxx.c +8
-0+/* +* Errata i810 - DPLL controller can get stuck while transitioning +* to a power saving state. Software must ensure the DPLL can not +* transition to a low power state while changing M/N values. +* Easiest way to accomplish this is to prevent DPLL autoidle +* before doing the M/N re-program. +*/ + errata_i810 =ti_clk_get_features ()->flags &TI_CLK_ERRATA_I810 ;
drivers/clk/ti/dpll3xxx.c static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) · line 371
Quoted 10 lines
drivers/clk/ti/dpll3xxx.c +10
-0+ +if (errata_i810) { + ai =omap3_dpll_autoidle_read (clk); +if (ai) { +omap3_dpll_deny_idle (clk); + +/* OCP barrier */ +omap3_dpll_autoidle_read (clk); + } + }
Should we just do this unconditionally? It seems like disabling the autoidle always before reprogramming is a good idea.
Regards,
Tony
PATCH 1/1 clk: ti: omap5+: dpll: implement errata i810
Quoted 14 lines · Tony Lindgren
Quoted 13 lines · Tero Kristo
drivers/clk/ti/dpll3xxx.c +13
-0+/* +* Errata i810 - DPLL controller can get stuck while transitioning +* to a power saving state. Software must ensure the DPLL can not +* transition to a low power state while changing M/N values. +* Easiest way to accomplish this is to prevent DPLL autoidle +* before doing the M/N re-program. +*/ + errata_i810 =ti_clk_get_features ()->flags &TI_CLK_ERRATA_I810 ; + +if (errata_i810) { + ai =omap3_dpll_autoidle_read (clk); +if (ai) { +omap3_dpll_deny_idle (clk);
Quoted 8 lines
drivers/clk/ti/dpll3xxx.c static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) · line 371
Quoted 5 lines
drivers/clk/ti/dpll3xxx.c +5
-0+ +/* OCP barrier */ +omap3_dpll_autoidle_read (clk); + } + }Should we just do this unconditionally? It seems like disabling the autoidle always before reprogramming is a good idea.
Well, that is a few extra register accesses, but given the DPLL re-programming is a slow operation it probably does not matter. Let me spin a new version of this patch, it will avoid the need for the errata flag also.
-Tero
Tony Lindgren
maintainerPATCH 1/1 clk: ti: omap5+: dpll: implement errata i810
Quoted 24 lines · Tero Kristo
Quoted 14 lines · Tony Lindgren
Quoted 13 lines · Tero Kristo
drivers/clk/ti/dpll3xxx.c +13
-0+/* +* Errata i810 - DPLL controller can get stuck while transitioning +* to a power saving state. Software must ensure the DPLL can not +* transition to a low power state while changing M/N values. +* Easiest way to accomplish this is to prevent DPLL autoidle +* before doing the M/N re-program. +*/ + errata_i810 =ti_clk_get_features ()->flags &TI_CLK_ERRATA_I810 ; + +if (errata_i810) { + ai =omap3_dpll_autoidle_read (clk); +if (ai) { +omap3_dpll_deny_idle (clk);Quoted 8 lines
drivers/clk/ti/dpll3xxx.c static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) · line 371
Quoted 5 lines
drivers/clk/ti/dpll3xxx.c +5
-0+ +/* OCP barrier */ +omap3_dpll_autoidle_read (clk); + } + }Should we just do this unconditionally? It seems like disabling the autoidle always before reprogramming is a good idea.
Quoted 4 lines
Well, that is a few extra register accesses, but given the DPLL re-programming is a slow operation it probably does not matter. Let me spin a new version of this patch, it will avoid the need for the errata flag also.
OK thanks,
Tony