From: Sascha Hauer <s.hauer@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH] ARM: i.MX51: PLL errata workaround
Date: Sat, 25 May 2013 15:35:07 +0200 [thread overview]
Message-ID: <1369488907-7397-1-git-send-email-s.hauer@pengutronix.de> (raw)
This is a port of the official PLL errata workaround from Freescale.
The PLL's in the i.MX51 processor can go out of lock due to a metastable
condition in an analog flip-flop when used at high frequencies.
This workaround implements an undocumented feature in the PLL (dither
mode), which causes the effect of this failure to be much lower (in terms
of frequency deviation), avoiding system failure, or at least decreasing
the likelihood of system failure.
This is based on U-Boot commit:
commit 9db1bfa110ac411ab3468e817f7f74b2439eb8c8
Author: David Jander <david@protonic.nl>
Date: Wed Jul 13 21:11:53 2011 +0000
ARM: MX51: PLL errata workaround
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/imx51.c | 55 +++++++++++++++++++++++++++++++++--
arch/arm/mach-imx/include/mach/imx5.h | 1 +
2 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c
index 0766a21..fdf2374 100644
--- a/arch/arm/mach-imx/imx51.c
+++ b/arch/arm/mach-imx/imx51.c
@@ -98,15 +98,63 @@ postcore_initcall(imx51_init);
* power up.
*/
+#define DP_MFN_800_DIT 60 /* PL Dither mode */
+
+/*
+ * Workaround for i.MX51 PLL errata. This is needed by all boards using the
+ * i.MX51 silicon version up until (including) 3.0 running at 800MHz.
+ * The PLL's in the i.MX51 processor can go out of lock due to a metastable
+ * condition in an analog flip-flop when used at high frequencies.
+ * This workaround implements an undocumented feature in the PLL (dither
+ * mode), which causes the effect of this failure to be much lower (in terms
+ * of frequency deviation), avoiding system failure, or at least decreasing
+ * the likelihood of system failure.
+ */
+static void imx51_setup_pll800_bug(void)
+{
+ void __iomem *base = (void *)MX51_PLL1_BASE_ADDR;
+ u32 dp_config;
+ volatile int i;
+
+ imx5_setup_pll_864(base);
+
+ dp_config = readl(base + MX5_PLL_DP_CONFIG);
+ dp_config &= ~MX5_PLL_DP_CONFIG_AREN;
+ writel(dp_config, base + MX5_PLL_DP_CONFIG);
+
+ /* Restart PLL with PLM = 1 */
+ writel(0x00001236, base + MX5_PLL_DP_CTL);
+
+ /* Wait for lock */
+ while (!(readl(base + MX5_PLL_DP_CTL) & 1));
+
+ /* Modify MFN value */
+ writel(DP_MFN_800_DIT, base + MX5_PLL_DP_MFN);
+ writel(DP_MFN_800_DIT, base + MX5_PLL_DP_HFS_MFN);
+
+ /* Reload MFN value */
+ writel(0x1, base + MX5_PLL_DP_CONFIG);
+
+ while (readl(base + MX5_PLL_DP_CONFIG) & 1);
+
+ /* Wait at least 4 us */
+ for (i = 0; i < 100; i++);
+
+ /* Enable auto-restart AREN bit */
+ dp_config |= MX5_PLL_DP_CONFIG_AREN;
+ writel(dp_config, base + MX5_PLL_DP_CONFIG);
+}
+
void imx51_init_lowlevel(unsigned int cpufreq_mhz)
{
void __iomem *ccm = (void __iomem *)MX51_CCM_BASE_ADDR;
u32 r;
+ int rev = imx_silicon_revision();
imx5_init_lowlevel();
/* disable write combine for TO 2 and lower revs */
- if (imx_silicon_revision() < IMX_CHIP_REV_3_0) {
+ if (rev < IMX_CHIP_REV_3_0) {
__asm__ __volatile__("mrc 15, 1, %0, c9, c0, 1":"=r"(r));
r |= (1 << 25);
__asm__ __volatile__("mcr 15, 1, %0, c9, c0, 1" : : "r"(r));
@@ -138,7 +186,10 @@ void imx51_init_lowlevel(unsigned int cpufreq_mhz)
break;
default:
/* Default maximum 800MHz */
- imx5_setup_pll_800((void __iomem *)MX51_PLL1_BASE_ADDR);
+ if (rev <= IMX_CHIP_REV_3_0)
+ imx51_setup_pll800_bug();
+ else
+ imx5_setup_pll_800((void __iomem *)MX51_PLL1_BASE_ADDR);
break;
}
diff --git a/arch/arm/mach-imx/include/mach/imx5.h b/arch/arm/mach-imx/include/mach/imx5.h
index 7f5c2ef..5d1a7d7 100644
--- a/arch/arm/mach-imx/include/mach/imx5.h
+++ b/arch/arm/mach-imx/include/mach/imx5.h
@@ -9,6 +9,7 @@ void imx5_init_lowlevel(void);
void imx5_setup_pll(void __iomem *base, int freq, u32 op, u32 mfd, u32 mfn);
#define imx5_setup_pll_1000(base) imx5_setup_pll((base), 1000, ((10 << 4) + ((1 - 1) << 0)), (12 - 1), 5)
+#define imx5_setup_pll_864(base) imx5_setup_pll((base), 864, (( 8 << 4) + ((1 - 1) << 0)), (180 - 1), 180)
#define imx5_setup_pll_800(base) imx5_setup_pll((base), 800, (( 8 << 4) + ((1 - 1) << 0)), (3 - 1), 1)
#define imx5_setup_pll_665(base) imx5_setup_pll((base), 665, (( 6 << 4) + ((1 - 1) << 0)), (96 - 1), 89)
#define imx5_setup_pll_600(base) imx5_setup_pll((base), 600, (( 6 << 4) + ((1 - 1) << 0)), ( 4 - 1), 1)
--
1.8.2.rc2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
reply other threads:[~2013-05-25 13:35 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1369488907-7397-1-git-send-email-s.hauer@pengutronix.de \
--to=s.hauer@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox