diff options
author | Kevin Hilman <khilman@ti.com> | 2011-06-02 20:28:13 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@ti.com> | 2011-09-15 15:08:58 -0400 |
commit | 8abc0b58fdb89124d8278f110f523b27c666d36c (patch) | |
tree | 7f48f3ab775b32adb21f1a1941fdeb18bd0e23e8 /arch/arm/mach-omap2 | |
parent | f5395480f5088a86cc8594d29b5c2f07f6995c3d (diff) |
OMAP3+: PM: VC: handle mutant channel config for OMAP4 MPU channel
On OMAP3+, all VC channels have the the same bitfield ordering for all
VC channels, except the OMAP4 MPU channel. This appears to be a freak
accident as all other VC channel (including OMAP5) have the standard
configuration. Handle the mutant case by adding a per-channel flag
to signal the deformity and handle it during VC init.
Special thanks to Nishanth Menon <nm@ti.com> for finding this problem
and for proposing the initial solution.
Cc: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/vc.c | 64 | ||||
-rw-r--r-- | arch/arm/mach-omap2/vc.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/vc44xx_data.c | 2 |
3 files changed, 53 insertions, 14 deletions
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c index 5d545632388d..f53d1f5acce1 100644 --- a/arch/arm/mach-omap2/vc.c +++ b/arch/arm/mach-omap2/vc.c | |||
@@ -19,17 +19,51 @@ | |||
19 | #include "prm-regbits-44xx.h" | 19 | #include "prm-regbits-44xx.h" |
20 | #include "prm44xx.h" | 20 | #include "prm44xx.h" |
21 | 21 | ||
22 | /* | 22 | /** |
23 | * Channel configuration bits, common for OMAP3 & 4 | 23 | * struct omap_vc_channel_cfg - describe the cfg_channel bitfield |
24 | * @sa: bit for slave address | ||
25 | * @rav: bit for voltage configuration register | ||
26 | * @rac: bit for command configuration register | ||
27 | * @racen: enable bit for RAC | ||
28 | * @cmd: bit for command value set selection | ||
29 | * | ||
30 | * Channel configuration bits, common for OMAP3+ | ||
24 | * OMAP3 register: PRM_VC_CH_CONF | 31 | * OMAP3 register: PRM_VC_CH_CONF |
25 | * OMAP4 register: PRM_VC_CFG_CHANNEL | 32 | * OMAP4 register: PRM_VC_CFG_CHANNEL |
33 | * OMAP5 register: PRM_VC_SMPS_<voltdm>_CONFIG | ||
26 | */ | 34 | */ |
27 | #define CFG_CHANNEL_SA BIT(0) | 35 | struct omap_vc_channel_cfg { |
28 | #define CFG_CHANNEL_RAV BIT(1) | 36 | u8 sa; |
29 | #define CFG_CHANNEL_RAC BIT(2) | 37 | u8 rav; |
30 | #define CFG_CHANNEL_RACEN BIT(3) | 38 | u8 rac; |
31 | #define CFG_CHANNEL_CMD BIT(4) | 39 | u8 racen; |
32 | #define CFG_CHANNEL_MASK 0x3f | 40 | u8 cmd; |
41 | }; | ||
42 | |||
43 | static struct omap_vc_channel_cfg vc_default_channel_cfg = { | ||
44 | .sa = BIT(0), | ||
45 | .rav = BIT(1), | ||
46 | .rac = BIT(2), | ||
47 | .racen = BIT(3), | ||
48 | .cmd = BIT(4), | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * On OMAP3+, all VC channels have the above default bitfield | ||
53 | * configuration, except the OMAP4 MPU channel. This appears | ||
54 | * to be a freak accident as every other VC channel has the | ||
55 | * default configuration, thus creating a mutant channel config. | ||
56 | */ | ||
57 | static struct omap_vc_channel_cfg vc_mutant_channel_cfg = { | ||
58 | .sa = BIT(0), | ||
59 | .rav = BIT(2), | ||
60 | .rac = BIT(3), | ||
61 | .racen = BIT(4), | ||
62 | .cmd = BIT(1), | ||
63 | }; | ||
64 | |||
65 | static struct omap_vc_channel_cfg *vc_cfg_bits; | ||
66 | #define CFG_CHANNEL_MASK 0x1f | ||
33 | 67 | ||
34 | /** | 68 | /** |
35 | * omap_vc_config_channel - configure VC channel to PMIC mappings | 69 | * omap_vc_config_channel - configure VC channel to PMIC mappings |
@@ -56,7 +90,7 @@ static int omap_vc_config_channel(struct voltagedomain *voltdm) | |||
56 | * All others must stay at zero (see function comment above.) | 90 | * All others must stay at zero (see function comment above.) |
57 | */ | 91 | */ |
58 | if (vc->flags & OMAP_VC_CHANNEL_DEFAULT) | 92 | if (vc->flags & OMAP_VC_CHANNEL_DEFAULT) |
59 | vc->cfg_channel &= CFG_CHANNEL_RACEN; | 93 | vc->cfg_channel &= vc_cfg_bits->racen; |
60 | 94 | ||
61 | voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift, | 95 | voltdm->rmw(CFG_CHANNEL_MASK << vc->cfg_channel_sa_shift, |
62 | vc->cfg_channel << vc->cfg_channel_sa_shift, | 96 | vc->cfg_channel << vc->cfg_channel_sa_shift, |
@@ -292,6 +326,10 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm) | |||
292 | } | 326 | } |
293 | 327 | ||
294 | vc->cfg_channel = 0; | 328 | vc->cfg_channel = 0; |
329 | if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT) | ||
330 | vc_cfg_bits = &vc_mutant_channel_cfg; | ||
331 | else | ||
332 | vc_cfg_bits = &vc_default_channel_cfg; | ||
295 | 333 | ||
296 | /* get PMIC/board specific settings */ | 334 | /* get PMIC/board specific settings */ |
297 | vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr; | 335 | vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr; |
@@ -303,7 +341,7 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm) | |||
303 | voltdm->rmw(vc->smps_sa_mask, | 341 | voltdm->rmw(vc->smps_sa_mask, |
304 | vc->i2c_slave_addr << __ffs(vc->smps_sa_mask), | 342 | vc->i2c_slave_addr << __ffs(vc->smps_sa_mask), |
305 | vc->common->smps_sa_reg); | 343 | vc->common->smps_sa_reg); |
306 | vc->cfg_channel |= CFG_CHANNEL_SA; | 344 | vc->cfg_channel |= vc_cfg_bits->sa; |
307 | 345 | ||
308 | /* | 346 | /* |
309 | * Configure the PMIC register addresses. | 347 | * Configure the PMIC register addresses. |
@@ -311,13 +349,13 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm) | |||
311 | voltdm->rmw(vc->smps_volra_mask, | 349 | voltdm->rmw(vc->smps_volra_mask, |
312 | vc->volt_reg_addr << __ffs(vc->smps_volra_mask), | 350 | vc->volt_reg_addr << __ffs(vc->smps_volra_mask), |
313 | vc->common->smps_volra_reg); | 351 | vc->common->smps_volra_reg); |
314 | vc->cfg_channel |= CFG_CHANNEL_RAV; | 352 | vc->cfg_channel |= vc_cfg_bits->rav; |
315 | 353 | ||
316 | if (vc->cmd_reg_addr) { | 354 | if (vc->cmd_reg_addr) { |
317 | voltdm->rmw(vc->smps_cmdra_mask, | 355 | voltdm->rmw(vc->smps_cmdra_mask, |
318 | vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask), | 356 | vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask), |
319 | vc->common->smps_cmdra_reg); | 357 | vc->common->smps_cmdra_reg); |
320 | vc->cfg_channel |= CFG_CHANNEL_RAC | CFG_CHANNEL_RACEN; | 358 | vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen; |
321 | } | 359 | } |
322 | 360 | ||
323 | /* Set up the on, inactive, retention and off voltage */ | 361 | /* Set up the on, inactive, retention and off voltage */ |
@@ -330,7 +368,7 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm) | |||
330 | (ret_vsel << vc->common->cmd_ret_shift) | | 368 | (ret_vsel << vc->common->cmd_ret_shift) | |
331 | (off_vsel << vc->common->cmd_off_shift)); | 369 | (off_vsel << vc->common->cmd_off_shift)); |
332 | voltdm->write(val, vc->cmdval_reg); | 370 | voltdm->write(val, vc->cmdval_reg); |
333 | vc->cfg_channel |= CFG_CHANNEL_CMD; | 371 | vc->cfg_channel |= vc_cfg_bits->cmd; |
334 | 372 | ||
335 | /* Channel configuration */ | 373 | /* Channel configuration */ |
336 | omap_vc_config_channel(voltdm); | 374 | omap_vc_config_channel(voltdm); |
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h index c86301330b75..7ed70e07becf 100644 --- a/arch/arm/mach-omap2/vc.h +++ b/arch/arm/mach-omap2/vc.h | |||
@@ -66,6 +66,7 @@ struct omap_vc_common { | |||
66 | 66 | ||
67 | /* omap_vc_channel.flags values */ | 67 | /* omap_vc_channel.flags values */ |
68 | #define OMAP_VC_CHANNEL_DEFAULT BIT(0) | 68 | #define OMAP_VC_CHANNEL_DEFAULT BIT(0) |
69 | #define OMAP_VC_CHANNEL_CFG_MUTANT BIT(1) | ||
69 | 70 | ||
70 | /** | 71 | /** |
71 | * struct omap_vc_channel - VC per-instance data | 72 | * struct omap_vc_channel - VC per-instance data |
diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c index 148be18397f8..0a4fc37877cc 100644 --- a/arch/arm/mach-omap2/vc44xx_data.c +++ b/arch/arm/mach-omap2/vc44xx_data.c | |||
@@ -52,7 +52,7 @@ static const struct omap_vc_common omap4_vc_common = { | |||
52 | 52 | ||
53 | /* VC instance data for each controllable voltage line */ | 53 | /* VC instance data for each controllable voltage line */ |
54 | struct omap_vc_channel omap4_vc_mpu = { | 54 | struct omap_vc_channel omap4_vc_mpu = { |
55 | .flags = OMAP_VC_CHANNEL_DEFAULT, | 55 | .flags = OMAP_VC_CHANNEL_DEFAULT | OMAP_VC_CHANNEL_CFG_MUTANT, |
56 | .common = &omap4_vc_common, | 56 | .common = &omap4_vc_common, |
57 | .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET, | 57 | .cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET, |
58 | .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK, | 58 | .smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK, |