diff options
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r-- | arch/arm/mach-imx/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpufreq.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpuidle-imx5.c | 37 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpuidle-imx6q.c | 26 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpuidle.c | 80 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpuidle.h | 10 | ||||
-rw-r--r-- | arch/arm/mach-imx/pm-imx5.c | 30 |
7 files changed, 48 insertions, 145 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index c4ce0906d76a..cb70961b6239 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile | |||
@@ -30,7 +30,7 @@ obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o | |||
30 | obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o | 30 | obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o |
31 | 31 | ||
32 | ifeq ($(CONFIG_CPU_IDLE),y) | 32 | ifeq ($(CONFIG_CPU_IDLE),y) |
33 | obj-y += cpuidle.o | 33 | obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o |
34 | obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o | 34 | obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o |
35 | endif | 35 | endif |
36 | 36 | ||
diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c index d8c75c3c925d..387dc4cceca2 100644 --- a/arch/arm/mach-imx/cpufreq.c +++ b/arch/arm/mach-imx/cpufreq.c | |||
@@ -87,13 +87,12 @@ static int mxc_set_target(struct cpufreq_policy *policy, | |||
87 | 87 | ||
88 | freqs.old = clk_get_rate(cpu_clk) / 1000; | 88 | freqs.old = clk_get_rate(cpu_clk) / 1000; |
89 | freqs.new = freq_Hz / 1000; | 89 | freqs.new = freq_Hz / 1000; |
90 | freqs.cpu = 0; | ||
91 | freqs.flags = 0; | 90 | freqs.flags = 0; |
92 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 91 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); |
93 | 92 | ||
94 | ret = set_cpu_freq(freq_Hz); | 93 | ret = set_cpu_freq(freq_Hz); |
95 | 94 | ||
96 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 95 | cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); |
97 | 96 | ||
98 | return ret; | 97 | return ret; |
99 | } | 98 | } |
@@ -145,14 +144,11 @@ static int mxc_cpufreq_init(struct cpufreq_policy *policy) | |||
145 | imx_freq_table[i].frequency = CPUFREQ_TABLE_END; | 144 | imx_freq_table[i].frequency = CPUFREQ_TABLE_END; |
146 | 145 | ||
147 | policy->cur = clk_get_rate(cpu_clk) / 1000; | 146 | policy->cur = clk_get_rate(cpu_clk) / 1000; |
148 | policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min; | ||
149 | policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max; | ||
150 | 147 | ||
151 | /* Manual states, that PLL stabilizes in two CLK32 periods */ | 148 | /* Manual states, that PLL stabilizes in two CLK32 periods */ |
152 | policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ; | 149 | policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ; |
153 | 150 | ||
154 | ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table); | 151 | ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table); |
155 | |||
156 | if (ret < 0) { | 152 | if (ret < 0) { |
157 | printk(KERN_ERR "%s: failed to register i.MXC CPUfreq with error code %d\n", | 153 | printk(KERN_ERR "%s: failed to register i.MXC CPUfreq with error code %d\n", |
158 | __func__, ret); | 154 | __func__, ret); |
diff --git a/arch/arm/mach-imx/cpuidle-imx5.c b/arch/arm/mach-imx/cpuidle-imx5.c new file mode 100644 index 000000000000..5a47e3c6172f --- /dev/null +++ b/arch/arm/mach-imx/cpuidle-imx5.c | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/cpuidle.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <asm/system_misc.h> | ||
12 | |||
13 | static int imx5_cpuidle_enter(struct cpuidle_device *dev, | ||
14 | struct cpuidle_driver *drv, int index) | ||
15 | { | ||
16 | arm_pm_idle(); | ||
17 | return index; | ||
18 | } | ||
19 | |||
20 | static struct cpuidle_driver imx5_cpuidle_driver = { | ||
21 | .name = "imx5_cpuidle", | ||
22 | .owner = THIS_MODULE, | ||
23 | .states[0] = { | ||
24 | .enter = imx5_cpuidle_enter, | ||
25 | .exit_latency = 2, | ||
26 | .target_residency = 1, | ||
27 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
28 | .name = "IMX5 SRPG", | ||
29 | .desc = "CPU state retained,powered off", | ||
30 | }, | ||
31 | .state_count = 1, | ||
32 | }; | ||
33 | |||
34 | int __init imx5_cpuidle_init(void) | ||
35 | { | ||
36 | return cpuidle_register(&imx5_cpuidle_driver, NULL); | ||
37 | } | ||
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c index d533e2695f0e..23ddfb693b2d 100644 --- a/arch/arm/mach-imx/cpuidle-imx6q.c +++ b/arch/arm/mach-imx/cpuidle-imx6q.c | |||
@@ -6,7 +6,6 @@ | |||
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/clockchips.h> | ||
10 | #include <linux/cpuidle.h> | 9 | #include <linux/cpuidle.h> |
11 | #include <linux/module.h> | 10 | #include <linux/module.h> |
12 | #include <asm/cpuidle.h> | 11 | #include <asm/cpuidle.h> |
@@ -21,10 +20,6 @@ static DEFINE_SPINLOCK(master_lock); | |||
21 | static int imx6q_enter_wait(struct cpuidle_device *dev, | 20 | static int imx6q_enter_wait(struct cpuidle_device *dev, |
22 | struct cpuidle_driver *drv, int index) | 21 | struct cpuidle_driver *drv, int index) |
23 | { | 22 | { |
24 | int cpu = dev->cpu; | ||
25 | |||
26 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); | ||
27 | |||
28 | if (atomic_inc_return(&master) == num_online_cpus()) { | 23 | if (atomic_inc_return(&master) == num_online_cpus()) { |
29 | /* | 24 | /* |
30 | * With this lock, we prevent other cpu to exit and enter | 25 | * With this lock, we prevent other cpu to exit and enter |
@@ -43,26 +38,13 @@ idle: | |||
43 | cpu_do_idle(); | 38 | cpu_do_idle(); |
44 | done: | 39 | done: |
45 | atomic_dec(&master); | 40 | atomic_dec(&master); |
46 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); | ||
47 | 41 | ||
48 | return index; | 42 | return index; |
49 | } | 43 | } |
50 | 44 | ||
51 | /* | ||
52 | * For each cpu, setup the broadcast timer because local timer | ||
53 | * stops for the states other than WFI. | ||
54 | */ | ||
55 | static void imx6q_setup_broadcast_timer(void *arg) | ||
56 | { | ||
57 | int cpu = smp_processor_id(); | ||
58 | |||
59 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu); | ||
60 | } | ||
61 | |||
62 | static struct cpuidle_driver imx6q_cpuidle_driver = { | 45 | static struct cpuidle_driver imx6q_cpuidle_driver = { |
63 | .name = "imx6q_cpuidle", | 46 | .name = "imx6q_cpuidle", |
64 | .owner = THIS_MODULE, | 47 | .owner = THIS_MODULE, |
65 | .en_core_tk_irqen = 1, | ||
66 | .states = { | 48 | .states = { |
67 | /* WFI */ | 49 | /* WFI */ |
68 | ARM_CPUIDLE_WFI_STATE, | 50 | ARM_CPUIDLE_WFI_STATE, |
@@ -70,7 +52,8 @@ static struct cpuidle_driver imx6q_cpuidle_driver = { | |||
70 | { | 52 | { |
71 | .exit_latency = 50, | 53 | .exit_latency = 50, |
72 | .target_residency = 75, | 54 | .target_residency = 75, |
73 | .flags = CPUIDLE_FLAG_TIME_VALID, | 55 | .flags = CPUIDLE_FLAG_TIME_VALID | |
56 | CPUIDLE_FLAG_TIMER_STOP, | ||
74 | .enter = imx6q_enter_wait, | 57 | .enter = imx6q_enter_wait, |
75 | .name = "WAIT", | 58 | .name = "WAIT", |
76 | .desc = "Clock off", | 59 | .desc = "Clock off", |
@@ -88,8 +71,5 @@ int __init imx6q_cpuidle_init(void) | |||
88 | /* Set chicken bit to get a reliable WAIT mode support */ | 71 | /* Set chicken bit to get a reliable WAIT mode support */ |
89 | imx6q_set_chicken_bit(); | 72 | imx6q_set_chicken_bit(); |
90 | 73 | ||
91 | /* Configure the broadcast timer on each cpu */ | 74 | return cpuidle_register(&imx6q_cpuidle_driver, NULL); |
92 | on_each_cpu(imx6q_setup_broadcast_timer, NULL, 1); | ||
93 | |||
94 | return imx_cpuidle_init(&imx6q_cpuidle_driver); | ||
95 | } | 75 | } |
diff --git a/arch/arm/mach-imx/cpuidle.c b/arch/arm/mach-imx/cpuidle.c deleted file mode 100644 index d4cb511a44a8..000000000000 --- a/arch/arm/mach-imx/cpuidle.c +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2012 Linaro Ltd. | ||
4 | * | ||
5 | * The code contained herein is licensed under the GNU General Public | ||
6 | * License. You may obtain a copy of the GNU General Public License | ||
7 | * Version 2 or later at the following locations: | ||
8 | * | ||
9 | * http://www.opensource.org/licenses/gpl-license.html | ||
10 | * http://www.gnu.org/copyleft/gpl.html | ||
11 | */ | ||
12 | |||
13 | #include <linux/cpuidle.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/hrtimer.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | static struct cpuidle_device __percpu * imx_cpuidle_devices; | ||
21 | |||
22 | static void __init imx_cpuidle_devices_uninit(void) | ||
23 | { | ||
24 | int cpu_id; | ||
25 | struct cpuidle_device *dev; | ||
26 | |||
27 | for_each_possible_cpu(cpu_id) { | ||
28 | dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id); | ||
29 | cpuidle_unregister_device(dev); | ||
30 | } | ||
31 | |||
32 | free_percpu(imx_cpuidle_devices); | ||
33 | } | ||
34 | |||
35 | int __init imx_cpuidle_init(struct cpuidle_driver *drv) | ||
36 | { | ||
37 | struct cpuidle_device *dev; | ||
38 | int cpu_id, ret; | ||
39 | |||
40 | if (drv->state_count > CPUIDLE_STATE_MAX) { | ||
41 | pr_err("%s: state_count exceeds maximum\n", __func__); | ||
42 | return -EINVAL; | ||
43 | } | ||
44 | |||
45 | ret = cpuidle_register_driver(drv); | ||
46 | if (ret) { | ||
47 | pr_err("%s: Failed to register cpuidle driver with error: %d\n", | ||
48 | __func__, ret); | ||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | imx_cpuidle_devices = alloc_percpu(struct cpuidle_device); | ||
53 | if (imx_cpuidle_devices == NULL) { | ||
54 | ret = -ENOMEM; | ||
55 | goto unregister_drv; | ||
56 | } | ||
57 | |||
58 | /* initialize state data for each cpuidle_device */ | ||
59 | for_each_possible_cpu(cpu_id) { | ||
60 | dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id); | ||
61 | dev->cpu = cpu_id; | ||
62 | dev->state_count = drv->state_count; | ||
63 | |||
64 | ret = cpuidle_register_device(dev); | ||
65 | if (ret) { | ||
66 | pr_err("%s: Failed to register cpu %u, error: %d\n", | ||
67 | __func__, cpu_id, ret); | ||
68 | goto uninit; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | return 0; | ||
73 | |||
74 | uninit: | ||
75 | imx_cpuidle_devices_uninit(); | ||
76 | |||
77 | unregister_drv: | ||
78 | cpuidle_unregister_driver(drv); | ||
79 | return ret; | ||
80 | } | ||
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h index e092d1359d94..786f98ecc145 100644 --- a/arch/arm/mach-imx/cpuidle.h +++ b/arch/arm/mach-imx/cpuidle.h | |||
@@ -10,18 +10,16 @@ | |||
10 | * http://www.gnu.org/copyleft/gpl.html | 10 | * http://www.gnu.org/copyleft/gpl.html |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/cpuidle.h> | ||
14 | |||
15 | #ifdef CONFIG_CPU_IDLE | 13 | #ifdef CONFIG_CPU_IDLE |
16 | extern int imx_cpuidle_init(struct cpuidle_driver *drv); | 14 | extern int imx5_cpuidle_init(void); |
17 | extern int imx6q_cpuidle_init(void); | 15 | extern int imx6q_cpuidle_init(void); |
18 | #else | 16 | #else |
19 | static inline int imx_cpuidle_init(struct cpuidle_driver *drv) | 17 | static inline int imx5_cpuidle_init(void) |
20 | { | 18 | { |
21 | return -ENODEV; | 19 | return 0; |
22 | } | 20 | } |
23 | static inline int imx6q_cpuidle_init(void) | 21 | static inline int imx6q_cpuidle_init(void) |
24 | { | 22 | { |
25 | return -ENODEV; | 23 | return 0; |
26 | } | 24 | } |
27 | #endif | 25 | #endif |
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c index f67fd7ee8127..82e79c658eb2 100644 --- a/arch/arm/mach-imx/pm-imx5.c +++ b/arch/arm/mach-imx/pm-imx5.c | |||
@@ -149,33 +149,6 @@ static void imx5_pm_idle(void) | |||
149 | imx5_cpu_do_idle(); | 149 | imx5_cpu_do_idle(); |
150 | } | 150 | } |
151 | 151 | ||
152 | static int imx5_cpuidle_enter(struct cpuidle_device *dev, | ||
153 | struct cpuidle_driver *drv, int idx) | ||
154 | { | ||
155 | int ret; | ||
156 | |||
157 | ret = imx5_cpu_do_idle(); | ||
158 | if (ret < 0) | ||
159 | return ret; | ||
160 | |||
161 | return idx; | ||
162 | } | ||
163 | |||
164 | static struct cpuidle_driver imx5_cpuidle_driver = { | ||
165 | .name = "imx5_cpuidle", | ||
166 | .owner = THIS_MODULE, | ||
167 | .en_core_tk_irqen = 1, | ||
168 | .states[0] = { | ||
169 | .enter = imx5_cpuidle_enter, | ||
170 | .exit_latency = 2, | ||
171 | .target_residency = 1, | ||
172 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
173 | .name = "IMX5 SRPG", | ||
174 | .desc = "CPU state retained,powered off", | ||
175 | }, | ||
176 | .state_count = 1, | ||
177 | }; | ||
178 | |||
179 | static int __init imx5_pm_common_init(void) | 152 | static int __init imx5_pm_common_init(void) |
180 | { | 153 | { |
181 | int ret; | 154 | int ret; |
@@ -193,8 +166,7 @@ static int __init imx5_pm_common_init(void) | |||
193 | /* Set the registers to the default cpu idle state. */ | 166 | /* Set the registers to the default cpu idle state. */ |
194 | mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE); | 167 | mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE); |
195 | 168 | ||
196 | imx_cpuidle_init(&imx5_cpuidle_driver); | 169 | return imx5_cpuidle_init(); |
197 | return 0; | ||
198 | } | 170 | } |
199 | 171 | ||
200 | void __init imx51_pm_init(void) | 172 | void __init imx51_pm_init(void) |