1 /* 2 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd. 3 * http://www.samsung.com 4 * 5 * EXYNOS - Suspend support 6 * 7 * Based on arch/arm/mach-s3c2410/pm.c 8 * Copyright (c) 2006 Simtec Electronics 9 * Ben Dooks <ben@simtec.co.uk> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 */ 15 16 #include <linux/init.h> 17 #include <linux/suspend.h> 18 #include <linux/syscore_ops.h> 19 #include <linux/cpu_pm.h> 20 #include <linux/io.h> 21 #include <linux/irq.h> 22 #include <linux/irqdomain.h> 23 #include <linux/of_address.h> 24 #include <linux/err.h> 25 #include <linux/regulator/machine.h> 26 27 #include <asm/cacheflush.h> 28 #include <asm/hardware/cache-l2x0.h> 29 #include <asm/firmware.h> 30 #include <asm/mcpm.h> 31 #include <asm/smp_scu.h> 32 #include <asm/suspend.h> 33 34 #include <plat/pm-common.h> 35 #include <plat/regs-srom.h> 36 37 #include "common.h" 38 #include "regs-pmu.h" 39 #include "exynos-pmu.h" 40 41 #define S5P_CHECK_SLEEP 0x00000BAD 42 43 #define REG_TABLE_END (-1U) 44 45 #define EXYNOS5420_CPU_STATE 0x28 46 47 /** 48 * struct exynos_wkup_irq - PMU IRQ to mask mapping 49 * @hwirq: Hardware IRQ signal of the PMU 50 * @mask: Mask in PMU wake-up mask register 51 */ 52 struct exynos_wkup_irq { 53 unsigned int hwirq; 54 u32 mask; 55 }; 56 57 static struct sleep_save exynos_core_save[] = { 58 /* SROM side */ 59 SAVE_ITEM(S5P_SROM_BW), 60 SAVE_ITEM(S5P_SROM_BC0), 61 SAVE_ITEM(S5P_SROM_BC1), 62 SAVE_ITEM(S5P_SROM_BC2), 63 SAVE_ITEM(S5P_SROM_BC3), 64 }; 65 66 struct exynos_pm_data { 67 const struct exynos_wkup_irq *wkup_irq; 68 struct sleep_save *extra_save; 69 int num_extra_save; 70 unsigned int wake_disable_mask; 71 unsigned int *release_ret_regs; 72 73 void (*pm_prepare)(void); 74 void (*pm_resume_prepare)(void); 75 void (*pm_resume)(void); 76 int (*pm_suspend)(void); 77 int (*cpu_suspend)(unsigned long); 78 }; 79 80 struct exynos_pm_data *pm_data; 81 82 static int exynos5420_cpu_state; 83 static unsigned int exynos_pmu_spare3; 84 85 /* 86 * GIC wake-up support 87 */ 88 89 static u32 exynos_irqwake_intmask = 0xffffffff; 90 91 static const struct exynos_wkup_irq exynos3250_wkup_irq[] = { 92 { 105, BIT(1) }, /* RTC alarm */ 93 { 106, BIT(2) }, /* RTC tick */ 94 { /* sentinel */ }, 95 }; 96 97 static const struct exynos_wkup_irq exynos4_wkup_irq[] = { 98 { 44, BIT(1) }, /* RTC alarm */ 99 { 45, BIT(2) }, /* RTC tick */ 100 { /* sentinel */ }, 101 }; 102 103 static const struct exynos_wkup_irq exynos5250_wkup_irq[] = { 104 { 43, BIT(1) }, /* RTC alarm */ 105 { 44, BIT(2) }, /* RTC tick */ 106 { /* sentinel */ }, 107 }; 108 109 unsigned int exynos_release_ret_regs[] = { 110 S5P_PAD_RET_MAUDIO_OPTION, 111 S5P_PAD_RET_GPIO_OPTION, 112 S5P_PAD_RET_UART_OPTION, 113 S5P_PAD_RET_MMCA_OPTION, 114 S5P_PAD_RET_MMCB_OPTION, 115 S5P_PAD_RET_EBIA_OPTION, 116 S5P_PAD_RET_EBIB_OPTION, 117 REG_TABLE_END, 118 }; 119 120 unsigned int exynos3250_release_ret_regs[] = { 121 S5P_PAD_RET_MAUDIO_OPTION, 122 S5P_PAD_RET_GPIO_OPTION, 123 S5P_PAD_RET_UART_OPTION, 124 S5P_PAD_RET_MMCA_OPTION, 125 S5P_PAD_RET_MMCB_OPTION, 126 S5P_PAD_RET_EBIA_OPTION, 127 S5P_PAD_RET_EBIB_OPTION, 128 S5P_PAD_RET_MMC2_OPTION, 129 S5P_PAD_RET_SPI_OPTION, 130 REG_TABLE_END, 131 }; 132 133 unsigned int exynos5420_release_ret_regs[] = { 134 EXYNOS_PAD_RET_DRAM_OPTION, 135 EXYNOS_PAD_RET_MAUDIO_OPTION, 136 EXYNOS_PAD_RET_JTAG_OPTION, 137 EXYNOS5420_PAD_RET_GPIO_OPTION, 138 EXYNOS5420_PAD_RET_UART_OPTION, 139 EXYNOS5420_PAD_RET_MMCA_OPTION, 140 EXYNOS5420_PAD_RET_MMCB_OPTION, 141 EXYNOS5420_PAD_RET_MMCC_OPTION, 142 EXYNOS5420_PAD_RET_HSI_OPTION, 143 EXYNOS_PAD_RET_EBIA_OPTION, 144 EXYNOS_PAD_RET_EBIB_OPTION, 145 EXYNOS5420_PAD_RET_SPI_OPTION, 146 EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION, 147 REG_TABLE_END, 148 }; 149 150 static int exynos_irq_set_wake(struct irq_data *data, unsigned int state) 151 { 152 const struct exynos_wkup_irq *wkup_irq; 153 154 if (!pm_data->wkup_irq) 155 return -ENOENT; 156 wkup_irq = pm_data->wkup_irq; 157 158 while (wkup_irq->mask) { 159 if (wkup_irq->hwirq == data->hwirq) { 160 if (!state) 161 exynos_irqwake_intmask |= wkup_irq->mask; 162 else 163 exynos_irqwake_intmask &= ~wkup_irq->mask; 164 return 0; 165 } 166 ++wkup_irq; 167 } 168 169 return -ENOENT; 170 } 171 172 static struct irq_chip exynos_pmu_chip = { 173 .name = "PMU", 174 .irq_eoi = irq_chip_eoi_parent, 175 .irq_mask = irq_chip_mask_parent, 176 .irq_unmask = irq_chip_unmask_parent, 177 .irq_retrigger = irq_chip_retrigger_hierarchy, 178 .irq_set_wake = exynos_irq_set_wake, 179 #ifdef CONFIG_SMP 180 .irq_set_affinity = irq_chip_set_affinity_parent, 181 #endif 182 }; 183 184 static int exynos_pmu_domain_xlate(struct irq_domain *domain, 185 struct device_node *controller, 186 const u32 *intspec, 187 unsigned int intsize, 188 unsigned long *out_hwirq, 189 unsigned int *out_type) 190 { 191 if (domain->of_node != controller) 192 return -EINVAL; /* Shouldn't happen, really... */ 193 if (intsize != 3) 194 return -EINVAL; /* Not GIC compliant */ 195 if (intspec[0] != 0) 196 return -EINVAL; /* No PPI should point to this domain */ 197 198 *out_hwirq = intspec[1]; 199 *out_type = intspec[2]; 200 return 0; 201 } 202 203 static int exynos_pmu_domain_alloc(struct irq_domain *domain, 204 unsigned int virq, 205 unsigned int nr_irqs, void *data) 206 { 207 struct of_phandle_args *args = data; 208 struct of_phandle_args parent_args; 209 irq_hw_number_t hwirq; 210 int i; 211 212 if (args->args_count != 3) 213 return -EINVAL; /* Not GIC compliant */ 214 if (args->args[0] != 0) 215 return -EINVAL; /* No PPI should point to this domain */ 216 217 hwirq = args->args[1]; 218 219 for (i = 0; i < nr_irqs; i++) 220 irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, 221 &exynos_pmu_chip, NULL); 222 223 parent_args = *args; 224 parent_args.np = domain->parent->of_node; 225 return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args); 226 } 227 228 static struct irq_domain_ops exynos_pmu_domain_ops = { 229 .xlate = exynos_pmu_domain_xlate, 230 .alloc = exynos_pmu_domain_alloc, 231 .free = irq_domain_free_irqs_common, 232 }; 233 234 static int __init exynos_pmu_irq_init(struct device_node *node, 235 struct device_node *parent) 236 { 237 struct irq_domain *parent_domain, *domain; 238 239 if (!parent) { 240 pr_err("%s: no parent, giving up\n", node->full_name); 241 return -ENODEV; 242 } 243 244 parent_domain = irq_find_host(parent); 245 if (!parent_domain) { 246 pr_err("%s: unable to obtain parent domain\n", node->full_name); 247 return -ENXIO; 248 } 249 250 pmu_base_addr = of_iomap(node, 0); 251 252 if (!pmu_base_addr) { 253 pr_err("%s: failed to find exynos pmu register\n", 254 node->full_name); 255 return -ENOMEM; 256 } 257 258 domain = irq_domain_add_hierarchy(parent_domain, 0, 0, 259 node, &exynos_pmu_domain_ops, 260 NULL); 261 if (!domain) { 262 iounmap(pmu_base_addr); 263 return -ENOMEM; 264 } 265 266 return 0; 267 } 268 269 #define EXYNOS_PMU_IRQ(symbol, name) OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init) 270 271 EXYNOS_PMU_IRQ(exynos3250_pmu_irq, "samsung,exynos3250-pmu"); 272 EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu"); 273 EXYNOS_PMU_IRQ(exynos4212_pmu_irq, "samsung,exynos4212-pmu"); 274 EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu"); 275 EXYNOS_PMU_IRQ(exynos4415_pmu_irq, "samsung,exynos4415-pmu"); 276 EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu"); 277 EXYNOS_PMU_IRQ(exynos5420_pmu_irq, "samsung,exynos5420-pmu"); 278 279 static int exynos_cpu_do_idle(void) 280 { 281 /* issue the standby signal into the pm unit. */ 282 cpu_do_idle(); 283 284 pr_info("Failed to suspend the system\n"); 285 return 1; /* Aborting suspend */ 286 } 287 static void exynos_flush_cache_all(void) 288 { 289 flush_cache_all(); 290 outer_flush_all(); 291 } 292 293 static int exynos_cpu_suspend(unsigned long arg) 294 { 295 exynos_flush_cache_all(); 296 return exynos_cpu_do_idle(); 297 } 298 299 static int exynos3250_cpu_suspend(unsigned long arg) 300 { 301 flush_cache_all(); 302 return exynos_cpu_do_idle(); 303 } 304 305 static int exynos5420_cpu_suspend(unsigned long arg) 306 { 307 /* MCPM works with HW CPU identifiers */ 308 unsigned int mpidr = read_cpuid_mpidr(); 309 unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); 310 unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); 311 312 __raw_writel(0x0, sysram_base_addr + EXYNOS5420_CPU_STATE); 313 314 if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) { 315 mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume); 316 317 /* 318 * Residency value passed to mcpm_cpu_suspend back-end 319 * has to be given clear semantics. Set to 0 as a 320 * temporary value. 321 */ 322 mcpm_cpu_suspend(0); 323 } 324 325 pr_info("Failed to suspend the system\n"); 326 327 /* return value != 0 means failure */ 328 return 1; 329 } 330 331 static void exynos_pm_set_wakeup_mask(void) 332 { 333 /* Set wake-up mask registers */ 334 pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK); 335 pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK); 336 } 337 338 static void exynos_pm_enter_sleep_mode(void) 339 { 340 /* Set value of power down register for sleep mode */ 341 exynos_sys_powerdown_conf(SYS_SLEEP); 342 pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1); 343 } 344 345 static void exynos_pm_prepare(void) 346 { 347 /* Set wake-up mask registers */ 348 exynos_pm_set_wakeup_mask(); 349 350 s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); 351 352 if (pm_data->extra_save) 353 s3c_pm_do_save(pm_data->extra_save, 354 pm_data->num_extra_save); 355 356 exynos_pm_enter_sleep_mode(); 357 358 /* ensure at least INFORM0 has the resume address */ 359 pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0); 360 } 361 362 static void exynos3250_pm_prepare(void) 363 { 364 unsigned int tmp; 365 366 /* Set wake-up mask registers */ 367 exynos_pm_set_wakeup_mask(); 368 369 tmp = pmu_raw_readl(EXYNOS3_ARM_L2_OPTION); 370 tmp &= ~EXYNOS5_OPTION_USE_RETENTION; 371 pmu_raw_writel(tmp, EXYNOS3_ARM_L2_OPTION); 372 373 exynos_pm_enter_sleep_mode(); 374 375 /* ensure at least INFORM0 has the resume address */ 376 pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0); 377 } 378 379 static void exynos5420_pm_prepare(void) 380 { 381 unsigned int tmp; 382 383 /* Set wake-up mask registers */ 384 exynos_pm_set_wakeup_mask(); 385 386 s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); 387 388 exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3); 389 /* 390 * The cpu state needs to be saved and restored so that the 391 * secondary CPUs will enter low power start. Though the U-Boot 392 * is setting the cpu state with low power flag, the kernel 393 * needs to restore it back in case, the primary cpu fails to 394 * suspend for any reason. 395 */ 396 exynos5420_cpu_state = __raw_readl(sysram_base_addr + 397 EXYNOS5420_CPU_STATE); 398 399 exynos_pm_enter_sleep_mode(); 400 401 /* ensure at least INFORM0 has the resume address */ 402 if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) 403 pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0); 404 405 tmp = pmu_raw_readl(EXYNOS5_ARM_L2_OPTION); 406 tmp &= ~EXYNOS5_USE_RETENTION; 407 pmu_raw_writel(tmp, EXYNOS5_ARM_L2_OPTION); 408 409 tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); 410 tmp |= EXYNOS5420_UFS; 411 pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1); 412 413 tmp = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION); 414 tmp &= ~EXYNOS5420_L2RSTDISABLE_VALUE; 415 pmu_raw_writel(tmp, EXYNOS5420_ARM_COMMON_OPTION); 416 417 tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION); 418 tmp |= EXYNOS5420_EMULATION; 419 pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION); 420 421 tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION); 422 tmp |= EXYNOS5420_EMULATION; 423 pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION); 424 } 425 426 427 static int exynos_pm_suspend(void) 428 { 429 exynos_pm_central_suspend(); 430 431 /* Setting SEQ_OPTION register */ 432 pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0, 433 S5P_CENTRAL_SEQ_OPTION); 434 435 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) 436 exynos_cpu_save_register(); 437 438 return 0; 439 } 440 441 static int exynos5420_pm_suspend(void) 442 { 443 u32 this_cluster; 444 445 exynos_pm_central_suspend(); 446 447 /* Setting SEQ_OPTION register */ 448 449 this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1); 450 if (!this_cluster) 451 pmu_raw_writel(EXYNOS5420_ARM_USE_STANDBY_WFI0, 452 S5P_CENTRAL_SEQ_OPTION); 453 else 454 pmu_raw_writel(EXYNOS5420_KFC_USE_STANDBY_WFI0, 455 S5P_CENTRAL_SEQ_OPTION); 456 return 0; 457 } 458 459 static void exynos_pm_release_retention(void) 460 { 461 unsigned int i; 462 463 for (i = 0; (pm_data->release_ret_regs[i] != REG_TABLE_END); i++) 464 pmu_raw_writel(EXYNOS_WAKEUP_FROM_LOWPWR, 465 pm_data->release_ret_regs[i]); 466 } 467 468 static void exynos_pm_resume(void) 469 { 470 u32 cpuid = read_cpuid_part(); 471 472 if (exynos_pm_central_resume()) 473 goto early_wakeup; 474 475 /* For release retention */ 476 exynos_pm_release_retention(); 477 478 if (pm_data->extra_save) 479 s3c_pm_do_restore_core(pm_data->extra_save, 480 pm_data->num_extra_save); 481 482 s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); 483 484 if (cpuid == ARM_CPU_PART_CORTEX_A9) 485 scu_enable(S5P_VA_SCU); 486 487 if (call_firmware_op(resume) == -ENOSYS 488 && cpuid == ARM_CPU_PART_CORTEX_A9) 489 exynos_cpu_restore_register(); 490 491 early_wakeup: 492 493 /* Clear SLEEP mode set in INFORM1 */ 494 pmu_raw_writel(0x0, S5P_INFORM1); 495 } 496 497 static void exynos3250_pm_resume(void) 498 { 499 u32 cpuid = read_cpuid_part(); 500 501 if (exynos_pm_central_resume()) 502 goto early_wakeup; 503 504 /* For release retention */ 505 exynos_pm_release_retention(); 506 507 pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION); 508 509 if (call_firmware_op(resume) == -ENOSYS 510 && cpuid == ARM_CPU_PART_CORTEX_A9) 511 exynos_cpu_restore_register(); 512 513 early_wakeup: 514 515 /* Clear SLEEP mode set in INFORM1 */ 516 pmu_raw_writel(0x0, S5P_INFORM1); 517 } 518 519 static void exynos5420_prepare_pm_resume(void) 520 { 521 if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) 522 WARN_ON(mcpm_cpu_powered_up()); 523 } 524 525 static void exynos5420_pm_resume(void) 526 { 527 unsigned long tmp; 528 529 /* Restore the CPU0 low power state register */ 530 tmp = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG); 531 pmu_raw_writel(tmp | S5P_CORE_LOCAL_PWR_EN, 532 EXYNOS5_ARM_CORE0_SYS_PWR_REG); 533 534 /* Restore the sysram cpu state register */ 535 __raw_writel(exynos5420_cpu_state, 536 sysram_base_addr + EXYNOS5420_CPU_STATE); 537 538 pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, 539 S5P_CENTRAL_SEQ_OPTION); 540 541 if (exynos_pm_central_resume()) 542 goto early_wakeup; 543 544 /* For release retention */ 545 exynos_pm_release_retention(); 546 547 pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3); 548 549 s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); 550 551 early_wakeup: 552 553 tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); 554 tmp &= ~EXYNOS5420_UFS; 555 pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1); 556 557 tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION); 558 tmp &= ~EXYNOS5420_EMULATION; 559 pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION); 560 561 tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION); 562 tmp &= ~EXYNOS5420_EMULATION; 563 pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION); 564 565 /* Clear SLEEP mode set in INFORM1 */ 566 pmu_raw_writel(0x0, S5P_INFORM1); 567 } 568 569 /* 570 * Suspend Ops 571 */ 572 573 static int exynos_suspend_enter(suspend_state_t state) 574 { 575 int ret; 576 577 s3c_pm_debug_init(); 578 579 S3C_PMDBG("%s: suspending the system...\n", __func__); 580 581 S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__, 582 exynos_irqwake_intmask, exynos_get_eint_wake_mask()); 583 584 if (exynos_irqwake_intmask == -1U 585 && exynos_get_eint_wake_mask() == -1U) { 586 pr_err("%s: No wake-up sources!\n", __func__); 587 pr_err("%s: Aborting sleep\n", __func__); 588 return -EINVAL; 589 } 590 591 s3c_pm_save_uarts(); 592 if (pm_data->pm_prepare) 593 pm_data->pm_prepare(); 594 flush_cache_all(); 595 s3c_pm_check_store(); 596 597 ret = call_firmware_op(suspend); 598 if (ret == -ENOSYS) 599 ret = cpu_suspend(0, pm_data->cpu_suspend); 600 if (ret) 601 return ret; 602 603 if (pm_data->pm_resume_prepare) 604 pm_data->pm_resume_prepare(); 605 s3c_pm_restore_uarts(); 606 607 S3C_PMDBG("%s: wakeup stat: %08x\n", __func__, 608 pmu_raw_readl(S5P_WAKEUP_STAT)); 609 610 s3c_pm_check_restore(); 611 612 S3C_PMDBG("%s: resuming the system...\n", __func__); 613 614 return 0; 615 } 616 617 static int exynos_suspend_prepare(void) 618 { 619 int ret; 620 621 /* 622 * REVISIT: It would be better if struct platform_suspend_ops 623 * .prepare handler get the suspend_state_t as a parameter to 624 * avoid hard-coding the suspend to mem state. It's safe to do 625 * it now only because the suspend_valid_only_mem function is 626 * used as the .valid callback used to check if a given state 627 * is supported by the platform anyways. 628 */ 629 ret = regulator_suspend_prepare(PM_SUSPEND_MEM); 630 if (ret) { 631 pr_err("Failed to prepare regulators for suspend (%d)\n", ret); 632 return ret; 633 } 634 635 s3c_pm_check_prepare(); 636 637 return 0; 638 } 639 640 static void exynos_suspend_finish(void) 641 { 642 int ret; 643 644 s3c_pm_check_cleanup(); 645 646 ret = regulator_suspend_finish(); 647 if (ret) 648 pr_warn("Failed to resume regulators from suspend (%d)\n", ret); 649 } 650 651 static const struct platform_suspend_ops exynos_suspend_ops = { 652 .enter = exynos_suspend_enter, 653 .prepare = exynos_suspend_prepare, 654 .finish = exynos_suspend_finish, 655 .valid = suspend_valid_only_mem, 656 }; 657 658 static const struct exynos_pm_data exynos3250_pm_data = { 659 .wkup_irq = exynos3250_wkup_irq, 660 .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)), 661 .release_ret_regs = exynos3250_release_ret_regs, 662 .pm_suspend = exynos_pm_suspend, 663 .pm_resume = exynos3250_pm_resume, 664 .pm_prepare = exynos3250_pm_prepare, 665 .cpu_suspend = exynos3250_cpu_suspend, 666 }; 667 668 static const struct exynos_pm_data exynos4_pm_data = { 669 .wkup_irq = exynos4_wkup_irq, 670 .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)), 671 .release_ret_regs = exynos_release_ret_regs, 672 .pm_suspend = exynos_pm_suspend, 673 .pm_resume = exynos_pm_resume, 674 .pm_prepare = exynos_pm_prepare, 675 .cpu_suspend = exynos_cpu_suspend, 676 }; 677 678 static const struct exynos_pm_data exynos5250_pm_data = { 679 .wkup_irq = exynos5250_wkup_irq, 680 .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)), 681 .release_ret_regs = exynos_release_ret_regs, 682 .pm_suspend = exynos_pm_suspend, 683 .pm_resume = exynos_pm_resume, 684 .pm_prepare = exynos_pm_prepare, 685 .cpu_suspend = exynos_cpu_suspend, 686 }; 687 688 static struct exynos_pm_data exynos5420_pm_data = { 689 .wkup_irq = exynos5250_wkup_irq, 690 .wake_disable_mask = (0x7F << 7) | (0x1F << 1), 691 .release_ret_regs = exynos5420_release_ret_regs, 692 .pm_resume_prepare = exynos5420_prepare_pm_resume, 693 .pm_resume = exynos5420_pm_resume, 694 .pm_suspend = exynos5420_pm_suspend, 695 .pm_prepare = exynos5420_pm_prepare, 696 .cpu_suspend = exynos5420_cpu_suspend, 697 }; 698 699 static const struct of_device_id exynos_pmu_of_device_ids[] __initconst = { 700 { 701 .compatible = "samsung,exynos3250-pmu", 702 .data = &exynos3250_pm_data, 703 }, { 704 .compatible = "samsung,exynos4210-pmu", 705 .data = &exynos4_pm_data, 706 }, { 707 .compatible = "samsung,exynos4212-pmu", 708 .data = &exynos4_pm_data, 709 }, { 710 .compatible = "samsung,exynos4412-pmu", 711 .data = &exynos4_pm_data, 712 }, { 713 .compatible = "samsung,exynos5250-pmu", 714 .data = &exynos5250_pm_data, 715 }, { 716 .compatible = "samsung,exynos5420-pmu", 717 .data = &exynos5420_pm_data, 718 }, 719 { /*sentinel*/ }, 720 }; 721 722 static struct syscore_ops exynos_pm_syscore_ops; 723 724 void __init exynos_pm_init(void) 725 { 726 const struct of_device_id *match; 727 struct device_node *np; 728 u32 tmp; 729 730 np = of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match); 731 if (!np) { 732 pr_err("Failed to find PMU node\n"); 733 return; 734 } 735 736 if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) 737 pr_warn("Outdated DT detected, suspend/resume will NOT work\n"); 738 739 pm_data = (struct exynos_pm_data *) match->data; 740 741 /* All wakeup disable */ 742 tmp = pmu_raw_readl(S5P_WAKEUP_MASK); 743 tmp |= pm_data->wake_disable_mask; 744 pmu_raw_writel(tmp, S5P_WAKEUP_MASK); 745 746 exynos_pm_syscore_ops.suspend = pm_data->pm_suspend; 747 exynos_pm_syscore_ops.resume = pm_data->pm_resume; 748 749 register_syscore_ops(&exynos_pm_syscore_ops); 750 suspend_set_ops(&exynos_suspend_ops); 751 } 752