Browse Source

Merge branch 'pull/v3.18/for-omap-soc' of https://github.com/nmenon/linux-2.6-playground into omap-for-v3.18/soc

Tony Lindgren 11 years ago
parent
commit
887782e04f

+ 1 - 1
arch/arm/mach-omap2/common.h

@@ -60,7 +60,7 @@ static inline int omap3_pm_init(void)
 }
 }
 #endif
 #endif
 
 
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
+#if defined(CONFIG_PM) && (defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5))
 int omap4_pm_init(void);
 int omap4_pm_init(void);
 int omap4_pm_init_early(void);
 int omap4_pm_init_early(void);
 #else
 #else

+ 3 - 0
arch/arm/mach-omap2/io.c

@@ -667,6 +667,7 @@ void __init omap5_init_early(void)
 	omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE),
 	omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE),
 			     OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE));
 			     OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE));
 	omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE));
 	omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE));
+	omap4_pm_init_early();
 	omap_prm_base_init();
 	omap_prm_base_init();
 	omap_cm_base_init();
 	omap_cm_base_init();
 	omap44xx_prm_init();
 	omap44xx_prm_init();
@@ -682,6 +683,8 @@ void __init omap5_init_early(void)
 void __init omap5_init_late(void)
 void __init omap5_init_late(void)
 {
 {
 	omap_common_late_init();
 	omap_common_late_init();
+	omap4_pm_init();
+	omap2_clk_enable_autoidle_all();
 }
 }
 #endif
 #endif
 
 

+ 71 - 31
arch/arm/mach-omap2/omap-mpuss-lowpower.c

@@ -56,6 +56,7 @@
 #include "omap4-sar-layout.h"
 #include "omap4-sar-layout.h"
 #include "pm.h"
 #include "pm.h"
 #include "prcm_mpu44xx.h"
 #include "prcm_mpu44xx.h"
+#include "prcm_mpu54xx.h"
 #include "prminst44xx.h"
 #include "prminst44xx.h"
 #include "prcm44xx.h"
 #include "prcm44xx.h"
 #include "prm44xx.h"
 #include "prm44xx.h"
@@ -68,7 +69,6 @@ struct omap4_cpu_pm_info {
 	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;
 	void __iomem *l2x0_sar_addr;
-	void (*secondary_startup)(void);
 };
 };
 
 
 /**
 /**
@@ -76,6 +76,7 @@ struct omap4_cpu_pm_info {
  * @finish_suspend:	CPU suspend finisher function pointer
  * @finish_suspend:	CPU suspend finisher function pointer
  * @resume:		CPU resume function pointer
  * @resume:		CPU resume function pointer
  * @scu_prepare:	CPU Snoop Control program function pointer
  * @scu_prepare:	CPU Snoop Control program function pointer
+ * @hotplug_restart:	CPU restart function pointer
  *
  *
  * Structure holds functions pointer for CPU low power operations like
  * Structure holds functions pointer for CPU low power operations like
  * suspend, resume and scu programming.
  * suspend, resume and scu programming.
@@ -84,11 +85,13 @@ struct cpu_pm_ops {
 	int (*finish_suspend)(unsigned long cpu_state);
 	int (*finish_suspend)(unsigned long cpu_state);
 	void (*resume)(void);
 	void (*resume)(void);
 	void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state);
 	void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state);
+	void (*hotplug_restart)(void);
 };
 };
 
 
 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;
 static void __iomem *sar_base;
+static u32 cpu_context_offset;
 
 
 static int default_finish_suspend(unsigned long cpu_state)
 static int default_finish_suspend(unsigned long cpu_state)
 {
 {
@@ -106,6 +109,7 @@ struct cpu_pm_ops omap_pm_ops = {
 	.finish_suspend		= default_finish_suspend,
 	.finish_suspend		= default_finish_suspend,
 	.resume			= dummy_cpu_resume,
 	.resume			= dummy_cpu_resume,
 	.scu_prepare		= dummy_scu_prepare,
 	.scu_prepare		= dummy_scu_prepare,
+	.hotplug_restart	= dummy_cpu_resume,
 };
 };
 
 
 /*
 /*
@@ -116,7 +120,8 @@ 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);
 	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
 
 
-	writel_relaxed(addr, pm_info->wkup_sar_addr);
+	if (pm_info->wkup_sar_addr)
+		writel_relaxed(addr, pm_info->wkup_sar_addr);
 }
 }
 
 
 /*
 /*
@@ -141,7 +146,8 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
 		break;
 		break;
 	}
 	}
 
 
-	writel_relaxed(scu_pwr_st, pm_info->scu_sar_addr);
+	if (pm_info->scu_sar_addr)
+		writel_relaxed(scu_pwr_st, pm_info->scu_sar_addr);
 }
 }
 
 
 /* Helper functions for MPUSS OSWR */
 /* Helper functions for MPUSS OSWR */
