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 24 struct pwm_regulator_data { 25 /* Shared */ 26 struct pwm_device *pwm; 27 28 /* Voltage table */ 29 struct pwm_voltages *duty_cycle_table; 30 31 /* regulator descriptor */ 32 struct regulator_desc desc; 33 34 /* Regulator ops */ 35 struct regulator_ops ops; 36 37 int state; 38 39 /* Continuous voltage */ 40 int volt_uV; 41 }; 42 43 struct pwm_voltages { 44 unsigned int uV; 45 unsigned int dutycycle; 46 }; 47 48 /** 49 * Voltage table call-backs 50 */ 51 static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev) 52 { 53 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 54 55 return drvdata->state; 56 } 57 58 static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev, 59 unsigned selector) 60 { 61 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 62 unsigned int pwm_reg_period; 63 int dutycycle; 64 int ret; 65 66 pwm_reg_period = pwm_get_period(drvdata->pwm); 67 68 dutycycle = (pwm_reg_period * 69 drvdata->duty_cycle_table[selector].dutycycle) / 100; 70 71 ret = pwm_config(drvdata->pwm, dutycycle, pwm_reg_period); 72 if (ret) { 73 dev_err(&rdev->dev, "Failed to configure PWM\n"); 74 return ret; 75 } 76 77 drvdata->state = selector; 78 79 return 0; 80 } 81 82 static int pwm_regulator_list_voltage(struct regulator_dev *rdev, 83 unsigned selector) 84 { 85 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 86 87 if (selector >= rdev->desc->n_voltages) 88 return -EINVAL; 89 90 return drvdata->duty_cycle_table[selector].uV; 91 } 92 93 static int pwm_regulator_enable(struct regulator_dev *dev) 94 { 95 struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 96 97 return pwm_enable(drvdata->pwm); 98 } 99 100 static int pwm_regulator_disable(struct regulator_dev *dev) 101 { 102 struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 103 104 pwm_disable(drvdata->pwm); 105 106 return 0; 107 } 108 109 static int pwm_regulator_is_enabled(struct regulator_dev *dev) 110 { 111 struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); 112 113 return pwm_is_enabled(drvdata->pwm); 114 } 115 116 /** 117 * Continuous voltage call-backs 118 */ 119 static int pwm_voltage_to_duty_cycle_percentage(struct regulator_dev *rdev, int req_uV) 120 { 121 int min_uV = rdev->constraints->min_uV; 122 int max_uV = rdev->constraints->max_uV; 123 int diff = max_uV - min_uV; 124 125 return ((req_uV * 100) - (min_uV * 100)) / diff; 126 } 127 128 static int pwm_regulator_get_voltage(struct regulator_dev *rdev) 129 { 130 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 131 132 return drvdata->volt_uV; 133 } 134 135 static int pwm_regulator_set_voltage(struct regulator_dev *rdev, 136 int min_uV, int max_uV, 137 unsigned *selector) 138 { 139 struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev); 140 unsigned int ramp_delay = rdev->constraints->ramp_delay; 141 unsigned int period = pwm_get_period(drvdata->pwm); 142 int duty_cycle; 143 int ret; 144 145 duty_cycle = pwm_voltage_to_duty_cycle_percentage(rdev, min_uV); 146 147 ret = pwm_config(drvdata->pwm, (period / 100) * duty_cycle, period); 148 if (ret) { 149 dev_err(&rdev->dev, "Failed to configure PWM\n"); 150 return ret; 151 } 152 153 ret = pwm_enable(drvdata->pwm); 154 if (ret) { 155 dev_err(&rdev->dev, "Failed to enable PWM\n"); 156 return ret; 157 } 158 drvdata->volt_uV = min_uV; 159 160 /* Delay required by PWM regulator to settle to the new voltage */ 161 usleep_range(ramp_delay, ramp_delay + 1000); 162 163 return 0; 164 } 165 166 static struct regulator_ops pwm_regulator_voltage_table_ops = { 167 .set_voltage_sel = pwm_regulator_set_voltage_sel, 168 .get_voltage_sel = pwm_regulator_get_voltage_sel, 169 .list_voltage = pwm_regulator_list_voltage, 170 .map_voltage = regulator_map_voltage_iterate, 171 .enable = pwm_regulator_enable, 172 .disable = pwm_regulator_disable, 173 .is_enabled = pwm_regulator_is_enabled, 174 }; 175 176 static struct regulator_ops pwm_regulator_voltage_continuous_ops = { 177 .get_voltage = pwm_regulator_get_voltage, 178 .set_voltage = pwm_regulator_set_voltage, 179 .enable = pwm_regulator_enable, 180 .disable = pwm_regulator_disable, 181 .is_enabled = pwm_regulator_is_enabled, 182 }; 183 184 static struct regulator_desc pwm_regulator_desc = { 185 .name = "pwm-regulator", 186 .type = REGULATOR_VOLTAGE, 187 .owner = THIS_MODULE, 188 .supply_name = "pwm", 189 }; 190 191 static int pwm_regulator_init_table(struct platform_device *pdev, 192 struct pwm_regulator_data *drvdata) 193 { 194 struct device_node *np = pdev->dev.of_node; 195 struct pwm_voltages *duty_cycle_table; 196 unsigned int length = 0; 197 int ret; 198 199 of_find_property(np, "voltage-table", &length); 200 201 if ((length < sizeof(*duty_cycle_table)) || 202 (length % sizeof(*duty_cycle_table))) { 203 dev_err(&pdev->dev, 204 "voltage-table length(%d) is invalid\n", 205 length); 206 return -EINVAL; 207 } 208 209 duty_cycle_table = devm_kzalloc(&pdev->dev, length, GFP_KERNEL); 210 if (!duty_cycle_table) 211 return -ENOMEM; 212 213 ret = of_property_read_u32_array(np, "voltage-table", 214 (u32 *)duty_cycle_table, 215 length / sizeof(u32)); 216 if (ret) { 217 dev_err(&pdev->dev, "Failed to read voltage-table\n"); 218 return ret; 219 } 220 221 drvdata->duty_cycle_table = duty_cycle_table; 222 memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops, 223 sizeof(drvdata->ops)); 224 drvdata->desc.ops = &drvdata->ops; 225 drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table); 226 227 return 0; 228 } 229 230 static int pwm_regulator_init_continuous(struct platform_device *pdev, 231 struct pwm_regulator_data *drvdata) 232 { 233 memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops, 234 sizeof(drvdata->ops)); 235 drvdata->desc.ops = &drvdata->ops; 236 drvdata->desc.continuous_voltage_range = true; 237 238 return 0; 239 } 240 241 static int pwm_regulator_probe(struct platform_device *pdev) 242 { 243 const struct regulator_init_data *init_data; 244 struct pwm_regulator_data *drvdata; 245 struct regulator_dev *regulator; 246 struct regulator_config config = { }; 247 struct device_node *np = pdev->dev.of_node; 248 int ret; 249 250 if (!np) { 251 dev_err(&pdev->dev, "Device Tree node missing\n"); 252 return -EINVAL; 253 } 254 255 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); 256 if (!drvdata) 257 return -ENOMEM; 258 259 memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(drvdata->desc)); 260 261 if (of_find_property(np, "voltage-table", NULL)) 262 ret = pwm_regulator_init_table(pdev, drvdata); 263 else 264 ret = pwm_regulator_init_continuous(pdev, drvdata); 265 if (ret) 266 return ret; 267 268 init_data = of_get_regulator_init_data(&pdev->dev, np, 269 &drvdata->desc); 270 if (!init_data) 271 return -ENOMEM; 272 273 config.of_node = np; 274 config.dev = &pdev->dev; 275 config.driver_data = drvdata; 276 config.init_data = init_data; 277 278 drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); 279 if (IS_ERR(drvdata->pwm)) { 280 dev_err(&pdev->dev, "Failed to get PWM\n"); 281 return PTR_ERR(drvdata->pwm); 282 } 283 284 regulator = devm_regulator_register(&pdev->dev, 285 &drvdata->desc, &config); 286 if (IS_ERR(regulator)) { 287 dev_err(&pdev->dev, "Failed to register regulator %s\n", 288 drvdata->desc.name); 289 return PTR_ERR(regulator); 290 } 291 292 return 0; 293 } 294 295 static const struct of_device_id pwm_of_match[] = { 296 { .compatible = "pwm-regulator" }, 297 { }, 298 }; 299 MODULE_DEVICE_TABLE(of, pwm_of_match); 300 301 static struct platform_driver pwm_regulator_driver = { 302 .driver = { 303 .name = "pwm-regulator", 304 .of_match_table = of_match_ptr(pwm_of_match), 305 }, 306 .probe = pwm_regulator_probe, 307 }; 308 309 module_platform_driver(pwm_regulator_driver); 310 311 MODULE_LICENSE("GPL"); 312 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); 313 MODULE_DESCRIPTION("PWM Regulator Driver"); 314 MODULE_ALIAS("platform:pwm-regulator"); 315