[U-Boot] [PATCH 1/5] pmic: pmic_mc34vr500: Add a driver for the mc34vr500 pmic

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
This patch adds a simple pmic driver for the mc34vr500 pmic which is used in conjunction with the fsl T1 and LS1 series SoC.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- drivers/power/pmic/Kconfig | 7 ++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pmic_mc34vr500.c | 32 +++++++ include/power/mc34vr500_pmic.h | 166 ++++++++++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+) create mode 100644 drivers/power/pmic/pmic_mc34vr500.c create mode 100644 include/power/mc34vr500_pmic.h
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index ce204b3..73e1d53 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -157,3 +157,10 @@ config PMIC_LP873X ---help--- The LP873X is a PMIC containing couple of LDOs and couple of SMPS. This driver binds the pmic children. + +config POWER_MC34VR500 + bool "Enable driver for Freescale MC34VR500 PMIC" + ---help--- + The MC34VR500 is used in conjunction with the FSL T1 and LS1 series + SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed + via an I2C interface. diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index cd1c694..58d0241 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_POWER_TPS65218) += pmic_tps62362.o obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o obj-$(CONFIG_POWER_TPS65910) += pmic_tps65910.o obj-$(CONFIG_POWER_HI6553) += pmic_hi6553.o +obj-$(CONFIG_POWER_MC34VR500) += pmic_mc34vr500.o diff --git a/drivers/power/pmic/pmic_mc34vr500.c b/drivers/power/pmic/pmic_mc34vr500.c new file mode 100644 index 0000000..db9e210 --- /dev/null +++ b/drivers/power/pmic/pmic_mc34vr500.c @@ -0,0 +1,32 @@ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * Hou Zhiqiang Zhiqiang.Hou@freescale.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <i2c.h> +#include <power/pmic.h> +#include <power/mc34vr500_pmic.h> + +int power_mc34vr500_init(unsigned char bus) +{ + static const char name[] = "MC34VR500"; + struct pmic *p = pmic_alloc(); + + if (!p) { + printf("%s: POWER allocation error!\n", __func__); + return -ENOMEM; + } + + p->name = name; + p->interface = PMIC_I2C; + p->number_of_regs = MC34VR500_NUM_OF_REGS; + p->hw.i2c.addr = MC34VR500_I2C_ADDR; + p->hw.i2c.tx_num = 1; + p->bus = bus; + + return 0; +} diff --git a/include/power/mc34vr500_pmic.h b/include/power/mc34vr500_pmic.h new file mode 100644 index 0000000..df4985a --- /dev/null +++ b/include/power/mc34vr500_pmic.h @@ -0,0 +1,166 @@ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * Hou Zhiqiang Zhiqiang.Hou@freescale.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __MC34VR500_H_ +#define __MC34VR500_H_ + +#include <power/pmic.h> + +#define MC34VR500_I2C_ADDR 0x08 + +/* Drivers name */ +#define MC34VR500_REGULATOR_DRIVER "mc34vr500_regulator" + +/* Register map */ +enum { + MC34VR500_DEVICEID = 0x00, + + MC34VR500_SILICONREVID = 0x03, + MC34VR500_FABID, + MC34VR500_INTSTAT0, + MC34VR500_INTMASK0, + MC34VR500_INTSENSE0, + MC34VR500_INTSTAT1, + MC34VR500_INTMASK1, + MC34VR500_INTSENSE1, + + MC34VR500_INTSTAT4 = 0x11, + MC34VR500_INTMASK4, + MC34VR500_INTSENSE4, + + MC34VR500_PWRCTL = 0x1B, + + MC34VR500_SW1VOLT = 0x2E, + MC34VR500_SW1STBY, + MC34VR500_SW1OFF, + MC34VR500_SW1MODE, + MC34VR500_SW1CONF, + MC34VR500_SW2VOLT, + MC34VR500_SW2STBY, + MC34VR500_SW2OFF, + MC34VR500_SW2MODE, + MC34VR500_SW2CONF, + + MC34VR500_SW3VOLT = 0x3C, + MC34VR500_SW3STBY, + MC34VR500_SW3OFF, + MC34VR500_SW3MODE, + MC34VR500_SW3CONF, + + MC34VR500_SW4VOLT = 0x4A, + MC34VR500_SW4STBY, + MC34VR500_SW4OFF, + MC34VR500_SW4MODE, + MC34VR500_SW4CONF, + + MC34VR500_REFOUTCRTRL = 0x6A, + + MC34VR500_LDO1CTL = 0x6D, + MC34VR500_LDO2CTL, + MC34VR500_LDO3CTL, + MC34VR500_LDO4CTL, + MC34VR500_LDO5CTL, + + MC34VR500_PAGE_REGISTER = 0x7F, + + /* Internal RAM */ + MC34VR500_SW1_VOLT = 0xA8, + MC34VR500_SW1_SEQ, + MC34VR500_SW1_CONFIG, + + MC34VR500_SW2_VOLT = 0xAC, + MC34VR500_SW2_SEQ, + MC34VR500_SW2_CONFIG, + + MC34VR500_SW3_VOLT = 0xB0, + MC34VR500_SW3_SEQ, + MC34VR500_SW3_CONFIG, + + MC34VR500_SW4_VOLT = 0xB8, + MC34VR500_SW4_SEQ, + MC34VR500_SW4_CONFIG, + + MC34VR500_REFOUT_SEQ = 0xC4, + + MC34VR500_LDO1_VOLT = 0xCC, + MC34VR500_LDO1_SEQ, + + MC34VR500_LDO2_VOLT = 0xD0, + MC34VR500_LDO2_SEQ, + + MC34VR500_LDO3_VOLT = 0xD4, + MC34VR500_LDO3_SEQ, + + MC34VR500_LDO4_VOLT = 0xD8, + MC34VR500_LDO4_SEQ, + + MC34VR500_LDO5_VOLT = 0xDC, + MC34VR500_LDO5_SEQ, + + MC34VR500_PU_CONFIG1 = 0xE0, + + MC34VR500_TBB_POR = 0xE4, + + MC34VR500_PWRGD_EN = 0xE8, + + MC34VR500_NUM_OF_REGS, +}; + +/* Registor offset based on SWxVOLT register */ +#define MC34VR500_VOLT_OFFSET 0 +#define MC34VR500_STBY_OFFSET 1 +#define MC34VR500_OFF_OFFSET 2 +#define MC34VR500_MODE_OFFSET 3 +#define MC34VR500_CONF_OFFSET 4 + +#define SW_MODE_MASK 0xf +#define SW_MODE_SHIFT 0 + +#define LDO_VOL_MASK 0xf +#define LDO_EN (1 << 4) +#define LDO_MODE_SHIFT 4 +#define LDO_MODE_MASK (1 << 4) +#define LDO_MODE_OFF 0 +#define LDO_MODE_ON 1 + +#define REFOUTEN (1 << 4) + +/* + * Regulator Mode Control + * + * OFF: The regulator is switched off and the output voltage is discharged. + * PFM: In this mode, the regulator is always in PFM mode, which is useful + * at light loads for optimized efficiency. + * PWM: In this mode, the regulator is always in PWM mode operation + * regardless of load conditions. + * APS: In this mode, the regulator moves automatically between pulse + * skipping mode and PWM mode depending on load conditions. + * + * SWxMODE[3:0] + * Normal Mode | Standby Mode | value + * OFF OFF 0x0 + * PWM OFF 0x1 + * PFM OFF 0x3 + * APS OFF 0x4 + * PWM PWM 0x5 + * PWM APS 0x6 + * APS APS 0x8 + * APS PFM 0xc + * PWM PFM 0xd + */ +#define OFF_OFF 0x0 +#define PWM_OFF 0x1 +#define PFM_OFF 0x3 +#define APS_OFF 0x4 +#define PWM_PWM 0x5 +#define PWM_APS 0x6 +#define APS_APS 0x8 +#define APS_PFM 0xc +#define PWM_PFM 0xd + +int power_mc34vr500_init(unsigned char bus); +#endif /* __MC34VR500_PMIC_H_ */

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- board/freescale/common/Makefile | 1 + board/freescale/common/mc34vr500.c | 95 ++++++++++++++++++++++++++++++++++++++ include/power/mc34vr500_pmic.h | 9 ++++ 3 files changed, 105 insertions(+) create mode 100644 board/freescale/common/mc34vr500.c
diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile index be114ce..eea9514 100644 --- a/board/freescale/common/Makefile +++ b/board/freescale/common/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_VSC_CROSSBAR) += vsc3316_3308.o obj-$(CONFIG_IDT8T49N222A) += idt8t49n222a_serdes_clk.o obj-$(CONFIG_ZM7300) += zm7300.o obj-$(CONFIG_POWER_PFUZE100) += pfuze.o +obj-$(CONFIG_POWER_MC34VR500) += mc34vr500.o
obj-$(CONFIG_LS102XA_STREAM_ID) += ls102xa_stream_id.o
diff --git a/board/freescale/common/mc34vr500.c b/board/freescale/common/mc34vr500.c new file mode 100644 index 0000000..9c57569 --- /dev/null +++ b/board/freescale/common/mc34vr500.c @@ -0,0 +1,95 @@ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * Hou Zhiqiang Zhiqiang.Hou@freescale.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <i2c.h> +#include <power/pmic.h> +#include <power/mc34vr500_pmic.h> + +static uint8_t swxvolt_addr[4] = { MC34VR500_SW1VOLT, + MC34VR500_SW2VOLT, + MC34VR500_SW3VOLT, + MC34VR500_SW4VOLT }; + +static uint8_t swx_set_point_base[4] = { 13, 9, 9, 9 }; + +int mc34vr500_get_sw_volt(uint8_t sw) +{ + struct pmic *p; + u32 swxvolt; + uint8_t spb; + int sw_volt; + int ret; + + debug("%s: Get SW%u volt from swxvolt_addr = 0x%x\n", + __func__, sw + 1, swxvolt_addr[sw]); + if (sw > SW4) { + printf("%s: Unsupported SW(sw%d)\n", __func__, sw + 1); + return -EINVAL; + } + + p = pmic_get("MC34VR500"); + if (!p) { + printf("%s: Did NOT find PMIC MC34VR500\n", __func__); + return -ENODEV; + } + + ret = pmic_probe(p); + if (ret) + return ret; + + ret = pmic_reg_read(p, swxvolt_addr[sw], &swxvolt); + if (ret) { + printf("%s: Failed to get SW%u volt\n", __func__, sw + 1); + return ret; + } + + debug("%s: SW%d step point swxvolt = %u\n", __func__, sw + 1, swxvolt); + spb = swx_set_point_base[sw]; + /* The base of SW volt is 625mV and increase by step 25mV */ + sw_volt = 625 + (swxvolt - spb) * 25; + + debug("%s: SW%u volt = %dmV\n", __func__, sw + 1, sw_volt); + return sw_volt; +} + +int mc34vr500_set_sw_volt(uint8_t sw, int sw_volt) +{ + struct pmic *p; + u32 swxvolt; + uint8_t spb; + int ret; + + debug("%s: Set SW%u volt to %dmV\n", __func__, sw + 1, sw_volt); + /* The least SW volt is 625mV, and only 4 SW outputs */ + if (sw > SW4 || sw_volt < 625) + return -EINVAL; + + p = pmic_get("MC34VR500"); + if (!p) { + printf("%s: Did NOT find PMIC MC34VR500\n", __func__); + return -ENODEV; + } + + ret = pmic_probe(p); + if (ret) + return ret; + + spb = swx_set_point_base[sw]; + /* The base of SW volt is 625mV and increase by step 25mV */ + swxvolt = (sw_volt - 625) / 25 + spb; + debug("%s: SW%d step point swxvolt = %u\n", __func__, sw + 1, swxvolt); + if (swxvolt > 63) + return -EINVAL; + + ret = pmic_reg_write(p, swxvolt_addr[sw], swxvolt); + if (ret) + return ret; + + return 0; +} diff --git a/include/power/mc34vr500_pmic.h b/include/power/mc34vr500_pmic.h index df4985a..b0b143a 100644 --- a/include/power/mc34vr500_pmic.h +++ b/include/power/mc34vr500_pmic.h @@ -162,5 +162,14 @@ enum { #define APS_PFM 0xc #define PWM_PFM 0xd
+enum swx { + SW1 = 0, + SW2, + SW3, + SW4, +}; + +int mc34vr500_get_sw_volt(uint8_t sw); +int mc34vr500_set_sw_volt(uint8_t sw, int sw_volt); int power_mc34vr500_init(unsigned char bus); #endif /* __MC34VR500_PMIC_H_ */

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- board/freescale/ls1046ardb/cpld.c | 9 +++++++++ board/freescale/ls1046ardb/cpld.h | 1 + 2 files changed, 10 insertions(+)
diff --git a/board/freescale/ls1046ardb/cpld.c b/board/freescale/ls1046ardb/cpld.c index 81a646e..c0500f4 100644 --- a/board/freescale/ls1046ardb/cpld.c +++ b/board/freescale/ls1046ardb/cpld.c @@ -82,6 +82,15 @@ void cpld_set_sd(void)
CPLD_WRITE(system_rst, 1); } + +void cpld_select_core_volt(bool en_0v9) +{ + u8 reg17 = en_0v9; + + CPLD_WRITE(vdd_en, 1); + CPLD_WRITE(vdd_sel, reg17); +} + #ifdef DEBUG static void cpld_dump_regs(void) { diff --git a/board/freescale/ls1046ardb/cpld.h b/board/freescale/ls1046ardb/cpld.h index 458da7e..f6a1a61 100644 --- a/board/freescale/ls1046ardb/cpld.h +++ b/board/freescale/ls1046ardb/cpld.h @@ -35,6 +35,7 @@ struct cpld_data { u8 cpld_read(unsigned int reg); void cpld_write(unsigned int reg, u8 value); void cpld_rev_bit(unsigned char *value); +void cpld_select_core_volt(bool en_0v9);
#define CPLD_READ(reg) cpld_read(offsetof(struct cpld_data, reg)) #define CPLD_WRITE(reg, value) \

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Set up chip power supply voltage according to voltage ID. The fuse status register provides the values from on-chip voltage ID fuses programmed at the factory. These values define the voltage requirements for the chip.
Main operations: 1. Set up the core voltage 2. Set up the SERDES voltage and reset SERDES lanes 3. Enable/disable DDR controller support 0.9V if needed
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- .../cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c | 272 +++++++++++++++++++++ arch/arm/cpu/armv8/fsl-layerscape/soc.c | 89 +++++++ .../include/asm/arch-fsl-layerscape/fsl_serdes.h | 8 + arch/arm/include/asm/arch-fsl-layerscape/soc.h | 3 + include/fsl_ddr_sdram.h | 1 + 5 files changed, 373 insertions(+)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c index e06b063..c0b4d0a 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c @@ -129,6 +129,278 @@ void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift, serdes_prtcl_map[NONE] = 1; }
+__weak int get_serdes_volt(void) +{ + return -1; +} + +__weak int set_serdes_volt(int svdd) +{ + return -1; +} + +int setup_serdes_volt(u32 svdd) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + struct ccsr_serdes *serdes1_base; +#ifdef CONFIG_SYS_FSL_SRDS_2 + struct ccsr_serdes *serdes2_base; +#endif + u32 cfg_rcw4 = gur_in32(&gur->rcwsr[4]); + u32 cfg_rcw5 = gur_in32(&gur->rcwsr[5]); + u32 cfg_tmp, reg = 0; + int svdd_cur, svdd_tar; + int ret; + int i; + + /* Only support switch SVDD to 900mV/1000mV */ + if (svdd != 900 && svdd != 1000) + return -EINVAL; + + svdd_tar = svdd; + svdd_cur = get_serdes_volt(); + if (svdd_cur < 0) + return -EINVAL; + + debug("%s: current SVDD: %dmV; target SVDD: %dmV\n", + __func__, svdd_cur, svdd_tar); + if (svdd_cur == svdd_tar) + return 0; + + serdes1_base = (void *)CONFIG_SYS_FSL_SERDES_ADDR; +#ifdef CONFIG_SYS_FSL_SRDS_2 + serdes2_base = (void *)serdes1_base + 0x10000; +#endif + + /* Put the all enabled lanes in reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; + cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; + + for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) { + reg = in_be32(&serdes1_base->lane[i].gcr0); + reg &= 0xFF9FFFFF; + out_be32(&serdes1_base->lane[i].gcr0, reg); + } +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK; + cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT; + + for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) { + reg = in_be32(&serdes2_base->lane[i].gcr0); + reg &= 0xFF9FFFFF; + out_be32(&serdes2_base->lane[i].gcr0, reg); + } +#endif + + /* Put the all enabled PLL in reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = (cfg_rcw5 >> 22) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg &= 0xFFFFFFBF; + reg |= 0x10000000; + out_be32(&serdes1_base->bank[i].rstctl, reg); + udelay(1); + + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg &= 0xFFFFFF1F; + out_be32(&serdes1_base->bank[i].rstctl, reg); + } + udelay(1); +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = (cfg_rcw5 >> 20) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg &= 0xFFFFFFBF; + reg |= 0x10000000; + out_be32(&serdes2_base->bank[i].rstctl, reg); + udelay(1); + + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg &= 0xFFFFFF1F; + out_be32(&serdes2_base->bank[i].rstctl, reg); + } + udelay(1); +#endif + + /* Put the Rx/Tx calibration into reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + reg = in_be32(&serdes1_base->srdstcalcr); + reg &= 0xF7FFFFFF; + out_be32(&serdes1_base->srdstcalcr, reg); + reg = in_be32(&serdes1_base->srdsrcalcr); + reg &= 0xF7FFFFFF; + out_be32(&serdes1_base->srdsrcalcr, reg); + +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + reg = in_be32(&serdes2_base->srdstcalcr); + reg &= 0xF7FFFFFF; + out_be32(&serdes2_base->srdstcalcr, reg); + reg = in_be32(&serdes2_base->srdsrcalcr); + reg &= 0xF7FFFFFF; + out_be32(&serdes2_base->srdsrcalcr, reg); +#endif + + /* + * If SVDD set failed, will not return directly, so that the + * serdes lanes can complete reseting. + */ + ret = set_serdes_volt(svdd_tar); + if (ret) + printf("%s: Failed to set SVDD\n", __func__); + + /* Wait for SVDD to stabilize */ + udelay(100); + + /* For each PLL that’s not disabled via RCW */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = (cfg_rcw5 >> 22) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg |= 0x00000020; + out_be32(&serdes1_base->bank[i].rstctl, reg); + udelay(1); + + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg |= 0x00000080; + out_be32(&serdes1_base->bank[i].rstctl, reg); + + /* Take the Rx/Tx calibration out of reset */ + if (!(cfg_tmp == 0x3 && i == 1)) { + udelay(1); + reg = in_be32(&serdes1_base->srdstcalcr); + reg |= 0x08000000; + out_be32(&serdes1_base->srdstcalcr, reg); + reg = in_be32(&serdes1_base->srdsrcalcr); + reg |= 0x08000000; + out_be32(&serdes1_base->srdsrcalcr, reg); + } + } + udelay(1); +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = (cfg_rcw5 >> 20) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg |= 0x00000020; + out_be32(&serdes2_base->bank[i].rstctl, reg); + udelay(1); + + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg |= 0x00000080; + out_be32(&serdes2_base->bank[i].rstctl, reg); + + /* Take the Rx/Tx calibration out of reset */ + if (!(cfg_tmp == 0x3 && i == 1)) { + udelay(1); + reg = in_be32(&serdes2_base->srdstcalcr); + reg |= 0x08000000; + out_be32(&serdes2_base->srdstcalcr, reg); + reg = in_be32(&serdes2_base->srdsrcalcr); + reg |= 0x08000000; + out_be32(&serdes2_base->srdsrcalcr, reg); + } + } + udelay(1); + +#endif + + /* Wait for at lesat 625us to ensure the PLLs being reset are locked */ + udelay(800); + +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = (cfg_rcw5 >> 22) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + /* if the PLL is not locked, set RST_ERR */ + reg = in_be32(&serdes1_base->bank[i].pllcr0); + if (!((reg >> 23) & 0x1)) { + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg |= 0x20000000; + out_be32(&serdes1_base->bank[i].rstctl, reg); + } else { + udelay(1); + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg &= 0xFFFFFFEF; + reg |= 0x00000040; + out_be32(&serdes1_base->bank[i].rstctl, reg); + udelay(1); + } + } +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = (cfg_rcw5 >> 20) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes2_base->bank[i].pllcr0); + if (!((reg >> 23) & 0x1)) { + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg |= 0x20000000; + out_be32(&serdes2_base->bank[i].rstctl, reg); + } else { + udelay(1); + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg &= 0xFFFFFFEF; + reg |= 0x00000040; + out_be32(&serdes2_base->bank[i].rstctl, reg); + udelay(1); + } + } +#endif + + /* Take the all enabled lanes out of reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; + cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; + + for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) { + reg = in_be32(&serdes1_base->lane[i].gcr0); + reg |= 0x00600000; + out_be32(&serdes1_base->lane[i].gcr0, reg); + } +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK; + cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT; + + for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) { + reg = in_be32(&serdes2_base->lane[i].gcr0); + reg |= 0x00600000; + out_be32(&serdes2_base->lane[i].gcr0, reg); + } +#endif + /* For each PLL being reset, and achieved PLL lock set RST_DONE */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = (cfg_rcw5 >> 22) & 0x3; + for (i = 0; i < 2; i++) { + reg = in_be32(&serdes1_base->bank[i].pllcr0); + if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) { + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg |= 0x40000000; + out_be32(&serdes1_base->bank[i].rstctl, reg); + } + } +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = (cfg_rcw5 >> 20) & 0x3; + for (i = 0; i < 2; i++) { + reg = in_be32(&serdes2_base->bank[i].pllcr0); + if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) { + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg |= 0x40000000; + out_be32(&serdes2_base->bank[i].rstctl, reg); + } + } +#endif + + return ret; +} + void fsl_serdes_init(void) { #ifdef CONFIG_SYS_FSL_SRDS_1 diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index 6c42387..8b5e130 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -336,6 +336,95 @@ static void erratum_a010539(void) #endif }
+/* Get VDD in the unit mV from voltage ID */ +int get_core_volt_from_fuse(void) +{ + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + int vdd; + u32 fusesr; + u8 vid; + + fusesr = in_be32(&gur->dcfg_fusesr); + debug("%s: fusesr = 0x%x\n", __func__, fusesr); + vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) & + FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK; + if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) { + vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) & + FSL_CHASSIS2_DCFG_FUSESR_VID_MASK; + } + debug("%s: VID = 0x%x\n", __func__, vid); + switch (vid) { + case 0x00: /* VID isn't supported */ + vdd = -EINVAL; + debug("%s: The VID feature is not supported\n", __func__); + break; + case 0x08: /* 0.9V silicon */ + vdd = 900; + break; + case 0x10: /* 1.0V silicon */ + vdd = 1000; + break; + default: /* Other core voltage */ + vdd = -EINVAL; + printf("%s: The VID(%x) isn't supported\n", __func__, vid); + break; + } + debug("%s: The required minimum volt of CORE is %dmV\n", __func__, vdd); + + return vdd; +} + +__weak int board_switch_core_volt(u32 vdd) +{ + return 0; +} + +static int setup_core_volt(u32 vdd) +{ + return board_setup_core_volt(vdd); +} + +#ifdef CONFIG_SYS_FSL_DDR +static void ddr_enable_0v9_volt(bool en) +{ + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + u32 tmp; + + tmp = ddr_in32(&ddr->ddr_cdr1); + + if (en) + tmp |= DDR_CDR1_V0PT9_EN; + else + tmp &= ~DDR_CDR1_V0PT9_EN; + + ddr_out32(&ddr->ddr_cdr1, tmp); +} +#endif + +int setup_chip_volt(void) +{ + int vdd; + + vdd = get_core_volt_from_fuse(); + /* Nothing to do for silicons doesn't support VID */ + if (vdd < 0) + return vdd; + + if (setup_core_volt(vdd)) + printf("%s: Switch core VDD to %dmV failed\n", __func__, vdd); +#ifdef CONFIG_SYS_HAS_SERDES + if (setup_serdes_volt(vdd)) + printf("%s: Switch SVDD to %dmV failed\n", __func__, vdd); +#endif + +#ifdef CONFIG_SYS_FSL_DDR + if (vdd == 900) + ddr_enable_0v9_volt(true); +#endif + + return 0; +} + void fsl_lsch2_early_init_f(void) { struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR; diff --git a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h index 9f94b45..d9d948e 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h @@ -162,6 +162,14 @@ int is_serdes_prtcl_valid(int serdes, u32 prtcl); #ifdef CONFIG_FSL_LSCH2 const char *serdes_clock_to_string(u32 clock); int get_serdes_protocol(void); +#ifdef CONFIG_SYS_HAS_SERDES +/* Get the volt of SVDD in unit mV */ +int get_serdes_volt(void); +/* Set the volt of SVDD in unit mV */ +int set_serdes_volt(int svdd); +/* The target volt of SVDD in unit mV */ +int setup_serdes_volt(u32 svdd); +#endif #endif
#endif /* __FSL_SERDES_H__ */ diff --git a/arch/arm/include/asm/arch-fsl-layerscape/soc.h b/arch/arm/include/asm/arch-fsl-layerscape/soc.h index 78363b6..9bafa6d 100644 --- a/arch/arm/include/asm/arch-fsl-layerscape/soc.h +++ b/arch/arm/include/asm/arch-fsl-layerscape/soc.h @@ -99,6 +99,9 @@ struct ccsr_ahci { void fsl_lsch3_early_init_f(void); #elif defined(CONFIG_FSL_LSCH2) void fsl_lsch2_early_init_f(void); +int setup_chip_volt(void); +/* Setup core vdd in unit mV */ +int board_setup_core_volt(u32 vdd); #endif
void cpu_name(char *name); diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h index 36bd9d7..32365dc 100644 --- a/include/fsl_ddr_sdram.h +++ b/include/fsl_ddr_sdram.h @@ -173,6 +173,7 @@ typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t;
/* DDR_CDR1 */ #define DDR_CDR1_DHC_EN 0x80000000 +#define DDR_CDR1_V0PT9_EN 0x40000000 #define DDR_CDR1_ODT_SHIFT 17 #define DDR_CDR1_ODT_MASK 0x6 #define DDR_CDR2_ODT_MASK 0x1