@@ -161,14 +167,14 @@ static inline void cpu_clear_prev_logic_pwrst(unsigned int cpu_id)
 
 
 	if (cpu_id) {
 	if (cpu_id) {
 		reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU1_INST,
 		reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU1_INST,
-					OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET);
+					cpu_context_offset);
 		omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU1_INST,
 		omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU1_INST,
-					OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET);
+					cpu_context_offset);
 	} else {
 	} else {
 		reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU0_INST,
 		reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU0_INST,
-					OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET);
+					cpu_context_offset);
 		omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU0_INST,
 		omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU0_INST,
-					OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET);
+					cpu_context_offset);
 	}
 	}
 }
 }
 
 
@@ -179,7 +185,8 @@ 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);
 	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
 
 
-	writel_relaxed(save_state, pm_info->l2x0_sar_addr);
+	if (pm_info->l2x0_sar_addr)
+		writel_relaxed(save_state, pm_info->l2x0_sar_addr);
 }
 }
 
 
 /*
 /*
@@ -189,10 +196,14 @@ static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state)
 #ifdef CONFIG_CACHE_L2X0
 #ifdef CONFIG_CACHE_L2X0
 static void __init save_l2x0_context(void)
 static void __init save_l2x0_context(void)
 {
 {
-	writel_relaxed(l2x0_saved_regs.aux_ctrl,
-		     sar_base + L2X0_AUXCTRL_OFFSET);
-	writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
-		     sar_base + L2X0_PREFETCH_CTRL_OFFSET);
+	void __iomem *l2x0_base = omap4_get_l2cache_base();
+
+	if (l2x0_base && sar_base) {
+		writel_relaxed(l2x0_saved_regs.aux_ctrl,
+			       sar_base + L2X0_AUXCTRL_OFFSET);
+		writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
+			       sar_base + L2X0_PREFETCH_CTRL_OFFSET);
+	}
 }
 }
 #else
 #else
 static void __init save_l2x0_context(void)
 static void __init save_l2x0_context(void)
@@ -231,6 +242,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 		save_state = 1;
 		save_state = 1;
 		break;
 		break;
 	case PWRDM_POWER_RET:
 	case PWRDM_POWER_RET:
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) {
+			save_state = 0;
+			break;
+		}
 	default:
 	default:
 		/*
 		/*
 		 * CPUx CSWR is invalid hardware state. Also CPUx OSWR
 		 * CPUx CSWR is invalid hardware state. Also CPUx OSWR
@@ -307,7 +322,7 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 
 
 	pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
 	pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
 	pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
 	pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
-	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
+	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.hotplug_restart));
 	omap_pm_ops.scu_prepare(cpu, power_state);
 	omap_pm_ops.scu_prepare(cpu, power_state);
 
 
 	/*
 	/*
@@ -322,6 +337,21 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 }
 }
 
 
 
 
+/*
+ * Enable Mercury Fast HG retention mode by default.
+ */
+static void enable_mercury_retention_mode(void)
+{
+	u32 reg;
+
+	reg = omap4_prcm_mpu_read_inst_reg(OMAP54XX_PRCM_MPU_DEVICE_INST,
+				  OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET);
+	/* Enable HG_EN, HG_RAMPUP = fast mode */
+	reg |= BIT(24) | BIT(25);
+	omap4_prcm_mpu_write_inst_reg(reg, OMAP54XX_PRCM_MPU_DEVICE_INST,
+				      OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET);
+}
+
 /*
 /*
  * Initialise OMAP4 MPUSS
  * Initialise OMAP4 MPUSS
  */
  */
