aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWenyou Yang <wenyou.yang@microchip.com>2017-09-13 14:58:49 +0800
committerTom Rini <trini@konsulko.com>2017-09-14 16:02:44 -0400
commit2b21cf55cc767bc1303f22c3f6f7b9d6f0845c02 (patch)
tree0b3e5cf54c4daf6b025c69a811e4e8b466efe738
parent3ceb5118c6d7b0e042b399ef03b375fcef93b34d (diff)
downloadu-boot-2b21cf55cc767bc1303f22c3f6f7b9d6f0845c02.zip
u-boot-2b21cf55cc767bc1303f22c3f6f7b9d6f0845c02.tar.gz
u-boot-2b21cf55cc767bc1303f22c3f6f7b9d6f0845c02.tar.bz2
ARM: at91: spl: Add mck function to lower rate while switching
Refer to the commit 70f8c8316ad(PMC: add new mck function to lower rate while switching) from AT91Bootstrap. While switching to a lower clock source, we must switch the clock source first instead of last. Otherwise, we could end up with too high frequency on internal bus and peripherals. This happens on SAMA5D2 as exitting from the ROM code. Add a function pmc_mck_init_down() to allow this sequence. Signed-off-by: Wenyou Yang <wenyou.yang@microchip.com> Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r--arch/arm/mach-at91/armv7/clock.c42
-rw-r--r--arch/arm/mach-at91/include/mach/at91_common.h1
2 files changed, 43 insertions, 0 deletions
diff --git a/arch/arm/mach-at91/armv7/clock.c b/arch/arm/mach-at91/armv7/clock.c
index 2e55953..51c5e80 100644
--- a/arch/arm/mach-at91/armv7/clock.c
+++ b/arch/arm/mach-at91/armv7/clock.c
@@ -150,6 +150,48 @@ void at91_mck_init(u32 mckr)
;
}
+/*
+ * For the Master Clock Controller Register(MCKR), while switching
+ * to a lower clock source, we must switch the clock source first
+ * instead of last. Otherwise, we could end up with too high frequency
+ * on the internal bus and peripherals.
+ */
+void at91_mck_init_down(u32 mckr)
+{
+ struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+ u32 tmp;
+
+ tmp = readl(&pmc->mckr);
+ tmp &= (~AT91_PMC_MCKR_CSS_MASK);
+ tmp |= (mckr & AT91_PMC_MCKR_CSS_MASK);
+ writel(tmp, &pmc->mckr);
+
+ while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
+ ;
+
+#ifdef CPU_HAS_H32MXDIV
+ tmp = readl(&pmc->mckr);
+ tmp &= (~AT91_PMC_MCKR_H32MXDIV);
+ tmp |= (mckr & AT91_PMC_MCKR_H32MXDIV);
+ writel(tmp, &pmc->mckr);
+#endif
+
+ tmp = readl(&pmc->mckr);
+ tmp &= (~AT91_PMC_MCKR_PLLADIV_MASK);
+ tmp |= (mckr & AT91_PMC_MCKR_PLLADIV_MASK);
+ writel(tmp, &pmc->mckr);
+
+ tmp = readl(&pmc->mckr);
+ tmp &= (~AT91_PMC_MCKR_MDIV_MASK);
+ tmp |= (mckr & AT91_PMC_MCKR_MDIV_MASK);
+ writel(tmp, &pmc->mckr);
+
+ tmp = readl(&pmc->mckr);
+ tmp &= (~AT91_PMC_MCKR_PRES_MASK);
+ tmp |= (mckr & AT91_PMC_MCKR_PRES_MASK);
+ writel(tmp, &pmc->mckr);
+}
+
int at91_enable_periph_generated_clk(u32 id, u32 clk_source, u32 div)
{
struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
diff --git a/arch/arm/mach-at91/include/mach/at91_common.h b/arch/arm/mach-at91/include/mach/at91_common.h
index 5416eb4..0b09ce7 100644
--- a/arch/arm/mach-at91/include/mach/at91_common.h
+++ b/arch/arm/mach-at91/include/mach/at91_common.h
@@ -25,6 +25,7 @@ void at91_lcd_hw_init(void);
void at91_plla_init(u32 pllar);
void at91_pllb_init(u32 pllar);
void at91_mck_init(u32 mckr);
+void at91_mck_init_down(u32 mckr);
void at91_pmc_init(void);
void mem_init(void);
void at91_phy_reset(void);