From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
Add the chip power supply voltage initialization on LS1046ARDB. Add function power_init_board(), and it will initialize the PMIC and call the chip power initialization function.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com --- arch/arm/Kconfig | 1 + board/freescale/ls1046ardb/ls1046ardb.c | 34 +++++++++++++++++++++++++++++++++ include/configs/ls1046ardb.h | 6 ++++++ 3 files changed, 41 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 49bc9d8..62c0fd5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -819,6 +819,7 @@ config TARGET_LS1046ARDB select ARMV8_MULTIENTRY select SUPPORT_SPL select DM_SPI_FLASH if DM_SPI + select POWER_MC34VR500 help Support for Freescale LS1046ARDB platform. The LS1046A Reference Design Board (RDB) is a high-performance diff --git a/board/freescale/ls1046ardb/ls1046ardb.c b/board/freescale/ls1046ardb/ls1046ardb.c index 585c807..33a58cf 100644 --- a/board/freescale/ls1046ardb/ls1046ardb.c +++ b/board/freescale/ls1046ardb/ls1046ardb.c @@ -19,6 +19,7 @@ #include <fm_eth.h> #include <fsl_csu.h> #include <fsl_esdhc.h> +#include <power/mc34vr500_pmic.h> #include "cpld.h"
DECLARE_GLOBAL_DATA_PTR; @@ -87,6 +88,39 @@ int board_init(void) return 0; }
+int board_setup_core_volt(u32 vdd) +{ + bool en_0v9; + + en_0v9 = (vdd == 900) ? true : false; + cpld_select_core_volt(en_0v9); + + return 0; +} + +int get_serdes_volt(void) +{ + return mc34vr500_get_sw_volt(SW4); +} + +int set_serdes_volt(int svdd) +{ + return mc34vr500_set_sw_volt(SW4, svdd); +} + +int power_init_board(void) +{ + int ret; + + ret = power_mc34vr500_init(0); + if (ret) + return ret; + + setup_chip_volt(); + + return 0; +} + void config_board_mux(void) { #ifdef CONFIG_HAS_FSL_XHCI_USB diff --git a/include/configs/ls1046ardb.h b/include/configs/ls1046ardb.h index 2fe8fc1..d16736f 100644 --- a/include/configs/ls1046ardb.h +++ b/include/configs/ls1046ardb.h @@ -164,6 +164,12 @@ #define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 #define I2C_RETIMER_ADDR 0x18
+/* PMIC */ +#define CONFIG_POWER +#ifdef CONFIG_POWER +#define CONFIG_POWER_I2C +#endif + /* * Environment */

Hi,
On 9 December 2016 at 03:08, Zhiqiang Hou Zhiqiang.Hou@nxp.com wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
This patch adds a simple pmic driver for the mc34vr500 pmic which is used in conjunction with the fsl T1 and LS1 series SoC.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/power/pmic/Kconfig | 7 ++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pmic_mc34vr500.c | 32 +++++++ include/power/mc34vr500_pmic.h | 166 ++++++++++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+) create mode 100644 drivers/power/pmic/pmic_mc34vr500.c create mode 100644 include/power/mc34vr500_pmic.h
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index ce204b3..73e1d53 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -157,3 +157,10 @@ config PMIC_LP873X ---help--- The LP873X is a PMIC containing couple of LDOs and couple of SMPS. This driver binds the pmic children.
+config POWER_MC34VR500
bool "Enable driver for Freescale MC34VR500 PMIC"
---help---
The MC34VR500 is used in conjunction with the FSL T1 and LS1 series
SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed
via an I2C interface.
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index cd1c694..58d0241 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_POWER_TPS65218) += pmic_tps62362.o obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o obj-$(CONFIG_POWER_TPS65910) += pmic_tps65910.o obj-$(CONFIG_POWER_HI6553) += pmic_hi6553.o +obj-$(CONFIG_POWER_MC34VR500) += pmic_mc34vr500.o diff --git a/drivers/power/pmic/pmic_mc34vr500.c b/drivers/power/pmic/pmic_mc34vr500.c new file mode 100644 index 0000000..db9e210 --- /dev/null +++ b/drivers/power/pmic/pmic_mc34vr500.c @@ -0,0 +1,32 @@ +/*
- Copyright 2016 Freescale Semiconductor, Inc.
- Hou Zhiqiang Zhiqiang.Hou@freescale.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <errno.h> +#include <i2c.h> +#include <power/pmic.h> +#include <power/mc34vr500_pmic.h>
+int power_mc34vr500_init(unsigned char bus) +{
static const char name[] = "MC34VR500";
struct pmic *p = pmic_alloc();
We have a driver-model PMIC framework now so can you please convert this to use that? We should move towards removing the old framework.
Regards, Simon

Hi Simon,
Thanks a lot for your comments!
-----Original Message----- From: sjg@google.com [mailto:sjg@google.com] On Behalf Of Simon Glass Sent: 2016年12月12日 4:28 To: Z.Q. Hou zhiqiang.hou@nxp.com Cc: U-Boot Mailing List u-boot@lists.denx.de; york sun york.sun@nxp.com; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com; Shengzhou Liu shengzhou.liu@nxp.com; Priyanka Jain priyanka.jain@nxp.com; Mingkai Hu mingkai.hu@nxp.com Subject: Re: [PATCH 1/5] pmic: pmic_mc34vr500: Add a driver for the mc34vr500 pmic
Hi,
On 9 December 2016 at 03:08, Zhiqiang Hou Zhiqiang.Hou@nxp.com wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
This patch adds a simple pmic driver for the mc34vr500 pmic which is used in conjunction with the fsl T1 and LS1 series SoC.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/power/pmic/Kconfig | 7 ++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pmic_mc34vr500.c | 32 +++++++ include/power/mc34vr500_pmic.h | 166
++++++++++++++++++++++++++++++++++++
4 files changed, 206 insertions(+) create mode 100644 drivers/power/pmic/pmic_mc34vr500.c create mode 100644 include/power/mc34vr500_pmic.h
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index ce204b3..73e1d53 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -157,3 +157,10 @@ config PMIC_LP873X ---help--- The LP873X is a PMIC containing couple of LDOs and couple of
SMPS.
This driver binds the pmic children.
+config POWER_MC34VR500
bool "Enable driver for Freescale MC34VR500 PMIC"
---help---
The MC34VR500 is used in conjunction with the FSL T1 and LS1
series
SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is
accessed
via an I2C interface.
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index cd1c694..58d0241 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_POWER_TPS65218) += pmic_tps62362.o obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o obj-$(CONFIG_POWER_TPS65910) += pmic_tps65910.o obj-$(CONFIG_POWER_HI6553) += pmic_hi6553.o +obj-$(CONFIG_POWER_MC34VR500) += pmic_mc34vr500.o diff --git a/drivers/power/pmic/pmic_mc34vr500.c b/drivers/power/pmic/pmic_mc34vr500.c new file mode 100644 index 0000000..db9e210 --- /dev/null +++ b/drivers/power/pmic/pmic_mc34vr500.c @@ -0,0 +1,32 @@ +/*
- Copyright 2016 Freescale Semiconductor, Inc.
- Hou Zhiqiang Zhiqiang.Hou@freescale.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <errno.h> +#include <i2c.h> +#include <power/pmic.h> +#include <power/mc34vr500_pmic.h>
+int power_mc34vr500_init(unsigned char bus) {
static const char name[] = "MC34VR500";
struct pmic *p = pmic_alloc();
We have a driver-model PMIC framework now so can you please convert this to use that? We should move towards removing the old framework.
Yes, I know. Actually, I have written the driver based on driver-model PMIC framework, but it depends on DM_I2C, while the DM_I2C isn't ready on Layerscape SoCs. I will send the DM PMIC based MC34VR500 driver once the DM_I2C ready.
Thanks, Zhiqiang

+Jaehoon to comment on the driver
On 12/09/2016 12:22 AM, Zhiqiang Hou wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
This patch adds a simple pmic driver for the mc34vr500 pmic which is used in conjunction with the fsl T1 and LS1 series SoC.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/power/pmic/Kconfig | 7 ++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pmic_mc34vr500.c | 32 +++++++ include/power/mc34vr500_pmic.h | 166 ++++++++++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+) create mode 100644 drivers/power/pmic/pmic_mc34vr500.c create mode 100644 include/power/mc34vr500_pmic.h
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index ce204b3..73e1d53 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -157,3 +157,10 @@ config PMIC_LP873X ---help--- The LP873X is a PMIC containing couple of LDOs and couple of SMPS. This driver binds the pmic children.
+config POWER_MC34VR500
- bool "Enable driver for Freescale MC34VR500 PMIC"
- ---help---
- The MC34VR500 is used in conjunction with the FSL T1 and LS1 series
- SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed
- via an I2C interface.
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index cd1c694..58d0241 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_POWER_TPS65218) += pmic_tps62362.o obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o obj-$(CONFIG_POWER_TPS65910) += pmic_tps65910.o obj-$(CONFIG_POWER_HI6553) += pmic_hi6553.o +obj-$(CONFIG_POWER_MC34VR500) += pmic_mc34vr500.o diff --git a/drivers/power/pmic/pmic_mc34vr500.c b/drivers/power/pmic/pmic_mc34vr500.c new file mode 100644 index 0000000..db9e210 --- /dev/null +++ b/drivers/power/pmic/pmic_mc34vr500.c @@ -0,0 +1,32 @@ +/*
- Copyright 2016 Freescale Semiconductor, Inc.
- Hou Zhiqiang Zhiqiang.Hou@freescale.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <errno.h> +#include <i2c.h> +#include <power/pmic.h> +#include <power/mc34vr500_pmic.h>
+int power_mc34vr500_init(unsigned char bus) +{
- static const char name[] = "MC34VR500";
- struct pmic *p = pmic_alloc();
- if (!p) {
printf("%s: POWER allocation error!\n", __func__);
return -ENOMEM;
- }
- p->name = name;
- p->interface = PMIC_I2C;
- p->number_of_regs = MC34VR500_NUM_OF_REGS;
- p->hw.i2c.addr = MC34VR500_I2C_ADDR;
- p->hw.i2c.tx_num = 1;
- p->bus = bus;
- return 0;
+} diff --git a/include/power/mc34vr500_pmic.h b/include/power/mc34vr500_pmic.h new file mode 100644 index 0000000..df4985a --- /dev/null +++ b/include/power/mc34vr500_pmic.h @@ -0,0 +1,166 @@ +/*
- Copyright 2016 Freescale Semiconductor, Inc.
- Hou Zhiqiang Zhiqiang.Hou@freescale.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __MC34VR500_H_ +#define __MC34VR500_H_
+#include <power/pmic.h>
+#define MC34VR500_I2C_ADDR 0x08
+/* Drivers name */ +#define MC34VR500_REGULATOR_DRIVER "mc34vr500_regulator"
+/* Register map */ +enum {
- MC34VR500_DEVICEID = 0x00,
- MC34VR500_SILICONREVID = 0x03,
- MC34VR500_FABID,
- MC34VR500_INTSTAT0,
- MC34VR500_INTMASK0,
- MC34VR500_INTSENSE0,
- MC34VR500_INTSTAT1,
- MC34VR500_INTMASK1,
- MC34VR500_INTSENSE1,
- MC34VR500_INTSTAT4 = 0x11,
- MC34VR500_INTMASK4,
- MC34VR500_INTSENSE4,
- MC34VR500_PWRCTL = 0x1B,
- MC34VR500_SW1VOLT = 0x2E,
- MC34VR500_SW1STBY,
- MC34VR500_SW1OFF,
- MC34VR500_SW1MODE,
- MC34VR500_SW1CONF,
- MC34VR500_SW2VOLT,
- MC34VR500_SW2STBY,
- MC34VR500_SW2OFF,
- MC34VR500_SW2MODE,
- MC34VR500_SW2CONF,
- MC34VR500_SW3VOLT = 0x3C,
- MC34VR500_SW3STBY,
- MC34VR500_SW3OFF,
- MC34VR500_SW3MODE,
- MC34VR500_SW3CONF,
- MC34VR500_SW4VOLT = 0x4A,
- MC34VR500_SW4STBY,
- MC34VR500_SW4OFF,
- MC34VR500_SW4MODE,
- MC34VR500_SW4CONF,
- MC34VR500_REFOUTCRTRL = 0x6A,
- MC34VR500_LDO1CTL = 0x6D,
- MC34VR500_LDO2CTL,
- MC34VR500_LDO3CTL,
- MC34VR500_LDO4CTL,
- MC34VR500_LDO5CTL,
- MC34VR500_PAGE_REGISTER = 0x7F,
- /* Internal RAM */
- MC34VR500_SW1_VOLT = 0xA8,
- MC34VR500_SW1_SEQ,
- MC34VR500_SW1_CONFIG,
- MC34VR500_SW2_VOLT = 0xAC,
- MC34VR500_SW2_SEQ,
- MC34VR500_SW2_CONFIG,
- MC34VR500_SW3_VOLT = 0xB0,
- MC34VR500_SW3_SEQ,
- MC34VR500_SW3_CONFIG,
- MC34VR500_SW4_VOLT = 0xB8,
- MC34VR500_SW4_SEQ,
- MC34VR500_SW4_CONFIG,
- MC34VR500_REFOUT_SEQ = 0xC4,
- MC34VR500_LDO1_VOLT = 0xCC,
- MC34VR500_LDO1_SEQ,
- MC34VR500_LDO2_VOLT = 0xD0,
- MC34VR500_LDO2_SEQ,
- MC34VR500_LDO3_VOLT = 0xD4,
- MC34VR500_LDO3_SEQ,
- MC34VR500_LDO4_VOLT = 0xD8,
- MC34VR500_LDO4_SEQ,
- MC34VR500_LDO5_VOLT = 0xDC,
- MC34VR500_LDO5_SEQ,
- MC34VR500_PU_CONFIG1 = 0xE0,
- MC34VR500_TBB_POR = 0xE4,
- MC34VR500_PWRGD_EN = 0xE8,
- MC34VR500_NUM_OF_REGS,
+};
+/* Registor offset based on SWxVOLT register */ +#define MC34VR500_VOLT_OFFSET 0 +#define MC34VR500_STBY_OFFSET 1 +#define MC34VR500_OFF_OFFSET 2 +#define MC34VR500_MODE_OFFSET 3 +#define MC34VR500_CONF_OFFSET 4
+#define SW_MODE_MASK 0xf +#define SW_MODE_SHIFT 0
+#define LDO_VOL_MASK 0xf +#define LDO_EN (1 << 4) +#define LDO_MODE_SHIFT 4 +#define LDO_MODE_MASK (1 << 4) +#define LDO_MODE_OFF 0 +#define LDO_MODE_ON 1
+#define REFOUTEN (1 << 4)
+/*
- Regulator Mode Control
- OFF: The regulator is switched off and the output voltage is discharged.
- PFM: In this mode, the regulator is always in PFM mode, which is useful
at light loads for optimized efficiency.
- PWM: In this mode, the regulator is always in PWM mode operation
- regardless of load conditions.
- APS: In this mode, the regulator moves automatically between pulse
- skipping mode and PWM mode depending on load conditions.
- SWxMODE[3:0]
- Normal Mode | Standby Mode | value
- OFF OFF 0x0
- PWM OFF 0x1
- PFM OFF 0x3
- APS OFF 0x4
- PWM PWM 0x5
- PWM APS 0x6
- APS APS 0x8
- APS PFM 0xc
- PWM PFM 0xd
- */
+#define OFF_OFF 0x0 +#define PWM_OFF 0x1 +#define PFM_OFF 0x3 +#define APS_OFF 0x4 +#define PWM_PWM 0x5 +#define PWM_APS 0x6 +#define APS_APS 0x8 +#define APS_PFM 0xc +#define PWM_PFM 0xd
+int power_mc34vr500_init(unsigned char bus); +#endif /* __MC34VR500_PMIC_H_ */
Zhiqiang,
I'd like to hear from Jaehoon before taking an action.
York