@@ -334,13 +364,17 @@ int __init omap4_mpuss_init(void)
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	sar_base = omap4_get_sar_ram_base();
+	if (cpu_is_omap44xx())
+		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->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
-	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0;
+	if (sar_base) {
+		pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
+		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");
@@ -355,13 +389,12 @@ int __init omap4_mpuss_init(void)
 	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
 	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
 
 
 	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->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
-	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
-	if (cpu_is_omap446x())
-		pm_info->secondary_startup = omap4460_secondary_startup;
-	else
-		pm_info->secondary_startup = omap4_secondary_startup;
+	if (sar_base) {
+		pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
+		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) {
@@ -384,20 +417,27 @@ int __init omap4_mpuss_init(void)
 	pwrdm_clear_all_prev_pwrst(mpuss_pd);
 	pwrdm_clear_all_prev_pwrst(mpuss_pd);
 	mpuss_clear_prev_logic_pwrst();
 	mpuss_clear_prev_logic_pwrst();
 
 
-	/* Save device type on scratchpad for low level code to use */
-	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
-		writel_relaxed(1, sar_base + OMAP_TYPE_OFFSET);
-	else
-		writel_relaxed(0, sar_base + OMAP_TYPE_OFFSET);
-
-	save_l2x0_context();
+	if (sar_base) {
+		/* Save device type on scratchpad for low level code to use */
+		writel_relaxed((omap_type() != OMAP2_DEVICE_TYPE_GP) ? 1 : 0,
+			       sar_base + OMAP_TYPE_OFFSET);
+		save_l2x0_context();
+	}
 
 
 	if (cpu_is_omap44xx()) {
 	if (cpu_is_omap44xx()) {
 		omap_pm_ops.finish_suspend = omap4_finish_suspend;
 		omap_pm_ops.finish_suspend = omap4_finish_suspend;
 		omap_pm_ops.resume = omap4_cpu_resume;
 		omap_pm_ops.resume = omap4_cpu_resume;
 		omap_pm_ops.scu_prepare = scu_pwrst_prepare;
 		omap_pm_ops.scu_prepare = scu_pwrst_prepare;
+		omap_pm_ops.hotplug_restart = omap4_secondary_startup;
+		cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET;
+	} else if (soc_is_omap54xx() || soc_is_dra7xx()) {
+		cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET;
+		enable_mercury_retention_mode();
 	}
 	}
 
 
+	if (cpu_is_omap446x())
+		omap_pm_ops.hotplug_restart = omap4460_secondary_startup;
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 1 - 0
arch/arm/mach-omap2/omap-secure.h

@@ -45,6 +45,7 @@
 #define OMAP4_MON_L2X0_PREFETCH_INDEX	0x113
 #define OMAP4_MON_L2X0_PREFETCH_INDEX	0x113
 
 
 #define OMAP5_DRA7_MON_SET_CNTFRQ_INDEX	0x109
 #define OMAP5_DRA7_MON_SET_CNTFRQ_INDEX	0x109
+#define OMAP5_MON_AMBA_IF_INDEX		0x108
 
 
 /* Secure PPA(Primary Protected Application) APIs */
 /* Secure PPA(Primary Protected Application) APIs */
 #define OMAP4_PPA_L2_POR_INDEX		0x23
 #define OMAP4_PPA_L2_POR_INDEX		0x23

+ 19 - 1
arch/arm/mach-omap2/omap-wakeupgen.c

@@ -32,6 +32,7 @@
 #include "soc.h"
 #include "soc.h"
 #include "omap4-sar-layout.h"
 #include "omap4-sar-layout.h"
 #include "common.h"
 #include "common.h"
+#include "pm.h"
 
 
 #define AM43XX_NR_REG_BANKS	7
 #define AM43XX_NR_REG_BANKS	7
 #define AM43XX_IRQS		224
 #define AM43XX_IRQS		224
@@ -381,7 +382,7 @@ static struct notifier_block irq_notifier_block = {
 static void __init irq_pm_init(void)
 static void __init irq_pm_init(void)
 {
 {
 	/* FIXME: Remove this when MPU OSWR support is added */
 	/* FIXME: Remove this when MPU OSWR support is added */
-	if (!soc_is_omap54xx())
+	if (!IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE))
 		cpu_pm_register_notifier(&irq_notifier_block);
 		cpu_pm_register_notifier(&irq_notifier_block);
 }
 }
 #else
 #else
@@ -406,6 +407,7 @@ int __init omap_wakeupgen_init(void)
 {
 {
 	int i;
 	int i;
 	unsigned int boot_cpu = smp_processor_id();
 	unsigned int boot_cpu = smp_processor_id();
+	u32 val;
 
 
 	/* Not supported on OMAP4 ES1.0 silicon */
 	/* Not supported on OMAP4 ES1.0 silicon */
 	if (omap_rev() == OMAP4430_REV_ES1_0) {
 	if (omap_rev() == OMAP4430_REV_ES1_0) {
@@ -451,6 +453,22 @@ int __init omap_wakeupgen_init(void)
 	for (i = 0; i < max_irqs; i++)
 	for (i = 0; i < max_irqs; i++)
 		irq_target_cpu[i] = boot_cpu;
 		irq_target_cpu[i] = boot_cpu;
 
 
+	/*
+	 * Enables OMAP5 ES2 PM Mode using ES2_PM_MODE in AMBA_IF_MODE
+	 * 0x0:	ES1 behavior, CPU cores would enter and exit OFF mode together.
+	 * 0x1:	ES2 behavior, CPU cores are allowed to enter/exit OFF mode
+	 * independently.
+	 * This needs to be set one time thanks to always ON domain.
+	 *
+	 * We do not support ES1 behavior anymore. OMAP5 is assumed to be
+	 * ES2.0, and the same is applicable for DRA7.
+	 */
+	if (soc_is_omap54xx() || soc_is_dra7xx()) {
+		val = __raw_readl(wakeupgen_base + OMAP_AMBA_IF_MODE);
+		val |= BIT(5);
+		omap_smc1(OMAP5_MON_AMBA_IF_INDEX, val);
+	}
+
 	irq_hotplug_init();
 	irq_hotplug_init();
 	irq_pm_init();
 	irq_pm_init();
 
 

+ 1 - 0
arch/arm/mach-omap2/omap-wakeupgen.h

@@ -27,6 +27,7 @@
 #define OMAP_WKG_ENB_E_1			0x420
 #define OMAP_WKG_ENB_E_1			0x420
 #define OMAP_AUX_CORE_BOOT_0			0x800
 #define OMAP_AUX_CORE_BOOT_0			0x800
 #define OMAP_AUX_CORE_BOOT_1			0x804
 #define OMAP_AUX_CORE_BOOT_1			0x804
+#define OMAP_AMBA_IF_MODE			0x80c
 #define OMAP_PTMSYNCREQ_MASK			0xc00
 #define OMAP_PTMSYNCREQ_MASK			0xc00
 #define OMAP_PTMSYNCREQ_EN			0xc04
 #define OMAP_PTMSYNCREQ_EN			0xc04
 #define OMAP_TIMESTAMPCYCLELO			0xc08
 #define OMAP_TIMESTAMPCYCLELO			0xc08

+ 10 - 0
arch/arm/mach-omap2/pdata-quirks.c

@@ -352,6 +352,16 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a100040, "4a100040.pinmux", &pcs_pdata),
 	OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a100040, "4a100040.pinmux", &pcs_pdata),
 	OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a31e040, "4a31e040.pinmux", &pcs_pdata),
 	OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a31e040, "4a31e040.pinmux", &pcs_pdata),
 #endif
 #endif
+#ifdef CONFIG_SOC_OMAP5
+	OF_DEV_AUXDATA("ti,omap5-padconf", 0x4a002840, "4a002840.pinmux", &pcs_pdata),
+	OF_DEV_AUXDATA("ti,omap5-padconf", 0x4ae0c840, "4ae0c840.pinmux", &pcs_pdata),
+#endif
+#ifdef CONFIG_SOC_DRA7XX
+	OF_DEV_AUXDATA("ti,dra7-padconf", 0x4a003400, "4a003400.pinmux", &pcs_pdata),
+#endif
+#ifdef CONFIG_SOC_AM43XX
+	OF_DEV_AUXDATA("ti,am437-padconf", 0x44e10800, "44e10800.pinmux", &pcs_pdata),
+#endif
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
 	OF_DEV_AUXDATA("ti,omap4-iommu", 0x4a066000, "4a066000.mmu",
 	OF_DEV_AUXDATA("ti,omap4-iommu", 0x4a066000, "4a066000.mmu",
 		       &omap4_iommu_pdata),
 		       &omap4_iommu_pdata),

+ 1 - 0
arch/arm/mach-omap2/pm.h

@@ -101,6 +101,7 @@ static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 #endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
 
 #define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD	(1 << 0)
 #define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD	(1 << 0)
+#define PM_OMAP4_CPU_OSWR_DISABLE		(1 << 1)
 
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
 extern u16 pm44xx_errata;
 extern u16 pm44xx_errata;

+ 43 - 5
arch/arm/mach-omap2/pm44xx.c

@@ -37,6 +37,8 @@ struct power_state {
 	struct list_head node;
 	struct list_head node;
 };
 };
 
 
+static u32 cpu_suspend_state = PWRDM_POWER_OFF;
+
 static LIST_HEAD(pwrst_list);
 static LIST_HEAD(pwrst_list);
 
 
 #ifdef CONFIG_SUSPEND
 #ifdef CONFIG_SUSPEND
@@ -67,7 +69,7 @@ static int omap4_pm_suspend(void)
 	 * domain CSWR is not supported by hardware.
 	 * domain CSWR is not supported by hardware.
 	 * More details can be found in OMAP4430 TRM section 4.3.4.2.
 	 * More details can be found in OMAP4430 TRM section 4.3.4.2.
 	 */
 	 */
-	omap4_enter_lowpower(cpu_id, PWRDM_POWER_OFF);
+	omap4_enter_lowpower(cpu_id, cpu_suspend_state);
 
 
 	/* Restore next powerdomain state */
 	/* Restore next powerdomain state */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 	list_for_each_entry(pwrst, &pwrst_list, node) {
@@ -113,8 +115,11 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	 * through hotplug path and CPU0 explicitly programmed
 	 * through hotplug path and CPU0 explicitly programmed
 	 * further down in the code path
 	 * further down in the code path
 	 */
 	 */
-	if (!strncmp(pwrdm->name, "cpu", 3))
+	if (!strncmp(pwrdm->name, "cpu", 3)) {
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE))
+			cpu_suspend_state = PWRDM_POWER_RET;
 		return 0;
 		return 0;
+	}
 
 
 	pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
 	pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
 	if (!pwrst)
 	if (!pwrst)
