summaryrefslogtreecommitdiff
path: root/cpu/arm926ejs/mx28/generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/arm926ejs/mx28/generic.c')
-rw-r--r--cpu/arm926ejs/mx28/generic.c132
1 files changed, 92 insertions, 40 deletions
diff --git a/cpu/arm926ejs/mx28/generic.c b/cpu/arm926ejs/mx28/generic.c
index 6ac75e0..82929d5 100644
--- a/cpu/arm926ejs/mx28/generic.c
+++ b/cpu/arm926ejs/mx28/generic.c
@@ -1,5 +1,5 @@
/*
- * (C) Copyright 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
@@ -22,83 +22,120 @@
#include <common.h>
#include <asm/errno.h>
-#include <asm/arch/mx28.h>
#include <asm/arch/regs-clkctrl.h>
+#include <asm/cache-cp15.h>
+#include <asm/fec.h>
-#if defined(CONFIG_ARCH_CPU_INIT)
-int arch_cpu_init(void)
-{
- icache_enable();
- dcache_enable();
- return 0;
-}
-#endif
-
-#if defined(CONFIG_DISPLAY_CPUINFO)
-int print_cpuinfo(void)
+static u32 mx28_get_pclk(void)
{
const u32 xtal = 24, ref = 480;
- u32 cpu, bus, emi;
- u32 clkfrac, clkdeq, clkctrl;
+ u32 clkfrac, clkseq, clkctrl;
u32 frac, div;
+ u32 pclk;
clkfrac = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC0);
- clkdeq = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ);
-
- /* CPU */
+ clkseq = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ);
clkctrl = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_CPU);
+
if (clkctrl & (BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN |
BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN)) {
/* No support of fractional divider calculation */
- cpu = 0;
+ pclk = 0;
} else {
- if (clkdeq & BM_CLKCTRL_CLKSEQ_BYPASS_CPU) {
+ if (clkseq & BM_CLKCTRL_CLKSEQ_BYPASS_CPU) {
/* xtal path */
div = (clkctrl & BM_CLKCTRL_CPU_DIV_XTAL) >>
BP_CLKCTRL_CPU_DIV_XTAL;
- cpu = xtal / div;
+ pclk = xtal / div;
} else {
/* ref path */
frac = (clkfrac & BM_CLKCTRL_FRAC0_CPUFRAC) >>
BP_CLKCTRL_FRAC0_CPUFRAC;
div = (clkctrl & BM_CLKCTRL_CPU_DIV_CPU) >>
BP_CLKCTRL_CPU_DIV_CPU;
- cpu = (ref * 18 / frac) / div;
+ pclk = (ref * 18 / frac) / div;
}
}
- /* BUS */
+ return pclk;
+}
+
+static u32 mx28_get_hclk(void)
+{
+ u32 clkctrl, div, hclk;
+
clkctrl = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_HBUS);
+
if (clkctrl & BM_CLKCTRL_HBUS_DIV_FRAC_EN) {
/* No support of fractional divider calculation */
- bus = 0;
+ hclk = 0;
} else {
div = (clkctrl & BM_CLKCTRL_HBUS_DIV) >>
BP_CLKCTRL_HBUS_DIV;
- bus = cpu / div;
+ hclk = mx28_get_pclk() / div;
}
- /* EMI */
+ return hclk;
+}
+
+static u32 mx28_get_emiclk(void)
+{
+ const u32 xtal = 24, ref = 480;
+ u32 clkfrac, clkseq, clkctrl;
+ u32 frac, div;
+ u32 emiclk;
+
+ clkfrac = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_FRAC0);
+ clkseq = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_CLKSEQ);
clkctrl = REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_EMI);
- if (clkdeq & BM_CLKCTRL_CLKSEQ_BYPASS_EMI) {
+
+ if (clkseq & BM_CLKCTRL_CLKSEQ_BYPASS_EMI) {
/* xtal path */
div = (clkctrl & BM_CLKCTRL_EMI_DIV_XTAL) >>
BP_CLKCTRL_EMI_DIV_XTAL;
- emi = xtal / div;
+ emiclk = xtal / div;
} else {
/* ref path */
frac = (clkfrac & BM_CLKCTRL_FRAC0_EMIFRAC) >>
BP_CLKCTRL_FRAC0_EMIFRAC;
div = (clkctrl & BM_CLKCTRL_EMI_DIV_EMI) >>
BP_CLKCTRL_EMI_DIV_EMI;
- emi = (ref * 18 / frac) / div;
+ emiclk = (ref * 18 / frac) / div;
}
- /* Print */
+ return emiclk;
+}
+
+u32 mxc_get_clock(enum mxc_clock clk)
+{
+ switch (clk) {
+ case MXC_ARM_CLK:
+ return mx28_get_pclk() * 1000000;
+ case MXC_AHB_CLK:
+ case MXC_IPG_CLK:
+ return mx28_get_hclk() * 1000000;
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_ARCH_CPU_INIT)
+int arch_cpu_init(void)
+{
+ icache_enable();
+ dcache_enable();
+
+ return 0;
+}
+#endif
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
printf("Freescale i.MX28 family\n");
- printf("CPU: %d MHz\n", cpu);
- printf("BUS: %d MHz\n", bus);
- printf("EMI: %d MHz\n", emi);
+ printf("CPU: %d MHz\n", mx28_get_pclk());
+ printf("BUS: %d MHz\n", mx28_get_hclk());
+ printf("EMI: %d MHz\n", mx28_get_emiclk());
return 0;
}
@@ -107,13 +144,13 @@ int print_cpuinfo(void)
/*
* Initializes on-chip MMC controllers.
*/
-#if defined(CONFIG_MXC_ENET)
+#if defined(CONFIG_IMX_SSP_MMC)
int imx_ssp_mmc_initialize(bd_t *bis);
#endif
int cpu_mmc_init(bd_t *bis)
{
int rc = ENODEV;
-#ifdef CONFIG_IMX_SSP_MMC
+#if defined(CONFIG_IMX_SSP_MMC)
rc = imx_ssp_mmc_initialize(bis);
#endif
return rc;
@@ -122,14 +159,29 @@ int cpu_mmc_init(bd_t *bis)
/*
* Initializes on-chip ethernet controllers.
*/
-#if defined(CONFIG_MXC_ENET)
-int mxc_enet_initialize(bd_t *bis);
-#endif
int cpu_eth_init(bd_t *bis)
{
int rc = ENODEV;
-#if defined(CONFIG_MXC_ENET)
- rc = mxc_enet_initialize(bis);
+#if defined(CONFIG_MXC_FEC)
+ rc = mxc_fec_initialize(bis);
+
+ /* Turn on ENET clocks */
+ REG_WR(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET,
+ REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET) &
+ ~(BM_CLKCTRL_ENET_SLEEP | BM_CLKCTRL_ENET_DISABLE));
+
+ /* Set up ENET PLL for 50 MHz */
+ REG_SET(REGS_CLKCTRL_BASE, HW_CLKCTRL_PLL2CTRL0,
+ BM_CLKCTRL_PLL2CTRL0_POWER); /* Power on ENET PLL */
+ udelay(10); /* Wait 10 us */
+ REG_CLR(REGS_CLKCTRL_BASE, HW_CLKCTRL_PLL2CTRL0,
+ BM_CLKCTRL_PLL2CTRL0_CLKGATE); /* Gate on ENET PLL */
+ REG_WR(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET,
+ REG_RD(REGS_CLKCTRL_BASE, HW_CLKCTRL_ENET) |
+ BM_CLKCTRL_ENET_CLK_OUT_EN); /* Enable pad output */
+
+ /* Board level init */
+ enet_board_init();
#endif
return rc;
}