1 /* 2 * AM33XX PRM functions 3 * 4 * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation version 2. 9 * 10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 11 * kind, whether express or implied; without even the implied warranty 12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16 #include <linux/kernel.h> 17 #include <linux/types.h> 18 #include <linux/errno.h> 19 #include <linux/err.h> 20 #include <linux/io.h> 21 22 #include "common.h" 23 #include "powerdomain.h" 24 #include "prm33xx.h" 25 #include "prm-regbits-33xx.h" 26 27 /* Read a register in a PRM instance */ 28 u32 am33xx_prm_read_reg(s16 inst, u16 idx) 29 { 30 return __raw_readl(prm_base + inst + idx); 31 } 32 33 /* Write into a register in a PRM instance */ 34 void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx) 35 { 36 __raw_writel(val, prm_base + inst + idx); 37 } 38 39 /* Read-modify-write a register in PRM. Caller must lock */ 40 u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx) 41 { 42 u32 v; 43 44 v = am33xx_prm_read_reg(inst, idx); 45 v &= ~mask; 46 v |= bits; 47 am33xx_prm_write_reg(v, inst, idx); 48 49 return v; 50 } 51 52 /** 53 * am33xx_prm_is_hardreset_asserted - read the HW reset line state of 54 * submodules contained in the hwmod module 55 * @shift: register bit shift corresponding to the reset line to check 56 * @inst: CM instance register offset (*_INST macro) 57 * @rstctrl_offs: RM_RSTCTRL register address offset for this module 58 * 59 * Returns 1 if the (sub)module hardreset line is currently asserted, 60 * 0 if the (sub)module hardreset line is not currently asserted, or 61 * -EINVAL upon parameter error. 62 */ 63 int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, u16 rstctrl_offs) 64 { 65 u32 v; 66 67 v = am33xx_prm_read_reg(inst, rstctrl_offs); 68 v &= 1 << shift; 69 v >>= shift; 70 71 return v; 72 } 73 74 /** 75 * am33xx_prm_assert_hardreset - assert the HW reset line of a submodule 76 * @shift: register bit shift corresponding to the reset line to assert 77 * @inst: CM instance register offset (*_INST macro) 78 * @rstctrl_reg: RM_RSTCTRL register address for this module 79 * 80 * Some IPs like dsp, ipu or iva contain processors that require an HW 81 * reset line to be asserted / deasserted in order to fully enable the 82 * IP. These modules may have multiple hard-reset lines that reset 83 * different 'submodules' inside the IP block. This function will 84 * place the submodule into reset. Returns 0 upon success or -EINVAL 85 * upon an argument error. 86 */ 87 int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs) 88 { 89 u32 mask = 1 << shift; 90 91 am33xx_prm_rmw_reg_bits(mask, mask, inst, rstctrl_offs); 92 93 return 0; 94 } 95 96 /** 97 * am33xx_prm_deassert_hardreset - deassert a submodule hardreset line and 98 * wait 99 * @shift: register bit shift corresponding to the reset line to deassert 100 * @inst: CM instance register offset (*_INST macro) 101 * @rstctrl_reg: RM_RSTCTRL register address for this module 102 * @rstst_reg: RM_RSTST register address for this module 103 * 104 * Some IPs like dsp, ipu or iva contain processors that require an HW 105 * reset line to be asserted / deasserted in order to fully enable the 106 * IP. These modules may have multiple hard-reset lines that reset 107 * different 'submodules' inside the IP block. This function will 108 * take the submodule out of reset and wait until the PRCM indicates 109 * that the reset has completed before returning. Returns 0 upon success or 110 * -EINVAL upon an argument error, -EEXIST if the submodule was already out 111 * of reset, or -EBUSY if the submodule did not exit reset promptly. 112 */ 113 int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, s16 inst, 114 u16 rstctrl_offs, u16 rstst_offs) 115 { 116 int c; 117 u32 mask = 1 << st_shift; 118 119 /* Check the current status to avoid de-asserting the line twice */ 120 if (am33xx_prm_is_hardreset_asserted(shift, inst, rstctrl_offs) == 0) 121 return -EEXIST; 122 123 /* Clear the reset status by writing 1 to the status bit */ 124 am33xx_prm_rmw_reg_bits(0xffffffff, mask, inst, rstst_offs); 125 126 /* de-assert the reset control line */ 127 mask = 1 << shift; 128 129 am33xx_prm_rmw_reg_bits(mask, 0, inst, rstctrl_offs); 130 131 /* wait the status to be set */ 132 omap_test_timeout(am33xx_prm_is_hardreset_asserted(st_shift, inst, 133 rstst_offs), 134 MAX_MODULE_HARDRESET_WAIT, c); 135 136 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; 137 } 138 139 static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) 140 { 141 am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK, 142 (pwrst << OMAP_POWERSTATE_SHIFT), 143 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); 144 return 0; 145 } 146 147 static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) 148 { 149 u32 v; 150 151 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); 152 v &= OMAP_POWERSTATE_MASK; 153 v >>= OMAP_POWERSTATE_SHIFT; 154 155 return v; 156 } 157 158 static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm) 159 { 160 u32 v; 161 162 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); 163 v &= OMAP_POWERSTATEST_MASK; 164 v >>= OMAP_POWERSTATEST_SHIFT; 165 166 return v; 167 } 168 169 static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) 170 { 171 u32 v; 172 173 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); 174 v &= AM33XX_LASTPOWERSTATEENTERED_MASK; 175 v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT; 176 177 return v; 178 } 179 180 static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) 181 { 182 am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK, 183 (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT), 184 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); 185 return 0; 186 } 187 188 static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) 189 { 190 am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK, 191 AM33XX_LASTPOWERSTATEENTERED_MASK, 192 pwrdm->prcm_offs, pwrdm->pwrstst_offs); 193 return 0; 194 } 195 196 static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) 197 { 198 u32 m; 199 200 m = pwrdm->logicretstate_mask; 201 if (!m) 202 return -EINVAL; 203 204 am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), 205 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); 206 207 return 0; 208 } 209 210 static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) 211 { 212 u32 v; 213 214 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); 215 v &= AM33XX_LOGICSTATEST_MASK; 216 v >>= AM33XX_LOGICSTATEST_SHIFT; 217 218 return v; 219 } 220 221 static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm) 222 { 223 u32 v, m; 224 225 m = pwrdm->logicretstate_mask; 226 if (!m) 227 return -EINVAL; 228 229 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); 230 v &= m; 231 v >>= __ffs(m); 232 233 return v; 234 } 235 236 static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, 237 u8 pwrst) 238 { 239 u32 m; 240 241 m = pwrdm->mem_on_mask[bank]; 242 if (!m) 243 return -EINVAL; 244 245 am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), 246 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); 247 248 return 0; 249 } 250 251 static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, 252 u8 pwrst) 253 { 254 u32 m; 255 256 m = pwrdm->mem_ret_mask[bank]; 257 if (!m) 258 return -EINVAL; 259 260 am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)), 261 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); 262 263 return 0; 264 } 265 266 static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) 267 { 268 u32 m, v; 269 270 m = pwrdm->mem_pwrst_mask[bank]; 271 if (!m) 272 return -EINVAL; 273 274 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs); 275 v &= m; 276 v >>= __ffs(m); 277 278 return v; 279 } 280 281 static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) 282 { 283 u32 m, v; 284 285 m = pwrdm->mem_retst_mask[bank]; 286 if (!m) 287 return -EINVAL; 288 289 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs); 290 v &= m; 291 v >>= __ffs(m); 292 293 return v; 294 } 295 296 static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm) 297 { 298 u32 c = 0; 299 300 /* 301 * REVISIT: pwrdm_wait_transition() may be better implemented 302 * via a callback and a periodic timer check -- how long do we expect 303 * powerdomain transitions to take? 304 */ 305 306 /* XXX Is this udelay() value meaningful? */ 307 while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs) 308 & OMAP_INTRANSITION_MASK) && 309 (c++ < PWRDM_TRANSITION_BAILOUT)) 310 udelay(1); 311 312 if (c > PWRDM_TRANSITION_BAILOUT) { 313 pr_err("powerdomain: %s: waited too long to complete transition\n", 314 pwrdm->name); 315 return -EAGAIN; 316 } 317 318 pr_debug("powerdomain: completed transition in %d loops\n", c); 319 320 return 0; 321 } 322 323 static int am33xx_check_vcvp(void) 324 { 325 /* No VC/VP on am33xx devices */ 326 return 0; 327 } 328 329 struct pwrdm_ops am33xx_pwrdm_operations = { 330 .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst, 331 .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst, 332 .pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst, 333 .pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst, 334 .pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst, 335 .pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst, 336 .pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst, 337 .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst, 338 .pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange, 339 .pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst, 340 .pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst, 341 .pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst, 342 .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst, 343 .pwrdm_wait_transition = am33xx_pwrdm_wait_transition, 344 .pwrdm_has_voltdm = am33xx_check_vcvp, 345 }; 346