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 */ 38 static 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 */ 54 static 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 */ 79 static 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 */ 106 static 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 */ 123 static 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 133 int 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 141 int 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 149 static 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 173 static 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 184 static 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 195 struct 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 211 static 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 220 int __init omap2xxx_prm_init(const struct omap_prcm_init_data *data) 221 { 222 return prm_register(&omap2xxx_prm_ll_data); 223 } 224 225 static void __exit omap2xxx_prm_exit(void) 226 { 227 prm_unregister(&omap2xxx_prm_ll_data); 228 } 229 __exitcall(omap2xxx_prm_exit); 230
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.