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);