diff options
Diffstat (limited to 'cpu/arm1136')
-rw-r--r-- | cpu/arm1136/mx35/Makefile | 2 | ||||
-rw-r--r-- | cpu/arm1136/mx35/generic.c | 159 | ||||
-rw-r--r-- | cpu/arm1136/mx35/timer.c (renamed from cpu/arm1136/mx35/interrupts.c) | 22 | ||||
-rw-r--r-- | cpu/arm1136/start.S | 42 |
4 files changed, 177 insertions, 48 deletions
diff --git a/cpu/arm1136/mx35/Makefile b/cpu/arm1136/mx35/Makefile index afcf771..996360f 100644 --- a/cpu/arm1136/mx35/Makefile +++ b/cpu/arm1136/mx35/Makefile @@ -27,7 +27,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).a -COBJS = interrupts.o serial.o generic.o iomux.o +COBJS = timer.o serial.o generic.o iomux.o SOBJS = mxc_nand_load.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/cpu/arm1136/mx35/generic.c b/cpu/arm1136/mx35/generic.c index b70c3ea..31bcbec 100644 --- a/cpu/arm1136/mx35/generic.c +++ b/cpu/arm1136/mx35/generic.c @@ -24,6 +24,7 @@ */ #include <common.h> +#include <asm/io.h> #include <asm/errno.h> #include <asm/arch/mx35.h> #include "crm_regs.h" @@ -47,6 +48,12 @@ static int g_clk_mux_consumer[16] = { -1, -1, CLK_CODE(4, 2, 0), -1, }; +static int hsp_div_table[3][16] = { + {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1}, + {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1}, +}; + static u32 __get_arm_div(u32 pdr0, u32 *fi, u32 *fd) { int *pclk_mux; @@ -117,7 +124,7 @@ static u32 __get_mcu_main_clk(void) u32 arm_div, fi, fd; arm_div = __get_arm_div(__REG(CCM_BASE_ADDR + CLKCTL_PDR0), &fi, &fd); fi *= - __decode_pll(__REG(CCM_BASE_ADDR + CLKCTL_MPCTL), + __decode_pll(__REG(MCU_PLL), CONFIG_MX35_HCLK_FREQ); return fi / (arm_div * fd); } @@ -160,7 +167,7 @@ static u32 __get_uart_clk(void) if (__REG(CCM_BASE_ADDR + CLKCTL_PDR3) & MXC_CCM_PDR3_UART_M_U) freq = __get_mcu_main_clk(); else - freq = __decode_pll(__REG(CCM_BASE_ADDR + CLKCTL_PPCTL), + freq = __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ); freq /= ((CCM_GET_DIVIDER(pdr4, MXC_CCM_PDR4_UART_PRDF_MASK, @@ -171,6 +178,150 @@ static u32 __get_uart_clk(void) return freq; } +unsigned int mxc_get_main_clock(enum mxc_main_clocks clk) +{ + u32 nfc_pdf, hsp_podf; + u32 pll, ret_val = 0, usb_prdf, usb_podf; + + u32 reg = readl(CCM_BASE_ADDR + CLKCTL_PDR0); + u32 reg4 = readl(CCM_BASE_ADDR + CLKCTL_PDR4); + + reg |= 0x1; + + switch (clk) { + case CPU_CLK: + ret_val = __get_mcu_main_clk(); + break; + case AHB_CLK: + ret_val = __get_mcu_main_clk(); + break; + case HSP_CLK: + if (reg & CLKMODE_CONSUMER) { + hsp_podf = (reg >> 20) & 0x3; + pll = __get_mcu_main_clk(); + hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF]; + if(hsp_podf > 0 ) { + ret_val = pll / hsp_podf; + } else { + puts("mismatch HSP with ARM clock setting\n"); + ret_val = 0; + } + } else { + ret_val = __get_mcu_main_clk(); + } + break; + case IPG_CLK: + ret_val = __get_ipg_clk();; + break; + case IPG_PER_CLK: + ret_val = __get_ipg_per_clk(); + break; + case NFC_CLK: + nfc_pdf = (reg4 >> 28) & 0xF; + pll = __get_mcu_main_clk(); + /* AHB/nfc_pdf */ + ret_val = pll / (nfc_pdf + 1); + break; + case USB_CLK: + usb_prdf = (reg4 >> 25) & 0x7; + usb_podf = (reg4 >> 22) & 0x7; + if (reg4 & 0x200) + pll = __get_mcu_main_clk(); + else + pll = __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ); + + ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1)); + break; + default: + printf("Unknown clock: %d\n", clk); + break; + } + + return ret_val; +} +unsigned int mxc_get_peri_clock(enum mxc_peri_clocks clk) +{ + u32 ret_val = 0, pdf, pre_pdf, clk_sel; + u32 mpdr2 = readl(CCM_BASE_ADDR + CLKCTL_PDR2); + u32 mpdr3 = readl(CCM_BASE_ADDR + CLKCTL_PDR3); + u32 mpdr4 = readl(CCM_BASE_ADDR + CLKCTL_PDR4); + + switch (clk) { + case UART1_BAUD: + case UART2_BAUD: + case UART3_BAUD: + clk_sel = mpdr3 & (1 << 14); + pre_pdf = (mpdr4 >> 13) & 0x7; + pdf = (mpdr4 >> 10) & 0x7; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1)); + break; + case SSI1_BAUD: + pre_pdf = (mpdr2 >> 24) & 0x7; + pdf = mpdr2 & 0x3F; + clk_sel = mpdr2 & ( 1 << 6); + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1)); + break; + case SSI2_BAUD: + pre_pdf = (mpdr2 >> 27) & 0x7; + pdf = (mpdr2 >> 8)& 0x3F; + clk_sel = mpdr2 & ( 1 << 6); + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1)); + break; + case CSI_BAUD: + clk_sel = mpdr2 & (1 << 7); + pre_pdf = (mpdr2 >> 16) & 0x7; + pdf = (mpdr2 >> 19) & 0x7; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1)); + break; + case MSHC_CLK: + pre_pdf = readl(CCM_BASE_ADDR + CLKCTL_PDR1); + clk_sel = (pre_pdf & 0x80); + pdf = (pre_pdf >> 22) & 0x3F; + pre_pdf = (pre_pdf >> 28) & 0x7; + ret_val = ((clk_sel != 0)? mxc_get_main_clock(CPU_CLK) : + __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1)); + break; + case ESDHC1_CLK: + clk_sel = mpdr3 & 0x40; + pre_pdf = mpdr3&0x7; + pdf = (mpdr3>>3)&0x7; + ret_val = ((clk_sel != 0)? mxc_get_main_clock(CPU_CLK) : + __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1)); + break; + case ESDHC2_CLK: + clk_sel = mpdr3 & 0x40; + pre_pdf = (mpdr3 >> 8)&0x7; + pdf = (mpdr3 >> 11)&0x7; + ret_val = ((clk_sel != 0)? mxc_get_main_clock(CPU_CLK) : + __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1)); + break; + case ESDHC3_CLK: + clk_sel = mpdr3 & 0x40; + pre_pdf = (mpdr3 >> 16)&0x7; + pdf = (mpdr3 >> 19)&0x7; + ret_val = ((clk_sel != 0)? mxc_get_main_clock(CPU_CLK) : + __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1)); + break; + case SPDIF_CLK: + clk_sel = mpdr3 & 0x400000; + pre_pdf = (mpdr3 >> 29)&0x7; + pdf = (mpdr3 >> 23)&0x3F; + ret_val = ((clk_sel != 0)? mxc_get_main_clock(CPU_CLK) : + __decode_pll(__REG(PER_PLL), CONFIG_MX35_HCLK_FREQ)) / ((pre_pdf + 1) * (pdf + 1)); + break; + default: + printf("%s(): This clock: %d not supported yet \n", + __FUNCTION__, clk); + break; + } + + return ret_val; +} + unsigned int mxc_get_clock(enum mxc_clock clk) { switch (clk) { @@ -184,6 +335,10 @@ unsigned int mxc_get_clock(enum mxc_clock clk) return __get_ipg_per_clk(); case MXC_UART_CLK: return __get_uart_clk(); + case MXC_ESDHC_CLK: + return mxc_get_peri_clock(ESDHC1_CLK); + case MXC_USB_CLK: + return mxc_get_main_clock(USB_CLK); } return -1; } diff --git a/cpu/arm1136/mx35/interrupts.c b/cpu/arm1136/mx35/timer.c index 40b9d4c..d6f65cf 100644 --- a/cpu/arm1136/mx35/interrupts.c +++ b/cpu/arm1136/mx35/timer.c @@ -38,18 +38,28 @@ #define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ #define GPTCR_TEN (1) /* Timer enable */ -/* nothing really to do with interrupts, just starts up a counter. */ -int interrupt_init(void) +static inline void setup_gpt() { int i; + static int init_done; + + if (init_done) + return; + + init_done = 1; /* setup GP Timer 1 */ GPTCR = GPTCR_SWR; for (i = 0; i < 100; i++) - GPTCR = 0; /* We have no udelay by now */ - GPTPR = 0; /* 32Khz */ + GPTCR = 0; /* We have no udelay by now */ + GPTPR = 0; /* 32Khz */ /* Freerun Mode, PERCLK1 input */ GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; +} + +int timer_init(void) +{ + setup_gpt(); return 0; } @@ -86,7 +96,9 @@ void udelay(unsigned long usec) { ulong tmo, tmp; - /* if "big" number, spread normalization to seconds */ + setup_gpt(); + + /* if "big" number, spread normalization to seconds */ if (usec >= 1000) { /* start to normalize for usec to ticks per sec */ tmo = usec / 1000; diff --git a/cpu/arm1136/start.S b/cpu/arm1136/start.S index 57f13ef..b1d7087 100644 --- a/cpu/arm1136/start.S +++ b/cpu/arm1136/start.S @@ -130,6 +130,7 @@ next: #endif b setup_env +#ifndef CONFIG_SKIP_LOWLEVEL_INIT /* ************************************************************************* * @@ -166,7 +167,7 @@ cpu_init_crit: bl lowlevel_init /* go setup pll,mux,memory */ mov lr, ip /* restore link */ mov pc, lr /* back to my caller */ - +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ .section ".text.setup", "ax" @@ -263,45 +264,6 @@ _start_armboot: .word start_armboot #endif /* CONFIG_ONENAND_IPL */ #endif /* CONFIG_NAND_SPL */ -/* - ************************************************************************* - * - * CPU_init_critical registers - * - * setup important registers - * setup memory timing - * - ************************************************************************* - */ -#ifndef CONFIG_SKIP_LOWLEVEL_INIT -cpu_init_crit: - /* - * flush v4 I/D caches - */ - mov r0, #0 - mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ - mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ - - /* - * disable MMU stuff and caches - */ - mrc p15, 0, r0, c1, c0, 0 - bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) - bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) - orr r0, r0, #0x00000002 @ set bit 2 (A) Align - orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache - mcr p15, 0, r0, c1, c0, 0 - - /* - * Jump to board specific initialization... The Mask ROM will have already initialized - * basic memory. Go here to bump up clock rate and handle wake up conditions. - */ - mov ip, lr /* persevere link reg across call */ - bl lowlevel_init /* go setup pll,mux,memory */ - mov lr, ip /* restore link */ - mov pc, lr /* back to my caller */ -#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ - #ifndef CONFIG_PRELOADER /* ************************************************************************* |