diff options
Diffstat (limited to 'arch/arm/cpu/arm1136')
-rw-r--r-- | arch/arm/cpu/arm1136/mx31/generic.c | 12 | ||||
-rw-r--r-- | arch/arm/cpu/arm1136/mx31/timer.c | 16 | ||||
-rw-r--r-- | arch/arm/cpu/arm1136/mx35/generic.c | 90 | ||||
-rw-r--r-- | arch/arm/cpu/arm1136/mx35/timer.c | 46 |
4 files changed, 78 insertions, 86 deletions
diff --git a/arch/arm/cpu/arm1136/mx31/generic.c b/arch/arm/cpu/arm1136/mx31/generic.c index 8873fb719d..93f429cc52 100644 --- a/arch/arm/cpu/arm1136/mx31/generic.c +++ b/arch/arm/cpu/arm1136/mx31/generic.c @@ -22,6 +22,7 @@ */ #include <common.h> +#include <div64.h> #include <asm/arch/imx-regs.h> #include <asm/arch/clock.h> #include <asm/io.h> @@ -30,16 +31,17 @@ static u32 mx31_decode_pll(u32 reg, u32 infreq) { u32 mfi = GET_PLL_MFI(reg); - u32 mfn = GET_PLL_MFN(reg); + s32 mfn = GET_PLL_MFN(reg); u32 mfd = GET_PLL_MFD(reg); u32 pd = GET_PLL_PD(reg); mfi = mfi <= 5 ? 5 : mfi; + mfn = mfn >= 512 ? mfn - 1024 : mfn; mfd += 1; pd += 1; - return ((2 * (infreq >> 10) * (mfi * mfd + mfn)) / - (mfd * pd)) << 10; + return lldiv(2 * (u64)infreq * (mfi * mfd + mfn), + mfd * pd); } static u32 mx31_get_mpl_dpdgck_clk(void) @@ -47,9 +49,9 @@ static u32 mx31_get_mpl_dpdgck_clk(void) u32 infreq; if ((readl(CCM_CCMR) & CCMR_PRCS_MASK) == CCMR_FPM) - infreq = CONFIG_MX31_CLK32 * 1024; + infreq = MXC_CLK32 * 1024; else - infreq = CONFIG_MX31_HCLK_FREQ; + infreq = MXC_HCLK; return mx31_decode_pll(readl(CCM_MPCTL), infreq); } diff --git a/arch/arm/cpu/arm1136/mx31/timer.c b/arch/arm/cpu/arm1136/mx31/timer.c index 72081a8bde..36266da5aa 100644 --- a/arch/arm/cpu/arm1136/mx31/timer.c +++ b/arch/arm/cpu/arm1136/mx31/timer.c @@ -23,6 +23,7 @@ #include <common.h> #include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> #include <div64.h> #include <watchdog.h> #include <asm/io.h> @@ -53,28 +54,27 @@ DECLARE_GLOBAL_DATA_PTR; static inline unsigned long long tick_to_time(unsigned long long tick) { tick *= CONFIG_SYS_HZ; - do_div(tick, CONFIG_MX31_CLK32); + do_div(tick, MXC_CLK32); return tick; } static inline unsigned long long time_to_tick(unsigned long long time) { - time *= CONFIG_MX31_CLK32; + time *= MXC_CLK32; do_div(time, CONFIG_SYS_HZ); return time; } static inline unsigned long long us_to_tick(unsigned long long us) { - us = us * CONFIG_MX31_CLK32 + 999999; + us = us * MXC_CLK32 + 999999; do_div(us, 1000000); return us; } #else /* ~2% error */ -#define TICK_PER_TIME ((CONFIG_MX31_CLK32 + CONFIG_SYS_HZ / 2) \ - / CONFIG_SYS_HZ) -#define US_PER_TICK (1000000 / CONFIG_MX31_CLK32) +#define TICK_PER_TIME ((MXC_CLK32 + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ) +#define US_PER_TICK (1000000 / MXC_CLK32) static inline unsigned long long tick_to_time(unsigned long long tick) { @@ -128,7 +128,7 @@ ulong get_timer_masked(void) { /* * get_ticks() returns a long long (64 bit), it wraps in - * 2^64 / CONFIG_MX31_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ + * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in * 5 * 10^6 days - long enough. */ @@ -159,7 +159,7 @@ void __udelay(unsigned long usec) */ ulong get_tbclk(void) { - return CONFIG_MX31_CLK32; + return MXC_CLK32; } void reset_cpu(ulong addr) diff --git a/arch/arm/cpu/arm1136/mx35/generic.c b/arch/arm/cpu/arm1136/mx35/generic.c index d435e8af69..ef65176eed 100644 --- a/arch/arm/cpu/arm1136/mx35/generic.c +++ b/arch/arm/cpu/arm1136/mx35/generic.c @@ -24,6 +24,7 @@ */ #include <common.h> +#include <div64.h> #include <asm/io.h> #include <asm/errno.h> #include <asm/arch/imx-regs.h> @@ -129,15 +130,17 @@ static int get_ahb_div(u32 pdr0) static u32 decode_pll(u32 reg, u32 infreq) { u32 mfi = (reg >> 10) & 0xf; - u32 mfn = reg & 0x3f; - u32 mfd = (reg >> 16) & 0x3f; + s32 mfn = reg & 0x3ff; + u32 mfd = (reg >> 16) & 0x3ff; u32 pd = (reg >> 26) & 0xf; mfi = mfi <= 5 ? 5 : mfi; + mfn = mfn >= 512 ? mfn - 1024 : mfn; mfd += 1; pd += 1; - return ((2 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000; + return lldiv(2 * (u64)infreq * (mfi * mfd + mfn), + mfd * pd); } static u32 get_mcu_main_clk(void) @@ -146,9 +149,7 @@ static u32 get_mcu_main_clk(void) struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd); - fi *= - decode_pll(readl(&ccm->mpctl), - CONFIG_MX35_HCLK_FREQ); + fi *= decode_pll(readl(&ccm->mpctl), MXC_HCLK); return fi / (arm_div * fd); } @@ -171,17 +172,14 @@ static u32 get_ipg_per_clk(void) u32 pdr4 = readl(&ccm->pdr4); u32 div; if (pdr0 & MXC_CCM_PDR0_PER_SEL) { - div = (CCM_GET_DIVIDER(pdr4, - MXC_CCM_PDR4_PER0_PRDF_MASK, - MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1) * - (CCM_GET_DIVIDER(pdr4, + div = CCM_GET_DIVIDER(pdr4, MXC_CCM_PDR4_PER0_PODF_MASK, - MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1); + MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1; } else { div = CCM_GET_DIVIDER(pdr0, MXC_CCM_PDR0_PER_PODF_MASK, MXC_CCM_PDR0_PER_PODF_OFFSET) + 1; - freq /= get_ahb_div(pdr0); + div *= get_ahb_div(pdr0); } return freq / div; } @@ -193,25 +191,20 @@ u32 imx_get_uartclk(void) (struct ccm_regs *)IMX_CCM_BASE; u32 pdr4 = readl(&ccm->pdr4); - if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) { + if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) freq = get_mcu_main_clk(); - } else { - freq = decode_pll(readl(&ccm->ppctl), - CONFIG_MX35_HCLK_FREQ); - } - freq /= ((CCM_GET_DIVIDER(pdr4, - MXC_CCM_PDR4_UART_PRDF_MASK, - MXC_CCM_PDR4_UART_PRDF_OFFSET) + 1) * - (CCM_GET_DIVIDER(pdr4, + else + freq = decode_pll(readl(&ccm->ppctl), MXC_HCLK); + freq /= CCM_GET_DIVIDER(pdr4, MXC_CCM_PDR4_UART_PODF_MASK, - MXC_CCM_PDR4_UART_PODF_OFFSET) + 1)); + MXC_CCM_PDR4_UART_PODF_OFFSET) + 1; return freq; } unsigned int mxc_get_main_clock(enum mxc_main_clock clk) { u32 nfc_pdf, hsp_podf; - u32 pll, ret_val = 0, usb_prdf, usb_podf; + u32 pll, ret_val = 0, usb_podf; struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; @@ -255,16 +248,13 @@ unsigned int mxc_get_main_clock(enum mxc_main_clock clk) ret_val = pll / (nfc_pdf + 1); break; case USB_CLK: - usb_prdf = (reg4 >> 25) & 0x7; - usb_podf = (reg4 >> 22) & 0x7; - if (reg4 & 0x200) { + usb_podf = (reg4 >> 22) & 0x3F; + if (reg4 & 0x200) pll = get_mcu_main_clk(); - } else { - pll = decode_pll(readl(&ccm->ppctl), - CONFIG_MX35_HCLK_FREQ); - } + else + pll = decode_pll(readl(&ccm->ppctl), MXC_HCLK); - ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1)); + ret_val = pll / (usb_podf + 1); break; default: printf("Unknown clock: %d\n", clk); @@ -287,18 +277,16 @@ unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk) case UART2_BAUD: case UART3_BAUD: clk_sel = mpdr3 & (1 << 14); - pre_pdf = (mpdr4 >> 13) & 0x7; - pdf = (mpdr4 >> 10) & 0x7; + pdf = (mpdr4 >> 10) & 0x3F; ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : - decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / - ((pre_pdf + 1) * (pdf + 1)); + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (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(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / ((pre_pdf + 1) * (pdf + 1)); break; case SSI2_BAUD: @@ -306,16 +294,14 @@ unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk) pdf = (mpdr2 >> 8) & 0x3F; clk_sel = mpdr2 & (1 << 6); ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : - decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / ((pre_pdf + 1) * (pdf + 1)); break; case CSI_BAUD: clk_sel = mpdr2 & (1 << 7); - pre_pdf = (mpdr2 >> 16) & 0x7; - pdf = (mpdr2 >> 19) & 0x7; + pdf = (mpdr2 >> 16) & 0x3F; ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : - decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / - ((pre_pdf + 1) * (pdf + 1)); + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); break; case MSHC_CLK: pre_pdf = readl(&ccm->pdr1); @@ -323,39 +309,33 @@ unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk) pdf = (pre_pdf >> 22) & 0x3F; pre_pdf = (pre_pdf >> 28) & 0x7; ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : - decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / ((pre_pdf + 1) * (pdf + 1)); break; case ESDHC1_CLK: clk_sel = mpdr3 & 0x40; - pre_pdf = mpdr3 & 0x7; - pdf = (mpdr3>>3) & 0x7; + pdf = mpdr3 & 0x3F; ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : - decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / - ((pre_pdf + 1) * (pdf + 1)); + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); break; case ESDHC2_CLK: clk_sel = mpdr3 & 0x40; - pre_pdf = (mpdr3 >> 8) & 0x7; - pdf = (mpdr3 >> 11) & 0x7; + pdf = (mpdr3 >> 8) & 0x3F; ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : - decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / - ((pre_pdf + 1) * (pdf + 1)); + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); break; case ESDHC3_CLK: clk_sel = mpdr3 & 0x40; - pre_pdf = (mpdr3 >> 16) & 0x7; - pdf = (mpdr3 >> 19) & 0x7; + pdf = (mpdr3 >> 16) & 0x3F; ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : - decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / - ((pre_pdf + 1) * (pdf + 1)); + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (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(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) / + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / ((pre_pdf + 1) * (pdf + 1)); break; default: diff --git a/arch/arm/cpu/arm1136/mx35/timer.c b/arch/arm/cpu/arm1136/mx35/timer.c index 04937a1dfe..9680b7fde7 100644 --- a/arch/arm/cpu/arm1136/mx35/timer.c +++ b/arch/arm/cpu/arm1136/mx35/timer.c @@ -27,6 +27,7 @@ #include <asm/io.h> #include <div64.h> #include <asm/arch/imx-regs.h> +#include <asm/arch/crm_regs.h> #include <asm/arch/clock.h> DECLARE_GLOBAL_DATA_PTR; @@ -37,43 +38,52 @@ DECLARE_GLOBAL_DATA_PTR; /* General purpose timers bitfields */ #define GPTCR_SWR (1<<15) /* Software reset */ #define GPTCR_FRR (1<<9) /* Freerun / restart */ -#define GPTCR_CLKSOURCE_32 (0x100<<6) /* Clock source */ -#define GPTCR_CLKSOURCE_IPG (0x001<<6) /* Clock source */ +#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ #define GPTCR_TEN (1) /* Timer enable */ -#define TIMER_FREQ_HZ mxc_get_clock(MXC_IPG_CLK) - +/* + * "time" is measured in 1 / CONFIG_SYS_HZ seconds, + * "tick" is internal timer period + */ +/* ~0.4% error - measured with stop-watch on 100s boot-delay */ static inline unsigned long long tick_to_time(unsigned long long tick) { tick *= CONFIG_SYS_HZ; - do_div(tick, TIMER_FREQ_HZ); + do_div(tick, MXC_CLK32); return tick; } -static inline unsigned long long us_to_tick(unsigned long long usec) +static inline unsigned long long us_to_tick(unsigned long long us) { - usec *= TIMER_FREQ_HZ; - do_div(usec, 1000000); + us = us * MXC_CLK32 + 999999; + do_div(us, 1000000); - return usec; + return us; } +/* + * nothing really to do with interrupts, just starts up a counter. + * The 32KHz 32-bit timer overruns in 134217 seconds + */ int timer_init(void) { int i; struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR; + struct ccm_regs *ccm = (struct ccm_regs *)CCM_BASE_ADDR; /* setup GP Timer 1 */ writel(GPTCR_SWR, &gpt->ctrl); - for (i = 0; i < 100; i++) - writel(0, &gpt->ctrl); /* We have no udelay by now */ - writel(0, &gpt->pre); - /* Freerun Mode, PERCLK1 input */ - writel(readl(&gpt->ctrl) | - GPTCR_CLKSOURCE_IPG | GPTCR_TEN, - &gpt->ctrl); + writel(readl(&ccm->cgr1) | 3 << MXC_CCM_CGR1_GPT_OFFSET, &ccm->cgr1); + + for (i = 0; i < 100; i++) + writel(0, &gpt->ctrl); /* We have no udelay by now */ + writel(0, &gpt->pre); /* prescaler = 1 */ + /* Freerun Mode, 32KHz input */ + writel(readl(&gpt->ctrl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR, + &gpt->ctrl); + writel(readl(&gpt->ctrl) | GPTCR_TEN, &gpt->ctrl); return 0; } @@ -101,7 +111,7 @@ ulong get_timer_masked(void) { /* * get_ticks() returns a long long (64 bit), it wraps in - * 2^64 / CONFIG_MX25_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ + * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in * 5 * 10^6 days - long enough. */ @@ -132,5 +142,5 @@ void __udelay(unsigned long usec) */ ulong get_tbclk(void) { - return TIMER_FREQ_HZ; + return MXC_CLK32; } |