1 /* 2 * Regulator driver for PWM Regulators 3 * 4 * Copyright (C) 2014 - STMicroelectronics Inc. 5 * 6 * Author: Lee Jones <lee.jones@linaro.org> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/delay.h> 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/err.h> 17 #include <linux/regulator/driver.h> 18 #include <linux/regulator/machine.h> 19 #include <linux/regulator/of_regulator.h> 20 #include <linux/of.h> 21 #include <linux/of_device.h> 22 #include <linux/pwm.h> 23 #include <linux/gpio/consumer.h> 24 25 struct pwm_regulator_data { 26 /* Shared */ 27 struct pwm_device *pwm; 28 29 /* Voltage table */ 30 struct pwm_voltages *duty_cycle_table; 31 32 /* regulator descriptor */ 33 struct regulator_desc desc; 34 35 /* Regulator ops */ 36 struct regulator_ops ops; 37 38 int state; 39 40 /* Continuous voltage */ 41 int volt_uV; 42 43 /* Enable GPIO */ 44 struct gpio_desc *enb_gpio; 45 }; 46 47 struct pwm_voltages { 48 unsigned int uV; 49 unsigned int dutycycle; 50 }; 51 52 /** 53 * Voltage table call-backs 54 */ 55 static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev) 56 { 57 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 58 59 return drvdata->state; 60 } 61 62 static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev, 63 unsigned selector) 64 { 65 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 66 struct pwm_args pargs; 67 int dutycycle; 68 int ret; 69 70 pwm_get_args(drvdata->pwm, &pargs); 71 72 dutycycle = (pargs.period * 73 drvdata->duty_cycle_table[selector].dutycycle) / 100; 74 75 ret = pwm_config(drvdata->pwm, dutycycle, pargs.period); 76 if (ret) { 77 dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); 78 return ret; 79 } 80 81 drvdata->state = selector; 82 83 return 0; 84 } 85 86 static int pwm_regulator_list_voltage(struct regulator_dev *rdev, 87 unsigned selector) 88 { 89 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 90 91 if (selector >= rdev->desc->n_voltages) 92 return -EINVAL; 93 94 return drvdata->duty_cycle_table[selector].uV; 95 } 96 97 static int pwm_regulator_enable(struct regulator_dev *dev) 98 { 99 struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 100 101 if (drvdata->enb_gpio) 102 gpiod_set_value_cansleep(drvdata->enb_gpio, 1); 103 104 return pwm_enable(drvdata->pwm); 105 } 106 107 static int pwm_regulator_disable(struct regulator_dev *dev) 108 { 109 struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 110 111 pwm_disable(drvdata->pwm); 112 113 if (drvdata->enb_gpio) 114 gpiod_set_value_cansleep(drvdata->enb_gpio, 0); 115 116 return 0; 117 } 118 119 static int pwm_regulator_is_enabled(struct regulator_dev *dev) 120 { 121 struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 122 123 if (drvdata->enb_gpio && !gpiod_get_value_cansleep(drvdata->enb_gpio)) 124 return false; 125 126 return pwm_is_enabled(drvdata->pwm); 127 } 128 129 static int pwm_regulator_get_voltage(struct regulator_dev *rdev) 130 { 131 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 132 133 return drvdata->volt_uV; 134 } 135 136 static int pwm_regulator_set_voltage(struct regulator_dev *rdev, 137 int min_uV, int max_uV, 138 unsigned *selector) 139 { 140 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 141 unsigned int ramp_delay = rdev->constraints->ramp_delay; 142 struct pwm_args pargs; 143 unsigned int req_diff = min_uV - rdev->constraints->min_uV; 144 unsigned int diff; 145 unsigned int duty_pulse; 146 u64 req_period; 147 u32 rem; 148 int old_uV = pwm_regulator_get_voltage(rdev); 149 int ret; 150 151 pwm_get_args(drvdata->pwm, &pargs); 152 diff = rdev->constraints->max_uV - rdev->constraints->min_uV; 153 154 /* First try to find out if we get the iduty cycle time which is 155 * factor of PWM period time. If (request_diff_to_min * pwm_period) 156 * is perfect divided by voltage_range_diff then it is possible to 157 * get duty cycle time which is factor of PWM period. This will help 158 * to get output voltage nearer to requested value as there is no 159 * calculation loss. 160 */ 161 req_period = req_diff * pargs.period; 162 div_u64_rem(req_period, diff, &rem); 163 if (!rem) { 164 do_div(req_period, diff); 165 duty_pulse = (unsigned int)req_period; 166 } else { 167 duty_pulse = (pargs.period / 100) * ((req_diff * 100) / diff); 168 } 169 170 ret = pwm_config(drvdata->pwm, duty_pulse, pargs.period); 171 if (ret) { 172 dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); 173 return ret; 174 } 175 176 drvdata->volt_uV = min_uV; 177 178 if ((ramp_delay == 0) || !pwm_regulator_is_enabled(rdev)) 179 return 0; 180 181 /* Ramp delay is in uV/uS. Adjust to uS and delay */ 182 ramp_delay = DIV_ROUND_UP(abs(min_uV - old_uV), ramp_delay); 183 usleep_range(ramp_delay, ramp_delay + DIV_ROUND_UP(ramp_delay, 10)); 184 185 return 0; 186 } 187 188 static struct regulator_ops pwm_regulator_voltage_table_ops = { 189 .set_voltage_sel = pwm_regulator_set_voltage_sel, 190 .get_voltage_sel = pwm_regulator_get_voltage_sel, 191 .list_voltage = pwm_regulator_list_voltage, 192 .map_voltage = regulator_map_voltage_iterate, 193 .enable = pwm_regulator_enable, 194 .disable = pwm_regulator_disable, 195 .is_enabled = pwm_regulator_is_enabled, 196 }; 197 198 static struct regulator_ops pwm_regulator_voltage_continuous_ops = { 199 .get_voltage = pwm_regulator_get_voltage, 200 .set_voltage = pwm_regulator_set_voltage, 201 .enable = pwm_regulator_enable, 202 .disable = pwm_regulator_disable, 203 .is_enabled = pwm_regulator_is_enabled, 204 }; 205 206 static struct regulator_desc pwm_regulator_desc = { 207 .name = "pwm-regulator", 208 .type = REGULATOR_VOLTAGE, 209 .owner = THIS_MODULE, 210 .supply_name = "pwm", 211 }; 212 213 static int pwm_regulator_init_table(struct platform_device *pdev, 214 struct pwm_regulator_data *drvdata) 215 { 216 struct device_node *np = pdev->dev.of_node; 217 struct pwm_voltages *duty_cycle_table; 218 unsigned int length = 0; 219 int ret; 220 221 of_find_property(np, "voltage-table", &length); 222 223 if ((length < sizeof(*duty_cycle_table)) || 224 (length % sizeof(*duty_cycle_table))) { 225 dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n", 226 length); 227 return -EINVAL; 228 } 229 230 duty_cycle_table = devm_kzalloc(&pdev->dev, length, GFP_KERNEL); 231 if (!duty_cycle_table) 232 return -ENOMEM; 233 234 ret = of_property_read_u32_array(np, "voltage-table", 235 (u32 *)duty_cycle_table, 236 length / sizeof(u32)); 237 if (ret) { 238 dev_err(&pdev->dev, "Failed to read voltage-table: %d\n", ret); 239 return ret; 240 } 241 242 drvdata->duty_cycle_table = duty_cycle_table; 243 memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops, 244 sizeof(drvdata->ops)); 245 drvdata->desc.ops = &drvdata->ops; 246 drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table); 247 248 return 0; 249 } 250 251 static int pwm_regulator_init_continuous(struct platform_device *pdev, 252 struct pwm_regulator_data *drvdata) 253 { 254 memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops, 255 sizeof(drvdata->ops)); 256 drvdata->desc.ops = &drvdata->ops; 257 drvdata->desc.continuous_voltage_range = true; 258 259 return 0; 260 } 261 262 static int pwm_regulator_probe(struct platform_device *pdev) 263 { 264 const struct regulator_init_data *init_data; 265 struct pwm_regulator_data *drvdata; 266 struct regulator_dev *regulator; 267 struct regulator_config config = { }; 268 struct device_node *np = pdev->dev.of_node; 269 enum gpiod_flags gpio_flags; 270 int ret; 271 272 if (!np) { 273 dev_err(&pdev->dev, "Device Tree node missing\n"); 274 return -EINVAL; 275 } 276 277 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); 278 if (!drvdata) 279 return -ENOMEM; 280 281 memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(drvdata->desc)); 282 283 if (of_find_property(np, "voltage-table", NULL)) 284 ret = pwm_regulator_init_table(pdev, drvdata); 285 else 286 ret = pwm_regulator_init_continuous(pdev, drvdata); 287 if (ret) 288 return ret; 289 290 init_data = of_get_regulator_init_data(&pdev->dev, np, 291 &drvdata->desc); 292 if (!init_data) 293 return -ENOMEM; 294 295 config.of_node = np; 296 config.dev = &pdev->dev; 297 config.driver_data = drvdata; 298 config.init_data = init_data; 299 300 drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); 301 if (IS_ERR(drvdata->pwm)) { 302 ret = PTR_ERR(drvdata->pwm); 303 dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret); 304 return ret; 305 } 306 307 if (init_data->constraints.boot_on || init_data->constraints.always_on) 308 gpio_flags = GPIOD_OUT_HIGH; 309 else 310 gpio_flags = GPIOD_OUT_LOW; 311 drvdata->enb_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 312 gpio_flags); 313 if (IS_ERR(drvdata->enb_gpio)) { 314 ret = PTR_ERR(drvdata->enb_gpio); 315 dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n", ret); 316 return ret; 317 } 318 319 /* 320 * FIXME: pwm_apply_args() should be removed when switching to the 321 * atomic PWM API. 322 */ 323 pwm_apply_args(drvdata->pwm); 324 325 regulator = devm_regulator_register(&pdev->dev, 326 &drvdata->desc, &config); 327 if (IS_ERR(regulator)) { 328 ret = PTR_ERR(regulator); 329 dev_err(&pdev->dev, "Failed to register regulator %s: %d\n", 330 drvdata->desc.name, ret); 331 return ret; 332 } 333 334 return 0; 335 } 336 337 static const struct of_device_id pwm_of_match[] = { 338 { .compatible = "pwm-regulator" }, 339 { }, 340 }; 341 MODULE_DEVICE_TABLE(of, pwm_of_match); 342 343 static struct platform_driver pwm_regulator_driver = { 344 .driver = { 345 .name = "pwm-regulator", 346 .of_match_table = of_match_ptr(pwm_of_match), 347 }, 348 .probe = pwm_regulator_probe, 349 }; 350 351 module_platform_driver(pwm_regulator_driver); 352 353 MODULE_LICENSE("GPL"); 354 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); 355 MODULE_DESCRIPTION("PWM Regulator Driver"); 356 MODULE_ALIAS("platform:pwm-regulator"); 357