diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-08-14 16:18:04 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-08-14 16:18:04 -0400 |
commit | ee42f75dba3c66e559a13ac86ad1889d2a396378 (patch) | |
tree | c2e234d229ff467999cfb366f1edef80ea243433 /arch/arm | |
parent | d4e4ab86bcba5a72779c43dc1459f71fea3d89c8 (diff) | |
parent | 9aadfa8fd9f8d311ba3014bf76e4d8aeee515533 (diff) |
Merge back earlier 'pm-cpuidle' material.
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-davinci/cpuidle.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-ux500/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-ux500/cpuidle.c | 128 |
3 files changed, 1 insertions, 130 deletions
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 36aef3a7dedb..f1ac1c94ac0f 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c | |||
@@ -65,7 +65,7 @@ static struct cpuidle_driver davinci_idle_driver = { | |||
65 | .states[1] = { | 65 | .states[1] = { |
66 | .enter = davinci_enter_idle, | 66 | .enter = davinci_enter_idle, |
67 | .exit_latency = 10, | 67 | .exit_latency = 10, |
68 | .target_residency = 100000, | 68 | .target_residency = 10000, |
69 | .flags = CPUIDLE_FLAG_TIME_VALID, | 69 | .flags = CPUIDLE_FLAG_TIME_VALID, |
70 | .name = "DDR SR", | 70 | .name = "DDR SR", |
71 | .desc = "WFI and DDR Self Refresh", | 71 | .desc = "WFI and DDR Self Refresh", |
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index bf9b6be5b180..fe1f3e26b88b 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile | |||
@@ -4,7 +4,6 @@ | |||
4 | 4 | ||
5 | obj-y := cpu.o devices.o devices-common.o \ | 5 | obj-y := cpu.o devices.o devices-common.o \ |
6 | id.o usb.o timer.o pm.o | 6 | id.o usb.o timer.o pm.o |
7 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o | ||
8 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o | 7 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o |
9 | obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o | 8 | obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o |
10 | obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ | 9 | obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ |
diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c deleted file mode 100644 index a45dd09daed9..000000000000 --- a/arch/arm/mach-ux500/cpuidle.c +++ /dev/null | |||
@@ -1,128 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Linaro : Daniel Lezcano <daniel.lezcano@linaro.org> (IBM) | ||
3 | * | ||
4 | * Based on the work of Rickard Andersson <rickard.andersson@stericsson.com> | ||
5 | * and Jonas Aaberg <jonas.aberg@stericsson.com>. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/cpuidle.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/atomic.h> | ||
16 | #include <linux/smp.h> | ||
17 | #include <linux/mfd/dbx500-prcmu.h> | ||
18 | #include <linux/platform_data/arm-ux500-pm.h> | ||
19 | |||
20 | #include <asm/cpuidle.h> | ||
21 | #include <asm/proc-fns.h> | ||
22 | |||
23 | #include "db8500-regs.h" | ||
24 | #include "id.h" | ||
25 | |||
26 | static atomic_t master = ATOMIC_INIT(0); | ||
27 | static DEFINE_SPINLOCK(master_lock); | ||
28 | |||
29 | static inline int ux500_enter_idle(struct cpuidle_device *dev, | ||
30 | struct cpuidle_driver *drv, int index) | ||
31 | { | ||
32 | int this_cpu = smp_processor_id(); | ||
33 | bool recouple = false; | ||
34 | |||
35 | if (atomic_inc_return(&master) == num_online_cpus()) { | ||
36 | |||
37 | /* With this lock, we prevent the other cpu to exit and enter | ||
38 | * this function again and become the master */ | ||
39 | if (!spin_trylock(&master_lock)) | ||
40 | goto wfi; | ||
41 | |||
42 | /* decouple the gic from the A9 cores */ | ||
43 | if (prcmu_gic_decouple()) { | ||
44 | spin_unlock(&master_lock); | ||
45 | goto out; | ||
46 | } | ||
47 | |||
48 | /* If an error occur, we will have to recouple the gic | ||
49 | * manually */ | ||
50 | recouple = true; | ||
51 | |||
52 | /* At this state, as the gic is decoupled, if the other | ||
53 | * cpu is in WFI, we have the guarantee it won't be wake | ||
54 | * up, so we can safely go to retention */ | ||
55 | if (!prcmu_is_cpu_in_wfi(this_cpu ? 0 : 1)) | ||
56 | goto out; | ||
57 | |||
58 | /* The prcmu will be in charge of watching the interrupts | ||
59 | * and wake up the cpus */ | ||
60 | if (prcmu_copy_gic_settings()) | ||
61 | goto out; | ||
62 | |||
63 | /* Check in the meantime an interrupt did | ||
64 | * not occur on the gic ... */ | ||
65 | if (prcmu_gic_pending_irq()) | ||
66 | goto out; | ||
67 | |||
68 | /* ... and the prcmu */ | ||
69 | if (prcmu_pending_irq()) | ||
70 | goto out; | ||
71 | |||
72 | /* Go to the retention state, the prcmu will wait for the | ||
73 | * cpu to go WFI and this is what happens after exiting this | ||
74 | * 'master' critical section */ | ||
75 | if (prcmu_set_power_state(PRCMU_AP_IDLE, true, true)) | ||
76 | goto out; | ||
77 | |||
78 | /* When we switch to retention, the prcmu is in charge | ||
79 | * of recoupling the gic automatically */ | ||
80 | recouple = false; | ||
81 | |||
82 | spin_unlock(&master_lock); | ||
83 | } | ||
84 | wfi: | ||
85 | cpu_do_idle(); | ||
86 | out: | ||
87 | atomic_dec(&master); | ||
88 | |||
89 | if (recouple) { | ||
90 | prcmu_gic_recouple(); | ||
91 | spin_unlock(&master_lock); | ||
92 | } | ||
93 | |||
94 | return index; | ||
95 | } | ||
96 | |||
97 | static struct cpuidle_driver ux500_idle_driver = { | ||
98 | .name = "ux500_idle", | ||
99 | .owner = THIS_MODULE, | ||
100 | .states = { | ||
101 | ARM_CPUIDLE_WFI_STATE, | ||
102 | { | ||
103 | .enter = ux500_enter_idle, | ||
104 | .exit_latency = 70, | ||
105 | .target_residency = 260, | ||
106 | .flags = CPUIDLE_FLAG_TIME_VALID | | ||
107 | CPUIDLE_FLAG_TIMER_STOP, | ||
108 | .name = "ApIdle", | ||
109 | .desc = "ARM Retention", | ||
110 | }, | ||
111 | }, | ||
112 | .safe_state_index = 0, | ||
113 | .state_count = 2, | ||
114 | }; | ||
115 | |||
116 | int __init ux500_idle_init(void) | ||
117 | { | ||
118 | if (!(cpu_is_u8500_family() || cpu_is_ux540_family())) | ||
119 | return -ENODEV; | ||
120 | |||
121 | /* Configure wake up reasons */ | ||
122 | prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | | ||
123 | PRCMU_WAKEUP(ABB)); | ||
124 | |||
125 | return cpuidle_register(&ux500_idle_driver, NULL); | ||
126 | } | ||
127 | |||
128 | device_initcall(ux500_idle_init); | ||