diff --git a/arch/arm/cpu/armv7/omap3/clock.c b/arch/arm/cpu/armv7/omap3/clock.c index 6330c9e5da..2238c52e3b 100644 --- a/arch/arm/cpu/armv7/omap3/clock.c +++ b/arch/arm/cpu/armv7/omap3/clock.c @@ -50,12 +50,7 @@ u32 get_osc_clk_speed(void) if (val & SYSCLKDIV_2) cdiv = 2; - else if (val & SYSCLKDIV_1) - cdiv = 1; else - /* - * Should never reach here! (Assume divider as 1) - */ cdiv = 1; /* enable timer2 */ @@ -89,11 +84,7 @@ u32 get_osc_clk_speed(void) while (readl(&s32k_base->s32k_cr) < (start + 20)) ; cend = readl(&gpt1_base->tcrr); /* get end sys_clk count */ cdiff = cend - cstart; /* get elapsed ticks */ - - if (cdiv == 2) - { - cdiff *= 2; - } + cdiff *= cdiv; /* based on number of ticks assign speed */ if (cdiff > 19000) @@ -135,24 +126,410 @@ void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel) } } +/* + * OMAP34XX/35XX specific functions + */ + +static void dpll3_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_core_dpll_param(); + void (*f_lock_pll) (u32, u32, u32, u32); + int xip_safe, p0, p1, p2, p3; + + xip_safe = is_running_in_sram(); + + /* Moving to the right sysclk and ES rev base */ + ptr = ptr + (3 * clk_index) + sil_index; + + if (xip_safe) { + /* + * CORE DPLL + * sr32(CM_CLKSEL2_EMU) set override to work when asleep + */ + sr32(&prcm_base->clken_pll, 0, 3, PLL_FAST_RELOCK_BYPASS); + wait_on_value(ST_CORE_CLK, 0, &prcm_base->idlest_ckgen, + LDELAY); + + /* + * For OMAP3 ES1.0 Errata 1.50, default value directly doesn't + * work. write another value and then default value. + */ + + /* CM_CLKSEL1_EMU[DIV_DPLL3] */ + sr32(&prcm_base->clksel1_emu, 16, 5, (CORE_M3X2 + 1)) ; + sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2); + + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + sr32(&prcm_base->clksel1_pll, 27, 5, ptr->m2); + + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + sr32(&prcm_base->clksel1_pll, 16, 11, ptr->m); + + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + sr32(&prcm_base->clksel1_pll, 8, 7, ptr->n); + + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + sr32(&prcm_base->clksel1_pll, 6, 1, 0); + + /* SSI */ + sr32(&prcm_base->clksel_core, 8, 4, CORE_SSI_DIV); + /* FSUSB */ + sr32(&prcm_base->clksel_core, 4, 2, CORE_FUSB_DIV); + /* L4 */ + sr32(&prcm_base->clksel_core, 2, 2, CORE_L4_DIV); + /* L3 */ + sr32(&prcm_base->clksel_core, 0, 2, CORE_L3_DIV); + /* GFX */ + sr32(&prcm_base->clksel_gfx, 0, 3, GFX_DIV); + /* RESET MGR */ + sr32(&prcm_base->clksel_wkup, 1, 2, WKUP_RSM); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + sr32(&prcm_base->clken_pll, 4, 4, ptr->fsel); + /* LOCK MODE */ + sr32(&prcm_base->clken_pll, 0, 3, PLL_LOCK); + + wait_on_value(ST_CORE_CLK, 1, &prcm_base->idlest_ckgen, + LDELAY); + } else if (is_running_in_flash()) { + /* + * if running from flash, jump to small relocated code + * area in SRAM. + */ + f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start + + SRAM_VECT_CODE); + + p0 = readl(&prcm_base->clken_pll); + sr32(&p0, 0, 3, PLL_FAST_RELOCK_BYPASS); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + sr32(&p0, 4, 4, ptr->fsel); + + p1 = readl(&prcm_base->clksel1_pll); + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + sr32(&p1, 27, 5, ptr->m2); + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + sr32(&p1, 16, 11, ptr->m); + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + sr32(&p1, 8, 7, ptr->n); + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + sr32(&p1, 6, 1, 0); + + p2 = readl(&prcm_base->clksel_core); + /* SSI */ + sr32(&p2, 8, 4, CORE_SSI_DIV); + /* FSUSB */ + sr32(&p2, 4, 2, CORE_FUSB_DIV); + /* L4 */ + sr32(&p2, 2, 2, CORE_L4_DIV); + /* L3 */ + sr32(&p2, 0, 2, CORE_L3_DIV); + + p3 = (u32)&prcm_base->idlest_ckgen; + + (*f_lock_pll) (p0, p1, p2, p3); + } +} + +static void dpll4_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_per_dpll_param(); + + /* Moving it to the right sysclk base */ + ptr = ptr + clk_index; + + /* EN_PERIPH_DPLL: CM_CLKEN_PLL[16:18] */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_STOP); + wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); + + /* + * Errata 1.50 Workaround for OMAP3 ES1.0 only + * If using default divisors, write default divisor + 1 + * and then the actual divisor value + */ + /* M6 */ + sr32(&prcm_base->clksel1_emu, 24, 5, (PER_M6X2 + 1)); + sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2); + /* M5 */ + sr32(&prcm_base->clksel_cam, 0, 5, (PER_M5X2 + 1)); + sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2); + /* M4 */ + sr32(&prcm_base->clksel_dss, 0, 5, (PER_M4X2 + 1)); + sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2); + /* M3 */ + sr32(&prcm_base->clksel_dss, 8, 5, (PER_M3X2 + 1)); + sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2); + /* M2 (DIV_96M): CM_CLKSEL3_PLL[0:4] */ + sr32(&prcm_base->clksel3_pll, 0, 5, (ptr->m2 + 1)); + sr32(&prcm_base->clksel3_pll, 0, 5, ptr->m2); + /* Workaround end */ + + /* M (PERIPH_DPLL_MULT): CM_CLKSEL2_PLL[8:18] */ + sr32(&prcm_base->clksel2_pll, 8, 11, ptr->m); + + /* N (PERIPH_DPLL_DIV): CM_CLKSEL2_PLL[0:6] */ + sr32(&prcm_base->clksel2_pll, 0, 7, ptr->n); + + /* FREQSEL (PERIPH_DPLL_FREQSEL): CM_CLKEN_PLL[20:23] */ + sr32(&prcm_base->clken_pll, 20, 4, ptr->fsel); + + /* LOCK MODE (EN_PERIPH_DPLL): CM_CLKEN_PLL[16:18] */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_LOCK); + wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY); +} + +static void mpu_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_mpu_dpll_param(); + + /* Moving to the right sysclk and ES rev base */ + ptr = ptr + (3 * clk_index) + sil_index; + + /* MPU DPLL (unlocked already) */ + + /* M2 (MPU_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_MPU[0:4] */ + sr32(&prcm_base->clksel2_pll_mpu, 0, 5, ptr->m2); + + /* M (MPU_DPLL_MULT) : CM_CLKSEL2_PLL_MPU[8:18] */ + sr32(&prcm_base->clksel1_pll_mpu, 8, 11, ptr->m); + + /* N (MPU_DPLL_DIV) : CM_CLKSEL2_PLL_MPU[0:6] */ + sr32(&prcm_base->clksel1_pll_mpu, 0, 7, ptr->n); + + /* FREQSEL (MPU_DPLL_FREQSEL) : CM_CLKEN_PLL_MPU[4:7] */ + sr32(&prcm_base->clken_pll_mpu, 4, 4, ptr->fsel); +} + +static void iva_init_34xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_iva_dpll_param(); + + /* Moving to the right sysclk and ES rev base */ + ptr = ptr + (3 * clk_index) + sil_index; + + /* IVA DPLL */ + /* EN_IVA2_DPLL : CM_CLKEN_PLL_IVA2[0:2] */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_STOP); + wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY); + + /* M2 (IVA2_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_IVA2[0:4] */ + sr32(&prcm_base->clksel2_pll_iva2, 0, 5, ptr->m2); + + /* M (IVA2_DPLL_MULT) : CM_CLKSEL1_PLL_IVA2[8:18] */ + sr32(&prcm_base->clksel1_pll_iva2, 8, 11, ptr->m); + + /* N (IVA2_DPLL_DIV) : CM_CLKSEL1_PLL_IVA2[0:6] */ + sr32(&prcm_base->clksel1_pll_iva2, 0, 7, ptr->n); + + /* FREQSEL (IVA2_DPLL_FREQSEL) : CM_CLKEN_PLL_IVA2[4:7] */ + sr32(&prcm_base->clken_pll_iva2, 4, 4, ptr->fsel); + + /* LOCK MODE (EN_IVA2_DPLL) : CM_CLKEN_PLL_IVA2[0:2] */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_LOCK); + + wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); +} + +/* + * OMAP3630 specific functions + */ + +static void dpll3_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_36x_core_dpll_param(); + void (*f_lock_pll) (u32, u32, u32, u32); + int xip_safe, p0, p1, p2, p3; + + xip_safe = is_running_in_sram(); + + /* Moving it to the right sysclk base */ + ptr += clk_index; + + if (xip_safe) { + /* CORE DPLL */ + + /* Select relock bypass: CM_CLKEN_PLL[0:2] */ + sr32(&prcm_base->clken_pll, 0, 3, PLL_FAST_RELOCK_BYPASS); + wait_on_value(ST_CORE_CLK, 0, &prcm_base->idlest_ckgen, + LDELAY); + + /* CM_CLKSEL1_EMU[DIV_DPLL3] */ + sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2); + + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + sr32(&prcm_base->clksel1_pll, 27, 5, ptr->m2); + + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + sr32(&prcm_base->clksel1_pll, 16, 11, ptr->m); + + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + sr32(&prcm_base->clksel1_pll, 8, 7, ptr->n); + + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + sr32(&prcm_base->clksel1_pll, 6, 1, 0); + + /* SSI */ + sr32(&prcm_base->clksel_core, 8, 4, CORE_SSI_DIV); + /* FSUSB */ + sr32(&prcm_base->clksel_core, 4, 2, CORE_FUSB_DIV); + /* L4 */ + sr32(&prcm_base->clksel_core, 2, 2, CORE_L4_DIV); + /* L3 */ + sr32(&prcm_base->clksel_core, 0, 2, CORE_L3_DIV); + /* GFX */ + sr32(&prcm_base->clksel_gfx, 0, 3, GFX_DIV); + /* RESET MGR */ + sr32(&prcm_base->clksel_wkup, 1, 2, WKUP_RSM); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + sr32(&prcm_base->clken_pll, 4, 4, ptr->fsel); + /* LOCK MODE */ + sr32(&prcm_base->clken_pll, 0, 3, PLL_LOCK); + + wait_on_value(ST_CORE_CLK, 1, &prcm_base->idlest_ckgen, + LDELAY); + } else if (is_running_in_flash()) { + /* + * if running from flash, jump to small relocated code + * area in SRAM. + */ + f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start + + SRAM_VECT_CODE); + + p0 = readl(&prcm_base->clken_pll); + sr32(&p0, 0, 3, PLL_FAST_RELOCK_BYPASS); + /* FREQSEL (CORE_DPLL_FREQSEL): CM_CLKEN_PLL[4:7] */ + sr32(&p0, 4, 4, ptr->fsel); + + p1 = readl(&prcm_base->clksel1_pll); + /* M2 (CORE_DPLL_CLKOUT_DIV): CM_CLKSEL1_PLL[27:31] */ + sr32(&p1, 27, 5, ptr->m2); + /* M (CORE_DPLL_MULT): CM_CLKSEL1_PLL[16:26] */ + sr32(&p1, 16, 11, ptr->m); + /* N (CORE_DPLL_DIV): CM_CLKSEL1_PLL[8:14] */ + sr32(&p1, 8, 7, ptr->n); + /* Source is the CM_96M_FCLK: CM_CLKSEL1_PLL[6] */ + sr32(&p1, 6, 1, 0); + + p2 = readl(&prcm_base->clksel_core); + /* SSI */ + sr32(&p2, 8, 4, CORE_SSI_DIV); + /* FSUSB */ + sr32(&p2, 4, 2, CORE_FUSB_DIV); + /* L4 */ + sr32(&p2, 2, 2, CORE_L4_DIV); + /* L3 */ + sr32(&p2, 0, 2, CORE_L3_DIV); + + p3 = (u32)&prcm_base->idlest_ckgen; + + (*f_lock_pll) (p0, p1, p2, p3); + } +} + +static void dpll4_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + struct dpll_per_36x_param *ptr; + + ptr = (struct dpll_per_36x_param *)get_36x_per_dpll_param(); + + /* Moving it to the right sysclk base */ + ptr += clk_index; + + /* EN_PERIPH_DPLL: CM_CLKEN_PLL[16:18] */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_STOP); + wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); + + /* M6 (DIV_DPLL4): CM_CLKSEL1_EMU[24:29] */ + sr32(&prcm_base->clksel1_emu, 24, 6, ptr->m6); + + /* M5 (CLKSEL_CAM): CM_CLKSEL1_EMU[0:5] */ + sr32(&prcm_base->clksel_cam, 0, 6, ptr->m5); + + /* M4 (CLKSEL_DSS1): CM_CLKSEL_DSS[0:5] */ + sr32(&prcm_base->clksel_dss, 0, 6, ptr->m4); + + /* M3 (CLKSEL_DSS1): CM_CLKSEL_DSS[8:13] */ + sr32(&prcm_base->clksel_dss, 8, 6, ptr->m3); + + /* M2 (DIV_96M): CM_CLKSEL3_PLL[0:4] */ + sr32(&prcm_base->clksel3_pll, 0, 5, ptr->m2); + + /* M (PERIPH_DPLL_MULT): CM_CLKSEL2_PLL[8:19] */ + sr32(&prcm_base->clksel2_pll, 8, 12, ptr->m); + + /* N (PERIPH_DPLL_DIV): CM_CLKSEL2_PLL[0:6] */ + sr32(&prcm_base->clksel2_pll, 0, 7, ptr->n); + + /* M2DIV (CLKSEL_96M): CM_CLKSEL_CORE[12:13] */ + sr32(&prcm_base->clksel_core, 12, 2, ptr->m2div); + + /* LOCK MODE (EN_PERIPH_DPLL): CM_CLKEN_PLL[16:18] */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_LOCK); + wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY); +} + +static void mpu_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *) get_36x_mpu_dpll_param(); + + /* Moving to the right sysclk */ + ptr += clk_index; + + /* MPU DPLL (unlocked already */ + + /* M2 (MPU_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_MPU[0:4] */ + sr32(&prcm_base->clksel2_pll_mpu, 0, 5, ptr->m2); + + /* M (MPU_DPLL_MULT) : CM_CLKSEL2_PLL_MPU[8:18] */ + sr32(&prcm_base->clksel1_pll_mpu, 8, 11, ptr->m); + + /* N (MPU_DPLL_DIV) : CM_CLKSEL2_PLL_MPU[0:6] */ + sr32(&prcm_base->clksel1_pll_mpu, 0, 7, ptr->n); +} + +static void iva_init_36xx(u32 sil_index, u32 clk_index) +{ + struct prcm *prcm_base = (struct prcm *)PRCM_BASE; + dpll_param *ptr = (dpll_param *)get_36x_iva_dpll_param(); + + /* Moving to the right sysclk */ + ptr += clk_index; + + /* IVA DPLL */ + /* EN_IVA2_DPLL : CM_CLKEN_PLL_IVA2[0:2] */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_STOP); + wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY); + + /* M2 (IVA2_DPLL_CLKOUT_DIV) : CM_CLKSEL2_PLL_IVA2[0:4] */ + sr32(&prcm_base->clksel2_pll_iva2, 0, 5, ptr->m2); + + /* M (IVA2_DPLL_MULT) : CM_CLKSEL1_PLL_IVA2[8:18] */ + sr32(&prcm_base->clksel1_pll_iva2, 8, 11, ptr->m); + + /* N (IVA2_DPLL_DIV) : CM_CLKSEL1_PLL_IVA2[0:6] */ + sr32(&prcm_base->clksel1_pll_iva2, 0, 7, ptr->n); + + /* LOCK (MODE (EN_IVA2_DPLL) : CM_CLKEN_PLL_IVA2[0:2] */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_LOCK); + + wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); +} + /****************************************************************************** * prcm_init() - inits clocks for PRCM as defined in clocks.h * called from SRAM, or Flash (using temp SRAM stack). *****************************************************************************/ void prcm_init(void) { - void (*f_lock_pll) (u32, u32, u32, u32); - int xip_safe, p0, p1, p2, p3; u32 osc_clk = 0, sys_clkin_sel; u32 clk_index, sil_index = 0; struct prm *prm_base = (struct prm *)PRM_BASE; struct prcm *prcm_base = (struct prcm *)PRCM_BASE; - dpll_param *dpll_param_p; - - f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start + - SRAM_VECT_CODE); - - xip_safe = is_running_in_sram(); /* * Gauge the input clock speed and find out the sys_clkin_sel @@ -175,172 +552,50 @@ void prcm_init(void) 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()) - sil_index = 1; - - /* Unlock MPU DPLL (slows things down, and needed later) */ - sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOW_POWER_BYPASS); - wait_on_value(ST_MPU_CLK, 0, &prcm_base->idlest_pll_mpu, LDELAY); - - /* Getting the base address of Core DPLL param table */ - dpll_param_p = (dpll_param *) get_core_dpll_param(); - - /* Moving it to the right sysclk and ES rev base */ - dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; - if (xip_safe) { - /* - * CORE DPLL - * sr32(CM_CLKSEL2_EMU) set override to work when asleep - */ - sr32(&prcm_base->clken_pll, 0, 3, PLL_FAST_RELOCK_BYPASS); - wait_on_value(ST_CORE_CLK, 0, &prcm_base->idlest_ckgen, + if (get_cpu_family() == CPU_OMAP36XX) { + /* Unlock MPU DPLL (slows things down, and needed later) */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOW_POWER_BYPASS); + wait_on_value(ST_MPU_CLK, 0, &prcm_base->idlest_pll_mpu, LDELAY); - /* - * For OMAP3 ES1.0 Errata 1.50, default value directly doesn't - * work. write another value and then default value. - */ + dpll3_init_36xx(0, clk_index); + dpll4_init_36xx(0, clk_index); + iva_init_36xx(0, clk_index); + mpu_init_36xx(0, clk_index); - /* m3x2 */ - sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2 + 1); - /* m3x2 */ - sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2); - /* Set M2 */ - sr32(&prcm_base->clksel1_pll, 27, 2, dpll_param_p->m2); - /* Set M */ - sr32(&prcm_base->clksel1_pll, 16, 11, dpll_param_p->m); - /* Set N */ - sr32(&prcm_base->clksel1_pll, 8, 7, dpll_param_p->n); - /* 96M Src */ - sr32(&prcm_base->clksel1_pll, 6, 1, 0); - /* ssi */ - sr32(&prcm_base->clksel_core, 8, 4, CORE_SSI_DIV); - /* fsusb */ - sr32(&prcm_base->clksel_core, 4, 2, CORE_FUSB_DIV); - /* l4 */ - sr32(&prcm_base->clksel_core, 2, 2, CORE_L4_DIV); - /* l3 */ - sr32(&prcm_base->clksel_core, 0, 2, CORE_L3_DIV); - /* gfx */ - sr32(&prcm_base->clksel_gfx, 0, 3, GFX_DIV); - /* reset mgr */ - sr32(&prcm_base->clksel_wkup, 1, 2, WKUP_RSM); - /* FREQSEL */ - sr32(&prcm_base->clken_pll, 4, 4, dpll_param_p->fsel); - /* lock mode */ - sr32(&prcm_base->clken_pll, 0, 3, PLL_LOCK); - - wait_on_value(ST_CORE_CLK, 1, &prcm_base->idlest_ckgen, + /* Lock MPU DPLL to set frequency */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOCK); + wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, LDELAY); - } else if (is_running_in_flash()) { + } else { /* - * if running from flash, jump to small relocated code - * area in SRAM. + * 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. */ - p0 = readl(&prcm_base->clken_pll); - sr32(&p0, 0, 3, PLL_FAST_RELOCK_BYPASS); - sr32(&p0, 4, 4, dpll_param_p->fsel); /* FREQSEL */ + if (((get_cpu_family() == CPU_OMAP34XX) + && (get_cpu_rev() >= CPU_3XX_ES20)) || + (get_cpu_family() == CPU_AM35XX)) + sil_index = 1; - p1 = readl(&prcm_base->clksel1_pll); - sr32(&p1, 27, 2, dpll_param_p->m2); /* Set M2 */ - sr32(&p1, 16, 11, dpll_param_p->m); /* Set M */ - sr32(&p1, 8, 7, dpll_param_p->n); /* Set N */ - sr32(&p1, 6, 1, 0); /* set source for 96M */ + /* Unlock MPU DPLL (slows things down, and needed later) */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOW_POWER_BYPASS); + wait_on_value(ST_MPU_CLK, 0, &prcm_base->idlest_pll_mpu, + LDELAY); - p2 = readl(&prcm_base->clksel_core); - sr32(&p2, 8, 4, CORE_SSI_DIV); /* ssi */ - sr32(&p2, 4, 2, CORE_FUSB_DIV); /* fsusb */ - sr32(&p2, 2, 2, CORE_L4_DIV); /* l4 */ - sr32(&p2, 0, 2, CORE_L3_DIV); /* l3 */ + dpll3_init_34xx(sil_index, clk_index); + dpll4_init_34xx(sil_index, clk_index); + iva_init_34xx(sil_index, clk_index); + mpu_init_34xx(sil_index, clk_index); - p3 = (u32)&prcm_base->idlest_ckgen; - - (*f_lock_pll) (p0, p1, p2, p3); + /* Lock MPU DPLL to set frequency */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOCK); + wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, + LDELAY); } - /* PER DPLL */ - sr32(&prcm_base->clken_pll, 16, 3, PLL_STOP); - wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); - - /* Getting the base address to PER DPLL param table */ - - /* Set N */ - dpll_param_p = (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 OMAP3 ES1.0 only - * If using default divisors, write default divisor + 1 - * and then the actual divisor value - */ - sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2 + 1); /* set M6 */ - sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2); /* set M6 */ - sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2 + 1); /* set M5 */ - sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2); /* set M5 */ - sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2 + 1); /* set M4 */ - sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2); /* set M4 */ - sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2 + 1); /* set M3 */ - sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2); /* set M3 */ - sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2 + 1); /* set M2 */ - sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2); /* set M2 */ - /* Workaround end */ - - sr32(&prcm_base->clksel2_pll, 8, 11, dpll_param_p->m); /* set m */ - sr32(&prcm_base->clksel2_pll, 0, 7, dpll_param_p->n); /* set n */ - sr32(&prcm_base->clken_pll, 20, 4, dpll_param_p->fsel); /* FREQSEL */ - sr32(&prcm_base->clken_pll, 16, 3, PLL_LOCK); /* lock mode */ - wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY); - - /* Getting the base address to MPU DPLL param table */ - dpll_param_p = (dpll_param *) get_mpu_dpll_param(); - - /* Moving it to the right sysclk and ES rev base */ - dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; - - /* MPU DPLL (unlocked already) */ - - /* Set M2 */ - sr32(&prcm_base->clksel2_pll_mpu, 0, 5, dpll_param_p->m2); - /* Set M */ - sr32(&prcm_base->clksel1_pll_mpu, 8, 11, dpll_param_p->m); - /* Set N */ - sr32(&prcm_base->clksel1_pll_mpu, 0, 7, dpll_param_p->n); - /* FREQSEL */ - sr32(&prcm_base->clken_pll_mpu, 4, 4, dpll_param_p->fsel); - /* lock mode */ - sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOCK); - wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, LDELAY); - - /* Getting the base address to IVA DPLL param table */ - dpll_param_p = (dpll_param *) get_iva_dpll_param(); - - /* Moving it to the right sysclk and ES rev base */ - dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; - - /* IVA DPLL (set to 12*20=240MHz) */ - sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_STOP); - wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY); - /* set M2 */ - sr32(&prcm_base->clksel2_pll_iva2, 0, 5, dpll_param_p->m2); - /* set M */ - sr32(&prcm_base->clksel1_pll_iva2, 8, 11, dpll_param_p->m); - /* set N */ - sr32(&prcm_base->clksel1_pll_iva2, 0, 7, dpll_param_p->n); - /* FREQSEL */ - sr32(&prcm_base->clken_pll_iva2, 4, 4, dpll_param_p->fsel); - /* lock mode */ - sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_LOCK); - wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); - /* Set up GPTimers to sys_clk source only */ sr32(&prcm_base->clksel_per, 0, 8, 0xff); sr32(&prcm_base->clksel_wkup, 0, 1, 1); diff --git a/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/arch/arm/cpu/armv7/omap3/lowlevel_init.S index 73063ec8e6..91c6dbcc09 100644 --- a/arch/arm/cpu/armv7/omap3/lowlevel_init.S +++ b/arch/arm/cpu/armv7/omap3/lowlevel_init.S @@ -359,3 +359,72 @@ per_dpll_param: get_per_dpll_param: adr r0, per_dpll_param mov pc, lr + +/* + * Tables for 36XX/37XX devices + * + */ +mpu_36x_dpll_param: +/* 12MHz */ +.word 50, 0, 0, 1 +/* 13MHz */ +.word 600, 12, 0, 1 +/* 19.2MHz */ +.word 125, 3, 0, 1 +/* 26MHz */ +.word 300, 12, 0, 1 +/* 38.4MHz */ +.word 125, 7, 0, 1 + +iva_36x_dpll_param: +/* 12MHz */ +.word 130, 2, 0, 1 +/* 13MHz */ +.word 20, 0, 0, 1 +/* 19.2MHz */ +.word 325, 11, 0, 1 +/* 26MHz */ +.word 10, 0, 0, 1 +/* 38.4MHz */ +.word 325, 23, 0, 1 + +core_36x_dpll_param: +/* 12MHz */ +.word 100, 2, 0, 1 +/* 13MHz */ +.word 400, 12, 0, 1 +/* 19.2MHz */ +.word 375, 17, 0, 1 +/* 26MHz */ +.word 200, 12, 0, 1 +/* 38.4MHz */ +.word 375, 35, 0, 1 + +per_36x_dpll_param: +/* SYSCLK M N M2 M3 M4 M5 M6 m2DIV */ +.word 12000, 360, 4, 9, 16, 5, 4, 3, 1 +.word 13000, 864, 12, 9, 16, 9, 4, 3, 1 +.word 19200, 360, 7, 9, 16, 5, 4, 3, 1 +.word 26000, 432, 12, 9, 16, 9, 4, 3, 1 +.word 38400, 360, 15, 9, 16, 5, 4, 3, 1 + +.globl get_36x_mpu_dpll_param +get_36x_mpu_dpll_param: + adr r0, mpu_36x_dpll_param + mov pc, lr + +.globl get_36x_iva_dpll_param +get_36x_iva_dpll_param: + adr r0, iva_36x_dpll_param + mov pc, lr + +.globl get_36x_core_dpll_param +get_36x_core_dpll_param: + adr r0, core_36x_dpll_param + mov pc, lr + +.globl get_36x_per_dpll_param +get_36x_per_dpll_param: + adr r0, per_36x_dpll_param + mov pc, lr + diff --git a/arch/arm/include/asm/arch-omap3/clocks.h b/arch/arm/include/asm/arch-omap3/clocks.h index 71a0cb6ae4..40f80baf61 100644 --- a/arch/arm/include/asm/arch-omap3/clocks.h +++ b/arch/arm/include/asm/arch-omap3/clocks.h @@ -51,12 +51,29 @@ typedef struct { unsigned int m2; } dpll_param; +struct dpll_per_36x_param { + unsigned int sys_clk; + unsigned int m; + unsigned int n; + unsigned int m2; + unsigned int m3; + unsigned int m4; + unsigned int m5; + unsigned int m6; + unsigned int m2div; +}; + /* Following functions are exported from lowlevel_init.S */ extern dpll_param *get_mpu_dpll_param(void); extern dpll_param *get_iva_dpll_param(void); extern dpll_param *get_core_dpll_param(void); extern dpll_param *get_per_dpll_param(void); +extern dpll_param *get_36x_mpu_dpll_param(void); +extern dpll_param *get_36x_iva_dpll_param(void); +extern dpll_param *get_36x_core_dpll_param(void); +extern dpll_param *get_36x_per_dpll_param(void); + extern void *_end_vect, *_start; #endif diff --git a/arch/arm/include/asm/arch-omap3/clocks_omap3.h b/arch/arm/include/asm/arch-omap3/clocks_omap3.h index 661407b564..30ef690fa2 100644 --- a/arch/arm/include/asm/arch-omap3/clocks_omap3.h +++ b/arch/arm/include/asm/arch-omap3/clocks_omap3.h @@ -282,4 +282,31 @@ #define PER_FSEL_38P4 0x07 #define PER_M2_38P4 0x09 +/* 36XX PER DPLL */ + +#define PER_36XX_M_12 0x1B0 +#define PER_36XX_N_12 0x05 +#define PER_36XX_FSEL_12 0x07 +#define PER_36XX_M2_12 0x09 + +#define PER_36XX_M_13 0x360 +#define PER_36XX_N_13 0x0C +#define PER_36XX_FSEL_13 0x03 +#define PER_36XX_M2_13 0x09 + +#define PER_36XX_M_19P2 0x1C2 +#define PER_36XX_N_19P2 0x09 +#define PER_36XX_FSEL_19P2 0x07 +#define PER_36XX_M2_19P2 0x09 + +#define PER_36XX_M_26 0x1B0 +#define PER_36XX_N_26 0x0C +#define PER_36XX_FSEL_26 0x07 +#define PER_36XX_M2_26 0x09 + +#define PER_36XX_M_38P4 0x1C2 +#define PER_36XX_N_38P4 0x13 +#define PER_36XX_FSEL_38P4 0x07 +#define PER_36XX_M2_38P4 0x09 + #endif /* endif _CLOCKS_OMAP3_H_ */