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 (4137B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * DaVinci Power Management Routines
      4 *
      5 * Copyright (C) 2009 Texas Instruments, Inc. https://www.ti.com/
      6 */
      7
      8#include <linux/pm.h>
      9#include <linux/suspend.h>
     10#include <linux/module.h>
     11#include <linux/platform_device.h>
     12#include <linux/clk.h>
     13#include <linux/spinlock.h>
     14
     15#include <asm/cacheflush.h>
     16#include <asm/delay.h>
     17#include <asm/io.h>
     18
     19#include "common.h"
     20#include "da8xx.h"
     21#include "mux.h"
     22#include "pm.h"
     23#include "clock.h"
     24#include "psc.h"
     25#include "sram.h"
     26
     27#define DA850_PLL1_BASE		0x01e1a000
     28#define DEEPSLEEP_SLEEPCOUNT_MASK	0xFFFF
     29#define DEEPSLEEP_SLEEPCOUNT		128
     30
     31static void (*davinci_sram_suspend) (struct davinci_pm_config *);
     32static struct davinci_pm_config pm_config = {
     33	.sleepcount = DEEPSLEEP_SLEEPCOUNT,
     34	.ddrpsc_num = DA8XX_LPSC1_EMIF3C,
     35};
     36
     37static void davinci_sram_push(void *dest, void *src, unsigned int size)
     38{
     39	memcpy(dest, src, size);
     40	flush_icache_range((unsigned long)dest, (unsigned long)(dest + size));
     41}
     42
     43static void davinci_pm_suspend(void)
     44{
     45	unsigned val;
     46
     47	if (pm_config.cpupll_reg_base != pm_config.ddrpll_reg_base) {
     48
     49		/* Switch CPU PLL to bypass mode */
     50		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
     51		val &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
     52		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
     53
     54		udelay(PLL_BYPASS_TIME);
     55
     56		/* Powerdown CPU PLL */
     57		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
     58		val |= PLLCTL_PLLPWRDN;
     59		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
     60	}
     61
     62	/* Configure sleep count in deep sleep register */
     63	val = __raw_readl(pm_config.deepsleep_reg);
     64	val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
     65	val |= pm_config.sleepcount;
     66	__raw_writel(val, pm_config.deepsleep_reg);
     67
     68	/* System goes to sleep in this call */
     69	davinci_sram_suspend(&pm_config);
     70
     71	if (pm_config.cpupll_reg_base != pm_config.ddrpll_reg_base) {
     72
     73		/* put CPU PLL in reset */
     74		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
     75		val &= ~PLLCTL_PLLRST;
     76		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
     77
     78		/* put CPU PLL in power down */
     79		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
     80		val &= ~PLLCTL_PLLPWRDN;
     81		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
     82
     83		/* wait for CPU PLL reset */
     84		udelay(PLL_RESET_TIME);
     85
     86		/* bring CPU PLL out of reset */
     87		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
     88		val |= PLLCTL_PLLRST;
     89		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
     90
     91		/* Wait for CPU PLL to lock */
     92		udelay(PLL_LOCK_TIME);
     93
     94		/* Remove CPU PLL from bypass mode */
     95		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
     96		val &= ~PLLCTL_PLLENSRC;
     97		val |= PLLCTL_PLLEN;
     98		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
     99	}
    100}
    101
    102static int davinci_pm_enter(suspend_state_t state)
    103{
    104	int ret = 0;
    105
    106	switch (state) {
    107	case PM_SUSPEND_MEM:
    108		davinci_pm_suspend();
    109		break;
    110	default:
    111		ret = -EINVAL;
    112	}
    113
    114	return ret;
    115}
    116
    117static const struct platform_suspend_ops davinci_pm_ops = {
    118	.enter		= davinci_pm_enter,
    119	.valid		= suspend_valid_only_mem,
    120};
    121
    122int __init davinci_pm_init(void)
    123{
    124	int ret;
    125
    126	ret = davinci_cfg_reg(DA850_RTC_ALARM);
    127	if (ret)
    128		return ret;
    129
    130	pm_config.ddr2_ctlr_base = da8xx_get_mem_ctlr();
    131	pm_config.deepsleep_reg = DA8XX_SYSCFG1_VIRT(DA8XX_DEEPSLEEP_REG);
    132
    133	pm_config.cpupll_reg_base = ioremap(DA8XX_PLL0_BASE, SZ_4K);
    134	if (!pm_config.cpupll_reg_base)
    135		return -ENOMEM;
    136
    137	pm_config.ddrpll_reg_base = ioremap(DA850_PLL1_BASE, SZ_4K);
    138	if (!pm_config.ddrpll_reg_base) {
    139		ret = -ENOMEM;
    140		goto no_ddrpll_mem;
    141	}
    142
    143	pm_config.ddrpsc_reg_base = ioremap(DA8XX_PSC1_BASE, SZ_4K);
    144	if (!pm_config.ddrpsc_reg_base) {
    145		ret = -ENOMEM;
    146		goto no_ddrpsc_mem;
    147	}
    148
    149	davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL);
    150	if (!davinci_sram_suspend) {
    151		pr_err("PM: cannot allocate SRAM memory\n");
    152		ret = -ENOMEM;
    153		goto no_sram_mem;
    154	}
    155
    156	davinci_sram_push(davinci_sram_suspend, davinci_cpu_suspend,
    157						davinci_cpu_suspend_sz);
    158
    159	suspend_set_ops(&davinci_pm_ops);
    160
    161	return 0;
    162
    163no_sram_mem:
    164	iounmap(pm_config.ddrpsc_reg_base);
    165no_ddrpsc_mem:
    166	iounmap(pm_config.ddrpll_reg_base);
    167no_ddrpll_mem:
    168	iounmap(pm_config.cpupll_reg_base);
    169	return ret;
    170}