aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/Makefile3
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c100
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_common_data.c44
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h73
4 files changed, 191 insertions, 29 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index dfc49a0c6927..3ebd0b6525df 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -5,7 +5,8 @@
5# Common support 5# Common support
6obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o 6obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o
7 7
8omap-2-3-common = irq.o sdrc.o omap_hwmod.o 8omap-2-3-common = irq.o sdrc.o omap_hwmod.o \
9 omap_hwmod_common_data.o
9omap-3-4-common = dpll3xxx.o 10omap-3-4-common = dpll3xxx.o
10prcm-common = prcm.o powerdomain.o 11prcm-common = prcm.o powerdomain.o
11clock-common = clock.o clock_common_data.o \ 12clock-common = clock.o clock_common_data.o \
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 70912d1c71e0..fb11ec176d55 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -137,12 +137,24 @@ static void _write_sysconfig(u32 v, struct omap_hwmod *oh)
137static int _set_master_standbymode(struct omap_hwmod *oh, u8 standbymode, 137static int _set_master_standbymode(struct omap_hwmod *oh, u8 standbymode,
138 u32 *v) 138 u32 *v)
139{ 139{
140 u32 mstandby_mask;
141 u8 mstandby_shift;
142
140 if (!oh->sysconfig || 143 if (!oh->sysconfig ||
141 !(oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE)) 144 !(oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE))
142 return -EINVAL; 145 return -EINVAL;
143 146
144 *v &= ~SYSC_MIDLEMODE_MASK; 147 if (!oh->sysconfig->sysc_fields) {
145 *v |= __ffs(standbymode) << SYSC_MIDLEMODE_SHIFT; 148 WARN(!oh->sysconfig->sysc_fields, "offset struct for "
149 "sysconfig not provided!\n");
150 return -EINVAL;
151 }
152
153 mstandby_shift = oh->sysconfig->sysc_fields->midle_shift;
154 mstandby_mask = (0x3 << mstandby_shift);
155
156 *v &= ~mstandby_mask;
157 *v |= __ffs(standbymode) << mstandby_shift;
146 158
147 return 0; 159 return 0;
148} 160}
@@ -159,12 +171,24 @@ static int _set_master_standbymode(struct omap_hwmod *oh, u8 standbymode,
159 */ 171 */
160static int _set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode, u32 *v) 172static int _set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode, u32 *v)
161{ 173{
174 u32 sidle_mask;
175 u8 sidle_shift;
176
162 if (!oh->sysconfig || 177 if (!oh->sysconfig ||
163 !(oh->sysconfig->sysc_flags & SYSC_HAS_SIDLEMODE)) 178 !(oh->sysconfig->sysc_flags & SYSC_HAS_SIDLEMODE))
164 return -EINVAL; 179 return -EINVAL;
165 180
166 *v &= ~SYSC_SIDLEMODE_MASK; 181 if (!oh->sysconfig->sysc_fields) {
167 *v |= __ffs(idlemode) << SYSC_SIDLEMODE_SHIFT; 182 WARN(!oh->sysconfig->sysc_fields, "offset struct for "
183 "sysconfig not provided!\n");
184 return -EINVAL;
185 }
186
187 sidle_shift = oh->sysconfig->sysc_fields->sidle_shift;
188 sidle_mask = (0x3 << sidle_shift);
189
190 *v &= ~sidle_mask;
191 *v |= __ffs(idlemode) << sidle_shift;
168 192
169 return 0; 193 return 0;
170} 194}
@@ -182,12 +206,24 @@ static int _set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode, u32 *v)
182 */ 206 */
183static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v) 207static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v)
184{ 208{
209 u32 clkact_mask;
210 u8 clkact_shift;
211
185 if (!oh->sysconfig || 212 if (!oh->sysconfig ||
186 !(oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY)) 213 !(oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY))
187 return -EINVAL; 214 return -EINVAL;
188 215
189 *v &= ~SYSC_CLOCKACTIVITY_MASK; 216 if (!oh->sysconfig->sysc_fields) {
190 *v |= clockact << SYSC_CLOCKACTIVITY_SHIFT; 217 WARN(!oh->sysconfig->sysc_fields, "offset struct for "
218 "sysconfig not provided!\n");
219 return -EINVAL;
220 }
221
222 clkact_shift = oh->sysconfig->sysc_fields->clkact_shift;
223 clkact_mask = (0x3 << clkact_shift);
224
225 *v &= ~clkact_mask;
226 *v |= clockact << clkact_shift;
191 227
192 return 0; 228 return 0;
193} 229}
@@ -202,11 +238,21 @@ static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v)
202 */ 238 */
203static int _set_softreset(struct omap_hwmod *oh, u32 *v) 239static int _set_softreset(struct omap_hwmod *oh, u32 *v)
204{ 240{
241 u32 softrst_mask;
242
205 if (!oh->sysconfig || 243 if (!oh->sysconfig ||
206 !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET)) 244 !(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET))
207 return -EINVAL; 245 return -EINVAL;
208 246
209 *v |= SYSC_SOFTRESET_MASK; 247 if (!oh->sysconfig->sysc_fields) {
248 WARN(!oh->sysconfig->sysc_fields, "offset struct for "
249 "sysconfig not provided!\n");
250 return -EINVAL;
251 }
252
253 softrst_mask = (0x1 << oh->sysconfig->sysc_fields->srst_shift);
254
255 *v |= softrst_mask;
210 256
211 return 0; 257 return 0;
212} 258}
@@ -227,12 +273,24 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
227static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, 273static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
228 u32 *v) 274 u32 *v)
229{ 275{
276 u32 autoidle_mask;
277 u8 autoidle_shift;
278
230 if (!oh->sysconfig || 279 if (!oh->sysconfig ||
231 !(oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE)) 280 !(oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE))
232 return -EINVAL; 281 return -EINVAL;
233 282
234 *v &= ~SYSC_AUTOIDLE_MASK; 283 if (!oh->sysconfig->sysc_fields) {
235 *v |= autoidle << SYSC_AUTOIDLE_SHIFT; 284 WARN(oh->sysconfig->sysc_fields, "offset struct for "
285 "sysconfig not provided!\n");
286 return -EINVAL;
287 }
288
289 autoidle_shift = oh->sysconfig->sysc_fields->autoidle_shift;
290 autoidle_mask = (0x3 << autoidle_shift);
291
292 *v &= ~autoidle_mask;
293 *v |= autoidle << autoidle_shift;
236 294
237 return 0; 295 return 0;
238} 296}
@@ -246,14 +304,22 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
246 */ 304 */
247static int _enable_wakeup(struct omap_hwmod *oh) 305static int _enable_wakeup(struct omap_hwmod *oh)
248{ 306{
249 u32 v; 307 u32 v, wakeup_mask;
250 308
251 if (!oh->sysconfig || 309 if (!oh->sysconfig ||
252 !(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP)) 310 !(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP))
253 return -EINVAL; 311 return -EINVAL;
254 312
313 if (!oh->sysconfig->sysc_fields) {
314 WARN(!oh->sysconfig->sysc_fields, "offset struct for "
315 "sysconfig not provided!\n");
316 return -EINVAL;
317 }
318
319 wakeup_mask = (0x1 << oh->sysconfig->sysc_fields->enwkup_shift);
320
255 v = oh->_sysc_cache; 321 v = oh->_sysc_cache;
256 v |= SYSC_ENAWAKEUP_MASK; 322 v |= wakeup_mask;
257 _write_sysconfig(v, oh); 323 _write_sysconfig(v, oh);
258 324
259 /* XXX test pwrdm_get_wken for this hwmod's subsystem */ 325 /* XXX test pwrdm_get_wken for this hwmod's subsystem */
@@ -272,14 +338,22 @@ static int _enable_wakeup(struct omap_hwmod *oh)
272 */ 338 */
273static int _disable_wakeup(struct omap_hwmod *oh) 339static int _disable_wakeup(struct omap_hwmod *oh)
274{ 340{
275 u32 v; 341 u32 v, wakeup_mask;
276 342
277 if (!oh->sysconfig || 343 if (!oh->sysconfig ||
278 !(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP)) 344 !(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP))
279 return -EINVAL; 345 return -EINVAL;
280 346
347 if (!oh->sysconfig->sysc_fields) {
348 WARN(!oh->sysconfig->sysc_fields, "offset struct for "
349 "sysconfig not provided!\n");
350 return -EINVAL;
351 }
352
353 wakeup_mask = (0x1 << oh->sysconfig->sysc_fields->enwkup_shift);
354
281 v = oh->_sysc_cache; 355 v = oh->_sysc_cache;
282 v &= ~SYSC_ENAWAKEUP_MASK; 356 v &= ~wakeup_mask;
283 _write_sysconfig(v, oh); 357 _write_sysconfig(v, oh);
284 358
285 /* XXX test pwrdm_get_wken for this hwmod's subsystem */ 359 /* XXX test pwrdm_get_wken for this hwmod's subsystem */
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.c b/arch/arm/mach-omap2/omap_hwmod_common_data.c
new file mode 100644
index 000000000000..2567c6edc6af
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c
@@ -0,0 +1,44 @@
1/*
2 * omap_hwmod common data structures
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc.
5 * Thara Gopinath <thara@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This data/structures are to be used while defining OMAP on-chip module
12 * data and their integration with other OMAP modules and Linux.
13 */
14
15#include <plat/omap_hwmod.h>
16
17/**
18 * struct omap_hwmod_sysc_type1 - TYPE1 sysconfig scheme.
19 *
20 * To be used by hwmod structure to specify the sysconfig offsets
21 * if the device ip is compliant with the original PRCM protocol
22 * defined for OMAP2420.
23 */
24struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1 = {
25 .midle_shift = SYSC_TYPE1_MIDLEMODE_SHIFT,
26 .clkact_shift = SYSC_TYPE1_CLOCKACTIVITY_SHIFT,
27 .sidle_shift = SYSC_TYPE1_SIDLEMODE_SHIFT,
28 .enwkup_shift = SYSC_TYPE1_ENAWAKEUP_SHIFT,
29 .srst_shift = SYSC_TYPE1_SOFTRESET_SHIFT,
30 .autoidle_shift = SYSC_TYPE1_AUTOIDLE_SHIFT,
31};
32
33/**
34 * struct omap_hwmod_sysc_type2 - TYPE2 sysconfig scheme.
35 *
36 * To be used by hwmod structure to specify the sysconfig offsets if the
37 * device ip is compliant with the new PRCM protocol defined for new
38 * OMAP4 IPs.
39 */
40struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = {
41 .midle_shift = SYSC_TYPE2_MIDLEMODE_SHIFT,
42 .sidle_shift = SYSC_TYPE2_SIDLEMODE_SHIFT,
43 .srst_shift = SYSC_TYPE2_SOFTRESET_SHIFT,
44};
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 921990e2a29a..665420e89c21 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -33,25 +33,42 @@
33#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H 33#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
34 34
35#include <linux/kernel.h> 35#include <linux/kernel.h>
36#include <linux/list.h>
36#include <linux/ioport.h> 37#include <linux/ioport.h>
37
38#include <plat/cpu.h> 38#include <plat/cpu.h>
39 39
40struct omap_device; 40struct omap_device;
41 41
42/* OCP SYSCONFIG bit shifts/masks */ 42extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1;
43#define SYSC_MIDLEMODE_SHIFT 12 43extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
44#define SYSC_MIDLEMODE_MASK (0x3 << SYSC_MIDLEMODE_SHIFT) 44
45#define SYSC_CLOCKACTIVITY_SHIFT 8 45/*
46#define SYSC_CLOCKACTIVITY_MASK (0x3 << SYSC_CLOCKACTIVITY_SHIFT) 46 * OCP SYSCONFIG bit shifts/masks TYPE1. These are for IPs compliant
47#define SYSC_SIDLEMODE_SHIFT 3 47 * with the original PRCM protocol defined for OMAP2420
48#define SYSC_SIDLEMODE_MASK (0x3 << SYSC_SIDLEMODE_SHIFT) 48 */
49#define SYSC_ENAWAKEUP_SHIFT 2 49#define SYSC_TYPE1_MIDLEMODE_SHIFT 12
50#define SYSC_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT) 50#define SYSC_TYPE1_MIDLEMODE_MASK (0x3 << SYSC_MIDLEMODE_SHIFT)
51#define SYSC_SOFTRESET_SHIFT 1 51#define SYSC_TYPE1_CLOCKACTIVITY_SHIFT 8
52#define SYSC_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT) 52#define SYSC_TYPE1_CLOCKACTIVITY_MASK (0x3 << SYSC_CLOCKACTIVITY_SHIFT)
53#define SYSC_AUTOIDLE_SHIFT 0 53#define SYSC_TYPE1_SIDLEMODE_SHIFT 3
54#define SYSC_AUTOIDLE_MASK (1 << SYSC_AUTOIDLE_SHIFT) 54#define SYSC_TYPE1_SIDLEMODE_MASK (0x3 << SYSC_SIDLEMODE_SHIFT)
55#define SYSC_TYPE1_ENAWAKEUP_SHIFT 2
56#define SYSC_TYPE1_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT)
57#define SYSC_TYPE1_SOFTRESET_SHIFT 1
58#define SYSC_TYPE1_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT)
59#define SYSC_TYPE1_AUTOIDLE_SHIFT 0
60#define SYSC_TYPE1_AUTOIDLE_MASK (1 << SYSC_AUTOIDLE_SHIFT)
61
62/*
63 * OCP SYSCONFIG bit shifts/masks TYPE2. These are for IPs compliant
64 * with the new PRCM protocol defined for new OMAP4 IPs.
65 */
66#define SYSC_TYPE2_SOFTRESET_SHIFT 0
67#define SYSC_TYPE2_SOFTRESET_MASK (1 << SYSC_TYPE2_SOFTRESET_SHIFT)
68#define SYSC_TYPE2_SIDLEMODE_SHIFT 2
69#define SYSC_TYPE2_SIDLEMODE_MASK (0x3 << SYSC_TYPE2_SIDLEMODE_SHIFT)
70#define SYSC_TYPE2_MIDLEMODE_SHIFT 4
71#define SYSC_TYPE2_MIDLEMODE_MASK (0x3 << SYSC_TYPE2_MIDLEMODE_SHIFT)
55 72
56/* OCP SYSSTATUS bit shifts/masks */ 73/* OCP SYSSTATUS bit shifts/masks */
57#define SYSS_RESETDONE_SHIFT 0 74#define SYSS_RESETDONE_SHIFT 0
@@ -62,7 +79,6 @@ struct omap_device;
62#define HWMOD_IDLEMODE_NO (1 << 1) 79#define HWMOD_IDLEMODE_NO (1 << 1)
63#define HWMOD_IDLEMODE_SMART (1 << 2) 80#define HWMOD_IDLEMODE_SMART (1 << 2)
64 81
65
66/** 82/**
67 * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod 83 * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
68 * @name: name of the IRQ channel (module local name) 84 * @name: name of the IRQ channel (module local name)
@@ -236,6 +252,24 @@ struct omap_hwmod_ocp_if {
236#define CLOCKACT_TEST_NONE 0x3 252#define CLOCKACT_TEST_NONE 0x3
237 253
238/** 254/**
255 * struct omap_hwmod_sysc_fields - hwmod OCP_SYSCONFIG register field offsets.
256 * @midle_shift: Offset of the midle bit
257 * @clkact_shift: Offset of the clockactivity bit
258 * @sidle_shift: Offset of the sidle bit
259 * @enwkup_shift: Offset of the enawakeup bit
260 * @srst_shift: Offset of the softreset bit
261 * @autoidle_shift: Offset of the autoidle bit.
262 */
263struct omap_hwmod_sysc_fields {
264 u8 midle_shift;
265 u8 clkact_shift;
266 u8 sidle_shift;
267 u8 enwkup_shift;
268 u8 srst_shift;
269 u8 autoidle_shift;
270};
271
272/**
239 * struct omap_hwmod_sysconfig - hwmod OCP_SYSCONFIG/OCP_SYSSTATUS data 273 * struct omap_hwmod_sysconfig - hwmod OCP_SYSCONFIG/OCP_SYSSTATUS data
240 * @rev_offs: IP block revision register offset (from module base addr) 274 * @rev_offs: IP block revision register offset (from module base addr)
241 * @sysc_offs: OCP_SYSCONFIG register offset (from module base addr) 275 * @sysc_offs: OCP_SYSCONFIG register offset (from module base addr)
@@ -252,6 +286,14 @@ struct omap_hwmod_ocp_if {
252 * been associated with the clocks marked in @clockact. This field is 286 * been associated with the clocks marked in @clockact. This field is
253 * only used if HWMOD_SET_DEFAULT_CLOCKACT is set (see below) 287 * only used if HWMOD_SET_DEFAULT_CLOCKACT is set (see below)
254 * 288 *
289 *
290 * @sysc_fields: structure containing the offset positions of various bits in
291 * SYSCONFIG register. This can be populated using omap_hwmod_sysc_type1 or
292 * omap_hwmod_sysc_type2 defined in omap_hwmod_common_data.c depending on
293 * whether the device ip is compliant with the original PRCM protocol
294 * defined for OMAP2420 or the new PRCM protocol for new OMAP4 IPs.
295 * If the device follows a differnt scheme for the sysconfig register ,
296 * then this field has to be populated with the correct offset structure.
255 */ 297 */
256struct omap_hwmod_sysconfig { 298struct omap_hwmod_sysconfig {
257 u16 rev_offs; 299 u16 rev_offs;
@@ -260,6 +302,7 @@ struct omap_hwmod_sysconfig {
260 u8 idlemodes; 302 u8 idlemodes;
261 u8 sysc_flags; 303 u8 sysc_flags;
262 u8 clockact; 304 u8 clockact;
305 struct omap_hwmod_sysc_fields *sysc_fields;
263}; 306};
264 307
265/** 308/**