diff options
Diffstat (limited to 'cpu/arm926ejs/mx28/generic.c')
-rw-r--r-- | cpu/arm926ejs/mx28/generic.c | 132 |
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; } |