aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVijaya Kumar Kilari <vijay.kilari@stericsson.com>2011-06-17 12:14:06 +0530
committersaid m bagheri <ebgheri@steludxu2848.(none)>2011-06-29 10:30:29 +0200
commit69089ef0e5f86dc6df052e57862ff2cb3c8e854c (patch)
tree77ae2aa9731217def1da6365871ea1fb838c30d6
parentb46be45033679cf1da17c522ecea92fb7a1dbe44 (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.h20
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu-db8500.h32
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu.h32
-rw-r--r--arch/arm/mach-ux500/pm/suspend.c3
-rw-r--r--arch/arm/mach-ux500/prcmu-db5500.c78
-rw-r--r--arch/arm/mach-ux500/prcmu-db8500.c2
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))