From b558af81281975d032c063ad228a400d8e619ad5 Mon Sep 17 00:00:00 2001 From: Lubomir Popov Date: Fri, 19 Dec 2014 17:34:31 +0200 Subject: ARM: OMAP5: DRA7xx: Add support for power rail grouping 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 --- arch/arm/cpu/armv7/omap-common/clocks-common.c | 83 ++++++++++++++++++++++++-- arch/arm/cpu/armv7/omap5/hw_data.c | 43 +++++++------ arch/arm/include/asm/arch-omap5/clock.h | 20 ++++++- 3 files changed, 118 insertions(+), 28 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/omap-common/clocks-common.c b/arch/arm/cpu/armv7/omap-common/clocks-common.c index 8e7411d..03674e6 100644 --- a/arch/arm/cpu/armv7/omap-common/clocks-common.c +++ b/arch/arm/cpu/armv7/omap-common/clocks-common.c @@ -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) diff --git a/arch/arm/cpu/armv7/omap5/hw_data.c b/arch/arm/cpu/armv7/omap5/hw_data.c index 95f1686..b9734fe 100644 --- a/arch/arm/cpu/armv7/omap5/hw_data.c +++ b/arch/arm/cpu/armv7/omap5/hw_data.c @@ -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, }; diff --git a/arch/arm/include/asm/arch-omap5/clock.h b/arch/arm/include/asm/arch-omap5/clock.h index 0dc584b..f8e5630 100644 --- a/arch/arm/include/asm/arch-omap5/clock.h +++ b/arch/arm/include/asm/arch-omap5/clock.h @@ -236,13 +236,20 @@ #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 @@ -284,6 +291,13 @@ #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 -- cgit v1.1