Merge branch 'lpc32xx/dts' of git://git.antcom.de/linux-2.6 into next/dt
[platform/adaptation/renesas_rcar/renesas_kernel.git] / arch / arm / mach-shmobile / pm-sh7372.c
1 /*
2  * sh7372 Power management support
3  *
4  *  Copyright (C) 2011 Magnus Damm
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file "COPYING" in the main directory of this archive
8  * for more details.
9  */
10
11 #include <linux/pm.h>
12 #include <linux/suspend.h>
13 #include <linux/cpuidle.h>
14 #include <linux/module.h>
15 #include <linux/list.h>
16 #include <linux/err.h>
17 #include <linux/slab.h>
18 #include <linux/pm_clock.h>
19 #include <linux/platform_device.h>
20 #include <linux/delay.h>
21 #include <linux/irq.h>
22 #include <linux/bitrev.h>
23 #include <linux/console.h>
24 #include <asm/io.h>
25 #include <asm/tlbflush.h>
26 #include <asm/suspend.h>
27 #include <mach/common.h>
28 #include <mach/sh7372.h>
29 #include <mach/pm-rmobile.h>
30
31 /* DBG */
32 #define DBGREG1 0xe6100020
33 #define DBGREG9 0xe6100040
34
35 /* CPGA */
36 #define SYSTBCR 0xe6150024
37 #define MSTPSR0 0xe6150030
38 #define MSTPSR1 0xe6150038
39 #define MSTPSR2 0xe6150040
40 #define MSTPSR3 0xe6150048
41 #define MSTPSR4 0xe615004c
42 #define PLLC01STPCR 0xe61500c8
43
44 /* SYSC */
45 #define SBAR 0xe6180020
46 #define WUPRMSK 0xe6180028
47 #define WUPSMSK 0xe618002c
48 #define WUPSMSK2 0xe6180048
49 #define WUPSFAC 0xe6180098
50 #define IRQCR 0xe618022c
51 #define IRQCR2 0xe6180238
52 #define IRQCR3 0xe6180244
53 #define IRQCR4 0xe6180248
54 #define PDNSEL 0xe6180254
55
56 /* INTC */
57 #define ICR1A 0xe6900000
58 #define ICR2A 0xe6900004
59 #define ICR3A 0xe6900008
60 #define ICR4A 0xe690000c
61 #define INTMSK00A 0xe6900040
62 #define INTMSK10A 0xe6900044
63 #define INTMSK20A 0xe6900048
64 #define INTMSK30A 0xe690004c
65
66 /* MFIS */
67 #define SMFRAM 0xe6a70000
68
69 /* AP-System Core */
70 #define APARMBAREA 0xe6f10020
71
72 #ifdef CONFIG_PM
73
74 struct rmobile_pm_domain sh7372_pd_a4lc = {
75         .genpd.name = "A4LC",
76         .bit_shift = 1,
77 };
78
79 struct rmobile_pm_domain sh7372_pd_a4mp = {
80         .genpd.name = "A4MP",
81         .bit_shift = 2,
82 };
83
84 struct rmobile_pm_domain sh7372_pd_d4 = {
85         .genpd.name = "D4",
86         .bit_shift = 3,
87 };
88
89 static int sh7372_a4r_pd_suspend(void)
90 {
91         sh7372_intcs_suspend();
92         __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
93         return 0;
94 }
95
96 struct rmobile_pm_domain sh7372_pd_a4r = {
97         .genpd.name = "A4R",
98         .bit_shift = 5,
99         .suspend = sh7372_a4r_pd_suspend,
100         .resume = sh7372_intcs_resume,
101 };
102
103 struct rmobile_pm_domain sh7372_pd_a3rv = {
104         .genpd.name = "A3RV",
105         .bit_shift = 6,
106 };
107
108 struct rmobile_pm_domain sh7372_pd_a3ri = {
109         .genpd.name = "A3RI",
110         .bit_shift = 8,
111 };
112
113 static int sh7372_pd_a4s_suspend(void)
114 {
115         /*
116          * The A4S domain contains the CPU core and therefore it should
117          * only be turned off if the CPU is in use.
118          */
119         return -EBUSY;
120 }
121
122 struct rmobile_pm_domain sh7372_pd_a4s = {
123         .genpd.name = "A4S",
124         .bit_shift = 10,
125         .gov = &pm_domain_always_on_gov,
126         .no_debug = true,
127         .suspend = sh7372_pd_a4s_suspend,
128 };
129
130 static int sh7372_a3sp_pd_suspend(void)
131 {
132         /*
133          * Serial consoles make use of SCIF hardware located in A3SP,
134          * keep such power domain on if "no_console_suspend" is set.
135          */
136         return console_suspend_enabled ? 0 : -EBUSY;
137 }
138
139 struct rmobile_pm_domain sh7372_pd_a3sp = {
140         .genpd.name = "A3SP",
141         .bit_shift = 11,
142         .gov = &pm_domain_always_on_gov,
143         .no_debug = true,
144         .suspend = sh7372_a3sp_pd_suspend,
145 };
146
147 struct rmobile_pm_domain sh7372_pd_a3sg = {
148         .genpd.name = "A3SG",
149         .bit_shift = 13,
150 };
151
152 #endif /* CONFIG_PM */
153
154 #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
155 static void sh7372_set_reset_vector(unsigned long address)
156 {
157         /* set reset vector, translate 4k */
158         __raw_writel(address, SBAR);
159         __raw_writel(0, APARMBAREA);
160 }
161
162 static void sh7372_enter_sysc(int pllc0_on, unsigned long sleep_mode)
163 {
164         if (pllc0_on)
165                 __raw_writel(0, PLLC01STPCR);
166         else
167                 __raw_writel(1 << 28, PLLC01STPCR);
168
169         __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */
170         cpu_suspend(sleep_mode, sh7372_do_idle_sysc);
171         __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */
172
173          /* disable reset vector translation */
174         __raw_writel(0, SBAR);
175 }
176
177 static int sh7372_sysc_valid(unsigned long *mskp, unsigned long *msk2p)
178 {
179         unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4;
180         unsigned long msk, msk2;
181
182         /* check active clocks to determine potential wakeup sources */
183
184         mstpsr0 = __raw_readl(MSTPSR0);
185         if ((mstpsr0 & 0x00000003) != 0x00000003) {
186                 pr_debug("sh7372 mstpsr0 0x%08lx\n", mstpsr0);
187                 return 0;
188         }
189
190         mstpsr1 = __raw_readl(MSTPSR1);
191         if ((mstpsr1 & 0xff079b7f) != 0xff079b7f) {
192                 pr_debug("sh7372 mstpsr1 0x%08lx\n", mstpsr1);
193                 return 0;
194         }
195
196         mstpsr2 = __raw_readl(MSTPSR2);
197         if ((mstpsr2 & 0x000741ff) != 0x000741ff) {
198                 pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2);
199                 return 0;
200         }
201
202         mstpsr3 = __raw_readl(MSTPSR3);
203         if ((mstpsr3 & 0x1a60f010) != 0x1a60f010) {
204                 pr_debug("sh7372 mstpsr3 0x%08lx\n", mstpsr3);
205                 return 0;
206         }
207
208         mstpsr4 = __raw_readl(MSTPSR4);
209         if ((mstpsr4 & 0x00008cf0) != 0x00008cf0) {
210                 pr_debug("sh7372 mstpsr4 0x%08lx\n", mstpsr4);
211                 return 0;
212         }
213
214         msk = 0;
215         msk2 = 0;
216
217         /* make bitmaps of limited number of wakeup sources */
218
219         if ((mstpsr2 & (1 << 23)) == 0) /* SPU2 */
220                 msk |= 1 << 31;
221
222         if ((mstpsr2 & (1 << 12)) == 0) /* MFI_MFIM */
223                 msk |= 1 << 21;
224
225         if ((mstpsr4 & (1 << 3)) == 0) /* KEYSC */
226                 msk |= 1 << 2;
227
228         if ((mstpsr1 & (1 << 24)) == 0) /* CMT0 */
229                 msk |= 1 << 1;
230
231         if ((mstpsr3 & (1 << 29)) == 0) /* CMT1 */
232                 msk |= 1 << 1;
233
234         if ((mstpsr4 & (1 << 0)) == 0) /* CMT2 */
235                 msk |= 1 << 1;
236
237         if ((mstpsr2 & (1 << 13)) == 0) /* MFI_MFIS */
238                 msk2 |= 1 << 17;
239
240         *mskp = msk;
241         *msk2p = msk2;
242
243         return 1;
244 }
245
246 static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p)
247 {
248         u16 tmp, irqcr1, irqcr2;
249         int k;
250
251         irqcr1 = 0;
252         irqcr2 = 0;
253
254         /* convert INTCA ICR register layout to SYSC IRQCR+IRQCR2 */
255         for (k = 0; k <= 7; k++) {
256                 tmp = (icr >> ((7 - k) * 4)) & 0xf;
257                 irqcr1 |= (tmp & 0x03) << (k * 2);
258                 irqcr2 |= (tmp >> 2) << (k * 2);
259         }
260
261         *irqcr1p = irqcr1;
262         *irqcr2p = irqcr2;
263 }
264
265 static void sh7372_setup_sysc(unsigned long msk, unsigned long msk2)
266 {
267         u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high;
268         unsigned long tmp;
269
270         /* read IRQ0A -> IRQ15A mask */
271         tmp = bitrev8(__raw_readb(INTMSK00A));
272         tmp |= bitrev8(__raw_readb(INTMSK10A)) << 8;
273
274         /* setup WUPSMSK from clocks and external IRQ mask */
275         msk = (~msk & 0xc030000f) | (tmp << 4);
276         __raw_writel(msk, WUPSMSK);
277
278         /* propage level/edge trigger for external IRQ 0->15 */
279         sh7372_icr_to_irqcr(__raw_readl(ICR1A), &irqcrx_low, &irqcry_low);
280         sh7372_icr_to_irqcr(__raw_readl(ICR2A), &irqcrx_high, &irqcry_high);
281         __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR);
282         __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR2);
283
284         /* read IRQ16A -> IRQ31A mask */
285         tmp = bitrev8(__raw_readb(INTMSK20A));
286         tmp |= bitrev8(__raw_readb(INTMSK30A)) << 8;
287
288         /* setup WUPSMSK2 from clocks and external IRQ mask */
289         msk2 = (~msk2 & 0x00030000) | tmp;
290         __raw_writel(msk2, WUPSMSK2);
291
292         /* propage level/edge trigger for external IRQ 16->31 */
293         sh7372_icr_to_irqcr(__raw_readl(ICR3A), &irqcrx_low, &irqcry_low);
294         sh7372_icr_to_irqcr(__raw_readl(ICR4A), &irqcrx_high, &irqcry_high);
295         __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3);
296         __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4);
297 }
298
299 static void sh7372_enter_a3sm_common(int pllc0_on)
300 {
301         /* use INTCA together with SYSC for wakeup */
302         sh7372_setup_sysc(1 << 0, 0);
303         sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
304         sh7372_enter_sysc(pllc0_on, 1 << 12);
305 }
306 #endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */
307
308 #ifdef CONFIG_CPU_IDLE
309 static int sh7372_do_idle_core_standby(unsigned long unused)
310 {
311         cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */
312         return 0;
313 }
314
315 static void sh7372_enter_core_standby(void)
316 {
317         sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
318
319         /* enter sleep mode with SYSTBCR to 0x10 */
320         __raw_writel(0x10, SYSTBCR);
321         cpu_suspend(0, sh7372_do_idle_core_standby);
322         __raw_writel(0, SYSTBCR);
323
324          /* disable reset vector translation */
325         __raw_writel(0, SBAR);
326 }
327
328 static void sh7372_enter_a3sm_pll_on(void)
329 {
330         sh7372_enter_a3sm_common(1);
331 }
332
333 static void sh7372_enter_a3sm_pll_off(void)
334 {
335         sh7372_enter_a3sm_common(0);
336 }
337
338 static void sh7372_cpuidle_setup(struct cpuidle_driver *drv)
339 {
340         struct cpuidle_state *state = &drv->states[drv->state_count];
341
342         snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
343         strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN);
344         state->exit_latency = 10;
345         state->target_residency = 20 + 10;
346         state->flags = CPUIDLE_FLAG_TIME_VALID;
347         shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby;
348         drv->state_count++;
349
350         state = &drv->states[drv->state_count];
351         snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
352         strncpy(state->desc, "A3SM PLL ON", CPUIDLE_DESC_LEN);
353         state->exit_latency = 20;
354         state->target_residency = 30 + 20;
355         state->flags = CPUIDLE_FLAG_TIME_VALID;
356         shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_on;
357         drv->state_count++;
358
359         state = &drv->states[drv->state_count];
360         snprintf(state->name, CPUIDLE_NAME_LEN, "C4");
361         strncpy(state->desc, "A3SM PLL OFF", CPUIDLE_DESC_LEN);
362         state->exit_latency = 120;
363         state->target_residency = 30 + 120;
364         state->flags = CPUIDLE_FLAG_TIME_VALID;
365         shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_off;
366         drv->state_count++;
367 }
368
369 static void sh7372_cpuidle_init(void)
370 {
371         shmobile_cpuidle_setup = sh7372_cpuidle_setup;
372 }
373 #else
374 static void sh7372_cpuidle_init(void) {}
375 #endif
376
377 #ifdef CONFIG_SUSPEND
378 static void sh7372_enter_a4s_common(int pllc0_on)
379 {
380         sh7372_intca_suspend();
381         memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
382         sh7372_set_reset_vector(SMFRAM);
383         sh7372_enter_sysc(pllc0_on, 1 << 10);
384         sh7372_intca_resume();
385 }
386
387 static int sh7372_enter_suspend(suspend_state_t suspend_state)
388 {
389         unsigned long msk, msk2;
390
391         /* check active clocks to determine potential wakeup sources */
392         if (sh7372_sysc_valid(&msk, &msk2)) {
393                 if (!console_suspend_enabled &&
394                     sh7372_pd_a4s.genpd.status == GPD_STATE_POWER_OFF) {
395                         /* convert INTC mask/sense to SYSC mask/sense */
396                         sh7372_setup_sysc(msk, msk2);
397
398                         /* enter A4S sleep with PLLC0 off */
399                         pr_debug("entering A4S\n");
400                         sh7372_enter_a4s_common(0);
401                         return 0;
402                 }
403         }
404
405         /* default to enter A3SM sleep with PLLC0 off */
406         pr_debug("entering A3SM\n");
407         sh7372_enter_a3sm_common(0);
408         return 0;
409 }
410
411 /**
412  * sh7372_pm_notifier_fn - SH7372 PM notifier routine.
413  * @notifier: Unused.
414  * @pm_event: Event being handled.
415  * @unused: Unused.
416  */
417 static int sh7372_pm_notifier_fn(struct notifier_block *notifier,
418                                  unsigned long pm_event, void *unused)
419 {
420         switch (pm_event) {
421         case PM_SUSPEND_PREPARE:
422                 /*
423                  * This is necessary, because the A4R domain has to be "on"
424                  * when suspend_device_irqs() and resume_device_irqs() are
425                  * executed during system suspend and resume, respectively, so
426                  * that those functions don't crash while accessing the INTCS.
427                  */
428                 pm_genpd_poweron(&sh7372_pd_a4r.genpd);
429                 break;
430         case PM_POST_SUSPEND:
431                 pm_genpd_poweroff_unused();
432                 break;
433         }
434
435         return NOTIFY_DONE;
436 }
437
438 static void sh7372_suspend_init(void)
439 {
440         shmobile_suspend_ops.enter = sh7372_enter_suspend;
441         pm_notifier(sh7372_pm_notifier_fn, 0);
442 }
443 #else
444 static void sh7372_suspend_init(void) {}
445 #endif
446
447 void __init sh7372_pm_init(void)
448 {
449         /* enable DBG hardware block to kick SYSC */
450         __raw_writel(0x0000a500, DBGREG9);
451         __raw_writel(0x0000a501, DBGREG9);
452         __raw_writel(0x00000000, DBGREG1);
453
454         /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
455         __raw_writel(0, PDNSEL);
456
457         sh7372_suspend_init();
458         sh7372_cpuidle_init();
459 }