Skip to contentSkip to conversation

clk: ti: omap5+: dpll: implement errata i810

PATCH New Tero Kristo 3 participants 5 messages Nov 30, 2015 – Dec 11, 2015

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

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
index acb60ed..d058125 100644
@@ -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
index f4dec00..1c30038 100644
@@ -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
index 223be69..75205df 100644
@@ -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
#1 lore raw

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.

---

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
maintainer
#2 lore raw

PATCH 1/1 clk: ti: omap5+: dpll: implement errata i810

In reply to Tero Kristo
Quoted 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

#3 lore raw

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

maintainer
#4 lore raw

PATCH 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