diff mbox

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

Message ID 1448894605-30097-1-git-send-email-t-kristo@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tero Kristo Nov. 30, 2015, 2:43 p.m. UTC
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.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 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(-)

Comments

Stephen Boyd Nov. 30, 2015, 7:35 p.m. UTC | #1
On 11/30, Tero Kristo wrote:
> 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.
> 
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>
Tony Lindgren Dec. 3, 2015, 4:48 p.m. UTC | #2
* Tero Kristo <t-kristo@ti.com> [151130 06:44]:
> +	/*
> +	 * 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);
> +		}
> +	}

Should we just do this unconditionally? It seems like disabling the
autoidle always before reprogramming is a good idea.

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tero Kristo Dec. 11, 2015, 8:43 a.m. UTC | #3
On 12/03/2015 06:48 PM, Tony Lindgren wrote:
> * Tero Kristo <t-kristo@ti.com> [151130 06:44]:
>> +	/*
>> +	 * 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);
>> +		}
>> +	}
>
> 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

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tony Lindgren Dec. 11, 2015, 4:55 p.m. UTC | #4
* Tero Kristo <t-kristo@ti.com> [151211 00:42]:
> On 12/03/2015 06:48 PM, Tony Lindgren wrote:
> >* Tero Kristo <t-kristo@ti.com> [151130 06:44]:
> >>+	/*
> >>+	 * 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);
> >>+		}
> >>+	}
> >
> >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.

OK thanks,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index acb60ed..d058125 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -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);
 }
diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c
index f4dec00..1c30038 100644
--- a/drivers/clk/ti/dpll3xxx.c
+++ b/drivers/clk/ti/dpll3xxx.c
@@ -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;
 }
 
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 223be69..75205df 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -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);