|
@@ -269,3 +269,159 @@ void omap_ctrl_write_dsp_boot_addr(u32 bootaddr)
|
|
void omap_ctrl_write_dsp_boot_mode(u8 bootmode)
|
|
void omap_ctrl_write_dsp_boot_mode(u8 bootmode)
|
|
{
|
|
{
|
|
u32 offset = cpu_is_omap243x() ? OMAP243X_CONTROL_IVA2_BOOTMOD :
|
|
u32 offset = cpu_is_omap243x() ? OMAP243X_CONTROL_IVA2_BOOTMOD :
|
|
|
|
+ cpu_is_omap34xx() ? OMAP343X_CONTROL_IVA2_BOOTMOD :
|
|
|
|
+ 0;
|
|
|
|
+
|
|
|
|
+ if (!offset) {
|
|
|
|
+ pr_err("%s: unsupported omap type\n", __func__);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ omap_ctrl_writel(bootmode, offset);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
|
|
|
|
+/*
|
|
|
|
+ * Clears the scratchpad contents in case of cold boot-
|
|
|
|
+ * called during bootup
|
|
|
|
+ */
|
|
|
|
+void omap3_clear_scratchpad_contents(void)
|
|
|
|
+{
|
|
|
|
+ u32 max_offset = OMAP343X_SCRATCHPAD_ROM_OFFSET;
|
|
|
|
+ void __iomem *v_addr;
|
|
|
|
+ u32 offset = 0;
|
|
|
|
+ v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
|
|
|
|
+ if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
|
|
|
|
+ OMAP3430_GLOBAL_COLD_RST_MASK) {
|
|
|
|
+ for ( ; offset <= max_offset; offset += 0x4)
|
|
|
|
+ __raw_writel(0x0, (v_addr + offset));
|
|
|
|
+ omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK,
|
|
|
|
+ OMAP3430_GR_MOD,
|
|
|
|
+ OMAP3_PRM_RSTST_OFFSET);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Populate the scratchpad structure with restore structure */
|
|
|
|
+void omap3_save_scratchpad_contents(void)
|
|
|
|
+{
|
|
|
|
+ void __iomem *scratchpad_address;
|
|
|
|
+ u32 arm_context_addr;
|
|
|
|
+ struct omap3_scratchpad scratchpad_contents;
|
|
|
|
+ struct omap3_scratchpad_prcm_block prcm_block_contents;
|
|
|
|
+ struct omap3_scratchpad_sdrc_block sdrc_block_contents;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Populate the Scratchpad contents
|
|
|
|
+ *
|
|
|
|
+ * The "get_*restore_pointer" functions are used to provide a
|
|
|
|
+ * physical restore address where the ROM code jumps while waking
|
|
|
|
+ * up from MPU OFF/OSWR state.
|
|
|
|
+ * The restore pointer is stored into the scratchpad.
|
|
|
|
+ */
|
|
|
|
+ scratchpad_contents.boot_config_ptr = 0x0;
|
|
|
|
+ if (cpu_is_omap3630())
|
|
|
|
+ scratchpad_contents.public_restore_ptr =
|
|
|
|
+ virt_to_phys(omap3_restore_3630);
|
|
|
|
+ else if (omap_rev() != OMAP3430_REV_ES3_0 &&
|
|
|
|
+ omap_rev() != OMAP3430_REV_ES3_1)
|
|
|
|
+ scratchpad_contents.public_restore_ptr =
|
|
|
|
+ virt_to_phys(omap3_restore);
|
|
|
|
+ else
|
|
|
|
+ scratchpad_contents.public_restore_ptr =
|
|
|
|
+ virt_to_phys(omap3_restore_es3);
|
|
|
|
+
|
|
|
|
+ if (omap_type() == OMAP2_DEVICE_TYPE_GP)
|
|
|
|
+ scratchpad_contents.secure_ram_restore_ptr = 0x0;
|
|
|
|
+ else
|
|
|
|
+ scratchpad_contents.secure_ram_restore_ptr =
|
|
|
|
+ (u32) __pa(omap3_secure_ram_storage);
|
|
|
|
+ scratchpad_contents.sdrc_module_semaphore = 0x0;
|
|
|
|
+ scratchpad_contents.prcm_block_offset = 0x2C;
|
|
|
|
+ scratchpad_contents.sdrc_block_offset = 0x64;
|
|
|
|
+
|
|
|
|
+ /* Populate the PRCM block contents */
|
|
|
|
+ prcm_block_contents.prm_clksrc_ctrl =
|
|
|
|
+ omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
|
|
|
|
+ OMAP3_PRM_CLKSRC_CTRL_OFFSET);
|
|
|
|
+ prcm_block_contents.prm_clksel =
|
|
|
|
+ omap2_prm_read_mod_reg(OMAP3430_CCR_MOD,
|
|
|
|
+ OMAP3_PRM_CLKSEL_OFFSET);
|
|
|
|
+ prcm_block_contents.cm_clksel_core =
|
|
|
|
+ omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
|
|
|
|
+ prcm_block_contents.cm_clksel_wkup =
|
|
|
|
+ omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
|
|
|
|
+ prcm_block_contents.cm_clken_pll =
|
|
|
|
+ omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
|
|
|
|
+ /*
|
|
|
|
+ * As per erratum i671, ROM code does not respect the PER DPLL
|
|
|
|
+ * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
|
|
|
|
+ * Then, in anycase, clear these bits to avoid extra latencies.
|
|
|
|
+ */
|
|
|
|
+ prcm_block_contents.cm_autoidle_pll =
|
|
|
|
+ omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
|
|
|
|
+ ~OMAP3430_AUTO_PERIPH_DPLL_MASK;
|
|
|
|
+ prcm_block_contents.cm_clksel1_pll =
|
|
|
|
+ omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
|
|
|
|
+ prcm_block_contents.cm_clksel2_pll =
|
|
|
|
+ omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
|
|
|
|
+ prcm_block_contents.cm_clksel3_pll =
|
|
|
|
+ omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
|
|
|
|
+ prcm_block_contents.cm_clken_pll_mpu =
|
|
|
|
+ omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
|
|
|
|
+ prcm_block_contents.cm_autoidle_pll_mpu =
|
|
|
|
+ omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
|
|
|
|
+ prcm_block_contents.cm_clksel1_pll_mpu =
|
|
|
|
+ omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
|
|
|
|
+ prcm_block_contents.cm_clksel2_pll_mpu =
|
|
|
|
+ omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
|
|
|
|
+ prcm_block_contents.prcm_block_size = 0x0;
|
|
|
|
+
|
|
|
|
+ /* Populate the SDRC block contents */
|
|
|
|
+ sdrc_block_contents.sysconfig =
|
|
|
|
+ (sdrc_read_reg(SDRC_SYSCONFIG) & 0xFFFF);
|
|
|
|
+ sdrc_block_contents.cs_cfg =
|
|
|
|
+ (sdrc_read_reg(SDRC_CS_CFG) & 0xFFFF);
|
|
|
|
+ sdrc_block_contents.sharing =
|
|
|
|
+ (sdrc_read_reg(SDRC_SHARING) & 0xFFFF);
|
|
|
|
+ sdrc_block_contents.err_type =
|
|
|
|
+ (sdrc_read_reg(SDRC_ERR_TYPE) & 0xFFFF);
|
|
|
|
+ sdrc_block_contents.dll_a_ctrl = sdrc_read_reg(SDRC_DLLA_CTRL);
|
|
|
|
+ sdrc_block_contents.dll_b_ctrl = 0x0;
|
|
|
|
+ /*
|
|
|
|
+ * Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should
|
|
|
|
+ * be programed to issue automatic self refresh on timeout
|
|
|
|
+ * of AUTO_CNT = 1 prior to any transition to OFF mode.
|
|
|
|
+ */
|
|
|
|
+ if ((omap_type() != OMAP2_DEVICE_TYPE_GP)
|
|
|
|
+ && (omap_rev() >= OMAP3430_REV_ES3_0))
|
|
|
|
+ sdrc_block_contents.power = (sdrc_read_reg(SDRC_POWER) &
|
|
|
|
+ ~(SDRC_POWER_AUTOCOUNT_MASK|
|
|
|
|
+ SDRC_POWER_CLKCTRL_MASK)) |
|
|
|
|
+ (1 << SDRC_POWER_AUTOCOUNT_SHIFT) |
|
|
|
|
+ SDRC_SELF_REFRESH_ON_AUTOCOUNT;
|
|
|
|
+ else
|
|
|
|
+ sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER);
|
|
|
|
+
|
|
|
|
+ sdrc_block_contents.cs_0 = 0x0;
|
|
|
|
+ sdrc_block_contents.mcfg_0 = sdrc_read_reg(SDRC_MCFG_0);
|
|
|
|
+ sdrc_block_contents.mr_0 = (sdrc_read_reg(SDRC_MR_0) & 0xFFFF);
|
|
|
|
+ sdrc_block_contents.emr_1_0 = 0x0;
|
|
|
|
+ sdrc_block_contents.emr_2_0 = 0x0;
|
|
|
|
+ sdrc_block_contents.emr_3_0 = 0x0;
|
|
|
|
+ sdrc_block_contents.actim_ctrla_0 =
|
|
|
|
+ sdrc_read_reg(SDRC_ACTIM_CTRL_A_0);
|
|
|
|
+ sdrc_block_contents.actim_ctrlb_0 =
|
|
|
|
+ sdrc_read_reg(SDRC_ACTIM_CTRL_B_0);
|
|
|
|
+ sdrc_block_contents.rfr_ctrl_0 =
|
|
|
|
+ sdrc_read_reg(SDRC_RFR_CTRL_0);
|
|
|
|
+ sdrc_block_contents.cs_1 = 0x0;
|
|
|
|
+ sdrc_block_contents.mcfg_1 = sdrc_read_reg(SDRC_MCFG_1);
|
|
|
|
+ sdrc_block_contents.mr_1 = sdrc_read_reg(SDRC_MR_1) & 0xFFFF;
|
|
|
|
+ sdrc_block_contents.emr_1_1 = 0x0;
|
|
|
|
+ sdrc_block_contents.emr_2_1 = 0x0;
|
|
|
|
+ sdrc_block_contents.emr_3_1 = 0x0;
|
|
|
|
+ sdrc_block_contents.actim_ctrla_1 =
|
|
|
|
+ sdrc_read_reg(SDRC_ACTIM_CTRL_A_1);
|
|
|
|
+ sdrc_block_contents.actim_ctrlb_1 =
|
|
|
|
+ sdrc_read_reg(SDRC_ACTIM_CTRL_B_1);
|
|
|
|
+ sdrc_block_contents.rfr_ctrl_1 =
|