Hi,
On 01/05/2017 05:33 AM, york sun wrote:
+Jaehoon to comment on the driver
On 12/09/2016 12:22 AM, Zhiqiang Hou wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
This patch adds a simple pmic driver for the mc34vr500 pmic which is used in conjunction with the fsl T1 and LS1 series SoC.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/power/pmic/Kconfig | 7 ++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pmic_mc34vr500.c | 32 +++++++ include/power/mc34vr500_pmic.h | 166 ++++++++++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+) create mode 100644 drivers/power/pmic/pmic_mc34vr500.c create mode 100644 include/power/mc34vr500_pmic.h
[snip]
+int power_mc34vr500_init(unsigned char bus); +#endif /* __MC34VR500_PMIC_H_ */
Zhiqiang,
I'd like to hear from Jaehoon before taking an action.
I hope that this driver will change to Driver model. Otherwise, there is no objection.
For PATCH[1/5]~[2/5],
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
York

Hi Jaehoon,
Thanks a lot for your review!
-----Original Message----- From: Jaehoon Chung [mailto:jh80.chung@samsung.com] Sent: 2017年1月5日 9:46 To: york sun york.sun@nxp.com; Z.Q. Hou zhiqiang.hou@nxp.com Cc: u-boot@lists.denx.de; sjg@chromium.org; Prabhakar Kushwaha prabhakar.kushwaha@nxp.com; Shengzhou Liu shengzhou.liu@nxp.com; Priyanka Jain priyanka.jain@nxp.com; Mingkai Hu mingkai.hu@nxp.com Subject: Re: [PATCH 1/5] pmic: pmic_mc34vr500: Add a driver for the mc34vr500 pmic
Hi,
On 01/05/2017 05:33 AM, york sun wrote:
+Jaehoon to comment on the driver
On 12/09/2016 12:22 AM, Zhiqiang Hou wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
This patch adds a simple pmic driver for the mc34vr500 pmic which is used in conjunction with the fsl T1 and LS1 series SoC.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
drivers/power/pmic/Kconfig | 7 ++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pmic_mc34vr500.c | 32 +++++++ include/power/mc34vr500_pmic.h | 166
++++++++++++++++++++++++++++++++++++
4 files changed, 206 insertions(+) create mode 100644 drivers/power/pmic/pmic_mc34vr500.c create mode 100644 include/power/mc34vr500_pmic.h
[snip]
+int power_mc34vr500_init(unsigned char bus); #endif /* +__MC34VR500_PMIC_H_ */
Zhiqiang,
I'd like to hear from Jaehoon before taking an action.
I hope that this driver will change to Driver model.
Yes, totally agree, but the DM PMIC framework depends on DM I2C. Once the Layerscape I2C DM driver is ready, I will send out the DM based MC34VR500 driver.
Otherwise, there is no objection.
For PATCH[1/5]~[2/5],
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Thanks, Zhiqiang

On 12/09/2016 12:22 AM, Zhiqiang Hou wrote:
From: Hou Zhiqiang Zhiqiang.Hou@nxp.com
This patch adds a simple pmic driver for the mc34vr500 pmic which is used in conjunction with the fsl T1 and LS1 series SoC.
Signed-off-by: Hou Zhiqiang Zhiqiang.Hou@nxp.com
This set is applied to fsl-qoriq master, awaiting upstream. Thanks.
York
participants (5)
-
Jaehoon Chung
-
Simon Glass
-
york sun
-
Z.Q. Hou
-
Zhiqiang Hou