@@ -207,6 +212,32 @@ static inline int omap4_init_static_deps(void)
 	return ret;
 	return ret;
 }
 }
 
 
+/**
+ * omap5_dra7_init_static_deps - Init static clkdm dependencies on OMAP5 and
+ *				 DRA7
+ *
+ * The dynamic dependency between MPUSS -> EMIF is broken and has
+ * not worked as expected. The hardware recommendation is to
+ * enable static dependencies for these to avoid system
+ * lock ups or random crashes.
+ */
+static inline int omap5_dra7_init_static_deps(void)
+{
+	struct clockdomain *mpuss_clkdm, *emif_clkdm;
+	int ret;
+
+	mpuss_clkdm = clkdm_lookup("mpu_clkdm");
+	emif_clkdm = clkdm_lookup("emif_clkdm");
+	if (!mpuss_clkdm || !emif_clkdm)
+		return -EINVAL;
+
+	ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm);
+	if (ret)
+		pr_err("Failed to add MPUSS -> EMIF wakeup dependency\n");
+
+	return ret;
+}
+
 /**
 /**
  * omap4_pm_init_early - Does early initialization necessary for OMAP4+ devices
  * omap4_pm_init_early - Does early initialization necessary for OMAP4+ devices
  *
  *
@@ -217,6 +248,9 @@ int __init omap4_pm_init_early(void)
 	if (cpu_is_omap446x())
 	if (cpu_is_omap446x())
 		pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD;
 		pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD;
 
 
+	if (soc_is_omap54xx() || soc_is_dra7xx())
+		pm44xx_errata |= PM_OMAP4_CPU_OSWR_DISABLE;
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -244,10 +278,14 @@ int __init omap4_pm_init(void)
 		goto err2;
 		goto err2;
 	}
 	}
 
 
-	if (cpu_is_omap44xx()) {
+	if (cpu_is_omap44xx())
 		ret = omap4_init_static_deps();
 		ret = omap4_init_static_deps();
-		if (ret)
-			goto err2;
+	else if (soc_is_omap54xx() || soc_is_dra7xx())
+		ret = omap5_dra7_init_static_deps();
+
+	if (ret) {
+		pr_err("Failed to initialise static dependencies.\n");
+		goto err2;
 	}
 	}
 
 
 	ret = omap4_mpuss_init();
 	ret = omap4_mpuss_init();

+ 18 - 0
arch/arm/mach-omap2/prm3xxx.c

@@ -17,6 +17,7 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irq.h>
+#include <linux/of_irq.h>
 
 
 #include "soc.h"
 #include "soc.h"
 #include "common.h"
 #include "common.h"
@@ -649,6 +650,11 @@ int __init omap3xxx_prm_init(void)
 	return prm_register(&omap3xxx_prm_ll_data);
 	return prm_register(&omap3xxx_prm_ll_data);
 }
 }
 
 
+static struct of_device_id omap3_prm_dt_match_table[] = {
+	{ .compatible = "ti,omap3-prm" },
+	{ }
+};
+
 static int omap3xxx_prm_late_init(void)
 static int omap3xxx_prm_late_init(void)
 {
 {
 	int ret;
 	int ret;
@@ -656,6 +662,18 @@ static int omap3xxx_prm_late_init(void)
 	if (!(prm_features & PRM_HAS_IO_WAKEUP))
 	if (!(prm_features & PRM_HAS_IO_WAKEUP))
 		return 0;
 		return 0;
 
 
+	if (of_have_populated_dt()) {
+		struct device_node *np;
+		int irq_num;
+
+		np = of_find_matching_node(NULL, omap3_prm_dt_match_table);
+		if (np) {
+			irq_num = of_irq_get(np, 0);
+			if (irq_num >= 0)
+				omap3_prcm_irq_setup.irq = irq_num;
+		}
+	}
+
 	omap3xxx_prm_enable_io_wakeup();
 	omap3xxx_prm_enable_io_wakeup();
 	ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
 	ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
 	if (!ret)
 	if (!ret)

+ 79 - 11
arch/arm/mach-omap2/prm44xx.c

@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/of_irq.h>
 
 
 
 
 #include "soc.h"
 #include "soc.h"
@@ -32,7 +33,6 @@
 /* Static data */
 /* Static data */
 
 
 static const struct omap_prcm_irq omap4_prcm_irqs[] = {
 static const struct omap_prcm_irq omap4_prcm_irqs[] = {
-	OMAP_PRCM_IRQ("wkup",   0,      0),
 	OMAP_PRCM_IRQ("io",     9,      1),
 	OMAP_PRCM_IRQ("io",     9,      1),
 };
 };
 
 
