[U-Boot] [PATCH v2 0/7] add pwm regulator driver

This patch set add pwm regulator driver and enable it on rk3399, also do some update and fix to make the regulator driver work properly.
Changes in v2: - add comments for pwm_regulator_info struct member - do not init pwm_id if there is none - other fix for comments from Simon - add Acked-by tag from Simon and commit message fix - update the commit message
Kever Yang (7): rockchip: rk3399: update PPLL and pmu_pclk frequency rockchip: rkpwm: fix the register sequence power: regulator: add pwm regulator rockchip: evb_rk3399: init vdd_center regulator Kconfig: rockchip: enable DM_PWM and DM_REGULATOR dts: evb-rk3399: add init voltage node for vdd-center config: evb-rk3399: enable pwm regulator
arch/arm/Kconfig | 2 + arch/arm/dts/rk3399-evb.dts | 1 + arch/arm/include/asm/arch-rockchip/cru_rk3399.h | 4 +- arch/arm/include/asm/arch-rockchip/pwm.h | 2 +- board/rockchip/evb_rk3399/evb-rk3399.c | 6 + configs/evb-rk3399_defconfig | 1 + drivers/power/regulator/Kconfig | 10 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/pwm_regulator.c | 160 ++++++++++++++++++++++++ 9 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 drivers/power/regulator/pwm_regulator.c

Update PPLL to 676MHz and PMU_PCLK to 48MHz, because: 1. 48MHz can make sure the pwm can get exact 50% duty ratio, but 99MHz can not, 2. We think 48MHz is fast enough for pmu pclk and it is lower power cost than 99MHz, 3. PPLL 676 MHz and PMU_PCLK 48MHz are the clock rate we are using internally for kernel,it suppose not to change the bus clock like pmu_pclk in kernel, so we want to change it in uboot.
Signed-off-by: Kever Yang kever.yang@rock-chips.com ---
Changes in v2: None
arch/arm/include/asm/arch-rockchip/cru_rk3399.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h index c919f47..6776e48 100644 --- a/arch/arm/include/asm/arch-rockchip/cru_rk3399.h +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3399.h @@ -64,9 +64,9 @@ check_member(rk3399_cru, sdio1_con[1], 0x594); #define APLL_HZ (600*MHz) #define GPLL_HZ (594*MHz) #define CPLL_HZ (384*MHz) -#define PPLL_HZ (594*MHz) +#define PPLL_HZ (676*MHz)
-#define PMU_PCLK_HZ (99*MHz) +#define PMU_PCLK_HZ (48*MHz)
#define ACLKM_CORE_HZ (300*MHz) #define ATCLK_CORE_HZ (300*MHz)

On 8 September 2016 at 19:19, Kever Yang kever.yang@rock-chips.com wrote:
Update PPLL to 676MHz and PMU_PCLK to 48MHz, because:
- 48MHz can make sure the pwm can get exact 50% duty ratio, but 99MHz
can not, 2. We think 48MHz is fast enough for pmu pclk and it is lower power cost than 99MHz, 3. PPLL 676 MHz and PMU_PCLK 48MHz are the clock rate we are using internally for kernel,it suppose not to change the bus clock like pmu_pclk in kernel, so we want to change it in uboot.
Signed-off-by: Kever Yang kever.yang@rock-chips.com
Changes in v2: None
arch/arm/include/asm/arch-rockchip/cru_rk3399.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Acked-by: Simon Glass sjg@chromium.org

Reference to kernel source code, rockchip pwm has three type, we are using v2 for rk3288 and rk3399, so let's update the register to sync with pwm_data_v2 in kernel.
Signed-off-by: Kever Yang kever.yang@rock-chips.com Acked-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/arm/include/asm/arch-rockchip/pwm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/arch-rockchip/pwm.h b/arch/arm/include/asm/arch-rockchip/pwm.h index 08ff945..5d9a178 100644 --- a/arch/arm/include/asm/arch-rockchip/pwm.h +++ b/arch/arm/include/asm/arch-rockchip/pwm.h @@ -10,8 +10,8 @@
struct rk3288_pwm { u32 cnt; - u32 period_hpr; u32 duty_lpr; + u32 period_hpr; u32 ctrl; }; check_member(rk3288_pwm, ctrl, 0xc);

