[U-Boot-Users] [Patch 12/17] U-Boot-V2:ARM:OMAP3: Add support for OMAP3 Silicon files

This patch introduces support for OMAP3430 clocking infrastructure. Please note that SRAM based configuration requires GPMC values to be updated before returning to caller- TBD.
Signed-off-by: Nishanth Menonx0nishan@ti.com
--- arch/arm/mach-omap/omap3_clock.c | 378 ++++++++++++++++++++++++++++++++ arch/arm/mach-omap/omap3_clock_core.S | 312 ++++++++++++++++++++++++++ arch/arm/mach-omap/s32k_clksource.c | 80 ++++++ include/asm-arm/arch-omap/clocks.h | 48 ++++ include/asm-arm/arch-omap/omap3-clock.h | 124 ++++++++++ 5 files changed, 942 insertions(+)
Index: u-boot-v2.git/arch/arm/mach-omap/omap3_clock.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-v2.git/arch/arm/mach-omap/omap3_clock.c 2008-05-20 17:53:04.000000000 -0500 @@ -0,0 +1,378 @@ +/** + * @file + * @brief OMAP DPLL and various clock configuration + * + * FileName: arch/arm/mach-omap/omap3_clock.c + * + * @ref prcm_init This is the second level clock init for PRCM as defined in + * clocks.h -- called from SRAM, or Flash (using temp SRAM stack). + * + * During reconfiguring the clocks while in SDRAM/Flash, we can have invalid + * clock configuration to which ARM instruction/data fetch ops can fail. + * This critical path is handled by relocating the relevant functions in + * omap3_clock_core.S to OMAP's ISRAM and executing it there. + * + * @warning: IMPORTANT: These functions run from ISRAM stack, so no bss sections + * should be used: functions cannot use global variables/switch constructs. + * + * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz + */ +/* + * (C) Copyright 2006-2008 + * Texas Instruments, <www.ti.com> + * Richard Woodruff r-woodruff2@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/silicon.h> +#include <asm/arch/clocks.h> +#include <asm/arch/timers.h> +#include <asm/arch/sys_info.h> +#include <asm/arch/syslib.h> + +/* Following functions are exported from omap3_clock_core.S */ +#ifdef CONFIG_OMAP3_COPY_CLOCK_SRAM +/* A.K.A go_to_speed */ +static void (*f_lock_pll) (u32, u32, u32, u32); +#endif +/* Helper functions */ +static u32 get_osc_clk_speed(void); +static void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel); +static void per_clocks_enable(void); + +/** + * @brief Determine reference oscillator speed + * + * This is based on known 32kHz clock and gptimer. + * + * @return clock speed S38_4M, S26M S24M S19_2M S13M S12M + */ +static u32 get_osc_clk_speed(void) +{ + u32 start, cstart, cend, cdiff, val; + + val = __raw_readl(PRM_REG(CLKSRC_CTRL)); + /* If SYS_CLK is being divided by 2, remove for now */ + val = (val & (~BIT7)) | BIT6; + __raw_writel(val, PRM_REG(CLKSRC_CTRL)); + + /* enable timer2 */ + val = __raw_readl(CM_REG(CLKSEL_WKUP)) | BIT0; + __raw_writel(val, CM_REG(CLKSEL_WKUP)); /* select sys_clk for GPT1 */ + + /* Enable I and F Clocks for GPT1 */ + val = __raw_readl(CM_REG(ICLKEN_WKUP)) | BIT0 | BIT2; + __raw_writel(val, CM_REG(ICLKEN_WKUP)); + val = __raw_readl(CM_REG(FCLKEN_WKUP)) | BIT0; + __raw_writel(val, CM_REG(FCLKEN_WKUP)); + + __raw_writel(0, OMAP_GPTIMER1_BASE + TLDR); /* start counting at 0 */ + __raw_writel(GPT_EN, OMAP_GPTIMER1_BASE + TCLR); /* enable clock */ + /* enable 32kHz source *//* enabled out of reset */ + /* determine sys_clk via gauging */ + + start = 20 + __raw_readl(S32K_CR); /* start time in 20 cycles */ + while (__raw_readl(S32K_CR) < start) ; /* dead loop till start time */ + /* get start sys_clk count */ + cstart = __raw_readl(OMAP_GPTIMER1_BASE + TCRR); + while (__raw_readl(S32K_CR) < (start + 20)) ; /* wait for 40 cycles */ + /* get end sys_clk count */ + cend = __raw_readl(OMAP_GPTIMER1_BASE + TCRR); + cdiff = cend - cstart; /* get elapsed ticks */ + + /* based on number of ticks assign speed */ + if (cdiff > 19000) + return (S38_4M); + else if (cdiff > 15200) + return (S26M); + else if (cdiff > 13000) + return (S24M); + else if (cdiff > 9000) + return (S19_2M); + else if (cdiff > 7600) + return (S13M); + else + return (S12M); +} + +/** + * @brief Returns the sys_clkin_sel field value + * + * This is based on input oscillator clock frequency. + * + * @param[in] osc_clk - Oscilaltor Clock to OMAP + * @param[out] sys_clkin_sel - returns the sys_clk selection + * + * @return void + */ +static void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel) +{ + if (osc_clk == S38_4M) + *sys_clkin_sel = 4; + else if (osc_clk == S26M) + *sys_clkin_sel = 3; + else if (osc_clk == S19_2M) + *sys_clkin_sel = 2; + else if (osc_clk == S13M) + *sys_clkin_sel = 1; + else if (osc_clk == S12M) + *sys_clkin_sel = 0; +} + +/** + * @brief Inits clocks for PRCM + * + * This is called from SRAM, or Flash (using temp SRAM stack). + * if CONFIG_OMAP3_COPY_CLOCK_SRAM is defined, @ref go_to_speed + * + * @return void + */ +void prcm_init(void) +{ + int xip_safe; + u32 osc_clk = 0, sys_clkin_sel = 0; + u32 clk_index, sil_index; + struct dpll_param *dpll_param_p; +#ifdef CONFIG_OMAP3_COPY_CLOCK_SRAM + int p0, p1, p2, p3; + f_lock_pll = (void *)(OMAP_SRAM_INTVECT + OMAP_SRAM_INTVECT_COPYSIZE); +#endif + + xip_safe = running_in_sram(); + + /* Gauge the input clock speed and find out the sys_clkin_sel + * value corresponding to the input clock. + */ + osc_clk = get_osc_clk_speed(); + get_sys_clkin_sel(osc_clk, &sys_clkin_sel); + /* set input crystal speed */ + sr32(PRM_REG(CLKSEL), 0, 3, sys_clkin_sel); + + /* If the input clock is greater than 19.2M always divide/2 */ + if (sys_clkin_sel > 2) { + /* input clock divider */ + sr32(PRM_REG(CLKSRC_CTRL), 6, 2, 2); + clk_index = sys_clkin_sel / 2; + } else { + /* input clock divider */ + sr32(PRM_REG(CLKSRC_CTRL), 6, 2, 1); + clk_index = sys_clkin_sel; + } + + /* The DPLL tables are defined according to sysclk value and + * silicon revision. The clk_index value will be used to get + * the values for that input sysclk from the DPLL param table + * and sil_index will get the values for that SysClk for the + * appropriate silicon rev. + */ + if (get_cpu_rev() >= CPU_ES2) + sil_index = 1; + /* Unlock MPU DPLL (slows things down, and needed later) */ + sr32(CM_REG(CLKEN_PLL_MPU), 0, 3, PLL_LOW_POWER_BYPASS); + wait_on_value(BIT0, 0, CM_REG(IDLEST_PLL_MPU), LDELAY); + + /* Getting the base address of Core DPLL param table */ + dpll_param_p = (struct dpll_param *) get_core_dpll_param(); + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + MAX_SIL_INDEX * clk_index + sil_index; + if (xip_safe) { + /* CORE DPLL */ + /* sr32(CM_REG(CLKSEL2_EMU)) set override to work when asleep */ + sr32(CM_REG(CLKEN_PLL), 0, 3, PLL_FAST_RELOCK_BYPASS); + wait_on_value(BIT0, 0, CM_REG(IDLEST_CKGEN), LDELAY); + /* For 3430 ES1.0 Errata 1.50, default value directly doesnt + work. write another value and then default value. */ + sr32(CM_REG(CLKSEL1_EMU), 16, 5, CORE_M3X2 + 1); /* m3x2 */ + sr32(CM_REG(CLKSEL1_EMU), 16, 5, CORE_M3X2); /* m3x2 */ + sr32(CM_REG(CLKSEL1_PLL), 27, 2, dpll_param_p->m2); /* Set M2 */ + sr32(CM_REG(CLKSEL1_PLL), 16, 11, dpll_param_p->m); /* Set M */ + sr32(CM_REG(CLKSEL1_PLL), 8, 7, dpll_param_p->n); /* Set N */ + sr32(CM_REG(CLKSEL1_PLL), 6, 1, 0); /* 96M Src */ + sr32(CM_REG(CLKSEL_CORE), 8, 4, CORE_SSI_DIV); /* ssi */ + sr32(CM_REG(CLKSEL_CORE), 4, 2, CORE_FUSB_DIV); /* fsusb */ + sr32(CM_REG(CLKSEL_CORE), 2, 2, CORE_L4_DIV); /* l4 */ + sr32(CM_REG(CLKSEL_CORE), 0, 2, CORE_L3_DIV); /* l3 */ + sr32(CM_REG(CLKSEL_GFX), 0, 3, GFX_DIV); /* gfx */ + sr32(CM_REG(CLKSEL_WKUP), 1, 2, WKUP_RSM); /* reset mgr */ + sr32(CM_REG(CLKEN_PLL), 4, 4, dpll_param_p->fsel); /* FREQSEL */ + sr32(CM_REG(CLKEN_PLL), 0, 3, PLL_LOCK); /* lock mode */ + wait_on_value(BIT0, 1, CM_REG(IDLEST_CKGEN), LDELAY); + } else if (running_in_flash()) { +#ifdef CONFIG_OMAP3_COPY_CLOCK_SRAM + /* if running from flash, + * jump to small relocated code area in SRAM. + */ + p0 = __raw_readl(CM_REG(CLKEN_PLL)); + sr32((u32) &p0, 0, 3, PLL_FAST_RELOCK_BYPASS); + sr32((u32) &p0, 4, 4, dpll_param_p->fsel); /* FREQSEL */ + + p1 = __raw_readl(CM_REG(CLKSEL1_PLL)); + sr32((u32) &p1, 27, 2, dpll_param_p->m2); /* Set M2 */ + sr32((u32) &p1, 16, 11, dpll_param_p->m); /* Set M */ + sr32((u32) &p1, 8, 7, dpll_param_p->n); /* Set N */ + sr32((u32) &p1, 6, 1, 0); /* set source for 96M */ + p2 = __raw_readl(CM_REG(CLKSEL_CORE)); + sr32((u32) &p2, 8, 4, CORE_SSI_DIV); /* ssi */ + sr32((u32) &p2, 4, 2, CORE_FUSB_DIV); /* fsusb */ + sr32((u32) &p2, 2, 2, CORE_L4_DIV); /* l4 */ + sr32((u32) &p2, 0, 2, CORE_L3_DIV); /* l3 */ + + p3 = CM_REG(IDLEST_CKGEN); + + (*f_lock_pll) (p0, p1, p2, p3); +#else + /***Oopps.. Wrong .config!! *****/ + hang(); +#endif + } + + /* PER DPLL */ + sr32(CM_REG(CLKEN_PLL), 16, 3, PLL_STOP); + wait_on_value(BIT1, 0, CM_REG(IDLEST_CKGEN), LDELAY); + + /* Getting the base address to PER DPLL param table */ + /* Set N */ + dpll_param_p = (struct dpll_param *) get_per_dpll_param(); + /* Moving it to the right sysclk base */ + dpll_param_p = dpll_param_p + clk_index; + /* Errata 1.50 Workaround for 3430 ES1.0 only */ + /* If using default divisors, write default divisor + 1 + and then the actual divisor value */ + /* Need to change it to silicon and revisino check */ + if (1) { + sr32(CM_REG(CLKSEL1_EMU), 24, 5, PER_M6X2 + 1); /* set M6 */ + sr32(CM_REG(CLKSEL1_EMU), 24, 5, PER_M6X2); /* set M6 */ + sr32(CM_REG(CLKSEL_CAM), 0, 5, PER_M5X2 + 1); /* set M5 */ + sr32(CM_REG(CLKSEL_CAM), 0, 5, PER_M5X2); /* set M5 */ + sr32(CM_REG(CLKSEL_DSS), 0, 5, PER_M4X2 + 1); /* set M4 */ + sr32(CM_REG(CLKSEL_DSS), 0, 5, PER_M4X2); /* set M4 */ + sr32(CM_REG(CLKSEL_DSS), 8, 5, PER_M3X2 + 1); /* set M3 */ + sr32(CM_REG(CLKSEL_DSS), 8, 5, PER_M3X2); /* set M3 */ + /* set M2 */ + sr32(CM_REG(CLKSEL3_PLL), 0, 5, dpll_param_p->m2 + 1); + sr32(CM_REG(CLKSEL3_PLL), 0, 5, dpll_param_p->m2); /* set M2 */ + } else { + sr32(CM_REG(CLKSEL1_EMU), 24, 5, PER_M6X2); /* set M6 */ + sr32(CM_REG(CLKSEL_CAM), 0, 5, PER_M5X2); /* set M5 */ + sr32(CM_REG(CLKSEL_DSS), 0, 5, PER_M4X2); /* set M4 */ + sr32(CM_REG(CLKSEL_DSS), 8, 5, PER_M3X2); /* set M3 */ + sr32(CM_REG(CLKSEL3_PLL), 0, 5, dpll_param_p->m2); /* set M2 */ + } + sr32(CM_REG(CLKSEL2_PLL), 8, 11, dpll_param_p->m); /* set m */ + sr32(CM_REG(CLKSEL2_PLL), 0, 7, dpll_param_p->n); /* set n */ + sr32(CM_REG(CLKEN_PLL), 20, 4, dpll_param_p->fsel); /* FREQSEL */ + sr32(CM_REG(CLKEN_PLL), 16, 3, PLL_LOCK); /* lock mode */ + wait_on_value(BIT1, 2, CM_REG(IDLEST_CKGEN), LDELAY); + + /* Getting the base address to MPU DPLL param table */ + dpll_param_p = (struct dpll_param *) get_mpu_dpll_param(); + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + MAX_SIL_INDEX * clk_index + sil_index; + /* MPU DPLL (unlocked already) */ + sr32(CM_REG(CLKSEL2_PLL_MPU), 0, 5, dpll_param_p->m2); /* Set M2 */ + sr32(CM_REG(CLKSEL1_PLL_MPU), 8, 11, dpll_param_p->m); /* Set M */ + sr32(CM_REG(CLKSEL1_PLL_MPU), 0, 7, dpll_param_p->n); /* Set N */ + sr32(CM_REG(CLKEN_PLL_MPU), 4, 4, dpll_param_p->fsel); /* FREQSEL */ + sr32(CM_REG(CLKEN_PLL_MPU), 0, 3, PLL_LOCK); /* lock mode */ + wait_on_value(BIT0, 1, CM_REG(IDLEST_PLL_MPU), LDELAY); + + /* Getting the base address to IVA DPLL param table */ + dpll_param_p = (struct dpll_param *) get_iva_dpll_param(); + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + MAX_SIL_INDEX * clk_index + sil_index; + /* IVA DPLL (set to 12*20=240MHz) */ + sr32(CM_REG(CLKEN_PLL_IVA2), 0, 3, PLL_STOP); + wait_on_value(BIT0, 0, CM_REG(IDLEST_PLL_IVA2), LDELAY); + sr32(CM_REG(CLKSEL2_PLL_IVA2), 0, 5, dpll_param_p->m2); /* set M2 */ + sr32(CM_REG(CLKSEL1_PLL_IVA2), 8, 11, dpll_param_p->m); /* set M */ + sr32(CM_REG(CLKSEL1_PLL_IVA2), 0, 7, dpll_param_p->n); /* set N */ + sr32(CM_REG(CLKEN_PLL_IVA2), 4, 4, dpll_param_p->fsel); /* FREQSEL */ + sr32(CM_REG(CLKEN_PLL_IVA2), 0, 3, PLL_LOCK); /* lock mode */ + wait_on_value(BIT0, 1, CM_REG(IDLEST_PLL_IVA2), LDELAY); + + /* Set up GPTimers to sys_clk source only */ + sr32(CM_REG(CLKSEL_PER), 0, 8, 0xff); + sr32(CM_REG(CLKSEL_WKUP), 0, 1, 1); + + sdelay(5000); + + /* Enable Peripheral Clocks */ + per_clocks_enable(); +} + +/** + * @brief Enable the clks & power for perifs + * + * GPT2 Sysclk, ICLK,FCLK, 32k Sync is enabled by default + * Uses CONFIG_OMAP_CLOCK_UART to enable UART clocks + * Uses CONFIG_OMAP_CLOCK_I2C to enable I2C clocks + * Uses CONFIG_OMAP_CLOCK_ALL to enable All Clocks! + * - Not a wise idea in most cases + * + * @return void + */ +static void per_clocks_enable(void) +{ + /* Enable GP2 timer. */ + sr32(CM_REG(CLKSEL_PER), 0, 1, 0x1); /* GPT2 = sys clk */ + sr32(CM_REG(ICLKEN_PER), 3, 1, 0x1); /* ICKen GPT2 */ + sr32(CM_REG(FCLKEN_PER), 3, 1, 0x1); /* FCKen GPT2 */ + /* Enable the ICLK for 32K Sync Timer as its used in udelay */ + sr32(CM_REG(ICLKEN_WKUP), 2, 1, 0x1); + +#ifdef CONFIG_OMAP_CLOCK_UART + /* Enable UART1 clocks */ + sr32(CM_REG(FCLKEN1_CORE), 13, 1, 0x1); + sr32(CM_REG(ICLKEN1_CORE), 13, 1, 0x1); +#endif +#ifdef CONFIG_OMAP_CLOCK_I2C + /* Turn on all 3 I2C clocks */ + sr32(CM_REG(FCLKEN1_CORE), 15, 3, 0x7); + sr32(CM_REG(ICLKEN1_CORE), 15, 3, 0x7); /* I2C1,2,3 = on */ +#endif + +#ifdef CONFIG_OMAP_CLOCK_ALL +#define FCK_IVA2_ON 0x00000001 +#define FCK_CORE1_ON 0x03fffe29 +#define ICK_CORE1_ON 0x3ffffffb +#define ICK_CORE2_ON 0x0000001f +#define FCK_WKUP_ON 0x000000e9 +#define ICK_WKUP_ON 0x0000003f +#define FCK_DSS_ON 0x00000005 /* tv+dss1 (not dss2) */ +#define ICK_DSS_ON 0x00000001 +#define FCK_CAM_ON 0x00000001 +#define ICK_CAM_ON 0x00000001 +#define FCK_PER_ON 0x0003ffff +#define ICK_PER_ON 0x0003ffff + sr32(CM_REG(FCLKEN_IVA2), 0, 32, FCK_IVA2_ON); + sr32(CM_REG(FCLKEN1_CORE), 0, 32, FCK_CORE1_ON); + sr32(CM_REG(ICLKEN1_CORE), 0, 32, ICK_CORE1_ON); + sr32(CM_REG(ICLKEN2_CORE), 0, 32, ICK_CORE2_ON); + sr32(CM_REG(FCLKEN_WKUP), 0, 32, FCK_WKUP_ON); + sr32(CM_REG(ICLKEN_WKUP), 0, 32, ICK_WKUP_ON); + sr32(CM_REG(FCLKEN_DSS), 0, 32, FCK_DSS_ON); + sr32(CM_REG(ICLKEN_DSS), 0, 32, ICK_DSS_ON); + sr32(CM_REG(FCLKEN_CAM), 0, 32, FCK_CAM_ON); + sr32(CM_REG(ICLKEN_CAM), 0, 32, ICK_CAM_ON); + sr32(CM_REG(FCLKEN_PER), 0, 32, FCK_PER_ON); + sr32(CM_REG(ICLKEN_PER), 0, 32, ICK_PER_ON); +#endif + /* Settle down my friend */ + sdelay(1000); +} Index: u-boot-v2.git/arch/arm/mach-omap/omap3_clock_core.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-v2.git/arch/arm/mach-omap/omap3_clock_core.S 2008-05-20 17:47:25.000000000 -0500 @@ -0,0 +1,312 @@ +/** + * @file + * @brief Provides PRCM divisors and SRAM execution code. + * + * FileName: arch/arm/mach-omap/omap3_clock_core.S + * + * This provides two things: + * @li @ref omap3_clock.c cannot have switch or global variables. + * This file provides the constant data for the file to use. + * + * @li @ref prcm_init cannot execute certain critical clock + * configurations while running in SDRAM/Flash. This provides + * relocation and execution capability for the same. + * + * Orignally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz + */ +/* + * (C) Copyright 2006-2008 + * Texas Instruments, <www.ti.com> + * Richard Woodruff r-woodruff2@ti.com + * Nishanth Menon x0nishan@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <asm/arch/silicon.h> +#include <asm/arch/clocks.h> +#include <asm/arch/gpmc.h> + +#ifdef CONFIG_OMAP3_COPY_CLOCK_SRAM +/** + * @fn void cpy_clk_code(u32 R1) + * + * @brief cpy_clk_code: relocates clock code into SRAM where its safer to + * execute + * + * @param[in] R1 = SRAM destination address. + * + * @return void + */ +.global cpy_clk_code + cpy_clk_code: + /* Copy DPLL code into SRAM */ + adr r0, go_to_speed /* get addr of clock setting code */ + mov r2, #384 /* r2 size to copy (div by 32 bytes) */ + mov r1, r1 /* r1 <- dest address (passed in) */ + add r2, r2, r0 /* r2 <- source end address */ +next2: + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end address [r2] */ + bne next2 + mov pc, lr /* back to caller */ + +/** + * @fn void go_to_speed(u32 R0, u32 R1, u32 R3) + * + * @brief go_to_speed: Function which configures the clocks + * Moves to bypass, -Commits clock dividers, -puts dpll at speed + * -executed from SRAM. + * @warning Note: If core unlocks/relocks and SDRAM is running fast already + * it gets confused. A reset of the controller gets it back. Taking + * away its L3 when its not in self refresh seems bad for it. + * Normally, this code runs from flash before SDR is init so that + * should be ok. + * + * @param[in] R1 = SRAM destination address. + * @param[in] R0 = CM_CLKEN_PLL-bypass value + * @param[in] R1 = CM_CLKSEL1_PLL-m, n, and divider values + * @param[in] R2 = CM_CLKSEL_CORE-divider values + * @param[in] R3 = CM_IDLEST_CKGEN - addr dpll lock wait + * + * @return void + */ +.global go_to_speed + go_to_speed: + stmfd sp!, {r4-r6} + + /* move into fast relock bypass */ + ldr r4, pll_ctl_add + str r0, [r4] +wait1: + ldr r5, [r3] /* get status */ + and r5, r5, #0x1 /* isolate core status */ + cmp r5, #0x1 /* still locked? */ + beq wait1 /* if lock, loop */ + + /* set new dpll dividers _after_ in bypass */ + ldr r5, pll_div_add1 + str r1, [r5] /* set m, n, m2 */ + ldr r5, pll_div_add2 + str r2, [r5] /* set l3/l4/.. dividers*/ + ldr r5, pll_div_add3 /* wkup */ + ldr r2, pll_div_val3 /* rsm val */ + str r2, [r5] + ldr r5, pll_div_add4 /* gfx */ + ldr r2, pll_div_val4 + str r2, [r5] + ldr r5, pll_div_add5 /* emu */ + ldr r2, pll_div_val5 + str r2, [r5] + +#if 0 + /* FIXME: now prepare GPMC (flash) for new dpll speed + * For NOR/NAND/OneNAND boot ->make this as Kconfig? + */ + /* flash needs to be stable when we jump back to it */ + ldr r6, flash_cfg_offset + ldr r5, flash_cfg_addr /* CFG1 */ + ldr r2, flash_cfg1_val + str r2, [r5] + add r5, r5, r6 /* CFG2 */ + ldr r2, flash_cfg2_val + str r2, [r5] + add r5, r5, r6 /* CFG3 */ + ldr r2, flash_cfg3_val + str r2, [r5] + add r5, r5, r6 /* CFG4 */ + ldr r2, flash_cfg4_val + str r2, [r5] + add r5, r5, r6 /* CFG5 */ + ldr r2, flash_cfg5_val + str r2, [r5] + add r5, r5, r6 /* CFG6 */ + ldr r2, flash_cfg6_val + str r2, [r5] +#endif /* Debug */ + + /* lock DPLL3 and wait a bit */ + orr r0, r0, #0x7 /* set up for lock mode */ + str r0, [r4] /* lock */ + nop /* ARM slow at this point working at sys_clk */ + nop + nop + nop +wait2: + ldr r5, [r3] /* get status */ + and r5, r5, #0x1 /* isolate core status */ + cmp r5, #0x1 /* still locked? */ + bne wait2 /* if lock, loop */ + nop + nop + nop + nop + ldmfd sp!, {r4-r6} + mov pc, lr /* back to caller, locked */ + +_go_to_speed: .word go_to_speed + +/* these constants need to be close for PIC code */ +/* FIXME: The Nor has to be in the Flash Base CS0 for this condition to happen*/ +#if 0 +flash_cfg_addr: + .word GPMC_REG(CONFIG1_0) +flash_cfg_offset: + .word GPMC_REG(CONFIG2_0) - GPMC_REG(CONFIG1_0) +flash_cfg1_val: + .word CONFIG_VALUE_GPMC_CONFIG1 +flash_cfg2_val: + .word CONFIG_VALUE_GPMC_CONFIG2 +flash_cfg3_val: + .word CONFIG_VALUE_GPMC_CONFIG3 +flash_cfg4_val: + .word CONFIG_VALUE_GPMC_CONFIG4 +flash_cfg5_val: + .word CONFIG_VALUE_GPMC_CONFIG5 +flash_cfg6_val: + .word CONFIG_VALUE_GPMC_CONFIG6 +#endif +pll_ctl_add: + .word CM_CLKEN_PLL +pll_div_add1: + .word CM_CLKSEL1_PLL +pll_div_add2: + .word CM_CLKSEL_CORE +pll_div_add3: + .word CM_CLKSEL_WKUP +pll_div_val3: + .word (WKUP_RSM << 1) +pll_div_add4: + .word CM_CLKSEL_GFX +pll_div_val4: + .word (GFX_DIV << 0) +pll_div_add5: + .word CM_CLKSEL1_EMU +pll_div_val5: + .word CLSEL1_EMU_VAL + +#endif /* OMAP3_CLOCK_COPY_SRAM */ + + /* the literal pools origin */ + .ltorg + +/* DPLL(1-4) PARAM TABLES */ +/* Each of the tables has M, N, FREQSEL, M2 values defined for nominal + * OPP (1.2V). The fields are defined according to dpll_param + * struct(omap3_clock.c). MAX index is as per omap3_clock.h + */ + +mpu_dpll_param: +/* 12MHz */ +/* ES2 */ +.word 0x0FA,0x05,0x07,0x01 + +/* 13MHz */ +/* ES2 */ +.word 0x1F4,0x0C,0x03,0x01 + +/* 19.2MHz */ +/* ES2 */ +.word 0x271,0x17,0x03,0x01 + +/* 26MHz */ +/* ES2 */ +.word 0x0FA,0x0C,0x07,0x01 + +/* 38.4MHz */ +/* ES2 */ +.word 0x271,0x2F,0x03,0x01 + +.globl get_mpu_dpll_param +get_mpu_dpll_param: + adr r0, mpu_dpll_param + mov pc, lr + +iva_dpll_param: +/* 12MHz */ +/* ES2 */ +.word 0x0B4,0x05,0x07,0x01 + +/* 13MHz */ +/* ES2 */ +.word 0x168,0x0C,0x03,0x01 + +/* 19.2MHz */ +/* ES2 */ +.word 0x0E1,0x0B,0x06,0x01 + +/* 26MHz */ +/* ES2 */ +.word 0x0B4,0x0C,0x07,0x01 + +/* 38.4MHz */ +/* ES2 */ +.word 0x0E1,0x17,0x06,0x01 + +.globl get_iva_dpll_param +get_iva_dpll_param: + adr r0, iva_dpll_param + mov pc, lr + +core_dpll_param: +/* 12MHz */ +/* ES2 */ +.word 0x0A6,0x05,0x07,0x01 + +/* 13MHz */ +/* ES2 */ +.word 0x14C,0x0C,0x03,0x01 + +/* 19.2MHz */ +/* ES2 */ +.word 0x19F,0x17,0x03,0x01 + +/* 26MHz */ +/* ES2 */ +.word 0x0A6,0x0C,0x07,0x01 + +/* 38.4MHz */ +/* ES2 */ +.word 0x19F,0x2F,0x03,0x01 + +.globl get_core_dpll_param +get_core_dpll_param: + adr r0, core_dpll_param + mov pc, lr + +/* PER DPLL values are same for both ES1 and ES2 */ +per_dpll_param: +/* 12MHz */ +.word 0xD8,0x05,0x07,0x09 + +/* 13MHz */ +.word 0x1B0,0x0C,0x03,0x09 + +/* 19.2MHz */ +.word 0xE1,0x09,0x07,0x09 + +/* 26MHz */ +.word 0xD8,0x0C,0x07,0x09 + +/* 38.4MHz */ +.word 0xE1,0x13,0x07,0x09 + +.globl get_per_dpll_param +get_per_dpll_param: + adr r0, per_dpll_param + mov pc, lr Index: u-boot-v2.git/arch/arm/mach-omap/s32k_clksource.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-v2.git/arch/arm/mach-omap/s32k_clksource.c 2008-05-20 17:47:25.000000000 -0500 @@ -0,0 +1,80 @@ +/** + * @file + * @brief Provide @ref clocksource functionality for OMAP + * + * FileName: arch/arm/mach-omap/s32k_clksource.c + * + * @ref clocksource provides a neat architecture. all we do is + * To loop in with Sync 32Khz clock ticking away at 32768hz on OMAP. + * Sync 32Khz clock is an always ON clock. + * + */ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * Nishanth Menon x0nishan@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <clock.h> +#include <init.h> +#include <asm/io.h> +#include <asm/arch/silicon.h> +#include <asm/arch/clocks.h> +#include <asm/arch/timers.h> +#include <asm/arch/sys_info.h> +#include <asm/arch/syslib.h> + +/** + * @brief Provide a simple clock read + * + * Nothing is simpler.. read direct from clock and provide it + * to the caller. + * + * @return S32K clock counter + */ +static uint64_t s32k_clocksource_read(void) +{ + return __raw_readl(S32K_CR); +} + +/* A bit obvious isn't it? */ +static struct clocksource s32k_cs = { + .read = s32k_clocksource_read, + .mask = 0xffffffff, + .shift = 10, +}; + +/** + * @brief Initialize the Clock + * + * There is nothing to do on OMAP as SYNC32K clock is + * always on, and we do a simple data structure initialization. + * 32K clock gives 32768 ticks a seconds + * + * @return result of @ref init_clock + */ +static int s32k_clocksource_init(void) +{ + s32k_cs.mult = clocksource_hz2mult(S32K_FREQUENCY, s32k_cs.shift); + + return init_clock(&s32k_cs); +} + +/* Run me at boot time */ +core_initcall(s32k_clocksource_init); Index: u-boot-v2.git/include/asm-arm/arch-omap/omap3-clock.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-v2.git/include/asm-arm/arch-omap/omap3-clock.h 2008-05-20 17:53:07.000000000 -0500 @@ -0,0 +1,124 @@ +/** + * @file + * @brief Contains the PRM and CM definitions + * + * FileName: include/asm-arm/arch-omap/omap3-clock.h + * + * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz + * + */ +/* + * (C) Copyright 2006-2008 + * Texas Instruments, <www.ti.com> + * Richard Woodruff r-woodruff2@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef _OMAP343X_CLOCKS_H_ +#define _OMAP343X_CLOCKS_H_ + +/** CM Clock Regs Wrapper */ +#define CM_REG(REGNAME) (OMAP_CM_BASE + CM_##REGNAME) + +#define CM_FCLKEN_IVA2 0X0000 +#define CM_CLKEN_PLL_IVA2 0X0004 +#define CM_IDLEST_PLL_IVA2 0X0024 +#define CM_CLKSEL1_PLL_IVA2 0X0040 +#define CM_CLKSEL2_PLL_IVA2 0X0044 +#define CM_CLKEN_PLL_MPU 0X0904 +#define CM_IDLEST_PLL_MPU 0X0924 +#define CM_CLKSEL1_PLL_MPU 0X0940 +#define CM_CLKSEL2_PLL_MPU 0X0944 +#define CM_FCLKEN1_CORE 0X0A00 +#define CM_ICLKEN1_CORE 0X0A10 +#define CM_ICLKEN2_CORE 0X0A14 +#define CM_CLKSEL_CORE 0X0A40 +#define CM_FCLKEN_GFX 0X0B00 +#define CM_ICLKEN_GFX 0X0B10 +#define CM_CLKSEL_GFX 0X0B40 +#define CM_FCLKEN_WKUP 0X0C00 +#define CM_ICLKEN_WKUP 0X0C10 +#define CM_CLKSEL_WKUP 0X0C40 +#define CM_IDLEST_WKUP 0X0C20 +#define CM_CLKEN_PLL 0X0D00 +#define CM_IDLEST_CKGEN 0X0D20 +#define CM_CLKSEL1_PLL 0X0D40 +#define CM_CLKSEL2_PLL 0X0D44 +#define CM_CLKSEL3_PLL 0X0D48 +#define CM_FCLKEN_DSS 0X0E00 +#define CM_ICLKEN_DSS 0X0E10 +#define CM_CLKSEL_DSS 0X0E40 +#define CM_FCLKEN_CAM 0X0F00 +#define CM_ICLKEN_CAM 0X0F10 +#define CM_CLKSEL_CAM 0X0f40 +#define CM_FCLKEN_PER 0X1000 +#define CM_ICLKEN_PER 0X1010 +#define CM_CLKSEL_PER 0X1040 +#define CM_CLKSEL1_EMU 0X1140 + +/** PRM Clock Regs */ +#define PRM_REG(REGNAME) (OMAP_PRM_BASE + PRM_##REGNAME) +#define PRM_CLKSEL 0x0D40 +#define PRM_RSTCTRL 0x1250 +#define PRM_CLKSRC_CTRL 0x1270 + +/*************** Clock Values */ +#define PLL_STOP 1 /* PER & IVA */ +#define PLL_LOW_POWER_BYPASS 5 /* MPU, IVA & CORE */ +#define PLL_FAST_RELOCK_BYPASS 6 /* CORE */ +#define PLL_LOCK 7 /* MPU, IVA, CORE & PER */ + +/* The following configurations are OPP and SysClk value independant + * and hence are defined here. + */ + +/* CORE DPLL */ +#define CORE_M3X2 2 /* 332MHz : CM_CLKSEL1_EMU */ +#define CORE_SSI_DIV 3 /* 221MHz : CM_CLKSEL_CORE */ +#define CORE_FUSB_DIV 2 /* 41.5MHz: */ +#define CORE_L4_DIV 2 /* 83MHz : L4 */ +#define CORE_L3_DIV 2 /* 166MHz : L3 {DDR} */ +#define GFX_DIV 2 /* 83MHz : CM_CLKSEL_GFX */ +#define WKUP_RSM 2 /* 41.5MHz: CM_CLKSEL_WKUP */ + +/* PER DPLL */ +#define PER_M6X2 3 /* 288MHz: CM_CLKSEL1_EMU */ +#define PER_M5X2 4 /* 216MHz: CM_CLKSEL_CAM */ +#define PER_M4X2 9 /* 96MHz : CM_CLKSEL_DSS-dss1 */ +#define PER_M3X2 16 /* 54MHz : CM_CLKSEL_DSS-tv */ + +#define CLSEL1_EMU_VAL ((CORE_M3X2 << 16) | (PER_M6X2 << 24) | (0x0a50)) + +#define MAX_SIL_INDEX 1 + +#ifndef __ASSEMBLY__ +void prcm_init(void); +/* Used to index into DPLL parameter tables -See TRM for further details */ +struct dpll_param { + unsigned int m; + unsigned int n; + unsigned int fsel; + unsigned int m2; +}; +/* External functions see omap3_clock_core.S */ +extern struct dpll_param *get_mpu_dpll_param(void); +extern struct dpll_param *get_iva_dpll_param(void); +extern struct dpll_param *get_core_dpll_param(void); +extern struct dpll_param *get_per_dpll_param(void); + +#endif /* __ASSEMBLY__ */ + +#endif /* endif _OMAP343X_CLOCKS_H_ */ Index: u-boot-v2.git/include/asm-arm/arch-omap/clocks.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-v2.git/include/asm-arm/arch-omap/clocks.h 2008-05-20 17:47:25.000000000 -0500 @@ -0,0 +1,48 @@ +/** + * @file + * @brief Generic Clock wrapper header. + * + * FileName: include/asm-arm/arch-omap/clocks.h + * + * This includes each of the architecture Clock definitions under it. + * + * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz + */ +/* + * (C) Copyright 2006-2008 + * Texas Instruments, <www.ti.com> + * Richard Woodruff r-woodruff2@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef __OMAP_CLOCKS_H_ +#define __OMAP_CLOCKS_H_ + +#define LDELAY 12000000 + +/* Standard defines for Various clocks */ +#define S12M 12000000 +#define S13M 13000000 +#define S19_2M 19200000 +#define S24M 24000000 +#define S26M 26000000 +#define S38_4M 38400000 + +#ifdef CONFIG_ARCH_OMAP3 +#include <asm/arch/omap3-clock.h> +#endif + +#endif /* __OMAP_CLOCKS_H_ */