@@ -154,21 +154,36 @@ void omap4_prm_vp_clear_txdone(u8 vp_id)
 
 
 u32 omap4_prm_vcvp_read(u8 offset)
 u32 omap4_prm_vcvp_read(u8 offset)
 {
 {
+	s32 inst = omap4_prmst_get_prm_dev_inst();
+
+	if (inst == PRM_INSTANCE_UNKNOWN)
+		return 0;
+
 	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
 	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
-					   OMAP4430_PRM_DEVICE_INST, offset);
+					   inst, offset);
 }
 }
 
 
 void omap4_prm_vcvp_write(u32 val, u8 offset)
 void omap4_prm_vcvp_write(u32 val, u8 offset)
 {
 {
+	s32 inst = omap4_prmst_get_prm_dev_inst();
+
+	if (inst == PRM_INSTANCE_UNKNOWN)
+		return;
+
 	omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
 	omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION,
-				     OMAP4430_PRM_DEVICE_INST, offset);
+				     inst, offset);
 }
 }
 
 
 u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
 u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
 {
 {
+	s32 inst = omap4_prmst_get_prm_dev_inst();
+
+	if (inst == PRM_INSTANCE_UNKNOWN)
+		return 0;
+
 	return omap4_prminst_rmw_inst_reg_bits(mask, bits,
 	return omap4_prminst_rmw_inst_reg_bits(mask, bits,
 					       OMAP4430_PRM_PARTITION,
 					       OMAP4430_PRM_PARTITION,
-					       OMAP4430_PRM_DEVICE_INST,
+					       inst,
 					       offset);
 					       offset);
 }
 }
 
 
