Commit c618a3a9 authored by Venkateswara Rao Mandela's avatar Venkateswara Rao Mandela Committed by Tomi Valkeinen

drm/omap: Implement workaround for DRA7 errata ID:i932

Description of DRA7 Errata i932:

In rare circumstances DPLL_VIDEO1 and DPLL_VIDEO2 PLL's may not lock on
the first attempt during DSS initialization. When this occurs, a
subsequent attempt to relock the PLL will result in PLL successfully
locking.

This patch does the following as per the errata recommendation:

- retries locking the PLL upto 20 times.

- The time to wait for a PLL lock set to 1000 REFCLK cycles. We use
usleep_range to wait for 1000 REFCLK cycles in the us range. This tight
constraint is imposed as a lock later than 1000 REFCLK cycles may have
high jitter.

- Criteria for PLL lock is extended from check on just the PLL_LOCK bit
to check on 6 PLL_STATUS bits.

Silicon Versions Impacted:
DRA71, DRA72, DRA74, DRA76 - All silicon revisions
AM57x - All silicon revisions

OMAP4/5 are not impacted by this errata
Signed-off-by: default avatarVenkateswara Rao Mandela <venkat.mandela@ti.com>
[tomi.valkeinen@ti.com: ported to v4.14]
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
parent 6ada1328
...@@ -180,6 +180,9 @@ struct dss_pll_hw { ...@@ -180,6 +180,9 @@ struct dss_pll_hw {
/* DRA7 errata i886: use high N & M to avoid jitter */ /* DRA7 errata i886: use high N & M to avoid jitter */
bool errata_i886; bool errata_i886;
/* DRA7 errata i932: retry pll lock on failure */
bool errata_i932;
}; };
struct dss_pll { struct dss_pll {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#define DSS_SUBSYS_NAME "PLL" #define DSS_SUBSYS_NAME "PLL"
#include <linux/delay.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -381,6 +382,22 @@ static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask) ...@@ -381,6 +382,22 @@ static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
static bool pll_is_locked(u32 stat)
{
/*
* Required value for each bitfield listed below
*
* PLL_STATUS[6] = 0 PLL_BYPASS
* PLL_STATUS[5] = 0 PLL_HIGHJITTER
*
* PLL_STATUS[3] = 0 PLL_LOSSREF
* PLL_STATUS[2] = 0 PLL_RECAL
* PLL_STATUS[1] = 1 PLL_LOCK
* PLL_STATUS[0] = 1 PLL_CTRL_RESET_DONE
*/
return ((stat & 0x6f) == 0x3);
}
int dss_pll_write_config_type_a(struct dss_pll *pll, int dss_pll_write_config_type_a(struct dss_pll *pll,
const struct dss_pll_clock_info *cinfo) const struct dss_pll_clock_info *cinfo)
{ {
...@@ -436,6 +453,41 @@ int dss_pll_write_config_type_a(struct dss_pll *pll, ...@@ -436,6 +453,41 @@ int dss_pll_write_config_type_a(struct dss_pll *pll,
l = FLD_MOD(l, 0, 25, 25); /* M7_CLOCK_EN */ l = FLD_MOD(l, 0, 25, 25); /* M7_CLOCK_EN */
writel_relaxed(l, base + PLL_CONFIGURATION2); writel_relaxed(l, base + PLL_CONFIGURATION2);
if (hw->errata_i932) {
int cnt = 0;
u32 sleep_time;
const u32 max_lock_retries = 20;
/*
* Calculate wait time for PLL LOCK
* 1000 REFCLK cycles in us.
*/
sleep_time = DIV_ROUND_UP(1000*1000*1000, cinfo->fint);
for (cnt = 0; cnt < max_lock_retries; cnt++) {
writel_relaxed(1, base + PLL_GO); /* PLL_GO */
/**
* read the register back to ensure the write is
* flushed
*/
readl_relaxed(base + PLL_GO);
usleep_range(sleep_time, sleep_time + 5);
l = readl_relaxed(base + PLL_STATUS);
if (pll_is_locked(l) &&
!(readl_relaxed(base + PLL_GO) & 0x1))
break;
}
if (cnt == max_lock_retries) {
DSSERR("cannot lock PLL\n");
r = -EIO;
goto err;
}
} else {
writel_relaxed(1, base + PLL_GO); /* PLL_GO */ writel_relaxed(1, base + PLL_GO); /* PLL_GO */
if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) { if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) {
...@@ -449,6 +501,7 @@ int dss_pll_write_config_type_a(struct dss_pll *pll, ...@@ -449,6 +501,7 @@ int dss_pll_write_config_type_a(struct dss_pll *pll,
r = -EIO; r = -EIO;
goto err; goto err;
} }
}
l = readl_relaxed(base + PLL_CONFIGURATION2); l = readl_relaxed(base + PLL_CONFIGURATION2);
l = FLD_MOD(l, 1, 14, 14); /* PHY_CLKINEN */ l = FLD_MOD(l, 1, 14, 14); /* PHY_CLKINEN */
......
...@@ -134,6 +134,7 @@ static const struct dss_pll_hw dss_dra7_video_pll_hw = { ...@@ -134,6 +134,7 @@ static const struct dss_pll_hw dss_dra7_video_pll_hw = {
.has_refsel = true, .has_refsel = true,
.errata_i886 = true, .errata_i886 = true,
.errata_i932 = true,
}; };
struct dss_pll *dss_video_pll_init(struct dss_device *dss, struct dss_pll *dss_video_pll_init(struct dss_device *dss,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment