1 /* 2 * arch/arm/mach-at91/pm.c 3 * AT91 Power Management 4 * 5 * Copyright (C) 2005 David Brownell 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 */ 12 13 #include <linux/suspend.h> 14 #include <linux/sched.h> 15 #include <linux/proc_fs.h> 16 #include <linux/interrupt.h> 17 #include <linux/sysfs.h> 18 #include <linux/module.h> 19 #include <linux/platform_device.h> 20 21 #include <asm/io.h> 22 #include <asm/irq.h> 23 #include <asm/atomic.h> 24 #include <asm/mach/time.h> 25 #include <asm/mach/irq.h> 26 #include <asm/mach-types.h> 27 28 #include <asm/arch/at91_pmc.h> 29 #include <asm/arch/at91rm9200_mc.h> 30 #include <asm/arch/gpio.h> 31 #include <asm/arch/cpu.h> 32 33 #include "generic.h" 34 35 36 static int at91_pm_valid_state(suspend_state_t state) 37 { 38 switch (state) { 39 case PM_SUSPEND_ON: 40 case PM_SUSPEND_STANDBY: 41 case PM_SUSPEND_MEM: 42 return 1; 43 44 default: 45 return 0; 46 } 47 } 48 49 50 static suspend_state_t target_state; 51 52 /* 53 * Called after processes are frozen, but before we shutdown devices. 54 */ 55 static int at91_pm_begin(suspend_state_t state) 56 { 57 target_state = state; 58 return 0; 59 } 60 61 /* 62 * Verify that all the clocks are correct before entering 63 * slow-clock mode. 64 */ 65 static int at91_pm_verify_clocks(void) 66 { 67 unsigned long scsr; 68 int i; 69 70 scsr = at91_sys_read(AT91_PMC_SCSR); 71 72 /* USB must not be using PLLB */ 73 if (cpu_is_at91rm9200()) { 74 if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) { 75 pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); 76 return 0; 77 } 78 } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) { 79 if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) { 80 pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); 81 return 0; 82 } 83 } else if (cpu_is_at91cap9()) { 84 if ((scsr & AT91CAP9_PMC_UHP) != 0) { 85 pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); 86 return 0; 87 } 88 } 89 90 #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS 91 /* PCK0..PCK3 must be disabled, or configured to use clk32k */ 92 for (i = 0; i < 4; i++) { 93 u32 css; 94 95 if ((scsr & (AT91_PMC_PCK0 << i)) == 0) 96 continue; 97 98 css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS; 99 if (css != AT91_PMC_CSS_SLOW) { 100 pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); 101 return 0; 102 } 103 } 104 #endif 105 106 return 1; 107 } 108 109 /* 110 * Call this from platform driver suspend() to see how deeply to suspend. 111 * For example, some controllers (like OHCI) need one of the PLL clocks 112 * in order to act as a wakeup source, and those are not available when 113 * going into slow clock mode. 114 * 115 * REVISIT: generalize as clk_will_be_available(clk)? Other platforms have 116 * the very same problem (but not using at91 main_clk), and it'd be better 117 * to add one generic API rather than lots of platform-specific ones. 118 */ 119 int at91_suspend_entering_slow_clock(void) 120 { 121 return (target_state == PM_SUSPEND_MEM); 122 } 123 EXPORT_SYMBOL(at91_suspend_entering_slow_clock); 124 125 126 static void (*slow_clock)(void); 127 128 129 static int at91_pm_enter(suspend_state_t state) 130 { 131 at91_gpio_suspend(); 132 at91_irq_suspend(); 133 134 pr_debug("AT91: PM - wake mask %08x, pm state %d\n", 135 /* remember all the always-wake irqs */ 136 (at91_sys_read(AT91_PMC_PCSR) 137 | (1 << AT91_ID_FIQ) 138 | (1 << AT91_ID_SYS) 139 | (at91_extern_irq)) 140 & at91_sys_read(AT91_AIC_IMR), 141 state); 142 143 switch (state) { 144 /* 145 * Suspend-to-RAM is like STANDBY plus slow clock mode, so 146 * drivers must suspend more deeply: only the master clock 147 * controller may be using the main oscillator. 148 */ 149 case PM_SUSPEND_MEM: 150 /* 151 * Ensure that clocks are in a valid state. 152 */ 153 if (!at91_pm_verify_clocks()) 154 goto error; 155 156 /* 157 * Enter slow clock mode by switching over to clk32k and 158 * turning off the main oscillator; reverse on wakeup. 159 */ 160 if (slow_clock) { 161 slow_clock(); 162 break; 163 } else { 164 /* DEVELOPMENT ONLY */ 165 pr_info("AT91: PM - no slow clock mode yet ...\n"); 166 /* FALLTHROUGH leaving master clock alone */ 167 } 168 169 /* 170 * STANDBY mode has *all* drivers suspended; ignores irqs not 171 * marked as 'wakeup' event sources; and reduces DRAM power. 172 * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and 173 * nothing fancy done with main or cpu clocks. 174 */ 175 case PM_SUSPEND_STANDBY: 176 /* 177 * NOTE: the Wait-for-Interrupt instruction needs to be 178 * in icache so the SDRAM stays in self-refresh mode until 179 * the wakeup IRQ occurs. 180 */ 181 asm("b 1f; .align 5; 1:"); 182 asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ 183 at91_sys_write(AT91_SDRAMC_SRR, 1); /* self-refresh mode */ 184 /* fall though to next state */ 185 186 case PM_SUSPEND_ON: 187 asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */ 188 break; 189 190 default: 191 pr_debug("AT91: PM - bogus suspend state %d\n", state); 192 goto error; 193 } 194 195 pr_debug("AT91: PM - wakeup %08x\n", 196 at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR)); 197 198 error: 199 target_state = PM_SUSPEND_ON; 200 at91_irq_resume(); 201 at91_gpio_resume(); 202 return 0; 203 } 204 205 /* 206 * Called right prior to thawing processes. 207 */ 208 static void at91_pm_end(void) 209 { 210 target_state = PM_SUSPEND_ON; 211 } 212 213 214 static struct platform_suspend_ops at91_pm_ops ={ 215 .valid = at91_pm_valid_state, 216 .begin = at91_pm_begin, 217 .enter = at91_pm_enter, 218 .end = at91_pm_end, 219 }; 220 221 static int __init at91_pm_init(void) 222 { 223 printk("AT91: Power Management\n"); 224 225 #ifdef CONFIG_AT91_PM_SLOW_CLOCK 226 /* REVISIT allocations of SRAM should be dynamically managed. 227 * FIQ handlers and other components will want SRAM/TCM too... 228 */ 229 slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K)); 230 memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz); 231 #endif 232 233 /* Disable SDRAM low-power mode. Cannot be used with self-refresh. */ 234 at91_sys_write(AT91_SDRAMC_LPR, 0); 235 236 suspend_set_ops(&at91_pm_ops); 237 238 return 0; 239 } 240 arch_initcall(at91_pm_init); 241