@@ -275,14 +290,18 @@ void omap44xx_prm_restore_irqen(u32 *saved_mask)
 void omap44xx_prm_reconfigure_io_chain(void)
 void omap44xx_prm_reconfigure_io_chain(void)
 {
 {
 	int i = 0;
 	int i = 0;
+	s32 inst = omap4_prmst_get_prm_dev_inst();
+
+	if (inst == PRM_INSTANCE_UNKNOWN)
+		return;
 
 
 	/* Trigger WUCLKIN enable */
 	/* Trigger WUCLKIN enable */
 	omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
 	omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
 				    OMAP4430_WUCLK_CTRL_MASK,
 				    OMAP4430_WUCLK_CTRL_MASK,
-				    OMAP4430_PRM_DEVICE_INST,
+				    inst,
 				    OMAP4_PRM_IO_PMCTRL_OFFSET);
 				    OMAP4_PRM_IO_PMCTRL_OFFSET);
 	omap_test_timeout(
 	omap_test_timeout(
-		(((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+		(((omap4_prm_read_inst_reg(inst,
 					   OMAP4_PRM_IO_PMCTRL_OFFSET) &
 					   OMAP4_PRM_IO_PMCTRL_OFFSET) &
 		   OMAP4430_WUCLK_STATUS_MASK) >>
 		   OMAP4430_WUCLK_STATUS_MASK) >>
 		  OMAP4430_WUCLK_STATUS_SHIFT) == 1),
 		  OMAP4430_WUCLK_STATUS_SHIFT) == 1),
@@ -292,10 +311,10 @@ void omap44xx_prm_reconfigure_io_chain(void)
 
 
 	/* Trigger WUCLKIN disable */
 	/* Trigger WUCLKIN disable */
 	omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
 	omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
-				    OMAP4430_PRM_DEVICE_INST,
+				    inst,
 				    OMAP4_PRM_IO_PMCTRL_OFFSET);
 				    OMAP4_PRM_IO_PMCTRL_OFFSET);
 	omap_test_timeout(
 	omap_test_timeout(
-		(((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+		(((omap4_prm_read_inst_reg(inst,
 					   OMAP4_PRM_IO_PMCTRL_OFFSET) &
 					   OMAP4_PRM_IO_PMCTRL_OFFSET) &
 		   OMAP4430_WUCLK_STATUS_MASK) >>
 		   OMAP4430_WUCLK_STATUS_MASK) >>
 		  OMAP4430_WUCLK_STATUS_SHIFT) == 0),
 		  OMAP4430_WUCLK_STATUS_SHIFT) == 0),
@@ -316,9 +335,14 @@ void omap44xx_prm_reconfigure_io_chain(void)
  */
  */
 static void __init omap44xx_prm_enable_io_wakeup(void)
 static void __init omap44xx_prm_enable_io_wakeup(void)
 {
 {
+	s32 inst = omap4_prmst_get_prm_dev_inst();
+
+	if (inst == PRM_INSTANCE_UNKNOWN)
+		return;
+
 	omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
 	omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
 				    OMAP4430_GLOBAL_WUEN_MASK,
 				    OMAP4430_GLOBAL_WUEN_MASK,
-				    OMAP4430_PRM_DEVICE_INST,
+				    inst,
 				    OMAP4_PRM_IO_PMCTRL_OFFSET);
 				    OMAP4_PRM_IO_PMCTRL_OFFSET);
 }
 }
 
 
