ARM: OMAP5: DRA7xx: Add support for power rail grouping
authorLubomir Popov <lpopov@mm-sol.com>
Fri, 19 Dec 2014 15:34:31 +0000 (17:34 +0200)
committerTom Rini <trini@ti.com>
Thu, 29 Jan 2015 17:00:49 +0000 (12:00 -0500)
On the DRA72x (J6Eco) EVM one PMIC SMPS is powering three SoC
core rails. This concept of using one SMPS to supply multiple
core domains (in various, although limited combinations, per
primary device use case) has now become common and is used by
many customer J6/J6Eco designs; it is supported by a number of
corresponding PMIC OTP versions.

This patch implements correct operation of the core voltages
scaling routine by ensuring that each SMPS that is supplying
more than one domain shall be written only once, and with the
highest voltage of those fused in the SoC (or of those defined
in the corresponding header if fuse read is disabled or fails)
for the power rails belonging to the group.

The patch also replaces some PMIC-related magic numbers with
the appropriate definitions. The default OPP_NOM voltages for
the DRA7xx SoCs are updated as well, per the latest DMs.

Signed-off-by: Lubomir Popov <l-popov@ti.com>
arch/arm/cpu/armv7/omap-common/clocks-common.c
arch/arm/cpu/armv7/omap5/hw_data.c
arch/arm/include/asm/arch-omap5/clock.h

index 8e7411d43781186bee0ceed9159394bafec63e6b..03674e609ffce42c28eea7ee88539308a65b5c73 100644 (file)
@@ -437,12 +437,15 @@ void do_scale_vcore(u32 vcore_reg, u32 volt_mv, struct pmic_data *pmic)
 {
        u32 offset_code;
        u32 offset = volt_mv;
+#ifndef        CONFIG_DRA7XX
        int ret = 0;
+#endif
 
        if (!volt_mv)
                return;
 
        pmic->pmic_bus_init();
+#ifndef        CONFIG_DRA7XX
        /* See if we can first get the GPIO if needed */
        if (pmic->gpio_en)
                ret = gpio_request(pmic->gpio, "PMIC_GPIO");
@@ -456,7 +459,7 @@ void do_scale_vcore(u32 vcore_reg, u32 volt_mv, struct pmic_data *pmic)
        /* Pull the GPIO low to select SET0 register, while we program SET1 */
        if (pmic->gpio_en)
                gpio_direction_output(pmic->gpio, 0);
-
+#endif
        /* convert to uV for better accuracy in the calculations */
        offset *= 1000;
 
@@ -467,9 +470,10 @@ void do_scale_vcore(u32 vcore_reg, u32 volt_mv, struct pmic_data *pmic)
 
        if (pmic->pmic_write(pmic->i2c_slave_addr, vcore_reg, offset_code))
                printf("Scaling voltage failed for 0x%x\n", vcore_reg);
-
+#ifndef        CONFIG_DRA7XX
        if (pmic->gpio_en)
                gpio_direction_output(pmic->gpio, 1);
+#endif
 }
 
 static u32 optimize_vcore_voltage(struct volts const *v)
