diff options
author | Vijaya Kumar Kilari <vijay.kilari@stericsson.com> | 2011-06-17 12:14:06 +0530 |
---|---|---|
committer | said m bagheri <ebgheri@steludxu2848.(none)> | 2011-06-29 10:30:29 +0200 |
commit | 69089ef0e5f86dc6df052e57862ff2cb3c8e854c (patch) | |
tree | 77ae2aa9731217def1da6365871ea1fb838c30d6 | |
parent | b46be45033679cf1da17c522ecea92fb7a1dbe44 (diff) |
U5500: Add support for power state transition
PRCMU driver is updated to provide API for
system power state transition
ST-Ericsson Linux next: -
ST-Ericsson ID: 334774
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: I38dc2ef4f1ba9fd5e2ca0558fc4653b952f2fcef
Signed-off-by: Vijaya Kumar K <vijay.kilari@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24974
Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
-rw-r--r-- | arch/arm/mach-ux500/include/mach/prcmu-db5500.h | 20 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/prcmu-db8500.h | 32 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/prcmu.h | 32 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/suspend.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-ux500/prcmu-db5500.c | 78 | ||||
-rw-r--r-- | arch/arm/mach-ux500/prcmu-db8500.c | 2 |
6 files changed, 131 insertions, 36 deletions
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-db5500.h b/arch/arm/mach-ux500/include/mach/prcmu-db5500.h index 10747dd08d6..6e786bf0522 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu-db5500.h +++ b/arch/arm/mach-ux500/include/mach/prcmu-db5500.h @@ -22,12 +22,9 @@ int db5500_prcmu_enable_dsipll(void); void db5500_prcmu_config_abb_event_readout(u32 abb_events); void db5500_prcmu_get_abb_event_buffer(void __iomem **buf); int prcmu_resetout(u8 resoutn, u8 state); - -static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, - bool keep_ap_pll) -{ - return 0; -} +int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, + bool keep_ap_pll); +int db5500_prcmu_config_esram0_deep_sleep(u8 state); static inline void db5500_prcmu_system_reset(u16 reset_code) {} @@ -62,6 +59,11 @@ static inline int db5500_prcmu_enable_dsipll(void) return 0; } +static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state) +{ + return 0; +} + static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {} static inline int prcmu_resetout(u8 resoutn, u8 state) @@ -77,6 +79,12 @@ static inline int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state) static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {} static inline void db5500_prcmu_config_abb_event_readout(u32 abb_events) {} +static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, + bool keep_ap_pll) +{ + return 0; +} + #endif /* CONFIG_UX500_SOC_DB5500 */ #endif /* __MACH_PRCMU_U5500_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu-db8500.h b/arch/arm/mach-ux500/include/mach/prcmu-db8500.h index 3ebf8274312..4ba3b15d8fa 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu-db8500.h +++ b/arch/arm/mach-ux500/include/mach/prcmu-db8500.h @@ -81,26 +81,6 @@ enum hw_acc_dev{ NUM_HW_ACC }; -/* - * Definitions for controlling ESRAM0 in deep sleep. - */ -#define ESRAM0_DEEP_SLEEP_STATE_OFF 1 -#define ESRAM0_DEEP_SLEEP_STATE_RET 2 - -/** - * enum ddr_pwrst - DDR power states definition - * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged - * @DDR_PWR_STATE_ON: - * @DDR_PWR_STATE_OFFLOWLAT: - * @DDR_PWR_STATE_OFFHIGHLAT: - */ -enum ddr_pwrst { - DDR_PWR_STATE_UNCHANGED = 0x00, - DDR_PWR_STATE_ON = 0x01, - DDR_PWR_STATE_OFFLOWLAT = 0x02, - DDR_PWR_STATE_OFFHIGHLAT = 0x03 -}; - /** * enum hw_acc_state - State definition for hardware accelerator * @HW_NO_CHANGE: The hardware accelerator state must remain unchanged @@ -198,7 +178,6 @@ enum romcode_read prcmu_get_rc_p2a(void); enum ap_pwrst prcmu_get_xp70_current_state(void); /* TODO: Common API with DB5500? */ -int prcmu_config_esram0_deep_sleep(u8 state); bool prcmu_has_arm_maxopp(void); int prcmu_config_hotdog(u8 threshold); int prcmu_config_hotmon(u8 low, u8 high); @@ -218,6 +197,7 @@ int db8500_prcmu_disable_dsipll(void); int db8500_prcmu_enable_dsipll(void); void db8500_prcmu_config_abb_event_readout(u32 abb_events); void db8500_prcmu_get_abb_event_buffer(void __iomem **buf); +int db8500_prcmu_config_esram0_deep_sleep(u8 state); #else /* !CONFIG_UX500_SOC_DB8500 */ @@ -271,11 +251,6 @@ static inline enum ap_pwrst prcmu_get_xp70_current_state(void) return AP_EXECUTE; } -static inline int prcmu_config_esram0_deep_sleep(u8 state) -{ - return 0; -} - static inline bool prcmu_has_arm_maxopp(void) { return false; @@ -345,6 +320,11 @@ static inline int db8500_prcmu_enable_dsipll(void) return 0; } +static inline int db8500_prcmu_config_esram0_deep_sleep(u8 state) +{ + return 0; +} + static inline void db8500_prcmu_config_abb_event_readout(u32 abb_events) {} static inline void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) {} diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h index 67fe875e0a6..bf26f0c3408 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu.h +++ b/arch/arm/mach-ux500/include/mach/prcmu.h @@ -202,6 +202,26 @@ enum ddr_opp { DDR_25_OPP = 0x02, }; +/* + * Definitions for controlling ESRAM0 in deep sleep. + */ +#define ESRAM0_DEEP_SLEEP_STATE_OFF 1 +#define ESRAM0_DEEP_SLEEP_STATE_RET 2 + +/** + * enum ddr_pwrst - DDR power states definition + * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged + * @DDR_PWR_STATE_ON: + * @DDR_PWR_STATE_OFFLOWLAT: + * @DDR_PWR_STATE_OFFHIGHLAT: + */ +enum ddr_pwrst { + DDR_PWR_STATE_UNCHANGED = 0x00, + DDR_PWR_STATE_ON = 0x01, + DDR_PWR_STATE_OFFLOWLAT = 0x02, + DDR_PWR_STATE_OFFHIGHLAT = 0x03 +}; + #include <mach/prcmu-db8500.h> #include <mach/prcmu-db5500.h> @@ -314,6 +334,13 @@ static inline int prcmu_enable_dsipll(void) return db8500_prcmu_enable_dsipll(); } +static inline int prcmu_config_esram0_deep_sleep(u8 state) +{ + if (machine_is_u5500()) + return db5500_prcmu_config_esram0_deep_sleep(state); + else + return db8500_prcmu_config_esram0_deep_sleep(state); +} #else static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, @@ -414,6 +441,11 @@ static inline int prcmu_enable_dsipll(void) return 0; } +static inline int prcmu_config_esram0_deep_sleep(u8 state) +{ + return 0; +} + static inline void prcmu_config_abb_event_readout(u32 abb_events) {} static inline void prcmu_get_abb_event_buffer(void __iomem **buf) diff --git a/arch/arm/mach-ux500/pm/suspend.c b/arch/arm/mach-ux500/pm/suspend.c index 7fa17631796..1f50fec5958 100644 --- a/arch/arm/mach-ux500/pm/suspend.c +++ b/arch/arm/mach-ux500/pm/suspend.c @@ -171,7 +171,8 @@ static int ux500_suspend_enter(suspend_state_t state) if (ux500_suspend_sleep_enabled()) return suspend(false); /* For debugging, if Sleep and DeepSleep disabled, do Idle */ - prcmu_set_power_state(PRCMU_AP_IDLE, true, true); + if (!cpu_is_u5500()) + prcmu_set_power_state(PRCMU_AP_IDLE, true, true); } dsb(); diff --git a/arch/arm/mach-ux500/prcmu-db5500.c b/arch/arm/mach-ux500/prcmu-db5500.c index b169867892c..766a59fb634 100644 --- a/arch/arm/mach-ux500/prcmu-db5500.c +++ b/arch/arm/mach-ux500/prcmu-db5500.c @@ -68,9 +68,10 @@ /* Mailbox 0 REQs */ #define PRCM_REQ_MB0_AP_POWER_STATE (PRCM_REQ_MB0 + 0x0) -#define PRCM_REQ_MB0_AP_PLL_STATE (PRCM_REQ_MB0 + 0x1) -#define PRCM_REQ_MB0_ULP_CLOCK_STATE (PRCM_REQ_MB0 + 0x2) +#define PRCM_REQ_MB0_ULP_CLOCK_STATE (PRCM_REQ_MB0 + 0x1) +#define PRCM_REQ_MB0_AP_PLL_STATE (PRCM_REQ_MB0 + 0x2) #define PRCM_REQ_MB0_DDR_STATE (PRCM_REQ_MB0 + 0x3) +#define PRCM_REQ_MB0_ESRAM0_STATE (PRCM_REQ_MB0 + 0x4) #define PRCM_REQ_MB0_WAKEUP_DBB (PRCM_REQ_MB0 + 0x8) #define PRCM_REQ_MB0_WAKEUP_ABB (PRCM_REQ_MB0 + 0xC) @@ -150,6 +151,18 @@ enum db5500_prcmu_pll { DB5500_NUM_PLL_ID, }; +enum on_off_ret { + OFF_ST, + RET_ST, + ON_ST, +}; + +enum db5500_ap_pwr_state { + DB5500_AP_SLEEP = 2, + DB5500_AP_DEEP_SLEEP, + DB5500_AP_IDLE, +}; + /* Request mailbox 3 fields */ #define PRCM_REQ_MB3_REFCLK_MGT (PRCM_REQ_MB3 + 0x0) @@ -563,6 +576,67 @@ static void config_wakeups(void) last_abb_events = abb_events; } +int db5500_prcmu_config_esram0_deep_sleep(u8 state) +{ + unsigned long flags; + + if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || + (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) + return -EINVAL; + + spin_lock_irqsave(&mb0_transfer.lock, flags); + + if (state == ESRAM0_DEEP_SLEEP_STATE_RET) + writeb(RET_ST, PRCM_REQ_MB0_ESRAM0_STATE); + else + writeb(OFF_ST, PRCM_REQ_MB0_ESRAM0_STATE); + + spin_unlock_irqrestore(&mb0_transfer.lock, flags); + + return 0; +} + +int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) +{ + int r = 0; + unsigned long flags; + + /* Deep Idle is not supported in U5500 */ + BUG_ON((state < PRCMU_AP_SLEEP) || (state >= PRCMU_AP_DEEP_IDLE)); + + spin_lock_irqsave(&mb0_transfer.lock, flags); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) + cpu_relax(); + + switch (state) { + case PRCMU_AP_IDLE: + writeb(DB5500_AP_IDLE, PRCM_REQ_MB0_AP_POWER_STATE); + /* TODO: Can be high latency */ + writeb(DDR_PWR_STATE_OFFLOWLAT, PRCM_REQ_MB0_DDR_STATE); + break; + case PRCMU_AP_SLEEP: + writeb(DB5500_AP_SLEEP, PRCM_REQ_MB0_AP_POWER_STATE); + break; + case PRCMU_AP_DEEP_SLEEP: + writeb(DB5500_AP_DEEP_SLEEP, PRCM_REQ_MB0_AP_POWER_STATE); + break; + default: + r = -EINVAL; + goto unlock_return; + } + writeb((keep_ap_pll ? 1 : 0), PRCM_REQ_MB0_AP_PLL_STATE); + writeb((keep_ulp_clk ? 1 : 0), PRCM_REQ_MB0_ULP_CLOCK_STATE); + + writeb(MB0H_PWR_STATE_TRANS, PRCM_REQ_MB0_HEADER); + writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + +unlock_return: + spin_unlock_irqrestore(&mb0_transfer.lock, flags); + + return r; +} + void db5500_prcmu_enable_wakeups(u32 wakeups) { unsigned long flags; diff --git a/arch/arm/mach-ux500/prcmu-db8500.c b/arch/arm/mach-ux500/prcmu-db8500.c index 5e4d96d0de9..58f5ec330f7 100644 --- a/arch/arm/mach-ux500/prcmu-db8500.c +++ b/arch/arm/mach-ux500/prcmu-db8500.c @@ -1450,7 +1450,7 @@ int db8500_prcmu_request_clock(u8 clock, bool enable) return -EINVAL; } -int prcmu_config_esram0_deep_sleep(u8 state) +int db8500_prcmu_config_esram0_deep_sleep(u8 state) { if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) |