1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2aa66cc66SChris Zhong /* 3aa66cc66SChris Zhong * Regulator driver for PWM Regulators 4aa66cc66SChris Zhong * 5aa66cc66SChris Zhong * Copyright (C) 2014 - STMicroelectronics Inc. 6aa66cc66SChris Zhong * 7aa66cc66SChris Zhong * Author: Lee Jones <lee.jones@linaro.org> 8aa66cc66SChris Zhong */ 9aa66cc66SChris Zhong 10aa66cc66SChris Zhong #include <linux/module.h> 11aa66cc66SChris Zhong #include <linux/init.h> 12aa66cc66SChris Zhong #include <linux/err.h> 13aa66cc66SChris Zhong #include <linux/regulator/driver.h> 14aa66cc66SChris Zhong #include <linux/regulator/machine.h> 15aa66cc66SChris Zhong #include <linux/regulator/of_regulator.h> 16aa66cc66SChris Zhong #include <linux/of.h> 17aa66cc66SChris Zhong #include <linux/of_device.h> 18aa66cc66SChris Zhong #include <linux/pwm.h> 1927bfa889SAlexandre Courbot #include <linux/gpio/consumer.h> 20aa66cc66SChris Zhong 21ea398e28SBoris Brezillon struct pwm_continuous_reg_data { 22ea398e28SBoris Brezillon unsigned int min_uV_dutycycle; 23ea398e28SBoris Brezillon unsigned int max_uV_dutycycle; 24ea398e28SBoris Brezillon unsigned int dutycycle_unit; 25ea398e28SBoris Brezillon }; 26ea398e28SBoris Brezillon 27aa66cc66SChris Zhong struct pwm_regulator_data { 284773be18SLee Jones /* Shared */ 29aa66cc66SChris Zhong struct pwm_device *pwm; 304773be18SLee Jones 314773be18SLee Jones /* Voltage table */ 324773be18SLee Jones struct pwm_voltages *duty_cycle_table; 33f907a0a9SLaxman Dewangan 34ea398e28SBoris Brezillon /* Continuous mode info */ 35ea398e28SBoris Brezillon struct pwm_continuous_reg_data continuous; 36ea398e28SBoris Brezillon 37f907a0a9SLaxman Dewangan /* regulator descriptor */ 38f907a0a9SLaxman Dewangan struct regulator_desc desc; 39f907a0a9SLaxman Dewangan 40aa66cc66SChris Zhong int state; 414773be18SLee Jones 4227bfa889SAlexandre Courbot /* Enable GPIO */ 4327bfa889SAlexandre Courbot struct gpio_desc *enb_gpio; 44aa66cc66SChris Zhong }; 45aa66cc66SChris Zhong 46aa66cc66SChris Zhong struct pwm_voltages { 47aa66cc66SChris Zhong unsigned int uV; 48aa66cc66SChris Zhong unsigned int dutycycle; 49aa66cc66SChris Zhong }; 50aa66cc66SChris Zhong 514773be18SLee Jones /** 524773be18SLee Jones * Voltage table call-backs 534773be18SLee Jones */ 5487248991SBoris Brezillon static void pwm_regulator_init_state(struct regulator_dev *rdev) 5587248991SBoris Brezillon { 5687248991SBoris Brezillon struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 5787248991SBoris Brezillon struct pwm_state pwm_state; 5887248991SBoris Brezillon unsigned int dutycycle; 5987248991SBoris Brezillon int i; 6087248991SBoris Brezillon 6187248991SBoris Brezillon pwm_get_state(drvdata->pwm, &pwm_state); 6287248991SBoris Brezillon dutycycle = pwm_get_relative_duty_cycle(&pwm_state, 100); 6387248991SBoris Brezillon 6487248991SBoris Brezillon for (i = 0; i < rdev->desc->n_voltages; i++) { 6587248991SBoris Brezillon if (dutycycle == drvdata->duty_cycle_table[i].dutycycle) { 6687248991SBoris Brezillon drvdata->state = i; 6787248991SBoris Brezillon return; 6887248991SBoris Brezillon } 6987248991SBoris Brezillon } 7087248991SBoris Brezillon } 7187248991SBoris Brezillon 72ab101e35SLee Jones static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev) 73aa66cc66SChris Zhong { 74ab101e35SLee Jones struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 75aa66cc66SChris Zhong 7687248991SBoris Brezillon if (drvdata->state < 0) 7787248991SBoris Brezillon pwm_regulator_init_state(rdev); 7887248991SBoris Brezillon 79aa66cc66SChris Zhong return drvdata->state; 80aa66cc66SChris Zhong } 81aa66cc66SChris Zhong 82ab101e35SLee Jones static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev, 83aa66cc66SChris Zhong unsigned selector) 84aa66cc66SChris Zhong { 85ab101e35SLee Jones struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 863f4eb39bSBoris Brezillon struct pwm_state pstate; 87aa66cc66SChris Zhong int ret; 88aa66cc66SChris Zhong 893f4eb39bSBoris Brezillon pwm_init_state(drvdata->pwm, &pstate); 903f4eb39bSBoris Brezillon pwm_set_relative_duty_cycle(&pstate, 913f4eb39bSBoris Brezillon drvdata->duty_cycle_table[selector].dutycycle, 100); 92aa66cc66SChris Zhong 933f4eb39bSBoris Brezillon ret = pwm_apply_state(drvdata->pwm, &pstate); 94aa66cc66SChris Zhong if (ret) { 955bf59bd5SLaxman Dewangan dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); 96aa66cc66SChris Zhong return ret; 97aa66cc66SChris Zhong } 98aa66cc66SChris Zhong 99aa66cc66SChris Zhong drvdata->state = selector; 100aa66cc66SChris Zhong 101aa66cc66SChris Zhong return 0; 102aa66cc66SChris Zhong } 103aa66cc66SChris Zhong 104ab101e35SLee Jones static int pwm_regulator_list_voltage(struct regulator_dev *rdev, 105aa66cc66SChris Zhong unsigned selector) 106aa66cc66SChris Zhong { 107ab101e35SLee Jones struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 108aa66cc66SChris Zhong 109ab101e35SLee Jones if (selector >= rdev->desc->n_voltages) 110aa66cc66SChris Zhong return -EINVAL; 111aa66cc66SChris Zhong 112aa66cc66SChris Zhong return drvdata->duty_cycle_table[selector].uV; 113aa66cc66SChris Zhong } 1144773be18SLee Jones 1151de7d802SBoris Brezillon static int pwm_regulator_enable(struct regulator_dev *dev) 1161de7d802SBoris Brezillon { 1171de7d802SBoris Brezillon struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 1181de7d802SBoris Brezillon 11927bfa889SAlexandre Courbot gpiod_set_value_cansleep(drvdata->enb_gpio, 1); 12027bfa889SAlexandre Courbot 1211de7d802SBoris Brezillon return pwm_enable(drvdata->pwm); 1221de7d802SBoris Brezillon } 1231de7d802SBoris Brezillon 1241de7d802SBoris Brezillon static int pwm_regulator_disable(struct regulator_dev *dev) 1251de7d802SBoris Brezillon { 1261de7d802SBoris Brezillon struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 1271de7d802SBoris Brezillon 1281de7d802SBoris Brezillon pwm_disable(drvdata->pwm); 1291de7d802SBoris Brezillon 13027bfa889SAlexandre Courbot gpiod_set_value_cansleep(drvdata->enb_gpio, 0); 13127bfa889SAlexandre Courbot 1321de7d802SBoris Brezillon return 0; 1331de7d802SBoris Brezillon } 1341de7d802SBoris Brezillon 1351de7d802SBoris Brezillon static int pwm_regulator_is_enabled(struct regulator_dev *dev) 1361de7d802SBoris Brezillon { 1371de7d802SBoris Brezillon struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 1381de7d802SBoris Brezillon 13927bfa889SAlexandre Courbot if (drvdata->enb_gpio && !gpiod_get_value_cansleep(drvdata->enb_gpio)) 14027bfa889SAlexandre Courbot return false; 14127bfa889SAlexandre Courbot 1421de7d802SBoris Brezillon return pwm_is_enabled(drvdata->pwm); 1431de7d802SBoris Brezillon } 1441de7d802SBoris Brezillon 1454773be18SLee Jones static int pwm_regulator_get_voltage(struct regulator_dev *rdev) 1464773be18SLee Jones { 1474773be18SLee Jones struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 148ea398e28SBoris Brezillon unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; 149ea398e28SBoris Brezillon unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; 150ea398e28SBoris Brezillon unsigned int duty_unit = drvdata->continuous.dutycycle_unit; 151d9070fdbSBoris Brezillon int min_uV = rdev->constraints->min_uV; 152ea398e28SBoris Brezillon int max_uV = rdev->constraints->max_uV; 153ea398e28SBoris Brezillon int diff_uV = max_uV - min_uV; 154d9070fdbSBoris Brezillon struct pwm_state pstate; 155ea398e28SBoris Brezillon unsigned int diff_duty; 156ea398e28SBoris Brezillon unsigned int voltage; 1574773be18SLee Jones 158d9070fdbSBoris Brezillon pwm_get_state(drvdata->pwm, &pstate); 159d9070fdbSBoris Brezillon 160ea398e28SBoris Brezillon voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit); 161ea398e28SBoris Brezillon 162ea398e28SBoris Brezillon /* 163ea398e28SBoris Brezillon * The dutycycle for min_uV might be greater than the one for max_uV. 164ea398e28SBoris Brezillon * This is happening when the user needs an inversed polarity, but the 165ea398e28SBoris Brezillon * PWM device does not support inversing it in hardware. 166ea398e28SBoris Brezillon */ 167ea398e28SBoris Brezillon if (max_uV_duty < min_uV_duty) { 168ea398e28SBoris Brezillon voltage = min_uV_duty - voltage; 169ea398e28SBoris Brezillon diff_duty = min_uV_duty - max_uV_duty; 170ea398e28SBoris Brezillon } else { 171ea398e28SBoris Brezillon voltage = voltage - min_uV_duty; 172ea398e28SBoris Brezillon diff_duty = max_uV_duty - min_uV_duty; 173ea398e28SBoris Brezillon } 174ea398e28SBoris Brezillon 175ea398e28SBoris Brezillon voltage = DIV_ROUND_CLOSEST_ULL((u64)voltage * diff_uV, diff_duty); 176ea398e28SBoris Brezillon 177ea398e28SBoris Brezillon return voltage + min_uV; 1784773be18SLee Jones } 1794773be18SLee Jones 1804773be18SLee Jones static int pwm_regulator_set_voltage(struct regulator_dev *rdev, 181ea398e28SBoris Brezillon int req_min_uV, int req_max_uV, 182ea398e28SBoris Brezillon unsigned int *selector) 1834773be18SLee Jones { 1844773be18SLee Jones struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 185ea398e28SBoris Brezillon unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; 186ea398e28SBoris Brezillon unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; 187ea398e28SBoris Brezillon unsigned int duty_unit = drvdata->continuous.dutycycle_unit; 188ea398e28SBoris Brezillon int min_uV = rdev->constraints->min_uV; 189ea398e28SBoris Brezillon int max_uV = rdev->constraints->max_uV; 190ea398e28SBoris Brezillon int diff_uV = max_uV - min_uV; 1913f4eb39bSBoris Brezillon struct pwm_state pstate; 192ea398e28SBoris Brezillon unsigned int diff_duty; 193ea398e28SBoris Brezillon unsigned int dutycycle; 1944773be18SLee Jones int ret; 1954773be18SLee Jones 1963f4eb39bSBoris Brezillon pwm_init_state(drvdata->pwm, &pstate); 1974773be18SLee Jones 198ea398e28SBoris Brezillon /* 199ea398e28SBoris Brezillon * The dutycycle for min_uV might be greater than the one for max_uV. 200ea398e28SBoris Brezillon * This is happening when the user needs an inversed polarity, but the 201ea398e28SBoris Brezillon * PWM device does not support inversing it in hardware. 202ea398e28SBoris Brezillon */ 203ea398e28SBoris Brezillon if (max_uV_duty < min_uV_duty) 204ea398e28SBoris Brezillon diff_duty = min_uV_duty - max_uV_duty; 205ea398e28SBoris Brezillon else 206ea398e28SBoris Brezillon diff_duty = max_uV_duty - min_uV_duty; 207ea398e28SBoris Brezillon 208ea398e28SBoris Brezillon dutycycle = DIV_ROUND_CLOSEST_ULL((u64)(req_min_uV - min_uV) * 209ea398e28SBoris Brezillon diff_duty, 210ea398e28SBoris Brezillon diff_uV); 211ea398e28SBoris Brezillon 212ea398e28SBoris Brezillon if (max_uV_duty < min_uV_duty) 213ea398e28SBoris Brezillon dutycycle = min_uV_duty - dutycycle; 214ea398e28SBoris Brezillon else 215ea398e28SBoris Brezillon dutycycle = min_uV_duty + dutycycle; 216ea398e28SBoris Brezillon 217ea398e28SBoris Brezillon pwm_set_relative_duty_cycle(&pstate, dutycycle, duty_unit); 218fd786fb0SLaxman Dewangan 2193f4eb39bSBoris Brezillon ret = pwm_apply_state(drvdata->pwm, &pstate); 2204773be18SLee Jones if (ret) { 2215bf59bd5SLaxman Dewangan dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); 2224773be18SLee Jones return ret; 2234773be18SLee Jones } 2244773be18SLee Jones 2254773be18SLee Jones return 0; 2264773be18SLee Jones } 2274773be18SLee Jones 228638aef7aSAxel Lin static const struct regulator_ops pwm_regulator_voltage_table_ops = { 229aa66cc66SChris Zhong .set_voltage_sel = pwm_regulator_set_voltage_sel, 230aa66cc66SChris Zhong .get_voltage_sel = pwm_regulator_get_voltage_sel, 231aa66cc66SChris Zhong .list_voltage = pwm_regulator_list_voltage, 232aa66cc66SChris Zhong .map_voltage = regulator_map_voltage_iterate, 2331de7d802SBoris Brezillon .enable = pwm_regulator_enable, 2341de7d802SBoris Brezillon .disable = pwm_regulator_disable, 2351de7d802SBoris Brezillon .is_enabled = pwm_regulator_is_enabled, 236aa66cc66SChris Zhong }; 237aa66cc66SChris Zhong 238638aef7aSAxel Lin static const struct regulator_ops pwm_regulator_voltage_continuous_ops = { 2394773be18SLee Jones .get_voltage = pwm_regulator_get_voltage, 2404773be18SLee Jones .set_voltage = pwm_regulator_set_voltage, 2411de7d802SBoris Brezillon .enable = pwm_regulator_enable, 2421de7d802SBoris Brezillon .disable = pwm_regulator_disable, 2431de7d802SBoris Brezillon .is_enabled = pwm_regulator_is_enabled, 2444773be18SLee Jones }; 2454773be18SLee Jones 246638aef7aSAxel Lin static const struct regulator_desc pwm_regulator_desc = { 247aa66cc66SChris Zhong .name = "pwm-regulator", 248aa66cc66SChris Zhong .type = REGULATOR_VOLTAGE, 249aa66cc66SChris Zhong .owner = THIS_MODULE, 250aa66cc66SChris Zhong .supply_name = "pwm", 251aa66cc66SChris Zhong }; 252aa66cc66SChris Zhong 253f9178dadSLee Jones static int pwm_regulator_init_table(struct platform_device *pdev, 254f9178dadSLee Jones struct pwm_regulator_data *drvdata) 255f9178dadSLee Jones { 256f9178dadSLee Jones struct device_node *np = pdev->dev.of_node; 257f9178dadSLee Jones struct pwm_voltages *duty_cycle_table; 25860cb65ebSLee Jones unsigned int length = 0; 259f9178dadSLee Jones int ret; 260f9178dadSLee Jones 261f9178dadSLee Jones of_find_property(np, "voltage-table", &length); 262f9178dadSLee Jones 263f9178dadSLee Jones if ((length < sizeof(*duty_cycle_table)) || 264f9178dadSLee Jones (length % sizeof(*duty_cycle_table))) { 2655bf59bd5SLaxman Dewangan dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n", 266f9178dadSLee Jones length); 267f9178dadSLee Jones return -EINVAL; 268f9178dadSLee Jones } 269f9178dadSLee Jones 270f9178dadSLee Jones duty_cycle_table = devm_kzalloc(&pdev->dev, length, GFP_KERNEL); 271f9178dadSLee Jones if (!duty_cycle_table) 272f9178dadSLee Jones return -ENOMEM; 273f9178dadSLee Jones 274f9178dadSLee Jones ret = of_property_read_u32_array(np, "voltage-table", 275f9178dadSLee Jones (u32 *)duty_cycle_table, 276f9178dadSLee Jones length / sizeof(u32)); 277f9178dadSLee Jones if (ret) { 2785bf59bd5SLaxman Dewangan dev_err(&pdev->dev, "Failed to read voltage-table: %d\n", ret); 279f9178dadSLee Jones return ret; 280f9178dadSLee Jones } 281f9178dadSLee Jones 28287248991SBoris Brezillon drvdata->state = -EINVAL; 283f9178dadSLee Jones drvdata->duty_cycle_table = duty_cycle_table; 284638aef7aSAxel Lin drvdata->desc.ops = &pwm_regulator_voltage_table_ops; 285f907a0a9SLaxman Dewangan drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table); 286f9178dadSLee Jones 287f9178dadSLee Jones return 0; 288f9178dadSLee Jones } 289f9178dadSLee Jones 2904773be18SLee Jones static int pwm_regulator_init_continuous(struct platform_device *pdev, 2914773be18SLee Jones struct pwm_regulator_data *drvdata) 2924773be18SLee Jones { 293ea398e28SBoris Brezillon u32 dutycycle_range[2] = { 0, 100 }; 294ea398e28SBoris Brezillon u32 dutycycle_unit = 100; 295ea398e28SBoris Brezillon 296638aef7aSAxel Lin drvdata->desc.ops = &pwm_regulator_voltage_continuous_ops; 297f907a0a9SLaxman Dewangan drvdata->desc.continuous_voltage_range = true; 2984773be18SLee Jones 299ea398e28SBoris Brezillon of_property_read_u32_array(pdev->dev.of_node, 300ea398e28SBoris Brezillon "pwm-dutycycle-range", 301ea398e28SBoris Brezillon dutycycle_range, 2); 302ea398e28SBoris Brezillon of_property_read_u32(pdev->dev.of_node, "pwm-dutycycle-unit", 303ea398e28SBoris Brezillon &dutycycle_unit); 304ea398e28SBoris Brezillon 305ea398e28SBoris Brezillon if (dutycycle_range[0] > dutycycle_unit || 306ea398e28SBoris Brezillon dutycycle_range[1] > dutycycle_unit) 307ea398e28SBoris Brezillon return -EINVAL; 308ea398e28SBoris Brezillon 309ea398e28SBoris Brezillon drvdata->continuous.dutycycle_unit = dutycycle_unit; 310ea398e28SBoris Brezillon drvdata->continuous.min_uV_dutycycle = dutycycle_range[0]; 311ea398e28SBoris Brezillon drvdata->continuous.max_uV_dutycycle = dutycycle_range[1]; 312ea398e28SBoris Brezillon 3134773be18SLee Jones return 0; 3144773be18SLee Jones } 3154773be18SLee Jones 316aa66cc66SChris Zhong static int pwm_regulator_probe(struct platform_device *pdev) 317aa66cc66SChris Zhong { 3185ad2cb14SLee Jones const struct regulator_init_data *init_data; 319aa66cc66SChris Zhong struct pwm_regulator_data *drvdata; 320aa66cc66SChris Zhong struct regulator_dev *regulator; 321aa66cc66SChris Zhong struct regulator_config config = { }; 322aa66cc66SChris Zhong struct device_node *np = pdev->dev.of_node; 32327bfa889SAlexandre Courbot enum gpiod_flags gpio_flags; 324f9178dadSLee Jones int ret; 325aa66cc66SChris Zhong 326aa66cc66SChris Zhong if (!np) { 327aa66cc66SChris Zhong dev_err(&pdev->dev, "Device Tree node missing\n"); 328aa66cc66SChris Zhong return -EINVAL; 329aa66cc66SChris Zhong } 330aa66cc66SChris Zhong 331aa66cc66SChris Zhong drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); 332aa66cc66SChris Zhong if (!drvdata) 333aa66cc66SChris Zhong return -ENOMEM; 334aa66cc66SChris Zhong 335f907a0a9SLaxman Dewangan memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(drvdata->desc)); 336f907a0a9SLaxman Dewangan 3374773be18SLee Jones if (of_find_property(np, "voltage-table", NULL)) 338f9178dadSLee Jones ret = pwm_regulator_init_table(pdev, drvdata); 3394773be18SLee Jones else 3404773be18SLee Jones ret = pwm_regulator_init_continuous(pdev, drvdata); 341f9178dadSLee Jones if (ret) 342aa66cc66SChris Zhong return ret; 343aa66cc66SChris Zhong 3445ad2cb14SLee Jones init_data = of_get_regulator_init_data(&pdev->dev, np, 345f907a0a9SLaxman Dewangan &drvdata->desc); 3465ad2cb14SLee Jones if (!init_data) 347aa66cc66SChris Zhong return -ENOMEM; 348aa66cc66SChris Zhong 349aa66cc66SChris Zhong config.of_node = np; 350aa66cc66SChris Zhong config.dev = &pdev->dev; 351aa66cc66SChris Zhong config.driver_data = drvdata; 3525ad2cb14SLee Jones config.init_data = init_data; 353aa66cc66SChris Zhong 354aa66cc66SChris Zhong drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); 355aa66cc66SChris Zhong if (IS_ERR(drvdata->pwm)) { 3565bf59bd5SLaxman Dewangan ret = PTR_ERR(drvdata->pwm); 3575bf59bd5SLaxman Dewangan dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret); 3585bf59bd5SLaxman Dewangan return ret; 359aa66cc66SChris Zhong } 360aa66cc66SChris Zhong 36127bfa889SAlexandre Courbot if (init_data->constraints.boot_on || init_data->constraints.always_on) 36227bfa889SAlexandre Courbot gpio_flags = GPIOD_OUT_HIGH; 36327bfa889SAlexandre Courbot else 36427bfa889SAlexandre Courbot gpio_flags = GPIOD_OUT_LOW; 36527bfa889SAlexandre Courbot drvdata->enb_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 36627bfa889SAlexandre Courbot gpio_flags); 36727bfa889SAlexandre Courbot if (IS_ERR(drvdata->enb_gpio)) { 36827bfa889SAlexandre Courbot ret = PTR_ERR(drvdata->enb_gpio); 36927bfa889SAlexandre Courbot dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n", ret); 37027bfa889SAlexandre Courbot return ret; 37127bfa889SAlexandre Courbot } 37227bfa889SAlexandre Courbot 373fd4f99c4SBoris Brezillon ret = pwm_adjust_config(drvdata->pwm); 374fd4f99c4SBoris Brezillon if (ret) 375fd4f99c4SBoris Brezillon return ret; 3768c12ad8eSBoris Brezillon 377aa66cc66SChris Zhong regulator = devm_regulator_register(&pdev->dev, 378f907a0a9SLaxman Dewangan &drvdata->desc, &config); 379aa66cc66SChris Zhong if (IS_ERR(regulator)) { 3805bf59bd5SLaxman Dewangan ret = PTR_ERR(regulator); 3815bf59bd5SLaxman Dewangan dev_err(&pdev->dev, "Failed to register regulator %s: %d\n", 3825bf59bd5SLaxman Dewangan drvdata->desc.name, ret); 3835bf59bd5SLaxman Dewangan return ret; 384aa66cc66SChris Zhong } 385aa66cc66SChris Zhong 386aa66cc66SChris Zhong return 0; 387aa66cc66SChris Zhong } 388aa66cc66SChris Zhong 389aa66cc66SChris Zhong static const struct of_device_id pwm_of_match[] = { 390aa66cc66SChris Zhong { .compatible = "pwm-regulator" }, 391aa66cc66SChris Zhong { }, 392aa66cc66SChris Zhong }; 393aa66cc66SChris Zhong MODULE_DEVICE_TABLE(of, pwm_of_match); 394aa66cc66SChris Zhong 395aa66cc66SChris Zhong static struct platform_driver pwm_regulator_driver = { 396aa66cc66SChris Zhong .driver = { 397aa66cc66SChris Zhong .name = "pwm-regulator", 398aa66cc66SChris Zhong .of_match_table = of_match_ptr(pwm_of_match), 399aa66cc66SChris Zhong }, 400aa66cc66SChris Zhong .probe = pwm_regulator_probe, 401aa66cc66SChris Zhong }; 402aa66cc66SChris Zhong 403aa66cc66SChris Zhong module_platform_driver(pwm_regulator_driver); 404aa66cc66SChris Zhong 405aa66cc66SChris Zhong MODULE_LICENSE("GPL"); 406aa66cc66SChris Zhong MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); 407aa66cc66SChris Zhong MODULE_DESCRIPTION("PWM Regulator Driver"); 408aa66cc66SChris Zhong MODULE_ALIAS("platform:pwm-regulator"); 409