@@ -505,13 +509,79 @@ static u32 optimize_vcore_voltage(struct volts const *v)
 }
 
 /*
- * Setup the voltages for vdd_mpu, vdd_core, and vdd_iva
- * We set the maximum voltages allowed here because Smart-Reflex is not
- * enabled in bootloader. Voltage initialization in the kernel will set
- * these to the nominal values after enabling Smart-Reflex
+ * Setup the voltages for the main SoC core power domains.
+ * We start with the maximum voltages allowed here, as set in the corresponding
+ * vcores_data struct, and then scale (usually down) to the fused values that
+ * are retrieved from the SoC. The scaling happens only if the efuse.reg fields
+ * are initialised.
+ * Rail grouping is supported for the DRA7xx SoCs only, therefore the code is
+ * compiled conditionally. Note that the new code writes the scaled (or zeroed)
+ * values back to the vcores_data struct for eventual reuse. Zero values mean
+ * that the corresponding rails are not controlled separately, and are not sent
+ * to the PMIC.
  */
 void scale_vcores(struct vcores_data const *vcores)
 {
+#if defined(CONFIG_DRA7XX)
+       int i;
+       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) {
+                       /* Handle non-empty members only */
+                       pv->value = optimize_vcore_voltage(pv);
+                       px = (struct volts *)vcores;
+                       while (px < pv) {
+                               /*
+                                * Scan already handled non-empty members to see
+                                * if we have a group and find the max voltage,
+                                * which is set to the first occurance of the
+                                * 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;
+                                       }
+                               }
+                               px++;
+                       }
+               }
+               debug("%d\n", pv->value);
+               pv++;
+       }
+
+       debug("cor: %d\n", vcores->core.value);
+       do_scale_vcore(vcores->core.addr, vcores->core.value, vcores->core.pmic);
+       debug("mpu: %d\n", vcores->mpu.value);
+       do_scale_vcore(vcores->mpu.addr, vcores->mpu.value, vcores->mpu.pmic);
+       /* Configure MPU ABB LDO after scale */
+       abb_setup((*ctrl)->control_std_fuse_opp_vdd_mpu_2,
+                 (*ctrl)->control_wkup_ldovbb_mpu_voltage_ctrl,
+                 (*prcm)->prm_abbldo_mpu_setup,
+                 (*prcm)->prm_abbldo_mpu_ctrl,
+                 (*prcm)->prm_irqstatus_mpu_2,
+                 OMAP_ABB_MPU_TXDONE_MASK,
+                 OMAP_ABB_FAST_OPP);
+
+       /* The .mm member is not used for the DRA7xx */
+
+       debug("gpu: %d\n", vcores->gpu.value);
+       do_scale_vcore(vcores->gpu.addr, vcores->gpu.value, vcores->gpu.pmic);
+       debug("eve: %d\n", vcores->eve.value);
+       do_scale_vcore(vcores->eve.addr, vcores->eve.value, vcores->eve.pmic);
+       debug("iva: %d\n", vcores->iva.value);
+       do_scale_vcore(vcores->iva.addr, vcores->iva.value, vcores->iva.pmic);
+       /* Might need udelay(1000) here if debug is enabled to see all prints */
+#else
        u32 val;
 
        val = optimize_vcore_voltage(&vcores->core);
@@ -540,6 +610,7 @@ void scale_vcores(struct vcores_data const *vcores)
 
        val = optimize_vcore_voltage(&vcores->iva);
        do_scale_vcore(vcores->iva.addr, val, vcores->iva.pmic);
+#endif
 }
 
 static inline void enable_clock_domain(u32 const clkctrl_reg, u32 enable_mode)
index 95f16866e6cbd9e043dcdf969a937e648bbd13a8..b9734fea8febaea9cf3cd805c4090a038d5337e0 100644 (file)
@@ -320,6 +320,7 @@ struct pmic_data palmas = {
        .pmic_write     = omap_vc_bypass_send_value,
 };
 
+/* The TPS659038 and TPS65917 are software-compatible, use common struct */
 struct pmic_data tps659038 = {
        .base_offset = PALMAS_SMPS_BASE_VOLT_UV,
        .step = 10000, /* 10 mV represented in uV */
@@ -394,34 +395,38 @@ struct vcores_data dra752_volts = {
 };
 
 struct vcores_data dra722_volts = {
-       .mpu.value      = 1000,
+       .mpu.value      = VDD_MPU_DRA72x,
        .mpu.efuse.reg  = STD_FUSE_OPP_VMIN_MPU_NOM,
-       .mpu.efuse.reg_bits     = DRA752_EFUSE_REGBITS,
-       .mpu.addr       = 0x23,
+       .mpu.efuse.reg_bits = DRA752_EFUSE_REGBITS,
+       .mpu.addr       = TPS65917_REG_ADDR_SMPS1,
        .mpu.pmic       = &tps659038,
 
-       .eve.value      = 1000,
-       .eve.efuse.reg  = STD_FUSE_OPP_VMIN_DSPEVE_NOM,
-       .eve.efuse.reg_bits     = DRA752_EFUSE_REGBITS,
-       .eve.addr       = 0x2f,
-       .eve.pmic       = &tps659038,
+       .core.value     = VDD_CORE_DRA72x,
+       .core.efuse.reg = STD_FUSE_OPP_VMIN_CORE_NOM,
+       .core.efuse.reg_bits = DRA752_EFUSE_REGBITS,
+       .core.addr      = TPS65917_REG_ADDR_SMPS2,
+       .core.pmic      = &tps659038,
 
-       .gpu.value      = 1000,
+       /*
+        * The DSPEVE, GPU and IVA rails are usually grouped on DRA72x
+        * designs and powered by TPS65917 SMPS3, as on the J6Eco EVM.
+        */
+       .gpu.value      = VDD_GPU_DRA72x,
        .gpu.efuse.reg  = STD_FUSE_OPP_VMIN_GPU_NOM,
-       .gpu.efuse.reg_bits     = DRA752_EFUSE_REGBITS,
-       .gpu.addr       = 0x2f,
+       .gpu.efuse.reg_bits = DRA752_EFUSE_REGBITS,
+       .gpu.addr       = TPS65917_REG_ADDR_SMPS3,
        .gpu.pmic       = &tps659038,
 
-       .core.value     = 1000,
-       .core.efuse.reg = STD_FUSE_OPP_VMIN_CORE_NOM,
-       .core.efuse.reg_bits = DRA752_EFUSE_REGBITS,
-       .core.addr      = 0x27,
-       .core.pmic      = &tps659038,
+       .eve.value      = VDD_EVE_DRA72x,
+       .eve.efuse.reg  = STD_FUSE_OPP_VMIN_DSPEVE_NOM,
+       .eve.efuse.reg_bits = DRA752_EFUSE_REGBITS,
+       .eve.addr       = TPS65917_REG_ADDR_SMPS3,
+       .eve.pmic       = &tps659038,
 
-       .iva.value      = 1000,
+       .iva.value      = VDD_IVA_DRA72x,
        .iva.efuse.reg  = STD_FUSE_OPP_VMIN_IVA_NOM,
-       .iva.efuse.reg_bits     = DRA752_EFUSE_REGBITS,
-       .iva.addr       = 0x2f,
+       .iva.efuse.reg_bits = DRA752_EFUSE_REGBITS,
+       .iva.addr       = TPS65917_REG_ADDR_SMPS3,
        .iva.pmic       = &tps659038,
 };
 
index 0dc584b8ce68a6d38ba8a711b68fa3bd7842652a..f8e5630bcb4214a44cddf180296eb6b38bc7db0c 100644 (file)
 #define VDD_MPU_ES2_LOW 880
 #define VDD_MM_ES2_LOW 880
 
-/* TPS659038 Voltage settings in mv for OPP_NOMINAL */
-#define VDD_MPU_DRA752         1090
+/* DRA74x/75x voltage settings in mv for OPP_NOM per DM */
+#define VDD_MPU_DRA752         1100
 #define VDD_EVE_DRA752         1060
 #define VDD_GPU_DRA752         1060
-#define VDD_CORE_DRA752                1030
+#define VDD_CORE_DRA752                1060
 #define VDD_IVA_DRA752         1060
 
+/* DRA72x voltage settings in mv for OPP_NOM per DM */
+#define VDD_MPU_DRA72x         1100
+#define VDD_EVE_DRA72x         1060
+#define VDD_GPU_DRA72x         1060
+#define VDD_CORE_DRA72x                1060
+#define VDD_IVA_DRA72x         1060
+
 /* Efuse register offsets for DRA7xx platform */
 #define DRA752_EFUSE_BASE      0x4A002000
 #define DRA752_EFUSE_REGBITS   16
 #define TPS659038_REG_ADDR_SMPS7               0x33
 #define TPS659038_REG_ADDR_SMPS8               0x37
 
+/* TPS65917 */
+#define TPS65917_I2C_SLAVE_ADDR                0x58
+#define TPS65917_REG_ADDR_SMPS1                0x23
+#define TPS65917_REG_ADDR_SMPS2                0x27
+#define TPS65917_REG_ADDR_SMPS3                0x2F
+
+
 /* TPS */
 #define TPS62361_I2C_SLAVE_ADDR                0x60
 #define TPS62361_REG_ADDR_SET0         0x0