.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * OMAP3 Power Management Routines |
---|
3 | 4 | * |
---|
.. | .. |
---|
12 | 13 | * Richard Woodruff <r-woodruff2@ti.com> |
---|
13 | 14 | * |
---|
14 | 15 | * Based on pm.c for omap1 |
---|
15 | | - * |
---|
16 | | - * This program is free software; you can redistribute it and/or modify |
---|
17 | | - * it under the terms of the GNU General Public License version 2 as |
---|
18 | | - * published by the Free Software Foundation. |
---|
19 | 16 | */ |
---|
20 | 17 | |
---|
| 18 | +#include <linux/cpu_pm.h> |
---|
21 | 19 | #include <linux/pm.h> |
---|
22 | 20 | #include <linux/suspend.h> |
---|
23 | 21 | #include <linux/interrupt.h> |
---|
24 | 22 | #include <linux/module.h> |
---|
25 | 23 | #include <linux/list.h> |
---|
26 | 24 | #include <linux/err.h> |
---|
27 | | -#include <linux/gpio.h> |
---|
28 | 25 | #include <linux/clk.h> |
---|
29 | 26 | #include <linux/delay.h> |
---|
30 | 27 | #include <linux/slab.h> |
---|
31 | | -#include <linux/omap-dma.h> |
---|
| 28 | +#include <linux/of.h> |
---|
32 | 29 | #include <linux/omap-gpmc.h> |
---|
33 | | -#include <linux/platform_data/gpio-omap.h> |
---|
34 | 30 | |
---|
35 | 31 | #include <trace/events/power.h> |
---|
36 | 32 | |
---|
.. | .. |
---|
89 | 85 | omap3_gpmc_save_context(); |
---|
90 | 86 | /* Save the system control module context, padconf already save above*/ |
---|
91 | 87 | omap3_control_save_context(); |
---|
92 | | - omap_dma_global_context_save(); |
---|
93 | 88 | } |
---|
94 | 89 | |
---|
95 | 90 | static void omap3_core_restore_context(void) |
---|
.. | .. |
---|
100 | 95 | omap3_gpmc_restore_context(); |
---|
101 | 96 | /* Restore the interrupt controller context */ |
---|
102 | 97 | omap_intc_restore_context(); |
---|
103 | | - omap_dma_global_context_restore(); |
---|
104 | 98 | } |
---|
105 | 99 | |
---|
106 | 100 | /* |
---|
.. | .. |
---|
197 | 191 | int mpu_next_state = PWRDM_POWER_ON; |
---|
198 | 192 | int per_next_state = PWRDM_POWER_ON; |
---|
199 | 193 | int core_next_state = PWRDM_POWER_ON; |
---|
200 | | - int per_going_off; |
---|
201 | 194 | u32 sdrc_pwr = 0; |
---|
| 195 | + int error; |
---|
202 | 196 | |
---|
203 | 197 | mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); |
---|
204 | 198 | switch (mpu_next_state) { |
---|
.. | .. |
---|
227 | 221 | pwrdm_pre_transition(NULL); |
---|
228 | 222 | |
---|
229 | 223 | /* PER */ |
---|
230 | | - if (per_next_state < PWRDM_POWER_ON) { |
---|
231 | | - per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; |
---|
232 | | - omap2_gpio_prepare_for_idle(per_going_off); |
---|
| 224 | + if (per_next_state == PWRDM_POWER_OFF) { |
---|
| 225 | + error = cpu_cluster_pm_enter(); |
---|
| 226 | + if (error) |
---|
| 227 | + return; |
---|
233 | 228 | } |
---|
234 | 229 | |
---|
235 | 230 | /* CORE */ |
---|
.. | .. |
---|
295 | 290 | pwrdm_post_transition(NULL); |
---|
296 | 291 | |
---|
297 | 292 | /* PER */ |
---|
298 | | - if (per_next_state < PWRDM_POWER_ON) |
---|
299 | | - omap2_gpio_resume_after_idle(); |
---|
| 293 | + if (per_next_state == PWRDM_POWER_OFF) |
---|
| 294 | + cpu_cluster_pm_exit(); |
---|
300 | 295 | } |
---|
301 | 296 | |
---|
302 | 297 | static void omap3_pm_idle(void) |
---|
.. | .. |
---|
304 | 299 | if (omap_irq_pending()) |
---|
305 | 300 | return; |
---|
306 | 301 | |
---|
307 | | - trace_cpu_idle_rcuidle(1, smp_processor_id()); |
---|
308 | | - |
---|
309 | 302 | omap_sram_idle(); |
---|
310 | | - |
---|
311 | | - trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); |
---|
312 | 303 | } |
---|
313 | 304 | |
---|
314 | 305 | #ifdef CONFIG_SUSPEND |
---|
.. | .. |
---|
420 | 411 | if (!pwrst) |
---|
421 | 412 | return -ENOMEM; |
---|
422 | 413 | pwrst->pwrdm = pwrdm; |
---|
423 | | - pwrst->next_state = PWRDM_POWER_RET; |
---|
| 414 | + |
---|
| 415 | + if (enable_off_mode) |
---|
| 416 | + pwrst->next_state = PWRDM_POWER_OFF; |
---|
| 417 | + else |
---|
| 418 | + pwrst->next_state = PWRDM_POWER_RET; |
---|
| 419 | + |
---|
424 | 420 | list_add(&pwrst->node, &pwrst_list); |
---|
425 | 421 | |
---|
426 | 422 | if (pwrdm_has_hdwr_sar(pwrdm)) |
---|
.. | .. |
---|
451 | 447 | PM_PER_MEMORIES_ERRATUM_i582); |
---|
452 | 448 | } else if (cpu_is_omap34xx()) { |
---|
453 | 449 | pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582; |
---|
| 450 | + } |
---|
| 451 | +} |
---|
| 452 | + |
---|
| 453 | +static void __init omap3_pm_check_pmic(void) |
---|
| 454 | +{ |
---|
| 455 | + struct device_node *np; |
---|
| 456 | + |
---|
| 457 | + np = of_find_compatible_node(NULL, NULL, "ti,twl4030-power-idle"); |
---|
| 458 | + if (!np) |
---|
| 459 | + np = of_find_compatible_node(NULL, NULL, "ti,twl4030-power-idle-osc-off"); |
---|
| 460 | + |
---|
| 461 | + if (np) { |
---|
| 462 | + of_node_put(np); |
---|
| 463 | + enable_off_mode = 1; |
---|
| 464 | + } else { |
---|
| 465 | + enable_off_mode = 0; |
---|
454 | 466 | } |
---|
455 | 467 | } |
---|
456 | 468 | |
---|
.. | .. |
---|
486 | 498 | pr_err("pm: Failed to request pm_io irq\n"); |
---|
487 | 499 | goto err2; |
---|
488 | 500 | } |
---|
| 501 | + |
---|
| 502 | + omap3_pm_check_pmic(); |
---|
489 | 503 | |
---|
490 | 504 | ret = pwrdm_for_each(pwrdms_setup, NULL); |
---|
491 | 505 | if (ret) { |
---|
.. | .. |
---|
554 | 568 | |
---|
555 | 569 | local_irq_disable(); |
---|
556 | 570 | |
---|
557 | | - omap_dma_global_context_save(); |
---|
558 | 571 | omap3_save_secure_ram_context(); |
---|
559 | | - omap_dma_global_context_restore(); |
---|
560 | 572 | |
---|
561 | 573 | local_irq_enable(); |
---|
562 | 574 | } |
---|