1 // SPDX-License-Identifier: GPL-2.0-only 1 2 /* 3 * DaVinci Power Management Routines 4 * 5 * Copyright (C) 2009 Texas Instruments, Inc. 6 */ 7 8 #include <linux/pm.h> 9 #include <linux/suspend.h> 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/clk.h> 13 #include <linux/spinlock.h> 14 15 #include <asm/cacheflush.h> 16 #include <asm/delay.h> 17 #include <asm/io.h> 18 19 #include "common.h" 20 #include "da8xx.h" 21 #include "mux.h" 22 #include "pm.h" 23 #include "clock.h" 24 #include "psc.h" 25 #include "sram.h" 26 27 #define DA850_PLL1_BASE 0x01e1a000 28 #define DEEPSLEEP_SLEEPCOUNT_MASK 0xFFFF 29 #define DEEPSLEEP_SLEEPCOUNT 128 30 31 static void (*davinci_sram_suspend) (struct da 32 static struct davinci_pm_config pm_config = { 33 .sleepcount = DEEPSLEEP_SLEEPCOUNT, 34 .ddrpsc_num = DA8XX_LPSC1_EMIF3C, 35 }; 36 37 static void davinci_sram_push(void *dest, void 38 { 39 memcpy(dest, src, size); 40 flush_icache_range((unsigned long)dest 41 } 42 43 static void davinci_pm_suspend(void) 44 { 45 unsigned val; 46 47 if (pm_config.cpupll_reg_base != pm_co 48 49 /* Switch CPU PLL to bypass mo 50 val = __raw_readl(pm_config.cp 51 val &= ~(PLLCTL_PLLENSRC | PLL 52 __raw_writel(val, pm_config.cp 53 54 udelay(PLL_BYPASS_TIME); 55 56 /* Powerdown CPU PLL */ 57 val = __raw_readl(pm_config.cp 58 val |= PLLCTL_PLLPWRDN; 59 __raw_writel(val, pm_config.cp 60 } 61 62 /* Configure sleep count in deep sleep 63 val = __raw_readl(pm_config.deepsleep_ 64 val &= ~DEEPSLEEP_SLEEPCOUNT_MASK; 65 val |= pm_config.sleepcount; 66 __raw_writel(val, pm_config.deepsleep_ 67 68 /* System goes to sleep in this call * 69 davinci_sram_suspend(&pm_config); 70 71 if (pm_config.cpupll_reg_base != pm_co 72 73 /* put CPU PLL in reset */ 74 val = __raw_readl(pm_config.cp 75 val &= ~PLLCTL_PLLRST; 76 __raw_writel(val, pm_config.cp 77 78 /* put CPU PLL in power down * 79 val = __raw_readl(pm_config.cp 80 val &= ~PLLCTL_PLLPWRDN; 81 __raw_writel(val, pm_config.cp 82 83 /* wait for CPU PLL reset */ 84 udelay(PLL_RESET_TIME); 85 86 /* bring CPU PLL out of reset 87 val = __raw_readl(pm_config.cp 88 val |= PLLCTL_PLLRST; 89 __raw_writel(val, pm_config.cp 90 91 /* Wait for CPU PLL to lock */ 92 udelay(PLL_LOCK_TIME); 93 94 /* Remove CPU PLL from bypass 95 val = __raw_readl(pm_config.cp 96 val &= ~PLLCTL_PLLENSRC; 97 val |= PLLCTL_PLLEN; 98 __raw_writel(val, pm_config.cp 99 } 100 } 101 102 static int davinci_pm_enter(suspend_state_t st 103 { 104 int ret = 0; 105 106 switch (state) { 107 case PM_SUSPEND_MEM: 108 davinci_pm_suspend(); 109 break; 110 default: 111 ret = -EINVAL; 112 } 113 114 return ret; 115 } 116 117 static const struct platform_suspend_ops davin 118 .enter = davinci_pm_enter, 119 .valid = suspend_valid_only_m 120 }; 121 122 int __init davinci_pm_init(void) 123 { 124 int ret; 125 126 ret = davinci_cfg_reg(DA850_RTC_ALARM) 127 if (ret) 128 return ret; 129 130 pm_config.ddr2_ctlr_base = da8xx_get_m 131 pm_config.deepsleep_reg = DA8XX_SYSCFG 132 133 pm_config.cpupll_reg_base = ioremap(DA 134 if (!pm_config.cpupll_reg_base) 135 return -ENOMEM; 136 137 pm_config.ddrpll_reg_base = ioremap(DA 138 if (!pm_config.ddrpll_reg_base) { 139 ret = -ENOMEM; 140 goto no_ddrpll_mem; 141 } 142 143 pm_config.ddrpsc_reg_base = ioremap(DA 144 if (!pm_config.ddrpsc_reg_base) { 145 ret = -ENOMEM; 146 goto no_ddrpsc_mem; 147 } 148 149 davinci_sram_suspend = sram_alloc(davi 150 if (!davinci_sram_suspend) { 151 pr_err("PM: cannot allocate SR 152 ret = -ENOMEM; 153 goto no_sram_mem; 154 } 155 156 davinci_sram_push(davinci_sram_suspend 157 158 159 suspend_set_ops(&davinci_pm_ops); 160 161 return 0; 162 163 no_sram_mem: 164 iounmap(pm_config.ddrpsc_reg_base); 165 no_ddrpsc_mem: 166 iounmap(pm_config.ddrpll_reg_base); 167 no_ddrpll_mem: 168 iounmap(pm_config.cpupll_reg_base); 169 return ret; 170 } 171
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.