aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorKevin Hilman <khilman@ti.com>2011-06-02 20:28:13 -0400
committerKevin Hilman <khilman@ti.com>2011-09-15 15:08:58 -0400
commit8abc0b58fdb89124d8278f110f523b27c666d36c (patch)
tree7f48f3ab775b32adb21f1a1941fdeb18bd0e23e8 /arch/arm/mach-omap2
parentf5395480f5088a86cc8594d29b5c2f07f6995c3d (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.c64
-rw-r--r--arch/arm/mach-omap2/vc.h1
-rw-r--r--arch/arm/mach-omap2/vc44xx_data.c2
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) 35struct 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
43static 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 */
57static 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
65static 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 */
54struct omap_vc_channel omap4_vc_mpu = { 54struct 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,