xref: /openbmc/linux/arch/arm/mach-omap2/prminst44xx.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * OMAP4 PRM instance functions
4   *
5   * Copyright (C) 2009 Nokia Corporation
6   * Copyright (C) 2011 Texas Instruments, Inc.
7   * Paul Walmsley
8   */
9  
10  #include <linux/kernel.h>
11  #include <linux/types.h>
12  #include <linux/errno.h>
13  #include <linux/err.h>
14  #include <linux/io.h>
15  
16  #include "iomap.h"
17  #include "common.h"
18  #include "prcm-common.h"
19  #include "prm44xx.h"
20  #include "prm54xx.h"
21  #include "prm7xx.h"
22  #include "prminst44xx.h"
23  #include "prm-regbits-44xx.h"
24  #include "prcm44xx.h"
25  #include "prcm43xx.h"
26  #include "prcm_mpu44xx.h"
27  #include "soc.h"
28  
29  static struct omap_domain_base _prm_bases[OMAP4_MAX_PRCM_PARTITIONS];
30  
31  static s32 prm_dev_inst = PRM_INSTANCE_UNKNOWN;
32  
33  /**
34   * omap_prm_base_init - Populates the prm partitions
35   *
36   * Populates the base addresses of the _prm_bases
37   * array used for read/write of prm module registers.
38   */
omap_prm_base_init(void)39  void omap_prm_base_init(void)
40  {
41  	memcpy(&_prm_bases[OMAP4430_PRM_PARTITION], &prm_base,
42  	       sizeof(prm_base));
43  	memcpy(&_prm_bases[OMAP4430_PRCM_MPU_PARTITION], &prcm_mpu_base,
44  	       sizeof(prcm_mpu_base));
45  }
46  
omap4_prmst_get_prm_dev_inst(void)47  s32 omap4_prmst_get_prm_dev_inst(void)
48  {
49  	return prm_dev_inst;
50  }
51  
omap4_prminst_set_prm_dev_inst(s32 dev_inst)52  void omap4_prminst_set_prm_dev_inst(s32 dev_inst)
53  {
54  	prm_dev_inst = dev_inst;
55  }
56  
57  /* Read a register in a PRM instance */
omap4_prminst_read_inst_reg(u8 part,s16 inst,u16 idx)58  u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
59  {
60  	BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
61  	       part == OMAP4430_INVALID_PRCM_PARTITION ||
62  	       !_prm_bases[part].va);
63  	return readl_relaxed(_prm_bases[part].va + inst + idx);
64  }
65  
66  /* Write into a register in a PRM instance */
omap4_prminst_write_inst_reg(u32 val,u8 part,s16 inst,u16 idx)67  void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
68  {
69  	BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
70  	       part == OMAP4430_INVALID_PRCM_PARTITION ||
71  	       !_prm_bases[part].va);
72  	writel_relaxed(val, _prm_bases[part].va + inst + idx);
73  }
74  
75  /* Read-modify-write a register in PRM. Caller must lock */
omap4_prminst_rmw_inst_reg_bits(u32 mask,u32 bits,u8 part,s16 inst,u16 idx)76  u32 omap4_prminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
77  				    u16 idx)
78  {
79  	u32 v;
80  
81  	v = omap4_prminst_read_inst_reg(part, inst, idx);
82  	v &= ~mask;
83  	v |= bits;
84  	omap4_prminst_write_inst_reg(v, part, inst, idx);
85  
86  	return v;
87  }
88  
89  /**
90   * omap4_prminst_is_hardreset_asserted - read the HW reset line state of
91   * submodules contained in the hwmod module
92   * @rstctrl_reg: RM_RSTCTRL register address for this module
93   * @shift: register bit shift corresponding to the reset line to check
94   *
95   * Returns 1 if the (sub)module hardreset line is currently asserted,
96   * 0 if the (sub)module hardreset line is not currently asserted, or
97   * -EINVAL upon parameter error.
98   */
omap4_prminst_is_hardreset_asserted(u8 shift,u8 part,s16 inst,u16 rstctrl_offs)99  int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
100  					u16 rstctrl_offs)
101  {
102  	u32 v;
103  
104  	v = omap4_prminst_read_inst_reg(part, inst, rstctrl_offs);
105  	v &= 1 << shift;
106  	v >>= shift;
107  
108  	return v;
109  }
110  
111  /**
112   * omap4_prminst_assert_hardreset - assert the HW reset line of a submodule
113   * @rstctrl_reg: RM_RSTCTRL register address for this module
114   * @shift: register bit shift corresponding to the reset line to assert
115   *
116   * Some IPs like dsp, ipu or iva contain processors that require an HW
117   * reset line to be asserted / deasserted in order to fully enable the
118   * IP.  These modules may have multiple hard-reset lines that reset
119   * different 'submodules' inside the IP block.  This function will
120   * place the submodule into reset.  Returns 0 upon success or -EINVAL
121   * upon an argument error.
122   */
omap4_prminst_assert_hardreset(u8 shift,u8 part,s16 inst,u16 rstctrl_offs)123  int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
124  				   u16 rstctrl_offs)
125  {
126  	u32 mask = 1 << shift;
127  
128  	omap4_prminst_rmw_inst_reg_bits(mask, mask, part, inst, rstctrl_offs);
129  
130  	return 0;
131  }
132  
133  /**
134   * omap4_prminst_deassert_hardreset - deassert a submodule hardreset line and
135   * wait
136   * @shift: register bit shift corresponding to the reset line to deassert
137   * @st_shift: status bit offset corresponding to the reset line
138   * @part: PRM partition
139   * @inst: PRM instance offset
140   * @rstctrl_offs: reset register offset
141   * @rstst_offs: reset status register offset
142   *
143   * Some IPs like dsp, ipu or iva contain processors that require an HW
144   * reset line to be asserted / deasserted in order to fully enable the
145   * IP.  These modules may have multiple hard-reset lines that reset
146   * different 'submodules' inside the IP block.  This function will
147   * take the submodule out of reset and wait until the PRCM indicates
148   * that the reset has completed before returning.  Returns 0 upon success or
149   * -EINVAL upon an argument error, -EEXIST if the submodule was already out
150   * of reset, or -EBUSY if the submodule did not exit reset promptly.
151   */
omap4_prminst_deassert_hardreset(u8 shift,u8 st_shift,u8 part,s16 inst,u16 rstctrl_offs,u16 rstst_offs)152  int omap4_prminst_deassert_hardreset(u8 shift, u8 st_shift, u8 part, s16 inst,
153  				     u16 rstctrl_offs, u16 rstst_offs)
154  {
155  	int c;
156  	u32 mask = 1 << shift;
157  	u32 st_mask = 1 << st_shift;
158  
159  	/* Check the current status to avoid de-asserting the line twice */
160  	if (omap4_prminst_is_hardreset_asserted(shift, part, inst,
161  						rstctrl_offs) == 0)
162  		return -EEXIST;
163  
164  	/* Clear the reset status by writing 1 to the status bit */
165  	omap4_prminst_rmw_inst_reg_bits(0xffffffff, st_mask, part, inst,
166  					rstst_offs);
167  	/* de-assert the reset control line */
168  	omap4_prminst_rmw_inst_reg_bits(mask, 0, part, inst, rstctrl_offs);
169  	/* wait the status to be set */
170  	omap_test_timeout(omap4_prminst_is_hardreset_asserted(st_shift, part,
171  							      inst, rstst_offs),
172  			  MAX_MODULE_HARDRESET_WAIT, c);
173  
174  	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
175  }
176  
177  
omap4_prminst_global_warm_sw_reset(void)178  void omap4_prminst_global_warm_sw_reset(void)
179  {
180  	u32 v;
181  	s32 inst = omap4_prmst_get_prm_dev_inst();
182  
183  	if (inst == PRM_INSTANCE_UNKNOWN)
184  		return;
185  
186  	v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, inst,
187  					OMAP4_PRM_RSTCTRL_OFFSET);
188  	v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
189  	omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION,
190  				 inst, OMAP4_PRM_RSTCTRL_OFFSET);
191  
192  	/* OCP barrier */
193  	v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
194  				    inst, OMAP4_PRM_RSTCTRL_OFFSET);
195  }
196