From: "Rajendra Nayak" <rnayak@ti.com>
To: linux-omap@vger.kernel.org
Subject: [PATCH 02/11] per/neon and core handling in idle
Date: Tue, 1 Jul 2008 19:46:10 +0530 [thread overview]
Message-ID: <003f01c8db85$02c99dc0$68bf18ac@ent.ti.com> (raw)
This patches adds handling of PER/NEON and CORE domain in idle.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
arch/arm/mach-omap2/cpuidle34xx.c | 98 +++++++++++++++++++++++++++++++-------
arch/arm/mach-omap2/cpuidle34xx.h | 6 +-
arch/arm/mach-omap2/pm34xx.c | 58 ++++++++++++++--------
3 files changed, 121 insertions(+), 41 deletions(-)
Index: linux-omap-2.6/arch/arm/mach-omap2/cpuidle34xx.c
===================================================================
--- linux-omap-2.6.orig/arch/arm/mach-omap2/cpuidle34xx.c 2008-07-01 18:48:09.962433167 +0530
+++ linux-omap-2.6/arch/arm/mach-omap2/cpuidle34xx.c 2008-07-01 18:48:12.884339399 +0530
@@ -26,6 +26,8 @@
#include <asm/arch/pm.h>
#include <asm/arch/prcm.h>
#include <asm/arch/powerdomain.h>
+#include <asm/arch/clockdomain.h>
+#include <asm/arch/gpio.h>
#include "cpuidle34xx.h"
#ifdef CONFIG_CPU_IDLE
@@ -35,6 +37,8 @@ struct omap3_processor_cx current_cx_sta
static int omap3_idle_bm_check(void)
{
+ if (!omap3_can_sleep())
+ return 1;
return 0;
}
@@ -46,34 +50,86 @@ static int omap3_enter_idle(struct cpuid
{
struct omap3_processor_cx *cx = cpuidle_get_statedata(state);
struct timespec ts_preidle, ts_postidle, ts_idle;
- struct powerdomain *mpu_pd;
+ struct powerdomain *mpu_pd, *core_pd, *per_pd, *neon_pd;
+ int per_pwrst, neon_pwrst;
current_cx_state = *cx;
- /* Used to keep track of the total time in idle */
- getnstimeofday(&ts_preidle);
-
-
if (cx->type == OMAP3_STATE_C0) {
/* Do nothing for C0, not even a wfi */
return 0;
}
+ /* Used to keep track of the total time in idle */
+ getnstimeofday(&ts_preidle);
+
mpu_pd = pwrdm_lookup("mpu_pwrdm");
+ core_pd = pwrdm_lookup("core_pwrdm");
+ per_pd = pwrdm_lookup("per_pwrdm");
+ neon_pd = pwrdm_lookup("neon_pwrdm");
+
+ /* Reset previous power state registers */
+ pwrdm_clear_all_prev_pwrst(mpu_pd);
+ pwrdm_clear_all_prev_pwrst(neon_pd);
+ pwrdm_clear_all_prev_pwrst(core_pd);
+ pwrdm_clear_all_prev_pwrst(per_pd);
+
+ if (omap_irq_pending())
+ return 0;
+
+ per_pwrst = pwrdm_read_pwrst(per_pd);
+ neon_pwrst = pwrdm_read_pwrst(neon_pd);
+
/* Program MPU to target state */
- if (cx->mpu_state < PWRDM_POWER_ON)
+ if (cx->mpu_state < PWRDM_POWER_ON) {
+ if (neon_pwrst == PWRDM_POWER_ON)
+ pwrdm_set_next_pwrst(neon_pd, PWRDM_POWER_RET);
pwrdm_set_next_pwrst(mpu_pd, cx->mpu_state);
+ }
+
+ /* Program CORE and PER to target state */
+ if (cx->core_state < PWRDM_POWER_ON) {
+ if (per_pwrst == PWRDM_POWER_ON) {
+ omap2_gpio_prepare_for_retention();
+ if (clocks_off_while_idle) {
+ per_gpio_clk_disable();
+ omap_serial_enable_clocks(0);
+ }
+ }
+ pwrdm_set_next_pwrst(core_pd, cx->core_state);
+ }
/* Execute ARM wfi */
omap_sram_idle();
- /* Program MPU to ON */
- if (cx->mpu_state < PWRDM_POWER_ON)
+ /* Program MPU/NEON to ON */
+ if (cx->mpu_state < PWRDM_POWER_ON) {
+ if (neon_pwrst == PWRDM_POWER_ON)
+ pwrdm_set_next_pwrst(neon_pd, PWRDM_POWER_ON);
pwrdm_set_next_pwrst(mpu_pd, PWRDM_POWER_ON);
+ }
+
+ if (cx->core_state < PWRDM_POWER_ON) {
+ if (per_pwrst == PWRDM_POWER_ON) {
+ if (clocks_off_while_idle) {
+ omap_serial_enable_clocks(1);
+ per_gpio_clk_enable();
+ }
+ omap2_gpio_resume_after_retention();
+ }
+ pwrdm_set_next_pwrst(core_pd, PWRDM_POWER_ON);
+ }
+
+ pr_debug("MPU prev st:%x,NEON prev st:%x\n",
+ pwrdm_read_prev_pwrst(mpu_pd),
+ pwrdm_read_prev_pwrst(neon_pd));
+ pr_debug("PER prev st:%x,CORE prev st:%x\n",
+ pwrdm_read_prev_pwrst(per_pd),
+ pwrdm_read_prev_pwrst(core_pd));
getnstimeofday(&ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
- return timespec_to_ns(&ts_idle);
+ return (u32)timespec_to_ns(&ts_idle)/1000;
}
static int omap3_enter_idle_bm(struct cpuidle_device *dev,
@@ -130,7 +186,7 @@ void omap_init_power_states(void)
omap3_power_states[0].threshold = 0;
omap3_power_states[0].mpu_state = PWRDM_POWER_ON;
omap3_power_states[0].core_state = PWRDM_POWER_ON;
- omap3_power_states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+ omap3_power_states[0].flags = CPUIDLE_FLAG_SHALLOW;
/* C1 . MPU WFI + Core active */
omap3_power_states[1].valid = 1;
@@ -140,7 +196,8 @@ void omap_init_power_states(void)
omap3_power_states[1].threshold = 30;
omap3_power_states[1].mpu_state = PWRDM_POWER_ON;
omap3_power_states[1].core_state = PWRDM_POWER_ON;
- omap3_power_states[1].flags = CPUIDLE_FLAG_TIME_VALID;
+ omap3_power_states[1].flags = CPUIDLE_FLAG_TIME_VALID |
+ CPUIDLE_FLAG_SHALLOW;
/* C2 . MPU CSWR + Core active */
omap3_power_states[2].valid = 1;
@@ -150,7 +207,8 @@ void omap_init_power_states(void)
omap3_power_states[2].threshold = 300;
omap3_power_states[2].mpu_state = PWRDM_POWER_RET;
omap3_power_states[2].core_state = PWRDM_POWER_ON;
- omap3_power_states[2].flags = CPUIDLE_FLAG_TIME_VALID;
+ omap3_power_states[2].flags = CPUIDLE_FLAG_TIME_VALID |
+ CPUIDLE_FLAG_BALANCED;
/* C3 . MPU OFF + Core active */
omap3_power_states[3].valid = 0;
@@ -159,18 +217,20 @@ void omap_init_power_states(void)
omap3_power_states[3].wakeup_latency = 1800;
omap3_power_states[3].threshold = 4000;
omap3_power_states[3].mpu_state = PWRDM_POWER_OFF;
- omap3_power_states[3].core_state = PWRDM_POWER_RET;
- omap3_power_states[3].flags = CPUIDLE_FLAG_TIME_VALID;
+ omap3_power_states[3].core_state = PWRDM_POWER_ON;
+ omap3_power_states[3].flags = CPUIDLE_FLAG_TIME_VALID |
+ CPUIDLE_FLAG_BALANCED | CPUIDLE_FLAG_CHECK_BM;
/* C4 . MPU CSWR + Core CSWR*/
- omap3_power_states[4].valid = 0;
+ omap3_power_states[4].valid = 1;
omap3_power_states[4].type = OMAP3_STATE_C4;
omap3_power_states[4].sleep_latency = 2500;
omap3_power_states[4].wakeup_latency = 7500;
omap3_power_states[4].threshold = 12000;
omap3_power_states[4].mpu_state = PWRDM_POWER_RET;
omap3_power_states[4].core_state = PWRDM_POWER_RET;
- omap3_power_states[4].flags = CPUIDLE_FLAG_TIME_VALID;
+ omap3_power_states[4].flags = CPUIDLE_FLAG_TIME_VALID |
+ CPUIDLE_FLAG_BALANCED | CPUIDLE_FLAG_CHECK_BM;
/* C5 . MPU OFF + Core CSWR */
omap3_power_states[5].valid = 0;
@@ -180,7 +240,8 @@ void omap_init_power_states(void)
omap3_power_states[5].threshold = 15000;
omap3_power_states[5].mpu_state = PWRDM_POWER_OFF;
omap3_power_states[5].core_state = PWRDM_POWER_RET;
- omap3_power_states[5].flags = CPUIDLE_FLAG_TIME_VALID;
+ omap3_power_states[5].flags = CPUIDLE_FLAG_TIME_VALID |
+ CPUIDLE_FLAG_BALANCED | CPUIDLE_FLAG_CHECK_BM;
/* C6 . MPU OFF + Core OFF */
omap3_power_states[6].valid = 0;
@@ -190,7 +251,8 @@ void omap_init_power_states(void)
omap3_power_states[6].threshold = 300000;
omap3_power_states[6].mpu_state = PWRDM_POWER_OFF;
omap3_power_states[6].core_state = PWRDM_POWER_OFF;
- omap3_power_states[6].flags = CPUIDLE_FLAG_TIME_VALID;
+ omap3_power_states[6].flags = CPUIDLE_FLAG_TIME_VALID |
+ CPUIDLE_FLAG_DEEP | CPUIDLE_FLAG_CHECK_BM;
}
struct cpuidle_driver omap3_idle_driver = {
Index: linux-omap-2.6/arch/arm/mach-omap2/cpuidle34xx.h
===================================================================
--- linux-omap-2.6.orig/arch/arm/mach-omap2/cpuidle34xx.h 2008-07-01 18:48:09.962433167 +0530
+++ linux-omap-2.6/arch/arm/mach-omap2/cpuidle34xx.h 2008-07-01 18:48:12.885339367 +0530
@@ -33,11 +33,13 @@
/* Currently, we support only upto C2 */
#define MAX_SUPPORTED_STATES 3
+extern unsigned short clocks_off_while_idle;
extern void omap_sram_idle(void);
-extern int omap3_irq_pending(void);
+extern int omap_irq_pending(void);
extern void per_gpio_clk_enable(void);
extern void per_gpio_clk_disable(void);
-
+extern void omap_serial_enable_clocks(int enable);
+extern int omap3_can_sleep();
struct omap3_processor_cx {
u8 valid;
u8 type;
Index: linux-omap-2.6/arch/arm/mach-omap2/pm34xx.c
===================================================================
--- linux-omap-2.6.orig/arch/arm/mach-omap2/pm34xx.c 2008-07-01 18:48:09.962433167 +0530
+++ linux-omap-2.6/arch/arm/mach-omap2/pm34xx.c 2008-07-01 18:48:12.885339367 +0530
@@ -61,7 +61,7 @@ static struct clk *gpio_fcks[NUM_OF_PERG
/* XXX This is for gpio fclk hack. Will be removed as gpio driver
* handles fcks correctly */
-static void per_gpio_clk_enable(void)
+void per_gpio_clk_enable(void)
{
int i;
for (i = 1; i < NUM_OF_PERGPIOS + 1; i++)
@@ -70,7 +70,7 @@ static void per_gpio_clk_enable(void)
/* XXX This is for gpio fclk hack. Will be removed as gpio driver
* handles fcks correctly */
-static void per_gpio_clk_disable(void)
+void per_gpio_clk_disable(void)
{
int i;
for (i = 1; i < NUM_OF_PERGPIOS + 1; i++)
@@ -202,25 +202,7 @@ void omap_sram_idle(void)
return;
}
- omap2_gpio_prepare_for_retention();
-
- if (clocks_off_while_idle) {
- omap_serial_enable_clocks(0);
- /* XXX This is for gpio fclk hack. Will be removed as
- * gpio driver * handles fcks correctly */
- per_gpio_clk_disable();
- }
-
_omap_sram_idle(NULL, save_state, clocks_off_while_idle);
-
- if (clocks_off_while_idle) {
- omap_serial_enable_clocks(1);
- /* XXX This is for gpio fclk hack. Will be removed as
- * gpio driver * handles fcks correctly */
- per_gpio_clk_enable();
- }
-
- omap2_gpio_resume_after_retention();
}
static int omap3_fclks_active(void)
@@ -258,7 +240,7 @@ static int omap3_fclks_active(void)
return 0;
}
-static int omap3_can_sleep(void)
+int omap3_can_sleep(void)
{
if (!enable_dyn_sleep)
return 0;
@@ -329,8 +311,25 @@ static void omap3_pm_idle(void)
if (omap_irq_pending())
goto out;
+ omap2_gpio_prepare_for_retention();
+
+ if (clocks_off_while_idle) {
+ omap_serial_enable_clocks(0);
+ /* XXX This is for gpio fclk hack. Will be removed as
+ * gpio driver * handles fcks correctly */
+ per_gpio_clk_disable();
+ }
+
omap_sram_idle();
+ if (clocks_off_while_idle) {
+ omap_serial_enable_clocks(1);
+ /* XXX This is for gpio fclk hack. Will be removed as
+ * gpio driver * handles fcks correctly */
+ per_gpio_clk_enable();
+ }
+
+ omap2_gpio_resume_after_retention();
out:
local_fiq_enable();
local_irq_enable();
@@ -363,8 +362,25 @@ static int omap3_pm_suspend(void)
goto restore;
}
+ omap2_gpio_prepare_for_retention();
+
+ if (clocks_off_while_idle) {
+ omap_serial_enable_clocks(0);
+ /* XXX This is for gpio fclk hack. Will be removed as
+ * gpio driver * handles fcks correctly */
+ per_gpio_clk_disable();
+ }
+
omap_sram_idle();
+ if (clocks_off_while_idle) {
+ omap_serial_enable_clocks(1);
+ /* XXX This is for gpio fclk hack. Will be removed as
+ * gpio driver * handles fcks correctly */
+ per_gpio_clk_enable();
+ }
+
+ omap2_gpio_resume_after_retention();
restore:
/* Restore next_pwrsts */
list_for_each_entry(pwrst, &pwrst_list, node) {
next reply other threads:[~2008-07-01 14:16 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-01 14:16 Rajendra Nayak [this message]
2008-07-02 11:48 ` [PATCH 02/11] per/neon and core handling in idle Högander Jouni
2008-07-02 13:04 ` Rajendra Nayak
2008-07-02 13:32 ` Högander Jouni
-- strict thread matches above, loose matches on Subject: below --
2008-07-18 13:18 Rajendra Nayak
2008-08-06 13:13 Rajendra Nayak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='003f01c8db85$02c99dc0$68bf18ac@ent.ti.com' \
--to=rnayak@ti.com \
--cc=linux-omap@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox