Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * AM33XX PRM functions
0004  *
0005  * Copyright (C) 2011-2012 Texas Instruments Incorporated - https://www.ti.com/
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/types.h>
0010 #include <linux/errno.h>
0011 #include <linux/err.h>
0012 #include <linux/io.h>
0013 
0014 #include "powerdomain.h"
0015 #include "prm33xx.h"
0016 #include "prm-regbits-33xx.h"
0017 
0018 #define AM33XX_PRM_RSTCTRL_OFFSET       0x0000
0019 
0020 #define AM33XX_RST_GLOBAL_WARM_SW_MASK      (1 << 0)
0021 
0022 /* Read a register in a PRM instance */
0023 static u32 am33xx_prm_read_reg(s16 inst, u16 idx)
0024 {
0025     return readl_relaxed(prm_base.va + inst + idx);
0026 }
0027 
0028 /* Write into a register in a PRM instance */
0029 static void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx)
0030 {
0031     writel_relaxed(val, prm_base.va + inst + idx);
0032 }
0033 
0034 /* Read-modify-write a register in PRM. Caller must lock */
0035 static u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
0036 {
0037     u32 v;
0038 
0039     v = am33xx_prm_read_reg(inst, idx);
0040     v &= ~mask;
0041     v |= bits;
0042     am33xx_prm_write_reg(v, inst, idx);
0043 
0044     return v;
0045 }
0046 
0047 /**
0048  * am33xx_prm_is_hardreset_asserted - read the HW reset line state of
0049  * submodules contained in the hwmod module
0050  * @shift: register bit shift corresponding to the reset line to check
0051  * @part: PRM partition, ignored for AM33xx
0052  * @inst: CM instance register offset (*_INST macro)
0053  * @rstctrl_offs: RM_RSTCTRL register address offset for this module
0054  *
0055  * Returns 1 if the (sub)module hardreset line is currently asserted,
0056  * 0 if the (sub)module hardreset line is not currently asserted, or
0057  * -EINVAL upon parameter error.
0058  */
0059 static int am33xx_prm_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
0060                         u16 rstctrl_offs)
0061 {
0062     u32 v;
0063 
0064     v = am33xx_prm_read_reg(inst, rstctrl_offs);
0065     v &= 1 << shift;
0066     v >>= shift;
0067 
0068     return v;
0069 }
0070 
0071 /**
0072  * am33xx_prm_assert_hardreset - assert the HW reset line of a submodule
0073  * @shift: register bit shift corresponding to the reset line to assert
0074  * @part: CM partition, ignored for AM33xx
0075  * @inst: CM instance register offset (*_INST macro)
0076  * @rstctrl_reg: RM_RSTCTRL register address for this module
0077  *
0078  * Some IPs like dsp, ipu or iva contain processors that require an HW
0079  * reset line to be asserted / deasserted in order to fully enable the
0080  * IP.  These modules may have multiple hard-reset lines that reset
0081  * different 'submodules' inside the IP block.  This function will
0082  * place the submodule into reset.  Returns 0 upon success or -EINVAL
0083  * upon an argument error.
0084  */
0085 static int am33xx_prm_assert_hardreset(u8 shift, u8 part, s16 inst,
0086                        u16 rstctrl_offs)
0087 {
0088     u32 mask = 1 << shift;
0089 
0090     am33xx_prm_rmw_reg_bits(mask, mask, inst, rstctrl_offs);
0091 
0092     return 0;
0093 }
0094 
0095 /**
0096  * am33xx_prm_deassert_hardreset - deassert a submodule hardreset line and
0097  * wait
0098  * @shift: register bit shift corresponding to the reset line to deassert
0099  * @st_shift: reset status register bit shift corresponding to the reset line
0100  * @part: PRM partition, not used for AM33xx
0101  * @inst: CM instance register offset (*_INST macro)
0102  * @rstctrl_reg: RM_RSTCTRL register address for this module
0103  * @rstst_reg: RM_RSTST register address for this module
0104  *
0105  * Some IPs like dsp, ipu or iva contain processors that require an HW
0106  * reset line to be asserted / deasserted in order to fully enable the
0107  * IP.  These modules may have multiple hard-reset lines that reset
0108  * different 'submodules' inside the IP block.  This function will
0109  * take the submodule out of reset and wait until the PRCM indicates
0110  * that the reset has completed before returning.  Returns 0 upon success or
0111  * -EINVAL upon an argument error, -EEXIST if the submodule was already out
0112  * of reset, or -EBUSY if the submodule did not exit reset promptly.
0113  */
0114 static int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, u8 part,
0115                      s16 inst, u16 rstctrl_offs,
0116                      u16 rstst_offs)
0117 {
0118     int c;
0119     u32 mask = 1 << st_shift;
0120 
0121     /* Check the current status to avoid  de-asserting the line twice */
0122     if (am33xx_prm_is_hardreset_asserted(shift, 0, inst, rstctrl_offs) == 0)
0123         return -EEXIST;
0124 
0125     /* Clear the reset status by writing 1 to the status bit */
0126     am33xx_prm_rmw_reg_bits(0xffffffff, mask, inst, rstst_offs);
0127 
0128     /* de-assert the reset control line */
0129     mask = 1 << shift;
0130 
0131     am33xx_prm_rmw_reg_bits(mask, 0, inst, rstctrl_offs);
0132 
0133     /* wait the status to be set */
0134     omap_test_timeout(am33xx_prm_is_hardreset_asserted(st_shift, 0, inst,
0135                                rstst_offs),
0136               MAX_MODULE_HARDRESET_WAIT, c);
0137 
0138     return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
0139 }
0140 
0141 static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
0142 {
0143     am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
0144                 (pwrst << OMAP_POWERSTATE_SHIFT),
0145                 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0146     return 0;
0147 }
0148 
0149 static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
0150 {
0151     u32 v;
0152 
0153     v = am33xx_prm_read_reg(pwrdm->prcm_offs,  pwrdm->pwrstctrl_offs);
0154     v &= OMAP_POWERSTATE_MASK;
0155     v >>= OMAP_POWERSTATE_SHIFT;
0156 
0157     return v;
0158 }
0159 
0160 static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
0161 {
0162     u32 v;
0163 
0164     v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
0165     v &= OMAP_POWERSTATEST_MASK;
0166     v >>= OMAP_POWERSTATEST_SHIFT;
0167 
0168     return v;
0169 }
0170 
0171 static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
0172 {
0173     am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
0174                 (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
0175                 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0176     return 0;
0177 }
0178 
0179 static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
0180 {
0181     am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
0182                 AM33XX_LASTPOWERSTATEENTERED_MASK,
0183                 pwrdm->prcm_offs, pwrdm->pwrstst_offs);
0184     return 0;
0185 }
0186 
0187 static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
0188 {
0189     u32 m;
0190 
0191     m = pwrdm->logicretstate_mask;
0192     if (!m)
0193         return -EINVAL;
0194 
0195     am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
0196                 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0197 
0198     return 0;
0199 }
0200 
0201 static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
0202 {
0203     u32 v;
0204 
0205     v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
0206     v &= AM33XX_LOGICSTATEST_MASK;
0207     v >>= AM33XX_LOGICSTATEST_SHIFT;
0208 
0209     return v;
0210 }
0211 
0212 static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
0213 {
0214     u32 v, m;
0215 
0216     m = pwrdm->logicretstate_mask;
0217     if (!m)
0218         return -EINVAL;
0219 
0220     v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0221     v &= m;
0222     v >>= __ffs(m);
0223 
0224     return v;
0225 }
0226 
0227 static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
0228         u8 pwrst)
0229 {
0230     u32 m;
0231 
0232     m = pwrdm->mem_on_mask[bank];
0233     if (!m)
0234         return -EINVAL;
0235 
0236     am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
0237                 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0238 
0239     return 0;
0240 }
0241 
0242 static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
0243                     u8 pwrst)
0244 {
0245     u32 m;
0246 
0247     m = pwrdm->mem_ret_mask[bank];
0248     if (!m)
0249         return -EINVAL;
0250 
0251     am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
0252                 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0253 
0254     return 0;
0255 }
0256 
0257 static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
0258 {
0259     u32 m, v;
0260 
0261     m = pwrdm->mem_pwrst_mask[bank];
0262     if (!m)
0263         return -EINVAL;
0264 
0265     v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
0266     v &= m;
0267     v >>= __ffs(m);
0268 
0269     return v;
0270 }
0271 
0272 static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
0273 {
0274     u32 m, v;
0275 
0276     m = pwrdm->mem_retst_mask[bank];
0277     if (!m)
0278         return -EINVAL;
0279 
0280     v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
0281     v &= m;
0282     v >>= __ffs(m);
0283 
0284     return v;
0285 }
0286 
0287 static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
0288 {
0289     u32 c = 0;
0290 
0291     /*
0292      * REVISIT: pwrdm_wait_transition() may be better implemented
0293      * via a callback and a periodic timer check -- how long do we expect
0294      * powerdomain transitions to take?
0295      */
0296 
0297     /* XXX Is this udelay() value meaningful? */
0298     while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
0299             & OMAP_INTRANSITION_MASK) &&
0300             (c++ < PWRDM_TRANSITION_BAILOUT))
0301         udelay(1);
0302 
0303     if (c > PWRDM_TRANSITION_BAILOUT) {
0304         pr_err("powerdomain: %s: waited too long to complete transition\n",
0305                pwrdm->name);
0306         return -EAGAIN;
0307     }
0308 
0309     pr_debug("powerdomain: completed transition in %d loops\n", c);
0310 
0311     return 0;
0312 }
0313 
0314 static int am33xx_check_vcvp(void)
0315 {
0316     /* No VC/VP on am33xx devices */
0317     return 0;
0318 }
0319 
0320 /**
0321  * am33xx_prm_global_warm_sw_reset - reboot the device via warm reset
0322  *
0323  * Immediately reboots the device through warm reset.
0324  */
0325 static void am33xx_prm_global_warm_sw_reset(void)
0326 {
0327     am33xx_prm_rmw_reg_bits(AM33XX_RST_GLOBAL_WARM_SW_MASK,
0328                 AM33XX_RST_GLOBAL_WARM_SW_MASK,
0329                 AM33XX_PRM_DEVICE_MOD,
0330                 AM33XX_PRM_RSTCTRL_OFFSET);
0331 
0332     /* OCP barrier */
0333     (void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD,
0334                   AM33XX_PRM_RSTCTRL_OFFSET);
0335 }
0336 
0337 static void am33xx_pwrdm_save_context(struct powerdomain *pwrdm)
0338 {
0339     pwrdm->context = am33xx_prm_read_reg(pwrdm->prcm_offs,
0340                         pwrdm->pwrstctrl_offs);
0341     /*
0342      * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request,
0343      * reading back a 1 indicates a request in progress.
0344      */
0345     pwrdm->context &= ~AM33XX_LOWPOWERSTATECHANGE_MASK;
0346 }
0347 
0348 static void am33xx_pwrdm_restore_context(struct powerdomain *pwrdm)
0349 {
0350     int st, ctrl;
0351 
0352     st = am33xx_prm_read_reg(pwrdm->prcm_offs,
0353                  pwrdm->pwrstst_offs);
0354 
0355     am33xx_prm_write_reg(pwrdm->context, pwrdm->prcm_offs,
0356                  pwrdm->pwrstctrl_offs);
0357 
0358     /* Make sure we only wait for a transition if there is one */
0359     st &= OMAP_POWERSTATEST_MASK;
0360     ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context;
0361 
0362     if (st != ctrl)
0363         am33xx_pwrdm_wait_transition(pwrdm);
0364 }
0365 
0366 struct pwrdm_ops am33xx_pwrdm_operations = {
0367     .pwrdm_set_next_pwrst       = am33xx_pwrdm_set_next_pwrst,
0368     .pwrdm_read_next_pwrst      = am33xx_pwrdm_read_next_pwrst,
0369     .pwrdm_read_pwrst       = am33xx_pwrdm_read_pwrst,
0370     .pwrdm_set_logic_retst      = am33xx_pwrdm_set_logic_retst,
0371     .pwrdm_read_logic_pwrst     = am33xx_pwrdm_read_logic_pwrst,
0372     .pwrdm_read_logic_retst     = am33xx_pwrdm_read_logic_retst,
0373     .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst,
0374     .pwrdm_set_lowpwrstchange   = am33xx_pwrdm_set_lowpwrstchange,
0375     .pwrdm_read_mem_pwrst       = am33xx_pwrdm_read_mem_pwrst,
0376     .pwrdm_read_mem_retst       = am33xx_pwrdm_read_mem_retst,
0377     .pwrdm_set_mem_onst     = am33xx_pwrdm_set_mem_onst,
0378     .pwrdm_set_mem_retst        = am33xx_pwrdm_set_mem_retst,
0379     .pwrdm_wait_transition      = am33xx_pwrdm_wait_transition,
0380     .pwrdm_has_voltdm       = am33xx_check_vcvp,
0381     .pwrdm_save_context     = am33xx_pwrdm_save_context,
0382     .pwrdm_restore_context      = am33xx_pwrdm_restore_context,
0383 };
0384 
0385 static struct prm_ll_data am33xx_prm_ll_data = {
0386     .assert_hardreset       = am33xx_prm_assert_hardreset,
0387     .deassert_hardreset     = am33xx_prm_deassert_hardreset,
0388     .is_hardreset_asserted      = am33xx_prm_is_hardreset_asserted,
0389     .reset_system           = am33xx_prm_global_warm_sw_reset,
0390 };
0391 
0392 int __init am33xx_prm_init(const struct omap_prcm_init_data *data)
0393 {
0394     return prm_register(&am33xx_prm_ll_data);
0395 }
0396 
0397 static void __exit am33xx_prm_exit(void)
0398 {
0399     prm_unregister(&am33xx_prm_ll_data);
0400 }
0401 __exitcall(am33xx_prm_exit);