aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-08-15 14:58:19 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-09-03 19:45:01 -0400
commit5b41147ceae44350f43f9b8124687d22bed2bbb9 (patch)
tree5eb101652ed2aa3c950b90a0d712211696d152c7
parent35f2b0bd5911dc0eef3f5352b6acb79c69420111 (diff)
ARM: shmobile: Make sh7372 cpuidle handling more straightforward
The sh7372 cpuidle code uses the same artificially designed routine shmobile_cpuidle_enter() as the .enter() callback for all of its cpuidle states. However, shmobile_cpuidle_enter() calls a different "enter" function for each state using an array of function pointers populated by the sh7372 PM initialization code. Moreover, the states[] array of the shmobile cpuidle driver is populated by that code as well, although in principle it just might have been filled with static data. All of that complexity goes away if the sh7372 cpuidle code is allowed to define its own cpuidle driver structure that can be passed for registration to the common shmobile cpuidle initialization routine, so modify the code accordingly. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Magnus Damm <damm@opensource.se>
-rw-r--r--arch/arm/mach-shmobile/cpuidle.c39
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h6
-rw-r--r--arch/arm/mach-shmobile/pm-sh7372.c79
3 files changed, 62 insertions, 62 deletions
diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c
index 7b541e911ab4..9e050268cde4 100644
--- a/arch/arm/mach-shmobile/cpuidle.c
+++ b/arch/arm/mach-shmobile/cpuidle.c
@@ -16,51 +16,38 @@
16#include <asm/cpuidle.h> 16#include <asm/cpuidle.h>
17#include <asm/io.h> 17#include <asm/io.h>
18 18
19static void shmobile_enter_wfi(void) 19int shmobile_enter_wfi(struct cpuidle_device *dev, struct cpuidle_driver *drv,
20 int index)
20{ 21{
21 cpu_do_idle(); 22 cpu_do_idle();
22} 23 return 0;
23
24void (*shmobile_cpuidle_modes[CPUIDLE_STATE_MAX])(void) = {
25 shmobile_enter_wfi, /* regular sleep mode */
26};
27
28static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
29 struct cpuidle_driver *drv,
30 int index)
31{
32 shmobile_cpuidle_modes[index]();
33
34 return index;
35} 24}
36 25
37static struct cpuidle_device shmobile_cpuidle_dev; 26static struct cpuidle_device shmobile_cpuidle_dev;
38static struct cpuidle_driver shmobile_cpuidle_driver = { 27static struct cpuidle_driver shmobile_cpuidle_default_driver = {
39 .name = "shmobile_cpuidle", 28 .name = "shmobile_cpuidle",
40 .owner = THIS_MODULE, 29 .owner = THIS_MODULE,
41 .en_core_tk_irqen = 1, 30 .en_core_tk_irqen = 1,
42 .states[0] = ARM_CPUIDLE_WFI_STATE, 31 .states[0] = ARM_CPUIDLE_WFI_STATE,
32 .states[0].enter = shmobile_enter_wfi,
43 .safe_state_index = 0, /* C1 */ 33 .safe_state_index = 0, /* C1 */
44 .state_count = 1, 34 .state_count = 1,
45}; 35};
46 36
47void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); 37static struct cpuidle_driver *cpuidle_drv = &shmobile_cpuidle_default_driver;
38
39void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv)
40{
41 cpuidle_drv = drv;
42}
48 43
49int shmobile_cpuidle_init(void) 44int shmobile_cpuidle_init(void)
50{ 45{
51 struct cpuidle_device *dev = &shmobile_cpuidle_dev; 46 struct cpuidle_device *dev = &shmobile_cpuidle_dev;
52 struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
53 int i;
54
55 for (i = 0; i < CPUIDLE_STATE_MAX; i++)
56 drv->states[i].enter = shmobile_cpuidle_enter;
57
58 if (shmobile_cpuidle_setup)
59 shmobile_cpuidle_setup(drv);
60 47
61 cpuidle_register_driver(drv); 48 cpuidle_register_driver(cpuidle_drv);
62 49
63 dev->state_count = drv->state_count; 50 dev->state_count = cpuidle_drv->state_count;
64 cpuidle_register_device(dev); 51 cpuidle_register_device(dev);
65 52
66 return 0; 53 return 0;
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 9175c183ba7a..eb89293fff4d 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -14,8 +14,10 @@ extern int shmobile_clk_init(void);
14extern void shmobile_handle_irq_intc(struct pt_regs *); 14extern void shmobile_handle_irq_intc(struct pt_regs *);
15extern struct platform_suspend_ops shmobile_suspend_ops; 15extern struct platform_suspend_ops shmobile_suspend_ops;
16struct cpuidle_driver; 16struct cpuidle_driver;
17extern void (*shmobile_cpuidle_modes[])(void); 17struct cpuidle_device;
18extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); 18extern int shmobile_enter_wfi(struct cpuidle_device *dev,
19 struct cpuidle_driver *drv, int index);
20extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
19 21
20extern void sh7367_init_irq(void); 22extern void sh7367_init_irq(void);
21extern void sh7367_map_io(void); 23extern void sh7367_map_io(void);
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index d01122c0d9be..5cafd35cc411 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -21,6 +21,7 @@
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <linux/bitrev.h> 22#include <linux/bitrev.h>
23#include <linux/console.h> 23#include <linux/console.h>
24#include <asm/cpuidle.h>
24#include <asm/io.h> 25#include <asm/io.h>
25#include <asm/tlbflush.h> 26#include <asm/tlbflush.h>
26#include <asm/suspend.h> 27#include <asm/suspend.h>
@@ -347,7 +348,8 @@ static int sh7372_do_idle_core_standby(unsigned long unused)
347 return 0; 348 return 0;
348} 349}
349 350
350static void sh7372_enter_core_standby(void) 351static int sh7372_enter_core_standby(struct cpuidle_device *dev,
352 struct cpuidle_driver *drv, int index)
351{ 353{
352 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); 354 sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
353 355
@@ -358,52 +360,61 @@ static void sh7372_enter_core_standby(void)
358 360
359 /* disable reset vector translation */ 361 /* disable reset vector translation */
360 __raw_writel(0, SBAR); 362 __raw_writel(0, SBAR);
363
364 return 1;
361} 365}
362 366
363static void sh7372_enter_a3sm_pll_on(void) 367static int sh7372_enter_a3sm_pll_on(struct cpuidle_device *dev,
368 struct cpuidle_driver *drv, int index)
364{ 369{
365 sh7372_enter_a3sm_common(1); 370 sh7372_enter_a3sm_common(1);
371 return 2;
366} 372}
367 373
368static void sh7372_enter_a3sm_pll_off(void) 374static int sh7372_enter_a3sm_pll_off(struct cpuidle_device *dev,
375 struct cpuidle_driver *drv, int index)
369{ 376{
370 sh7372_enter_a3sm_common(0); 377 sh7372_enter_a3sm_common(0);
378 return 3;
371} 379}
372 380
373static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) 381static struct cpuidle_driver sh7372_cpuidle_driver = {
374{ 382 .name = "sh7372_cpuidle",
375 struct cpuidle_state *state = &drv->states[drv->state_count]; 383 .owner = THIS_MODULE,
376 384 .en_core_tk_irqen = 1,
377 snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); 385 .state_count = 4,
378 strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN); 386 .safe_state_index = 0, /* C1 */
379 state->exit_latency = 10; 387 .states[0] = ARM_CPUIDLE_WFI_STATE,
380 state->target_residency = 20 + 10; 388 .states[0].enter = shmobile_enter_wfi,
381 state->flags = CPUIDLE_FLAG_TIME_VALID; 389 .states[1] = {
382 shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby; 390 .name = "C2",
383 drv->state_count++; 391 .desc = "Core Standby Mode",
384 392 .exit_latency = 10,
385 state = &drv->states[drv->state_count]; 393 .target_residency = 20 + 10,
386 snprintf(state->name, CPUIDLE_NAME_LEN, "C3"); 394 .flags = CPUIDLE_FLAG_TIME_VALID,
387 strncpy(state->desc, "A3SM PLL ON", CPUIDLE_DESC_LEN); 395 .enter = sh7372_enter_core_standby,
388 state->exit_latency = 20; 396 },
389 state->target_residency = 30 + 20; 397 .states[2] = {
390 state->flags = CPUIDLE_FLAG_TIME_VALID; 398 .name = "C3",
391 shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_on; 399 .desc = "A3SM PLL ON",
392 drv->state_count++; 400 .exit_latency = 20,
393 401 .target_residency = 30 + 20,
394 state = &drv->states[drv->state_count]; 402 .flags = CPUIDLE_FLAG_TIME_VALID,
395 snprintf(state->name, CPUIDLE_NAME_LEN, "C4"); 403 .enter = sh7372_enter_a3sm_pll_on,
396 strncpy(state->desc, "A3SM PLL OFF", CPUIDLE_DESC_LEN); 404 },
397 state->exit_latency = 120; 405 .states[3] = {
398 state->target_residency = 30 + 120; 406 .name = "C4",
399 state->flags = CPUIDLE_FLAG_TIME_VALID; 407 .desc = "A3SM PLL OFF",
400 shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_off; 408 .exit_latency = 120,
401 drv->state_count++; 409 .target_residency = 30 + 120,
402} 410 .flags = CPUIDLE_FLAG_TIME_VALID,
411 .enter = sh7372_enter_a3sm_pll_off,
412 },
413};
403 414
404static void sh7372_cpuidle_init(void) 415static void sh7372_cpuidle_init(void)
405{ 416{
406 shmobile_cpuidle_setup = sh7372_cpuidle_setup; 417 shmobile_cpuidle_set_driver(&sh7372_cpuidle_driver);
407} 418}
408#else 419#else
409static void sh7372_cpuidle_init(void) {} 420static void sh7372_cpuidle_init(void) {}