Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / arch / arm / mach-omap2 / prm44xx.c
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 */
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 */
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 */
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 */
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 */
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
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
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  */
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  */
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  */
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
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 }