Skip to content

Commit 358f0e6

Browse files
thara-zzPaul Walmsley
authored andcommitted
OMAP3: hwmod: support to specify the offset position of various SYSCONFIG register bits.
In OMAP3 Some modules like Smartreflex do not have the regular sysconfig register.Instead clockactivity bits are part of another register at a different bit position than the usual bit positions 8 and 9. In OMAP4, a new scheme is available due to the new protocol between the PRCM and the IPs. Depending of the scheme, the SYSCONFIG bitfields position will be different. The IP_REVISION register should be at offset 0x00. It should contain a SCHEME field. From this we can determine whether the IP follows legacy scheme or the new scheme. 31:30 SCHEME Used to distinguish between old scheme and current. Read 0x0: Legacy protocol. Read 0x1: New PRCM protocol defined for new OMAP4 IPs For legacy IP 13:12 MIDLEMODE 11:8 CLOCKACTIVITY 6 EMUSOFT 5 EMUFREE 4:3 SIDLEMODE 2 ENAWAKEUP 1 SOFTRESET 0 AUTOIDLE For new OMAP4 IP's, the bit position in SYSCONFIG is (for simple target): 5:4 STANDBYMODE (Ex MIDLEMODE) 3:2 IDLEMODE (Ex SIDLEMODE) 1 FREEEMU (Ex EMUFREE) 0 SOFTRESET Unfortunately In OMAP4 also some IPs will not follow any of these two schemes. This is the case at least for McASP, SmartReflex and some security IPs. This patch introduces a new field sysc_fields in omap_hwmod_sysconfig which can be used by the hwmod structures to specify the offsets for the sysconfig register of the IP.Also two static structures omap_hwmod_sysc_type1 and omap_hwmod_sysc_type2 are defined which can be used directly to populate the sysc_fields if the IP follows legacy or new OMAP4 scheme. If the IP follows none of these two schemes a new omap_hwmod_sysc_fields structure has to be defined and passed as part of omap_hwmod_sysconfig. Signed-off-by: Thara Gopinath <[email protected]> Signed-off-by: Benoit Cousson <[email protected]> Signed-off-by: Paul Walmsley <[email protected]>
1 parent 5eb75f5 commit 358f0e6

File tree

4 files changed

+191
-29
lines changed

4 files changed

+191
-29
lines changed

arch/arm/mach-omap2/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
# Common support
66
obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o
77

8-
omap-2-3-common = irq.o sdrc.o omap_hwmod.o
8+
omap-2-3-common = irq.o sdrc.o omap_hwmod.o \
9+
omap_hwmod_common_data.o
910
omap-3-4-common = dpll3xxx.o
1011
prcm-common = prcm.o powerdomain.o
1112
clock-common = clock.o clock_common_data.o \

arch/arm/mach-omap2/omap_hwmod.c

