xref: /linux/arch/sh/boards/mach-hp6xx/pm.c (revision 597473720f4dc69749542bfcfed4a927a43d935e)
1*aaf9128aSKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
2da2014a2SPaul Mundt /*
3da2014a2SPaul Mundt  * hp6x0 Power Management Routines
4da2014a2SPaul Mundt  *
5da2014a2SPaul Mundt  * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
6da2014a2SPaul Mundt  */
7da2014a2SPaul Mundt #include <linux/init.h>
8da2014a2SPaul Mundt #include <linux/suspend.h>
9da2014a2SPaul Mundt #include <linux/errno.h>
10da2014a2SPaul Mundt #include <linux/time.h>
113e517627SMagnus Damm #include <linux/delay.h>
123e517627SMagnus Damm #include <linux/gfp.h>
13da2014a2SPaul Mundt #include <asm/io.h>
14da2014a2SPaul Mundt #include <asm/hd64461.h>
15f03c4866SPaul Mundt #include <asm/bl_bit.h>
167639a454SPaul Mundt #include <mach/hp6xx.h>
17da2014a2SPaul Mundt #include <cpu/dac.h>
183e517627SMagnus Damm #include <asm/freq.h>
193e517627SMagnus Damm #include <asm/watchdog.h>
203e517627SMagnus Damm 
213e517627SMagnus Damm #define INTR_OFFSET	0x600
22da2014a2SPaul Mundt 
23da2014a2SPaul Mundt #define STBCR		0xffffff82
24da2014a2SPaul Mundt #define STBCR2		0xffffff88
25da2014a2SPaul Mundt 
263e517627SMagnus Damm #define STBCR_STBY	0x80
273e517627SMagnus Damm #define STBCR_MSTP2	0x04
283e517627SMagnus Damm 
293e517627SMagnus Damm #define MCR		0xffffff68
303e517627SMagnus Damm #define RTCNT		0xffffff70
313e517627SMagnus Damm 
323e517627SMagnus Damm #define MCR_RMODE	2
333e517627SMagnus Damm #define MCR_RFSH	4
343e517627SMagnus Damm 
353e517627SMagnus Damm extern u8 wakeup_start;
363e517627SMagnus Damm extern u8 wakeup_end;
373e517627SMagnus Damm 
pm_enter(void)383e517627SMagnus Damm static void pm_enter(void)
393e517627SMagnus Damm {
403e517627SMagnus Damm 	u8 stbcr, csr;
413e517627SMagnus Damm 	u16 frqcr, mcr;
423e517627SMagnus Damm 	u32 vbr_new, vbr_old;
433e517627SMagnus Damm 
443e517627SMagnus Damm 	set_bl_bit();
453e517627SMagnus Damm 
463e517627SMagnus Damm 	/* set wdt */
473e517627SMagnus Damm 	csr = sh_wdt_read_csr();
483e517627SMagnus Damm 	csr &= ~WTCSR_TME;
493e517627SMagnus Damm 	csr |= WTCSR_CKS_4096;
503e517627SMagnus Damm 	sh_wdt_write_csr(csr);
513e517627SMagnus Damm 	csr = sh_wdt_read_csr();
523e517627SMagnus Damm 	sh_wdt_write_cnt(0);
533e517627SMagnus Damm 
543e517627SMagnus Damm 	/* disable PLL1 */
559d56dd3bSPaul Mundt 	frqcr = __raw_readw(FRQCR);
563e517627SMagnus Damm 	frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY);
579d56dd3bSPaul Mundt 	__raw_writew(frqcr, FRQCR);
583e517627SMagnus Damm 
593e517627SMagnus Damm 	/* enable standby */
609d56dd3bSPaul Mundt 	stbcr = __raw_readb(STBCR);
619d56dd3bSPaul Mundt 	__raw_writeb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR);
623e517627SMagnus Damm 
633e517627SMagnus Damm 	/* set self-refresh */
649d56dd3bSPaul Mundt 	mcr = __raw_readw(MCR);
659d56dd3bSPaul Mundt 	__raw_writew(mcr & ~MCR_RFSH, MCR);
663e517627SMagnus Damm 
673e517627SMagnus Damm 	/* set interrupt handler */
683e517627SMagnus Damm 	asm volatile("stc vbr, %0" : "=r" (vbr_old));
693e517627SMagnus Damm 	vbr_new = get_zeroed_page(GFP_ATOMIC);
703e517627SMagnus Damm 	udelay(50);
713e517627SMagnus Damm 	memcpy((void*)(vbr_new + INTR_OFFSET),
723e517627SMagnus Damm 	       &wakeup_start, &wakeup_end - &wakeup_start);
733e517627SMagnus Damm 	asm volatile("ldc %0, vbr" : : "r" (vbr_new));
743e517627SMagnus Damm 
759d56dd3bSPaul Mundt 	__raw_writew(0, RTCNT);
769d56dd3bSPaul Mundt 	__raw_writew(mcr | MCR_RFSH | MCR_RMODE, MCR);
773e517627SMagnus Damm 
783e517627SMagnus Damm 	cpu_sleep();
793e517627SMagnus Damm 
803e517627SMagnus Damm 	asm volatile("ldc %0, vbr" : : "r" (vbr_old));
813e517627SMagnus Damm 
823e517627SMagnus Damm 	free_page(vbr_new);
833e517627SMagnus Damm 
843e517627SMagnus Damm 	/* enable PLL1 */
859d56dd3bSPaul Mundt 	frqcr = __raw_readw(FRQCR);
863e517627SMagnus Damm 	frqcr |= FRQCR_PSTBY;
879d56dd3bSPaul Mundt 	__raw_writew(frqcr, FRQCR);
883e517627SMagnus Damm 	udelay(50);
893e517627SMagnus Damm 	frqcr |= FRQCR_PLLEN;
909d56dd3bSPaul Mundt 	__raw_writew(frqcr, FRQCR);
913e517627SMagnus Damm 
929d56dd3bSPaul Mundt 	__raw_writeb(stbcr, STBCR);
933e517627SMagnus Damm 
943e517627SMagnus Damm 	clear_bl_bit();
953e517627SMagnus Damm }
963e517627SMagnus Damm 
hp6x0_pm_enter(suspend_state_t state)97da2014a2SPaul Mundt static int hp6x0_pm_enter(suspend_state_t state)
98da2014a2SPaul Mundt {
99da2014a2SPaul Mundt 	u8 stbcr, stbcr2;
100da2014a2SPaul Mundt #ifdef CONFIG_HD64461_ENABLER
101da2014a2SPaul Mundt 	u8 scr;
102da2014a2SPaul Mundt 	u16 hd64461_stbcr;
103da2014a2SPaul Mundt #endif
104da2014a2SPaul Mundt 
105da2014a2SPaul Mundt #ifdef CONFIG_HD64461_ENABLER
106da2014a2SPaul Mundt 	outb(0, HD64461_PCC1CSCIER);
107da2014a2SPaul Mundt 
108da2014a2SPaul Mundt 	scr = inb(HD64461_PCC1SCR);
109da2014a2SPaul Mundt 	scr |= HD64461_PCCSCR_VCC1;
110da2014a2SPaul Mundt 	outb(scr, HD64461_PCC1SCR);
111da2014a2SPaul Mundt 
112da2014a2SPaul Mundt 	hd64461_stbcr = inw(HD64461_STBCR);
113da2014a2SPaul Mundt 	hd64461_stbcr |= HD64461_STBCR_SPC1ST;
114da2014a2SPaul Mundt 	outw(hd64461_stbcr, HD64461_STBCR);
115da2014a2SPaul Mundt #endif
116da2014a2SPaul Mundt 
1179d56dd3bSPaul Mundt 	__raw_writeb(0x1f, DACR);
118da2014a2SPaul Mundt 
1199d56dd3bSPaul Mundt 	stbcr = __raw_readb(STBCR);
1209d56dd3bSPaul Mundt 	__raw_writeb(0x01, STBCR);
121da2014a2SPaul Mundt 
1229d56dd3bSPaul Mundt 	stbcr2 = __raw_readb(STBCR2);
1239d56dd3bSPaul Mundt 	__raw_writeb(0x7f , STBCR2);
124da2014a2SPaul Mundt 
125da2014a2SPaul Mundt 	outw(0xf07f, HD64461_SCPUCR);
126da2014a2SPaul Mundt 
127da2014a2SPaul Mundt 	pm_enter();
128da2014a2SPaul Mundt 
129da2014a2SPaul Mundt 	outw(0, HD64461_SCPUCR);
1309d56dd3bSPaul Mundt 	__raw_writeb(stbcr, STBCR);
1319d56dd3bSPaul Mundt 	__raw_writeb(stbcr2, STBCR2);
132da2014a2SPaul Mundt 
133da2014a2SPaul Mundt #ifdef CONFIG_HD64461_ENABLER
134da2014a2SPaul Mundt 	hd64461_stbcr = inw(HD64461_STBCR);
135da2014a2SPaul Mundt 	hd64461_stbcr &= ~HD64461_STBCR_SPC1ST;
136da2014a2SPaul Mundt 	outw(hd64461_stbcr, HD64461_STBCR);
137da2014a2SPaul Mundt 
138da2014a2SPaul Mundt 	outb(0x4c, HD64461_PCC1CSCIER);
139da2014a2SPaul Mundt 	outb(0x00, HD64461_PCC1CSCR);
140da2014a2SPaul Mundt #endif
141da2014a2SPaul Mundt 
142da2014a2SPaul Mundt 	return 0;
143da2014a2SPaul Mundt }
144da2014a2SPaul Mundt 
1452f55ac07SLionel Debroux static const struct platform_suspend_ops hp6x0_pm_ops = {
146da2014a2SPaul Mundt 	.enter		= hp6x0_pm_enter,
147da2014a2SPaul Mundt 	.valid		= suspend_valid_only_mem,
148da2014a2SPaul Mundt };
149da2014a2SPaul Mundt 
hp6x0_pm_init(void)150da2014a2SPaul Mundt static int __init hp6x0_pm_init(void)
151da2014a2SPaul Mundt {
152da2014a2SPaul Mundt 	suspend_set_ops(&hp6x0_pm_ops);
153da2014a2SPaul Mundt 	return 0;
154da2014a2SPaul Mundt }
155da2014a2SPaul Mundt 
156da2014a2SPaul Mundt late_initcall(hp6x0_pm_init);
157