|
@@ -74,3 +74,160 @@ struct omap4_cpu_pm_info {
|
|
|
static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
|
|
|
static struct powerdomain *mpuss_pd;
|
|
|
static void __iomem *sar_base;
|
|
|
+
|
|
|
+/*
|
|
|
+ * Program the wakeup routine address for the CPU0 and CPU1
|
|
|
+ * used for OFF or DORMANT wakeup.
|
|
|
+ */
|
|
|
+static inline void set_cpu_wakeup_addr(unsigned int cpu_id, u32 addr)
|
|
|
+{
|
|
|
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
|
|
|
+
|
|
|
+ __raw_writel(addr, pm_info->wkup_sar_addr);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Set the CPUx powerdomain's previous power state
|
|
|
+ */
|
|
|
+static inline void set_cpu_next_pwrst(unsigned int cpu_id,
|
|
|
+ unsigned int power_state)
|
|
|
+{
|
|
|
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
|
|
|
+
|
|
|
+ pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Read CPU's previous power state
|
|
|
+ */
|
|
|
+static inline unsigned int read_cpu_prev_pwrst(unsigned int cpu_id)
|
|
|
+{
|
|
|
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
|
|
|
+
|
|
|
+ return pwrdm_read_prev_pwrst(pm_info->pwrdm);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Clear the CPUx powerdomain's previous power state
|
|
|
+ */
|
|
|
+static inline void clear_cpu_prev_pwrst(unsigned int cpu_id)
|
|
|
+{
|
|
|
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
|
|
|
+
|
|
|
+ pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Store the SCU power status value to scratchpad memory
|
|
|
+ */
|
|
|
+static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
|
|
|
+{
|
|
|
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
|
|
|
+ u32 scu_pwr_st;
|
|
|
+
|
|
|
+ switch (cpu_state) {
|
|
|
+ case PWRDM_POWER_RET:
|
|
|
+ scu_pwr_st = SCU_PM_DORMANT;
|
|
|
+ break;
|
|
|
+ case PWRDM_POWER_OFF:
|
|
|
+ scu_pwr_st = SCU_PM_POWEROFF;
|
|
|
+ break;
|
|
|
+ case PWRDM_POWER_ON:
|
|
|
+ case PWRDM_POWER_INACTIVE:
|
|
|
+ default:
|
|
|
+ scu_pwr_st = SCU_PM_NORMAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ __raw_writel(scu_pwr_st, pm_info->scu_sar_addr);
|
|
|
+}
|
|
|
+
|
|
|
+/* Helper functions for MPUSS OSWR */
|
|
|
+static inline void mpuss_clear_prev_logic_pwrst(void)
|
|
|
+{
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
|
|
|
+ OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET);
|
|
|
+ omap4_prminst_write_inst_reg(reg, OMAP4430_PRM_PARTITION,
|
|
|
+ OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void cpu_clear_prev_logic_pwrst(unsigned int cpu_id)
|
|
|
+{
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ if (cpu_id) {
|
|
|
+ reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU1_INST,
|
|
|
+ OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET);
|
|
|
+ omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU1_INST,
|
|
|
+ OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET);
|
|
|
+ } else {
|
|
|
+ reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU0_INST,
|
|
|
+ OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET);
|
|
|
+ omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU0_INST,
|
|
|
+ OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap4_mpuss_read_prev_context_state:
|
|
|
+ * Function returns the MPUSS previous context state
|
|
|
+ */
|
|
|
+u32 omap4_mpuss_read_prev_context_state(void)
|
|
|
+{
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
|
|
|
+ OMAP4430_PRM_MPU_INST, OMAP4_RM_MPU_MPU_CONTEXT_OFFSET);
|
|
|
+ reg &= OMAP4430_LOSTCONTEXT_DFF_MASK;
|
|
|
+ return reg;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Store the CPU cluster state for L2X0 low power operations.
|
|
|
+ */
|
|
|
+static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state)
|
|
|
+{
|
|
|
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
|
|
|
+
|
|
|
+ __raw_writel(save_state, pm_info->l2x0_sar_addr);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Save the L2X0 AUXCTRL and POR value to SAR memory. Its used to
|
|
|
+ * in every restore MPUSS OFF path.
|
|
|
+ */
|
|
|
+#ifdef CONFIG_CACHE_L2X0
|
|
|
+static void save_l2x0_context(void)
|
|
|
+{
|
|
|
+ u32 val;
|
|
|
+ void __iomem *l2x0_base = omap4_get_l2cache_base();
|
|
|
+
|
|
|
+ val = __raw_readl(l2x0_base + L2X0_AUX_CTRL);
|
|
|
+ __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET);
|
|
|
+ val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
|
|
|
+ __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET);
|
|
|
+}
|
|
|
+#else
|
|
|
+static void save_l2x0_context(void)
|
|
|
+{}
|
|
|
+#endif
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
|
|
|
+ * The purpose of this function is to manage low power programming
|
|
|
+ * of OMAP4 MPUSS subsystem
|
|
|
+ * @cpu : CPU ID
|
|
|
+ * @power_state: Low power state.
|
|
|
+ *
|
|
|
+ * MPUSS states for the context save:
|
|
|
+ * save_state =
|
|
|
+ * 0 - Nothing lost and no need to save: MPUSS INACTIVE
|
|
|
+ * 1 - CPUx L1 and logic lost: MPUSS CSWR
|
|
|
+ * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
|
|
|
+ * 3 - CPUx L1 and logic lost + GIC + L2 lost: DEVICE OFF
|
|
|
+ */
|
|
|
+int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
|
|
|
+{
|
|
|
+ unsigned int save_state = 0;
|