}
}
+inline u32 check_for_lock(u32 *const base)
+{
+ struct dpll_regs *const dpll_regs = (struct dpll_regs *)base;
+ u32 lock = readl(&dpll_regs->cm_idlest_dpll) & ST_DPLL_CLK_MASK;
+
+ return lock;
+}
+
static void do_setup_dpll(u32 *const base, const struct dpll_params *params,
- u8 lock)
+ u8 lock, char *dpll)
{
- u32 temp;
+ u32 temp, M, N;
struct dpll_regs *const dpll_regs = (struct dpll_regs *)base;
+ temp = readl(&dpll_regs->cm_clksel_dpll);
+
+ if (check_for_lock(base)) {
+ /*
+ * The Dpll has already been locked by rom code using CH.
+ * Check if M,N are matching with Ideal nominal opp values.
+ * If matches, skip the rest otherwise relock.
+ */
+ M = (temp & CM_CLKSEL_DPLL_M_MASK) >> CM_CLKSEL_DPLL_M_SHIFT;
+ N = (temp & CM_CLKSEL_DPLL_N_MASK) >> CM_CLKSEL_DPLL_N_SHIFT;
+ if ((M != (params->m)) || (N != (params->n))) {
+ debug("\n %s Dpll locked, but not for ideal M = %d,"
+ "N = %d values, current values are M = %d,"
+ "N= %d" , dpll, params->m, params->n,
+ M, N);
+ } else {
+ /* Dpll locked with ideal values for nominal opps. */
+ debug("\n %s Dpll already locked with ideal"
+ "nominal opp values", dpll);
+ goto setup_post_dividers;
+ }
+ }
+
bypass_dpll(base);
/* Set M & N */
- temp = readl(&dpll_regs->cm_clksel_dpll);
-
temp &= ~CM_CLKSEL_DPLL_M_MASK;
temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK;
if (lock)
do_lock_dpll(base);
+setup_post_dividers:
setup_post_dividers(base, params);
/* Wait till the DPLL locks */
}
params = get_mpu_dpll_params();
- do_setup_dpll(&prcm->cm_clkmode_dpll_mpu, params, DPLL_LOCK);
+
+ do_setup_dpll(&prcm->cm_clkmode_dpll_mpu, params, DPLL_LOCK, "mpu");
debug("MPU DPLL locked\n");
}
+#ifdef CONFIG_USB_EHCI_OMAP
+static void setup_usb_dpll(void)
+{
+ const struct dpll_params *params;
+ u32 sys_clk_khz, sd_div, num, den;
+
+ sys_clk_khz = get_sys_clk_freq() / 1000;
+ /*
+ * USB:
+ * USB dpll is J-type. Need to set DPLL_SD_DIV for jitter correction
+ * DPLL_SD_DIV = CEILING ([DPLL_MULT/(DPLL_DIV+1)]* CLKINP / 250)
+ * - where CLKINP is sys_clk in MHz
+ * Use CLKINP in KHz and adjust the denominator accordingly so
+ * that we have enough accuracy and at the same time no overflow
+ */
+ params = get_usb_dpll_params();
+ num = params->m * sys_clk_khz;
+ den = (params->n + 1) * 250 * 1000;
+ num += den - 1;
+ sd_div = num / den;
+ clrsetbits_le32(&prcm->cm_clksel_dpll_usb,
+ CM_CLKSEL_DPLL_DPLL_SD_DIV_MASK,
+ sd_div << CM_CLKSEL_DPLL_DPLL_SD_DIV_SHIFT);
+
+ /* Now setup the dpll with the regular function */
+ do_setup_dpll(&prcm->cm_clkmode_dpll_usb, params, DPLL_LOCK, "usb");
+}
+#endif
+
static void setup_dplls(void)
{
- u32 sysclk_ind, temp;
+ u32 temp;
const struct dpll_params *params;
- debug("setup_dplls\n");
- sysclk_ind = get_sys_clk_index();
+ debug("setup_dplls\n");
/* CORE dpll */
params = get_core_dpll_params(); /* default - safest */
* Core DPLL will be locked after setting up EMIF
* using the FREQ_UPDATE method(freq_update_core())
*/
- do_setup_dpll(&prcm->cm_clkmode_dpll_core, params, DPLL_NO_LOCK);
+ do_setup_dpll(&prcm->cm_clkmode_dpll_core, params, DPLL_NO_LOCK,
+ "core");
/* Set the ratios for CORE_CLK, L3_CLK, L4_CLK */
temp = (CLKSEL_CORE_X2_DIV_1 << CLKSEL_CORE_SHIFT) |
(CLKSEL_L3_CORE_DIV_2 << CLKSEL_L3_SHIFT) |
/* lock PER dpll */
params = get_per_dpll_params();
do_setup_dpll(&prcm->cm_clkmode_dpll_per,
- params, DPLL_LOCK);
+ params, DPLL_LOCK, "per");
debug("PER DPLL locked\n");
/* MPU dpll */
configure_mpu_dpll();
+
+#ifdef CONFIG_USB_EHCI_OMAP
+ setup_usb_dpll();
+#endif
}
+#ifdef CONFIG_SYS_CLOCKS_ENABLE_ALL
static void setup_non_essential_dplls(void)
{
u32 sys_clk_khz, abe_ref_clk;
- u32 sysclk_ind, sd_div, num, den;
const struct dpll_params *params;
- sysclk_ind = get_sys_clk_index();
sys_clk_khz = get_sys_clk_freq() / 1000;
/* IVA */
CM_BYPCLK_DPLL_IVA_CLKSEL_MASK, DPLL_IVA_CLKSEL_CORE_X2_DIV_2);
params = get_iva_dpll_params();
- do_setup_dpll(&prcm->cm_clkmode_dpll_iva, params, DPLL_LOCK);
-
- /*
- * USB:
- * USB dpll is J-type. Need to set DPLL_SD_DIV for jitter correction
- * DPLL_SD_DIV = CEILING ([DPLL_MULT/(DPLL_DIV+1)]* CLKINP / 250)
- * - where CLKINP is sys_clk in MHz
- * Use CLKINP in KHz and adjust the denominator accordingly so
- * that we have enough accuracy and at the same time no overflow
- */
- params = get_usb_dpll_params();
- num = params->m * sys_clk_khz;
- den = (params->n + 1) * 250 * 1000;
- num += den - 1;
- sd_div = num / den;
- clrsetbits_le32(&prcm->cm_clksel_dpll_usb,
- CM_CLKSEL_DPLL_DPLL_SD_DIV_MASK,
- sd_div << CM_CLKSEL_DPLL_DPLL_SD_DIV_SHIFT);
-
- /* Now setup the dpll with the regular function */
- do_setup_dpll(&prcm->cm_clkmode_dpll_usb, params, DPLL_LOCK);
+ do_setup_dpll(&prcm->cm_clkmode_dpll_iva, params, DPLL_LOCK, "iva");
/* Configure ABE dpll */
params = get_abe_dpll_params();
CM_ABE_PLL_REF_CLKSEL_CLKSEL_MASK,
abe_ref_clk << CM_ABE_PLL_REF_CLKSEL_CLKSEL_SHIFT);
/* Lock the dpll */
- do_setup_dpll(&prcm->cm_clkmode_dpll_abe, params, DPLL_LOCK);
+ do_setup_dpll(&prcm->cm_clkmode_dpll_abe, params, DPLL_LOCK, "abe");
}
+#endif
void do_scale_tps62361(u32 reg, u32 volt_mv)
{
step = volt_mv - TPS62361_BASE_VOLT_MV;
step /= 10;
- /*
- * Select SET1 in TPS62361:
- * VSEL1 is grounded on board. So the following selects
- * VSEL1 = 0 and VSEL0 = 1
- */
- gpio_direction_output(TPS62361_VSEL0_GPIO, 0);
- gpio_set_value(TPS62361_VSEL0_GPIO, 1);
-
temp = TPS62361_I2C_SLAVE_ADDR |
(reg << PRM_VC_VAL_BYPASS_REGADDR_SHIFT) |
(step << PRM_VC_VAL_BYPASS_DATA_SHIFT) |
enable_basic_clocks();
scale_vcores();
setup_dplls();
+#ifdef CONFIG_SYS_CLOCKS_ENABLE_ALL
setup_non_essential_dplls();
enable_non_essential_clocks();
+#endif
break;
default:
break;
}
+
+ if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context())
+ enable_basic_uboot_clocks();
}