2 * sh7372 Power management support
4 * Copyright (C) 2011 Magnus Damm
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
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/system.h>
26 #include <asm/tlbflush.h>
27 #include <asm/suspend.h>
28 #include <mach/common.h>
29 #include <mach/sh7372.h>
32 #define DBGREG1 0xe6100020
33 #define DBGREG9 0xe6100040
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
45 #define SPDCR 0xe6180008
46 #define SWUCR 0xe6180014
47 #define SBAR 0xe6180020
48 #define WUPRMSK 0xe6180028
49 #define WUPSMSK 0xe618002c
50 #define WUPSMSK2 0xe6180048
51 #define PSTR 0xe6180080
52 #define WUPSFAC 0xe6180098
53 #define IRQCR 0xe618022c
54 #define IRQCR2 0xe6180238
55 #define IRQCR3 0xe6180244
56 #define IRQCR4 0xe6180248
57 #define PDNSEL 0xe6180254
60 #define ICR1A 0xe6900000
61 #define ICR2A 0xe6900004
62 #define ICR3A 0xe6900008
63 #define ICR4A 0xe690000c
64 #define INTMSK00A 0xe6900040
65 #define INTMSK10A 0xe6900044
66 #define INTMSK20A 0xe6900048
67 #define INTMSK30A 0xe690004c
70 #define SMFRAM 0xe6a70000
73 #define APARMBAREA 0xe6f10020
75 #define PSTR_RETRIES 100
76 #define PSTR_DELAY_US 10
80 static int pd_power_down(struct generic_pm_domain
*genpd
)
82 struct sh7372_pm_domain
*sh7372_pd
= to_sh7372_pd(genpd
);
83 unsigned int mask
= 1 << sh7372_pd
->bit_shift
;
85 if (sh7372_pd
->suspend
)
88 if (sh7372_pd
->stay_on
)
91 if (__raw_readl(PSTR
) & mask
) {
92 unsigned int retry_count
;
94 __raw_writel(mask
, SPDCR
);
96 for (retry_count
= PSTR_RETRIES
; retry_count
; retry_count
--) {
97 if (!(__raw_readl(SPDCR
) & mask
))
103 if (!sh7372_pd
->no_debug
)
104 pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n",
105 mask
, __raw_readl(PSTR
));
110 static int __pd_power_up(struct sh7372_pm_domain
*sh7372_pd
, bool do_resume
)
112 unsigned int mask
= 1 << sh7372_pd
->bit_shift
;
113 unsigned int retry_count
;
116 if (sh7372_pd
->stay_on
)
119 if (__raw_readl(PSTR
) & mask
)
122 __raw_writel(mask
, SWUCR
);
124 for (retry_count
= 2 * PSTR_RETRIES
; retry_count
; retry_count
--) {
125 if (!(__raw_readl(SWUCR
) & mask
))
127 if (retry_count
> PSTR_RETRIES
)
128 udelay(PSTR_DELAY_US
);
135 if (!sh7372_pd
->no_debug
)
136 pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n",
137 mask
, __raw_readl(PSTR
));
140 if (ret
== 0 && sh7372_pd
->resume
&& do_resume
)
146 static int pd_power_up(struct generic_pm_domain
*genpd
)
148 return __pd_power_up(to_sh7372_pd(genpd
), true);
151 static void sh7372_a4r_suspend(void)
153 sh7372_intcs_suspend();
154 __raw_writel(0x300fffff, WUPRMSK
); /* avoid wakeup */
157 static bool pd_active_wakeup(struct device
*dev
)
162 static bool sh7372_power_down_forbidden(struct dev_pm_domain
*domain
)
167 struct dev_power_governor sh7372_always_on_gov
= {
168 .power_down_ok
= sh7372_power_down_forbidden
,
171 void sh7372_init_pm_domain(struct sh7372_pm_domain
*sh7372_pd
)
173 struct generic_pm_domain
*genpd
= &sh7372_pd
->genpd
;
175 pm_genpd_init(genpd
, sh7372_pd
->gov
, false);
176 genpd
->stop_device
= pm_clk_suspend
;
177 genpd
->start_device
= pm_clk_resume
;
178 genpd
->dev_irq_safe
= true;
179 genpd
->active_wakeup
= pd_active_wakeup
;
180 genpd
->power_off
= pd_power_down
;
181 genpd
->power_on
= pd_power_up
;
182 __pd_power_up(sh7372_pd
, false);
185 void sh7372_add_device_to_domain(struct sh7372_pm_domain
*sh7372_pd
,
186 struct platform_device
*pdev
)
188 struct device
*dev
= &pdev
->dev
;
190 pm_genpd_add_device(&sh7372_pd
->genpd
, dev
);
191 if (pm_clk_no_clocks(dev
))
192 pm_clk_add(dev
, NULL
);
195 void sh7372_pm_add_subdomain(struct sh7372_pm_domain
*sh7372_pd
,
196 struct sh7372_pm_domain
*sh7372_sd
)
198 pm_genpd_add_subdomain(&sh7372_pd
->genpd
, &sh7372_sd
->genpd
);
201 struct sh7372_pm_domain sh7372_a4lc
= {
205 struct sh7372_pm_domain sh7372_a4mp
= {
209 struct sh7372_pm_domain sh7372_d4
= {
213 struct sh7372_pm_domain sh7372_a4r
= {
215 .gov
= &sh7372_always_on_gov
,
216 .suspend
= sh7372_a4r_suspend
,
217 .resume
= sh7372_intcs_resume
,
221 struct sh7372_pm_domain sh7372_a3rv
= {
225 struct sh7372_pm_domain sh7372_a3ri
= {
229 struct sh7372_pm_domain sh7372_a3sp
= {
231 .gov
= &sh7372_always_on_gov
,
235 static void sh7372_a3sp_init(void)
237 /* serial consoles make use of SCIF hardware located in A3SP,
238 * keep such power domain on if "no_console_suspend" is set.
240 sh7372_a3sp
.stay_on
= !console_suspend_enabled
;
243 struct sh7372_pm_domain sh7372_a3sg
= {
247 #else /* !CONFIG_PM */
249 static inline void sh7372_a3sp_init(void) {}
251 #endif /* !CONFIG_PM */
253 #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
254 static int sh7372_do_idle_core_standby(unsigned long unused
)
256 cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */
260 static void sh7372_enter_core_standby(void)
262 /* set reset vector, translate 4k */
263 __raw_writel(__pa(sh7372_resume_core_standby_a3sm
), SBAR
);
264 __raw_writel(0, APARMBAREA
);
266 /* enter sleep mode with SYSTBCR to 0x10 */
267 __raw_writel(0x10, SYSTBCR
);
268 cpu_suspend(0, sh7372_do_idle_core_standby
);
269 __raw_writel(0, SYSTBCR
);
271 /* disable reset vector translation */
272 __raw_writel(0, SBAR
);
276 #ifdef CONFIG_SUSPEND
277 static void sh7372_enter_a3sm_common(int pllc0_on
)
279 /* set reset vector, translate 4k */
280 __raw_writel(__pa(sh7372_resume_core_standby_a3sm
), SBAR
);
281 __raw_writel(0, APARMBAREA
);
284 __raw_writel(0, PLLC01STPCR
);
286 __raw_writel(1 << 28, PLLC01STPCR
);
288 __raw_writel(0, PDNSEL
); /* power-down A3SM only, not A4S */
289 __raw_readl(WUPSFAC
); /* read wakeup int. factor before sleep */
290 cpu_suspend(0, sh7372_do_idle_a3sm
);
291 __raw_readl(WUPSFAC
); /* read wakeup int. factor after wakeup */
293 /* disable reset vector translation */
294 __raw_writel(0, SBAR
);
297 static int sh7372_a3sm_valid(unsigned long *mskp
, unsigned long *msk2p
)
299 unsigned long mstpsr0
, mstpsr1
, mstpsr2
, mstpsr3
, mstpsr4
;
300 unsigned long msk
, msk2
;
302 /* check active clocks to determine potential wakeup sources */
304 mstpsr0
= __raw_readl(MSTPSR0
);
305 if ((mstpsr0
& 0x00000003) != 0x00000003) {
306 pr_debug("sh7372 mstpsr0 0x%08lx\n", mstpsr0
);
310 mstpsr1
= __raw_readl(MSTPSR1
);
311 if ((mstpsr1
& 0xff079b7f) != 0xff079b7f) {
312 pr_debug("sh7372 mstpsr1 0x%08lx\n", mstpsr1
);
316 mstpsr2
= __raw_readl(MSTPSR2
);
317 if ((mstpsr2
& 0x000741ff) != 0x000741ff) {
318 pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2
);
322 mstpsr3
= __raw_readl(MSTPSR3
);
323 if ((mstpsr3
& 0x1a60f010) != 0x1a60f010) {
324 pr_debug("sh7372 mstpsr3 0x%08lx\n", mstpsr3
);
328 mstpsr4
= __raw_readl(MSTPSR4
);
329 if ((mstpsr4
& 0x00008cf0) != 0x00008cf0) {
330 pr_debug("sh7372 mstpsr4 0x%08lx\n", mstpsr4
);
337 /* make bitmaps of limited number of wakeup sources */
339 if ((mstpsr2
& (1 << 23)) == 0) /* SPU2 */
342 if ((mstpsr2
& (1 << 12)) == 0) /* MFI_MFIM */
345 if ((mstpsr4
& (1 << 3)) == 0) /* KEYSC */
348 if ((mstpsr1
& (1 << 24)) == 0) /* CMT0 */
351 if ((mstpsr3
& (1 << 29)) == 0) /* CMT1 */
354 if ((mstpsr4
& (1 << 0)) == 0) /* CMT2 */
357 if ((mstpsr2
& (1 << 13)) == 0) /* MFI_MFIS */
366 static void sh7372_icr_to_irqcr(unsigned long icr
, u16
*irqcr1p
, u16
*irqcr2p
)
368 u16 tmp
, irqcr1
, irqcr2
;
374 /* convert INTCA ICR register layout to SYSC IRQCR+IRQCR2 */
375 for (k
= 0; k
<= 7; k
++) {
376 tmp
= (icr
>> ((7 - k
) * 4)) & 0xf;
377 irqcr1
|= (tmp
& 0x03) << (k
* 2);
378 irqcr2
|= (tmp
>> 2) << (k
* 2);
385 static void sh7372_setup_a3sm(unsigned long msk
, unsigned long msk2
)
387 u16 irqcrx_low
, irqcrx_high
, irqcry_low
, irqcry_high
;
390 /* read IRQ0A -> IRQ15A mask */
391 tmp
= bitrev8(__raw_readb(INTMSK00A
));
392 tmp
|= bitrev8(__raw_readb(INTMSK10A
)) << 8;
394 /* setup WUPSMSK from clocks and external IRQ mask */
395 msk
= (~msk
& 0xc030000f) | (tmp
<< 4);
396 __raw_writel(msk
, WUPSMSK
);
398 /* propage level/edge trigger for external IRQ 0->15 */
399 sh7372_icr_to_irqcr(__raw_readl(ICR1A
), &irqcrx_low
, &irqcry_low
);
400 sh7372_icr_to_irqcr(__raw_readl(ICR2A
), &irqcrx_high
, &irqcry_high
);
401 __raw_writel((irqcrx_high
<< 16) | irqcrx_low
, IRQCR
);
402 __raw_writel((irqcry_high
<< 16) | irqcry_low
, IRQCR2
);
404 /* read IRQ16A -> IRQ31A mask */
405 tmp
= bitrev8(__raw_readb(INTMSK20A
));
406 tmp
|= bitrev8(__raw_readb(INTMSK30A
)) << 8;
408 /* setup WUPSMSK2 from clocks and external IRQ mask */
409 msk2
= (~msk2
& 0x00030000) | tmp
;
410 __raw_writel(msk2
, WUPSMSK2
);
412 /* propage level/edge trigger for external IRQ 16->31 */
413 sh7372_icr_to_irqcr(__raw_readl(ICR3A
), &irqcrx_low
, &irqcry_low
);
414 sh7372_icr_to_irqcr(__raw_readl(ICR4A
), &irqcrx_high
, &irqcry_high
);
415 __raw_writel((irqcrx_high
<< 16) | irqcrx_low
, IRQCR3
);
416 __raw_writel((irqcry_high
<< 16) | irqcry_low
, IRQCR4
);
420 #ifdef CONFIG_CPU_IDLE
422 static void sh7372_cpuidle_setup(struct cpuidle_driver
*drv
)
424 struct cpuidle_state
*state
= &drv
->states
[drv
->state_count
];
426 snprintf(state
->name
, CPUIDLE_NAME_LEN
, "C2");
427 strncpy(state
->desc
, "Core Standby Mode", CPUIDLE_DESC_LEN
);
428 state
->exit_latency
= 10;
429 state
->target_residency
= 20 + 10;
430 state
->flags
= CPUIDLE_FLAG_TIME_VALID
;
431 shmobile_cpuidle_modes
[drv
->state_count
] = sh7372_enter_core_standby
;
436 static void sh7372_cpuidle_init(void)
438 shmobile_cpuidle_setup
= sh7372_cpuidle_setup
;
441 static void sh7372_cpuidle_init(void) {}
444 #ifdef CONFIG_SUSPEND
446 static int sh7372_enter_suspend(suspend_state_t suspend_state
)
448 unsigned long msk
, msk2
;
450 /* check active clocks to determine potential wakeup sources */
451 if (sh7372_a3sm_valid(&msk
, &msk2
)) {
453 /* convert INTC mask and sense to SYSC mask and sense */
454 sh7372_setup_a3sm(msk
, msk2
);
456 /* enter A3SM sleep with PLLC0 off */
457 pr_debug("entering A3SM\n");
458 sh7372_enter_a3sm_common(0);
460 /* default to Core Standby that supports all wakeup sources */
461 pr_debug("entering Core Standby\n");
462 sh7372_enter_core_standby();
467 static void sh7372_suspend_init(void)
469 shmobile_suspend_ops
.enter
= sh7372_enter_suspend
;
472 static void sh7372_suspend_init(void) {}
475 void __init
sh7372_pm_init(void)
477 /* enable DBG hardware block to kick SYSC */
478 __raw_writel(0x0000a500, DBGREG9
);
479 __raw_writel(0x0000a501, DBGREG9
);
480 __raw_writel(0x00000000, DBGREG1
);
482 /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
483 __raw_writel(0, PDNSEL
);
487 sh7372_suspend_init();
488 sh7372_cpuidle_init();