Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * OMAP4 PRM instance functions
0004  *
0005  * Copyright (C) 2009 Nokia Corporation
0006  * Copyright (C) 2011 Texas Instruments, Inc.
0007  * Paul Walmsley
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/types.h>
0012 #include <linux/errno.h>
0013 #include <linux/err.h>
0014 #include <linux/io.h>
0015 
0016 #include "iomap.h"
0017 #include "common.h"
0018 #include "prcm-common.h"
0019 #include "prm44xx.h"
0020 #include "prm54xx.h"
0021 #include "prm7xx.h"
0022 #include "prminst44xx.h"
0023 #include "prm-regbits-44xx.h"
0024 #include "prcm44xx.h"
0025 #include "prcm43xx.h"
0026 #include "prcm_mpu44xx.h"
0027 #include "soc.h"
0028 
0029 static struct omap_domain_base _prm_bases[OMAP4_MAX_PRCM_PARTITIONS];
0030 
0031 static s32 prm_dev_inst = PRM_INSTANCE_UNKNOWN;
0032 
0033 /**
0034  * omap_prm_base_init - Populates the prm partitions
0035  *
0036  * Populates the base addresses of the _prm_bases
0037  * array used for read/write of prm module registers.
0038  */
0039 void omap_prm_base_init(void)
0040 {
0041     memcpy(&_prm_bases[OMAP4430_PRM_PARTITION], &prm_base,
0042            sizeof(prm_base));
0043     memcpy(&_prm_bases[OMAP4430_PRCM_MPU_PARTITION], &prcm_mpu_base,
0044            sizeof(prcm_mpu_base));
0045 }
0046 
0047 s32 omap4_prmst_get_prm_dev_inst(void)
0048 {
0049     return prm_dev_inst;
0050 }
0051 
0052 void omap4_prminst_set_prm_dev_inst(s32 dev_inst)
0053 {
0054     prm_dev_inst = dev_inst;
0055 }
0056 
0057 /* Read a register in a PRM instance */
0058 u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
0059 {
0060     BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
0061            part == OMAP4430_INVALID_PRCM_PARTITION ||
0062            !_prm_bases[part].va);
0063     return readl_relaxed(_prm_bases[part].va + inst + idx);
0064 }
0065 
0066 /* Write into a register in a PRM instance */
0067 void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
0068 {
0069     BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
0070            part == OMAP4430_INVALID_PRCM_PARTITION ||
0071            !_prm_bases[part].va);
0072     writel_relaxed(val, _prm_bases[part].va + inst + idx);
0073 }
0074 
0075 /* Read-modify-write a register in PRM. Caller must lock */
0076 u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
0077                     u16 idx)
0078 {
0079     u32 v;
0080 
0081     v = omap4_prminst_read_inst_reg(part, inst, idx);
0082     v &= ~mask;
0083     v |= bits;
0084     omap4_prminst_write_inst_reg(v, part, inst, idx);
0085 
0086     return v;
0087 }
0088 
0089 /**
0090  * omap4_prminst_is_hardreset_asserted - read the HW reset line state of
0091  * submodules contained in the hwmod module
0092  * @rstctrl_reg: RM_RSTCTRL register address for this module
0093  * @shift: register bit shift corresponding to the reset line to check
0094  *
0095  * Returns 1 if the (sub)module hardreset line is currently asserted,
0096  * 0 if the (sub)module hardreset line is not currently asserted, or
0097  * -EINVAL upon parameter error.
0098  */
0099 int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
0100                     u16 rstctrl_offs)
0101 {
0102     u32 v;
0103 
0104     v = omap4_prminst_read_inst_reg(part, inst, rstctrl_offs);
0105     v &= 1 << shift;
0106     v >>= shift;
0107 
0108     return v;
0109 }
0110 
0111 /**
0112  * omap4_prminst_assert_hardreset - assert the HW reset line of a submodule
0113  * @rstctrl_reg: RM_RSTCTRL register address for this module
0114  * @shift: register bit shift corresponding to the reset line to assert
0115  *
0116  * Some IPs like dsp, ipu or iva contain processors that require an HW
0117  * reset line to be asserted / deasserted in order to fully enable the
0118  * IP.  These modules may have multiple hard-reset lines that reset
0119  * different 'submodules' inside the IP block.  This function will
0120  * place the submodule into reset.  Returns 0 upon success or -EINVAL
0121  * upon an argument error.
0122  */
0123 int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
0124                    u16 rstctrl_offs)
0125 {
0126     u32 mask = 1 << shift;
0127 
0128     omap4_prminst_rmw_inst_reg_bits(mask, mask, part, inst, rstctrl_offs);
0129 
0130     return 0;
0131 }
0132 
0133 /**
0134  * omap4_prminst_deassert_hardreset - deassert a submodule hardreset line and
0135  * wait
0136  * @shift: register bit shift corresponding to the reset line to deassert
0137  * @st_shift: status bit offset corresponding to the reset line
0138  * @part: PRM partition
0139  * @inst: PRM instance offset
0140  * @rstctrl_offs: reset register offset
0141  * @rstst_offs: reset status register offset
0142  *
0143  * Some IPs like dsp, ipu or iva contain processors that require an HW
0144  * reset line to be asserted / deasserted in order to fully enable the
0145  * IP.  These modules may have multiple hard-reset lines that reset
0146  * different 'submodules' inside the IP block.  This function will
0147  * take the submodule out of reset and wait until the PRCM indicates
0148  * that the reset has completed before returning.  Returns 0 upon success or
0149  * -EINVAL upon an argument error, -EEXIST if the submodule was already out
0150  * of reset, or -EBUSY if the submodule did not exit reset promptly.
0151  */
0152 int omap4_prminst_deassert_hardreset(u8 shift, u8 st_shift, u8 part, s16 inst,
0153                      u16 rstctrl_offs, u16 rstst_offs)
0154 {
0155     int c;
0156     u32 mask = 1 << shift;
0157     u32 st_mask = 1 << st_shift;
0158 
0159     /* Check the current status to avoid de-asserting the line twice */
0160     if (omap4_prminst_is_hardreset_asserted(shift, part, inst,
0161                         rstctrl_offs) == 0)
0162         return -EEXIST;
0163 
0164     /* Clear the reset status by writing 1 to the status bit */
0165     omap4_prminst_rmw_inst_reg_bits(0xffffffff, st_mask, part, inst,
0166                     rstst_offs);
0167     /* de-assert the reset control line */
0168     omap4_prminst_rmw_inst_reg_bits(mask, 0, part, inst, rstctrl_offs);
0169     /* wait the status to be set */
0170     omap_test_timeout(omap4_prminst_is_hardreset_asserted(st_shift, part,
0171                                   inst, rstst_offs),
0172               MAX_MODULE_HARDRESET_WAIT, c);
0173 
0174     return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
0175 }
0176 
0177 
0178 void omap4_prminst_global_warm_sw_reset(void)
0179 {
0180     u32 v;
0181     s32 inst = omap4_prmst_get_prm_dev_inst();
0182 
0183     if (inst == PRM_INSTANCE_UNKNOWN)
0184         return;
0185 
0186     v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, inst,
0187                     OMAP4_PRM_RSTCTRL_OFFSET);
0188     v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
0189     omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
0190                  inst, OMAP4_PRM_RSTCTRL_OFFSET);
0191 
0192     /* OCP barrier */
0193     v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
0194                     inst, OMAP4_PRM_RSTCTRL_OFFSET);
0195 }