diff mbox series

[U-Boot,v5,4/9] ARM: at91: spl: Add mck function to lower rate while switching

Message ID 20170913021017.9764-5-wenyou.yang@microchip.com
State Superseded
Delegated to: Tom Rini
Headers show
Series board: atmel: Add new board SAMA5D27-SOM1-EK board. | expand

Commit Message

Wenyou Yang Sept. 13, 2017, 2:10 a.m. UTC
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 happen on SAMA5D2 as we exit from ROM code @396MHz.

Add a function pmc_mck_init_down() to allow this sequence.

Signed-off-by: Wenyou Yang <wenyou.yang@microchip.com>
---

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/arm/mach-at91/armv7/clock.c              | 36 +++++++++++++++++++++++++++
 arch/arm/mach-at91/include/mach/at91_common.h |  1 +
 2 files changed, 37 insertions(+)

Comments

Simon Glass Sept. 13, 2017, 4:28 a.m. UTC | #1
On 12 September 2017 at 20:10, Wenyou Yang <wenyou.yang@microchip.com> wrote:
> 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 happen on SAMA5D2 as we exit from ROM code @396MHz.
>
> Add a function pmc_mck_init_down() to allow this sequence.
>
> Signed-off-by: Wenyou Yang <wenyou.yang@microchip.com>
> ---
>
> Changes in v5: None
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None
>
>  arch/arm/mach-at91/armv7/clock.c              | 36 +++++++++++++++++++++++++++
>  arch/arm/mach-at91/include/mach/at91_common.h |  1 +
>  2 files changed, 37 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/arch/arm/mach-at91/armv7/clock.c b/arch/arm/mach-at91/armv7/clock.c
> index 2e55953799..8ae01f4020 100644
> --- a/arch/arm/mach-at91/armv7/clock.c
> +++ b/arch/arm/mach-at91/armv7/clock.c
> @@ -150,6 +150,42 @@ void at91_mck_init(u32 mckr)
>                 ;
>  }
>
> +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 5416eb455d..0b09ce7b2e 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);

Function comment?

>  void at91_pmc_init(void);
>  void mem_init(void);
>  void at91_phy_reset(void);
> --
> 2.13.0
>
diff mbox series

Patch

diff --git a/arch/arm/mach-at91/armv7/clock.c b/arch/arm/mach-at91/armv7/clock.c
index 2e55953799..8ae01f4020 100644
--- a/arch/arm/mach-at91/armv7/clock.c
+++ b/arch/arm/mach-at91/armv7/clock.c
@@ -150,6 +150,42 @@  void at91_mck_init(u32 mckr)
 		;
 }
 
+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 5416eb455d..0b09ce7b2e 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);