add driver support for pwm regulator.
Signed-off-by: Elaine Zhang zhangqing@rock-chips.com Signed-off-by: Kever Yang kever.yang@rock-chips.com ---
Changes in v2: - add comments for pwm_regulator_info struct member - do not init pwm_id if there is none - other fix for comments from Simon
drivers/power/regulator/Kconfig | 10 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/pwm_regulator.c | 160 ++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 drivers/power/regulator/pwm_regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 17f22dd..c7e88c0 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -42,6 +42,16 @@ config DM_REGULATOR_PFUZE100 features for REGULATOR PFUZE100. The driver implements get/set api for: value, enable and mode.
+config REGULATOR_PWM + bool "Enable driver for PWM regulators" + depends on DM_REGULATOR + ---help--- + Enable support for the PWM regulator functions which voltage are + controlled by PWM duty ratio. Some of Rockchip board using this kind + of regulator. The driver implements get/set api for the various BUCKS. + This driver is controlled by a device tree node + which includes voltage limits. + config DM_REGULATOR_MAX77686 bool "Enable Driver Model for REGULATOR MAX77686" depends on DM_REGULATOR && DM_PMIC_MAX77686 diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 1590d85..ab461ec 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR) += regulator-uclass.o obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o +obj-$(CONFIG_REGULATOR_PWM) += pwm_regulator.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o obj-$(CONFIG_REGULATOR_RK808) += rk808.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o diff --git a/drivers/power/regulator/pwm_regulator.c b/drivers/power/regulator/pwm_regulator.c new file mode 100644 index 0000000..abecb5f --- /dev/null +++ b/drivers/power/regulator/pwm_regulator.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co., Ltd + * + * Based on kernel drivers/regulator/pwm-regulator.c + * Copyright (C) 2014 - STMicroelectronics Inc. + * Author: Lee Jones lee.jones@linaro.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <pwm.h> +#include <power/regulator.h> +#include <libfdt.h> +#include <fdt_support.h> +#include <fdtdec.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct pwm_regulator_info { + /* pwm id corresponding to the PWM driver */ + int pwm_id; + /* the period of one PWM cycle */ + int period_ns; + struct udevice *pwm; + /* initialize voltage of regulator */ + unsigned int init_voltage; + /* the maximum voltage of regulator */ + unsigned int max_voltage; + /* the minimum voltage of regulator */ + unsigned int min_voltage; + /* the current voltage of regulator */ + unsigned int volt_uV; +}; + +static int pwm_regulator_enable(struct udevice *dev, bool enable) +{ + struct pwm_regulator_info *priv = dev_get_priv(dev); + + return pwm_set_enable(priv->pwm, priv->pwm_id, enable); +} + +static int pwm_voltage_to_duty_cycle_percentage(struct udevice *dev, int req_uV) +{ + struct pwm_regulator_info *priv = dev_get_priv(dev); + int min_uV = priv->min_voltage; + int max_uV = priv->max_voltage; + int diff = max_uV - min_uV; + + return 100 - (((req_uV * 100) - (min_uV * 100)) / diff); +} + +static int pwm_regulator_get_voltage(struct udevice *dev) +{ + struct pwm_regulator_info *priv = dev_get_priv(dev); + + return priv->volt_uV; +} + +static int pwm_regulator_set_voltage(struct udevice *dev, int uvolt) +{ + struct pwm_regulator_info *priv = dev_get_priv(dev); + int duty_cycle; + int ret = 0; + + duty_cycle = pwm_voltage_to_duty_cycle_percentage(dev, uvolt); + + ret = pwm_set_config(priv->pwm, priv->pwm_id, + (priv->period_ns / 100) * duty_cycle, priv->period_ns); + if (ret) { + dev_err(dev, "Failed to configure PWM\n"); + return ret; + } + + ret = pwm_set_enable(priv->pwm, priv->pwm_id, true); + if (ret) { + dev_err(dev, "Failed to enable PWM\n"); + return ret; + } + priv->volt_uV = uvolt; + return ret; +} + +static int pwm_regulator_ofdata_to_platdata(struct udevice *dev) +{ + struct pwm_regulator_info *priv = dev_get_priv(dev); + struct fdtdec_phandle_args args; + const void *blob = gd->fdt_blob; + int node = dev->of_offset; + int ret; + + ret = fdtdec_parse_phandle_with_args(blob, node, "pwms", "#pwm-cells", + 0, 0, &args); + if (ret) { + debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret); + return ret; + } + /* TODO: pwm_id here from device tree if needed */ + + priv->period_ns = args.args[1]; + + priv->init_voltage = fdtdec_get_int(blob, node, + "regulator-init-microvolt", -1); + if (priv->init_voltage < 0) { + printf("Cannot find regulator pwm init_voltage\n"); + return -EINVAL; + } + + ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm); + if (ret) { + debug("%s: Cannot get PWM: ret=%d\n", __func__, ret); + return ret; + } + + return 0; +} + +static int pwm_regulator_probe(struct udevice *dev) +{ + struct pwm_regulator_info *priv = dev_get_priv(dev); + struct dm_regulator_uclass_platdata *uc_pdata; + + uc_pdata = dev_get_uclass_platdata(dev); + + uc_pdata->type = REGULATOR_TYPE_BUCK; + uc_pdata->mode_count = 0; + priv->max_voltage = uc_pdata->max_uV; + priv->min_voltage = uc_pdata->min_uV; + + if (priv->init_voltage) + pwm_regulator_set_voltage(dev, priv->init_voltage); + + if (priv->boot_on) + pwm_regulator_enable(dev, 1); + + return 0; +} + +static const struct dm_regulator_ops pwm_regulator_ops = { + .get_value = pwm_regulator_get_voltage, + .set_value = pwm_regulator_set_voltage, + .set_enable = pwm_regulator_enable, +}; + +static const struct udevice_id pwm_regulator_ids[] = { + { .compatible = "pwm-regulator" }, + { } +}; + +U_BOOT_DRIVER(pwm_regulator) = { + .name = "pwm_regulator", + .id = UCLASS_REGULATOR, + .ops = &pwm_regulator_ops, + .probe = pwm_regulator_probe, + .of_match = pwm_regulator_ids, + .ofdata_to_platdata = pwm_regulator_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct pwm_regulator_info), +};

