aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/ti
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/ti')
-rw-r--r--drivers/clk/ti/apll.c2
-rw-r--r--drivers/clk/ti/clk-814x.c4
-rw-r--r--drivers/clk/ti/dpll3xxx.c25
3 files changed, 29 insertions, 2 deletions
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
index f3eab6e79027..b336a8c11e2a 100644
--- a/drivers/clk/ti/apll.c
+++ b/drivers/clk/ti/apll.c
@@ -323,7 +323,7 @@ static void omap2_apll_deny_idle(struct clk_hw_omap *clk)
omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_DISABLE);
}
-static struct clk_hw_omap_ops omap2_apll_hwops = {
+static const struct clk_hw_omap_ops omap2_apll_hwops = {
.allow_idle = &omap2_apll_allow_idle,
.deny_idle = &omap2_apll_deny_idle,
};
diff --git a/drivers/clk/ti/clk-814x.c b/drivers/clk/ti/clk-814x.c
index e172920798ea..9e85fcc74cc9 100644
--- a/drivers/clk/ti/clk-814x.c
+++ b/drivers/clk/ti/clk-814x.c
@@ -14,10 +14,14 @@ static struct ti_dt_clk dm814_clks[] = {
DT_CLK(NULL, "devosc_ck", "devosc_ck"),
DT_CLK(NULL, "mpu_ck", "mpu_ck"),
DT_CLK(NULL, "sysclk4_ck", "sysclk4_ck"),
+ DT_CLK(NULL, "sysclk5_ck", "sysclk5_ck"),
DT_CLK(NULL, "sysclk6_ck", "sysclk6_ck"),
+ DT_CLK(NULL, "sysclk8_ck", "sysclk8_ck"),
DT_CLK(NULL, "sysclk10_ck", "sysclk10_ck"),
DT_CLK(NULL, "sysclk18_ck", "sysclk18_ck"),
DT_CLK(NULL, "timer_sys_ck", "devosc_ck"),
+ DT_CLK(NULL, "timer1_fck", "timer1_fck"),
+ DT_CLK(NULL, "timer2_fck", "timer2_fck"),
DT_CLK(NULL, "cpsw_125mhz_gclk", "cpsw_125mhz_gclk"),
DT_CLK(NULL, "cpsw_cpts_rft_clk", "cpsw_cpts_rft_clk"),
{ .node_name = NULL },
diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c
index f4dec00fb684..1c300388782b 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;
}