diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-05-30 09:55:19 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-05-30 09:55:19 -0400 |
commit | 52d1d0b12beaf98b6d144d7d1b24eb96cfea60f6 (patch) | |
tree | 4dde4eeb3f6ce7a4d3b68f4ab9adfc60da519a6e | |
parent | c7208164e66f63e3ec1759b98087849286410741 (diff) | |
parent | 3022f4de491c096650d55ae9d562a9c811830724 (diff) |
Merge branch 'acpi-lpss' into acpi-enumeration
-rw-r--r-- | Documentation/power/devices.txt | 34 | ||||
-rw-r--r-- | Documentation/power/runtime_pm.txt | 17 | ||||
-rw-r--r-- | Documentation/power/swsusp.txt | 5 | ||||
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 249 | ||||
-rw-r--r-- | drivers/acpi/acpi_platform.c | 29 | ||||
-rw-r--r-- | drivers/acpi/device_pm.c | 46 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 3 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 4 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 19 | ||||
-rw-r--r-- | drivers/base/power/main.c | 66 | ||||
-rw-r--r-- | drivers/clk/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/clk-fractional-divider.c | 135 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 55 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 17 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 3 | ||||
-rw-r--r-- | include/linux/acpi.h | 6 | ||||
-rw-r--r-- | include/linux/clk-provider.h | 31 | ||||
-rw-r--r-- | include/linux/cpuidle.h | 7 | ||||
-rw-r--r-- | include/linux/pm.h | 36 | ||||
-rw-r--r-- | include/linux/pm_runtime.h | 6 | ||||
-rw-r--r-- | include/linux/suspend.h | 7 | ||||
-rw-r--r-- | kernel/power/hibernate.c | 27 | ||||
-rw-r--r-- | kernel/power/suspend.c | 17 | ||||
-rw-r--r-- | kernel/sched/idle.c | 20 |
24 files changed, 707 insertions, 133 deletions
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 47d46dff70f7..d172bce0fd49 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt | |||
@@ -2,6 +2,7 @@ Device Power Management | |||
2 | 2 | ||
3 | Copyright (c) 2010-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | 3 | Copyright (c) 2010-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. |
4 | Copyright (c) 2010 Alan Stern <stern@rowland.harvard.edu> | 4 | Copyright (c) 2010 Alan Stern <stern@rowland.harvard.edu> |
5 | Copyright (c) 2014 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com> | ||
5 | 6 | ||
6 | 7 | ||
7 | Most of the code in Linux is device drivers, so most of the Linux power | 8 | Most of the code in Linux is device drivers, so most of the Linux power |
@@ -326,6 +327,20 @@ the phases are: | |||
326 | driver in some way for the upcoming system power transition, but it | 327 | driver in some way for the upcoming system power transition, but it |
327 | should not put the device into a low-power state. | 328 | should not put the device into a low-power state. |
328 | 329 | ||
330 | For devices supporting runtime power management, the return value of the | ||
331 | prepare callback can be used to indicate to the PM core that it may | ||
332 | safely leave the device in runtime suspend (if runtime-suspended | ||
333 | already), provided that all of the device's descendants are also left in | ||
334 | runtime suspend. Namely, if the prepare callback returns a positive | ||
335 | number and that happens for all of the descendants of the device too, | ||
336 | and all of them (including the device itself) are runtime-suspended, the | ||
337 | PM core will skip the suspend, suspend_late and suspend_noirq suspend | ||
338 | phases as well as the resume_noirq, resume_early and resume phases of | ||
339 | the following system resume for all of these devices. In that case, | ||
340 | the complete callback will be called directly after the prepare callback | ||
341 | and is entirely responsible for bringing the device back to the | ||
342 | functional state as appropriate. | ||
343 | |||
329 | 2. The suspend methods should quiesce the device to stop it from performing | 344 | 2. The suspend methods should quiesce the device to stop it from performing |
330 | I/O. They also may save the device registers and put it into the | 345 | I/O. They also may save the device registers and put it into the |
331 | appropriate low-power state, depending on the bus type the device is on, | 346 | appropriate low-power state, depending on the bus type the device is on, |
@@ -400,12 +415,23 @@ When resuming from freeze, standby or memory sleep, the phases are: | |||
400 | the resume callbacks occur; it's not necessary to wait until the | 415 | the resume callbacks occur; it's not necessary to wait until the |
401 | complete phase. | 416 | complete phase. |
402 | 417 | ||
418 | Moreover, if the preceding prepare callback returned a positive number, | ||
419 | the device may have been left in runtime suspend throughout the whole | ||
420 | system suspend and resume (the suspend, suspend_late, suspend_noirq | ||
421 | phases of system suspend and the resume_noirq, resume_early, resume | ||
422 | phases of system resume may have been skipped for it). In that case, | ||
423 | the complete callback is entirely responsible for bringing the device | ||
424 | back to the functional state after system suspend if necessary. [For | ||
425 | example, it may need to queue up a runtime resume request for the device | ||
426 | for this purpose.] To check if that is the case, the complete callback | ||
427 | can consult the device's power.direct_complete flag. Namely, if that | ||
428 | flag is set when the complete callback is being run, it has been called | ||
429 | directly after the preceding prepare and special action may be required | ||
430 | to make the device work correctly afterward. | ||
431 | |||
403 | At the end of these phases, drivers should be as functional as they were before | 432 | At the end of these phases, drivers should be as functional as they were before |
404 | suspending: I/O can be performed using DMA and IRQs, and the relevant clocks are | 433 | suspending: I/O can be performed using DMA and IRQs, and the relevant clocks are |
405 | gated on. Even if the device was in a low-power state before the system sleep | 434 | gated on. |
406 | because of runtime power management, afterwards it should be back in its | ||
407 | full-power state. There are multiple reasons why it's best to do this; they are | ||
408 | discussed in more detail in Documentation/power/runtime_pm.txt. | ||
409 | 435 | ||
410 | However, the details here may again be platform-specific. For example, | 436 | However, the details here may again be platform-specific. For example, |
411 | some systems support multiple "run" states, and the mode in effect at | 437 | some systems support multiple "run" states, and the mode in effect at |
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 5f96daf8566a..e1bee8a4aaac 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt | |||
@@ -2,6 +2,7 @@ Runtime Power Management Framework for I/O Devices | |||
2 | 2 | ||
3 | (C) 2009-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | 3 | (C) 2009-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. |
4 | (C) 2010 Alan Stern <stern@rowland.harvard.edu> | 4 | (C) 2010 Alan Stern <stern@rowland.harvard.edu> |
5 | (C) 2014 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com> | ||
5 | 6 | ||
6 | 1. Introduction | 7 | 1. Introduction |
7 | 8 | ||
@@ -444,6 +445,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: | |||
444 | bool pm_runtime_status_suspended(struct device *dev); | 445 | bool pm_runtime_status_suspended(struct device *dev); |
445 | - return true if the device's runtime PM status is 'suspended' | 446 | - return true if the device's runtime PM status is 'suspended' |
446 | 447 | ||
448 | bool pm_runtime_suspended_if_enabled(struct device *dev); | ||
449 | - return true if the device's runtime PM status is 'suspended' and its | ||
450 | 'power.disable_depth' field is equal to 1 | ||
451 | |||
447 | void pm_runtime_allow(struct device *dev); | 452 | void pm_runtime_allow(struct device *dev); |
448 | - set the power.runtime_auto flag for the device and decrease its usage | 453 | - set the power.runtime_auto flag for the device and decrease its usage |
449 | counter (used by the /sys/devices/.../power/control interface to | 454 | counter (used by the /sys/devices/.../power/control interface to |
@@ -644,6 +649,18 @@ place (in particular, if the system is not waking up from hibernation), it may | |||
644 | be more efficient to leave the devices that had been suspended before the system | 649 | be more efficient to leave the devices that had been suspended before the system |
645 | suspend began in the suspended state. | 650 | suspend began in the suspended state. |
646 | 651 | ||
652 | To this end, the PM core provides a mechanism allowing some coordination between | ||
653 | different levels of device hierarchy. Namely, if a system suspend .prepare() | ||
654 | callback returns a positive number for a device, that indicates to the PM core | ||
655 | that the device appears to be runtime-suspended and its state is fine, so it | ||
656 | may be left in runtime suspend provided that all of its descendants are also | ||
657 | left in runtime suspend. If that happens, the PM core will not execute any | ||
658 | system suspend and resume callbacks for all of those devices, except for the | ||
659 | complete callback, which is then entirely responsible for handling the device | ||
660 | as appropriate. This only applies to system suspend transitions that are not | ||
661 | related to hibernation (see Documentation/power/devices.txt for more | ||
662 | information). | ||
663 | |||
647 | The PM core does its best to reduce the probability of race conditions between | 664 | The PM core does its best to reduce the probability of race conditions between |
648 | the runtime PM and system suspend/resume (and hibernation) callbacks by carrying | 665 | the runtime PM and system suspend/resume (and hibernation) callbacks by carrying |
649 | out the following operations: | 666 | out the following operations: |
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index 079160e22bcc..f732a8321e8a 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt | |||
@@ -220,7 +220,10 @@ Q: After resuming, system is paging heavily, leading to very bad interactivity. | |||
220 | 220 | ||
221 | A: Try running | 221 | A: Try running |
222 | 222 | ||
223 | cat `cat /proc/[0-9]*/maps | grep / | sed 's:.* /:/:' | sort -u` > /dev/null | 223 | cat /proc/[0-9]*/maps | grep / | sed 's:.* /:/:' | sort -u | while read file |
224 | do | ||
225 | test -f "$file" && cat "$file" > /dev/null | ||
226 | done | ||
224 | 227 | ||
225 | after resume. swapoff -a; swapon -a may also be useful. | 228 | after resume. swapoff -a; swapon -a may also be useful. |
226 | 229 | ||
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 69e29f409d4c..db362a96c38e 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/platform_data/clk-lpss.h> | 20 | #include <linux/platform_data/clk-lpss.h> |
21 | #include <linux/pm_runtime.h> | 21 | #include <linux/pm_runtime.h> |
22 | #include <linux/delay.h> | ||
22 | 23 | ||
23 | #include "internal.h" | 24 | #include "internal.h" |
24 | 25 | ||
@@ -28,6 +29,7 @@ ACPI_MODULE_NAME("acpi_lpss"); | |||
28 | #define LPSS_LTR_SIZE 0x18 | 29 | #define LPSS_LTR_SIZE 0x18 |
29 | 30 | ||
30 | /* Offsets relative to LPSS_PRIVATE_OFFSET */ | 31 | /* Offsets relative to LPSS_PRIVATE_OFFSET */ |
32 | #define LPSS_CLK_DIVIDER_DEF_MASK (BIT(1) | BIT(16)) | ||
31 | #define LPSS_GENERAL 0x08 | 33 | #define LPSS_GENERAL 0x08 |
32 | #define LPSS_GENERAL_LTR_MODE_SW BIT(2) | 34 | #define LPSS_GENERAL_LTR_MODE_SW BIT(2) |
33 | #define LPSS_GENERAL_UART_RTS_OVRD BIT(3) | 35 | #define LPSS_GENERAL_UART_RTS_OVRD BIT(3) |
@@ -43,6 +45,8 @@ ACPI_MODULE_NAME("acpi_lpss"); | |||
43 | #define LPSS_TX_INT 0x20 | 45 | #define LPSS_TX_INT 0x20 |
44 | #define LPSS_TX_INT_MASK BIT(1) | 46 | #define LPSS_TX_INT_MASK BIT(1) |
45 | 47 | ||
48 | #define LPSS_PRV_REG_COUNT 9 | ||
49 | |||
46 | struct lpss_shared_clock { | 50 | struct lpss_shared_clock { |
47 | const char *name; | 51 | const char *name; |
48 | unsigned long rate; | 52 | unsigned long rate; |
@@ -57,7 +61,9 @@ struct lpss_device_desc { | |||
57 | bool ltr_required; | 61 | bool ltr_required; |
58 | unsigned int prv_offset; | 62 | unsigned int prv_offset; |
59 | size_t prv_size_override; | 63 | size_t prv_size_override; |
64 | bool clk_divider; | ||
60 | bool clk_gate; | 65 | bool clk_gate; |
66 | bool save_ctx; | ||
61 | struct lpss_shared_clock *shared_clock; | 67 | struct lpss_shared_clock *shared_clock; |
62 | void (*setup)(struct lpss_private_data *pdata); | 68 | void (*setup)(struct lpss_private_data *pdata); |
63 | }; | 69 | }; |
@@ -72,6 +78,7 @@ struct lpss_private_data { | |||
72 | resource_size_t mmio_size; | 78 | resource_size_t mmio_size; |
73 | struct clk *clk; | 79 | struct clk *clk; |
74 | const struct lpss_device_desc *dev_desc; | 80 | const struct lpss_device_desc *dev_desc; |
81 | u32 prv_reg_ctx[LPSS_PRV_REG_COUNT]; | ||
75 | }; | 82 | }; |
76 | 83 | ||
77 | static void lpss_uart_setup(struct lpss_private_data *pdata) | 84 | static void lpss_uart_setup(struct lpss_private_data *pdata) |
@@ -92,6 +99,14 @@ static struct lpss_device_desc lpt_dev_desc = { | |||
92 | .clk_required = true, | 99 | .clk_required = true, |
93 | .prv_offset = 0x800, | 100 | .prv_offset = 0x800, |
94 | .ltr_required = true, | 101 | .ltr_required = true, |
102 | .clk_divider = true, | ||
103 | .clk_gate = true, | ||
104 | }; | ||
105 | |||
106 | static struct lpss_device_desc lpt_i2c_dev_desc = { | ||
107 | .clk_required = true, | ||
108 | .prv_offset = 0x800, | ||
109 | .ltr_required = true, | ||
95 | .clk_gate = true, | 110 | .clk_gate = true, |
96 | }; | 111 | }; |
97 | 112 | ||
@@ -99,6 +114,7 @@ static struct lpss_device_desc lpt_uart_dev_desc = { | |||
99 | .clk_required = true, | 114 | .clk_required = true, |
100 | .prv_offset = 0x800, | 115 | .prv_offset = 0x800, |
101 | .ltr_required = true, | 116 | .ltr_required = true, |
117 | .clk_divider = true, | ||
102 | .clk_gate = true, | 118 | .clk_gate = true, |
103 | .setup = lpss_uart_setup, | 119 | .setup = lpss_uart_setup, |
104 | }; | 120 | }; |
@@ -116,32 +132,25 @@ static struct lpss_shared_clock pwm_clock = { | |||
116 | 132 | ||
117 | static struct lpss_device_desc byt_pwm_dev_desc = { | 133 | static struct lpss_device_desc byt_pwm_dev_desc = { |
118 | .clk_required = true, | 134 | .clk_required = true, |
135 | .save_ctx = true, | ||
119 | .shared_clock = &pwm_clock, | 136 | .shared_clock = &pwm_clock, |
120 | }; | 137 | }; |
121 | 138 | ||
122 | static struct lpss_shared_clock uart_clock = { | ||
123 | .name = "uart_clk", | ||
124 | .rate = 44236800, | ||
125 | }; | ||
126 | |||
127 | static struct lpss_device_desc byt_uart_dev_desc = { | 139 | static struct lpss_device_desc byt_uart_dev_desc = { |
128 | .clk_required = true, | 140 | .clk_required = true, |
129 | .prv_offset = 0x800, | 141 | .prv_offset = 0x800, |
142 | .clk_divider = true, | ||
130 | .clk_gate = true, | 143 | .clk_gate = true, |
131 | .shared_clock = &uart_clock, | 144 | .save_ctx = true, |
132 | .setup = lpss_uart_setup, | 145 | .setup = lpss_uart_setup, |
133 | }; | 146 | }; |
134 | 147 | ||
135 | static struct lpss_shared_clock spi_clock = { | ||
136 | .name = "spi_clk", | ||
137 | .rate = 50000000, | ||
138 | }; | ||
139 | |||
140 | static struct lpss_device_desc byt_spi_dev_desc = { | 148 | static struct lpss_device_desc byt_spi_dev_desc = { |
141 | .clk_required = true, | 149 | .clk_required = true, |
142 | .prv_offset = 0x400, | 150 | .prv_offset = 0x400, |
151 | .clk_divider = true, | ||
143 | .clk_gate = true, | 152 | .clk_gate = true, |
144 | .shared_clock = &spi_clock, | 153 | .save_ctx = true, |
145 | }; | 154 | }; |
146 | 155 | ||
147 | static struct lpss_device_desc byt_sdio_dev_desc = { | 156 | static struct lpss_device_desc byt_sdio_dev_desc = { |
@@ -156,6 +165,7 @@ static struct lpss_shared_clock i2c_clock = { | |||
156 | static struct lpss_device_desc byt_i2c_dev_desc = { | 165 | static struct lpss_device_desc byt_i2c_dev_desc = { |
157 | .clk_required = true, | 166 | .clk_required = true, |
158 | .prv_offset = 0x800, | 167 | .prv_offset = 0x800, |
168 | .save_ctx = true, | ||
159 | .shared_clock = &i2c_clock, | 169 | .shared_clock = &i2c_clock, |
160 | }; | 170 | }; |
161 | 171 | ||
@@ -166,8 +176,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { | |||
166 | /* Lynxpoint LPSS devices */ | 176 | /* Lynxpoint LPSS devices */ |
167 | { "INT33C0", (unsigned long)&lpt_dev_desc }, | 177 | { "INT33C0", (unsigned long)&lpt_dev_desc }, |
168 | { "INT33C1", (unsigned long)&lpt_dev_desc }, | 178 | { "INT33C1", (unsigned long)&lpt_dev_desc }, |
169 | { "INT33C2", (unsigned long)&lpt_dev_desc }, | 179 | { "INT33C2", (unsigned long)&lpt_i2c_dev_desc }, |
170 | { "INT33C3", (unsigned long)&lpt_dev_desc }, | 180 | { "INT33C3", (unsigned long)&lpt_i2c_dev_desc }, |
171 | { "INT33C4", (unsigned long)&lpt_uart_dev_desc }, | 181 | { "INT33C4", (unsigned long)&lpt_uart_dev_desc }, |
172 | { "INT33C5", (unsigned long)&lpt_uart_dev_desc }, | 182 | { "INT33C5", (unsigned long)&lpt_uart_dev_desc }, |
173 | { "INT33C6", (unsigned long)&lpt_sdio_dev_desc }, | 183 | { "INT33C6", (unsigned long)&lpt_sdio_dev_desc }, |
@@ -183,8 +193,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { | |||
183 | 193 | ||
184 | { "INT3430", (unsigned long)&lpt_dev_desc }, | 194 | { "INT3430", (unsigned long)&lpt_dev_desc }, |
185 | { "INT3431", (unsigned long)&lpt_dev_desc }, | 195 | { "INT3431", (unsigned long)&lpt_dev_desc }, |
186 | { "INT3432", (unsigned long)&lpt_dev_desc }, | 196 | { "INT3432", (unsigned long)&lpt_i2c_dev_desc }, |
187 | { "INT3433", (unsigned long)&lpt_dev_desc }, | 197 | { "INT3433", (unsigned long)&lpt_i2c_dev_desc }, |
188 | { "INT3434", (unsigned long)&lpt_uart_dev_desc }, | 198 | { "INT3434", (unsigned long)&lpt_uart_dev_desc }, |
189 | { "INT3435", (unsigned long)&lpt_uart_dev_desc }, | 199 | { "INT3435", (unsigned long)&lpt_uart_dev_desc }, |
190 | { "INT3436", (unsigned long)&lpt_sdio_dev_desc }, | 200 | { "INT3436", (unsigned long)&lpt_sdio_dev_desc }, |
@@ -212,9 +222,11 @@ static int register_device_clock(struct acpi_device *adev, | |||
212 | { | 222 | { |
213 | const struct lpss_device_desc *dev_desc = pdata->dev_desc; | 223 | const struct lpss_device_desc *dev_desc = pdata->dev_desc; |
214 | struct lpss_shared_clock *shared_clock = dev_desc->shared_clock; | 224 | struct lpss_shared_clock *shared_clock = dev_desc->shared_clock; |
225 | const char *devname = dev_name(&adev->dev); | ||
215 | struct clk *clk = ERR_PTR(-ENODEV); | 226 | struct clk *clk = ERR_PTR(-ENODEV); |
216 | struct lpss_clk_data *clk_data; | 227 | struct lpss_clk_data *clk_data; |
217 | const char *parent; | 228 | const char *parent, *clk_name; |
229 | void __iomem *prv_base; | ||
218 | 230 | ||
219 | if (!lpss_clk_dev) | 231 | if (!lpss_clk_dev) |
220 | lpt_register_clock_device(); | 232 | lpt_register_clock_device(); |
@@ -225,7 +237,7 @@ static int register_device_clock(struct acpi_device *adev, | |||
225 | 237 | ||
226 | if (dev_desc->clkdev_name) { | 238 | if (dev_desc->clkdev_name) { |
227 | clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name, | 239 | clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name, |
228 | dev_name(&adev->dev)); | 240 | devname); |
229 | return 0; | 241 | return 0; |
230 | } | 242 | } |
231 | 243 | ||
@@ -234,6 +246,7 @@ static int register_device_clock(struct acpi_device *adev, | |||
234 | return -ENODATA; | 246 | return -ENODATA; |
235 | 247 | ||
236 | parent = clk_data->name; | 248 | parent = clk_data->name; |
249 | prv_base = pdata->mmio_base + dev_desc->prv_offset; | ||
237 | 250 | ||
238 | if (shared_clock) { | 251 | if (shared_clock) { |
239 | clk = shared_clock->clk; | 252 | clk = shared_clock->clk; |
@@ -247,16 +260,41 @@ static int register_device_clock(struct acpi_device *adev, | |||
247 | } | 260 | } |
248 | 261 | ||
249 | if (dev_desc->clk_gate) { | 262 | if (dev_desc->clk_gate) { |
250 | clk = clk_register_gate(NULL, dev_name(&adev->dev), parent, 0, | 263 | clk = clk_register_gate(NULL, devname, parent, 0, |
251 | pdata->mmio_base + dev_desc->prv_offset, | 264 | prv_base, 0, 0, NULL); |
252 | 0, 0, NULL); | 265 | parent = devname; |
253 | pdata->clk = clk; | 266 | } |
267 | |||
268 | if (dev_desc->clk_divider) { | ||
269 | /* Prevent division by zero */ | ||
270 | if (!readl(prv_base)) | ||
271 | writel(LPSS_CLK_DIVIDER_DEF_MASK, prv_base); | ||
272 | |||
273 | clk_name = kasprintf(GFP_KERNEL, "%s-div", devname); | ||
274 | if (!clk_name) | ||
275 | return -ENOMEM; | ||
276 | clk = clk_register_fractional_divider(NULL, clk_name, parent, | ||
277 | 0, prv_base, | ||
278 | 1, 15, 16, 15, 0, NULL); | ||
279 | parent = clk_name; | ||
280 | |||
281 | clk_name = kasprintf(GFP_KERNEL, "%s-update", devname); | ||
282 | if (!clk_name) { | ||
283 | kfree(parent); | ||
284 | return -ENOMEM; | ||
285 | } | ||
286 | clk = clk_register_gate(NULL, clk_name, parent, | ||
287 | CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, | ||
288 | prv_base, 31, 0, NULL); | ||
289 | kfree(parent); | ||
290 | kfree(clk_name); | ||
254 | } | 291 | } |
255 | 292 | ||
256 | if (IS_ERR(clk)) | 293 | if (IS_ERR(clk)) |
257 | return PTR_ERR(clk); | 294 | return PTR_ERR(clk); |
258 | 295 | ||
259 | clk_register_clkdev(clk, NULL, dev_name(&adev->dev)); | 296 | pdata->clk = clk; |
297 | clk_register_clkdev(clk, NULL, devname); | ||
260 | return 0; | 298 | return 0; |
261 | } | 299 | } |
262 | 300 | ||
@@ -267,12 +305,14 @@ static int acpi_lpss_create_device(struct acpi_device *adev, | |||
267 | struct lpss_private_data *pdata; | 305 | struct lpss_private_data *pdata; |
268 | struct resource_list_entry *rentry; | 306 | struct resource_list_entry *rentry; |
269 | struct list_head resource_list; | 307 | struct list_head resource_list; |
308 | struct platform_device *pdev; | ||
270 | int ret; | 309 | int ret; |
271 | 310 | ||
272 | dev_desc = (struct lpss_device_desc *)id->driver_data; | 311 | dev_desc = (struct lpss_device_desc *)id->driver_data; |
273 | if (!dev_desc) | 312 | if (!dev_desc) { |
274 | return acpi_create_platform_device(adev, id); | 313 | pdev = acpi_create_platform_device(adev); |
275 | 314 | return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1; | |
315 | } | ||
276 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 316 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); |
277 | if (!pdata) | 317 | if (!pdata) |
278 | return -ENOMEM; | 318 | return -ENOMEM; |
@@ -322,10 +362,13 @@ static int acpi_lpss_create_device(struct acpi_device *adev, | |||
322 | dev_desc->setup(pdata); | 362 | dev_desc->setup(pdata); |
323 | 363 | ||
324 | adev->driver_data = pdata; | 364 | adev->driver_data = pdata; |
325 | ret = acpi_create_platform_device(adev, id); | 365 | pdev = acpi_create_platform_device(adev); |
326 | if (ret > 0) | 366 | if (!IS_ERR_OR_NULL(pdev)) { |
327 | return ret; | 367 | device_enable_async_suspend(&pdev->dev); |
368 | return 1; | ||
369 | } | ||
328 | 370 | ||
371 | ret = PTR_ERR(pdev); | ||
329 | adev->driver_data = NULL; | 372 | adev->driver_data = NULL; |
330 | 373 | ||
331 | err_out: | 374 | err_out: |
@@ -449,6 +492,126 @@ static void acpi_lpss_set_ltr(struct device *dev, s32 val) | |||
449 | } | 492 | } |
450 | } | 493 | } |
451 | 494 | ||
495 | #ifdef CONFIG_PM | ||
496 | /** | ||
497 | * acpi_lpss_save_ctx() - Save the private registers of LPSS device | ||
498 | * @dev: LPSS device | ||
499 | * | ||
500 | * Most LPSS devices have private registers which may loose their context when | ||
501 | * the device is powered down. acpi_lpss_save_ctx() saves those registers into | ||
502 | * prv_reg_ctx array. | ||
503 | */ | ||
504 | static void acpi_lpss_save_ctx(struct device *dev) | ||
505 | { | ||
506 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | ||
507 | unsigned int i; | ||
508 | |||
509 | for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { | ||
510 | unsigned long offset = i * sizeof(u32); | ||
511 | |||
512 | pdata->prv_reg_ctx[i] = __lpss_reg_read(pdata, offset); | ||
513 | dev_dbg(dev, "saving 0x%08x from LPSS reg at offset 0x%02lx\n", | ||
514 | pdata->prv_reg_ctx[i], offset); | ||
515 | } | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * acpi_lpss_restore_ctx() - Restore the private registers of LPSS device | ||
520 | * @dev: LPSS device | ||
521 | * | ||
522 | * Restores the registers that were previously stored with acpi_lpss_save_ctx(). | ||
523 | */ | ||
524 | static void acpi_lpss_restore_ctx(struct device *dev) | ||
525 | { | ||
526 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | ||
527 | unsigned int i; | ||
528 | |||
529 | /* | ||
530 | * The following delay is needed or the subsequent write operations may | ||
531 | * fail. The LPSS devices are actually PCI devices and the PCI spec | ||
532 | * expects 10ms delay before the device can be accessed after D3 to D0 | ||
533 | * transition. | ||
534 | */ | ||
535 | msleep(10); | ||
536 | |||
537 | for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { | ||
538 | unsigned long offset = i * sizeof(u32); | ||
539 | |||
540 | __lpss_reg_write(pdata->prv_reg_ctx[i], pdata, offset); | ||
541 | dev_dbg(dev, "restoring 0x%08x to LPSS reg at offset 0x%02lx\n", | ||
542 | pdata->prv_reg_ctx[i], offset); | ||
543 | } | ||
544 | } | ||
545 | |||
546 | #ifdef CONFIG_PM_SLEEP | ||
547 | static int acpi_lpss_suspend_late(struct device *dev) | ||
548 | { | ||
549 | int ret = pm_generic_suspend_late(dev); | ||
550 | |||
551 | if (ret) | ||
552 | return ret; | ||
553 | |||
554 | acpi_lpss_save_ctx(dev); | ||
555 | return acpi_dev_suspend_late(dev); | ||
556 | } | ||
557 | |||
558 | static int acpi_lpss_restore_early(struct device *dev) | ||
559 | { | ||
560 | int ret = acpi_dev_resume_early(dev); | ||
561 | |||
562 | if (ret) | ||
563 | return ret; | ||
564 | |||
565 | acpi_lpss_restore_ctx(dev); | ||
566 | return pm_generic_resume_early(dev); | ||
567 | } | ||
568 | #endif /* CONFIG_PM_SLEEP */ | ||
569 | |||
570 | #ifdef CONFIG_PM_RUNTIME | ||
571 | static int acpi_lpss_runtime_suspend(struct device *dev) | ||
572 | { | ||
573 | int ret = pm_generic_runtime_suspend(dev); | ||
574 | |||
575 | if (ret) | ||
576 | return ret; | ||
577 | |||
578 | acpi_lpss_save_ctx(dev); | ||
579 | return acpi_dev_runtime_suspend(dev); | ||
580 | } | ||
581 | |||
582 | static int acpi_lpss_runtime_resume(struct device *dev) | ||
583 | { | ||
584 | int ret = acpi_dev_runtime_resume(dev); | ||
585 | |||
586 | if (ret) | ||
587 | return ret; | ||
588 | |||
589 | acpi_lpss_restore_ctx(dev); | ||
590 | return pm_generic_runtime_resume(dev); | ||
591 | } | ||
592 | #endif /* CONFIG_PM_RUNTIME */ | ||
593 | #endif /* CONFIG_PM */ | ||
594 | |||
595 | static struct dev_pm_domain acpi_lpss_pm_domain = { | ||
596 | .ops = { | ||
597 | #ifdef CONFIG_PM_SLEEP | ||
598 | .suspend_late = acpi_lpss_suspend_late, | ||
599 | .restore_early = acpi_lpss_restore_early, | ||
600 | .prepare = acpi_subsys_prepare, | ||
601 | .complete = acpi_subsys_complete, | ||
602 | .suspend = acpi_subsys_suspend, | ||
603 | .resume_early = acpi_subsys_resume_early, | ||
604 | .freeze = acpi_subsys_freeze, | ||
605 | .poweroff = acpi_subsys_suspend, | ||
606 | .poweroff_late = acpi_subsys_suspend_late, | ||
607 | #endif | ||
608 | #ifdef CONFIG_PM_RUNTIME | ||
609 | .runtime_suspend = acpi_lpss_runtime_suspend, | ||
610 | .runtime_resume = acpi_lpss_runtime_resume, | ||
611 | #endif | ||
612 | }, | ||
613 | }; | ||
614 | |||
452 | static int acpi_lpss_platform_notify(struct notifier_block *nb, | 615 | static int acpi_lpss_platform_notify(struct notifier_block *nb, |
453 | unsigned long action, void *data) | 616 | unsigned long action, void *data) |
454 | { | 617 | { |
@@ -456,7 +619,6 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, | |||
456 | struct lpss_private_data *pdata; | 619 | struct lpss_private_data *pdata; |
457 | struct acpi_device *adev; | 620 | struct acpi_device *adev; |
458 | const struct acpi_device_id *id; | 621 | const struct acpi_device_id *id; |
459 | int ret = 0; | ||
460 | 622 | ||
461 | id = acpi_match_device(acpi_lpss_device_ids, &pdev->dev); | 623 | id = acpi_match_device(acpi_lpss_device_ids, &pdev->dev); |
462 | if (!id || !id->driver_data) | 624 | if (!id || !id->driver_data) |
@@ -466,7 +628,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, | |||
466 | return 0; | 628 | return 0; |
467 | 629 | ||
468 | pdata = acpi_driver_data(adev); | 630 | pdata = acpi_driver_data(adev); |
469 | if (!pdata || !pdata->mmio_base || !pdata->dev_desc->ltr_required) | 631 | if (!pdata || !pdata->mmio_base) |
470 | return 0; | 632 | return 0; |
471 | 633 | ||
472 | if (pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { | 634 | if (pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { |
@@ -474,12 +636,27 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, | |||
474 | return 0; | 636 | return 0; |
475 | } | 637 | } |
476 | 638 | ||
477 | if (action == BUS_NOTIFY_ADD_DEVICE) | 639 | switch (action) { |
478 | ret = sysfs_create_group(&pdev->dev.kobj, &lpss_attr_group); | 640 | case BUS_NOTIFY_BOUND_DRIVER: |
479 | else if (action == BUS_NOTIFY_DEL_DEVICE) | 641 | if (pdata->dev_desc->save_ctx) |
480 | sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); | 642 | pdev->dev.pm_domain = &acpi_lpss_pm_domain; |
643 | break; | ||
644 | case BUS_NOTIFY_UNBOUND_DRIVER: | ||
645 | if (pdata->dev_desc->save_ctx) | ||
646 | pdev->dev.pm_domain = NULL; | ||
647 | break; | ||
648 | case BUS_NOTIFY_ADD_DEVICE: | ||
649 | if (pdata->dev_desc->ltr_required) | ||
650 | return sysfs_create_group(&pdev->dev.kobj, | ||
651 | &lpss_attr_group); | ||
652 | case BUS_NOTIFY_DEL_DEVICE: | ||
653 | if (pdata->dev_desc->ltr_required) | ||
654 | sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); | ||
655 | default: | ||
656 | break; | ||
657 | } | ||
481 | 658 | ||
482 | return ret; | 659 | return 0; |
483 | } | 660 | } |
484 | 661 | ||
485 | static struct notifier_block acpi_lpss_nb = { | 662 | static struct notifier_block acpi_lpss_nb = { |
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 1d4950388fa1..3bb89def2292 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c | |||
@@ -31,6 +31,10 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { | |||
31 | { "PNP0D40" }, | 31 | { "PNP0D40" }, |
32 | { "VPC2004" }, | 32 | { "VPC2004" }, |
33 | { "BCM4752" }, | 33 | { "BCM4752" }, |
34 | { "LNV4752" }, | ||
35 | { "BCM2E1A" }, | ||
36 | { "BCM2E39" }, | ||
37 | { "BCM2E3D" }, | ||
34 | 38 | ||
35 | /* Intel Smart Sound Technology */ | 39 | /* Intel Smart Sound Technology */ |
36 | { "INT33C8" }, | 40 | { "INT33C8" }, |
@@ -42,7 +46,6 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { | |||
42 | /** | 46 | /** |
43 | * acpi_create_platform_device - Create platform device for ACPI device node | 47 | * acpi_create_platform_device - Create platform device for ACPI device node |
44 | * @adev: ACPI device node to create a platform device for. | 48 | * @adev: ACPI device node to create a platform device for. |
45 | * @id: ACPI device ID used to match @adev. | ||
46 | * | 49 | * |
47 | * Check if the given @adev can be represented as a platform device and, if | 50 | * Check if the given @adev can be represented as a platform device and, if |
48 | * that's the case, create and register a platform device, populate its common | 51 | * that's the case, create and register a platform device, populate its common |
@@ -50,8 +53,7 @@ static const struct acpi_device_id acpi_platform_device_ids[] = { | |||
50 | * | 53 | * |
51 | * Name of the platform device will be the same as @adev's. | 54 | * Name of the platform device will be the same as @adev's. |
52 | */ | 55 | */ |
53 | int acpi_create_platform_device(struct acpi_device *adev, | 56 | struct platform_device *acpi_create_platform_device(struct acpi_device *adev) |
54 | const struct acpi_device_id *id) | ||
55 | { | 57 | { |
56 | struct platform_device *pdev = NULL; | 58 | struct platform_device *pdev = NULL; |
57 | struct acpi_device *acpi_parent; | 59 | struct acpi_device *acpi_parent; |
@@ -63,19 +65,19 @@ int acpi_create_platform_device(struct acpi_device *adev, | |||
63 | 65 | ||
64 | /* If the ACPI node already has a physical device attached, skip it. */ | 66 | /* If the ACPI node already has a physical device attached, skip it. */ |
65 | if (adev->physical_node_count) | 67 | if (adev->physical_node_count) |
66 | return 0; | 68 | return NULL; |
67 | 69 | ||
68 | INIT_LIST_HEAD(&resource_list); | 70 | INIT_LIST_HEAD(&resource_list); |
69 | count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); | 71 | count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); |
70 | if (count < 0) { | 72 | if (count < 0) { |
71 | return 0; | 73 | return NULL; |
72 | } else if (count > 0) { | 74 | } else if (count > 0) { |
73 | resources = kmalloc(count * sizeof(struct resource), | 75 | resources = kmalloc(count * sizeof(struct resource), |
74 | GFP_KERNEL); | 76 | GFP_KERNEL); |
75 | if (!resources) { | 77 | if (!resources) { |
76 | dev_err(&adev->dev, "No memory for resources\n"); | 78 | dev_err(&adev->dev, "No memory for resources\n"); |
77 | acpi_dev_free_resource_list(&resource_list); | 79 | acpi_dev_free_resource_list(&resource_list); |
78 | return -ENOMEM; | 80 | return ERR_PTR(-ENOMEM); |
79 | } | 81 | } |
80 | count = 0; | 82 | count = 0; |
81 | list_for_each_entry(rentry, &resource_list, node) | 83 | list_for_each_entry(rentry, &resource_list, node) |
@@ -112,22 +114,27 @@ int acpi_create_platform_device(struct acpi_device *adev, | |||
112 | pdevinfo.num_res = count; | 114 | pdevinfo.num_res = count; |
113 | pdevinfo.acpi_node.companion = adev; | 115 | pdevinfo.acpi_node.companion = adev; |
114 | pdev = platform_device_register_full(&pdevinfo); | 116 | pdev = platform_device_register_full(&pdevinfo); |
115 | if (IS_ERR(pdev)) { | 117 | if (IS_ERR(pdev)) |
116 | dev_err(&adev->dev, "platform device creation failed: %ld\n", | 118 | dev_err(&adev->dev, "platform device creation failed: %ld\n", |
117 | PTR_ERR(pdev)); | 119 | PTR_ERR(pdev)); |
118 | pdev = NULL; | 120 | else |
119 | } else { | ||
120 | dev_dbg(&adev->dev, "created platform device %s\n", | 121 | dev_dbg(&adev->dev, "created platform device %s\n", |
121 | dev_name(&pdev->dev)); | 122 | dev_name(&pdev->dev)); |
122 | } | ||
123 | 123 | ||
124 | kfree(resources); | 124 | kfree(resources); |
125 | return pdev; | ||
126 | } | ||
127 | |||
128 | static int acpi_platform_attach(struct acpi_device *adev, | ||
129 | const struct acpi_device_id *id) | ||
130 | { | ||
131 | acpi_create_platform_device(adev); | ||
125 | return 1; | 132 | return 1; |
126 | } | 133 | } |
127 | 134 | ||
128 | static struct acpi_scan_handler platform_handler = { | 135 | static struct acpi_scan_handler platform_handler = { |
129 | .ids = acpi_platform_device_ids, | 136 | .ids = acpi_platform_device_ids, |
130 | .attach = acpi_create_platform_device, | 137 | .attach = acpi_platform_attach, |
131 | }; | 138 | }; |
132 | 139 | ||
133 | void __init acpi_platform_init(void) | 140 | void __init acpi_platform_init(void) |
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index d047739f3380..49a51277f81d 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
@@ -900,18 +900,47 @@ EXPORT_SYMBOL_GPL(acpi_dev_resume_early); | |||
900 | */ | 900 | */ |
901 | int acpi_subsys_prepare(struct device *dev) | 901 | int acpi_subsys_prepare(struct device *dev) |
902 | { | 902 | { |
903 | /* | 903 | struct acpi_device *adev = ACPI_COMPANION(dev); |
904 | * Devices having power.ignore_children set may still be necessary for | 904 | u32 sys_target; |
905 | * suspending their children in the next phase of device suspend. | 905 | int ret, state; |
906 | */ | 906 | |
907 | if (dev->power.ignore_children) | 907 | ret = pm_generic_prepare(dev); |
908 | pm_runtime_resume(dev); | 908 | if (ret < 0) |
909 | return ret; | ||
910 | |||
911 | if (!adev || !pm_runtime_suspended(dev) | ||
912 | || device_may_wakeup(dev) != !!adev->wakeup.prepare_count) | ||
913 | return 0; | ||
914 | |||
915 | sys_target = acpi_target_system_state(); | ||
916 | if (sys_target == ACPI_STATE_S0) | ||
917 | return 1; | ||
909 | 918 | ||
910 | return pm_generic_prepare(dev); | 919 | if (adev->power.flags.dsw_present) |
920 | return 0; | ||
921 | |||
922 | ret = acpi_dev_pm_get_state(dev, adev, sys_target, NULL, &state); | ||
923 | return !ret && state == adev->power.state; | ||
911 | } | 924 | } |
912 | EXPORT_SYMBOL_GPL(acpi_subsys_prepare); | 925 | EXPORT_SYMBOL_GPL(acpi_subsys_prepare); |
913 | 926 | ||
914 | /** | 927 | /** |
928 | * acpi_subsys_complete - Finalize device's resume during system resume. | ||
929 | * @dev: Device to handle. | ||
930 | */ | ||
931 | void acpi_subsys_complete(struct device *dev) | ||
932 | { | ||
933 | /* | ||
934 | * If the device had been runtime-suspended before the system went into | ||
935 | * the sleep state it is going out of and it has never been resumed till | ||
936 | * now, resume it in case the firmware powered it up. | ||
937 | */ | ||
938 | if (dev->power.direct_complete) | ||
939 | pm_request_resume(dev); | ||
940 | } | ||
941 | EXPORT_SYMBOL_GPL(acpi_subsys_complete); | ||
942 | |||
943 | /** | ||
915 | * acpi_subsys_suspend - Run the device driver's suspend callback. | 944 | * acpi_subsys_suspend - Run the device driver's suspend callback. |
916 | * @dev: Device to handle. | 945 | * @dev: Device to handle. |
917 | * | 946 | * |
@@ -923,6 +952,7 @@ int acpi_subsys_suspend(struct device *dev) | |||
923 | pm_runtime_resume(dev); | 952 | pm_runtime_resume(dev); |
924 | return pm_generic_suspend(dev); | 953 | return pm_generic_suspend(dev); |
925 | } | 954 | } |
955 | EXPORT_SYMBOL_GPL(acpi_subsys_suspend); | ||
926 | 956 | ||
927 | /** | 957 | /** |
928 | * acpi_subsys_suspend_late - Suspend device using ACPI. | 958 | * acpi_subsys_suspend_late - Suspend device using ACPI. |
@@ -968,6 +998,7 @@ int acpi_subsys_freeze(struct device *dev) | |||
968 | pm_runtime_resume(dev); | 998 | pm_runtime_resume(dev); |
969 | return pm_generic_freeze(dev); | 999 | return pm_generic_freeze(dev); |
970 | } | 1000 | } |
1001 | EXPORT_SYMBOL_GPL(acpi_subsys_freeze); | ||
971 | 1002 | ||
972 | #endif /* CONFIG_PM_SLEEP */ | 1003 | #endif /* CONFIG_PM_SLEEP */ |
973 | 1004 | ||
@@ -979,6 +1010,7 @@ static struct dev_pm_domain acpi_general_pm_domain = { | |||
979 | #endif | 1010 | #endif |
980 | #ifdef CONFIG_PM_SLEEP | 1011 | #ifdef CONFIG_PM_SLEEP |
981 | .prepare = acpi_subsys_prepare, | 1012 | .prepare = acpi_subsys_prepare, |
1013 | .complete = acpi_subsys_complete, | ||
982 | .suspend = acpi_subsys_suspend, | 1014 | .suspend = acpi_subsys_suspend, |
983 | .suspend_late = acpi_subsys_suspend_late, | 1015 | .suspend_late = acpi_subsys_suspend_late, |
984 | .resume_early = acpi_subsys_resume_early, | 1016 | .resume_early = acpi_subsys_resume_early, |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 957391306cbf..bb7de413d06d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -180,8 +180,7 @@ static inline void suspend_nvs_restore(void) {} | |||
180 | -------------------------------------------------------------------------- */ | 180 | -------------------------------------------------------------------------- */ |
181 | struct platform_device; | 181 | struct platform_device; |
182 | 182 | ||
183 | int acpi_create_platform_device(struct acpi_device *adev, | 183 | struct platform_device *acpi_create_platform_device(struct acpi_device *adev); |
184 | const struct acpi_device_id *id); | ||
185 | 184 | ||
186 | /*-------------------------------------------------------------------------- | 185 | /*-------------------------------------------------------------------------- |
187 | Video | 186 | Video |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7efe546a8c42..df6e4c924b35 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -1551,9 +1551,13 @@ static void acpi_bus_get_power_flags(struct acpi_device *device) | |||
1551 | */ | 1551 | */ |
1552 | if (acpi_has_method(device->handle, "_PSC")) | 1552 | if (acpi_has_method(device->handle, "_PSC")) |
1553 | device->power.flags.explicit_get = 1; | 1553 | device->power.flags.explicit_get = 1; |
1554 | |||
1554 | if (acpi_has_method(device->handle, "_IRC")) | 1555 | if (acpi_has_method(device->handle, "_IRC")) |
1555 | device->power.flags.inrush_current = 1; | 1556 | device->power.flags.inrush_current = 1; |
1556 | 1557 | ||
1558 | if (acpi_has_method(device->handle, "_DSW")) | ||
1559 | device->power.flags.dsw_present = 1; | ||
1560 | |||
1557 | /* | 1561 | /* |
1558 | * Enumerate supported power management states | 1562 | * Enumerate supported power management states |
1559 | */ | 1563 | */ |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index c40fb2e81bbc..c11e3795431b 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -89,6 +89,7 @@ u32 acpi_target_system_state(void) | |||
89 | { | 89 | { |
90 | return acpi_target_sleep_state; | 90 | return acpi_target_sleep_state; |
91 | } | 91 | } |
92 | EXPORT_SYMBOL_GPL(acpi_target_system_state); | ||
92 | 93 | ||
93 | static bool pwr_btn_event_pending; | 94 | static bool pwr_btn_event_pending; |
94 | 95 | ||
@@ -611,6 +612,22 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = { | |||
611 | .recover = acpi_pm_finish, | 612 | .recover = acpi_pm_finish, |
612 | }; | 613 | }; |
613 | 614 | ||
615 | static int acpi_freeze_begin(void) | ||
616 | { | ||
617 | acpi_scan_lock_acquire(); | ||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | static void acpi_freeze_end(void) | ||
622 | { | ||
623 | acpi_scan_lock_release(); | ||
624 | } | ||
625 | |||
626 | static const struct platform_freeze_ops acpi_freeze_ops = { | ||
627 | .begin = acpi_freeze_begin, | ||
628 | .end = acpi_freeze_end, | ||
629 | }; | ||
630 | |||
614 | static void acpi_sleep_suspend_setup(void) | 631 | static void acpi_sleep_suspend_setup(void) |
615 | { | 632 | { |
616 | int i; | 633 | int i; |
@@ -621,7 +638,9 @@ static void acpi_sleep_suspend_setup(void) | |||
621 | 638 | ||
622 | suspend_set_ops(old_suspend_ordering ? | 639 | suspend_set_ops(old_suspend_ordering ? |
623 | &acpi_suspend_ops_old : &acpi_suspend_ops); | 640 | &acpi_suspend_ops_old : &acpi_suspend_ops); |
641 | freeze_set_ops(&acpi_freeze_ops); | ||
624 | } | 642 | } |
643 | |||
625 | #else /* !CONFIG_SUSPEND */ | 644 | #else /* !CONFIG_SUSPEND */ |
626 | static inline void acpi_sleep_suspend_setup(void) {} | 645 | static inline void acpi_sleep_suspend_setup(void) {} |
627 | #endif /* !CONFIG_SUSPEND */ | 646 | #endif /* !CONFIG_SUSPEND */ |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 86d5e4fb5b98..343ffad59377 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -479,7 +479,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn | |||
479 | TRACE_DEVICE(dev); | 479 | TRACE_DEVICE(dev); |
480 | TRACE_RESUME(0); | 480 | TRACE_RESUME(0); |
481 | 481 | ||
482 | if (dev->power.syscore) | 482 | if (dev->power.syscore || dev->power.direct_complete) |
483 | goto Out; | 483 | goto Out; |
484 | 484 | ||
485 | if (!dev->power.is_noirq_suspended) | 485 | if (!dev->power.is_noirq_suspended) |
@@ -605,7 +605,7 @@ static int device_resume_early(struct device *dev, pm_message_t state, bool asyn | |||
605 | TRACE_DEVICE(dev); | 605 | TRACE_DEVICE(dev); |
606 | TRACE_RESUME(0); | 606 | TRACE_RESUME(0); |
607 | 607 | ||
608 | if (dev->power.syscore) | 608 | if (dev->power.syscore || dev->power.direct_complete) |
609 | goto Out; | 609 | goto Out; |
610 | 610 | ||
611 | if (!dev->power.is_late_suspended) | 611 | if (!dev->power.is_late_suspended) |
@@ -735,6 +735,12 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
735 | if (dev->power.syscore) | 735 | if (dev->power.syscore) |
736 | goto Complete; | 736 | goto Complete; |
737 | 737 | ||
738 | if (dev->power.direct_complete) { | ||
739 | /* Match the pm_runtime_disable() in __device_suspend(). */ | ||
740 | pm_runtime_enable(dev); | ||
741 | goto Complete; | ||
742 | } | ||
743 | |||
738 | dpm_wait(dev->parent, async); | 744 | dpm_wait(dev->parent, async); |
739 | dpm_watchdog_set(&wd, dev); | 745 | dpm_watchdog_set(&wd, dev); |
740 | device_lock(dev); | 746 | device_lock(dev); |
@@ -1007,7 +1013,7 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a | |||
1007 | goto Complete; | 1013 | goto Complete; |
1008 | } | 1014 | } |
1009 | 1015 | ||
1010 | if (dev->power.syscore) | 1016 | if (dev->power.syscore || dev->power.direct_complete) |
1011 | goto Complete; | 1017 | goto Complete; |
1012 | 1018 | ||
1013 | dpm_wait_for_children(dev, async); | 1019 | dpm_wait_for_children(dev, async); |
@@ -1146,7 +1152,7 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as | |||
1146 | goto Complete; | 1152 | goto Complete; |
1147 | } | 1153 | } |
1148 | 1154 | ||
1149 | if (dev->power.syscore) | 1155 | if (dev->power.syscore || dev->power.direct_complete) |
1150 | goto Complete; | 1156 | goto Complete; |
1151 | 1157 | ||
1152 | dpm_wait_for_children(dev, async); | 1158 | dpm_wait_for_children(dev, async); |
@@ -1332,6 +1338,17 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
1332 | if (dev->power.syscore) | 1338 | if (dev->power.syscore) |
1333 | goto Complete; | 1339 | goto Complete; |
1334 | 1340 | ||
1341 | if (dev->power.direct_complete) { | ||
1342 | if (pm_runtime_status_suspended(dev)) { | ||
1343 | pm_runtime_disable(dev); | ||
1344 | if (pm_runtime_suspended_if_enabled(dev)) | ||
1345 | goto Complete; | ||
1346 | |||
1347 | pm_runtime_enable(dev); | ||
1348 | } | ||
1349 | dev->power.direct_complete = false; | ||
1350 | } | ||
1351 | |||
1335 | dpm_watchdog_set(&wd, dev); | 1352 | dpm_watchdog_set(&wd, dev); |
1336 | device_lock(dev); | 1353 | device_lock(dev); |
1337 | 1354 | ||
@@ -1382,10 +1399,19 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
1382 | 1399 | ||
1383 | End: | 1400 | End: |
1384 | if (!error) { | 1401 | if (!error) { |
1402 | struct device *parent = dev->parent; | ||
1403 | |||
1385 | dev->power.is_suspended = true; | 1404 | dev->power.is_suspended = true; |
1386 | if (dev->power.wakeup_path | 1405 | if (parent) { |
1387 | && dev->parent && !dev->parent->power.ignore_children) | 1406 | spin_lock_irq(&parent->power.lock); |
1388 | dev->parent->power.wakeup_path = true; | 1407 | |
1408 | dev->parent->power.direct_complete = false; | ||
1409 | if (dev->power.wakeup_path | ||
1410 | && !dev->parent->power.ignore_children) | ||
1411 | dev->parent->power.wakeup_path = true; | ||
1412 | |||
1413 | spin_unlock_irq(&parent->power.lock); | ||
1414 | } | ||
1389 | } | 1415 | } |
1390 | 1416 | ||
1391 | device_unlock(dev); | 1417 | device_unlock(dev); |
@@ -1487,7 +1513,7 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
1487 | { | 1513 | { |
1488 | int (*callback)(struct device *) = NULL; | 1514 | int (*callback)(struct device *) = NULL; |
1489 | char *info = NULL; | 1515 | char *info = NULL; |
1490 | int error = 0; | 1516 | int ret = 0; |
1491 | 1517 | ||
1492 | if (dev->power.syscore) | 1518 | if (dev->power.syscore) |
1493 | return 0; | 1519 | return 0; |
@@ -1523,17 +1549,27 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
1523 | callback = dev->driver->pm->prepare; | 1549 | callback = dev->driver->pm->prepare; |
1524 | } | 1550 | } |
1525 | 1551 | ||
1526 | if (callback) { | 1552 | if (callback) |
1527 | error = callback(dev); | 1553 | ret = callback(dev); |
1528 | suspend_report_result(callback, error); | ||
1529 | } | ||
1530 | 1554 | ||
1531 | device_unlock(dev); | 1555 | device_unlock(dev); |
1532 | 1556 | ||
1533 | if (error) | 1557 | if (ret < 0) { |
1558 | suspend_report_result(callback, ret); | ||
1534 | pm_runtime_put(dev); | 1559 | pm_runtime_put(dev); |
1535 | 1560 | return ret; | |
1536 | return error; | 1561 | } |
1562 | /* | ||
1563 | * A positive return value from ->prepare() means "this device appears | ||
1564 | * to be runtime-suspended and its state is fine, so if it really is | ||
1565 | * runtime-suspended, you can leave it in that state provided that you | ||
1566 | * will do the same thing with all of its descendants". This only | ||
1567 | * applies to suspend transitions, however. | ||
1568 | */ | ||
1569 | spin_lock_irq(&dev->power.lock); | ||
1570 | dev->power.direct_complete = ret > 0 && state.event == PM_EVENT_SUSPEND; | ||
1571 | spin_unlock_irq(&dev->power.lock); | ||
1572 | return 0; | ||
1537 | } | 1573 | } |
1538 | 1574 | ||
1539 | /** | 1575 | /** |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5f8a28735c96..0745059b1834 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o | |||
8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o | 8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o |
9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o | 9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o |
10 | obj-$(CONFIG_COMMON_CLK) += clk-composite.o | 10 | obj-$(CONFIG_COMMON_CLK) += clk-composite.o |
11 | obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o | ||
11 | 12 | ||
12 | # hardware specific clock types | 13 | # hardware specific clock types |
13 | # please keep this section sorted lexicographically by file/directory path name | 14 | # please keep this section sorted lexicographically by file/directory path name |
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c new file mode 100644 index 000000000000..ede685ca0d20 --- /dev/null +++ b/drivers/clk/clk-fractional-divider.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Intel Corporation | ||
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 | * Adjustable fractional divider clock implementation. | ||
9 | * Output rate = (m / n) * parent_rate. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/gcd.h> | ||
17 | |||
18 | #define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw) | ||
19 | |||
20 | static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, | ||
21 | unsigned long parent_rate) | ||
22 | { | ||
23 | struct clk_fractional_divider *fd = to_clk_fd(hw); | ||
24 | unsigned long flags = 0; | ||
25 | u32 val, m, n; | ||
26 | u64 ret; | ||
27 | |||
28 | if (fd->lock) | ||
29 | spin_lock_irqsave(fd->lock, flags); | ||
30 | |||
31 | val = clk_readl(fd->reg); | ||
32 | |||
33 | if (fd->lock) | ||
34 | spin_unlock_irqrestore(fd->lock, flags); | ||
35 | |||
36 | m = (val & fd->mmask) >> fd->mshift; | ||
37 | n = (val & fd->nmask) >> fd->nshift; | ||
38 | |||
39 | ret = parent_rate * m; | ||
40 | do_div(ret, n); | ||
41 | |||
42 | return ret; | ||
43 | } | ||
44 | |||
45 | static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, | ||
46 | unsigned long *prate) | ||
47 | { | ||
48 | struct clk_fractional_divider *fd = to_clk_fd(hw); | ||
49 | unsigned maxn = (fd->nmask >> fd->nshift) + 1; | ||
50 | unsigned div; | ||
51 | |||
52 | if (!rate || rate >= *prate) | ||
53 | return *prate; | ||
54 | |||
55 | div = gcd(*prate, rate); | ||
56 | |||
57 | while ((*prate / div) > maxn) { | ||
58 | div <<= 1; | ||
59 | rate <<= 1; | ||
60 | } | ||
61 | |||
62 | return rate; | ||
63 | } | ||
64 | |||
65 | static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate, | ||
66 | unsigned long parent_rate) | ||
67 | { | ||
68 | struct clk_fractional_divider *fd = to_clk_fd(hw); | ||
69 | unsigned long flags = 0; | ||
70 | unsigned long div; | ||
71 | unsigned n, m; | ||
72 | u32 val; | ||
73 | |||
74 | div = gcd(parent_rate, rate); | ||
75 | m = rate / div; | ||
76 | n = parent_rate / div; | ||
77 | |||
78 | if (fd->lock) | ||
79 | spin_lock_irqsave(fd->lock, flags); | ||
80 | |||
81 | val = clk_readl(fd->reg); | ||
82 | val &= ~(fd->mmask | fd->nmask); | ||
83 | val |= (m << fd->mshift) | (n << fd->nshift); | ||
84 | clk_writel(val, fd->reg); | ||
85 | |||
86 | if (fd->lock) | ||
87 | spin_unlock_irqrestore(fd->lock, flags); | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | const struct clk_ops clk_fractional_divider_ops = { | ||
93 | .recalc_rate = clk_fd_recalc_rate, | ||
94 | .round_rate = clk_fd_round_rate, | ||
95 | .set_rate = clk_fd_set_rate, | ||
96 | }; | ||
97 | EXPORT_SYMBOL_GPL(clk_fractional_divider_ops); | ||
98 | |||
99 | struct clk *clk_register_fractional_divider(struct device *dev, | ||
100 | const char *name, const char *parent_name, unsigned long flags, | ||
101 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, | ||
102 | u8 clk_divider_flags, spinlock_t *lock) | ||
103 | { | ||
104 | struct clk_fractional_divider *fd; | ||
105 | struct clk_init_data init; | ||
106 | struct clk *clk; | ||
107 | |||
108 | fd = kzalloc(sizeof(*fd), GFP_KERNEL); | ||
109 | if (!fd) { | ||
110 | dev_err(dev, "could not allocate fractional divider clk\n"); | ||
111 | return ERR_PTR(-ENOMEM); | ||
112 | } | ||
113 | |||
114 | init.name = name; | ||
115 | init.ops = &clk_fractional_divider_ops; | ||
116 | init.flags = flags | CLK_IS_BASIC; | ||
117 | init.parent_names = parent_name ? &parent_name : NULL; | ||
118 | init.num_parents = parent_name ? 1 : 0; | ||
119 | |||
120 | fd->reg = reg; | ||
121 | fd->mshift = mshift; | ||
122 | fd->mmask = (BIT(mwidth) - 1) << mshift; | ||
123 | fd->nshift = nshift; | ||
124 | fd->nmask = (BIT(nwidth) - 1) << nshift; | ||
125 | fd->flags = clk_divider_flags; | ||
126 | fd->lock = lock; | ||
127 | fd->hw.init = &init; | ||
128 | |||
129 | clk = clk_register(dev, &fd->hw); | ||
130 | if (IS_ERR(clk)) | ||
131 | kfree(fd); | ||
132 | |||
133 | return clk; | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(clk_register_fractional_divider); | ||
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 8236746e46bb..cb7019977c50 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -32,6 +32,7 @@ LIST_HEAD(cpuidle_detected_devices); | |||
32 | static int enabled_devices; | 32 | static int enabled_devices; |
33 | static int off __read_mostly; | 33 | static int off __read_mostly; |
34 | static int initialized __read_mostly; | 34 | static int initialized __read_mostly; |
35 | static bool use_deepest_state __read_mostly; | ||
35 | 36 | ||
36 | int cpuidle_disabled(void) | 37 | int cpuidle_disabled(void) |
37 | { | 38 | { |
@@ -65,23 +66,42 @@ int cpuidle_play_dead(void) | |||
65 | } | 66 | } |
66 | 67 | ||
67 | /** | 68 | /** |
68 | * cpuidle_enabled - check if the cpuidle framework is ready | 69 | * cpuidle_use_deepest_state - Enable/disable the "deepest idle" mode. |
69 | * @dev: cpuidle device for this cpu | 70 | * @enable: Whether enable or disable the feature. |
70 | * @drv: cpuidle driver for this cpu | 71 | * |
72 | * If the "deepest idle" mode is enabled, cpuidle will ignore the governor and | ||
73 | * always use the state with the greatest exit latency (out of the states that | ||
74 | * are not disabled). | ||
71 | * | 75 | * |
72 | * Return 0 on success, otherwise: | 76 | * This function can only be called after cpuidle_pause() to avoid races. |
73 | * -NODEV : the cpuidle framework is not available | ||
74 | * -EBUSY : the cpuidle framework is not initialized | ||
75 | */ | 77 | */ |
76 | int cpuidle_enabled(struct cpuidle_driver *drv, struct cpuidle_device *dev) | 78 | void cpuidle_use_deepest_state(bool enable) |
77 | { | 79 | { |
78 | if (off || !initialized) | 80 | use_deepest_state = enable; |
79 | return -ENODEV; | 81 | } |
80 | 82 | ||
81 | if (!drv || !dev || !dev->enabled) | 83 | /** |
82 | return -EBUSY; | 84 | * cpuidle_find_deepest_state - Find the state of the greatest exit latency. |
85 | * @drv: cpuidle driver for a given CPU. | ||
86 | * @dev: cpuidle device for a given CPU. | ||
87 | */ | ||
88 | static int cpuidle_find_deepest_state(struct cpuidle_driver *drv, | ||
89 | struct cpuidle_device *dev) | ||
90 | { | ||
91 | unsigned int latency_req = 0; | ||
92 | int i, ret = CPUIDLE_DRIVER_STATE_START - 1; | ||
83 | 93 | ||
84 | return 0; | 94 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { |
95 | struct cpuidle_state *s = &drv->states[i]; | ||
96 | struct cpuidle_state_usage *su = &dev->states_usage[i]; | ||
97 | |||
98 | if (s->disabled || su->disable || s->exit_latency <= latency_req) | ||
99 | continue; | ||
100 | |||
101 | latency_req = s->exit_latency; | ||
102 | ret = i; | ||
103 | } | ||
104 | return ret; | ||
85 | } | 105 | } |
86 | 106 | ||
87 | /** | 107 | /** |
@@ -138,6 +158,15 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, | |||
138 | */ | 158 | */ |
139 | int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | 159 | int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) |
140 | { | 160 | { |
161 | if (off || !initialized) | ||
162 | return -ENODEV; | ||
163 | |||
164 | if (!drv || !dev || !dev->enabled) | ||
165 | return -EBUSY; | ||
166 | |||
167 | if (unlikely(use_deepest_state)) | ||
168 | return cpuidle_find_deepest_state(drv, dev); | ||
169 | |||
141 | return cpuidle_curr_governor->select(drv, dev); | 170 | return cpuidle_curr_governor->select(drv, dev); |
142 | } | 171 | } |
143 | 172 | ||
@@ -169,7 +198,7 @@ int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, | |||
169 | */ | 198 | */ |
170 | void cpuidle_reflect(struct cpuidle_device *dev, int index) | 199 | void cpuidle_reflect(struct cpuidle_device *dev, int index) |
171 | { | 200 | { |
172 | if (cpuidle_curr_governor->reflect) | 201 | if (cpuidle_curr_governor->reflect && !unlikely(use_deepest_state)) |
173 | cpuidle_curr_governor->reflect(dev, index); | 202 | cpuidle_curr_governor->reflect(dev, index); |
174 | } | 203 | } |
175 | 204 | ||
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 71b523293354..c4f80c15a48d 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -296,7 +296,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
296 | data->needs_update = 0; | 296 | data->needs_update = 0; |
297 | } | 297 | } |
298 | 298 | ||
299 | data->last_state_idx = 0; | 299 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1; |
300 | 300 | ||
301 | /* Special case when user has set very strict latency requirement */ | 301 | /* Special case when user has set very strict latency requirement */ |
302 | if (unlikely(latency_req == 0)) | 302 | if (unlikely(latency_req == 0)) |
@@ -311,13 +311,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
311 | data->bucket = which_bucket(data->next_timer_us); | 311 | data->bucket = which_bucket(data->next_timer_us); |
312 | 312 | ||
313 | /* | 313 | /* |
314 | * if the correction factor is 0 (eg first time init or cpu hotplug | ||
315 | * etc), we actually want to start out with a unity factor. | ||
316 | */ | ||
317 | if (data->correction_factor[data->bucket] == 0) | ||
318 | data->correction_factor[data->bucket] = RESOLUTION * DECAY; | ||
319 | |||
320 | /* | ||
321 | * Force the result of multiplication to be 64 bits even if both | 314 | * Force the result of multiplication to be 64 bits even if both |
322 | * operands are 32 bits. | 315 | * operands are 32 bits. |
323 | * Make sure to round up for half microseconds. | 316 | * Make sure to round up for half microseconds. |
@@ -466,9 +459,17 @@ static int menu_enable_device(struct cpuidle_driver *drv, | |||
466 | struct cpuidle_device *dev) | 459 | struct cpuidle_device *dev) |
467 | { | 460 | { |
468 | struct menu_device *data = &per_cpu(menu_devices, dev->cpu); | 461 | struct menu_device *data = &per_cpu(menu_devices, dev->cpu); |
462 | int i; | ||
469 | 463 | ||
470 | memset(data, 0, sizeof(struct menu_device)); | 464 | memset(data, 0, sizeof(struct menu_device)); |
471 | 465 | ||
466 | /* | ||
467 | * if the correction factor is 0 (eg first time init or cpu hotplug | ||
468 | * etc), we actually want to start out with a unity factor. | ||
469 | */ | ||
470 | for(i = 0; i < BUCKETS; i++) | ||
471 | data->correction_factor[i] = RESOLUTION * DECAY; | ||
472 | |||
472 | return 0; | 473 | return 0; |
473 | } | 474 | } |
474 | 475 | ||
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 84a2e29a2314..7417a16c8d86 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -261,7 +261,8 @@ struct acpi_device_power_flags { | |||
261 | u32 inrush_current:1; /* Serialize Dx->D0 */ | 261 | u32 inrush_current:1; /* Serialize Dx->D0 */ |
262 | u32 power_removed:1; /* Optimize Dx->D0 */ | 262 | u32 power_removed:1; /* Optimize Dx->D0 */ |
263 | u32 ignore_parent:1; /* Power is independent of parent power state */ | 263 | u32 ignore_parent:1; /* Power is independent of parent power state */ |
264 | u32 reserved:27; | 264 | u32 dsw_present:1; /* _DSW present? */ |
265 | u32 reserved:26; | ||
265 | }; | 266 | }; |
266 | 267 | ||
267 | struct acpi_device_power_state { | 268 | struct acpi_device_power_state { |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 7a8f2cd66c8b..4c007262e891 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -554,14 +554,20 @@ static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; } | |||
554 | int acpi_dev_suspend_late(struct device *dev); | 554 | int acpi_dev_suspend_late(struct device *dev); |
555 | int acpi_dev_resume_early(struct device *dev); | 555 | int acpi_dev_resume_early(struct device *dev); |
556 | int acpi_subsys_prepare(struct device *dev); | 556 | int acpi_subsys_prepare(struct device *dev); |
557 | void acpi_subsys_complete(struct device *dev); | ||
557 | int acpi_subsys_suspend_late(struct device *dev); | 558 | int acpi_subsys_suspend_late(struct device *dev); |
558 | int acpi_subsys_resume_early(struct device *dev); | 559 | int acpi_subsys_resume_early(struct device *dev); |
560 | int acpi_subsys_suspend(struct device *dev); | ||
561 | int acpi_subsys_freeze(struct device *dev); | ||
559 | #else | 562 | #else |
560 | static inline int acpi_dev_suspend_late(struct device *dev) { return 0; } | 563 | static inline int acpi_dev_suspend_late(struct device *dev) { return 0; } |
561 | static inline int acpi_dev_resume_early(struct device *dev) { return 0; } | 564 | static inline int acpi_dev_resume_early(struct device *dev) { return 0; } |
562 | static inline int acpi_subsys_prepare(struct device *dev) { return 0; } | 565 | static inline int acpi_subsys_prepare(struct device *dev) { return 0; } |
566 | static inline void acpi_subsys_complete(struct device *dev) {} | ||
563 | static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; } | 567 | static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; } |
564 | static inline int acpi_subsys_resume_early(struct device *dev) { return 0; } | 568 | static inline int acpi_subsys_resume_early(struct device *dev) { return 0; } |
569 | static inline int acpi_subsys_suspend(struct device *dev) { return 0; } | ||
570 | static inline int acpi_subsys_freeze(struct device *dev) { return 0; } | ||
565 | #endif | 571 | #endif |
566 | 572 | ||
567 | #if defined(CONFIG_ACPI) && defined(CONFIG_PM) | 573 | #if defined(CONFIG_ACPI) && defined(CONFIG_PM) |
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 511917416fb0..fb4eca6907cd 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
@@ -413,6 +413,37 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, | |||
413 | const char *parent_name, unsigned long flags, | 413 | const char *parent_name, unsigned long flags, |
414 | unsigned int mult, unsigned int div); | 414 | unsigned int mult, unsigned int div); |
415 | 415 | ||
416 | /** | ||
417 | * struct clk_fractional_divider - adjustable fractional divider clock | ||
418 | * | ||
419 | * @hw: handle between common and hardware-specific interfaces | ||
420 | * @reg: register containing the divider | ||
421 | * @mshift: shift to the numerator bit field | ||
422 | * @mwidth: width of the numerator bit field | ||
423 | * @nshift: shift to the denominator bit field | ||
424 | * @nwidth: width of the denominator bit field | ||
425 | * @lock: register lock | ||
426 | * | ||
427 | * Clock with adjustable fractional divider affecting its output frequency. | ||
428 | */ | ||
429 | |||
430 | struct clk_fractional_divider { | ||
431 | struct clk_hw hw; | ||
432 | void __iomem *reg; | ||
433 | u8 mshift; | ||
434 | u32 mmask; | ||
435 | u8 nshift; | ||
436 | u32 nmask; | ||
437 | u8 flags; | ||
438 | spinlock_t *lock; | ||
439 | }; | ||
440 | |||
441 | extern const struct clk_ops clk_fractional_divider_ops; | ||
442 | struct clk *clk_register_fractional_divider(struct device *dev, | ||
443 | const char *name, const char *parent_name, unsigned long flags, | ||
444 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, | ||
445 | u8 clk_divider_flags, spinlock_t *lock); | ||
446 | |||
416 | /*** | 447 | /*** |
417 | * struct clk_composite - aggregate clock of mux, divider and gate clocks | 448 | * struct clk_composite - aggregate clock of mux, divider and gate clocks |
418 | * | 449 | * |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index b0238cba440b..c51a436135c4 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
@@ -120,8 +120,6 @@ struct cpuidle_driver { | |||
120 | #ifdef CONFIG_CPU_IDLE | 120 | #ifdef CONFIG_CPU_IDLE |
121 | extern void disable_cpuidle(void); | 121 | extern void disable_cpuidle(void); |
122 | 122 | ||
123 | extern int cpuidle_enabled(struct cpuidle_driver *drv, | ||
124 | struct cpuidle_device *dev); | ||
125 | extern int cpuidle_select(struct cpuidle_driver *drv, | 123 | extern int cpuidle_select(struct cpuidle_driver *drv, |
126 | struct cpuidle_device *dev); | 124 | struct cpuidle_device *dev); |
127 | extern int cpuidle_enter(struct cpuidle_driver *drv, | 125 | extern int cpuidle_enter(struct cpuidle_driver *drv, |
@@ -145,13 +143,11 @@ extern void cpuidle_resume(void); | |||
145 | extern int cpuidle_enable_device(struct cpuidle_device *dev); | 143 | extern int cpuidle_enable_device(struct cpuidle_device *dev); |
146 | extern void cpuidle_disable_device(struct cpuidle_device *dev); | 144 | extern void cpuidle_disable_device(struct cpuidle_device *dev); |
147 | extern int cpuidle_play_dead(void); | 145 | extern int cpuidle_play_dead(void); |
146 | extern void cpuidle_use_deepest_state(bool enable); | ||
148 | 147 | ||
149 | extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); | 148 | extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); |
150 | #else | 149 | #else |
151 | static inline void disable_cpuidle(void) { } | 150 | static inline void disable_cpuidle(void) { } |
152 | static inline int cpuidle_enabled(struct cpuidle_driver *drv, | ||
153 | struct cpuidle_device *dev) | ||
154 | {return -ENODEV; } | ||
155 | static inline int cpuidle_select(struct cpuidle_driver *drv, | 151 | static inline int cpuidle_select(struct cpuidle_driver *drv, |
156 | struct cpuidle_device *dev) | 152 | struct cpuidle_device *dev) |
157 | {return -ENODEV; } | 153 | {return -ENODEV; } |
@@ -180,6 +176,7 @@ static inline int cpuidle_enable_device(struct cpuidle_device *dev) | |||
180 | {return -ENODEV; } | 176 | {return -ENODEV; } |
181 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } | 177 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } |
182 | static inline int cpuidle_play_dead(void) {return -ENODEV; } | 178 | static inline int cpuidle_play_dead(void) {return -ENODEV; } |
179 | static inline void cpuidle_use_deepest_state(bool enable) {} | ||
183 | static inline struct cpuidle_driver *cpuidle_get_cpu_driver( | 180 | static inline struct cpuidle_driver *cpuidle_get_cpu_driver( |
184 | struct cpuidle_device *dev) {return NULL; } | 181 | struct cpuidle_device *dev) {return NULL; } |
185 | #endif | 182 | #endif |
diff --git a/include/linux/pm.h b/include/linux/pm.h index d915d0345fa1..72c0fe098a27 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -93,13 +93,23 @@ typedef struct pm_message { | |||
93 | * been registered) to recover from the race condition. | 93 | * been registered) to recover from the race condition. |
94 | * This method is executed for all kinds of suspend transitions and is | 94 | * This method is executed for all kinds of suspend transitions and is |
95 | * followed by one of the suspend callbacks: @suspend(), @freeze(), or | 95 | * followed by one of the suspend callbacks: @suspend(), @freeze(), or |
96 | * @poweroff(). The PM core executes subsystem-level @prepare() for all | 96 | * @poweroff(). If the transition is a suspend to memory or standby (that |
97 | * devices before starting to invoke suspend callbacks for any of them, so | 97 | * is, not related to hibernation), the return value of @prepare() may be |
98 | * generally devices may be assumed to be functional or to respond to | 98 | * used to indicate to the PM core to leave the device in runtime suspend |
99 | * runtime resume requests while @prepare() is being executed. However, | 99 | * if applicable. Namely, if @prepare() returns a positive number, the PM |
100 | * device drivers may NOT assume anything about the availability of user | 100 | * core will understand that as a declaration that the device appears to be |
101 | * space at that time and it is NOT valid to request firmware from within | 101 | * runtime-suspended and it may be left in that state during the entire |
102 | * @prepare() (it's too late to do that). It also is NOT valid to allocate | 102 | * transition and during the subsequent resume if all of its descendants |
103 | * are left in runtime suspend too. If that happens, @complete() will be | ||
104 | * executed directly after @prepare() and it must ensure the proper | ||
105 | * functioning of the device after the system resume. | ||
106 | * The PM core executes subsystem-level @prepare() for all devices before | ||
107 | * starting to invoke suspend callbacks for any of them, so generally | ||
108 | * devices may be assumed to be functional or to respond to runtime resume | ||
109 | * requests while @prepare() is being executed. However, device drivers | ||
110 | * may NOT assume anything about the availability of user space at that | ||
111 | * time and it is NOT valid to request firmware from within @prepare() | ||
112 | * (it's too late to do that). It also is NOT valid to allocate | ||
103 | * substantial amounts of memory from @prepare() in the GFP_KERNEL mode. | 113 | * substantial amounts of memory from @prepare() in the GFP_KERNEL mode. |
104 | * [To work around these limitations, drivers may register suspend and | 114 | * [To work around these limitations, drivers may register suspend and |
105 | * hibernation notifiers to be executed before the freezing of tasks.] | 115 | * hibernation notifiers to be executed before the freezing of tasks.] |
@@ -112,7 +122,16 @@ typedef struct pm_message { | |||
112 | * of the other devices that the PM core has unsuccessfully attempted to | 122 | * of the other devices that the PM core has unsuccessfully attempted to |
113 | * suspend earlier). | 123 | * suspend earlier). |
114 | * The PM core executes subsystem-level @complete() after it has executed | 124 | * The PM core executes subsystem-level @complete() after it has executed |
115 | * the appropriate resume callbacks for all devices. | 125 | * the appropriate resume callbacks for all devices. If the corresponding |
126 | * @prepare() at the beginning of the suspend transition returned a | ||
127 | * positive number and the device was left in runtime suspend (without | ||
128 | * executing any suspend and resume callbacks for it), @complete() will be | ||
129 | * the only callback executed for the device during resume. In that case, | ||
130 | * @complete() must be prepared to do whatever is necessary to ensure the | ||
131 | * proper functioning of the device after the system resume. To this end, | ||
132 | * @complete() can check the power.direct_complete flag of the device to | ||
133 | * learn whether (unset) or not (set) the previous suspend and resume | ||
134 | * callbacks have been executed for it. | ||
116 | * | 135 | * |
117 | * @suspend: Executed before putting the system into a sleep state in which the | 136 | * @suspend: Executed before putting the system into a sleep state in which the |
118 | * contents of main memory are preserved. The exact action to perform | 137 | * contents of main memory are preserved. The exact action to perform |
@@ -546,6 +565,7 @@ struct dev_pm_info { | |||
546 | bool is_late_suspended:1; | 565 | bool is_late_suspended:1; |
547 | bool ignore_children:1; | 566 | bool ignore_children:1; |
548 | bool early_init:1; /* Owned by the PM core */ | 567 | bool early_init:1; /* Owned by the PM core */ |
568 | bool direct_complete:1; /* Owned by the PM core */ | ||
549 | spinlock_t lock; | 569 | spinlock_t lock; |
550 | #ifdef CONFIG_PM_SLEEP | 570 | #ifdef CONFIG_PM_SLEEP |
551 | struct list_head entry; | 571 | struct list_head entry; |
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 2a5897a4afbc..43fd6716f662 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h | |||
@@ -101,6 +101,11 @@ static inline bool pm_runtime_status_suspended(struct device *dev) | |||
101 | return dev->power.runtime_status == RPM_SUSPENDED; | 101 | return dev->power.runtime_status == RPM_SUSPENDED; |
102 | } | 102 | } |
103 | 103 | ||
104 | static inline bool pm_runtime_suspended_if_enabled(struct device *dev) | ||
105 | { | ||
106 | return pm_runtime_status_suspended(dev) && dev->power.disable_depth == 1; | ||
107 | } | ||
108 | |||
104 | static inline bool pm_runtime_enabled(struct device *dev) | 109 | static inline bool pm_runtime_enabled(struct device *dev) |
105 | { | 110 | { |
106 | return !dev->power.disable_depth; | 111 | return !dev->power.disable_depth; |
@@ -150,6 +155,7 @@ static inline void device_set_run_wake(struct device *dev, bool enable) {} | |||
150 | static inline bool pm_runtime_suspended(struct device *dev) { return false; } | 155 | static inline bool pm_runtime_suspended(struct device *dev) { return false; } |
151 | static inline bool pm_runtime_active(struct device *dev) { return true; } | 156 | static inline bool pm_runtime_active(struct device *dev) { return true; } |
152 | static inline bool pm_runtime_status_suspended(struct device *dev) { return false; } | 157 | static inline bool pm_runtime_status_suspended(struct device *dev) { return false; } |
158 | static inline bool pm_runtime_suspended_if_enabled(struct device *dev) { return false; } | ||
153 | static inline bool pm_runtime_enabled(struct device *dev) { return false; } | 159 | static inline bool pm_runtime_enabled(struct device *dev) { return false; } |
154 | 160 | ||
155 | static inline void pm_runtime_no_callbacks(struct device *dev) {} | 161 | static inline void pm_runtime_no_callbacks(struct device *dev) {} |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index f73cabf59012..91d66fd8dce1 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -187,6 +187,11 @@ struct platform_suspend_ops { | |||
187 | void (*recover)(void); | 187 | void (*recover)(void); |
188 | }; | 188 | }; |
189 | 189 | ||
190 | struct platform_freeze_ops { | ||
191 | int (*begin)(void); | ||
192 | void (*end)(void); | ||
193 | }; | ||
194 | |||
190 | #ifdef CONFIG_SUSPEND | 195 | #ifdef CONFIG_SUSPEND |
191 | /** | 196 | /** |
192 | * suspend_set_ops - set platform dependent suspend operations | 197 | * suspend_set_ops - set platform dependent suspend operations |
@@ -194,6 +199,7 @@ struct platform_suspend_ops { | |||
194 | */ | 199 | */ |
195 | extern void suspend_set_ops(const struct platform_suspend_ops *ops); | 200 | extern void suspend_set_ops(const struct platform_suspend_ops *ops); |
196 | extern int suspend_valid_only_mem(suspend_state_t state); | 201 | extern int suspend_valid_only_mem(suspend_state_t state); |
202 | extern void freeze_set_ops(const struct platform_freeze_ops *ops); | ||
197 | extern void freeze_wake(void); | 203 | extern void freeze_wake(void); |
198 | 204 | ||
199 | /** | 205 | /** |
@@ -220,6 +226,7 @@ extern int pm_suspend(suspend_state_t state); | |||
220 | 226 | ||
221 | static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {} | 227 | static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {} |
222 | static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; } | 228 | static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; } |
229 | static inline void freeze_set_ops(const struct platform_freeze_ops *ops) {} | ||
223 | static inline void freeze_wake(void) {} | 230 | static inline void freeze_wake(void) {} |
224 | #endif /* !CONFIG_SUSPEND */ | 231 | #endif /* !CONFIG_SUSPEND */ |
225 | 232 | ||
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index f4f2073711d3..df88d55dc436 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -35,7 +35,7 @@ | |||
35 | static int nocompress; | 35 | static int nocompress; |
36 | static int noresume; | 36 | static int noresume; |
37 | static int resume_wait; | 37 | static int resume_wait; |
38 | static int resume_delay; | 38 | static unsigned int resume_delay; |
39 | static char resume_file[256] = CONFIG_PM_STD_PARTITION; | 39 | static char resume_file[256] = CONFIG_PM_STD_PARTITION; |
40 | dev_t swsusp_resume_device; | 40 | dev_t swsusp_resume_device; |
41 | sector_t swsusp_resume_block; | 41 | sector_t swsusp_resume_block; |
@@ -228,19 +228,23 @@ static void platform_recover(int platform_mode) | |||
228 | void swsusp_show_speed(struct timeval *start, struct timeval *stop, | 228 | void swsusp_show_speed(struct timeval *start, struct timeval *stop, |
229 | unsigned nr_pages, char *msg) | 229 | unsigned nr_pages, char *msg) |
230 | { | 230 | { |
231 | s64 elapsed_centisecs64; | 231 | u64 elapsed_centisecs64; |
232 | int centisecs; | 232 | unsigned int centisecs; |
233 | int k; | 233 | unsigned int k; |
234 | int kps; | 234 | unsigned int kps; |
235 | 235 | ||
236 | elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start); | 236 | elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start); |
237 | /* | ||
238 | * If "(s64)elapsed_centisecs64 < 0", it will print long elapsed time, | ||
239 | * it is obvious enough for what went wrong. | ||
240 | */ | ||
237 | do_div(elapsed_centisecs64, NSEC_PER_SEC / 100); | 241 | do_div(elapsed_centisecs64, NSEC_PER_SEC / 100); |
238 | centisecs = elapsed_centisecs64; | 242 | centisecs = elapsed_centisecs64; |
239 | if (centisecs == 0) | 243 | if (centisecs == 0) |
240 | centisecs = 1; /* avoid div-by-zero */ | 244 | centisecs = 1; /* avoid div-by-zero */ |
241 | k = nr_pages * (PAGE_SIZE / 1024); | 245 | k = nr_pages * (PAGE_SIZE / 1024); |
242 | kps = (k * 100) / centisecs; | 246 | kps = (k * 100) / centisecs; |
243 | printk(KERN_INFO "PM: %s %d kbytes in %d.%02d seconds (%d.%02d MB/s)\n", | 247 | printk(KERN_INFO "PM: %s %u kbytes in %u.%02u seconds (%u.%02u MB/s)\n", |
244 | msg, k, | 248 | msg, k, |
245 | centisecs / 100, centisecs % 100, | 249 | centisecs / 100, centisecs % 100, |
246 | kps / 1000, (kps % 1000) / 10); | 250 | kps / 1000, (kps % 1000) / 10); |
@@ -595,7 +599,8 @@ static void power_down(void) | |||
595 | case HIBERNATION_PLATFORM: | 599 | case HIBERNATION_PLATFORM: |
596 | hibernation_platform_enter(); | 600 | hibernation_platform_enter(); |
597 | case HIBERNATION_SHUTDOWN: | 601 | case HIBERNATION_SHUTDOWN: |
598 | kernel_power_off(); | 602 | if (pm_power_off) |
603 | kernel_power_off(); | ||
599 | break; | 604 | break; |
600 | #ifdef CONFIG_SUSPEND | 605 | #ifdef CONFIG_SUSPEND |
601 | case HIBERNATION_SUSPEND: | 606 | case HIBERNATION_SUSPEND: |
@@ -623,7 +628,8 @@ static void power_down(void) | |||
623 | * corruption after resume. | 628 | * corruption after resume. |
624 | */ | 629 | */ |
625 | printk(KERN_CRIT "PM: Please power down manually\n"); | 630 | printk(KERN_CRIT "PM: Please power down manually\n"); |
626 | while(1); | 631 | while (1) |
632 | cpu_relax(); | ||
627 | } | 633 | } |
628 | 634 | ||
629 | /** | 635 | /** |
@@ -1109,7 +1115,10 @@ static int __init resumewait_setup(char *str) | |||
1109 | 1115 | ||
1110 | static int __init resumedelay_setup(char *str) | 1116 | static int __init resumedelay_setup(char *str) |
1111 | { | 1117 | { |
1112 | resume_delay = simple_strtoul(str, NULL, 0); | 1118 | int rc = kstrtouint(str, 0, &resume_delay); |
1119 | |||
1120 | if (rc) | ||
1121 | return rc; | ||
1113 | return 1; | 1122 | return 1; |
1114 | } | 1123 | } |
1115 | 1124 | ||
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 8233cd4047d7..b62bea0bb624 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
@@ -38,6 +38,7 @@ const char *const pm_states[PM_SUSPEND_MAX] = { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | static const struct platform_suspend_ops *suspend_ops; | 40 | static const struct platform_suspend_ops *suspend_ops; |
41 | static const struct platform_freeze_ops *freeze_ops; | ||
41 | 42 | ||
42 | static bool need_suspend_ops(suspend_state_t state) | 43 | static bool need_suspend_ops(suspend_state_t state) |
43 | { | 44 | { |
@@ -47,6 +48,13 @@ static bool need_suspend_ops(suspend_state_t state) | |||
47 | static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head); | 48 | static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head); |
48 | static bool suspend_freeze_wake; | 49 | static bool suspend_freeze_wake; |
49 | 50 | ||
51 | void freeze_set_ops(const struct platform_freeze_ops *ops) | ||
52 | { | ||
53 | lock_system_sleep(); | ||
54 | freeze_ops = ops; | ||
55 | unlock_system_sleep(); | ||
56 | } | ||
57 | |||
50 | static void freeze_begin(void) | 58 | static void freeze_begin(void) |
51 | { | 59 | { |
52 | suspend_freeze_wake = false; | 60 | suspend_freeze_wake = false; |
@@ -54,9 +62,11 @@ static void freeze_begin(void) | |||
54 | 62 | ||
55 | static void freeze_enter(void) | 63 | static void freeze_enter(void) |
56 | { | 64 | { |
65 | cpuidle_use_deepest_state(true); | ||
57 | cpuidle_resume(); | 66 | cpuidle_resume(); |
58 | wait_event(suspend_freeze_wait_head, suspend_freeze_wake); | 67 | wait_event(suspend_freeze_wait_head, suspend_freeze_wake); |
59 | cpuidle_pause(); | 68 | cpuidle_pause(); |
69 | cpuidle_use_deepest_state(false); | ||
60 | } | 70 | } |
61 | 71 | ||
62 | void freeze_wake(void) | 72 | void freeze_wake(void) |
@@ -269,6 +279,10 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
269 | error = suspend_ops->begin(state); | 279 | error = suspend_ops->begin(state); |
270 | if (error) | 280 | if (error) |
271 | goto Close; | 281 | goto Close; |
282 | } else if (state == PM_SUSPEND_FREEZE && freeze_ops->begin) { | ||
283 | error = freeze_ops->begin(); | ||
284 | if (error) | ||
285 | goto Close; | ||
272 | } | 286 | } |
273 | suspend_console(); | 287 | suspend_console(); |
274 | suspend_test_start(); | 288 | suspend_test_start(); |
@@ -294,6 +308,9 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
294 | Close: | 308 | Close: |
295 | if (need_suspend_ops(state) && suspend_ops->end) | 309 | if (need_suspend_ops(state) && suspend_ops->end) |
296 | suspend_ops->end(); | 310 | suspend_ops->end(); |
311 | else if (state == PM_SUSPEND_FREEZE && freeze_ops->end) | ||
312 | freeze_ops->end(); | ||
313 | |||
297 | trace_machine_suspend(PWR_EVENT_EXIT); | 314 | trace_machine_suspend(PWR_EVENT_EXIT); |
298 | return error; | 315 | return error; |
299 | 316 | ||
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 8f4390a079c7..a8f12247ce7c 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c | |||
@@ -101,19 +101,13 @@ static int cpuidle_idle_call(void) | |||
101 | rcu_idle_enter(); | 101 | rcu_idle_enter(); |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * Check if the cpuidle framework is ready, otherwise fallback | 104 | * Ask the cpuidle framework to choose a convenient idle state. |
105 | * to the default arch specific idle method | 105 | * Fall back to the default arch specific idle method on errors. |
106 | */ | 106 | */ |
107 | ret = cpuidle_enabled(drv, dev); | 107 | next_state = cpuidle_select(drv, dev); |
108 | |||
109 | if (!ret) { | ||
110 | /* | ||
111 | * Ask the governor to choose an idle state it thinks | ||
112 | * it is convenient to go to. There is *always* a | ||
113 | * convenient idle state | ||
114 | */ | ||
115 | next_state = cpuidle_select(drv, dev); | ||
116 | 108 | ||
109 | ret = next_state; | ||
110 | if (ret >= 0) { | ||
117 | /* | 111 | /* |
118 | * The idle task must be scheduled, it is pointless to | 112 | * The idle task must be scheduled, it is pointless to |
119 | * go to idle, just update no idle residency and get | 113 | * go to idle, just update no idle residency and get |
@@ -140,7 +134,7 @@ static int cpuidle_idle_call(void) | |||
140 | CLOCK_EVT_NOTIFY_BROADCAST_ENTER, | 134 | CLOCK_EVT_NOTIFY_BROADCAST_ENTER, |
141 | &dev->cpu); | 135 | &dev->cpu); |
142 | 136 | ||
143 | if (!ret) { | 137 | if (ret >= 0) { |
144 | trace_cpu_idle_rcuidle(next_state, dev->cpu); | 138 | trace_cpu_idle_rcuidle(next_state, dev->cpu); |
145 | 139 | ||
146 | /* | 140 | /* |
@@ -175,7 +169,7 @@ static int cpuidle_idle_call(void) | |||
175 | * We can't use the cpuidle framework, let's use the default | 169 | * We can't use the cpuidle framework, let's use the default |
176 | * idle routine | 170 | * idle routine |
177 | */ | 171 | */ |
178 | if (ret) | 172 | if (ret < 0) |
179 | arch_cpu_idle(); | 173 | arch_cpu_idle(); |
180 | 174 | ||
181 | __current_set_polling(); | 175 | __current_set_polling(); |