
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.villemoes@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);