1ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee/* linux/arch/arm/mach-s5pv210/pm.c 2ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * 30a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa * Copyright (c) 2010-2014 Samsung Electronics Co., Ltd. 4ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * http://www.samsung.com 5ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * 6ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * S5PV210 - Power Management support 7ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * 8ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * Based on arch/arm/mach-s3c2410/pm.c 9ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * Copyright (c) 2006 Simtec Electronics 10ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * Ben Dooks <ben@simtec.co.uk> 11ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * 12ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * This program is free software; you can redistribute it and/or modify 13ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * it under the terms of the GNU General Public License version 2 as 14ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * published by the Free Software Foundation. 15ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee*/ 16ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 17ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee#include <linux/init.h> 18ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee#include <linux/suspend.h> 19bb072c3cf21d1c9a5a2eeb5a00679ee7bf39675bRafael J. Wysocki#include <linux/syscore_ops.h> 20ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee#include <linux/io.h> 21ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 220a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa#include <asm/cacheflush.h> 230a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa#include <asm/suspend.h> 240a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 250a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa#include <plat/pm-common.h> 26ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 270a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa#include "common.h" 289740bdd985277a7f71423738c34a2c88cd533f1cKukjin Kim#include "regs-clock.h" 290a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 30ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Leestatic struct sleep_save s5pv210_core_save[] = { 31ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee /* Clock ETC */ 32ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee SAVE_ITEM(S5P_MDNIE_SEL), 33ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee}; 34ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 350a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa/* 360a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa * VIC wake-up support (TODO) 370a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa */ 380a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figastatic u32 s5pv210_irqwake_intmask = 0xffffffff; 390a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 400a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa/* 410a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa * Suspend helpers. 420a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa */ 437e1291dea213c46b6649a9f6ec94b16f0d88f97cAbhilash Kesavanstatic int s5pv210_cpu_suspend(unsigned long arg) 44ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee{ 45ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee unsigned long tmp; 46ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 47ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee /* issue the standby signal into the pm unit. Note, we 48ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee * issue a write-buffer drain just in case */ 49ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 50ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp = 0; 51ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 52ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee asm("b 1f\n\t" 53ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee ".align 5\n\t" 54ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee "1:\n\t" 55ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee "mcr p15, 0, %0, c7, c10, 5\n\t" 56ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee "mcr p15, 0, %0, c7, c10, 4\n\t" 57ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee "wfi" : : "r" (tmp)); 58ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 59d3fcacf52d24ff1b12d994d9ddb7496f651294a2Abhilash Kesavan pr_info("Failed to suspend the system\n"); 60d3fcacf52d24ff1b12d994d9ddb7496f651294a2Abhilash Kesavan return 1; /* Aborting suspend */ 61ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee} 62ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 63ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Leestatic void s5pv210_pm_prepare(void) 64ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee{ 65ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee unsigned int tmp; 66ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 670a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa /* Set wake-up mask registers */ 680a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa __raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK); 690a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa __raw_writel(s5pv210_irqwake_intmask, S5P_WAKEUP_MASK); 700a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 71ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee /* ensure at least INFORM0 has the resume address */ 720a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa __raw_writel(virt_to_phys(s5pv210_cpu_resume), S5P_INFORM0); 73ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 74ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp = __raw_readl(S5P_SLEEP_CFG); 75ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN); 76ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee __raw_writel(tmp, S5P_SLEEP_CFG); 77ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 78ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee /* WFI for SLEEP mode configuration by SYSCON */ 79ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp = __raw_readl(S5P_PWR_CFG); 80ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp &= S5P_CFG_WFI_CLEAN; 81ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp |= S5P_CFG_WFI_SLEEP; 82ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee __raw_writel(tmp, S5P_PWR_CFG); 83ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 84ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee /* SYSCON interrupt handling disable */ 85ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp = __raw_readl(S5P_OTHERS); 86ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp |= S5P_OTHER_SYSC_INTOFF; 87ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee __raw_writel(tmp, S5P_OTHERS); 88ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 89ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save)); 90ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee} 91ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 920a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa/* 930a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa * Suspend operations. 940a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa */ 950a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figastatic int s5pv210_suspend_enter(suspend_state_t state) 960a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa{ 970a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa int ret; 980a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 990a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa s3c_pm_debug_init(); 1000a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1010a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa S3C_PMDBG("%s: suspending the system...\n", __func__); 1020a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1030a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__, 1040a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa s5pv210_irqwake_intmask, exynos_get_eint_wake_mask()); 1050a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1060a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa if (s5pv210_irqwake_intmask == -1U 1070a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa && exynos_get_eint_wake_mask() == -1U) { 1080a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa pr_err("%s: No wake-up sources!\n", __func__); 1090a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa pr_err("%s: Aborting sleep\n", __func__); 1100a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa return -EINVAL; 1110a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa } 1120a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1130a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa s3c_pm_save_uarts(); 1140a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa s5pv210_pm_prepare(); 1150a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa flush_cache_all(); 1160a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa s3c_pm_check_store(); 1170a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1180a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa ret = cpu_suspend(0, s5pv210_cpu_suspend); 1190a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa if (ret) 1200a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa return ret; 1210a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1220a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa s3c_pm_restore_uarts(); 1230a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1240a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa S3C_PMDBG("%s: wakeup stat: %08x\n", __func__, 1250a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa __raw_readl(S5P_WAKEUP_STAT)); 1260a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1270a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa s3c_pm_check_restore(); 1280a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1290a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa S3C_PMDBG("%s: resuming the system...\n", __func__); 1300a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1310a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa return 0; 1320a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa} 1330a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1340a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figastatic int s5pv210_suspend_prepare(void) 1350a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa{ 1360a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa s3c_pm_check_prepare(); 1370a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1380a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa return 0; 1390a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa} 1400a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1410a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figastatic void s5pv210_suspend_finish(void) 1420a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa{ 1430a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa s3c_pm_check_cleanup(); 1440a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa} 1450a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1460a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figastatic const struct platform_suspend_ops s5pv210_suspend_ops = { 1470a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa .enter = s5pv210_suspend_enter, 1480a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa .prepare = s5pv210_suspend_prepare, 1490a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa .finish = s5pv210_suspend_finish, 1500a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa .valid = suspend_valid_only_mem, 1510a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa}; 1520a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa 1530a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa/* 1540a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa * Syscore operations used to delay restore of certain registers. 1550a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa */ 156bb072c3cf21d1c9a5a2eeb5a00679ee7bf39675bRafael J. Wysockistatic void s5pv210_pm_resume(void) 157ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee{ 158ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee u32 tmp; 159ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 160ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp = __raw_readl(S5P_OTHERS); 161ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF |\ 162ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART); 163ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee __raw_writel(tmp , S5P_OTHERS); 164ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 165ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save)); 166ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee} 167ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 168bb072c3cf21d1c9a5a2eeb5a00679ee7bf39675bRafael J. Wysockistatic struct syscore_ops s5pv210_pm_syscore_ops = { 169ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee .resume = s5pv210_pm_resume, 170ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee}; 171ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee 1720a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa/* 1730a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa * Initialization entry point. 1740a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa */ 1750a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figavoid __init s5pv210_pm_init(void) 176ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee{ 177bb072c3cf21d1c9a5a2eeb5a00679ee7bf39675bRafael J. Wysocki register_syscore_ops(&s5pv210_pm_syscore_ops); 1780a90d4d62c71e27cedebf938d7c37db543b93e78Tomasz Figa suspend_set_ops(&s5pv210_suspend_ops); 179ea31fd4330c823bd156d6484e32a0777c35f200fJongpill Lee} 180