Loading Documentation/devicetree/bindings/regulator/pwm-regulator.txt +25 −1 Original line number Diff line number Diff line Loading @@ -34,20 +34,44 @@ Only required for Voltage Table Mode: First cell is voltage in microvolts (uV) Second cell is duty-cycle in percent (%) Optional properties for Continuous mode: - pwm-dutycycle-unit: Integer value encoding the duty cycle unit. If not defined, <100> is assumed, meaning that pwm-dutycycle-range contains values expressed in percent. - pwm-dutycycle-range: Should contain 2 entries. The first entry is encoding the dutycycle for regulator-min-microvolt and the second one the dutycycle for regulator-max-microvolt. Duty cycle values are expressed in pwm-dutycycle-unit. If not defined, <0 100> is assumed. NB: To be clear, if voltage-table is provided, then the device will be used in Voltage Table Mode. If no voltage-table is provided, then the device will be used in Continuous Voltage Mode. Optional properties: -------------------- - enable-gpios: GPIO to use to enable/disable the regulator Any property defined as part of the core regulator binding can also be used. (See: ../regulator/regulator.txt) Continuous Voltage Example: Continuous Voltage With Enable GPIO Example: pwm_regulator { compatible = "pwm-regulator; pwms = <&pwm1 0 8448 0>; enable-gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; regulator-min-microvolt = <1016000>; regulator-max-microvolt = <1114000>; regulator-name = "vdd_logic"; /* unit == per-mille */ pwm-dutycycle-unit = <1000>; /* * Inverted PWM logic, and the duty cycle range is limited * to 30%-70%. */ pwm-dutycycle-range <700 300>; /* */ }; Voltage Table Example: Loading drivers/regulator/pwm-regulator.c +148 −48 Original line number Diff line number Diff line Loading @@ -20,6 +20,13 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/pwm.h> #include <linux/gpio/consumer.h> struct pwm_continuous_reg_data { unsigned int min_uV_dutycycle; unsigned int max_uV_dutycycle; unsigned int dutycycle_unit; }; struct pwm_regulator_data { /* Shared */ Loading @@ -28,6 +35,9 @@ struct pwm_regulator_data { /* Voltage table */ struct pwm_voltages *duty_cycle_table; /* Continuous mode info */ struct pwm_continuous_reg_data continuous; /* regulator descriptor */ struct regulator_desc desc; Loading @@ -36,8 +46,8 @@ struct pwm_regulator_data { int state; /* Continuous voltage */ int volt_uV; /* Enable GPIO */ struct gpio_desc *enb_gpio; }; struct pwm_voltages { Loading @@ -48,10 +58,31 @@ struct pwm_voltages { /** * Voltage table call-backs */ static void pwm_regulator_init_state(struct regulator_dev *rdev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); struct pwm_state pwm_state; unsigned int dutycycle; int i; pwm_get_state(drvdata->pwm, &pwm_state); dutycycle = pwm_get_relative_duty_cycle(&pwm_state, 100); for (i = 0; i < rdev->desc->n_voltages; i++) { if (dutycycle == drvdata->duty_cycle_table[i].dutycycle) { drvdata->state = i; return; } } } static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); if (drvdata->state < 0) pwm_regulator_init_state(rdev); return drvdata->state; } Loading @@ -59,16 +90,14 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); struct pwm_args pargs; int dutycycle; struct pwm_state pstate; int ret; pwm_get_args(drvdata->pwm, &pargs); pwm_init_state(drvdata->pwm, &pstate); pwm_set_relative_duty_cycle(&pstate, drvdata->duty_cycle_table[selector].dutycycle, 100); dutycycle = (pargs.period * drvdata->duty_cycle_table[selector].dutycycle) / 100; ret = pwm_config(drvdata->pwm, dutycycle, pargs.period); ret = pwm_apply_state(drvdata->pwm, &pstate); if (ret) { dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); return ret; Loading @@ -94,6 +123,9 @@ static int pwm_regulator_enable(struct regulator_dev *dev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); if (drvdata->enb_gpio) gpiod_set_value_cansleep(drvdata->enb_gpio, 1); return pwm_enable(drvdata->pwm); } Loading @@ -103,6 +135,9 @@ static int pwm_regulator_disable(struct regulator_dev *dev) pwm_disable(drvdata->pwm); if (drvdata->enb_gpio) gpiod_set_value_cansleep(drvdata->enb_gpio, 0); return 0; } Loading @@ -110,64 +145,100 @@ static int pwm_regulator_is_enabled(struct regulator_dev *dev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); if (drvdata->enb_gpio && !gpiod_get_value_cansleep(drvdata->enb_gpio)) return false; return pwm_is_enabled(drvdata->pwm); } static int pwm_regulator_get_voltage(struct regulator_dev *rdev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; unsigned int duty_unit = drvdata->continuous.dutycycle_unit; int min_uV = rdev->constraints->min_uV; int max_uV = rdev->constraints->max_uV; int diff_uV = max_uV - min_uV; struct pwm_state pstate; unsigned int diff_duty; unsigned int voltage; return drvdata->volt_uV; pwm_get_state(drvdata->pwm, &pstate); voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit); /* * The dutycycle for min_uV might be greater than the one for max_uV. * This is happening when the user needs an inversed polarity, but the * PWM device does not support inversing it in hardware. */ if (max_uV_duty < min_uV_duty) { voltage = min_uV_duty - voltage; diff_duty = min_uV_duty - max_uV_duty; } else { voltage = voltage - min_uV_duty; diff_duty = max_uV_duty - min_uV_duty; } voltage = DIV_ROUND_CLOSEST_ULL((u64)voltage * diff_uV, diff_duty); return voltage + min_uV; } static int pwm_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) int req_min_uV, int req_max_uV, unsigned int *selector) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; unsigned int duty_unit = drvdata->continuous.dutycycle_unit; unsigned int ramp_delay = rdev->constraints->ramp_delay; struct pwm_args pargs; unsigned int req_diff = min_uV - rdev->constraints->min_uV; unsigned int diff; unsigned int duty_pulse; u64 req_period; u32 rem; int min_uV = rdev->constraints->min_uV; int max_uV = rdev->constraints->max_uV; int diff_uV = max_uV - min_uV; struct pwm_state pstate; int old_uV = pwm_regulator_get_voltage(rdev); unsigned int diff_duty; unsigned int dutycycle; int ret; pwm_get_args(drvdata->pwm, &pargs); diff = rdev->constraints->max_uV - rdev->constraints->min_uV; pwm_init_state(drvdata->pwm, &pstate); /* First try to find out if we get the iduty cycle time which is * factor of PWM period time. If (request_diff_to_min * pwm_period) * is perfect divided by voltage_range_diff then it is possible to * get duty cycle time which is factor of PWM period. This will help * to get output voltage nearer to requested value as there is no * calculation loss. /* * The dutycycle for min_uV might be greater than the one for max_uV. * This is happening when the user needs an inversed polarity, but the * PWM device does not support inversing it in hardware. */ req_period = req_diff * pargs.period; div_u64_rem(req_period, diff, &rem); if (!rem) { do_div(req_period, diff); duty_pulse = (unsigned int)req_period; } else { duty_pulse = (pargs.period / 100) * ((req_diff * 100) / diff); } if (max_uV_duty < min_uV_duty) diff_duty = min_uV_duty - max_uV_duty; else diff_duty = max_uV_duty - min_uV_duty; dutycycle = DIV_ROUND_CLOSEST_ULL((u64)(req_min_uV - min_uV) * diff_duty, diff_uV); if (max_uV_duty < min_uV_duty) dutycycle = min_uV_duty - dutycycle; else dutycycle = min_uV_duty + dutycycle; ret = pwm_config(drvdata->pwm, duty_pulse, pargs.period); pwm_set_relative_duty_cycle(&pstate, dutycycle, duty_unit); ret = pwm_apply_state(drvdata->pwm, &pstate); if (ret) { dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); return ret; } ret = pwm_enable(drvdata->pwm); if (ret) { dev_err(&rdev->dev, "Failed to enable PWM: %d\n", ret); return ret; } drvdata->volt_uV = min_uV; if ((ramp_delay == 0) || !pwm_regulator_is_enabled(rdev)) return 0; /* Delay required by PWM regulator to settle to the new voltage */ usleep_range(ramp_delay, ramp_delay + 1000); /* Ramp delay is in uV/uS. Adjust to uS and delay */ ramp_delay = DIV_ROUND_UP(abs(req_min_uV - old_uV), ramp_delay); usleep_range(ramp_delay, ramp_delay + DIV_ROUND_UP(ramp_delay, 10)); return 0; } Loading Loading @@ -226,6 +297,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev, return ret; } drvdata->state = -EINVAL; drvdata->duty_cycle_table = duty_cycle_table; memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops, sizeof(drvdata->ops)); Loading @@ -238,11 +310,28 @@ static int pwm_regulator_init_table(struct platform_device *pdev, static int pwm_regulator_init_continuous(struct platform_device *pdev, struct pwm_regulator_data *drvdata) { u32 dutycycle_range[2] = { 0, 100 }; u32 dutycycle_unit = 100; memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops, sizeof(drvdata->ops)); drvdata->desc.ops = &drvdata->ops; drvdata->desc.continuous_voltage_range = true; of_property_read_u32_array(pdev->dev.of_node, "pwm-dutycycle-range", dutycycle_range, 2); of_property_read_u32(pdev->dev.of_node, "pwm-dutycycle-unit", &dutycycle_unit); if (dutycycle_range[0] > dutycycle_unit || dutycycle_range[1] > dutycycle_unit) return -EINVAL; drvdata->continuous.dutycycle_unit = dutycycle_unit; drvdata->continuous.min_uV_dutycycle = dutycycle_range[0]; drvdata->continuous.max_uV_dutycycle = dutycycle_range[1]; return 0; } Loading @@ -253,6 +342,7 @@ static int pwm_regulator_probe(struct platform_device *pdev) struct regulator_dev *regulator; struct regulator_config config = { }; struct device_node *np = pdev->dev.of_node; enum gpiod_flags gpio_flags; int ret; if (!np) { Loading Loading @@ -290,11 +380,21 @@ static int pwm_regulator_probe(struct platform_device *pdev) return ret; } /* * FIXME: pwm_apply_args() should be removed when switching to the * atomic PWM API. */ pwm_apply_args(drvdata->pwm); if (init_data->constraints.boot_on || init_data->constraints.always_on) gpio_flags = GPIOD_OUT_HIGH; else gpio_flags = GPIOD_OUT_LOW; drvdata->enb_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", gpio_flags); if (IS_ERR(drvdata->enb_gpio)) { ret = PTR_ERR(drvdata->enb_gpio); dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n", ret); return ret; } ret = pwm_adjust_config(drvdata->pwm); if (ret) return ret; regulator = devm_regulator_register(&pdev->dev, &drvdata->desc, &config); Loading Loading
Documentation/devicetree/bindings/regulator/pwm-regulator.txt +25 −1 Original line number Diff line number Diff line Loading @@ -34,20 +34,44 @@ Only required for Voltage Table Mode: First cell is voltage in microvolts (uV) Second cell is duty-cycle in percent (%) Optional properties for Continuous mode: - pwm-dutycycle-unit: Integer value encoding the duty cycle unit. If not defined, <100> is assumed, meaning that pwm-dutycycle-range contains values expressed in percent. - pwm-dutycycle-range: Should contain 2 entries. The first entry is encoding the dutycycle for regulator-min-microvolt and the second one the dutycycle for regulator-max-microvolt. Duty cycle values are expressed in pwm-dutycycle-unit. If not defined, <0 100> is assumed. NB: To be clear, if voltage-table is provided, then the device will be used in Voltage Table Mode. If no voltage-table is provided, then the device will be used in Continuous Voltage Mode. Optional properties: -------------------- - enable-gpios: GPIO to use to enable/disable the regulator Any property defined as part of the core regulator binding can also be used. (See: ../regulator/regulator.txt) Continuous Voltage Example: Continuous Voltage With Enable GPIO Example: pwm_regulator { compatible = "pwm-regulator; pwms = <&pwm1 0 8448 0>; enable-gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; regulator-min-microvolt = <1016000>; regulator-max-microvolt = <1114000>; regulator-name = "vdd_logic"; /* unit == per-mille */ pwm-dutycycle-unit = <1000>; /* * Inverted PWM logic, and the duty cycle range is limited * to 30%-70%. */ pwm-dutycycle-range <700 300>; /* */ }; Voltage Table Example: Loading
drivers/regulator/pwm-regulator.c +148 −48 Original line number Diff line number Diff line Loading @@ -20,6 +20,13 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/pwm.h> #include <linux/gpio/consumer.h> struct pwm_continuous_reg_data { unsigned int min_uV_dutycycle; unsigned int max_uV_dutycycle; unsigned int dutycycle_unit; }; struct pwm_regulator_data { /* Shared */ Loading @@ -28,6 +35,9 @@ struct pwm_regulator_data { /* Voltage table */ struct pwm_voltages *duty_cycle_table; /* Continuous mode info */ struct pwm_continuous_reg_data continuous; /* regulator descriptor */ struct regulator_desc desc; Loading @@ -36,8 +46,8 @@ struct pwm_regulator_data { int state; /* Continuous voltage */ int volt_uV; /* Enable GPIO */ struct gpio_desc *enb_gpio; }; struct pwm_voltages { Loading @@ -48,10 +58,31 @@ struct pwm_voltages { /** * Voltage table call-backs */ static void pwm_regulator_init_state(struct regulator_dev *rdev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); struct pwm_state pwm_state; unsigned int dutycycle; int i; pwm_get_state(drvdata->pwm, &pwm_state); dutycycle = pwm_get_relative_duty_cycle(&pwm_state, 100); for (i = 0; i < rdev->desc->n_voltages; i++) { if (dutycycle == drvdata->duty_cycle_table[i].dutycycle) { drvdata->state = i; return; } } } static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); if (drvdata->state < 0) pwm_regulator_init_state(rdev); return drvdata->state; } Loading @@ -59,16 +90,14 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); struct pwm_args pargs; int dutycycle; struct pwm_state pstate; int ret; pwm_get_args(drvdata->pwm, &pargs); pwm_init_state(drvdata->pwm, &pstate); pwm_set_relative_duty_cycle(&pstate, drvdata->duty_cycle_table[selector].dutycycle, 100); dutycycle = (pargs.period * drvdata->duty_cycle_table[selector].dutycycle) / 100; ret = pwm_config(drvdata->pwm, dutycycle, pargs.period); ret = pwm_apply_state(drvdata->pwm, &pstate); if (ret) { dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); return ret; Loading @@ -94,6 +123,9 @@ static int pwm_regulator_enable(struct regulator_dev *dev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); if (drvdata->enb_gpio) gpiod_set_value_cansleep(drvdata->enb_gpio, 1); return pwm_enable(drvdata->pwm); } Loading @@ -103,6 +135,9 @@ static int pwm_regulator_disable(struct regulator_dev *dev) pwm_disable(drvdata->pwm); if (drvdata->enb_gpio) gpiod_set_value_cansleep(drvdata->enb_gpio, 0); return 0; } Loading @@ -110,64 +145,100 @@ static int pwm_regulator_is_enabled(struct regulator_dev *dev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); if (drvdata->enb_gpio && !gpiod_get_value_cansleep(drvdata->enb_gpio)) return false; return pwm_is_enabled(drvdata->pwm); } static int pwm_regulator_get_voltage(struct regulator_dev *rdev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; unsigned int duty_unit = drvdata->continuous.dutycycle_unit; int min_uV = rdev->constraints->min_uV; int max_uV = rdev->constraints->max_uV; int diff_uV = max_uV - min_uV; struct pwm_state pstate; unsigned int diff_duty; unsigned int voltage; return drvdata->volt_uV; pwm_get_state(drvdata->pwm, &pstate); voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit); /* * The dutycycle for min_uV might be greater than the one for max_uV. * This is happening when the user needs an inversed polarity, but the * PWM device does not support inversing it in hardware. */ if (max_uV_duty < min_uV_duty) { voltage = min_uV_duty - voltage; diff_duty = min_uV_duty - max_uV_duty; } else { voltage = voltage - min_uV_duty; diff_duty = max_uV_duty - min_uV_duty; } voltage = DIV_ROUND_CLOSEST_ULL((u64)voltage * diff_uV, diff_duty); return voltage + min_uV; } static int pwm_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) int req_min_uV, int req_max_uV, unsigned int *selector) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; unsigned int duty_unit = drvdata->continuous.dutycycle_unit; unsigned int ramp_delay = rdev->constraints->ramp_delay; struct pwm_args pargs; unsigned int req_diff = min_uV - rdev->constraints->min_uV; unsigned int diff; unsigned int duty_pulse; u64 req_period; u32 rem; int min_uV = rdev->constraints->min_uV; int max_uV = rdev->constraints->max_uV; int diff_uV = max_uV - min_uV; struct pwm_state pstate; int old_uV = pwm_regulator_get_voltage(rdev); unsigned int diff_duty; unsigned int dutycycle; int ret; pwm_get_args(drvdata->pwm, &pargs); diff = rdev->constraints->max_uV - rdev->constraints->min_uV; pwm_init_state(drvdata->pwm, &pstate); /* First try to find out if we get the iduty cycle time which is * factor of PWM period time. If (request_diff_to_min * pwm_period) * is perfect divided by voltage_range_diff then it is possible to * get duty cycle time which is factor of PWM period. This will help * to get output voltage nearer to requested value as there is no * calculation loss. /* * The dutycycle for min_uV might be greater than the one for max_uV. * This is happening when the user needs an inversed polarity, but the * PWM device does not support inversing it in hardware. */ req_period = req_diff * pargs.period; div_u64_rem(req_period, diff, &rem); if (!rem) { do_div(req_period, diff); duty_pulse = (unsigned int)req_period; } else { duty_pulse = (pargs.period / 100) * ((req_diff * 100) / diff); } if (max_uV_duty < min_uV_duty) diff_duty = min_uV_duty - max_uV_duty; else diff_duty = max_uV_duty - min_uV_duty; dutycycle = DIV_ROUND_CLOSEST_ULL((u64)(req_min_uV - min_uV) * diff_duty, diff_uV); if (max_uV_duty < min_uV_duty) dutycycle = min_uV_duty - dutycycle; else dutycycle = min_uV_duty + dutycycle; ret = pwm_config(drvdata->pwm, duty_pulse, pargs.period); pwm_set_relative_duty_cycle(&pstate, dutycycle, duty_unit); ret = pwm_apply_state(drvdata->pwm, &pstate); if (ret) { dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); return ret; } ret = pwm_enable(drvdata->pwm); if (ret) { dev_err(&rdev->dev, "Failed to enable PWM: %d\n", ret); return ret; } drvdata->volt_uV = min_uV; if ((ramp_delay == 0) || !pwm_regulator_is_enabled(rdev)) return 0; /* Delay required by PWM regulator to settle to the new voltage */ usleep_range(ramp_delay, ramp_delay + 1000); /* Ramp delay is in uV/uS. Adjust to uS and delay */ ramp_delay = DIV_ROUND_UP(abs(req_min_uV - old_uV), ramp_delay); usleep_range(ramp_delay, ramp_delay + DIV_ROUND_UP(ramp_delay, 10)); return 0; } Loading Loading @@ -226,6 +297,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev, return ret; } drvdata->state = -EINVAL; drvdata->duty_cycle_table = duty_cycle_table; memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops, sizeof(drvdata->ops)); Loading @@ -238,11 +310,28 @@ static int pwm_regulator_init_table(struct platform_device *pdev, static int pwm_regulator_init_continuous(struct platform_device *pdev, struct pwm_regulator_data *drvdata) { u32 dutycycle_range[2] = { 0, 100 }; u32 dutycycle_unit = 100; memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops, sizeof(drvdata->ops)); drvdata->desc.ops = &drvdata->ops; drvdata->desc.continuous_voltage_range = true; of_property_read_u32_array(pdev->dev.of_node, "pwm-dutycycle-range", dutycycle_range, 2); of_property_read_u32(pdev->dev.of_node, "pwm-dutycycle-unit", &dutycycle_unit); if (dutycycle_range[0] > dutycycle_unit || dutycycle_range[1] > dutycycle_unit) return -EINVAL; drvdata->continuous.dutycycle_unit = dutycycle_unit; drvdata->continuous.min_uV_dutycycle = dutycycle_range[0]; drvdata->continuous.max_uV_dutycycle = dutycycle_range[1]; return 0; } Loading @@ -253,6 +342,7 @@ static int pwm_regulator_probe(struct platform_device *pdev) struct regulator_dev *regulator; struct regulator_config config = { }; struct device_node *np = pdev->dev.of_node; enum gpiod_flags gpio_flags; int ret; if (!np) { Loading Loading @@ -290,11 +380,21 @@ static int pwm_regulator_probe(struct platform_device *pdev) return ret; } /* * FIXME: pwm_apply_args() should be removed when switching to the * atomic PWM API. */ pwm_apply_args(drvdata->pwm); if (init_data->constraints.boot_on || init_data->constraints.always_on) gpio_flags = GPIOD_OUT_HIGH; else gpio_flags = GPIOD_OUT_LOW; drvdata->enb_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", gpio_flags); if (IS_ERR(drvdata->enb_gpio)) { ret = PTR_ERR(drvdata->enb_gpio); dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n", ret); return ret; } ret = pwm_adjust_config(drvdata->pwm); if (ret) return ret; regulator = devm_regulator_register(&pdev->dev, &drvdata->desc, &config); Loading