blob: a2a04bfa962855820c4f1a1576e9546ae87ef8c6 [file] [log] [blame]
Benoît Cousson0be16212010-09-21 10:34:10 -06001/*
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>
Paul Walmsley2ace8312010-12-21 21:05:14 -070018#include <linux/io.h>
Benoît Cousson0be16212010-09-21 10:34:10 -060019
20#include <plat/common.h>
21#include <plat/cpu.h>
22#include <plat/prcm.h>
23
Paul Walmsleyd198b512010-12-21 15:30:54 -070024#include "prm44xx.h"
Benoît Cousson0be16212010-09-21 10:34:10 -060025#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
Paul Walmsley2ace8312010-12-21 21:05:14 -070033/* PRM low-level functions */
34
35/* Read a register in a CM/PRM instance in the PRM module */
36u32 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 */
42void 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 */
48u32 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 */
62u32 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 */
75u32 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
87u32 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
92u32 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
Benoît Cousson0be16212010-09-21 10:34:10 -060097/**
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 */
107int 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 */
127int 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 */
154int 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
Paul Walmsleydac9a772010-12-21 21:05:14 -0700182void 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}