1/* 2 * Generic Power Management Routine 3 * 4 * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License. 8 */ 9#include <linux/suspend.h> 10#include <linux/delay.h> 11#include <linux/gfp.h> 12#include <asm/freq.h> 13#include <asm/io.h> 14#include <asm/watchdog.h> 15#include <asm/pm.h> 16 17#define INTR_OFFSET 0x600 18 19#define STBCR 0xffffff82 20#define STBCR2 0xffffff88 21 22#define STBCR_STBY 0x80 23#define STBCR_MSTP2 0x04 24 25#define MCR 0xffffff68 26#define RTCNT 0xffffff70 27 28#define MCR_RMODE 2 29#define MCR_RFSH 4 30 31void pm_enter(void) 32{ 33 u8 stbcr, csr; 34 u16 frqcr, mcr; 35 u32 vbr_new, vbr_old; 36 37 set_bl_bit(); 38 39 /* set wdt */ 40 csr = sh_wdt_read_csr(); 41 csr &= ~WTCSR_TME; 42 csr |= WTCSR_CKS_4096; 43 sh_wdt_write_csr(csr); 44 csr = sh_wdt_read_csr(); 45 sh_wdt_write_cnt(0); 46 47 /* disable PLL1 */ 48 frqcr = ctrl_inw(FRQCR); 49 frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY); 50 ctrl_outw(frqcr, FRQCR); 51 52 /* enable standby */ 53 stbcr = ctrl_inb(STBCR); 54 ctrl_outb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR); 55 56 /* set self-refresh */ 57 mcr = ctrl_inw(MCR); 58 ctrl_outw(mcr & ~MCR_RFSH, MCR); 59 60 /* set interrupt handler */ 61 asm volatile("stc vbr, %0" : "=r" (vbr_old)); 62 vbr_new = get_zeroed_page(GFP_ATOMIC); 63 udelay(50); 64 memcpy((void*)(vbr_new + INTR_OFFSET), 65 &wakeup_start, &wakeup_end - &wakeup_start); 66 asm volatile("ldc %0, vbr" : : "r" (vbr_new)); 67 68 ctrl_outw(0, RTCNT); 69 ctrl_outw(mcr | MCR_RFSH | MCR_RMODE, MCR); 70 71 cpu_sleep(); 72 73 asm volatile("ldc %0, vbr" : : "r" (vbr_old)); 74 75 free_page(vbr_new); 76 77 /* enable PLL1 */ 78 frqcr = ctrl_inw(FRQCR); 79 frqcr |= FRQCR_PSTBY; 80 ctrl_outw(frqcr, FRQCR); 81 udelay(50); 82 frqcr |= FRQCR_PLLEN; 83 ctrl_outw(frqcr, FRQCR); 84 85 ctrl_outb(stbcr, STBCR); 86 87 clear_bl_bit(); 88} 89