1 /*
2 * OMAP4 PRM module functions
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc.
5 * Copyright (C) 2010 Nokia Corporation
6 * Benoît Cousson
7 * Paul Walmsley
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14 #include <linux/kernel.h>
15 #include <linux/delay.h>
16 #include <linux/errno.h>
17 #include <linux/err.h>
18 #include <linux/io.h>
19
20 #include <plat/common.h>
21 #include <plat/cpu.h>
22 #include <plat/prcm.h>
23
24 #include "prm44xx.h"
25 #include "prm-regbits-44xx.h"
26
27 /*
28 * Address offset (in bytes) between the reset control and the reset
29 * status registers: 4 bytes on OMAP4
30 */
31 #define OMAP4_RST_CTRL_ST_OFFSET 4
32
33 /* PRM low-level functions */
34
35 /* Read a register in a CM/PRM instance in the PRM module */
omap4_prm_read_inst_reg(s16 inst,u16 reg)36 u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
37 {
38 return __raw_readl(OMAP44XX_PRM_REGADDR(inst, reg));
39 }
40
41 /* Write into a register in a CM/PRM instance in the PRM module */
omap4_prm_write_inst_reg(u32 val,s16 inst,u16 reg)42 void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
43 {
44 __raw_writel(val, OMAP44XX_PRM_REGADDR(inst, reg));
45 }
46
47 /* Read-modify-write a register in a PRM module. Caller must lock */
omap4_prm_rmw_inst_reg_bits(u32 mask,u32 bits,s16 inst,s16 reg)48 u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
49 {
50 u32 v;
51
52 v = omap4_prm_read_inst_reg(inst, reg);
53 v &= ~mask;
54 v |= bits;
55 omap4_prm_write_inst_reg(v, inst, reg);
56
57 return v;
58 }
59
60 /* Read a PRM register, AND it, and shift the result down to bit 0 */
61 /* XXX deprecated */
omap4_prm_read_bits_shift(void __iomem * reg,u32 mask)62 u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
63 {
64 u32 v;
65
66 v = __raw_readl(reg);
67 v &= mask;
68 v >>= __ffs(mask);
69
70 return v;
71 }
72
73 /* Read-modify-write a register in a PRM module. Caller must lock */
74 /* XXX deprecated */
omap4_prm_rmw_reg_bits(u32 mask,u32 bits,void __iomem * reg)75 u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
76 {
77 u32 v;
78
79 v = __raw_readl(reg);
80 v &= ~mask;
81 v |= bits;
82 __raw_writel(v, reg);
83
84 return v;
85 }
86
omap4_prm_set_inst_reg_bits(u32 bits,s16 inst,s16 reg)87 u32 omap4_prm_set_inst_reg_bits(u32 bits, s16 inst, s16 reg)
88 {
89 return omap4_prm_rmw_inst_reg_bits(bits, bits, inst, reg);
90 }
91
omap4_prm_clear_inst_reg_bits(u32 bits,s16 inst,s16 reg)92 u32 omap4_prm_clear_inst_reg_bits(u32 bits, s16 inst, s16 reg)
93 {
94 return omap4_prm_rmw_inst_reg_bits(bits, 0x0, inst, reg);
95 }
96
97 /**
98 * omap4_prm_is_hardreset_asserted - read the HW reset line state of
99 * submodules contained in the hwmod module
100 * @rstctrl_reg: RM_RSTCTRL register address for this module
101 * @shift: register bit shift corresponding to the reset line to check
102 *
103 * Returns 1 if the (sub)module hardreset line is currently asserted,
104 * 0 if the (sub)module hardreset line is not currently asserted, or
105 * -EINVAL upon parameter error.
106 */
omap4_prm_is_hardreset_asserted(void __iomem * rstctrl_reg,u8 shift)107 int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift)
108 {
109 if (!cpu_is_omap44xx() || !rstctrl_reg)
110 return -EINVAL;
111
112 return omap4_prm_read_bits_shift(rstctrl_reg, (1 << shift));
113 }
114
115 /**
116 * omap4_prm_assert_hardreset - assert the HW reset line of a submodule
117 * @rstctrl_reg: RM_RSTCTRL register address for this module
118 * @shift: register bit shift corresponding to the reset line to assert
119 *
120 * Some IPs like dsp, ipu or iva contain processors that require an HW
121 * reset line to be asserted / deasserted in order to fully enable the
122 * IP. These modules may have multiple hard-reset lines that reset
123 * different 'submodules' inside the IP block. This function will
124 * place the submodule into reset. Returns 0 upon success or -EINVAL
125 * upon an argument error.
126 */
omap4_prm_assert_hardreset(void __iomem * rstctrl_reg,u8 shift)127 int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift)
128 {
129 u32 mask;
130
131 if (!cpu_is_omap44xx() || !rstctrl_reg)
132 return -EINVAL;
133
134 mask = 1 << shift;
135 omap4_prm_rmw_reg_bits(mask, mask, rstctrl_reg);
136
137 return 0;
138 }
139
140 /**
141 * omap4_prm_deassert_hardreset - deassert a submodule hardreset line and wait
142 * @rstctrl_reg: RM_RSTCTRL register address for this module
143 * @shift: register bit shift corresponding to the reset line to deassert
144 *
145 * Some IPs like dsp, ipu or iva contain processors that require an HW
146 * reset line to be asserted / deasserted in order to fully enable the
147 * IP. These modules may have multiple hard-reset lines that reset
148 * different 'submodules' inside the IP block. This function will
149 * take the submodule out of reset and wait until the PRCM indicates
150 * that the reset has completed before returning. Returns 0 upon success or
151 * -EINVAL upon an argument error, -EEXIST if the submodule was already out
152 * of reset, or -EBUSY if the submodule did not exit reset promptly.
153 */
omap4_prm_deassert_hardreset(void __iomem * rstctrl_reg,u8 shift)154 int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift)
155 {
156 u32 mask;
157 void __iomem *rstst_reg;
158 int c;
159
160 if (!cpu_is_omap44xx() || !rstctrl_reg)
161 return -EINVAL;
162
163 rstst_reg = rstctrl_reg + OMAP4_RST_CTRL_ST_OFFSET;
164
165 mask = 1 << shift;
166
167 /* Check the current status to avoid de-asserting the line twice */
168 if (omap4_prm_read_bits_shift(rstctrl_reg, mask) == 0)
169 return -EEXIST;
170
171 /* Clear the reset status by writing 1 to the status bit */
172 omap4_prm_rmw_reg_bits(0xffffffff, mask, rstst_reg);
173 /* de-assert the reset control line */
174 omap4_prm_rmw_reg_bits(mask, 0, rstctrl_reg);
175 /* wait the status to be set */
176 omap_test_timeout(omap4_prm_read_bits_shift(rstst_reg, mask),
177 MAX_MODULE_HARDRESET_WAIT, c);
178
179 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
180 }
181
omap4_prm_global_warm_sw_reset(void)182 void omap4_prm_global_warm_sw_reset(void)
183 {
184 u32 v;
185
186 v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
187 OMAP4_RM_RSTCTRL);
188 v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
189 omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST,
190 OMAP4_RM_RSTCTRL);
191
192 /* OCP barrier */
193 v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
194 OMAP4_RM_RSTCTRL);
195 }
196