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