|
@@ -49,6 +49,7 @@
|
|
#include <asm/system.h>
|
|
#include <asm/system.h>
|
|
#include <asm/pgalloc.h>
|
|
#include <asm/pgalloc.h>
|
|
#include <asm/suspend.h>
|
|
#include <asm/suspend.h>
|
|
|
|
+#include <asm/hardware/cache-l2x0.h>
|
|
|
|
|
|
#include <plat/omap44xx.h>
|
|
#include <plat/omap44xx.h>
|
|
|
|
|
|
@@ -63,10 +64,12 @@ struct omap4_cpu_pm_info {
|
|
struct powerdomain *pwrdm;
|
|
struct powerdomain *pwrdm;
|
|
void __iomem *scu_sar_addr;
|
|
void __iomem *scu_sar_addr;
|
|
void __iomem *wkup_sar_addr;
|
|
void __iomem *wkup_sar_addr;
|
|
|
|
+ void __iomem *l2x0_sar_addr;
|
|
};
|
|
};
|
|
|
|
|
|
static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
|
|
static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
|
|
static struct powerdomain *mpuss_pd;
|
|
static struct powerdomain *mpuss_pd;
|
|
|
|
+static void __iomem *sar_base;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Program the wakeup routine address for the CPU0 and CPU1
|
|
* Program the wakeup routine address for the CPU0 and CPU1
|
|
@@ -135,6 +138,36 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
|
|
__raw_writel(scu_pwr_st, pm_info->scu_sar_addr);
|
|
__raw_writel(scu_pwr_st, pm_info->scu_sar_addr);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * 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
|
|
* omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
|
|
* The purpose of this function is to manage low power programming
|
|
* The purpose of this function is to manage low power programming
|
|
@@ -182,6 +215,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
|
|
set_cpu_next_pwrst(cpu, power_state);
|
|
set_cpu_next_pwrst(cpu, power_state);
|
|
set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume));
|
|
set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume));
|
|
scu_pwrst_prepare(cpu, power_state);
|
|
scu_pwrst_prepare(cpu, power_state);
|
|
|
|
+ l2x0_pwrst_prepare(cpu, save_state);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Call low level function with targeted low power state.
|
|
* Call low level function with targeted low power state.
|
|
@@ -239,17 +273,19 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
|
|
int __init omap4_mpuss_init(void)
|
|
int __init omap4_mpuss_init(void)
|
|
{
|
|
{
|
|
struct omap4_cpu_pm_info *pm_info;
|
|
struct omap4_cpu_pm_info *pm_info;
|
|
- void __iomem *sar_base = omap4_get_sar_ram_base();
|
|
|
|
|
|
|
|
if (omap_rev() == OMAP4430_REV_ES1_0) {
|
|
if (omap_rev() == OMAP4430_REV_ES1_0) {
|
|
WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
|
|
WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ sar_base = omap4_get_sar_ram_base();
|
|
|
|
+
|
|
/* Initilaise per CPU PM information */
|
|
/* Initilaise per CPU PM information */
|
|
pm_info = &per_cpu(omap4_pm_info, 0x0);
|
|
pm_info = &per_cpu(omap4_pm_info, 0x0);
|
|
pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
|
|
pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
|
|
pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
|
|
pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
|
|
|
|
+ pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0;
|
|
pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
|
|
pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
|
|
if (!pm_info->pwrdm) {
|
|
if (!pm_info->pwrdm) {
|
|
pr_err("Lookup failed for CPU0 pwrdm\n");
|
|
pr_err("Lookup failed for CPU0 pwrdm\n");
|
|
@@ -265,6 +301,7 @@ int __init omap4_mpuss_init(void)
|
|
pm_info = &per_cpu(omap4_pm_info, 0x1);
|
|
pm_info = &per_cpu(omap4_pm_info, 0x1);
|
|
pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
|
|
pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
|
|
pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
|
|
pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
|
|
|
|
+ pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
|
|
pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
|
|
pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
|
|
if (!pm_info->pwrdm) {
|
|
if (!pm_info->pwrdm) {
|
|
pr_err("Lookup failed for CPU1 pwrdm\n");
|
|
pr_err("Lookup failed for CPU1 pwrdm\n");
|
|
@@ -290,6 +327,8 @@ int __init omap4_mpuss_init(void)
|
|
else
|
|
else
|
|
__raw_writel(0, sar_base + OMAP_TYPE_OFFSET);
|
|
__raw_writel(0, sar_base + OMAP_TYPE_OFFSET);
|
|
|
|
|
|
|
|
+ save_l2x0_context();
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|