ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/linux/arch/arm/mach-mmp/asr_lowpower_tos.c b/marvell/linux/arch/arm/mach-mmp/asr_lowpower_tos.c
new file mode 100644
index 0000000..609cde7
--- /dev/null
+++ b/marvell/linux/arch/arm/mach-mmp/asr_lowpower_tos.c
@@ -0,0 +1,157 @@
+#include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/clk/dvfs-dvc.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/edge_wakeup_mmp.h>
+#include <linux/slab.h>
+#include <soc/asr/regs-addr.h>
+#include <linux/cputype.h>
+#include <asm/cpuidle.h>
+#include <asm/mach/map.h>
+#include <asm/mcpm.h>
+#include <soc/asr/mmp_cpuidle.h>
+#ifdef CONFIG_CPU_ASR1901
+#include <soc/asr/asr1901_lowpower.h>
+#else
+#include <soc/asr/asr18xx_lowpower.h>
+#endif
+#include "addr-map.h"
+#include <linux/arm-smccc.h>
+#include <linux/of_address.h>
+#include <linux/asr_tee_sip.h>
+
+extern int __init asr_platform_power_register(struct platform_idle *idle);
+
+
+#ifdef CONFIG_CPU_ASR1901
+#define ASR_CPUIDLE_FLAG CPUIDLE_FLAG_NONE
+#else
+#define ASR_CPUIDLE_FLAG CPUIDLE_FLAG_TIMER_STOP
+#endif
+
+static struct cpuidle_state asr_modes[] = {
+ [0] = {
+ .exit_latency = 18,
+ .target_residency = 36,
+ /*
+ * Use CPUIDLE_FLAG_TIMER_STOP flag to let the cpuidle
+ * framework handle the CLOCK_EVENT_NOTIFY_BROADCAST_
+ * ENTER/EXIT when entering idle states.
+ */
+ .flags = /* CPUIDLE_FLAG_TIME_VALID */0,
+ .name = "C1",
+ .desc = "C1: Core internal clock gated",
+ .enter = arm_cpuidle_simple_enter,
+ },
+ [1] = {
+ .exit_latency = 350,
+ .target_residency = 700,
+ .flags = ASR_CPUIDLE_FLAG,
+ .name = "C2",
+ .desc = "C2: Core power down",
+ },
+ [2] = {
+ .exit_latency = 500,
+ .target_residency = 1000,
+ .flags = ASR_CPUIDLE_FLAG,
+ .name = "D1p",
+ .desc = "D1p: AP idle state",
+ },
+ [3] = {
+ .exit_latency = 600,
+ .target_residency = 1200,
+ .flags = ASR_CPUIDLE_FLAG,
+ .name = "D1",
+ .desc = "D1: Chip idle state",
+ },
+
+
+};
+
+static int need_restore_pad_wakeup;
+
+#ifdef CONFIG_CPU_ASR1901
+#define EDGE_WAKEUP_GIC 39 /* GIC interrupt num for edge wakeup */
+
+extern void extern_gic_mask_unmask_irq(int irq_num, bool mask);
+
+static void edge_wakeup_gic_enable(void)
+{
+ extern_gic_mask_unmask_irq(EDGE_WAKEUP_GIC, 0);
+}
+
+static void edge_wakeup_gic_disable(void)
+{
+ extern_gic_mask_unmask_irq(EDGE_WAKEUP_GIC, 1);
+}
+#endif
+
+void asr_set_pmu(u32 cpu, u32 power_mode)
+{
+ (void)cpu;
+
+ /* TODO: move to TOS next step */
+ if(power_mode > POWER_MODE_CORE_POWERDOWN) {
+ edge_wakeup_mfp_enable();
+#ifdef CONFIG_CPU_ASR1901
+ edge_wakeup_gic_enable();
+#endif
+ need_restore_pad_wakeup = 1;
+ }
+}
+
+void asr_clr_pmu(u32 cpu)
+{
+ /* TODO: move to TOS next step */
+ if(need_restore_pad_wakeup) {
+ edge_wakeup_mfp_disable();
+#ifdef CONFIG_CPU_ASR1901
+ edge_wakeup_gic_disable();
+#endif
+ need_restore_pad_wakeup = 0;
+ }
+}
+
+static struct platform_power_ops asr_power_ops = {
+ .set_pmu = asr_set_pmu,
+ .clr_pmu = asr_clr_pmu,
+ .save_wakeup = NULL,
+ .restore_wakeup = NULL,
+ .power_up_setup = ca7_power_up_setup,
+ .cpu_power_status = NULL,
+};
+
+static struct platform_idle asr_idle = {
+ .cpudown_state = POWER_MODE_CORE_POWERDOWN,
+ .wakeup_state = POWER_MODE_SYS_SLEEP,
+ .hotplug_state = POWER_MODE_UDR,
+ .l2_flush_state = POWER_MODE_UDR,
+ .ops = &asr_power_ops,
+ .states = asr_modes,
+ .state_count = ARRAY_SIZE(asr_modes),
+};
+
+static int __init asr_lowpower_init(void)
+{
+
+ asr_platform_power_register(&asr_idle);
+
+#ifdef CONFIG_ARM_ERRATA_802022
+ {
+ u32 mp_idle_cfg;
+ int i;
+
+ for_each_possible_cpu(i) {
+ mp_idle_cfg = __raw_readl(APMU_MP_IDLE_CFG[i]);
+ mp_idle_cfg |= (PMUA_DIS_MP_SLP);
+ __raw_writel(mp_idle_cfg, APMU_MP_IDLE_CFG[i]);
+ }
+ }
+#endif
+
+ return 0;
+}
+early_initcall(asr_lowpower_init);