Lines changed: 87 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,24 @@ static void _write_sysconfig(u32 v, struct omap_hwmod *oh)
137137
static int _set_master_standbymode(struct omap_hwmod *oh, u8 standbymode,
138138
u32 *v)
139139
{
140+
u32 mstandby_mask;
141+
u8 mstandby_shift;
142+
140143
if (!oh->sysconfig ||
141144
!(oh->sysconfig->sysc_flags & SYSC_HAS_MIDLEMODE))
142145
return -EINVAL;
143146

144-
*v &= ~SYSC_MIDLEMODE_MASK;
145-
*v |= __ffs(standbymode) << SYSC_MIDLEMODE_SHIFT;
147+
if (!oh->sysconfig->sysc_fields) {
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;
146158

147159
return 0;
148160
}
@@ -159,12 +171,24 @@ static int _set_master_standbymode(struct omap_hwmod *oh, u8 standbymode,
159171
*/
160172
static int _set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode, u32 *v)
161173
{
174+
u32 sidle_mask;
175+
u8 sidle_shift;
176+
162177
if (!oh->sysconfig ||
163178
!(oh->sysconfig->sysc_flags & SYSC_HAS_SIDLEMODE))
164179
return -EINVAL;
165180

166-
*v &= ~SYSC_SIDLEMODE_MASK;
167-
*v |= __ffs(idlemode) << SYSC_SIDLEMODE_SHIFT;
181+
if (!oh->sysconfig->sysc_fields) {
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;
168192

169193
return 0;
170194
}
@@ -182,12 +206,24 @@ static int _set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode, u32 *v)
182206
*/
183207
static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v)
184208
{
209+
u32 clkact_mask;
210+
u8 clkact_shift;
211+
185212
if (!oh->sysconfig ||
186213
!(oh->sysconfig->sysc_flags & SYSC_HAS_CLOCKACTIVITY))
187214
return -EINVAL;
188215

189-
*v &= ~SYSC_CLOCKACTIVITY_MASK;
190-
*v |= clockact << SYSC_CLOCKACTIVITY_SHIFT;
216+
if (!oh->sysconfig->sysc_fields) {
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;
191227

192228
return 0;
193229
}
@@ -202,11 +238,21 @@ static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v)
202238
*/
203239
static int _set_softreset(struct omap_hwmod *oh, u32 *v)
204240
{
241+
u32 softrst_mask;
242+
205243
if (!oh->sysconfig ||
206244
!(oh->sysconfig->sysc_flags & SYSC_HAS_SOFTRESET))
207245
return -EINVAL;
208246

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;
210256

211257
return 0;
212258
}
@@ -227,12 +273,24 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
227273
static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
228274
u32 *v)
229275
{
276+
u32 autoidle_mask;
277+
u8 autoidle_shift;
278+
230279
if (!oh->sysconfig ||
231280
!(oh->sysconfig->sysc_flags & SYSC_HAS_AUTOIDLE))
232281
return -EINVAL;
233282

234-
*v &= ~SYSC_AUTOIDLE_MASK;
235-
*v |= autoidle << SYSC_AUTOIDLE_SHIFT;
283+
if (!oh->sysconfig->sysc_fields) {
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;
236294

237295
return 0;
238296
}
@@ -246,14 +304,22 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
246304
*/
247305
static int _enable_wakeup(struct omap_hwmod *oh)
248306
{
249-
u32 v;
307+
u32 v, wakeup_mask;
250308

251309
if (!oh->sysconfig ||
252310
!(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP))
253311
return -EINVAL;
254312

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+
255321
v = oh->_sysc_cache;
256-
v |= SYSC_ENAWAKEUP_MASK;
322+
v |= wakeup_mask;
257323
_write_sysconfig(v, oh);
258324

259325
/* XXX test pwrdm_get_wken for this hwmod's subsystem */
@@ -272,14 +338,22 @@ static int _enable_wakeup(struct omap_hwmod *oh)
272338
*/
273339
static int _disable_wakeup(struct omap_hwmod *oh)
274340
{
275-
u32 v;
341+
u32 v, wakeup_mask;
276342

277343
if (!oh->sysconfig ||
278344
!(oh->sysconfig->sysc_flags & SYSC_HAS_ENAWAKEUP))
279345
return -EINVAL;
280346

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+
281355
v = oh->_sysc_cache;
282-
v &= ~SYSC_ENAWAKEUP_MASK;
356+
v &= ~wakeup_mask;
283357
_write_sysconfig(v, oh);
284358

285359
/* XXX test pwrdm_get_wken for this hwmod's subsystem */
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* omap_hwmod common data structures
3+
*
4+
* Copyright (C) 2010 Texas Instruments, Inc.
5+
* Thara Gopinath <[email protected]>
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+
*/
24+
struct 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+
*/
40+
struct 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+
};

arch/arm/plat-omap/include/plat/omap_hwmod.h

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,42 @@
3333
#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
3434

3535
#include <linux/kernel.h>
36+
#include <linux/list.h>
3637
#include <linux/ioport.h>
37-
3838
#include <plat/cpu.h>
3939

4040
struct omap_device;
4141

42-
/* OCP SYSCONFIG bit shifts/masks */
43-
#define SYSC_MIDLEMODE_SHIFT 12
44-
#define SYSC_MIDLEMODE_MASK (0x3 << SYSC_MIDLEMODE_SHIFT)
45-
#define SYSC_CLOCKACTIVITY_SHIFT 8
46-
#define SYSC_CLOCKACTIVITY_MASK (0x3 << SYSC_CLOCKACTIVITY_SHIFT)
47-
#define SYSC_SIDLEMODE_SHIFT 3
48-
#define SYSC_SIDLEMODE_MASK (0x3 << SYSC_SIDLEMODE_SHIFT)
49-
#define SYSC_ENAWAKEUP_SHIFT 2
50-
#define SYSC_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT)
51-
#define SYSC_SOFTRESET_SHIFT 1
52-
#define SYSC_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT)
53-
#define SYSC_AUTOIDLE_SHIFT 0
54-
#define SYSC_AUTOIDLE_MASK (1 << SYSC_AUTOIDLE_SHIFT)
42+
extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1;
43+
extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
44+
45+
/*
46+
* OCP SYSCONFIG bit shifts/masks TYPE1. These are for IPs compliant
47+
* with the original PRCM protocol defined for OMAP2420
48+
*/
49+
#define SYSC_TYPE1_MIDLEMODE_SHIFT 12
50+
#define SYSC_TYPE1_MIDLEMODE_MASK (0x3 << SYSC_MIDLEMODE_SHIFT)
51+
#define SYSC_TYPE1_CLOCKACTIVITY_SHIFT 8
52+
#define SYSC_TYPE1_CLOCKACTIVITY_MASK (0x3 << SYSC_CLOCKACTIVITY_SHIFT)
53+
#define SYSC_TYPE1_SIDLEMODE_SHIFT 3
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)
5572

5673
/* OCP SYSSTATUS bit shifts/masks */
5774
#define SYSS_RESETDONE_SHIFT 0
@@ -62,7 +79,6 @@ struct omap_device;
6279
#define HWMOD_IDLEMODE_NO (1 << 1)
6380
#define HWMOD_IDLEMODE_SMART (1 << 2)
6481

65-
6682
/**
6783
* struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
6884
* @name: name of the IRQ channel (module local name)
@@ -235,6 +251,24 @@ struct omap_hwmod_ocp_if {
235251
#define CLOCKACT_TEST_ICLK 0x2
236252
#define CLOCKACT_TEST_NONE 0x3
237253

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+
*/
263+
struct 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+
238272
/**
239273
* struct omap_hwmod_sysconfig - hwmod OCP_SYSCONFIG/OCP_SYSSTATUS data
240274
* @rev_offs: IP block revision register offset (from module base addr)
@@ -252,6 +286,14 @@ struct omap_hwmod_ocp_if {
252286
* been associated with the clocks marked in @clockact. This field is
253287
* only used if HWMOD_SET_DEFAULT_CLOCKACT is set (see below)
254288
*
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.
255297
*/
256298
struct omap_hwmod_sysconfig {
257299
u16 rev_offs;
@@ -260,6 +302,7 @@ struct omap_hwmod_sysconfig {
260302
u8 idlemodes;
261303
u8 sysc_flags;
262304
u8 clockact;
305+
struct omap_hwmod_sysc_fields *sysc_fields;
263306
};
264307

265308
/**

0 commit comments

Comments
 (0)