On 8 September 2016 at 19:19, Kever Yang kever.yang@rock-chips.com wrote:
add driver support for pwm regulator.
Signed-off-by: Elaine Zhang zhangqing@rock-chips.com Signed-off-by: Kever Yang kever.yang@rock-chips.com
Changes in v2:
- add comments for pwm_regulator_info struct member
- do not init pwm_id if there is none
- other fix for comments from Simon
drivers/power/regulator/Kconfig | 10 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/pwm_regulator.c | 160 ++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 drivers/power/regulator/pwm_regulator.c
Acked-by: Simon Glass sjg@chromium.org

Add vdd_center pwm regulator get_device to enable this regulator.
Signed-off-by: Kever Yang kever.yang@rock-chips.com Acked-by: Simon Glass sjg@chromium.org ---
Changes in v2: - add Acked-by tag from Simon and commit message fix
board/rockchip/evb_rk3399/evb-rk3399.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/board/rockchip/evb_rk3399/evb-rk3399.c b/board/rockchip/evb_rk3399/evb-rk3399.c index f595a54..5e6ce7c 100644 --- a/board/rockchip/evb_rk3399/evb-rk3399.c +++ b/board/rockchip/evb_rk3399/evb-rk3399.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> #include <dm/pinctrl.h> +#include <dm/uclass-internal.h> #include <asm/arch/periph.h> #include <usb.h> #include <dwc3-uboot.h> @@ -41,6 +42,11 @@ int board_init(void) goto out; }
+ /* rk3399 need init vdd_center to get correct output voltage */ + ret = regulator_get_by_platname("vdd_center", ®ulator); + if (ret) + debug("%s: Cannot get vdd_center regulator\n", __func__); + ret = regulator_get_by_platname("vcc5v0_host", ®ulator); if (ret) { debug("%s vcc5v0_host init fail! ret %d\n", __func__, ret);

Enable DM_PWM and DM_REGULATOR on rockchip SoCs.
Signed-off-by: Kever Yang kever.yang@rock-chips.com Acked-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/arm/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4928206..c877f5d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -863,6 +863,8 @@ config ARCH_ROCKCHIP select DM_SPI select DM_SPI_FLASH select DM_USB if USB + select DM_PWM + select DM_REGULATOR
config TARGET_THUNDERX_88XX bool "Support ThunderX 88xx"

Add a regulator-init-microvolt for vdd_center regulator so that we can get a init value for driver probe. Not like pmic regulator, the PWM regulator do not have a known default output value, so we would like to init the regulator when driver probe.
Signed-off-by: Kever Yang kever.yang@rock-chips.com ---
Changes in v2: - update the commit message
arch/arm/dts/rk3399-evb.dts | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/dts/rk3399-evb.dts b/arch/arm/dts/rk3399-evb.dts index bd7801b..fa60e19 100644 --- a/arch/arm/dts/rk3399-evb.dts +++ b/arch/arm/dts/rk3399-evb.dts @@ -23,6 +23,7 @@ regulator-name = "vdd_center"; regulator-min-microvolt = <800000>; regulator-max-microvolt = <1400000>; + regulator-init-microvolt = <950000>; regulator-always-on; regulator-boot-on; status = "okay";

On 8 September 2016 at 19:19, Kever Yang kever.yang@rock-chips.com wrote:
Add a regulator-init-microvolt for vdd_center regulator so that we can get a init value for driver probe. Not like pmic regulator, the PWM regulator do not have a known default output value, so we would like to init the regulator when driver probe.
Signed-off-by: Kever Yang kever.yang@rock-chips.com
Changes in v2:
- update the commit message
arch/arm/dts/rk3399-evb.dts | 1 + 1 file changed, 1 insertion(+)
Acked-by: Simon Glass sjg@chromium.org

Enable the pwm regulator for evb-rk3399.
Signed-off-by: Kever Yang kever.yang@rock-chips.com Acked-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
configs/evb-rk3399_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig index 1e7575d..6468620 100644 --- a/configs/evb-rk3399_defconfig +++ b/configs/evb-rk3399_defconfig @@ -29,6 +29,7 @@ CONFIG_PINCTRL=y CONFIG_ROCKCHIP_RK3399_PINCTRL=y CONFIG_DM_PWM=y CONFIG_PWM_ROCKCHIP=y +CONFIG_REGULATOR_PWM=y CONFIG_RAM=y CONFIG_SYS_NS16550=y CONFIG_DEBUG_UART=y
participants (2)
-
Kever Yang
-
Simon Glass