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

prm2xxx.c (6164B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * OMAP2xxx PRM module functions
      4 *
      5 * Copyright (C) 2010-2012 Texas Instruments, Inc.
      6 * Copyright (C) 2010 Nokia Corporation
      7 * BenoƮt Cousson
      8 * Paul Walmsley
      9 * Rajendra Nayak <rnayak@ti.com>
     10 */
     11
     12#include <linux/kernel.h>
     13#include <linux/errno.h>
     14#include <linux/err.h>
     15#include <linux/io.h>
     16#include <linux/irq.h>
     17
     18#include "powerdomain.h"
     19#include "clockdomain.h"
     20#include "prm2xxx.h"
     21#include "cm2xxx_3xxx.h"
     22#include "prm-regbits-24xx.h"
     23
     24/*
     25 * OMAP24xx PM_PWSTCTRL_*.POWERSTATE and PM_PWSTST_*.LASTSTATEENTERED bits -
     26 * these are reversed from the bits used on OMAP3+
     27 */
     28#define OMAP24XX_PWRDM_POWER_ON			0x0
     29#define OMAP24XX_PWRDM_POWER_RET		0x1
     30#define OMAP24XX_PWRDM_POWER_OFF		0x3
     31
     32/*
     33 * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
     34 *   hardware register (which are specific to the OMAP2xxx SoCs) to
     35 *   reset source ID bit shifts (which is an OMAP SoC-independent
     36 *   enumeration)
     37 */
     38static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
     39	{ OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
     40	{ OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
     41	{ OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
     42	{ OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
     43	{ OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
     44	{ OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
     45	{ -1, -1 },
     46};
     47
     48/**
     49 * omap2xxx_prm_read_reset_sources - return the last SoC reset source
     50 *
     51 * Return a u32 representing the last reset sources of the SoC.  The
     52 * returned reset source bits are standardized across OMAP SoCs.
     53 */
     54static u32 omap2xxx_prm_read_reset_sources(void)
     55{
     56	struct prm_reset_src_map *p;
     57	u32 r = 0;
     58	u32 v;
     59
     60	v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
     61
     62	p = omap2xxx_prm_reset_src_map;
     63	while (p->reg_shift >= 0 && p->std_shift >= 0) {
     64		if (v & (1 << p->reg_shift))
     65			r |= 1 << p->std_shift;
     66		p++;
     67	}
     68
     69	return r;
     70}
     71
     72/**
     73 * omap2xxx_pwrst_to_common_pwrst - convert OMAP2xxx pwrst to common pwrst
     74 * @omap2xxx_pwrst: OMAP2xxx hardware power state to convert
     75 *
     76 * Return the common power state bits corresponding to the OMAP2xxx
     77 * hardware power state bits @omap2xxx_pwrst, or -EINVAL upon error.
     78 */
     79static int omap2xxx_pwrst_to_common_pwrst(u8 omap2xxx_pwrst)
     80{
     81	u8 pwrst;
     82
     83	switch (omap2xxx_pwrst) {
     84	case OMAP24XX_PWRDM_POWER_OFF:
     85		pwrst = PWRDM_POWER_OFF;
     86		break;
     87	case OMAP24XX_PWRDM_POWER_RET:
     88		pwrst = PWRDM_POWER_RET;
     89		break;
     90	case OMAP24XX_PWRDM_POWER_ON:
     91		pwrst = PWRDM_POWER_ON;
     92		break;
     93	default:
     94		return -EINVAL;
     95	}
     96
     97	return pwrst;
     98}
     99
    100/**
    101 * omap2xxx_prm_dpll_reset - use DPLL reset to reboot the OMAP SoC
    102 *
    103 * Set the DPLL reset bit, which should reboot the SoC.  This is the
    104 * recommended way to restart the SoC.  No return value.
    105 */
    106static void omap2xxx_prm_dpll_reset(void)
    107{
    108	omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, WKUP_MOD,
    109				   OMAP2_RM_RSTCTRL);
    110	/* OCP barrier */
    111	omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTCTRL);
    112}
    113
    114/**
    115 * omap2xxx_prm_clear_mod_irqs - clear wakeup status bits for a module
    116 * @module: PRM module to clear wakeups from
    117 * @regs: register offset to clear
    118 * @wkst_mask: wakeup status mask to clear
    119 *
    120 * Clears wakeup status bits for a given module, so that the device can
    121 * re-enter idle.
    122 */
    123static int omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask)
    124{
    125	u32 wkst;
    126
    127	wkst = omap2_prm_read_mod_reg(module, regs);
    128	wkst &= wkst_mask;
    129	omap2_prm_write_mod_reg(wkst, module, regs);
    130	return 0;
    131}
    132
    133int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
    134{
    135	omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
    136				   clkdm->pwrdm.ptr->prcm_offs,
    137				   OMAP2_PM_PWSTCTRL);
    138	return 0;
    139}
    140
    141int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm)
    142{
    143	omap2_prm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
    144				     clkdm->pwrdm.ptr->prcm_offs,
    145				     OMAP2_PM_PWSTCTRL);
    146	return 0;
    147}
    148
    149static int omap2xxx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
    150{
    151	u8 omap24xx_pwrst;
    152
    153	switch (pwrst) {
    154	case PWRDM_POWER_OFF:
    155		omap24xx_pwrst = OMAP24XX_PWRDM_POWER_OFF;
    156		break;
    157	case PWRDM_POWER_RET:
    158		omap24xx_pwrst = OMAP24XX_PWRDM_POWER_RET;
    159		break;
    160	case PWRDM_POWER_ON:
    161		omap24xx_pwrst = OMAP24XX_PWRDM_POWER_ON;
    162		break;
    163	default:
    164		return -EINVAL;
    165	}
    166
    167	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
    168				   (omap24xx_pwrst << OMAP_POWERSTATE_SHIFT),
    169				   pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
    170	return 0;
    171}
    172
    173static int omap2xxx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
    174{
    175	u8 omap2xxx_pwrst;
    176
    177	omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
    178						       OMAP2_PM_PWSTCTRL,
    179						       OMAP_POWERSTATE_MASK);
    180
    181	return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
    182}
    183
    184static int omap2xxx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
    185{
    186	u8 omap2xxx_pwrst;
    187
    188	omap2xxx_pwrst = omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
    189						       OMAP2_PM_PWSTST,
    190						       OMAP_POWERSTATEST_MASK);
    191
    192	return omap2xxx_pwrst_to_common_pwrst(omap2xxx_pwrst);
    193}
    194
    195struct pwrdm_ops omap2_pwrdm_operations = {
    196	.pwrdm_set_next_pwrst	= omap2xxx_pwrdm_set_next_pwrst,
    197	.pwrdm_read_next_pwrst	= omap2xxx_pwrdm_read_next_pwrst,
    198	.pwrdm_read_pwrst	= omap2xxx_pwrdm_read_pwrst,
    199	.pwrdm_set_logic_retst	= omap2_pwrdm_set_logic_retst,
    200	.pwrdm_set_mem_onst	= omap2_pwrdm_set_mem_onst,
    201	.pwrdm_set_mem_retst	= omap2_pwrdm_set_mem_retst,
    202	.pwrdm_read_mem_pwrst	= omap2_pwrdm_read_mem_pwrst,
    203	.pwrdm_read_mem_retst	= omap2_pwrdm_read_mem_retst,
    204	.pwrdm_wait_transition	= omap2_pwrdm_wait_transition,
    205};
    206
    207/*
    208 *
    209 */
    210
    211static struct prm_ll_data omap2xxx_prm_ll_data = {
    212	.read_reset_sources = &omap2xxx_prm_read_reset_sources,
    213	.assert_hardreset = &omap2_prm_assert_hardreset,
    214	.deassert_hardreset = &omap2_prm_deassert_hardreset,
    215	.is_hardreset_asserted = &omap2_prm_is_hardreset_asserted,
    216	.reset_system = &omap2xxx_prm_dpll_reset,
    217	.clear_mod_irqs = &omap2xxx_prm_clear_mod_irqs,
    218};
    219
    220int __init omap2xxx_prm_init(const struct omap_prcm_init_data *data)
    221{
    222	return prm_register(&omap2xxx_prm_ll_data);
    223}
    224
    225static void __exit omap2xxx_prm_exit(void)
    226{
    227	prm_unregister(&omap2xxx_prm_ll_data);
    228}
    229__exitcall(omap2xxx_prm_exit);