162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Regulator driver for PWM Regulators 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2014 - STMicroelectronics Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Lee Jones <lee.jones@linaro.org> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/init.h> 1262306a36Sopenharmony_ci#include <linux/err.h> 1362306a36Sopenharmony_ci#include <linux/platform_device.h> 1462306a36Sopenharmony_ci#include <linux/regulator/driver.h> 1562306a36Sopenharmony_ci#include <linux/regulator/machine.h> 1662306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h> 1762306a36Sopenharmony_ci#include <linux/of.h> 1862306a36Sopenharmony_ci#include <linux/pwm.h> 1962306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistruct pwm_continuous_reg_data { 2262306a36Sopenharmony_ci unsigned int min_uV_dutycycle; 2362306a36Sopenharmony_ci unsigned int max_uV_dutycycle; 2462306a36Sopenharmony_ci unsigned int dutycycle_unit; 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistruct pwm_regulator_data { 2862306a36Sopenharmony_ci /* Shared */ 2962306a36Sopenharmony_ci struct pwm_device *pwm; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci /* Voltage table */ 3262306a36Sopenharmony_ci struct pwm_voltages *duty_cycle_table; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci /* Continuous mode info */ 3562306a36Sopenharmony_ci struct pwm_continuous_reg_data continuous; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci /* regulator descriptor */ 3862306a36Sopenharmony_ci struct regulator_desc desc; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci int state; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci /* Enable GPIO */ 4362306a36Sopenharmony_ci struct gpio_desc *enb_gpio; 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct pwm_voltages { 4762306a36Sopenharmony_ci unsigned int uV; 4862306a36Sopenharmony_ci unsigned int dutycycle; 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* 5262306a36Sopenharmony_ci * Voltage table call-backs 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_cistatic void pwm_regulator_init_state(struct regulator_dev *rdev) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 5762306a36Sopenharmony_ci struct pwm_state pwm_state; 5862306a36Sopenharmony_ci unsigned int dutycycle; 5962306a36Sopenharmony_ci int i; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci pwm_get_state(drvdata->pwm, &pwm_state); 6262306a36Sopenharmony_ci dutycycle = pwm_get_relative_duty_cycle(&pwm_state, 100); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci for (i = 0; i < rdev->desc->n_voltages; i++) { 6562306a36Sopenharmony_ci if (dutycycle == drvdata->duty_cycle_table[i].dutycycle) { 6662306a36Sopenharmony_ci drvdata->state = i; 6762306a36Sopenharmony_ci return; 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (drvdata->state < 0) 7762306a36Sopenharmony_ci pwm_regulator_init_state(rdev); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci return drvdata->state; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev, 8362306a36Sopenharmony_ci unsigned selector) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 8662306a36Sopenharmony_ci struct pwm_state pstate; 8762306a36Sopenharmony_ci int ret; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci pwm_init_state(drvdata->pwm, &pstate); 9062306a36Sopenharmony_ci pwm_set_relative_duty_cycle(&pstate, 9162306a36Sopenharmony_ci drvdata->duty_cycle_table[selector].dutycycle, 100); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci ret = pwm_apply_state(drvdata->pwm, &pstate); 9462306a36Sopenharmony_ci if (ret) { 9562306a36Sopenharmony_ci dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); 9662306a36Sopenharmony_ci return ret; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci drvdata->state = selector; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci return 0; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic int pwm_regulator_list_voltage(struct regulator_dev *rdev, 10562306a36Sopenharmony_ci unsigned selector) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (selector >= rdev->desc->n_voltages) 11062306a36Sopenharmony_ci return -EINVAL; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci return drvdata->duty_cycle_table[selector].uV; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic int pwm_regulator_enable(struct regulator_dev *dev) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci gpiod_set_value_cansleep(drvdata->enb_gpio, 1); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return pwm_enable(drvdata->pwm); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic int pwm_regulator_disable(struct regulator_dev *dev) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci pwm_disable(drvdata->pwm); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci gpiod_set_value_cansleep(drvdata->enb_gpio, 0); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci return 0; 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic int pwm_regulator_is_enabled(struct regulator_dev *dev) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if (drvdata->enb_gpio && !gpiod_get_value_cansleep(drvdata->enb_gpio)) 14062306a36Sopenharmony_ci return false; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return pwm_is_enabled(drvdata->pwm); 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic int pwm_regulator_get_voltage(struct regulator_dev *rdev) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 14862306a36Sopenharmony_ci unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; 14962306a36Sopenharmony_ci unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; 15062306a36Sopenharmony_ci unsigned int duty_unit = drvdata->continuous.dutycycle_unit; 15162306a36Sopenharmony_ci int min_uV = rdev->constraints->min_uV; 15262306a36Sopenharmony_ci int max_uV = rdev->constraints->max_uV; 15362306a36Sopenharmony_ci int diff_uV = max_uV - min_uV; 15462306a36Sopenharmony_ci struct pwm_state pstate; 15562306a36Sopenharmony_ci unsigned int diff_duty; 15662306a36Sopenharmony_ci unsigned int voltage; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci pwm_get_state(drvdata->pwm, &pstate); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit); 16162306a36Sopenharmony_ci if (voltage < min(max_uV_duty, min_uV_duty) || 16262306a36Sopenharmony_ci voltage > max(max_uV_duty, min_uV_duty)) 16362306a36Sopenharmony_ci return -ENOTRECOVERABLE; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* 16662306a36Sopenharmony_ci * The dutycycle for min_uV might be greater than the one for max_uV. 16762306a36Sopenharmony_ci * This is happening when the user needs an inversed polarity, but the 16862306a36Sopenharmony_ci * PWM device does not support inversing it in hardware. 16962306a36Sopenharmony_ci */ 17062306a36Sopenharmony_ci if (max_uV_duty < min_uV_duty) { 17162306a36Sopenharmony_ci voltage = min_uV_duty - voltage; 17262306a36Sopenharmony_ci diff_duty = min_uV_duty - max_uV_duty; 17362306a36Sopenharmony_ci } else { 17462306a36Sopenharmony_ci voltage = voltage - min_uV_duty; 17562306a36Sopenharmony_ci diff_duty = max_uV_duty - min_uV_duty; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci voltage = DIV_ROUND_CLOSEST_ULL((u64)voltage * diff_uV, diff_duty); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return voltage + min_uV; 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int pwm_regulator_set_voltage(struct regulator_dev *rdev, 18462306a36Sopenharmony_ci int req_min_uV, int req_max_uV, 18562306a36Sopenharmony_ci unsigned int *selector) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 18862306a36Sopenharmony_ci unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; 18962306a36Sopenharmony_ci unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; 19062306a36Sopenharmony_ci unsigned int duty_unit = drvdata->continuous.dutycycle_unit; 19162306a36Sopenharmony_ci int min_uV = rdev->constraints->min_uV; 19262306a36Sopenharmony_ci int max_uV = rdev->constraints->max_uV; 19362306a36Sopenharmony_ci int diff_uV = max_uV - min_uV; 19462306a36Sopenharmony_ci struct pwm_state pstate; 19562306a36Sopenharmony_ci unsigned int diff_duty; 19662306a36Sopenharmony_ci unsigned int dutycycle; 19762306a36Sopenharmony_ci int ret; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci pwm_init_state(drvdata->pwm, &pstate); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* 20262306a36Sopenharmony_ci * The dutycycle for min_uV might be greater than the one for max_uV. 20362306a36Sopenharmony_ci * This is happening when the user needs an inversed polarity, but the 20462306a36Sopenharmony_ci * PWM device does not support inversing it in hardware. 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_ci if (max_uV_duty < min_uV_duty) 20762306a36Sopenharmony_ci diff_duty = min_uV_duty - max_uV_duty; 20862306a36Sopenharmony_ci else 20962306a36Sopenharmony_ci diff_duty = max_uV_duty - min_uV_duty; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci dutycycle = DIV_ROUND_CLOSEST_ULL((u64)(req_min_uV - min_uV) * 21262306a36Sopenharmony_ci diff_duty, 21362306a36Sopenharmony_ci diff_uV); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci if (max_uV_duty < min_uV_duty) 21662306a36Sopenharmony_ci dutycycle = min_uV_duty - dutycycle; 21762306a36Sopenharmony_ci else 21862306a36Sopenharmony_ci dutycycle = min_uV_duty + dutycycle; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci pwm_set_relative_duty_cycle(&pstate, dutycycle, duty_unit); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci ret = pwm_apply_state(drvdata->pwm, &pstate); 22362306a36Sopenharmony_ci if (ret) { 22462306a36Sopenharmony_ci dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); 22562306a36Sopenharmony_ci return ret; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci return 0; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic const struct regulator_ops pwm_regulator_voltage_table_ops = { 23262306a36Sopenharmony_ci .set_voltage_sel = pwm_regulator_set_voltage_sel, 23362306a36Sopenharmony_ci .get_voltage_sel = pwm_regulator_get_voltage_sel, 23462306a36Sopenharmony_ci .list_voltage = pwm_regulator_list_voltage, 23562306a36Sopenharmony_ci .map_voltage = regulator_map_voltage_iterate, 23662306a36Sopenharmony_ci .enable = pwm_regulator_enable, 23762306a36Sopenharmony_ci .disable = pwm_regulator_disable, 23862306a36Sopenharmony_ci .is_enabled = pwm_regulator_is_enabled, 23962306a36Sopenharmony_ci}; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic const struct regulator_ops pwm_regulator_voltage_continuous_ops = { 24262306a36Sopenharmony_ci .get_voltage = pwm_regulator_get_voltage, 24362306a36Sopenharmony_ci .set_voltage = pwm_regulator_set_voltage, 24462306a36Sopenharmony_ci .enable = pwm_regulator_enable, 24562306a36Sopenharmony_ci .disable = pwm_regulator_disable, 24662306a36Sopenharmony_ci .is_enabled = pwm_regulator_is_enabled, 24762306a36Sopenharmony_ci}; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic const struct regulator_desc pwm_regulator_desc = { 25062306a36Sopenharmony_ci .name = "pwm-regulator", 25162306a36Sopenharmony_ci .type = REGULATOR_VOLTAGE, 25262306a36Sopenharmony_ci .owner = THIS_MODULE, 25362306a36Sopenharmony_ci .supply_name = "pwm", 25462306a36Sopenharmony_ci}; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int pwm_regulator_init_table(struct platform_device *pdev, 25762306a36Sopenharmony_ci struct pwm_regulator_data *drvdata) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 26062306a36Sopenharmony_ci struct pwm_voltages *duty_cycle_table; 26162306a36Sopenharmony_ci unsigned int length = 0; 26262306a36Sopenharmony_ci int ret; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci of_find_property(np, "voltage-table", &length); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if ((length < sizeof(*duty_cycle_table)) || 26762306a36Sopenharmony_ci (length % sizeof(*duty_cycle_table))) { 26862306a36Sopenharmony_ci dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n", 26962306a36Sopenharmony_ci length); 27062306a36Sopenharmony_ci return -EINVAL; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci duty_cycle_table = devm_kzalloc(&pdev->dev, length, GFP_KERNEL); 27462306a36Sopenharmony_ci if (!duty_cycle_table) 27562306a36Sopenharmony_ci return -ENOMEM; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci ret = of_property_read_u32_array(np, "voltage-table", 27862306a36Sopenharmony_ci (u32 *)duty_cycle_table, 27962306a36Sopenharmony_ci length / sizeof(u32)); 28062306a36Sopenharmony_ci if (ret) { 28162306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to read voltage-table: %d\n", ret); 28262306a36Sopenharmony_ci return ret; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci drvdata->state = -ENOTRECOVERABLE; 28662306a36Sopenharmony_ci drvdata->duty_cycle_table = duty_cycle_table; 28762306a36Sopenharmony_ci drvdata->desc.ops = &pwm_regulator_voltage_table_ops; 28862306a36Sopenharmony_ci drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci return 0; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic int pwm_regulator_init_continuous(struct platform_device *pdev, 29462306a36Sopenharmony_ci struct pwm_regulator_data *drvdata) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci u32 dutycycle_range[2] = { 0, 100 }; 29762306a36Sopenharmony_ci u32 dutycycle_unit = 100; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci drvdata->desc.ops = &pwm_regulator_voltage_continuous_ops; 30062306a36Sopenharmony_ci drvdata->desc.continuous_voltage_range = true; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci of_property_read_u32_array(pdev->dev.of_node, 30362306a36Sopenharmony_ci "pwm-dutycycle-range", 30462306a36Sopenharmony_ci dutycycle_range, 2); 30562306a36Sopenharmony_ci of_property_read_u32(pdev->dev.of_node, "pwm-dutycycle-unit", 30662306a36Sopenharmony_ci &dutycycle_unit); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (dutycycle_range[0] > dutycycle_unit || 30962306a36Sopenharmony_ci dutycycle_range[1] > dutycycle_unit) 31062306a36Sopenharmony_ci return -EINVAL; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci drvdata->continuous.dutycycle_unit = dutycycle_unit; 31362306a36Sopenharmony_ci drvdata->continuous.min_uV_dutycycle = dutycycle_range[0]; 31462306a36Sopenharmony_ci drvdata->continuous.max_uV_dutycycle = dutycycle_range[1]; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return 0; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic int pwm_regulator_probe(struct platform_device *pdev) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci const struct regulator_init_data *init_data; 32262306a36Sopenharmony_ci struct pwm_regulator_data *drvdata; 32362306a36Sopenharmony_ci struct regulator_dev *regulator; 32462306a36Sopenharmony_ci struct regulator_config config = { }; 32562306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 32662306a36Sopenharmony_ci enum gpiod_flags gpio_flags; 32762306a36Sopenharmony_ci int ret; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if (!np) { 33062306a36Sopenharmony_ci dev_err(&pdev->dev, "Device Tree node missing\n"); 33162306a36Sopenharmony_ci return -EINVAL; 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); 33562306a36Sopenharmony_ci if (!drvdata) 33662306a36Sopenharmony_ci return -ENOMEM; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(drvdata->desc)); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (of_property_present(np, "voltage-table")) 34162306a36Sopenharmony_ci ret = pwm_regulator_init_table(pdev, drvdata); 34262306a36Sopenharmony_ci else 34362306a36Sopenharmony_ci ret = pwm_regulator_init_continuous(pdev, drvdata); 34462306a36Sopenharmony_ci if (ret) 34562306a36Sopenharmony_ci return ret; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci init_data = of_get_regulator_init_data(&pdev->dev, np, 34862306a36Sopenharmony_ci &drvdata->desc); 34962306a36Sopenharmony_ci if (!init_data) 35062306a36Sopenharmony_ci return -ENOMEM; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci config.of_node = np; 35362306a36Sopenharmony_ci config.dev = &pdev->dev; 35462306a36Sopenharmony_ci config.driver_data = drvdata; 35562306a36Sopenharmony_ci config.init_data = init_data; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); 35862306a36Sopenharmony_ci if (IS_ERR(drvdata->pwm)) 35962306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(drvdata->pwm), 36062306a36Sopenharmony_ci "Failed to get PWM\n"); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (init_data->constraints.boot_on || init_data->constraints.always_on) 36362306a36Sopenharmony_ci gpio_flags = GPIOD_OUT_HIGH; 36462306a36Sopenharmony_ci else 36562306a36Sopenharmony_ci gpio_flags = GPIOD_OUT_LOW; 36662306a36Sopenharmony_ci drvdata->enb_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 36762306a36Sopenharmony_ci gpio_flags); 36862306a36Sopenharmony_ci if (IS_ERR(drvdata->enb_gpio)) { 36962306a36Sopenharmony_ci ret = PTR_ERR(drvdata->enb_gpio); 37062306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n", ret); 37162306a36Sopenharmony_ci return ret; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci ret = pwm_adjust_config(drvdata->pwm); 37562306a36Sopenharmony_ci if (ret) 37662306a36Sopenharmony_ci return ret; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci regulator = devm_regulator_register(&pdev->dev, 37962306a36Sopenharmony_ci &drvdata->desc, &config); 38062306a36Sopenharmony_ci if (IS_ERR(regulator)) { 38162306a36Sopenharmony_ci ret = PTR_ERR(regulator); 38262306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to register regulator %s: %d\n", 38362306a36Sopenharmony_ci drvdata->desc.name, ret); 38462306a36Sopenharmony_ci return ret; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci return 0; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic const struct of_device_id __maybe_unused pwm_of_match[] = { 39162306a36Sopenharmony_ci { .compatible = "pwm-regulator" }, 39262306a36Sopenharmony_ci { }, 39362306a36Sopenharmony_ci}; 39462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, pwm_of_match); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic struct platform_driver pwm_regulator_driver = { 39762306a36Sopenharmony_ci .driver = { 39862306a36Sopenharmony_ci .name = "pwm-regulator", 39962306a36Sopenharmony_ci .probe_type = PROBE_PREFER_ASYNCHRONOUS, 40062306a36Sopenharmony_ci .of_match_table = of_match_ptr(pwm_of_match), 40162306a36Sopenharmony_ci }, 40262306a36Sopenharmony_ci .probe = pwm_regulator_probe, 40362306a36Sopenharmony_ci}; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cimodule_platform_driver(pwm_regulator_driver); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 40862306a36Sopenharmony_ciMODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); 40962306a36Sopenharmony_ciMODULE_DESCRIPTION("PWM Regulator Driver"); 41062306a36Sopenharmony_ciMODULE_ALIAS("platform:pwm-regulator"); 411