pm.c 3.1 KB
Newer Older
A
Andriy Skulysh 已提交
1 2 3 4 5 6 7 8 9 10 11 12
/*
 * hp6x0 Power Management Routines
 *
 * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License.
 */
#include <linux/init.h>
#include <linux/suspend.h>
#include <linux/errno.h>
#include <linux/time.h>
M
Magnus Damm 已提交
13 14
#include <linux/delay.h>
#include <linux/gfp.h>
A
Andriy Skulysh 已提交
15 16
#include <asm/io.h>
#include <asm/hd64461.h>
17
#include <mach/hp6xx.h>
P
Paul Mundt 已提交
18
#include <cpu/dac.h>
M
Magnus Damm 已提交
19 20 21 22
#include <asm/freq.h>
#include <asm/watchdog.h>

#define INTR_OFFSET	0x600
A
Andriy Skulysh 已提交
23 24 25 26

#define STBCR		0xffffff82
#define STBCR2		0xffffff88

M
Magnus Damm 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
#define STBCR_STBY	0x80
#define STBCR_MSTP2	0x04

#define MCR		0xffffff68
#define RTCNT		0xffffff70

#define MCR_RMODE	2
#define MCR_RFSH	4

extern u8 wakeup_start;
extern u8 wakeup_end;

static void pm_enter(void)
{
	u8 stbcr, csr;
	u16 frqcr, mcr;
	u32 vbr_new, vbr_old;

	set_bl_bit();

	/* set wdt */
	csr = sh_wdt_read_csr();
	csr &= ~WTCSR_TME;
	csr |= WTCSR_CKS_4096;
	sh_wdt_write_csr(csr);
	csr = sh_wdt_read_csr();
	sh_wdt_write_cnt(0);

	/* disable PLL1 */
56
	frqcr = __raw_readw(FRQCR);
M
Magnus Damm 已提交
57
	frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY);
58
	__raw_writew(frqcr, FRQCR);
M
Magnus Damm 已提交
59 60

	/* enable standby */
61 62
	stbcr = __raw_readb(STBCR);
	__raw_writeb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR);
M
Magnus Damm 已提交
63 64

	/* set self-refresh */
65 66
	mcr = __raw_readw(MCR);
	__raw_writew(mcr & ~MCR_RFSH, MCR);
M
Magnus Damm 已提交
67 68 69 70 71 72 73 74 75

	/* set interrupt handler */
	asm volatile("stc vbr, %0" : "=r" (vbr_old));
	vbr_new = get_zeroed_page(GFP_ATOMIC);
	udelay(50);
	memcpy((void*)(vbr_new + INTR_OFFSET),
	       &wakeup_start, &wakeup_end - &wakeup_start);
	asm volatile("ldc %0, vbr" : : "r" (vbr_new));

76 77
	__raw_writew(0, RTCNT);
	__raw_writew(mcr | MCR_RFSH | MCR_RMODE, MCR);
M
Magnus Damm 已提交
78 79 80 81 82 83 84 85

	cpu_sleep();

	asm volatile("ldc %0, vbr" : : "r" (vbr_old));

	free_page(vbr_new);

	/* enable PLL1 */
86
	frqcr = __raw_readw(FRQCR);
M
Magnus Damm 已提交
87
	frqcr |= FRQCR_PSTBY;
88
	__raw_writew(frqcr, FRQCR);
M
Magnus Damm 已提交
89 90
	udelay(50);
	frqcr |= FRQCR_PLLEN;
91
	__raw_writew(frqcr, FRQCR);
M
Magnus Damm 已提交
92

93
	__raw_writeb(stbcr, STBCR);
M
Magnus Damm 已提交
94 95 96 97

	clear_bl_bit();
}

A
Andriy Skulysh 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
static int hp6x0_pm_enter(suspend_state_t state)
{
	u8 stbcr, stbcr2;
#ifdef CONFIG_HD64461_ENABLER
	u8 scr;
	u16 hd64461_stbcr;
#endif

#ifdef CONFIG_HD64461_ENABLER
	outb(0, HD64461_PCC1CSCIER);

	scr = inb(HD64461_PCC1SCR);
	scr |= HD64461_PCCSCR_VCC1;
	outb(scr, HD64461_PCC1SCR);

	hd64461_stbcr = inw(HD64461_STBCR);
	hd64461_stbcr |= HD64461_STBCR_SPC1ST;
	outw(hd64461_stbcr, HD64461_STBCR);
#endif

118
	__raw_writeb(0x1f, DACR);
A
Andriy Skulysh 已提交
119

120 121
	stbcr = __raw_readb(STBCR);
	__raw_writeb(0x01, STBCR);
A
Andriy Skulysh 已提交
122

123 124
	stbcr2 = __raw_readb(STBCR2);
	__raw_writeb(0x7f , STBCR2);
A
Andriy Skulysh 已提交
125 126 127 128 129 130

	outw(0xf07f, HD64461_SCPUCR);

	pm_enter();

	outw(0, HD64461_SCPUCR);
131 132
	__raw_writeb(stbcr, STBCR);
	__raw_writeb(stbcr2, STBCR2);
A
Andriy Skulysh 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145

#ifdef CONFIG_HD64461_ENABLER
	hd64461_stbcr = inw(HD64461_STBCR);
	hd64461_stbcr &= ~HD64461_STBCR_SPC1ST;
	outw(hd64461_stbcr, HD64461_STBCR);

	outb(0x4c, HD64461_PCC1CSCIER);
	outb(0x00, HD64461_PCC1CSCR);
#endif

	return 0;
}

146
static const struct platform_suspend_ops hp6x0_pm_ops = {
A
Andriy Skulysh 已提交
147
	.enter		= hp6x0_pm_enter,
148
	.valid		= suspend_valid_only_mem,
A
Andriy Skulysh 已提交
149 150 151 152
};

static int __init hp6x0_pm_init(void)
{
153
	suspend_set_ops(&hp6x0_pm_ops);
A
Andriy Skulysh 已提交
154 155 156 157
	return 0;
}

late_initcall(hp6x0_pm_init);