This allows a board file to set the gpmiclk to something other than
the default 24 MHz based on ref_xtal.

I don't have an mx23-based board, but I believe there's a bug in the
current mxs_get_gpmiclk: According to the data sheet, the gpmiclk can
be derived from ref_io, not ref_cpu. Since other clocks are also
derived from ref_io, it seems most sensible to require the board file
to set that appropriately first, then derive the divider from its
current setting.

For mx28 boards, OTOH, there's a separate ref_gpmi only used for
clk_gpmi. For simplicity, if !xtal, simply enable that at its maximum
frequency.

Signed-off-by: Rasmus Villemoes <rasmus.villem...@prevas.dk>
---
 arch/arm/cpu/arm926ejs/mxs/clock.c    | 41 +++++++++++++++++++++++++++
 arch/arm/include/asm/arch-mxs/clock.h |  1 +
 2 files changed, 42 insertions(+)

diff --git a/arch/arm/cpu/arm926ejs/mxs/clock.c 
b/arch/arm/cpu/arm926ejs/mxs/clock.c
index 43d044d917..d247da56fe 100644
--- a/arch/arm/cpu/arm926ejs/mxs/clock.c
+++ b/arch/arm/cpu/arm926ejs/mxs/clock.c
@@ -138,6 +138,47 @@ static uint32_t mxs_get_gpmiclk(void)
        return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
 }
 
+void mxs_set_gpmiclk(uint32_t freq, int xtal)
+{
+       struct mxs_clkctrl_regs *clkctrl_regs =
+               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+       uint32_t clk, div;
+
+       if (xtal) {
+               clk = XTAL_FREQ_KHZ;
+       } else {
+#if defined(CONFIG_MX23)
+               clk = mxs_get_ioclk(MXC_IOCLK0);
+#elif defined(CONFIG_MX28)
+               /* enable ref_gpmi at 480 MHz. */
+               writeb(CLKCTRL_FRAC_CLKGATE,
+                       
&clkctrl_regs->hw_clkctrl_frac1_set[CLKCTRL_FRAC1_GPMI]);
+               writeb(CLKCTRL_FRAC_CLKGATE | PLL_FREQ_COEF,
+                       &clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI]);
+               writeb(CLKCTRL_FRAC_CLKGATE,
+                       
&clkctrl_regs->hw_clkctrl_frac1_clr[CLKCTRL_FRAC1_GPMI]);
+               clk = PLL_FREQ_KHZ;
+#endif
+       }
+       if (freq > clk)
+               return;
+       div = clk / freq;
+       if (div > CLKCTRL_GPMI_DIV_MASK)
+               div = CLKCTRL_GPMI_DIV_MASK;
+
+       clrbits_le32(&clkctrl_regs->hw_clkctrl_gpmi, CLKCTRL_GPMI_CLKGATE);
+       while (readl(&clkctrl_regs->hw_clkctrl_gpmi) & CLKCTRL_GPMI_CLKGATE)
+               ;
+       clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi, CLKCTRL_GPMI_DIV_MASK, 
div);
+       while (readl(&clkctrl_regs->hw_clkctrl_gpmi) & CLKCTRL_GPMI_BUSY)
+               ;
+
+       if (xtal)
+               writel(CLKCTRL_CLKSEQ_BYPASS_GPMI, 
&clkctrl_regs->hw_clkctrl_clkseq_set);
+       else
+               writel(CLKCTRL_CLKSEQ_BYPASS_GPMI, 
&clkctrl_regs->hw_clkctrl_clkseq_clr);
+}
+
 /*
  * Set IO clock frequency, in kHz
  */
diff --git a/arch/arm/include/asm/arch-mxs/clock.h 
b/arch/arm/include/asm/arch-mxs/clock.h
index ee56d10fec..0a6625eb90 100644
--- a/arch/arm/include/asm/arch-mxs/clock.h
+++ b/arch/arm/include/asm/arch-mxs/clock.h
@@ -44,6 +44,7 @@ uint32_t mxc_get_clock(enum mxc_clock clk);
 
 void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq);
 void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal);
+void mxs_set_gpmiclk(uint32_t freq, int xtal);
 void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq);
 void mxs_set_lcdclk(uint32_t __maybe_unused lcd_base, uint32_t freq);
 
-- 
2.20.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to