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

power.c (5268B)


      1/*
      2 * BRIEF MODULE DESCRIPTION
      3 *	Au1xx0 Power Management routines.
      4 *
      5 * Copyright 2001, 2008 MontaVista Software Inc.
      6 * Author: MontaVista Software, Inc. <source@mvista.com>
      7 *
      8 *  Some of the routines are right out of init/main.c, whose
      9 *  copyrights apply here.
     10 *
     11 *  This program is free software; you can redistribute	 it and/or modify it
     12 *  under  the terms of	 the GNU General  Public License as published by the
     13 *  Free Software Foundation;  either version 2 of the	License, or (at your
     14 *  option) any later version.
     15 *
     16 *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
     17 *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
     18 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
     19 *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
     20 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21 *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
     22 *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     23 *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
     24 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 *
     27 *  You should have received a copy of the  GNU General Public License along
     28 *  with this program; if not, write  to the Free Software Foundation, Inc.,
     29 *  675 Mass Ave, Cambridge, MA 02139, USA.
     30 */
     31
     32#include <linux/pm.h>
     33#include <linux/sysctl.h>
     34#include <linux/jiffies.h>
     35
     36#include <linux/uaccess.h>
     37#include <asm/mach-au1x00/au1000.h>
     38
     39/*
     40 * We need to save/restore a bunch of core registers that are
     41 * either volatile or reset to some state across a processor sleep.
     42 * If reading a register doesn't provide a proper result for a
     43 * later restore, we have to provide a function for loading that
     44 * register and save a copy.
     45 *
     46 * We only have to save/restore registers that aren't otherwise
     47 * done as part of a driver pm_* function.
     48 */
     49static unsigned int sleep_sys_clocks[5];
     50static unsigned int sleep_sys_pinfunc;
     51static unsigned int sleep_static_memctlr[4][3];
     52
     53
     54static void save_core_regs(void)
     55{
     56	/* Clocks and PLLs. */
     57	sleep_sys_clocks[0] = alchemy_rdsys(AU1000_SYS_FREQCTRL0);
     58	sleep_sys_clocks[1] = alchemy_rdsys(AU1000_SYS_FREQCTRL1);
     59	sleep_sys_clocks[2] = alchemy_rdsys(AU1000_SYS_CLKSRC);
     60	sleep_sys_clocks[3] = alchemy_rdsys(AU1000_SYS_CPUPLL);
     61	sleep_sys_clocks[4] = alchemy_rdsys(AU1000_SYS_AUXPLL);
     62
     63	/* pin mux config */
     64	sleep_sys_pinfunc = alchemy_rdsys(AU1000_SYS_PINFUNC);
     65
     66	/* Save the static memory controller configuration. */
     67	sleep_static_memctlr[0][0] = alchemy_rdsmem(AU1000_MEM_STCFG0);
     68	sleep_static_memctlr[0][1] = alchemy_rdsmem(AU1000_MEM_STTIME0);
     69	sleep_static_memctlr[0][2] = alchemy_rdsmem(AU1000_MEM_STADDR0);
     70	sleep_static_memctlr[1][0] = alchemy_rdsmem(AU1000_MEM_STCFG1);
     71	sleep_static_memctlr[1][1] = alchemy_rdsmem(AU1000_MEM_STTIME1);
     72	sleep_static_memctlr[1][2] = alchemy_rdsmem(AU1000_MEM_STADDR1);
     73	sleep_static_memctlr[2][0] = alchemy_rdsmem(AU1000_MEM_STCFG2);
     74	sleep_static_memctlr[2][1] = alchemy_rdsmem(AU1000_MEM_STTIME2);
     75	sleep_static_memctlr[2][2] = alchemy_rdsmem(AU1000_MEM_STADDR2);
     76	sleep_static_memctlr[3][0] = alchemy_rdsmem(AU1000_MEM_STCFG3);
     77	sleep_static_memctlr[3][1] = alchemy_rdsmem(AU1000_MEM_STTIME3);
     78	sleep_static_memctlr[3][2] = alchemy_rdsmem(AU1000_MEM_STADDR3);
     79}
     80
     81static void restore_core_regs(void)
     82{
     83	/* restore clock configuration.  Writing CPUPLL last will
     84	 * stall a bit and stabilize other clocks (unless this is
     85	 * one of those Au1000 with a write-only PLL, where we dont
     86	 * have a valid value)
     87	 */
     88	alchemy_wrsys(sleep_sys_clocks[0], AU1000_SYS_FREQCTRL0);
     89	alchemy_wrsys(sleep_sys_clocks[1], AU1000_SYS_FREQCTRL1);
     90	alchemy_wrsys(sleep_sys_clocks[2], AU1000_SYS_CLKSRC);
     91	alchemy_wrsys(sleep_sys_clocks[4], AU1000_SYS_AUXPLL);
     92	if (!au1xxx_cpu_has_pll_wo())
     93		alchemy_wrsys(sleep_sys_clocks[3], AU1000_SYS_CPUPLL);
     94
     95	alchemy_wrsys(sleep_sys_pinfunc, AU1000_SYS_PINFUNC);
     96
     97	/* Restore the static memory controller configuration. */
     98	alchemy_wrsmem(sleep_static_memctlr[0][0], AU1000_MEM_STCFG0);
     99	alchemy_wrsmem(sleep_static_memctlr[0][1], AU1000_MEM_STTIME0);
    100	alchemy_wrsmem(sleep_static_memctlr[0][2], AU1000_MEM_STADDR0);
    101	alchemy_wrsmem(sleep_static_memctlr[1][0], AU1000_MEM_STCFG1);
    102	alchemy_wrsmem(sleep_static_memctlr[1][1], AU1000_MEM_STTIME1);
    103	alchemy_wrsmem(sleep_static_memctlr[1][2], AU1000_MEM_STADDR1);
    104	alchemy_wrsmem(sleep_static_memctlr[2][0], AU1000_MEM_STCFG2);
    105	alchemy_wrsmem(sleep_static_memctlr[2][1], AU1000_MEM_STTIME2);
    106	alchemy_wrsmem(sleep_static_memctlr[2][2], AU1000_MEM_STADDR2);
    107	alchemy_wrsmem(sleep_static_memctlr[3][0], AU1000_MEM_STCFG3);
    108	alchemy_wrsmem(sleep_static_memctlr[3][1], AU1000_MEM_STTIME3);
    109	alchemy_wrsmem(sleep_static_memctlr[3][2], AU1000_MEM_STADDR3);
    110}
    111
    112void au_sleep(void)
    113{
    114	save_core_regs();
    115
    116	switch (alchemy_get_cputype()) {
    117	case ALCHEMY_CPU_AU1000:
    118	case ALCHEMY_CPU_AU1500:
    119	case ALCHEMY_CPU_AU1100:
    120		alchemy_sleep_au1000();
    121		break;
    122	case ALCHEMY_CPU_AU1550:
    123	case ALCHEMY_CPU_AU1200:
    124		alchemy_sleep_au1550();
    125		break;
    126	case ALCHEMY_CPU_AU1300:
    127		alchemy_sleep_au1300();
    128		break;
    129	}
    130
    131	restore_core_regs();
    132}