/*
- * Freescale i.MX28 clock setup code
+ * Freescale i.MX23/i.MX28 clock setup code
*
* Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
* on behalf of DENX Software Engineering GmbH
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
-/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
+/*
+ * The PLL frequency is 480MHz and XTAL frequency is 24MHz
+ * iMX23: datasheet section 4.2
+ * iMX28: datasheet section 10.2
+ */
#define PLL_FREQ_KHZ 480000
#define PLL_FREQ_COEF 18
-/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
#define XTAL_FREQ_KHZ 24000
#define PLL_FREQ_MHZ (PLL_FREQ_KHZ / 1000)
#define XTAL_FREQ_MHZ (XTAL_FREQ_KHZ / 1000)
-static uint32_t mx28_get_pclk(void)
+#if defined(CONFIG_MX23)
+#define MXC_SSPCLK_MAX MXC_SSPCLK0
+#elif defined(CONFIG_MX28)
+#define MXC_SSPCLK_MAX MXC_SSPCLK3
+#endif
+
+static uint32_t mxs_get_pclk(void)
{
- struct mx28_clkctrl_regs *clkctrl_regs =
- (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
uint32_t clkctrl, clkseq, div;
uint8_t clkfrac, frac;
return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
}
-static uint32_t mx28_get_hclk(void)
+static uint32_t mxs_get_hclk(void)
{
- struct mx28_clkctrl_regs *clkctrl_regs =
- (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
uint32_t div;
uint32_t clkctrl;
return 0;
div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
- return mx28_get_pclk() / div;
+ return mxs_get_pclk() / div;
}
-static uint32_t mx28_get_emiclk(void)
+static uint32_t mxs_get_emiclk(void)
{
- struct mx28_clkctrl_regs *clkctrl_regs =
- (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
uint32_t clkctrl, clkseq, div;
uint8_t clkfrac, frac;
return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
}
-static uint32_t mx28_get_gpmiclk(void)
+static uint32_t mxs_get_gpmiclk(void)
{
- struct mx28_clkctrl_regs *clkctrl_regs =
- (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
-
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
+#if defined(CONFIG_MX23)
+ uint8_t *reg =
+ &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU];
+#elif defined(CONFIG_MX28)
+ uint8_t *reg =
+ &clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI];
+#endif
uint32_t clkctrl, clkseq, div;
uint8_t clkfrac, frac;
}
/* REF Path */
- clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI]);
+ clkfrac = readb(reg);
frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK;
div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
/*
* Set IO clock frequency, in kHz
*/
-void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
+void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq)
{
- struct mx28_clkctrl_regs *clkctrl_regs =
- (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
uint32_t div;
int io_reg;
/*
* Get IO clock, returns IO clock in kHz
*/
-static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
+static uint32_t mxs_get_ioclk(enum mxs_ioclock io)
{
- struct mx28_clkctrl_regs *clkctrl_regs =
- (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
uint8_t ret;
int io_reg;
/*
* Configure SSP clock frequency, in kHz
*/
-void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
+void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
{
- struct mx28_clkctrl_regs *clkctrl_regs =
- (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
uint32_t clk, clkreg;
- if (ssp > MXC_SSPCLK3)
+ if (ssp > MXC_SSPCLK_MAX)
return;
clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
- (ssp * sizeof(struct mx28_register_32));
+ (ssp * sizeof(struct mxs_register_32));
clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE);
while (readl(clkreg) & CLKCTRL_SSP_CLKGATE)
if (xtal)
clk = XTAL_FREQ_KHZ;
else
- clk = mx28_get_ioclk(ssp >> 1);
+ clk = mxs_get_ioclk(ssp >> 1);
if (freq > clk)
return;
/*
* Return SSP frequency, in kHz
*/
-static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
+static uint32_t mxs_get_sspclk(enum mxs_sspclock ssp)
{
- struct mx28_clkctrl_regs *clkctrl_regs =
- (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
+ struct mxs_clkctrl_regs *clkctrl_regs =
+ (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
uint32_t clkreg;
uint32_t clk, tmp;
- if (ssp > MXC_SSPCLK3)
+ if (ssp > MXC_SSPCLK_MAX)
return 0;
tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
return XTAL_FREQ_KHZ;
clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
- (ssp * sizeof(struct mx28_register_32));
+ (ssp * sizeof(struct mxs_register_32));
tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK;
if (tmp == 0)
return 0;
- clk = mx28_get_ioclk(ssp >> 1);
+ clk = mxs_get_ioclk(ssp >> 1);
return clk / tmp;
}
/*
* Set SSP/MMC bus frequency, in kHz)
*/
-void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
+void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq)
{
- struct mx28_ssp_regs *ssp_regs;
- const uint32_t sspclk = mx28_get_sspclk(bus);
+ struct mxs_ssp_regs *ssp_regs;
+ const enum mxs_sspclock clk = mxs_ssp_clock_by_bus(bus);
+ const uint32_t sspclk = mxs_get_sspclk(clk);
uint32_t reg;
uint32_t divide, rate, tgtclk;
- ssp_regs = (struct mx28_ssp_regs *)(MXS_SSP0_BASE + (bus * 0x2000));
+ ssp_regs = mxs_ssp_regs_by_bus(bus);
/*
* SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
{
switch (clk) {
case MXC_ARM_CLK:
- return mx28_get_pclk() * 1000000;
+ return mxs_get_pclk() * 1000000;
case MXC_GPMI_CLK:
- return mx28_get_gpmiclk() * 1000000;
+ return mxs_get_gpmiclk() * 1000000;
case MXC_AHB_CLK:
case MXC_IPG_CLK:
- return mx28_get_hclk() * 1000000;
+ return mxs_get_hclk() * 1000000;
case MXC_EMI_CLK:
- return mx28_get_emiclk();
+ return mxs_get_emiclk();
case MXC_IO0_CLK:
- return mx28_get_ioclk(MXC_IOCLK0);
+ return mxs_get_ioclk(MXC_IOCLK0);
case MXC_IO1_CLK:
- return mx28_get_ioclk(MXC_IOCLK1);
+ return mxs_get_ioclk(MXC_IOCLK1);
+ case MXC_XTAL_CLK:
+ return XTAL_FREQ_KHZ * 1000;
case MXC_SSP0_CLK:
- return mx28_get_sspclk(MXC_SSPCLK0);
+ return mxs_get_sspclk(MXC_SSPCLK0);
+#ifdef CONFIG_MX28
case MXC_SSP1_CLK:
- return mx28_get_sspclk(MXC_SSPCLK1);
+ return mxs_get_sspclk(MXC_SSPCLK1);
case MXC_SSP2_CLK:
- return mx28_get_sspclk(MXC_SSPCLK2);
+ return mxs_get_sspclk(MXC_SSPCLK2);
case MXC_SSP3_CLK:
- return mx28_get_sspclk(MXC_SSPCLK3);
+ return mxs_get_sspclk(MXC_SSPCLK3);
+#endif
}
return 0;