@@ -333,8 +357,13 @@ static u32 omap44xx_prm_read_reset_sources(void)
 	struct prm_reset_src_map *p;
 	struct prm_reset_src_map *p;
 	u32 r = 0;
 	u32 r = 0;
 	u32 v;
 	u32 v;
+	s32 inst = omap4_prmst_get_prm_dev_inst();
 
 
-	v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+	if (inst == PRM_INSTANCE_UNKNOWN)
+		return 0;
+
+
+	v = omap4_prm_read_inst_reg(inst,
 				    OMAP4_RM_RSTST);
 				    OMAP4_RM_RSTST);
 
 
 	p = omap44xx_prm_reset_src_map;
 	p = omap44xx_prm_reset_src_map;
@@ -664,17 +693,56 @@ static struct prm_ll_data omap44xx_prm_ll_data = {
 
 
 int __init omap44xx_prm_init(void)
 int __init omap44xx_prm_init(void)
 {
 {
-	if (cpu_is_omap44xx())
+	if (cpu_is_omap44xx() || soc_is_omap54xx() || soc_is_dra7xx())
 		prm_features |= PRM_HAS_IO_WAKEUP;
 		prm_features |= PRM_HAS_IO_WAKEUP;
 
 
 	return prm_register(&omap44xx_prm_ll_data);
 	return prm_register(&omap44xx_prm_ll_data);
 }
 }
 
 
+static struct of_device_id omap_prm_dt_match_table[] = {
+	{ .compatible = "ti,omap4-prm" },
+	{ .compatible = "ti,omap5-prm" },
+	{ .compatible = "ti,dra7-prm" },
+	{ }
+};
+
 static int omap44xx_prm_late_init(void)
 static int omap44xx_prm_late_init(void)
 {
 {
+	struct device_node *np;
+	int irq_num;
+
 	if (!(prm_features & PRM_HAS_IO_WAKEUP))
 	if (!(prm_features & PRM_HAS_IO_WAKEUP))
 		return 0;
 		return 0;
 
 
+	/* OMAP4+ is DT only now */
+	if (!of_have_populated_dt())
+		return 0;
+
+	np = of_find_matching_node(NULL, omap_prm_dt_match_table);
+
+	if (!np) {
+		/* Default loaded up with OMAP4 values */
+		if (!cpu_is_omap44xx())
+			return 0;
+	} else {
+		irq_num = of_irq_get(np, 0);
+		/*
+		 * Already have OMAP4 IRQ num. For all other platforms, we need
+		 * IRQ numbers from DT
+		 */
+		if (irq_num < 0 && !cpu_is_omap44xx()) {
+			if (irq_num == -EPROBE_DEFER)
+				return irq_num;
+
+			/* Have nothing to do */
+			return 0;
+		}
+
+		/* Once OMAP4 DT is filled as well */
+		if (irq_num >= 0)
+			omap4_prcm_irq_setup.irq = irq_num;
+	}
+
 	omap44xx_prm_enable_io_wakeup();
 	omap44xx_prm_enable_io_wakeup();
 
 
 	return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
 	return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);

+ 25 - 15
arch/arm/mach-omap2/prminst44xx.c

@@ -31,6 +31,8 @@
 
 
 static void __iomem *_prm_bases[OMAP4_MAX_PRCM_PARTITIONS];
 static void __iomem *_prm_bases[OMAP4_MAX_PRCM_PARTITIONS];
 
 
+static s32 prm_dev_inst = PRM_INSTANCE_UNKNOWN;
+
 /**
 /**
  * omap_prm_base_init - Populates the prm partitions
  * omap_prm_base_init - Populates the prm partitions
  *
  *
@@ -43,6 +45,24 @@ void omap_prm_base_init(void)
 	_prm_bases[OMAP4430_PRCM_MPU_PARTITION] = prcm_mpu_base;
 	_prm_bases[OMAP4430_PRCM_MPU_PARTITION] = prcm_mpu_base;
 }
 }
 
 
+s32 omap4_prmst_get_prm_dev_inst(void)
+{
+	if (prm_dev_inst != PRM_INSTANCE_UNKNOWN)
+		return prm_dev_inst;
+
+	/* This cannot be done way early at boot.. as things are not setup */
+	if (cpu_is_omap44xx())
+		prm_dev_inst = OMAP4430_PRM_DEVICE_INST;
+	else if (soc_is_omap54xx())
+		prm_dev_inst = OMAP54XX_PRM_DEVICE_INST;
+	else if (soc_is_dra7xx())
+		prm_dev_inst = DRA7XX_PRM_DEVICE_INST;
+	else if (soc_is_am43xx())
+		prm_dev_inst = AM43XX_PRM_DEVICE_INST;
+
+	return prm_dev_inst;
+}
+
 /* Read a register in a PRM instance */
 /* Read a register in a PRM instance */
 u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
 u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
 {
 {
@@ -169,28 +189,18 @@ int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
 void omap4_prminst_global_warm_sw_reset(void)
 void omap4_prminst_global_warm_sw_reset(void)
 {
 {
 	u32 v;
 	u32 v;
-	s16 dev_inst;
+	s32 inst = omap4_prmst_get_prm_dev_inst();
 
 
-	if (cpu_is_omap44xx())
-		dev_inst = OMAP4430_PRM_DEVICE_INST;
-	else if (soc_is_omap54xx())
-		dev_inst = OMAP54XX_PRM_DEVICE_INST;
-	else if (soc_is_dra7xx())
-		dev_inst = DRA7XX_PRM_DEVICE_INST;
-	else if (soc_is_am43xx())
-		dev_inst = AM43XX_PRM_DEVICE_INST;
-	else
+	if (inst == PRM_INSTANCE_UNKNOWN)
 		return;
 		return;
 
 
-	v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, dev_inst,
+	v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, inst,
 					OMAP4_PRM_RSTCTRL_OFFSET);
 					OMAP4_PRM_RSTCTRL_OFFSET);
 	v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
 	v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
 	omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
 	omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
-				 dev_inst,
-				 OMAP4_PRM_RSTCTRL_OFFSET);
+				 inst, OMAP4_PRM_RSTCTRL_OFFSET);
 
 
 	/* OCP barrier */
 	/* OCP barrier */
 	v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
 	v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
-				    dev_inst,
-				    OMAP4_PRM_RSTCTRL_OFFSET);
+				    inst, OMAP4_PRM_RSTCTRL_OFFSET);
 }
 }

+ 3 - 0
arch/arm/mach-omap2/prminst44xx.h

@@ -12,6 +12,9 @@
 #ifndef __ARCH_ASM_MACH_OMAP2_PRMINST44XX_H
 #ifndef __ARCH_ASM_MACH_OMAP2_PRMINST44XX_H
 #define __ARCH_ASM_MACH_OMAP2_PRMINST44XX_H
 #define __ARCH_ASM_MACH_OMAP2_PRMINST44XX_H
 
 
+#define PRM_INSTANCE_UNKNOWN	-1
+extern s32 omap4_prmst_get_prm_dev_inst(void);
+
 /*
 /*
  * In an ideal world, we would not export these low-level functions,
  * In an ideal world, we would not export these low-level functions,
  * but this will probably take some time to fix properly
  * but this will probably take some time to fix properly