From 8823845547e133abafdc990bc1b6e997bcd4d396 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Thu, 25 Jan 2018 16:11:01 +0900 Subject: [PATCH 1/8] configs: trats2: enable the max77686 regulator config Enable the CONFIG_DM_REGULATOR_MAX77686 for using regulator driver. Signed-off-by: Jaehoon Chung --- configs/trats2_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/trats2_defconfig b/configs/trats2_defconfig index f270fc9..93aa211 100644 --- a/configs/trats2_defconfig +++ b/configs/trats2_defconfig @@ -37,6 +37,8 @@ CONFIG_MMC_SDHCI_SDMA=y CONFIG_MMC_SDHCI_S5P=y CONFIG_DM_PMIC=y CONFIG_DM_PMIC_MAX77686=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_MAX77686=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_GADGET=y From 9c67c4491ee4cce434d5d451b10850c9f55d5c4a Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Thu, 25 Jan 2018 16:11:02 +0900 Subject: [PATCH 2/8] power: pmic_max77686: remove the old pmic_max77686 file max77686 pmic is supporting with max77686.c under pmic/ and regulator/ direnctroy. Remove pmic_max77686.c what didn't use anywhere. Instead, enable CONFIG_DM_REGULATOR_MAX77686 and CONFIG_DM_PMIC_MAX77686. Signed-off-by: Jaehoon Chung --- drivers/power/pmic/Makefile | 1 - drivers/power/pmic/pmic_max77686.c | 303 ------------------------------------- 2 files changed, 304 deletions(-) delete mode 100644 drivers/power/pmic/pmic_max77686.c diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 64382b9..85ab176 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -28,7 +28,6 @@ obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o obj-$(CONFIG_POWER_MAX8997) += pmic_max8997.o obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o -obj-$(CONFIG_POWER_MAX77686) += pmic_max77686.o obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o obj-$(CONFIG_POWER_PFUZE3000) += pmic_pfuze3000.o obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o diff --git a/drivers/power/pmic/pmic_max77686.c b/drivers/power/pmic/pmic_max77686.c deleted file mode 100644 index 8b3d3f4..0000000 --- a/drivers/power/pmic/pmic_max77686.c +++ /dev/null @@ -1,303 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2012 Samsung Electronics - * Rajeshwari Shinde - */ - -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -static const char max77686_buck_addr[] = { - 0xff, 0x10, 0x12, 0x1c, 0x26, 0x30, 0x32, 0x34, 0x36, 0x38 -}; - -static unsigned int max77686_ldo_volt2hex(int ldo, ulong uV) -{ - unsigned int hex = 0; - - switch (ldo) { - case 1: - case 2: - case 6: - case 7: - case 8: - case 15: - hex = (uV - 800000) / 25000; - break; - default: - hex = (uV - 800000) / 50000; - } - - if (hex >= 0 && hex <= MAX77686_LDO_VOLT_MAX_HEX) - return hex; - - debug("%s: %ld is wrong voltage value for LDO%d\n", __func__, uV, ldo); - return 0; -} - -static int max77686_buck_volt2hex(int buck, ulong uV) -{ - int hex = 0; - - if (buck < 5 || buck > 9) { - debug("%s: buck %d is not supported\n", __func__, buck); - return -EINVAL; - } - - hex = (uV - 750000) / 50000; - - if (hex >= 0 && hex <= MAX77686_BUCK_VOLT_MAX_HEX) - return hex; - - debug("%s: %ld is wrong voltage value for BUCK%d\n", - __func__, uV, buck); - return -EINVAL; -} - -int max77686_set_ldo_voltage(struct pmic *p, int ldo, ulong uV) -{ - unsigned int val, ret, hex, adr; - - if (ldo < 1 || ldo > 26) { - printf("%s: %d is wrong ldo number\n", __func__, ldo); - return -EINVAL; - } - - adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1; - hex = max77686_ldo_volt2hex(ldo, uV); - - if (!hex) - return -EINVAL; - - ret = pmic_reg_read(p, adr, &val); - if (ret) - return ret; - - val &= ~MAX77686_LDO_VOLT_MASK; - val |= hex; - ret |= pmic_reg_write(p, adr, val); - - return ret; -} - -int max77686_set_buck_voltage(struct pmic *p, int buck, ulong uV) -{ - unsigned int val, adr; - int hex, ret; - - if (buck < 5 || buck > 9) { - printf("%s: %d is an unsupported bucket number\n", - __func__, buck); - return -EINVAL; - } - - adr = max77686_buck_addr[buck] + 1; - hex = max77686_buck_volt2hex(buck, uV); - - if (hex < 0) - return hex; - - ret = pmic_reg_read(p, adr, &val); - if (ret) - return ret; - - val &= ~MAX77686_BUCK_VOLT_MASK; - ret |= pmic_reg_write(p, adr, val | hex); - - return ret; -} - -int max77686_set_ldo_mode(struct pmic *p, int ldo, char opmode) -{ - unsigned int val, ret, adr, mode; - - if (ldo < 1 || 26 < ldo) { - printf("%s: %d is wrong ldo number\n", __func__, ldo); - return -EINVAL; - } - - adr = MAX77686_REG_PMIC_LDO1CTRL1 + ldo - 1; - - /* mode */ - switch (opmode) { - case OPMODE_OFF: - mode = MAX77686_LDO_MODE_OFF; - break; - case OPMODE_STANDBY: - switch (ldo) { - case 2: - case 6: - case 7: - case 8: - case 10: - case 11: - case 12: - case 14: - case 15: - case 16: - mode = MAX77686_LDO_MODE_STANDBY; - break; - default: - mode = 0xff; - } - break; - case OPMODE_LPM: - mode = MAX77686_LDO_MODE_LPM; - break; - case OPMODE_ON: - mode = MAX77686_LDO_MODE_ON; - break; - default: - mode = 0xff; - } - - if (mode == 0xff) { - printf("%s: %d is not supported on LDO%d\n", - __func__, opmode, ldo); - return -ENOTSUPP; - } - - ret = pmic_reg_read(p, adr, &val); - if (ret) - return ret; - - val &= ~MAX77686_LDO_MODE_MASK; - val |= mode; - ret |= pmic_reg_write(p, adr, val); - - return ret; -} - -int max77686_set_buck_mode(struct pmic *p, int buck, char opmode) -{ - unsigned int val, ret, mask, adr, size, mode, mode_shift; - - size = ARRAY_SIZE(max77686_buck_addr); - if (buck >= size) { - printf("%s: %d is wrong buck number\n", __func__, buck); - return -EINVAL; - } - - adr = max77686_buck_addr[buck]; - - /* mask */ - switch (buck) { - case 2: - case 3: - case 4: - mode_shift = MAX77686_BUCK_MODE_SHIFT_2; - break; - default: - mode_shift = MAX77686_BUCK_MODE_SHIFT_1; - } - - mask = MAX77686_BUCK_MODE_MASK << mode_shift; - - /* mode */ - switch (opmode) { - case OPMODE_OFF: - mode = MAX77686_BUCK_MODE_OFF << mode_shift; - break; - case OPMODE_STANDBY: - switch (buck) { - case 1: - case 2: - case 3: - case 4: - mode = MAX77686_BUCK_MODE_STANDBY << mode_shift; - break; - default: - mode = 0xff; - } - break; - case OPMODE_LPM: - switch (buck) { - case 2: - case 3: - case 4: - mode = MAX77686_BUCK_MODE_LPM << mode_shift; - break; - default: - mode = 0xff; - } - break; - case OPMODE_ON: - mode = MAX77686_BUCK_MODE_ON << mode_shift; - break; - default: - mode = 0xff; - } - - if (mode == 0xff) { - printf("%s: %d is not supported on BUCK%d\n", - __func__, opmode, buck); - return -ENOTSUPP; - } - - ret = pmic_reg_read(p, adr, &val); - if (ret) - return ret; - - val &= ~mask; - val |= mode; - ret |= pmic_reg_write(p, adr, val); - - return ret; -} - -int pmic_init(unsigned char bus) -{ - static const char name[] = "MAX77686_PMIC"; - struct pmic *p = pmic_alloc(); -#if CONFIG_IS_ENABLED(OF_CONTROL) - const void *blob = gd->fdt_blob; - int node, parent, tmp; -#endif - - if (!p) { - printf("%s: POWER allocation error!\n", __func__); - return -ENOMEM; - } - -#if CONFIG_IS_ENABLED(OF_CONTROL) - node = fdtdec_next_compatible(blob, 0, COMPAT_MAXIM_MAX77686_PMIC); - if (node < 0) { - debug("PMIC: No node for PMIC Chip in device tree\n"); - debug("node = %d\n", node); - return -ENODEV; - } - - parent = fdt_parent_offset(blob, node); - if (parent < 0) { - debug("%s: Cannot find node parent\n", __func__); - return -ENODEV; - } - - /* tmp since p->bus is unsigned */ - tmp = i2c_get_bus_num_fdt(parent); - if (tmp < 0) { - debug("%s: Cannot find I2C bus\n", __func__); - return -ENODEV; - } - p->bus = tmp; - p->hw.i2c.addr = fdtdec_get_int(blob, node, "reg", 9); -#else - p->bus = bus; - p->hw.i2c.addr = MAX77686_I2C_ADDR; -#endif - - p->name = name; - p->interface = PMIC_I2C; - p->number_of_regs = MAX77686_NUM_OF_REGS; - p->hw.i2c.tx_num = 1; - - puts("Board PMIC init\n"); - - return 0; -} From 817669231c89a97e3934baf07d457ca9671947ea Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Thu, 25 Jan 2018 16:11:03 +0900 Subject: [PATCH 3/8] lib: fdtdec: drop the old compatible about max77686 Drop the old compatible about max77686. Signed-off-by: Jaehoon Chung Acked-by: Lukasz Majewski --- include/fdtdec.h | 1 - lib/fdtdec.c | 1 - 2 files changed, 2 deletions(-) diff --git a/include/fdtdec.h b/include/fdtdec.h index eca6e98..5456a17 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -136,7 +136,6 @@ enum fdt_compat_id { COMPAT_SAMSUNG_EXYNOS_MIPI_DSI, /* Exynos mipi dsi */ COMPAT_SAMSUNG_EXYNOS_DWMMC, /* Exynos DWMMC controller */ COMPAT_SAMSUNG_EXYNOS_MMC, /* Exynos MMC controller */ - COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */ COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */ COMPAT_MAXIM_98095_CODEC, /* MAX98095 Codec */ COMPAT_SAMSUNG_EXYNOS5_I2C, /* Exynos5 High Speed I2C Controller */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 7ef6530..69bf126 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -48,7 +48,6 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"), COMPAT(SAMSUNG_EXYNOS_DWMMC, "samsung,exynos-dwmmc"), COMPAT(SAMSUNG_EXYNOS_MMC, "samsung,exynos-mmc"), - COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686"), COMPAT(GENERIC_SPI_FLASH, "spi-flash"), COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"), COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"), From 65117182543e58ba69f4abdc998423798137cbae Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 26 Jan 2018 19:25:29 +0900 Subject: [PATCH 4/8] mmc: add the MMC_CLK_ENABLE/DISABLE macro in mmc.h mmc_set_clock() function has the disable argument as bool type. When mmc_set_clock is called, it might be passed to "true" or "false". But it's too confusion whether clock is enabled or disabled with only "true" and "false". To prevent the confusion, replace to MMC_CLK_ENABLE/DISABLE macro from true/false. Signed-off-by: Jaehoon Chung --- drivers/mmc/fsl_esdhc.c | 2 +- drivers/mmc/meson_gx_mmc.c | 2 +- drivers/mmc/mmc.c | 18 ++++++++++-------- include/mmc.h | 3 +++ 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 1a006fa..4528345 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -982,7 +982,7 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) #endif /* Set the initial clock speed */ - mmc_set_clock(mmc, 400000, false); + mmc_set_clock(mmc, 400000, MMC_CLK_ENABLE); /* Disable the BRR and BWR bits in IRQSTAT */ esdhc_clrbits32(®s->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR); diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c index 0aea477..332f1e1 100644 --- a/drivers/mmc/meson_gx_mmc.c +++ b/drivers/mmc/meson_gx_mmc.c @@ -252,7 +252,7 @@ static int meson_mmc_probe(struct udevice *dev) mmc->priv = pdata; upriv->mmc = mmc; - mmc_set_clock(mmc, cfg->f_min, false); + mmc_set_clock(mmc, cfg->f_min, MMC_CLK_ENABLE); /* reset all status bits */ meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 01a02fb..29971a5 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -529,7 +529,7 @@ static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage) * During a signal voltage level switch, the clock must be gated * for 5 ms according to the SD spec */ - mmc_set_clock(mmc, mmc->clock, true); + mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); err = mmc_set_signal_voltage(mmc, signal_voltage); if (err) @@ -537,7 +537,7 @@ static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage) /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ mdelay(10); - mmc_set_clock(mmc, mmc->clock, false); + mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); /* * Failure to switch is indicated by the card holding @@ -1672,7 +1672,8 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) /* configure the bus mode (host) */ mmc_select_mode(mmc, mwt->mode); - mmc_set_clock(mmc, mmc->tran_speed, false); + mmc_set_clock(mmc, mmc->tran_speed, + MMC_CLK_ENABLE); #ifdef MMC_SUPPORTS_TUNING /* execute tuning if needed */ @@ -1697,7 +1698,8 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) error: /* revert to a safer bus speed */ mmc_select_mode(mmc, SD_LEGACY); - mmc_set_clock(mmc, mmc->tran_speed, false); + mmc_set_clock(mmc, mmc->tran_speed, + MMC_CLK_ENABLE); } } } @@ -1858,7 +1860,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) return -ENOTSUPP; } - mmc_set_clock(mmc, mmc->legacy_speed, false); + mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE); for_each_mmc_mode_by_pref(card_caps, mwt) { for_each_supported_width(card_caps & mwt->widths, @@ -1901,7 +1903,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) /* configure the bus mode (host) */ mmc_select_mode(mmc, mwt->mode); - mmc_set_clock(mmc, mmc->tran_speed, false); + mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE); #ifdef MMC_SUPPORTS_TUNING /* execute tuning if needed */ @@ -2426,7 +2428,7 @@ static void mmc_set_initial_state(struct mmc *mmc) mmc_select_mode(mmc, MMC_LEGACY); mmc_set_bus_width(mmc, 1); - mmc_set_clock(mmc, 0, false); + mmc_set_clock(mmc, 0, MMC_CLK_ENABLE); } static int mmc_power_on(struct mmc *mmc) @@ -2446,7 +2448,7 @@ static int mmc_power_on(struct mmc *mmc) static int mmc_power_off(struct mmc *mmc) { - mmc_set_clock(mmc, 0, true); + mmc_set_clock(mmc, 0, MMC_CLK_DISABLE); #if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR) if (mmc->vmmc_supply) { int ret = regulator_set_enable(mmc->vmmc_supply, false); diff --git a/include/mmc.h b/include/mmc.h index d9611a0..534c317 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -707,6 +707,9 @@ int mmc_voltage_to_mv(enum mmc_voltage voltage); */ int mmc_set_clock(struct mmc *mmc, uint clock, bool disable); +#define MMC_CLK_ENABLE false +#define MMC_CLK_DISABLE true + struct mmc *find_mmc_device(int dev_num); int mmc_set_dev(int dev_num); void print_mmc_devices(char separator); From d2faadb59c2be743854fe8e084def919c19b9634 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 26 Jan 2018 19:25:30 +0900 Subject: [PATCH 5/8] mmc: add the debug message in mmc_set_clock Add the debug message for checking the mmc clock status. It's helpful to debug the controlling clock. Signed-off-by: Jaehoon Chung --- drivers/mmc/mmc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 29971a5..a08c694 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1506,6 +1506,8 @@ int mmc_set_clock(struct mmc *mmc, uint clock, bool disable) mmc->clock = clock; mmc->clk_disable = disable; + debug("clock is %s (%dHz)\n", disable ? "disabled" : "enabled", clock); + return mmc_set_ios(mmc); } From 72b5a0371d2586607c6c66df8438b734d2562658 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 26 Jan 2018 19:25:31 +0900 Subject: [PATCH 6/8] mmc: Kconfig: add the MMC_TRACE config in Kconfig Add the MMC_TRACE config in Kconfig. Signed-off-by: Jaehoon Chung --- drivers/mmc/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 4fa8dd8..3f15f85 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -124,6 +124,14 @@ config MMC_VERBOSE Enable the output of more information about the card such as the operating mode. +config MMC_TRACE + bool "MMC debugging" + default n + help + This is an option for use by developer. Enable MMC core debugging. + + If you need to see the MMC core message, say Y. + config SPL_MMC_TINY bool "Tiny MMC framework in SPL" help From 55118ec90c316daed6a50e28da618de4545647b0 Mon Sep 17 00:00:00 2001 From: Patrick Bruenn Date: Tue, 6 Mar 2018 09:07:23 +0100 Subject: [PATCH 7/8] dm: mmc: socfpga: call dwmci_probe() On a socfpga_cyclone5 based board the SD card, was never powered up. For other dw_mmc based SoCs dwmci_probe() is called in the platform specific probe(). It seems this call is missing for socfpga_dw_mmc. With this change DWMCI_PWREN is set by dmwci_init(). Signed-off-by: Patrick Bruenn Reviewed-by: Jaehoon Chung --- drivers/mmc/socfpga_dw_mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index fa0e449..d0a0362 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -123,7 +123,7 @@ static int socfpga_dwmmc_probe(struct udevice *dev) upriv->mmc = host->mmc; host->mmc->dev = dev; - return 0; + return dwmci_probe(dev); } static int socfpga_dwmmc_bind(struct udevice *dev) From e1fd9e6bb88a3f42e7e89e9c59589dbf904efe23 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Tue, 27 Mar 2018 19:39:38 +0800 Subject: [PATCH 8/8] power: pwm regulator: support live tree Use live tree compatible api for pwm regulator. Signed-off-by: Andy Yan Reviewed-by: Kever Yang --- drivers/power/regulator/pwm_regulator.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/power/regulator/pwm_regulator.c b/drivers/power/regulator/pwm_regulator.c index f353c38..cd05c9b 100644 --- a/drivers/power/regulator/pwm_regulator.c +++ b/drivers/power/regulator/pwm_regulator.c @@ -12,9 +12,6 @@ #include #include #include -#include -#include -#include DECLARE_GLOBAL_DATA_PTR; @@ -93,13 +90,10 @@ static int pwm_regulator_set_voltage(struct udevice *dev, int uvolt) 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(dev); + struct ofnode_phandle_args args; int ret; - ret = fdtdec_parse_phandle_with_args(blob, node, "pwms", "#pwm-cells", - 0, 0, &args); + ret = dev_read_phandle_with_args(dev, "pwms", "#pwm-cells", 0, 0, &args); if (ret) { debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret); return ret; @@ -108,14 +102,13 @@ static int pwm_regulator_ofdata_to_platdata(struct udevice *dev) priv->period_ns = args.args[1]; priv->polarity = args.args[2]; - priv->init_voltage = fdtdec_get_int(blob, node, - "regulator-init-microvolt", -1); + priv->init_voltage = dev_read_u32_default(dev, "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); + ret = uclass_get_device_by_ofnode(UCLASS_PWM, args.node, &priv->pwm); if (ret) { debug("%s: Cannot get PWM: ret=%d\n", __func__, ret); return ret;