cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pm.c (3102B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * hp6x0 Power Management Routines
      4 *
      5 * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
      6 */
      7#include <linux/init.h>
      8#include <linux/suspend.h>
      9#include <linux/errno.h>
     10#include <linux/time.h>
     11#include <linux/delay.h>
     12#include <linux/gfp.h>
     13#include <asm/io.h>
     14#include <asm/hd64461.h>
     15#include <asm/bl_bit.h>
     16#include <mach/hp6xx.h>
     17#include <cpu/dac.h>
     18#include <asm/freq.h>
     19#include <asm/watchdog.h>
     20
     21#define INTR_OFFSET	0x600
     22
     23#define STBCR		0xffffff82
     24#define STBCR2		0xffffff88
     25
     26#define STBCR_STBY	0x80
     27#define STBCR_MSTP2	0x04
     28
     29#define MCR		0xffffff68
     30#define RTCNT		0xffffff70
     31
     32#define MCR_RMODE	2
     33#define MCR_RFSH	4
     34
     35extern u8 wakeup_start;
     36extern u8 wakeup_end;
     37
     38static void pm_enter(void)
     39{
     40	u8 stbcr, csr;
     41	u16 frqcr, mcr;
     42	u32 vbr_new, vbr_old;
     43
     44	set_bl_bit();
     45
     46	/* set wdt */
     47	csr = sh_wdt_read_csr();
     48	csr &= ~WTCSR_TME;
     49	csr |= WTCSR_CKS_4096;
     50	sh_wdt_write_csr(csr);
     51	csr = sh_wdt_read_csr();
     52	sh_wdt_write_cnt(0);
     53
     54	/* disable PLL1 */
     55	frqcr = __raw_readw(FRQCR);
     56	frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY);
     57	__raw_writew(frqcr, FRQCR);
     58
     59	/* enable standby */
     60	stbcr = __raw_readb(STBCR);
     61	__raw_writeb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR);
     62
     63	/* set self-refresh */
     64	mcr = __raw_readw(MCR);
     65	__raw_writew(mcr & ~MCR_RFSH, MCR);
     66
     67	/* set interrupt handler */
     68	asm volatile("stc vbr, %0" : "=r" (vbr_old));
     69	vbr_new = get_zeroed_page(GFP_ATOMIC);
     70	udelay(50);
     71	memcpy((void*)(vbr_new + INTR_OFFSET),
     72	       &wakeup_start, &wakeup_end - &wakeup_start);
     73	asm volatile("ldc %0, vbr" : : "r" (vbr_new));
     74
     75	__raw_writew(0, RTCNT);
     76	__raw_writew(mcr | MCR_RFSH | MCR_RMODE, MCR);
     77
     78	cpu_sleep();
     79
     80	asm volatile("ldc %0, vbr" : : "r" (vbr_old));
     81
     82	free_page(vbr_new);
     83
     84	/* enable PLL1 */
     85	frqcr = __raw_readw(FRQCR);
     86	frqcr |= FRQCR_PSTBY;
     87	__raw_writew(frqcr, FRQCR);
     88	udelay(50);
     89	frqcr |= FRQCR_PLLEN;
     90	__raw_writew(frqcr, FRQCR);
     91
     92	__raw_writeb(stbcr, STBCR);
     93
     94	clear_bl_bit();
     95}
     96
     97static int hp6x0_pm_enter(suspend_state_t state)
     98{
     99	u8 stbcr, stbcr2;
    100#ifdef CONFIG_HD64461_ENABLER
    101	u8 scr;
    102	u16 hd64461_stbcr;
    103#endif
    104
    105#ifdef CONFIG_HD64461_ENABLER
    106	outb(0, HD64461_PCC1CSCIER);
    107
    108	scr = inb(HD64461_PCC1SCR);
    109	scr |= HD64461_PCCSCR_VCC1;
    110	outb(scr, HD64461_PCC1SCR);
    111
    112	hd64461_stbcr = inw(HD64461_STBCR);
    113	hd64461_stbcr |= HD64461_STBCR_SPC1ST;
    114	outw(hd64461_stbcr, HD64461_STBCR);
    115#endif
    116
    117	__raw_writeb(0x1f, DACR);
    118
    119	stbcr = __raw_readb(STBCR);
    120	__raw_writeb(0x01, STBCR);
    121
    122	stbcr2 = __raw_readb(STBCR2);
    123	__raw_writeb(0x7f , STBCR2);
    124
    125	outw(0xf07f, HD64461_SCPUCR);
    126
    127	pm_enter();
    128
    129	outw(0, HD64461_SCPUCR);
    130	__raw_writeb(stbcr, STBCR);
    131	__raw_writeb(stbcr2, STBCR2);
    132
    133#ifdef CONFIG_HD64461_ENABLER
    134	hd64461_stbcr = inw(HD64461_STBCR);
    135	hd64461_stbcr &= ~HD64461_STBCR_SPC1ST;
    136	outw(hd64461_stbcr, HD64461_STBCR);
    137
    138	outb(0x4c, HD64461_PCC1CSCIER);
    139	outb(0x00, HD64461_PCC1CSCR);
    140#endif
    141
    142	return 0;
    143}
    144
    145static const struct platform_suspend_ops hp6x0_pm_ops = {
    146	.enter		= hp6x0_pm_enter,
    147	.valid		= suspend_valid_only_mem,
    148};
    149
    150static int __init hp6x0_pm_init(void)
    151{
    152	suspend_set_ops(&hp6x0_pm_ops);
    153	return 0;
    154}
    155
    156late_initcall(hp6x0_pm_init);