summaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorLokesh Vutla <lokeshvutla@ti.com>2016-11-23 12:54:39 +0530
committerTom Rini <trini@konsulko.com>2016-12-04 13:54:48 -0500
commitbeb71279d865deb77b2faa86d7d1d180df8339a0 (patch)
tree7c9c9969c2bfd9cfed3de41ad38cfd0836a14e10 /arch/arm/mach-omap2
parentf2388331026dec9526915ae3ea92ba3538830548 (diff)
ARM: OMAP4+: Add support for dynamically selecting OPPs
It can be expected that different paper spins of a SoC can have different definitions for OPP and can have their own constraints on the boot up OPP for each voltage rail. In order to have this flexibility, add support for dynamically selecting the OPP voltage based on the board to handle any such exceptions. Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com> Reviewed-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/clocks-common.c116
-rw-r--r--arch/arm/mach-omap2/omap4/hw_data.c24
-rw-r--r--arch/arm/mach-omap2/omap5/hw_data.c12
3 files changed, 90 insertions, 62 deletions
diff --git a/arch/arm/mach-omap2/clocks-common.c b/arch/arm/mach-omap2/clocks-common.c
index 9b97583104..84f93e73f6 100644
--- a/arch/arm/mach-omap2/clocks-common.c
+++ b/arch/arm/mach-omap2/clocks-common.c
@@ -477,35 +477,45 @@ void do_scale_vcore(u32 vcore_reg, u32 volt_mv, struct pmic_data *pmic)
gpio_direction_output(pmic->gpio, 1);
}
-static u32 optimize_vcore_voltage(struct volts const *v)
+int __weak get_voltrail_opp(int rail_offset)
+{
+ /*
+ * By default return OPP_NOM for all voltage rails.
+ */
+ return OPP_NOM;
+}
+
+static u32 optimize_vcore_voltage(struct volts const *v, int opp)
{
u32 val;
- if (!v->value)
+
+ if (!v->value[opp])
return 0;
- if (!v->efuse.reg)
- return v->value;
+ if (!v->efuse.reg[opp])
+ return v->value[opp];
switch (v->efuse.reg_bits) {
case 16:
- val = readw(v->efuse.reg);
+ val = readw(v->efuse.reg[opp]);
break;
case 32:
- val = readl(v->efuse.reg);
+ val = readl(v->efuse.reg[opp]);
break;
default:
printf("Error: efuse 0x%08x bits=%d unknown\n",
- v->efuse.reg, v->efuse.reg_bits);
- return v->value;
+ v->efuse.reg[opp], v->efuse.reg_bits);
+ return v->value[opp];
}
if (!val) {
printf("Error: efuse 0x%08x bits=%d val=0, using %d\n",
- v->efuse.reg, v->efuse.reg_bits, v->value);
- return v->value;
+ v->efuse.reg[opp], v->efuse.reg_bits, v->value[opp]);
+ return v->value[opp];
}
debug("%s:efuse 0x%08x bits=%d Vnom=%d, using efuse value %d\n",
- __func__, v->efuse.reg, v->efuse.reg_bits, v->value, val);
+ __func__, v->efuse.reg[opp], v->efuse.reg_bits, v->value[opp],
+ val);
return val;
}
@@ -529,16 +539,19 @@ void __weak recalibrate_iodelay(void)
*/
void scale_vcores(struct vcores_data const *vcores)
{
- int i;
+ int i, opp, j, ol;
struct volts *pv = (struct volts *)vcores;
struct volts *px;
for (i=0; i<(sizeof(struct vcores_data)/sizeof(struct volts)); i++) {
- debug("%d -> ", pv->value);
- if (pv->value) {
+ opp = get_voltrail_opp(i);
+ debug("%d -> ", pv->value[opp]);
+
+ if (pv->value[opp]) {
/* Handle non-empty members only */
- pv->value = optimize_vcore_voltage(pv);
+ pv->value[opp] = optimize_vcore_voltage(pv, opp);
px = (struct volts *)vcores;
+ j = 0;
while (px < pv) {
/*
* Scan already handled non-empty members to see
@@ -547,26 +560,29 @@ void scale_vcores(struct vcores_data const *vcores)
* particular SMPS; the other group voltages are
* zeroed.
*/
- if (px->value) {
- if ((pv->pmic->i2c_slave_addr ==
- px->pmic->i2c_slave_addr) &&
- (pv->addr == px->addr)) {
- /* Same PMIC, same SMPS */
- if (pv->value > px->value)
- px->value = pv->value;
-
- pv->value = 0;
- }
- }
+ ol = get_voltrail_opp(j);
+ if (px->value[ol] &&
+ (pv->pmic->i2c_slave_addr ==
+ px->pmic->i2c_slave_addr) &&
+ (pv->addr == px->addr)) {
+ /* Same PMIC, same SMPS */
+ if (pv->value[opp] > px->value[ol])
+ px->value[ol] = pv->value[opp];
+
+ pv->value[opp] = 0;
+ }
px++;
+ j++;
}
}
- debug("%d\n", pv->value);
+ debug("%d\n", pv->value[opp]);
pv++;
}
- debug("cor: %d\n", vcores->core.value);
- do_scale_vcore(vcores->core.addr, vcores->core.value, vcores->core.pmic);
+ opp = get_voltrail_opp(VOLT_CORE);
+ debug("cor: %d\n", vcores->core.value[opp]);
+ do_scale_vcore(vcores->core.addr, vcores->core.value[opp],
+ vcores->core.pmic);
/*
* IO delay recalibration should be done immediately after
* adjusting AVS voltages for VDD_CORE_L.
@@ -577,10 +593,12 @@ void scale_vcores(struct vcores_data const *vcores)
recalibrate_iodelay();
#endif
- debug("mpu: %d\n", vcores->mpu.value);
- do_scale_vcore(vcores->mpu.addr, vcores->mpu.value, vcores->mpu.pmic);
+ opp = get_voltrail_opp(VOLT_MPU);
+ debug("mpu: %d\n", vcores->mpu.value[opp]);
+ do_scale_vcore(vcores->mpu.addr, vcores->mpu.value[opp],
+ vcores->mpu.pmic);
/* Configure MPU ABB LDO after scale */
- abb_setup(vcores->mpu.efuse.reg,
+ abb_setup(vcores->mpu.efuse.reg[opp],
(*ctrl)->control_wkup_ldovbb_mpu_voltage_ctrl,
(*prcm)->prm_abbldo_mpu_setup,
(*prcm)->prm_abbldo_mpu_ctrl,
@@ -588,10 +606,12 @@ void scale_vcores(struct vcores_data const *vcores)
vcores->mpu.abb_tx_done_mask,
OMAP_ABB_FAST_OPP);
- debug("mm: %d\n", vcores->mm.value);
- do_scale_vcore(vcores->mm.addr, vcores->mm.value, vcores->mm.pmic);
+ opp = get_voltrail_opp(VOLT_MM);
+ debug("mm: %d\n", vcores->mm.value[opp]);
+ do_scale_vcore(vcores->mm.addr, vcores->mm.value[opp],
+ vcores->mm.pmic);
/* Configure MM ABB LDO after scale */
- abb_setup(vcores->mm.efuse.reg,
+ abb_setup(vcores->mm.efuse.reg[opp],
(*ctrl)->control_wkup_ldovbb_mm_voltage_ctrl,
(*prcm)->prm_abbldo_mm_setup,
(*prcm)->prm_abbldo_mm_ctrl,
@@ -599,30 +619,38 @@ void scale_vcores(struct vcores_data const *vcores)
vcores->mm.abb_tx_done_mask,
OMAP_ABB_FAST_OPP);
- debug("gpu: %d\n", vcores->gpu.value);
- do_scale_vcore(vcores->gpu.addr, vcores->gpu.value, vcores->gpu.pmic);
+ opp = get_voltrail_opp(VOLT_GPU);
+ debug("gpu: %d\n", vcores->gpu.value[opp]);
+ do_scale_vcore(vcores->gpu.addr, vcores->gpu.value[opp],
+ vcores->gpu.pmic);
/* Configure GPU ABB LDO after scale */
- abb_setup(vcores->gpu.efuse.reg,
+ abb_setup(vcores->gpu.efuse.reg[opp],
(*ctrl)->control_wkup_ldovbb_gpu_voltage_ctrl,
(*prcm)->prm_abbldo_gpu_setup,
(*prcm)->prm_abbldo_gpu_ctrl,
(*prcm)->prm_irqstatus_mpu,
vcores->gpu.abb_tx_done_mask,
OMAP_ABB_FAST_OPP);
- debug("eve: %d\n", vcores->eve.value);
- do_scale_vcore(vcores->eve.addr, vcores->eve.value, vcores->eve.pmic);
+
+ opp = get_voltrail_opp(VOLT_EVE);
+ debug("eve: %d\n", vcores->eve.value[opp]);
+ do_scale_vcore(vcores->eve.addr, vcores->eve.value[opp],
+ vcores->eve.pmic);
/* Configure EVE ABB LDO after scale */
- abb_setup(vcores->eve.efuse.reg,
+ abb_setup(vcores->eve.efuse.reg[opp],
(*ctrl)->control_wkup_ldovbb_eve_voltage_ctrl,
(*prcm)->prm_abbldo_eve_setup,
(*prcm)->prm_abbldo_eve_ctrl,
(*prcm)->prm_irqstatus_mpu,
vcores->eve.abb_tx_done_mask,
OMAP_ABB_FAST_OPP);
- debug("iva: %d\n", vcores->iva.value);
- do_scale_vcore(vcores->iva.addr, vcores->iva.value, vcores->iva.pmic);
+
+ opp = get_voltrail_opp(VOLT_IVA);
+ debug("iva: %d\n", vcores->iva.value[opp]);
+ do_scale_vcore(vcores->iva.addr, vcores->iva.value[opp],
+ vcores->iva.pmic);
/* Configure IVA ABB LDO after scale */
- abb_setup(vcores->iva.efuse.reg,
+ abb_setup(vcores->iva.efuse.reg[opp],
(*ctrl)->control_wkup_ldovbb_iva_voltage_ctrl,
(*prcm)->prm_abbldo_iva_setup,
(*prcm)->prm_abbldo_iva_ctrl,
diff --git a/arch/arm/mach-omap2/omap4/hw_data.c b/arch/arm/mach-omap2/omap4/hw_data.c
index 02c06c1577..6a4b8b93c0 100644
--- a/arch/arm/mach-omap2/omap4/hw_data.c
+++ b/arch/arm/mach-omap2/omap4/hw_data.c
@@ -261,43 +261,43 @@ struct pmic_data tps62361 = {
};
struct vcores_data omap4430_volts_es1 = {
- .mpu.value = 1325,
+ .mpu.value[OPP_NOM] = 1325,
.mpu.addr = SMPS_REG_ADDR_VCORE1,
.mpu.pmic = &twl6030_4430es1,
- .core.value = 1200,
+ .core.value[OPP_NOM] = 1200,
.core.addr = SMPS_REG_ADDR_VCORE3,
.core.pmic = &twl6030_4430es1,
- .mm.value = 1200,
+ .mm.value[OPP_NOM] = 1200,
.mm.addr = SMPS_REG_ADDR_VCORE2,
.mm.pmic = &twl6030_4430es1,
};
struct vcores_data omap4430_volts = {
- .mpu.value = 1325,
+ .mpu.value[OPP_NOM] = 1325,
.mpu.addr = SMPS_REG_ADDR_VCORE1,
.mpu.pmic = &twl6030,
- .core.value = 1200,
+ .core.value[OPP_NOM] = 1200,
.core.addr = SMPS_REG_ADDR_VCORE3,
.core.pmic = &twl6030,
- .mm.value = 1200,
+ .mm.value[OPP_NOM] = 1200,
.mm.addr = SMPS_REG_ADDR_VCORE2,
.mm.pmic = &twl6030,
};
struct vcores_data omap4460_volts = {
- .mpu.value = 1203,
+ .mpu.value[OPP_NOM] = 1203,
.mpu.addr = TPS62361_REG_ADDR_SET1,
.mpu.pmic = &tps62361,
- .core.value = 1200,
+ .core.value[OPP_NOM] = 1200,
.core.addr = SMPS_REG_ADDR_VCORE1,
.core.pmic = &twl6030,
- .mm.value = 1200,
+ .mm.value[OPP_NOM] = 1200,
.mm.addr = SMPS_REG_ADDR_VCORE2,
.mm.pmic = &twl6030,
};
@@ -307,15 +307,15 @@ struct vcores_data omap4460_volts = {
* voltage selection code. Aligned with OMAP4470 ES1.0 OCA V.0.7.
*/
struct vcores_data omap4470_volts = {
- .mpu.value = 1202,
+ .mpu.value[OPP_NOM] = 1202,
.mpu.addr = SMPS_REG_ADDR_SMPS1,
.mpu.pmic = &twl6030,
- .core.value = 1126,
+ .core.value[OPP_NOM] = 1126,
.core.addr = SMPS_REG_ADDR_SMPS2,
.core.pmic = &twl6030,
- .mm.value = 1139,
+ .mm.value[OPP_NOM] = 1139,
.mm.addr = SMPS_REG_ADDR_SMPS5,
.mm.pmic = &twl6030,
};
diff --git a/arch/arm/mach-omap2/omap5/hw_data.c b/arch/arm/mach-omap2/omap5/hw_data.c
index 02f086b2fb..c85c71a87c 100644
--- a/arch/arm/mach-omap2/omap5/hw_data.c
+++ b/arch/arm/mach-omap2/omap5/hw_data.c
@@ -337,30 +337,30 @@ struct pmic_data tps659038 = {
};
struct vcores_data omap5430_volts = {
- .mpu.value = VDD_MPU,
+ .mpu.value[OPP_NOM] = VDD_MPU,
.mpu.addr = SMPS_REG_ADDR_12_MPU,
.mpu.pmic = &palmas,
- .core.value = VDD_CORE,
+ .core.value[OPP_NOM] = VDD_CORE,
.core.addr = SMPS_REG_ADDR_8_CORE,
.core.pmic = &palmas,
- .mm.value = VDD_MM,
+ .mm.value[OPP_NOM] = VDD_MM,
.mm.addr = SMPS_REG_ADDR_45_IVA,
.mm.pmic = &palmas,
};
struct vcores_data omap5430_volts_es2 = {
- .mpu.value = VDD_MPU_ES2,
+ .mpu.value[OPP_NOM] = VDD_MPU_ES2,
.mpu.addr = SMPS_REG_ADDR_12_MPU,
.mpu.pmic = &palmas,
.mpu.abb_tx_done_mask = OMAP_ABB_MPU_TXDONE_MASK,
- .core.value = VDD_CORE_ES2,
+ .core.value[OPP_NOM] = VDD_CORE_ES2,
.core.addr = SMPS_REG_ADDR_8_CORE,
.core.pmic = &palmas,
- .mm.value = VDD_MM_ES2,
+ .mm.value[OPP_NOM] = VDD_MM_ES2,
.mm.addr = SMPS_REG_ADDR_45_IVA,
.mm.pmic = &palmas,
.mm.abb_tx_done_mask = OMAP_ABB_MM_TXDONE_MASK,