aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-03 18:59:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-03 18:59:39 -0400
commit40031da445fb4d269af9c7c445b2adf674f171e7 (patch)
tree021df7906708e939dee9978669a5461b12ff1296 /arch/arm
parentdcaaaeac871ff73043c616db3b2f91482637801d (diff)
parentf41b83126cba53849dd2353476a7715613af648f (diff)
Merge tag 'pm+acpi-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management updates from Rafael Wysocki: 1) ACPI-based PCI hotplug (ACPIPHP) subsystem rework and introduction of Intel Thunderbolt support on systems that use ACPI for signalling Thunderbolt hotplug events. This also should make ACPIPHP work in some cases in which it was known to have problems. From Rafael J Wysocki, Mika Westerberg and Kirill A Shutemov. 2) ACPI core code cleanups and dock station support cleanups from Jiang Liu and Rafael J Wysocki. 3) Fixes for locking problems related to ACPI device hotplug from Rafael J Wysocki. 4) ACPICA update to version 20130725 includig fixes, cleanups, support for more than 256 GPEs per GPE block and a change to make the ACPI PM Timer optional (we've seen systems without the PM Timer in the field already). One of the fixes, related to the DeRefOf operator, is necessary to prevent some Windows 8 oriented AML from causing problems to happen. From Bob Moore, Lv Zheng, and Jung-uk Kim. 5) Removal of the old and long deprecated /proc/acpi/event interface and related driver changes from Thomas Renninger. 6) ACPI and Xen changes to make the reduced hardware sleep work with the latter from Ben Guthro. 7) ACPI video driver cleanups and a blacklist of systems that should not tell the BIOS that they are compatible with Windows 8 (or ACPI backlight and possibly other things will not work on them). From Felipe Contreras. 8) Assorted ACPI fixes and cleanups from Aaron Lu, Hanjun Guo, Kuppuswamy Sathyanarayanan, Lan Tianyu, Sachin Kamat, Tang Chen, Toshi Kani, and Wei Yongjun. 9) cpufreq ondemand governor target frequency selection change to reduce oscillations between min and max frequencies (essentially, it causes the governor to choose target frequencies proportional to load) from Stratos Karafotis. 10) cpufreq fixes allowing sysfs attributes file permissions to be preserved over suspend/resume cycles Srivatsa S Bhat. 11) Removal of Device Tree parsing for CPU device nodes from multiple cpufreq drivers that required some changes related to of_get_cpu_node() to be made in a few architectures and in the driver core. From Sudeep KarkadaNagesha. 12) cpufreq core fixes and cleanups related to mutual exclusion and driver module references from Viresh Kumar, Lukasz Majewski and Rafael J Wysocki. 13) Assorted cpufreq fixes and cleanups from Amit Daniel Kachhap, Bartlomiej Zolnierkiewicz, Hanjun Guo, Jingoo Han, Joseph Lo, Julia Lawall, Li Zhong, Mark Brown, Sascha Hauer, Stephen Boyd, Stratos Karafotis, and Viresh Kumar. 14) Fixes to prevent race conditions in coupled cpuidle from happening from Colin Cross. 15) cpuidle core fixes and cleanups from Daniel Lezcano and Tuukka Tikkanen. 16) Assorted cpuidle fixes and cleanups from Daniel Lezcano, Geert Uytterhoeven, Jingoo Han, Julia Lawall, Linus Walleij, and Sahara. 17) System sleep tracing changes from Todd E Brandt and Shuah Khan. 18) PNP subsystem conversion to using struct dev_pm_ops for power management from Shuah Khan. * tag 'pm+acpi-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (217 commits) cpufreq: Don't use smp_processor_id() in preemptible context cpuidle: coupled: fix race condition between pokes and safe state cpuidle: coupled: abort idle if pokes are pending cpuidle: coupled: disable interrupts after entering safe state ACPI / hotplug: Remove containers synchronously driver core / ACPI: Avoid device hot remove locking issues cpufreq: governor: Fix typos in comments cpufreq: governors: Remove duplicate check of target freq in supported range cpufreq: Fix timer/workqueue corruption due to double queueing ACPI / EC: Add ASUSTEK L4R to quirk list in order to validate ECDT ACPI / thermal: Add check of "_TZD" availability and evaluating result cpufreq: imx6q: Fix clock enable balance ACPI: blacklist win8 OSI for buggy laptops cpufreq: tegra: fix the wrong clock name cpuidle: Change struct menu_device field types cpuidle: Add a comment warning about possible overflow cpuidle: Fix variable domains in get_typical_interval() cpuidle: Fix menu_device->intervals type cpuidle: CodingStyle: Break up multiple assignments on single line cpuidle: Check called function parameter in get_typical_interval() ...
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/kernel/devtree.c5
-rw-r--r--arch/arm/kernel/topology.c61
-rw-r--r--arch/arm/mach-davinci/cpuidle.c2
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c3
-rw-r--r--arch/arm/mach-mvebu/platsmp.c51
-rw-r--r--arch/arm/mach-ux500/Makefile1
-rw-r--r--arch/arm/mach-ux500/cpuidle.c128
7 files changed, 49 insertions, 202 deletions
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 5859c8bc727c..2ee8a17d2b01 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -169,6 +169,11 @@ void __init arm_dt_init_cpu_maps(void)
169 } 169 }
170} 170}
171 171
172bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
173{
174 return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu);
175}
176
172/** 177/**
173 * setup_machine_fdt - Machine setup when an dtb was passed to the kernel 178 * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
174 * @dt_phys: physical address of dt blob 179 * @dt_phys: physical address of dt blob
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index c5a59546a256..85a87370f144 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -74,12 +74,8 @@ struct cpu_efficiency table_efficiency[] = {
74 {NULL, }, 74 {NULL, },
75}; 75};
76 76
77struct cpu_capacity { 77unsigned long *__cpu_capacity;
78 unsigned long hwid; 78#define cpu_capacity(cpu) __cpu_capacity[cpu]
79 unsigned long capacity;
80};
81
82struct cpu_capacity *cpu_capacity;
83 79
84unsigned long middle_capacity = 1; 80unsigned long middle_capacity = 1;
85 81
@@ -100,15 +96,19 @@ static void __init parse_dt_topology(void)
100 unsigned long capacity = 0; 96 unsigned long capacity = 0;
101 int alloc_size, cpu = 0; 97 int alloc_size, cpu = 0;
102 98
103 alloc_size = nr_cpu_ids * sizeof(struct cpu_capacity); 99 alloc_size = nr_cpu_ids * sizeof(*__cpu_capacity);
104 cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT); 100 __cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT);
105 101
106 while ((cn = of_find_node_by_type(cn, "cpu"))) { 102 for_each_possible_cpu(cpu) {
107 const u32 *rate, *reg; 103 const u32 *rate;
108 int len; 104 int len;
109 105
110 if (cpu >= num_possible_cpus()) 106 /* too early to use cpu->of_node */
111 break; 107 cn = of_get_cpu_node(cpu, NULL);
108 if (!cn) {
109 pr_err("missing device node for CPU %d\n", cpu);
110 continue;
111 }
112 112
113 for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++) 113 for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++)
114 if (of_device_is_compatible(cn, cpu_eff->compatible)) 114 if (of_device_is_compatible(cn, cpu_eff->compatible))
@@ -124,12 +124,6 @@ static void __init parse_dt_topology(void)
124 continue; 124 continue;
125 } 125 }
126 126
127 reg = of_get_property(cn, "reg", &len);
128 if (!reg || len != 4) {
129 pr_err("%s missing reg property\n", cn->full_name);
130 continue;
131 }
132
133 capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency; 127 capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency;
134 128
135 /* Save min capacity of the system */ 129 /* Save min capacity of the system */
@@ -140,13 +134,9 @@ static void __init parse_dt_topology(void)
140 if (capacity > max_capacity) 134 if (capacity > max_capacity)
141 max_capacity = capacity; 135 max_capacity = capacity;
142 136
143 cpu_capacity[cpu].capacity = capacity; 137 cpu_capacity(cpu) = capacity;
144 cpu_capacity[cpu++].hwid = be32_to_cpup(reg);
145 } 138 }
146 139
147 if (cpu < num_possible_cpus())
148 cpu_capacity[cpu].hwid = (unsigned long)(-1);
149
150 /* If min and max capacities are equals, we bypass the update of the 140 /* If min and max capacities are equals, we bypass the update of the
151 * cpu_scale because all CPUs have the same capacity. Otherwise, we 141 * cpu_scale because all CPUs have the same capacity. Otherwise, we
152 * compute a middle_capacity factor that will ensure that the capacity 142 * compute a middle_capacity factor that will ensure that the capacity
@@ -154,9 +144,7 @@ static void __init parse_dt_topology(void)
154 * SCHED_POWER_SCALE, which is the default value, but with the 144 * SCHED_POWER_SCALE, which is the default value, but with the
155 * constraint explained near table_efficiency[]. 145 * constraint explained near table_efficiency[].
156 */ 146 */
157 if (min_capacity == max_capacity) 147 if (4*max_capacity < (3*(max_capacity + min_capacity)))
158 cpu_capacity[0].hwid = (unsigned long)(-1);
159 else if (4*max_capacity < (3*(max_capacity + min_capacity)))
160 middle_capacity = (min_capacity + max_capacity) 148 middle_capacity = (min_capacity + max_capacity)
161 >> (SCHED_POWER_SHIFT+1); 149 >> (SCHED_POWER_SHIFT+1);
162 else 150 else
@@ -170,23 +158,12 @@ static void __init parse_dt_topology(void)
170 * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the 158 * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the
171 * function returns directly for SMP system. 159 * function returns directly for SMP system.
172 */ 160 */
173void update_cpu_power(unsigned int cpu, unsigned long hwid) 161void update_cpu_power(unsigned int cpu)
174{ 162{
175 unsigned int idx = 0; 163 if (!cpu_capacity(cpu))
176
177 /* look for the cpu's hwid in the cpu capacity table */
178 for (idx = 0; idx < num_possible_cpus(); idx++) {
179 if (cpu_capacity[idx].hwid == hwid)
180 break;
181
182 if (cpu_capacity[idx].hwid == -1)
183 return;
184 }
185
186 if (idx == num_possible_cpus())
187 return; 164 return;
188 165
189 set_power_scale(cpu, cpu_capacity[idx].capacity / middle_capacity); 166 set_power_scale(cpu, cpu_capacity(cpu) / middle_capacity);
190 167
191 printk(KERN_INFO "CPU%u: update cpu_power %lu\n", 168 printk(KERN_INFO "CPU%u: update cpu_power %lu\n",
192 cpu, arch_scale_freq_power(NULL, cpu)); 169 cpu, arch_scale_freq_power(NULL, cpu));
@@ -194,7 +171,7 @@ void update_cpu_power(unsigned int cpu, unsigned long hwid)
194 171
195#else 172#else
196static inline void parse_dt_topology(void) {} 173static inline void parse_dt_topology(void) {}
197static inline void update_cpu_power(unsigned int cpuid, unsigned int mpidr) {} 174static inline void update_cpu_power(unsigned int cpuid) {}
198#endif 175#endif
199 176
200 /* 177 /*
@@ -281,7 +258,7 @@ void store_cpu_topology(unsigned int cpuid)
281 258
282 update_siblings_masks(cpuid); 259 update_siblings_masks(cpuid);
283 260
284 update_cpu_power(cpuid, mpidr & MPIDR_HWID_BITMASK); 261 update_cpu_power(cpuid);
285 262
286 printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", 263 printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
287 cpuid, cpu_topology[cpuid].thread_id, 264 cpuid, cpu_topology[cpuid].thread_id,
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-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 7be13f8e69a0..a02f275a198d 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -254,13 +254,12 @@ static void __init imx6q_opp_init(struct device *cpu_dev)
254{ 254{
255 struct device_node *np; 255 struct device_node *np;
256 256
257 np = of_find_node_by_path("/cpus/cpu@0"); 257 np = of_node_get(cpu_dev->of_node);
258 if (!np) { 258 if (!np) {
259 pr_warn("failed to find cpu0 node\n"); 259 pr_warn("failed to find cpu0 node\n");
260 return; 260 return;
261 } 261 }
262 262
263 cpu_dev->of_node = np;
264 if (of_init_opp_table(cpu_dev)) { 263 if (of_init_opp_table(cpu_dev)) {
265 pr_warn("failed to init OPP table\n"); 264 pr_warn("failed to init OPP table\n");
266 goto put_node; 265 goto put_node;
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c
index ce81d3031405..594b63db4215 100644
--- a/arch/arm/mach-mvebu/platsmp.c
+++ b/arch/arm/mach-mvebu/platsmp.c
@@ -29,45 +29,40 @@
29#include "pmsu.h" 29#include "pmsu.h"
30#include "coherency.h" 30#include "coherency.h"
31 31
32static struct clk *__init get_cpu_clk(int cpu)
33{
34 struct clk *cpu_clk;
35 struct device_node *np = of_get_cpu_node(cpu, NULL);
36
37 if (WARN(!np, "missing cpu node\n"))
38 return NULL;
39 cpu_clk = of_clk_get(np, 0);
40 if (WARN_ON(IS_ERR(cpu_clk)))
41 return NULL;
42 return cpu_clk;
43}
44
32void __init set_secondary_cpus_clock(void) 45void __init set_secondary_cpus_clock(void)
33{ 46{
34 int thiscpu; 47 int thiscpu, cpu;
35 unsigned long rate; 48 unsigned long rate;
36 struct clk *cpu_clk = NULL; 49 struct clk *cpu_clk;
37 struct device_node *np = NULL;
38 50
39 thiscpu = smp_processor_id(); 51 thiscpu = smp_processor_id();
40 for_each_node_by_type(np, "cpu") { 52 cpu_clk = get_cpu_clk(thiscpu);
41 int err; 53 if (!cpu_clk)
42 int cpu;
43
44 err = of_property_read_u32(np, "reg", &cpu);
45 if (WARN_ON(err))
46 return;
47
48 if (cpu == thiscpu) {
49 cpu_clk = of_clk_get(np, 0);
50 break;
51 }
52 }
53 if (WARN_ON(IS_ERR(cpu_clk)))
54 return; 54 return;
55 clk_prepare_enable(cpu_clk); 55 clk_prepare_enable(cpu_clk);
56 rate = clk_get_rate(cpu_clk); 56 rate = clk_get_rate(cpu_clk);
57 57
58 /* set all the other CPU clk to the same rate than the boot CPU */ 58 /* set all the other CPU clk to the same rate than the boot CPU */
59 for_each_node_by_type(np, "cpu") { 59 for_each_possible_cpu(cpu) {
60 int err; 60 if (cpu == thiscpu)
61 int cpu; 61 continue;
62 62 cpu_clk = get_cpu_clk(cpu);
63 err = of_property_read_u32(np, "reg", &cpu); 63 if (!cpu_clk)
64 if (WARN_ON(err))
65 return; 64 return;
66 65 clk_set_rate(cpu_clk, rate);
67 if (cpu != thiscpu) {
68 cpu_clk = of_clk_get(np, 0);
69 clk_set_rate(cpu_clk, rate);
70 }
71 } 66 }
72} 67}
73 68
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
5obj-y := cpu.o devices.o devices-common.o \ 5obj-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
7obj-$(CONFIG_CPU_IDLE) += cpuidle.o
8obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o 7obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
9obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o 8obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
10obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ 9obj-$(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
26static atomic_t master = ATOMIC_INIT(0);
27static DEFINE_SPINLOCK(master_lock);
28
29static 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 }
84wfi:
85 cpu_do_idle();
86out:
87 atomic_dec(&master);
88
89 if (recouple) {
90 prcmu_gic_recouple();
91 spin_unlock(&master_lock);
92 }
93
94 return index;
95}
96
97static 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
116int __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
128device_initcall(ux500_idle_init);