Sascha,
-----Original Message----- From: u-boot-users-bounces@lists.sourceforge.net [mailto:u-boot-users-bounces@lists.sourceforge.net] On Behalf Of Menon, Nishanth Sent: Wednesday, May 21, 2008 11:30 AM To: Sascha Hauer Cc: u-boot-users@lists.sourceforge.net; Kamat, Nishant; Syed Mohammed, Khasim; Laurent Desnogues; philip.balister@gmail.com Subject: [U-Boot-Users] [Patch 12/17] U-Boot-V2:ARM:OMAP3: Add support forOMAP3 Silicon files
This patch introduces support for OMAP3430 clocking infrastructure. Please note that SRAM based configuration requires GPMC values to be updated before returning to caller- TBD.
Cleanup with BIT defines and return style corrected.
Signed-off-by: Nishanth Menonx0nishan@ti.com
--- arch/arm/mach-omap/omap3_clock.c | 379 ++++++++++++++++++++++++++++++++ arch/arm/mach-omap/omap3_clock_core.S | 312 ++++++++++++++++++++++++++ arch/arm/mach-omap/s32k_clksource.c | 80 ++++++ include/asm-arm/arch-omap/clocks.h | 48 ++++ include/asm-arm/arch-omap/omap3-clock.h | 124 ++++++++++ 5 files changed, 943 insertions(+)
Index: u-boot.v2/arch/arm/mach-omap/omap3_clock.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot.v2/arch/arm/mach-omap/omap3_clock.c 2008-06-03 22:53:19.000000000 -0500 @@ -0,0 +1,379 @@ +/** + * @file + * @brief OMAP DPLL and various clock configuration + * + * FileName: arch/arm/mach-omap/omap3_clock.c + * + * @ref prcm_init This is the second level clock init for PRCM as defined in + * clocks.h -- called from SRAM, or Flash (using temp SRAM stack). + * + * During reconfiguring the clocks while in SDRAM/Flash, we can have invalid + * clock configuration to which ARM instruction/data fetch ops can fail. + * This critical path is handled by relocating the relevant functions in + * omap3_clock_core.S to OMAP's ISRAM and executing it there. + * + * @warning: IMPORTANT: These functions run from ISRAM stack, so no bss sections + * should be used: functions cannot use global variables/switch constructs. + * + * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz + */ +/* + * (C) Copyright 2006-2008 + * Texas Instruments, <www.ti.com> + * Richard Woodruff r-woodruff2@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/silicon.h> +#include <asm/arch/clocks.h> +#include <asm/arch/timers.h> +#include <asm/arch/sys_info.h> +#include <asm/arch/syslib.h> + +/* Following functions are exported from omap3_clock_core.S */ +#ifdef CONFIG_OMAP3_COPY_CLOCK_SRAM +/* A.K.A go_to_speed */ +static void (*f_lock_pll) (u32, u32, u32, u32); +#endif +/* Helper functions */ +static u32 get_osc_clk_speed(void); +static void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel); +static void per_clocks_enable(void); + +/** + * @brief Determine reference oscillator speed + * + * This is based on known 32kHz clock and gptimer. + * + * @return clock speed S38_4M, S26M S24M S19_2M S13M S12M + */ +static u32 get_osc_clk_speed(void) +{ + u32 start, cstart, cend, cdiff, val; + + val = __raw_readl(PRM_REG(CLKSRC_CTRL)); + /* If SYS_CLK is being divided by 2, remove for now */ + val = (val & (~(0x1 << 7))) | (0x1 << 6); + __raw_writel(val, PRM_REG(CLKSRC_CTRL)); + + /* enable timer2 */ + val = __raw_readl(CM_REG(CLKSEL_WKUP)) | (0x1 << 0); + __raw_writel(val, CM_REG(CLKSEL_WKUP)); /* select sys_clk for GPT1 */ + + /* Enable I and F Clocks for GPT1 */ + val = __raw_readl(CM_REG(ICLKEN_WKUP)) | (0x1 << 0) | (0x1 << 2); + __raw_writel(val, CM_REG(ICLKEN_WKUP)); + val = __raw_readl(CM_REG(FCLKEN_WKUP)) | (0x1 << 0); + __raw_writel(val, CM_REG(FCLKEN_WKUP)); + /* start counting at 0 */ + __raw_writel(0, OMAP_GPTIMER1_BASE + TLDR); + /* enable clock */ + __raw_writel(GPT_EN, OMAP_GPTIMER1_BASE + TCLR); + /* enable 32kHz source - enabled out of reset */ + /* determine sys_clk via gauging */ + + start = 20 + __raw_readl(S32K_CR); /* start time in 20 cycles */ + while (__raw_readl(S32K_CR) < start) ; /* dead loop till start time */ + /* get start sys_clk count */ + cstart = __raw_readl(OMAP_GPTIMER1_BASE + TCRR); + while (__raw_readl(S32K_CR) < (start + 20)) ; /* wait for 40 cycles */ + /* get end sys_clk count */ + cend = __raw_readl(OMAP_GPTIMER1_BASE + TCRR); + cdiff = cend - cstart; /* get elapsed ticks */ + + /* based on number of ticks assign speed */ + if (cdiff > 19000) + return S38_4M; + else if (cdiff > 15200) + return S26M; + else if (cdiff > 13000) + return S24M; + else if (cdiff > 9000) + return S19_2M; + else if (cdiff > 7600) + return S13M; + else + return S12M; +} + +/** + * @brief Returns the sys_clkin_sel field value + * + * This is based on input oscillator clock frequency. + * + * @param[in] osc_clk - Oscilaltor Clock to OMAP + * @param[out] sys_clkin_sel - returns the sys_clk selection + * + * @return void + */ +static void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel) +{ + if (osc_clk == S38_4M) + *sys_clkin_sel = 4; + else if (osc_clk == S26M) + *sys_clkin_sel = 3; + else if (osc_clk == S19_2M) + *sys_clkin_sel = 2; + else if (osc_clk == S13M) + *sys_clkin_sel = 1; + else if (osc_clk == S12M) + *sys_clkin_sel = 0; +} + +/** + * @brief Inits clocks for PRCM + * + * This is called from SRAM, or Flash (using temp SRAM stack). + * if CONFIG_OMAP3_COPY_CLOCK_SRAM is defined, @ref go_to_speed + * + * @return void + */ +void prcm_init(void) +{ + int xip_safe; + u32 osc_clk = 0, sys_clkin_sel = 0; + u32 clk_index, sil_index; + struct dpll_param *dpll_param_p; +#ifdef CONFIG_OMAP3_COPY_CLOCK_SRAM + int p0, p1, p2, p3; + f_lock_pll = (void *)(OMAP_SRAM_INTVECT + OMAP_SRAM_INTVECT_COPYSIZE); +#endif + + xip_safe = running_in_sram(); + + /* Gauge the input clock speed and find out the sys_clkin_sel + * value corresponding to the input clock. + */ + osc_clk = get_osc_clk_speed(); + get_sys_clkin_sel(osc_clk, &sys_clkin_sel); + /* set input crystal speed */ + sr32(PRM_REG(CLKSEL), 0, 3, sys_clkin_sel); + + /* If the input clock is greater than 19.2M always divide/2 */ + if (sys_clkin_sel > 2) { + /* input clock divider */ + sr32(PRM_REG(CLKSRC_CTRL), 6, 2, 2); + clk_index = sys_clkin_sel / 2; + } else { + /* input clock divider */ + sr32(PRM_REG(CLKSRC_CTRL), 6, 2, 1); + clk_index = sys_clkin_sel; + } + + /* The DPLL tables are defined according to sysclk value and + * silicon revision. The clk_index value will be used to get + * the values for that input sysclk from the DPLL param table + * and sil_index will get the values for that SysClk for the + * appropriate silicon rev. + */ + if (get_cpu_rev() >= CPU_ES2) + sil_index = 1; + /* Unlock MPU DPLL (slows things down, and needed later) */ + sr32(CM_REG(CLKEN_PLL_MPU), 0, 3, PLL_LOW_POWER_BYPASS); + wait_on_value((0x1 << 0), 0, CM_REG(IDLEST_PLL_MPU), LDELAY); + + /* Getting the base address of Core DPLL param table */ + dpll_param_p = (struct dpll_param *)get_core_dpll_param(); + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + MAX_SIL_INDEX * clk_index + sil_index; + if (xip_safe) { + /* CORE DPLL */ + /* sr32(CM_REG(CLKSEL2_EMU)) set override to work when asleep */ + sr32(CM_REG(CLKEN_PLL), 0, 3, PLL_FAST_RELOCK_BYPASS); + wait_on_value((0x1 << 0), 0, CM_REG(IDLEST_CKGEN), LDELAY); + /* For 3430 ES1.0 Errata 1.50, default value directly doesnt + work. write another value and then default value. */ + sr32(CM_REG(CLKSEL1_EMU), 16, 5, CORE_M3X2 + 1); + sr32(CM_REG(CLKSEL1_EMU), 16, 5, CORE_M3X2); + sr32(CM_REG(CLKSEL1_PLL), 27, 2, dpll_param_p->m2); + sr32(CM_REG(CLKSEL1_PLL), 16, 11, dpll_param_p->m); + sr32(CM_REG(CLKSEL1_PLL), 8, 7, dpll_param_p->n); + sr32(CM_REG(CLKSEL1_PLL), 6, 1, 0); + sr32(CM_REG(CLKSEL_CORE), 8, 4, CORE_SSI_DIV); + sr32(CM_REG(CLKSEL_CORE), 4, 2, CORE_FUSB_DIV); + sr32(CM_REG(CLKSEL_CORE), 2, 2, CORE_L4_DIV); + sr32(CM_REG(CLKSEL_CORE), 0, 2, CORE_L3_DIV); + sr32(CM_REG(CLKSEL_GFX), 0, 3, GFX_DIV); + sr32(CM_REG(CLKSEL_WKUP), 1, 2, WKUP_RSM); + sr32(CM_REG(CLKEN_PLL), 4, 4, dpll_param_p->fsel); + sr32(CM_REG(CLKEN_PLL), 0, 3, PLL_LOCK); + wait_on_value((0x1 << 0), 1, CM_REG(IDLEST_CKGEN), LDELAY); + } else if (running_in_flash()) { +#ifdef CONFIG_OMAP3_COPY_CLOCK_SRAM + /* if running from flash, + * jump to small relocated code area in SRAM. + */ + p0 = __raw_readl(CM_REG(CLKEN_PLL)); + sr32((u32) &p0, 0, 3, PLL_FAST_RELOCK_BYPASS); + sr32((u32) &p0, 4, 4, dpll_param_p->fsel); + + p1 = __raw_readl(CM_REG(CLKSEL1_PLL)); + sr32((u32) &p1, 27, 2, dpll_param_p->m2); + sr32((u32) &p1, 16, 11, dpll_param_p->m); + sr32((u32) &p1, 8, 7, dpll_param_p->n); + sr32((u32) &p1, 6, 1, 0); /* set source for 96M */ + p2 = __raw_readl(CM_REG(CLKSEL_CORE)); + sr32((u32) &p2, 8, 4, CORE_SSI_DIV); + sr32((u32) &p2, 4, 2, CORE_FUSB_DIV); + sr32((u32) &p2, 2, 2, CORE_L4_DIV); + sr32((u32) &p2, 0, 2, CORE_L3_DIV); + + p3 = CM_REG(IDLEST_CKGEN); + + (*f_lock_pll) (p0, p1, p2, p3); +#else + /***Oopps.. Wrong .config!! *****/ + hang(); +#endif + } + + /* PER DPLL */ + sr32(CM_REG(CLKEN_PLL), 16, 3, PLL_STOP); + wait_on_value((0x1 << 1), 0, CM_REG(IDLEST_CKGEN), LDELAY); + + /* Getting the base address to PER DPLL param table */ + /* Set N */ + dpll_param_p = (struct dpll_param *)get_per_dpll_param(); + /* Moving it to the right sysclk base */ + dpll_param_p = dpll_param_p + clk_index; + /* Errata 1.50 Workaround for 3430 ES1.0 only */ + /* If using default divisors, write default divisor + 1 + and then the actual divisor value */ + /* Need to change it to silicon and revisino check */ + if (1) { + sr32(CM_REG(CLKSEL1_EMU), 24, 5, PER_M6X2 + 1); /* set M6 */ + sr32(CM_REG(CLKSEL1_EMU), 24, 5, PER_M6X2); /* set M6 */ + sr32(CM_REG(CLKSEL_CAM), 0, 5, PER_M5X2 + 1); /* set M5 */ + sr32(CM_REG(CLKSEL_CAM), 0, 5, PER_M5X2); /* set M5 */ + sr32(CM_REG(CLKSEL_DSS), 0, 5, PER_M4X2 + 1); /* set M4 */ + sr32(CM_REG(CLKSEL_DSS), 0, 5, PER_M4X2); /* set M4 */ + sr32(CM_REG(CLKSEL_DSS), 8, 5, PER_M3X2 + 1); /* set M3 */ + sr32(CM_REG(CLKSEL_DSS), 8, 5, PER_M3X2); /* set M3 */ + /* set M2 */ + sr32(CM_REG(CLKSEL3_PLL), 0, 5, dpll_param_p->m2 + 1); + sr32(CM_REG(CLKSEL3_PLL), 0, 5, dpll_param_p->m2); + } else { + sr32(CM_REG(CLKSEL1_EMU), 24, 5, PER_M6X2); /* set M6 */ + sr32(CM_REG(CLKSEL_CAM), 0, 5, PER_M5X2); /* set M5 */ + sr32(CM_REG(CLKSEL_DSS), 0, 5, PER_M4X2); /* set M4 */ + sr32(CM_REG(CLKSEL_DSS), 8, 5, PER_M3X2); /* set M3 */ + sr32(CM_REG(CLKSEL3_PLL), 0, 5, dpll_param_p->m2); + } + sr32(CM_REG(CLKSEL2_PLL), 8, 11, dpll_param_p->m); /* set m */ + sr32(CM_REG(CLKSEL2_PLL), 0, 7, dpll_param_p->n); /* set n */ + sr32(CM_REG(CLKEN_PLL), 20, 4, dpll_param_p->fsel); /* FREQSEL */ + sr32(CM_REG(CLKEN_PLL), 16, 3, PLL_LOCK); /* lock mode */ + wait_on_value((0x1 << 1), 2, CM_REG(IDLEST_CKGEN), LDELAY); + + /* Getting the base address to MPU DPLL param table */ + dpll_param_p = (struct dpll_param *)get_mpu_dpll_param(); + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + MAX_SIL_INDEX * clk_index + sil_index; + /* MPU DPLL (unlocked already) */ + sr32(CM_REG(CLKSEL2_PLL_MPU), 0, 5, dpll_param_p->m2); /* Set M2 */ + sr32(CM_REG(CLKSEL1_PLL_MPU), 8, 11, dpll_param_p->m); /* Set M */ + sr32(CM_REG(CLKSEL1_PLL_MPU), 0, 7, dpll_param_p->n); /* Set N */ + sr32(CM_REG(CLKEN_PLL_MPU), 4, 4, dpll_param_p->fsel); /* FREQSEL */ + sr32(CM_REG(CLKEN_PLL_MPU), 0, 3, PLL_LOCK); /* lock mode */ + wait_on_value((0x1 << 0), 1, CM_REG(IDLEST_PLL_MPU), LDELAY); + + /* Getting the base address to IVA DPLL param table */ + dpll_param_p = (struct dpll_param *)get_iva_dpll_param(); + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + MAX_SIL_INDEX * clk_index + sil_index; + /* IVA DPLL (set to 12*20=240MHz) */ + sr32(CM_REG(CLKEN_PLL_IVA2), 0, 3, PLL_STOP); + wait_on_value((0x1 << 0), 0, CM_REG(IDLEST_PLL_IVA2), LDELAY); + sr32(CM_REG(CLKSEL2_PLL_IVA2), 0, 5, dpll_param_p->m2); /* set M2 */ + sr32(CM_REG(CLKSEL1_PLL_IVA2), 8, 11, dpll_param_p->m); /* set M */ + sr32(CM_REG(CLKSEL1_PLL_IVA2), 0, 7, dpll_param_p->n); /* set N */ + sr32(CM_REG(CLKEN_PLL_IVA2), 4, 4, dpll_param_p->fsel); /* FREQSEL */ + sr32(CM_REG(CLKEN_PLL_IVA2), 0, 3, PLL_LOCK); /* lock mode */ + wait_on_value((0x1 << 0), 1, CM_REG(IDLEST_PLL_IVA2), LDELAY); + + /* Set up GPTimers to sys_clk source only */ + sr32(CM_REG(CLKSEL_PER), 0, 8, 0xff); + sr32(CM_REG(CLKSEL_WKUP), 0, 1, 1); + + sdelay(5000); + + /* Enable Peripheral Clocks */ + per_clocks_enable(); +} + +/** + * @brief Enable the clks & power for perifs + * + * GPT2 Sysclk, ICLK,FCLK, 32k Sync is enabled by default + * Uses CONFIG_OMAP_CLOCK_UART to enable UART clocks + * Uses CONFIG_OMAP_CLOCK_I2C to enable I2C clocks + * Uses CONFIG_OMAP_CLOCK_ALL to enable All Clocks! + * - Not a wise idea in most cases + * + * @return void + */ +static void per_clocks_enable(void) +{ + /* Enable GP2 timer. */ + sr32(CM_REG(CLKSEL_PER), 0, 1, 0x1); /* GPT2 = sys clk */ + sr32(CM_REG(ICLKEN_PER), 3, 1, 0x1); /* ICKen GPT2 */ + sr32(CM_REG(FCLKEN_PER), 3, 1, 0x1); /* FCKen GPT2 */ + /* Enable the ICLK for 32K Sync Timer as its used in udelay */ + sr32(CM_REG(ICLKEN_WKUP), 2, 1, 0x1); + +#ifdef CONFIG_OMAP_CLOCK_UART + /* Enable UART1 clocks */ + sr32(CM_REG(FCLKEN1_CORE), 13, 1, 0x1); + sr32(CM_REG(ICLKEN1_CORE), 13, 1, 0x1); +#endif +#ifdef CONFIG_OMAP_CLOCK_I2C + /* Turn on all 3 I2C clocks */ + sr32(CM_REG(FCLKEN1_CORE), 15, 3, 0x7); + sr32(CM_REG(ICLKEN1_CORE), 15, 3, 0x7); /* I2C1,2,3 = on */ +#endif + +#ifdef CONFIG_OMAP_CLOCK_ALL +#define FCK_IVA2_ON 0x00000001 +#define FCK_CORE1_ON 0x03fffe29 +#define ICK_CORE1_ON 0x3ffffffb +#define ICK_CORE2_ON 0x0000001f +#define FCK_WKUP_ON 0x000000e9 +#define ICK_WKUP_ON 0x0000003f +#define FCK_DSS_ON 0x00000005 /* tv+dss1 (not dss2) */ +#define ICK_DSS_ON 0x00000001 +#define FCK_CAM_ON 0x00000001 +#define ICK_CAM_ON 0x00000001 +#define FCK_PER_ON 0x0003ffff +#define ICK_PER_ON 0x0003ffff + sr32(CM_REG(FCLKEN_IVA2), 0, 32, FCK_IVA2_ON); + sr32(CM_REG(FCLKEN1_CORE), 0, 32, FCK_CORE1_ON); + sr32(CM_REG(ICLKEN1_CORE), 0, 32, ICK_CORE1_ON); + sr32(CM_REG(ICLKEN2_CORE), 0, 32, ICK_CORE2_ON); + sr32(CM_REG(FCLKEN_WKUP), 0, 32, FCK_WKUP_ON); + sr32(CM_REG(ICLKEN_WKUP), 0, 32, ICK_WKUP_ON); + sr32(CM_REG(FCLKEN_DSS), 0, 32, FCK_DSS_ON); + sr32(CM_REG(ICLKEN_DSS), 0, 32, ICK_DSS_ON); + sr32(CM_REG(FCLKEN_CAM), 0, 32, FCK_CAM_ON); + sr32(CM_REG(ICLKEN_CAM), 0, 32, ICK_CAM_ON); + sr32(CM_REG(FCLKEN_PER), 0, 32, FCK_PER_ON); + sr32(CM_REG(ICLKEN_PER), 0, 32, ICK_PER_ON); +#endif + /* Settle down my friend */ + sdelay(1000); +} Index: u-boot.v2/arch/arm/mach-omap/omap3_clock_core.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot.v2/arch/arm/mach-omap/omap3_clock_core.S 2008-06-03 22:49:11.000000000 -0500 @@ -0,0 +1,312 @@ +/** + * @file + * @brief Provides PRCM divisors and SRAM execution code. + * + * FileName: arch/arm/mach-omap/omap3_clock_core.S + * + * This provides two things: + * @li @ref omap3_clock.c cannot have switch or global variables. + * This file provides the constant data for the file to use. + * + * @li @ref prcm_init cannot execute certain critical clock + * configurations while running in SDRAM/Flash. This provides + * relocation and execution capability for the same. + * + * Orignally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz + */ +/* + * (C) Copyright 2006-2008 + * Texas Instruments, <www.ti.com> + * Richard Woodruff r-woodruff2@ti.com + * Nishanth Menon x0nishan@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <asm/arch/silicon.h> +#include <asm/arch/clocks.h> +#include <asm/arch/gpmc.h> + +#ifdef CONFIG_OMAP3_COPY_CLOCK_SRAM +/** + * @fn void cpy_clk_code(u32 R1) + * + * @brief cpy_clk_code: relocates clock code into SRAM where its safer to + * execute + * + * @param[in] R1 = SRAM destination address. + * + * @return void + */ +.global cpy_clk_code + cpy_clk_code: + /* Copy DPLL code into SRAM */ + adr r0, go_to_speed /* get addr of clock setting code */ + mov r2, #384 /* r2 size to copy (div by 32 bytes) */ + mov r1, r1 /* r1 <- dest address (passed in) */ + add r2, r2, r0 /* r2 <- source end address */ +next2: + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end address [r2] */ + bne next2 + mov pc, lr /* back to caller */ + +/** + * @fn void go_to_speed(u32 R0, u32 R1, u32 R3) + * + * @brief go_to_speed: Function which configures the clocks + * Moves to bypass, -Commits clock dividers, -puts dpll at speed + * -executed from SRAM. + * @warning Note: If core unlocks/relocks and SDRAM is running fast already + * it gets confused. A reset of the controller gets it back. Taking + * away its L3 when its not in self refresh seems bad for it. + * Normally, this code runs from flash before SDR is init so that + * should be ok. + * + * @param[in] R1 = SRAM destination address. + * @param[in] R0 = CM_CLKEN_PLL-bypass value + * @param[in] R1 = CM_CLKSEL1_PLL-m, n, and divider values + * @param[in] R2 = CM_CLKSEL_CORE-divider values + * @param[in] R3 = CM_IDLEST_CKGEN - addr dpll lock wait + * + * @return void + */ +.global go_to_speed + go_to_speed: + stmfd sp!, {r4-r6} + + /* move into fast relock bypass */ + ldr r4, pll_ctl_add + str r0, [r4] +wait1: + ldr r5, [r3] /* get status */ + and r5, r5, #0x1 /* isolate core status */ + cmp r5, #0x1 /* still locked? */ + beq wait1 /* if lock, loop */ + + /* set new dpll dividers _after_ in bypass */ + ldr r5, pll_div_add1 + str r1, [r5] /* set m, n, m2 */ + ldr r5, pll_div_add2 + str r2, [r5] /* set l3/l4/.. dividers*/ + ldr r5, pll_div_add3 /* wkup */ + ldr r2, pll_div_val3 /* rsm val */ + str r2, [r5] + ldr r5, pll_div_add4 /* gfx */ + ldr r2, pll_div_val4 + str r2, [r5] + ldr r5, pll_div_add5 /* emu */ + ldr r2, pll_div_val5 + str r2, [r5] + +#if 0 + /* FIXME: now prepare GPMC (flash) for new dpll speed + * For NOR/NAND/OneNAND boot ->make this as Kconfig? + */ + /* flash needs to be stable when we jump back to it */ + ldr r6, flash_cfg_offset + ldr r5, flash_cfg_addr /* CFG1 */ + ldr r2, flash_cfg1_val + str r2, [r5] + add r5, r5, r6 /* CFG2 */ + ldr r2, flash_cfg2_val + str r2, [r5] + add r5, r5, r6 /* CFG3 */ + ldr r2, flash_cfg3_val + str r2, [r5] + add r5, r5, r6 /* CFG4 */ + ldr r2, flash_cfg4_val + str r2, [r5] + add r5, r5, r6 /* CFG5 */ + ldr r2, flash_cfg5_val + str r2, [r5] + add r5, r5, r6 /* CFG6 */ + ldr r2, flash_cfg6_val + str r2, [r5] +#endif /* Debug */ + + /* lock DPLL3 and wait a bit */ + orr r0, r0, #0x7 /* set up for lock mode */ + str r0, [r4] /* lock */ + nop /* ARM slow at this point working at sys_clk */ + nop + nop + nop +wait2: + ldr r5, [r3] /* get status */ + and r5, r5, #0x1 /* isolate core status */ + cmp r5, #0x1 /* still locked? */ + bne wait2 /* if lock, loop */ + nop + nop + nop + nop + ldmfd sp!, {r4-r6} + mov pc, lr /* back to caller, locked */ + +_go_to_speed: .word go_to_speed + +/* these constants need to be close for PIC code */ +/* FIXME: The Nor has to be in the Flash Base CS0 for this condition to happen*/ +#if 0 +flash_cfg_addr: + .word GPMC_REG(CONFIG1_0) +flash_cfg_offset: + .word GPMC_REG(CONFIG2_0) - GPMC_REG(CONFIG1_0) +flash_cfg1_val: + .word CONFIG_VALUE_GPMC_CONFIG1 +flash_cfg2_val: + .word CONFIG_VALUE_GPMC_CONFIG2 +flash_cfg3_val: + .word CONFIG_VALUE_GPMC_CONFIG3 +flash_cfg4_val: + .word CONFIG_VALUE_GPMC_CONFIG4 +flash_cfg5_val: + .word CONFIG_VALUE_GPMC_CONFIG5 +flash_cfg6_val: + .word CONFIG_VALUE_GPMC_CONFIG6 +#endif +pll_ctl_add: + .word CM_CLKEN_PLL +pll_div_add1: + .word CM_CLKSEL1_PLL +pll_div_add2: + .word CM_CLKSEL_CORE +pll_div_add3: + .word CM_CLKSEL_WKUP +pll_div_val3: + .word (WKUP_RSM << 1) +pll_div_add4: + .word CM_CLKSEL_GFX +pll_div_val4: + .word (GFX_DIV << 0) +pll_div_add5: + .word CM_CLKSEL1_EMU +pll_div_val5: + .word CLSEL1_EMU_VAL + +#endif /* OMAP3_CLOCK_COPY_SRAM */ + + /* the literal pools origin */ + .ltorg + +/* DPLL(1-4) PARAM TABLES */ +/* Each of the tables has M, N, FREQSEL, M2 values defined for nominal + * OPP (1.2V). The fields are defined according to dpll_param + * struct(omap3_clock.c). MAX index is as per omap3_clock.h + */ + +mpu_dpll_param: +/* 12MHz */ +/* ES2 */ +.word 0x0FA,0x05,0x07,0x01 + +/* 13MHz */ +/* ES2 */ +.word 0x1F4,0x0C,0x03,0x01 + +/* 19.2MHz */ +/* ES2 */ +.word 0x271,0x17,0x03,0x01 + +/* 26MHz */ +/* ES2 */ +.word 0x0FA,0x0C,0x07,0x01 + +/* 38.4MHz */ +/* ES2 */ +.word 0x271,0x2F,0x03,0x01 + +.globl get_mpu_dpll_param +get_mpu_dpll_param: + adr r0, mpu_dpll_param + mov pc, lr + +iva_dpll_param: +/* 12MHz */ +/* ES2 */ +.word 0x0B4,0x05,0x07,0x01 + +/* 13MHz */ +/* ES2 */ +.word 0x168,0x0C,0x03,0x01 + +/* 19.2MHz */ +/* ES2 */ +.word 0x0E1,0x0B,0x06,0x01 + +/* 26MHz */ +/* ES2 */ +.word 0x0B4,0x0C,0x07,0x01 + +/* 38.4MHz */ +/* ES2 */ +.word 0x0E1,0x17,0x06,0x01 + +.globl get_iva_dpll_param +get_iva_dpll_param: + adr r0, iva_dpll_param + mov pc, lr + +core_dpll_param: +/* 12MHz */ +/* ES2 */ +.word 0x0A6,0x05,0x07,0x01 + +/* 13MHz */ +/* ES2 */ +.word 0x14C,0x0C,0x03,0x01 + +/* 19.2MHz */ +/* ES2 */ +.word 0x19F,0x17,0x03,0x01 + +/* 26MHz */ +/* ES2 */ +.word 0x0A6,0x0C,0x07,0x01 + +/* 38.4MHz */ +/* ES2 */ +.word 0x19F,0x2F,0x03,0x01 + +.globl get_core_dpll_param +get_core_dpll_param: + adr r0, core_dpll_param + mov pc, lr + +/* PER DPLL values are same for both ES1 and ES2 */ +per_dpll_param: +/* 12MHz */ +.word 0xD8,0x05,0x07,0x09 + +/* 13MHz */ +.word 0x1B0,0x0C,0x03,0x09 + +/* 19.2MHz */ +.word 0xE1,0x09,0x07,0x09 + +/* 26MHz */ +.word 0xD8,0x0C,0x07,0x09 + +/* 38.4MHz */ +.word 0xE1,0x13,0x07,0x09 + +.globl get_per_dpll_param +get_per_dpll_param: + adr r0, per_dpll_param + mov pc, lr Index: u-boot.v2/arch/arm/mach-omap/s32k_clksource.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot.v2/arch/arm/mach-omap/s32k_clksource.c 2008-06-03 22:49:11.000000000 -0500 @@ -0,0 +1,80 @@ +/** + * @file + * @brief Provide @ref clocksource functionality for OMAP + * + * FileName: arch/arm/mach-omap/s32k_clksource.c + * + * @ref clocksource provides a neat architecture. all we do is + * To loop in with Sync 32Khz clock ticking away at 32768hz on OMAP. + * Sync 32Khz clock is an always ON clock. + * + */ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * Nishanth Menon x0nishan@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <clock.h> +#include <init.h> +#include <asm/io.h> +#include <asm/arch/silicon.h> +#include <asm/arch/clocks.h> +#include <asm/arch/timers.h> +#include <asm/arch/sys_info.h> +#include <asm/arch/syslib.h> + +/** + * @brief Provide a simple clock read + * + * Nothing is simpler.. read direct from clock and provide it + * to the caller. + * + * @return S32K clock counter + */ +static uint64_t s32k_clocksource_read(void) +{ + return __raw_readl(S32K_CR); +} + +/* A bit obvious isn't it? */ +static struct clocksource s32k_cs = { + .read = s32k_clocksource_read, + .mask = 0xffffffff, + .shift = 10, +}; + +/** + * @brief Initialize the Clock + * + * There is nothing to do on OMAP as SYNC32K clock is + * always on, and we do a simple data structure initialization. + * 32K clock gives 32768 ticks a seconds + * + * @return result of @ref init_clock + */ +static int s32k_clocksource_init(void) +{ + s32k_cs.mult = clocksource_hz2mult(S32K_FREQUENCY, s32k_cs.shift); + + return init_clock(&s32k_cs); +} + +/* Run me at boot time */ +core_initcall(s32k_clocksource_init); Index: u-boot.v2/include/asm-arm/arch-omap/omap3-clock.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot.v2/include/asm-arm/arch-omap/omap3-clock.h 2008-06-03 22:49:11.000000000 -0500 @@ -0,0 +1,124 @@ +/** + * @file + * @brief Contains the PRM and CM definitions + * + * FileName: include/asm-arm/arch-omap/omap3-clock.h + * + * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz + * + */ +/* + * (C) Copyright 2006-2008 + * Texas Instruments, <www.ti.com> + * Richard Woodruff r-woodruff2@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef _OMAP343X_CLOCKS_H_ +#define _OMAP343X_CLOCKS_H_ + +/** CM Clock Regs Wrapper */ +#define CM_REG(REGNAME) (OMAP_CM_BASE + CM_##REGNAME) + +#define CM_FCLKEN_IVA2 0X0000 +#define CM_CLKEN_PLL_IVA2 0X0004 +#define CM_IDLEST_PLL_IVA2 0X0024 +#define CM_CLKSEL1_PLL_IVA2 0X0040 +#define CM_CLKSEL2_PLL_IVA2 0X0044 +#define CM_CLKEN_PLL_MPU 0X0904 +#define CM_IDLEST_PLL_MPU 0X0924 +#define CM_CLKSEL1_PLL_MPU 0X0940 +#define CM_CLKSEL2_PLL_MPU 0X0944 +#define CM_FCLKEN1_CORE 0X0A00 +#define CM_ICLKEN1_CORE 0X0A10 +#define CM_ICLKEN2_CORE 0X0A14 +#define CM_CLKSEL_CORE 0X0A40 +#define CM_FCLKEN_GFX 0X0B00 +#define CM_ICLKEN_GFX 0X0B10 +#define CM_CLKSEL_GFX 0X0B40 +#define CM_FCLKEN_WKUP 0X0C00 +#define CM_ICLKEN_WKUP 0X0C10 +#define CM_CLKSEL_WKUP 0X0C40 +#define CM_IDLEST_WKUP 0X0C20 +#define CM_CLKEN_PLL 0X0D00 +#define CM_IDLEST_CKGEN 0X0D20 +#define CM_CLKSEL1_PLL 0X0D40 +#define CM_CLKSEL2_PLL 0X0D44 +#define CM_CLKSEL3_PLL 0X0D48 +#define CM_FCLKEN_DSS 0X0E00 +#define CM_ICLKEN_DSS 0X0E10 +#define CM_CLKSEL_DSS 0X0E40 +#define CM_FCLKEN_CAM 0X0F00 +#define CM_ICLKEN_CAM 0X0F10 +#define CM_CLKSEL_CAM 0X0f40 +#define CM_FCLKEN_PER 0X1000 +#define CM_ICLKEN_PER 0X1010 +#define CM_CLKSEL_PER 0X1040 +#define CM_CLKSEL1_EMU 0X1140 + +/** PRM Clock Regs */ +#define PRM_REG(REGNAME) (OMAP_PRM_BASE + PRM_##REGNAME) +#define PRM_CLKSEL 0x0D40 +#define PRM_RSTCTRL 0x1250 +#define PRM_CLKSRC_CTRL 0x1270 + +/*************** Clock Values */ +#define PLL_STOP 1 /* PER & IVA */ +#define PLL_LOW_POWER_BYPASS 5 /* MPU, IVA & CORE */ +#define PLL_FAST_RELOCK_BYPASS 6 /* CORE */ +#define PLL_LOCK 7 /* MPU, IVA, CORE & PER */ + +/* The following configurations are OPP and SysClk value independant + * and hence are defined here. + */ + +/* CORE DPLL */ +#define CORE_M3X2 2 /* 332MHz : CM_CLKSEL1_EMU */ +#define CORE_SSI_DIV 3 /* 221MHz : CM_CLKSEL_CORE */ +#define CORE_FUSB_DIV 2 /* 41.5MHz: */ +#define CORE_L4_DIV 2 /* 83MHz : L4 */ +#define CORE_L3_DIV 2 /* 166MHz : L3 {DDR} */ +#define GFX_DIV 2 /* 83MHz : CM_CLKSEL_GFX */ +#define WKUP_RSM 2 /* 41.5MHz: CM_CLKSEL_WKUP */ + +/* PER DPLL */ +#define PER_M6X2 3 /* 288MHz: CM_CLKSEL1_EMU */ +#define PER_M5X2 4 /* 216MHz: CM_CLKSEL_CAM */ +#define PER_M4X2 9 /* 96MHz : CM_CLKSEL_DSS-dss1 */ +#define PER_M3X2 16 /* 54MHz : CM_CLKSEL_DSS-tv */ + +#define CLSEL1_EMU_VAL ((CORE_M3X2 << 16) | (PER_M6X2 << 24) | (0x0a50)) + +#define MAX_SIL_INDEX 1 + +#ifndef __ASSEMBLY__ +void prcm_init(void); +/* Used to index into DPLL parameter tables -See TRM for further details */ +struct dpll_param { + unsigned int m; + unsigned int n; + unsigned int fsel; + unsigned int m2; +}; +/* External functions see omap3_clock_core.S */ +extern struct dpll_param *get_mpu_dpll_param(void); +extern struct dpll_param *get_iva_dpll_param(void); +extern struct dpll_param *get_core_dpll_param(void); +extern struct dpll_param *get_per_dpll_param(void); + +#endif /* __ASSEMBLY__ */ + +#endif /* endif _OMAP343X_CLOCKS_H_ */ Index: u-boot.v2/include/asm-arm/arch-omap/clocks.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot.v2/include/asm-arm/arch-omap/clocks.h 2008-06-03 22:49:11.000000000 -0500 @@ -0,0 +1,48 @@ +/** + * @file + * @brief Generic Clock wrapper header. + * + * FileName: include/asm-arm/arch-omap/clocks.h + * + * This includes each of the architecture Clock definitions under it. + * + * Originally from http://linux.omap.com/pub/bootloader/3430sdp/u-boot-v1.tar.gz + */ +/* + * (C) Copyright 2006-2008 + * Texas Instruments, <www.ti.com> + * Richard Woodruff r-woodruff2@ti.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef __OMAP_CLOCKS_H_ +#define __OMAP_CLOCKS_H_ + +#define LDELAY 12000000 + +/* Standard defines for Various clocks */ +#define S12M 12000000 +#define S13M 13000000 +#define S19_2M 19200000 +#define S24M 24000000 +#define S26M 26000000 +#define S38_4M 38400000 + +#ifdef CONFIG_ARCH_OMAP3 +#include <asm/arch/omap3-clock.h> +#endif + +#endif /* __OMAP_CLOCKS_H_ */
participants (1)
-
Menon, Nishanth