| 
					
				 | 
			
			
				@@ -0,0 +1,155 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * OMAP3 Power Management Routines 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Copyright (C) 2006-2008 Nokia Corporation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Tony Lindgren <tony@atomide.com> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Jouni Hogander 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Copyright (C) 2007 Texas Instruments, Inc. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Rajendra Nayak <rnayak@ti.com> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Copyright (C) 2005 Texas Instruments, Inc. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Richard Woodruff <r-woodruff2@ti.com> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Based on pm.c for omap1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * This program is free software; you can redistribute it and/or modify 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * it under the terms of the GNU General Public License version 2 as 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * published by the Free Software Foundation. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/pm.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/suspend.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/interrupt.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/module.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/list.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/err.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/gpio.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/clk.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/delay.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/slab.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/omap-dma.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <linux/platform_data/gpio-omap.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <trace/events/power.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <asm/fncpy.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <asm/suspend.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <asm/system_misc.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "clockdomain.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "powerdomain.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "soc.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "common.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "cm3xxx.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "cm-regbits-34xx.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "gpmc.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "prm-regbits-34xx.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "prm3xxx.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "pm.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "sdrc.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "sram.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "control.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* pm34xx errata defined in pm.h */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+u16 pm34xx_errata; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct power_state { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct powerdomain *pwrdm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 next_state; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef CONFIG_SUSPEND 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 saved_state; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct list_head node; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static LIST_HEAD(pwrst_list); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int (*_omap_save_secure_sram)(u32 *addr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void (*omap3_do_wfi_sram)(void); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct powerdomain *mpu_pwrdm, *neon_pwrdm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct powerdomain *core_pwrdm, *per_pwrdm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void omap3_core_save_context(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap3_ctrl_save_padconf(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * Force write last pad into memory, as this can fail in some 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * cases according to errata 1.157, 1.185 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap_ctrl_writel(omap_ctrl_readl(OMAP343X_PADCONF_ETK_D14), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		OMAP343X_CONTROL_MEM_WKUP + 0x2a0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Save the Interrupt controller context */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap_intc_save_context(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Save the GPMC context */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap3_gpmc_save_context(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Save the system control module context, padconf already save above*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap3_control_save_context(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap_dma_global_context_save(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void omap3_core_restore_context(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Restore the control module context, padconf restored by h/w */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap3_control_restore_context(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Restore the GPMC context */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap3_gpmc_restore_context(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* Restore the interrupt controller context */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap_intc_restore_context(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	omap_dma_global_context_restore(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * FIXME: This function should be called before entering off-mode after 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * OMAP3 secure services have been accessed. Currently it is only called 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * once during boot sequence, but this works as we are not using secure 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * services. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void omap3_save_secure_ram_context(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (omap_type() != OMAP2_DEVICE_TYPE_GP) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * MPU next state must be set to POWER_ON temporarily, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * otherwise the WFI executed inside the ROM code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 * will hang the system. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ret = _omap_save_secure_sram((u32 *) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				__pa(omap3_secure_ram_storage)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/* Following is for error tracking, it should not happen */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (ret) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			pr_err("save_secure_sram() returns %08x\n", ret); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			while (1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * PRCM Interrupt Handler Helper Function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * The purpose of this function is to clear any wake-up events latched 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * in the PRCM PM_WKST_x registers. It is possible that a wake-up event 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * may occur whilst attempting to clear a PM_WKST_x register and thus 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * set another bit in this register. A while loop is used to ensure 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * that any peripheral wake-up events occurring while attempting to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * clear the PM_WKST_x are detected and cleared. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u32 wkst, fclk, iclk, clken; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u16 iclk_off = (regs == 3) ? CM_ICLKEN3 : CM_ICLKEN1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	u16 grpsel_off = (regs == 3) ? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		OMAP3430ES2_PM_MPUGRPSEL3 : OMAP3430_PM_MPUGRPSEL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int c = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	wkst = omap2_prm_read_mod_reg(module, wkst_off); 
			 |