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/irqchip/arm-gic.h> 22 #include <linux/err.h> 23 #include <linux/regulator/machine.h> 24 25 #include <asm/cacheflush.h> 26 #include <asm/hardware/cache-l2x0.h> 27 #include <asm/firmware.h> 28 #include <asm/mcpm.h> 29 #include <asm/smp_scu.h> 30 #include <asm/suspend.h> 31 32 #include <plat/pm-common.h> 33 #include <plat/regs-srom.h> 34 35 #include "common.h" 36 #include "regs-pmu.h" 37 #include "regs-sys.h" 38 #include "exynos-pmu.h" 39 40 #define S5P_CHECK_SLEEP 0x00000BAD 41 42 #define REG_TABLE_END (-1U) 43 44 #define EXYNOS5420_CPU_STATE 0x28 45 46 /** 47 * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping 48 * @hwirq: Hardware IRQ signal of the GIC 49 * @mask: Mask in PMU wake-up mask register 50 */ 51 struct exynos_wkup_irq { 52 unsigned int hwirq; 53 u32 mask; 54 }; 55 56 static struct sleep_save exynos5_sys_save[] = { 57 SAVE_ITEM(EXYNOS5_SYS_I2C_CFG), 58 }; 59 60 static struct sleep_save exynos_core_save[] = { 61 /* SROM side */ 62 SAVE_ITEM(S5P_SROM_BW), 63 SAVE_ITEM(S5P_SROM_BC0), 64 SAVE_ITEM(S5P_SROM_BC1), 65 SAVE_ITEM(S5P_SROM_BC2), 66 SAVE_ITEM(S5P_SROM_BC3), 67 }; 68 69 struct exynos_pm_data { 70 const struct exynos_wkup_irq *wkup_irq; 71 struct sleep_save *extra_save; 72 int num_extra_save; 73 unsigned int wake_disable_mask; 74 unsigned int *release_ret_regs; 75 76 void (*pm_prepare)(void); 77 void (*pm_resume_prepare)(void); 78 void (*pm_resume)(void); 79 int (*pm_suspend)(void); 80 int (*cpu_suspend)(unsigned long); 81 }; 82 83 struct exynos_pm_data *pm_data; 84 85 static int exynos5420_cpu_state; 86 static unsigned int exynos_pmu_spare3; 87 88 /* 89 * GIC wake-up support 90 */ 91 92 static u32 exynos_irqwake_intmask = 0xffffffff; 93 94 static const struct exynos_wkup_irq exynos4_wkup_irq[] = { 95 { 76, BIT(1) }, /* RTC alarm */ 96 { 77, BIT(2) }, /* RTC tick */ 97 { /* sentinel */ }, 98 }; 99 100 static const struct exynos_wkup_irq exynos5250_wkup_irq[] = { 101 { 75, BIT(1) }, /* RTC alarm */ 102 { 76, BIT(2) }, /* RTC tick */ 103 { /* sentinel */ }, 104 }; 105 106 unsigned int exynos_release_ret_regs[] = { 107 S5P_PAD_RET_MAUDIO_OPTION, 108 S5P_PAD_RET_GPIO_OPTION, 109 S5P_PAD_RET_UART_OPTION, 110 S5P_PAD_RET_MMCA_OPTION, 111 S5P_PAD_RET_MMCB_OPTION, 112 S5P_PAD_RET_EBIA_OPTION, 113 S5P_PAD_RET_EBIB_OPTION, 114 REG_TABLE_END, 115 }; 116 117 unsigned int exynos5420_release_ret_regs[] = { 118 EXYNOS_PAD_RET_DRAM_OPTION, 119 EXYNOS_PAD_RET_MAUDIO_OPTION, 120 EXYNOS_PAD_RET_JTAG_OPTION, 121 EXYNOS5420_PAD_RET_GPIO_OPTION, 122 EXYNOS5420_PAD_RET_UART_OPTION, 123 EXYNOS5420_PAD_RET_MMCA_OPTION, 124 EXYNOS5420_PAD_RET_MMCB_OPTION, 125 EXYNOS5420_PAD_RET_MMCC_OPTION, 126 EXYNOS5420_PAD_RET_HSI_OPTION, 127 EXYNOS_PAD_RET_EBIA_OPTION, 128 EXYNOS_PAD_RET_EBIB_OPTION, 129 EXYNOS5420_PAD_RET_SPI_OPTION, 130 EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION, 131 REG_TABLE_END, 132 }; 133 134 static int exynos_irq_set_wake(struct irq_data *data, unsigned int state) 135 { 136 const struct exynos_wkup_irq *wkup_irq; 137 138 if (!pm_data->wkup_irq) 139 return -ENOENT; 140 wkup_irq = pm_data->wkup_irq; 141 142 while (wkup_irq->mask) { 143 if (wkup_irq->hwirq == data->hwirq) { 144 if (!state) 145 exynos_irqwake_intmask |= wkup_irq->mask; 146 else 147 exynos_irqwake_intmask &= ~wkup_irq->mask; 148 return 0; 149 } 150 ++wkup_irq; 151 } 152 153 return -ENOENT; 154 } 155 156 static int exynos_cpu_do_idle(void) 157 { 158 /* issue the standby signal into the pm unit. */ 159 cpu_do_idle(); 160 161 pr_info("Failed to suspend the system\n"); 162 return 1; /* Aborting suspend */ 163 } 164 static void exynos_flush_cache_all(void) 165 { 166 flush_cache_all(); 167 outer_flush_all(); 168 } 169 170 static int exynos_cpu_suspend(unsigned long arg) 171 { 172 exynos_flush_cache_all(); 173 return exynos_cpu_do_idle(); 174 } 175 176 static int exynos5420_cpu_suspend(unsigned long arg) 177 { 178 /* MCPM works with HW CPU identifiers */ 179 unsigned int mpidr = read_cpuid_mpidr(); 180 unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); 181 unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); 182 183 __raw_writel(0x0, sysram_base_addr + EXYNOS5420_CPU_STATE); 184 185 if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) { 186 mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume); 187 188 /* 189 * Residency value passed to mcpm_cpu_suspend back-end 190 * has to be given clear semantics. Set to 0 as a 191 * temporary value. 192 */ 193 mcpm_cpu_suspend(0); 194 } 195 196 pr_info("Failed to suspend the system\n"); 197 198 /* return value != 0 means failure */ 199 return 1; 200 } 201 202 static void exynos_pm_set_wakeup_mask(void) 203 { 204 /* Set wake-up mask registers */ 205 pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK); 206 pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK); 207 } 208 209 static void exynos_pm_enter_sleep_mode(void) 210 { 211 /* Set value of power down register for sleep mode */ 212 exynos_sys_powerdown_conf(SYS_SLEEP); 213 pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1); 214 } 215 216 static void exynos_pm_prepare(void) 217 { 218 /* Set wake-up mask registers */ 219 exynos_pm_set_wakeup_mask(); 220 221 s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); 222 223 if (pm_data->extra_save) 224 s3c_pm_do_save(pm_data->extra_save, 225 pm_data->num_extra_save); 226 227 exynos_pm_enter_sleep_mode(); 228 229 /* ensure at least INFORM0 has the resume address */ 230 pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0); 231 } 232 233 static void exynos5420_pm_prepare(void) 234 { 235 unsigned int tmp; 236 237 /* Set wake-up mask registers */ 238 exynos_pm_set_wakeup_mask(); 239 240 s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); 241 242 exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3); 243 /* 244 * The cpu state needs to be saved and restored so that the 245 * secondary CPUs will enter low power start. Though the U-Boot 246 * is setting the cpu state with low power flag, the kernel 247 * needs to restore it back in case, the primary cpu fails to 248 * suspend for any reason. 249 */ 250 exynos5420_cpu_state = __raw_readl(sysram_base_addr + 251 EXYNOS5420_CPU_STATE); 252 253 exynos_pm_enter_sleep_mode(); 254 255 /* ensure at least INFORM0 has the resume address */ 256 if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) 257 pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0); 258 259 tmp = pmu_raw_readl(EXYNOS5_ARM_L2_OPTION); 260 tmp &= ~EXYNOS5_USE_RETENTION; 261 pmu_raw_writel(tmp, EXYNOS5_ARM_L2_OPTION); 262 263 tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); 264 tmp |= EXYNOS5420_UFS; 265 pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1); 266 267 tmp = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION); 268 tmp &= ~EXYNOS5420_L2RSTDISABLE_VALUE; 269 pmu_raw_writel(tmp, EXYNOS5420_ARM_COMMON_OPTION); 270 271 tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION); 272 tmp |= EXYNOS5420_EMULATION; 273 pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION); 274 275 tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION); 276 tmp |= EXYNOS5420_EMULATION; 277 pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION); 278 } 279 280 281 static int exynos_pm_suspend(void) 282 { 283 exynos_pm_central_suspend(); 284 285 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) 286 exynos_cpu_save_register(); 287 288 return 0; 289 } 290 291 static int exynos5420_pm_suspend(void) 292 { 293 u32 this_cluster; 294 295 exynos_pm_central_suspend(); 296 297 /* Setting SEQ_OPTION register */ 298 299 this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1); 300 if (!this_cluster) 301 pmu_raw_writel(EXYNOS5420_ARM_USE_STANDBY_WFI0, 302 S5P_CENTRAL_SEQ_OPTION); 303 else 304 pmu_raw_writel(EXYNOS5420_KFC_USE_STANDBY_WFI0, 305 S5P_CENTRAL_SEQ_OPTION); 306 return 0; 307 } 308 309 static void exynos_pm_release_retention(void) 310 { 311 unsigned int i; 312 313 for (i = 0; (pm_data->release_ret_regs[i] != REG_TABLE_END); i++) 314 pmu_raw_writel(EXYNOS_WAKEUP_FROM_LOWPWR, 315 pm_data->release_ret_regs[i]); 316 } 317 318 static void exynos_pm_resume(void) 319 { 320 u32 cpuid = read_cpuid_part(); 321 322 if (exynos_pm_central_resume()) 323 goto early_wakeup; 324 325 /* For release retention */ 326 exynos_pm_release_retention(); 327 328 if (pm_data->extra_save) 329 s3c_pm_do_restore_core(pm_data->extra_save, 330 pm_data->num_extra_save); 331 332 s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); 333 334 if (cpuid == ARM_CPU_PART_CORTEX_A9) 335 scu_enable(S5P_VA_SCU); 336 337 if (call_firmware_op(resume) == -ENOSYS 338 && cpuid == ARM_CPU_PART_CORTEX_A9) 339 exynos_cpu_restore_register(); 340 341 early_wakeup: 342 343 /* Clear SLEEP mode set in INFORM1 */ 344 pmu_raw_writel(0x0, S5P_INFORM1); 345 } 346 347 static void exynos5420_prepare_pm_resume(void) 348 { 349 if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) 350 WARN_ON(mcpm_cpu_powered_up()); 351 } 352 353 static void exynos5420_pm_resume(void) 354 { 355 unsigned long tmp; 356 357 /* Restore the CPU0 low power state register */ 358 tmp = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG); 359 pmu_raw_writel(tmp | S5P_CORE_LOCAL_PWR_EN, 360 EXYNOS5_ARM_CORE0_SYS_PWR_REG); 361 362 /* Restore the sysram cpu state register */ 363 __raw_writel(exynos5420_cpu_state, 364 sysram_base_addr + EXYNOS5420_CPU_STATE); 365 366 pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, 367 S5P_CENTRAL_SEQ_OPTION); 368 369 if (exynos_pm_central_resume()) 370 goto early_wakeup; 371 372 /* For release retention */ 373 exynos_pm_release_retention(); 374 375 pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3); 376 377 s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); 378 379 early_wakeup: 380 381 tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); 382 tmp &= ~EXYNOS5420_UFS; 383 pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1); 384 385 tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION); 386 tmp &= ~EXYNOS5420_EMULATION; 387 pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION); 388 389 tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION); 390 tmp &= ~EXYNOS5420_EMULATION; 391 pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION); 392 393 /* Clear SLEEP mode set in INFORM1 */ 394 pmu_raw_writel(0x0, S5P_INFORM1); 395 } 396 397 /* 398 * Suspend Ops 399 */ 400 401 static int exynos_suspend_enter(suspend_state_t state) 402 { 403 int ret; 404 405 s3c_pm_debug_init(); 406 407 S3C_PMDBG("%s: suspending the system...\n", __func__); 408 409 S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__, 410 exynos_irqwake_intmask, exynos_get_eint_wake_mask()); 411 412 if (exynos_irqwake_intmask == -1U 413 && exynos_get_eint_wake_mask() == -1U) { 414 pr_err("%s: No wake-up sources!\n", __func__); 415 pr_err("%s: Aborting sleep\n", __func__); 416 return -EINVAL; 417 } 418 419 s3c_pm_save_uarts(); 420 if (pm_data->pm_prepare) 421 pm_data->pm_prepare(); 422 flush_cache_all(); 423 s3c_pm_check_store(); 424 425 ret = call_firmware_op(suspend); 426 if (ret == -ENOSYS) 427 ret = cpu_suspend(0, pm_data->cpu_suspend); 428 if (ret) 429 return ret; 430 431 if (pm_data->pm_resume_prepare) 432 pm_data->pm_resume_prepare(); 433 s3c_pm_restore_uarts(); 434 435 S3C_PMDBG("%s: wakeup stat: %08x\n", __func__, 436 pmu_raw_readl(S5P_WAKEUP_STAT)); 437 438 s3c_pm_check_restore(); 439 440 S3C_PMDBG("%s: resuming the system...\n", __func__); 441 442 return 0; 443 } 444 445 static int exynos_suspend_prepare(void) 446 { 447 int ret; 448 449 /* 450 * REVISIT: It would be better if struct platform_suspend_ops 451 * .prepare handler get the suspend_state_t as a parameter to 452 * avoid hard-coding the suspend to mem state. It's safe to do 453 * it now only because the suspend_valid_only_mem function is 454 * used as the .valid callback used to check if a given state 455 * is supported by the platform anyways. 456 */ 457 ret = regulator_suspend_prepare(PM_SUSPEND_MEM); 458 if (ret) { 459 pr_err("Failed to prepare regulators for suspend (%d)\n", ret); 460 return ret; 461 } 462 463 s3c_pm_check_prepare(); 464 465 return 0; 466 } 467 468 static void exynos_suspend_finish(void) 469 { 470 int ret; 471 472 s3c_pm_check_cleanup(); 473 474 ret = regulator_suspend_finish(); 475 if (ret) 476 pr_warn("Failed to resume regulators from suspend (%d)\n", ret); 477 } 478 479 static const struct platform_suspend_ops exynos_suspend_ops = { 480 .enter = exynos_suspend_enter, 481 .prepare = exynos_suspend_prepare, 482 .finish = exynos_suspend_finish, 483 .valid = suspend_valid_only_mem, 484 }; 485 486 static const struct exynos_pm_data exynos4_pm_data = { 487 .wkup_irq = exynos4_wkup_irq, 488 .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)), 489 .release_ret_regs = exynos_release_ret_regs, 490 .pm_suspend = exynos_pm_suspend, 491 .pm_resume = exynos_pm_resume, 492 .pm_prepare = exynos_pm_prepare, 493 .cpu_suspend = exynos_cpu_suspend, 494 }; 495 496 static const struct exynos_pm_data exynos5250_pm_data = { 497 .wkup_irq = exynos5250_wkup_irq, 498 .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)), 499 .release_ret_regs = exynos_release_ret_regs, 500 .extra_save = exynos5_sys_save, 501 .num_extra_save = ARRAY_SIZE(exynos5_sys_save), 502 .pm_suspend = exynos_pm_suspend, 503 .pm_resume = exynos_pm_resume, 504 .pm_prepare = exynos_pm_prepare, 505 .cpu_suspend = exynos_cpu_suspend, 506 }; 507 508 static struct exynos_pm_data exynos5420_pm_data = { 509 .wkup_irq = exynos5250_wkup_irq, 510 .wake_disable_mask = (0x7F << 7) | (0x1F << 1), 511 .release_ret_regs = exynos5420_release_ret_regs, 512 .pm_resume_prepare = exynos5420_prepare_pm_resume, 513 .pm_resume = exynos5420_pm_resume, 514 .pm_suspend = exynos5420_pm_suspend, 515 .pm_prepare = exynos5420_pm_prepare, 516 .cpu_suspend = exynos5420_cpu_suspend, 517 }; 518 519 static struct of_device_id exynos_pmu_of_device_ids[] = { 520 { 521 .compatible = "samsung,exynos4210-pmu", 522 .data = &exynos4_pm_data, 523 }, { 524 .compatible = "samsung,exynos4212-pmu", 525 .data = &exynos4_pm_data, 526 }, { 527 .compatible = "samsung,exynos4412-pmu", 528 .data = &exynos4_pm_data, 529 }, { 530 .compatible = "samsung,exynos5250-pmu", 531 .data = &exynos5250_pm_data, 532 }, { 533 .compatible = "samsung,exynos5420-pmu", 534 .data = &exynos5420_pm_data, 535 }, 536 { /*sentinel*/ }, 537 }; 538 539 static struct syscore_ops exynos_pm_syscore_ops; 540 541 void __init exynos_pm_init(void) 542 { 543 const struct of_device_id *match; 544 u32 tmp; 545 546 of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match); 547 if (!match) { 548 pr_err("Failed to find PMU node\n"); 549 return; 550 } 551 pm_data = (struct exynos_pm_data *) match->data; 552 553 /* Platform-specific GIC callback */ 554 gic_arch_extn.irq_set_wake = exynos_irq_set_wake; 555 556 /* All wakeup disable */ 557 tmp = pmu_raw_readl(S5P_WAKEUP_MASK); 558 tmp |= pm_data->wake_disable_mask; 559 pmu_raw_writel(tmp, S5P_WAKEUP_MASK); 560 561 exynos_pm_syscore_ops.suspend = pm_data->pm_suspend; 562 exynos_pm_syscore_ops.resume = pm_data->pm_resume; 563 564 register_syscore_ops(&exynos_pm_syscore_ops); 565 suspend_set_ops(&exynos_suspend_ops); 566 } 567