Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pm.c
Go to the documentation of this file.
1 /*
2  * Blackfin bf609 power management
3  *
4  * Copyright 2011 Analog Devices Inc.
5  *
6  * Licensed under the GPL-2
7  */
8 
9 #include <linux/suspend.h>
10 #include <linux/io.h>
11 #include <linux/interrupt.h>
12 #include <linux/gpio.h>
13 #include <linux/irq.h>
14 #include <linux/delay.h>
15 #include <linux/syscore_ops.h>
16 
17 #include <asm/dpmc.h>
18 #include <asm/pm.h>
19 #include <mach/pm.h>
20 #include <asm/blackfin.h>
21 #include <asm/mem_init.h>
22 
23 /***********************************************************/
24 /* */
25 /* Wakeup Actions for DPM_RESTORE */
26 /* */
27 /***********************************************************/
28 #define BITP_ROM_WUA_CHKHDR 24
29 #define BITP_ROM_WUA_DDRLOCK 7
30 #define BITP_ROM_WUA_DDRDLLEN 6
31 #define BITP_ROM_WUA_DDR 5
32 #define BITP_ROM_WUA_CGU 4
33 #define BITP_ROM_WUA_MEMBOOT 2
34 #define BITP_ROM_WUA_EN 1
35 
36 #define BITM_ROM_WUA_CHKHDR (0xFF000000)
37 #define ENUM_ROM_WUA_CHKHDR_AD 0xAD000000
38 
39 #define BITM_ROM_WUA_DDRLOCK (0x00000080)
40 #define BITM_ROM_WUA_DDRDLLEN (0x00000040)
41 #define BITM_ROM_WUA_DDR (0x00000020)
42 #define BITM_ROM_WUA_CGU (0x00000010)
43 #define BITM_ROM_WUA_MEMBOOT (0x00000002)
44 #define BITM_ROM_WUA_EN (0x00000001)
45 
46 /***********************************************************/
47 /* */
48 /* Syscontrol */
49 /* */
50 /***********************************************************/
51 #define BITP_ROM_SYSCTRL_CGU_LOCKINGEN 28 /* unlocks CGU_CTL register */
52 #define BITP_ROM_SYSCTRL_WUA_OVERRIDE 24
53 #define BITP_ROM_SYSCTRL_WUA_DDRDLLEN 20 /* Saves the DDR DLL and PADS registers to the DPM registers */
54 #define BITP_ROM_SYSCTRL_WUA_DDR 19 /* Saves the DDR registers to the DPM registers */
55 #define BITP_ROM_SYSCTRL_WUA_CGU 18 /* Saves the CGU registers into DPM registers */
56 #define BITP_ROM_SYSCTRL_WUA_DPMWRITE 17 /* Saves the Syscontrol structure structure contents into DPM registers */
57 #define BITP_ROM_SYSCTRL_WUA_EN 16 /* reads current PLL and DDR configuration into structure */
58 #define BITP_ROM_SYSCTRL_DDR_WRITE 13 /* writes the DDR registers from Syscontrol structure for wakeup initialization of DDR */
59 #define BITP_ROM_SYSCTRL_DDR_READ 12 /* Read the DDR registers into the Syscontrol structure for storing prior to hibernate */
60 #define BITP_ROM_SYSCTRL_CGU_AUTODIS 11 /* Disables auto handling of UPDT and ALGN fields */
61 #define BITP_ROM_SYSCTRL_CGU_CLKOUTSEL 7 /* access CGU_CLKOUTSEL register */
62 #define BITP_ROM_SYSCTRL_CGU_DIV 6 /* access CGU_DIV register */
63 #define BITP_ROM_SYSCTRL_CGU_STAT 5 /* access CGU_STAT register */
64 #define BITP_ROM_SYSCTRL_CGU_CTL 4 /* access CGU_CTL register */
65 #define BITP_ROM_SYSCTRL_CGU_RTNSTAT 2 /* Update structure STAT field upon error */
66 #define BITP_ROM_SYSCTRL_WRITE 1 /* write registers */
67 #define BITP_ROM_SYSCTRL_READ 0 /* read registers */
68 
69 #define BITM_ROM_SYSCTRL_CGU_READ (0x00000001) /* Read CGU registers */
70 #define BITM_ROM_SYSCTRL_CGU_WRITE (0x00000002) /* Write registers */
71 #define BITM_ROM_SYSCTRL_CGU_RTNSTAT (0x00000004) /* Update structure STAT field upon error or after a write operation */
72 #define BITM_ROM_SYSCTRL_CGU_CTL (0x00000010) /* Access CGU_CTL register */
73 #define BITM_ROM_SYSCTRL_CGU_STAT (0x00000020) /* Access CGU_STAT register */
74 #define BITM_ROM_SYSCTRL_CGU_DIV (0x00000040) /* Access CGU_DIV register */
75 #define BITM_ROM_SYSCTRL_CGU_CLKOUTSEL (0x00000080) /* Access CGU_CLKOUTSEL register */
76 #define BITM_ROM_SYSCTRL_CGU_AUTODIS (0x00000800) /* Disables auto handling of UPDT and ALGN fields */
77 #define BITM_ROM_SYSCTRL_DDR_READ (0x00001000) /* Reads the contents of the DDR registers and stores them into the structure */
78 #define BITM_ROM_SYSCTRL_DDR_WRITE (0x00002000) /* Writes the DDR registers from the structure, only really intented for wakeup functionality and not for full DDR configuration */
79 #define BITM_ROM_SYSCTRL_WUA_EN (0x00010000) /* Wakeup entry or exit opertation enable */
80 #define BITM_ROM_SYSCTRL_WUA_DPMWRITE (0x00020000) /* When set indicates a restore of the PLL and DDR is to be performed otherwise a save is required */
81 #define BITM_ROM_SYSCTRL_WUA_CGU (0x00040000) /* Only applicable for a PLL and DDR save operation to the DPM, saves the current settings if cleared or the contents of the structure if set */
82 #define BITM_ROM_SYSCTRL_WUA_DDR (0x00080000) /* Only applicable for a PLL and DDR save operation to the DPM, saves the current settings if cleared or the contents of the structure if set */
83 #define BITM_ROM_SYSCTRL_WUA_DDRDLLEN (0x00100000) /* Enables saving/restoring of the DDR DLLCTL register */
84 #define BITM_ROM_SYSCTRL_WUA_OVERRIDE (0x01000000)
85 #define BITM_ROM_SYSCTRL_CGU_LOCKINGEN (0x10000000) /* Unlocks the CGU_CTL register */
86 
87 
88 /* Structures for the syscontrol() function */
108 };
109 
110 struct bfin_pm_data {
114 };
115 
117 
120 
121 #define FUNC_ROM_SYSCONTROL 0xC8000080
122 __attribute__((l1_data))
123 static uint32_t (* const bfrom_SysControl)(uint32_t action_flags, struct STRUCT_ROM_SYSCTRL *settings, void *reserved) = (void *)FUNC_ROM_SYSCONTROL;
124 
125 __attribute__((l1_text))
126 void bfin_cpu_suspend(void)
127 {
128  __asm__ __volatile__( \
129  ".align 8;" \
130  "idle;" \
131  : : \
132  );
133 }
134 
135 __attribute__((l1_text))
136 void bf609_ddr_sr(void)
137 {
138  dmc_enter_self_refresh();
139 }
140 
141 __attribute__((l1_text))
142 void bf609_ddr_sr_exit(void)
143 {
144  dmc_exit_self_refresh();
145 
146  /* After wake up from deep sleep and exit DDR from self refress mode,
147  * should wait till CGU PLL is locked.
148  */
149  while (bfin_read32(CGU0_STAT) & CLKSALGN)
150  continue;
151 }
152 
153 __attribute__((l1_text))
154 void bf609_resume_ccbuf(void)
155 {
158 
159  while ((bfin_read32(DPM0_STAT) & 0xf) != 1);
160 }
161 
162 __attribute__((l1_text))
163 void bfin_hibernate_syscontrol(void)
164 {
165  configvalues.ulWUA_Flags = (0xAD000000 | BITM_ROM_WUA_EN
167 
171 
172  bfrom_SysControl(dactionflags, &configvalues, NULL);
173 
175 }
176 
177 #define IRQ_SID(irq) ((irq) - IVG15)
178 asmlinkage void enter_deepsleep(void);
179 
180 __attribute__((l1_text))
181 void bfin_deepsleep(unsigned long mask, unsigned long pol_mask)
182 {
183  bfin_write32(DPM0_WAKE_EN, mask);
184  bfin_write32(DPM0_WAKE_POL, pol_mask);
185  SSYNC();
186  enter_deepsleep();
187 }
188 
189 void bfin_hibernate(unsigned long mask, unsigned long pol_mask)
190 {
191  bfin_write32(DPM0_WAKE_EN, mask);
192  bfin_write32(DPM0_WAKE_POL, pol_mask);
193  bfin_write32(DPM0_PGCNTR, 0x0000FFFF);
194  bfin_write32(DPM0_HIB_DIS, 0xFFFF);
195 
196  bf609_hibernate();
197 }
198 
200 {
201  int error;
202  unsigned long wakeup = 0;
203  unsigned long wakeup_pol = 0;
204 
205 #ifdef CONFIG_PM_BFIN_WAKE_PA15
206  wakeup |= PA15WE;
207 # if CONFIG_PM_BFIN_WAKE_PA15_POL
208  wakeup_pol |= PA15WE;
209 # endif
210 #endif
211 
212 #ifdef CONFIG_PM_BFIN_WAKE_PB15
213  wakeup |= PB15WE;
214 # if CONFIG_PM_BFIN_WAKE_PA15_POL
215  wakeup_pol |= PB15WE;
216 # endif
217 #endif
218 
219 #ifdef CONFIG_PM_BFIN_WAKE_PC15
220  wakeup |= PC15WE;
221 # if CONFIG_PM_BFIN_WAKE_PC15_POL
222  wakeup_pol |= PC15WE;
223 # endif
224 #endif
225 
226 #ifdef CONFIG_PM_BFIN_WAKE_PD06
227  wakeup |= PD06WE;
228 # if CONFIG_PM_BFIN_WAKE_PD06_POL
229  wakeup_pol |= PD06WE;
230 # endif
231 #endif
232 
233 #ifdef CONFIG_PM_BFIN_WAKE_PE12
234  wakeup |= PE12WE;
235 # if CONFIG_PM_BFIN_WAKE_PE12_POL
236  wakeup_pol |= PE12WE;
237 # endif
238 #endif
239 
240 #ifdef CONFIG_PM_BFIN_WAKE_PG04
241  wakeup |= PG04WE;
242 # if CONFIG_PM_BFIN_WAKE_PG04_POL
243  wakeup_pol |= PG04WE;
244 # endif
245 #endif
246 
247 #ifdef CONFIG_PM_BFIN_WAKE_PG13
248  wakeup |= PG13WE;
249 # if CONFIG_PM_BFIN_WAKE_PG13_POL
250  wakeup_pol |= PG13WE;
251 # endif
252 #endif
253 
254 #ifdef CONFIG_PM_BFIN_WAKE_USB
255  wakeup |= USBWE;
256 # if CONFIG_PM_BFIN_WAKE_USB_POL
257  wakeup_pol |= USBWE;
258 # endif
259 #endif
260 
261  error = irq_set_irq_wake(255, 1);
262  if(error < 0)
263  printk(KERN_DEBUG "Unable to get irq wake\n");
264  error = irq_set_irq_wake(231, 1);
265  if (error < 0)
266  printk(KERN_DEBUG "Unable to get irq wake\n");
267 
268  if (state == PM_SUSPEND_STANDBY)
269  bfin_deepsleep(wakeup, wakeup_pol);
270  else {
271  bfin_hibernate(wakeup, wakeup_pol);
272  }
273 
274 }
275 
277 {
278  return 0;
279 }
280 
282 {
283 
284 }
285 
286 static struct bfin_cpu_pm_fns bf609_cpu_pm = {
287  .enter = bf609_cpu_pm_enter,
288  .prepare = bf609_cpu_pm_prepare,
289  .finish = bf609_cpu_pm_finish,
290 };
291 
292 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
293 static int smc_pm_syscore_suspend(void)
294 {
296  return 0;
297 }
298 
299 static void smc_pm_syscore_resume(void)
300 {
302 }
303 
304 static struct syscore_ops smc_pm_syscore_ops = {
305  .suspend = smc_pm_syscore_suspend,
306  .resume = smc_pm_syscore_resume,
307 };
308 #endif
309 
310 static irqreturn_t test_isr(int irq, void *dev_id)
311 {
312  printk(KERN_DEBUG "gpio irq %d\n", irq);
313  if (irq == 231)
315  return IRQ_HANDLED;
316 }
317 
318 static irqreturn_t dpm0_isr(int irq, void *dev_id)
319 {
322  return IRQ_HANDLED;
323 }
324 
325 static int __init bf609_init_pm(void)
326 {
327  int irq;
328  int error;
329 
330 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
331  register_syscore_ops(&smc_pm_syscore_ops);
332 #endif
333 
334 #ifdef CONFIG_PM_BFIN_WAKE_PE12
335  irq = gpio_to_irq(GPIO_PE12);
336  if (irq < 0) {
337  error = irq;
338  printk(KERN_DEBUG "Unable to get irq number for GPIO %d, error %d\n",
339  GPIO_PE12, error);
340  }
341 
342  error = request_irq(irq, test_isr, IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND
343  | IRQF_FORCE_RESUME, "gpiope12", NULL);
344  if(error < 0)
345  printk(KERN_DEBUG "Unable to get irq\n");
346 #endif
347 
348  error = request_irq(IRQ_CGU_EVT, dpm0_isr, IRQF_NO_SUSPEND |
349  IRQF_FORCE_RESUME, "cgu0 event", NULL);
350  if(error < 0)
351  printk(KERN_DEBUG "Unable to get irq\n");
352 
353  error = request_irq(IRQ_DPM, dpm0_isr, IRQF_NO_SUSPEND |
354  IRQF_FORCE_RESUME, "dpm0 event", NULL);
355  if (error < 0)
356  printk(KERN_DEBUG "Unable to get irq\n");
357 
358  bfin_cpu_pm = &bf609_cpu_pm;
359  return 0;
360 }
361 
362 late_initcall(bf609_init_pm);