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);