gpio-regulator.c (9697B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * gpio-regulator.c 4 * 5 * Copyright 2011 Heiko Stuebner <heiko@sntech.de> 6 * 7 * based on fixed.c 8 * 9 * Copyright 2008 Wolfson Microelectronics PLC. 10 * 11 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 12 * 13 * Copyright (c) 2009 Nokia Corporation 14 * Roger Quadros <ext-roger.quadros@nokia.com> 15 * 16 * This is useful for systems with mixed controllable and 17 * non-controllable regulators, as well as for allowing testing on 18 * systems with no controllable regulators. 19 */ 20 21#include <linux/err.h> 22#include <linux/mutex.h> 23#include <linux/module.h> 24#include <linux/platform_device.h> 25#include <linux/regulator/driver.h> 26#include <linux/regulator/machine.h> 27#include <linux/regulator/of_regulator.h> 28#include <linux/regulator/gpio-regulator.h> 29#include <linux/gpio/consumer.h> 30#include <linux/slab.h> 31#include <linux/of.h> 32 33struct gpio_regulator_data { 34 struct regulator_desc desc; 35 36 struct gpio_desc **gpiods; 37 int nr_gpios; 38 39 struct gpio_regulator_state *states; 40 int nr_states; 41 42 int state; 43}; 44 45static int gpio_regulator_get_value(struct regulator_dev *dev) 46{ 47 struct gpio_regulator_data *data = rdev_get_drvdata(dev); 48 int ptr; 49 50 for (ptr = 0; ptr < data->nr_states; ptr++) 51 if (data->states[ptr].gpios == data->state) 52 return data->states[ptr].value; 53 54 return -EINVAL; 55} 56 57static int gpio_regulator_set_voltage(struct regulator_dev *dev, 58 int min_uV, int max_uV, 59 unsigned *selector) 60{ 61 struct gpio_regulator_data *data = rdev_get_drvdata(dev); 62 int ptr, target = 0, state, best_val = INT_MAX; 63 64 for (ptr = 0; ptr < data->nr_states; ptr++) 65 if (data->states[ptr].value < best_val && 66 data->states[ptr].value >= min_uV && 67 data->states[ptr].value <= max_uV) { 68 target = data->states[ptr].gpios; 69 best_val = data->states[ptr].value; 70 if (selector) 71 *selector = ptr; 72 } 73 74 if (best_val == INT_MAX) 75 return -EINVAL; 76 77 for (ptr = 0; ptr < data->nr_gpios; ptr++) { 78 state = (target & (1 << ptr)) >> ptr; 79 gpiod_set_value_cansleep(data->gpiods[ptr], state); 80 } 81 data->state = target; 82 83 return 0; 84} 85 86static int gpio_regulator_list_voltage(struct regulator_dev *dev, 87 unsigned selector) 88{ 89 struct gpio_regulator_data *data = rdev_get_drvdata(dev); 90 91 if (selector >= data->nr_states) 92 return -EINVAL; 93 94 return data->states[selector].value; 95} 96 97static int gpio_regulator_set_current_limit(struct regulator_dev *dev, 98 int min_uA, int max_uA) 99{ 100 struct gpio_regulator_data *data = rdev_get_drvdata(dev); 101 int ptr, target = 0, state, best_val = 0; 102 103 for (ptr = 0; ptr < data->nr_states; ptr++) 104 if (data->states[ptr].value > best_val && 105 data->states[ptr].value >= min_uA && 106 data->states[ptr].value <= max_uA) { 107 target = data->states[ptr].gpios; 108 best_val = data->states[ptr].value; 109 } 110 111 if (best_val == 0) 112 return -EINVAL; 113 114 for (ptr = 0; ptr < data->nr_gpios; ptr++) { 115 state = (target & (1 << ptr)) >> ptr; 116 gpiod_set_value_cansleep(data->gpiods[ptr], state); 117 } 118 data->state = target; 119 120 return 0; 121} 122 123static const struct regulator_ops gpio_regulator_voltage_ops = { 124 .get_voltage = gpio_regulator_get_value, 125 .set_voltage = gpio_regulator_set_voltage, 126 .list_voltage = gpio_regulator_list_voltage, 127}; 128 129static struct gpio_regulator_config * 130of_get_gpio_regulator_config(struct device *dev, struct device_node *np, 131 const struct regulator_desc *desc) 132{ 133 struct gpio_regulator_config *config; 134 const char *regtype; 135 int proplen, i; 136 int ngpios; 137 int ret; 138 139 config = devm_kzalloc(dev, 140 sizeof(struct gpio_regulator_config), 141 GFP_KERNEL); 142 if (!config) 143 return ERR_PTR(-ENOMEM); 144 145 config->init_data = of_get_regulator_init_data(dev, np, desc); 146 if (!config->init_data) 147 return ERR_PTR(-EINVAL); 148 149 config->supply_name = config->init_data->constraints.name; 150 151 if (config->init_data->constraints.boot_on) 152 config->enabled_at_boot = true; 153 154 /* 155 * Do not use: undocumented device tree property. 156 * This is kept around solely for device tree ABI stability. 157 */ 158 if (of_property_read_bool(np, "enable-at-boot")) 159 config->enabled_at_boot = true; 160 161 of_property_read_u32(np, "startup-delay-us", &config->startup_delay); 162 163 /* Fetch GPIO init levels */ 164 ngpios = gpiod_count(dev, NULL); 165 if (ngpios > 0) { 166 config->gflags = devm_kzalloc(dev, 167 sizeof(enum gpiod_flags) 168 * ngpios, 169 GFP_KERNEL); 170 if (!config->gflags) 171 return ERR_PTR(-ENOMEM); 172 173 for (i = 0; i < ngpios; i++) { 174 u32 val; 175 176 ret = of_property_read_u32_index(np, "gpios-states", i, 177 &val); 178 179 /* Default to high per specification */ 180 if (ret) 181 config->gflags[i] = GPIOD_OUT_HIGH; 182 else 183 config->gflags[i] = 184 val ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; 185 } 186 } 187 config->ngpios = ngpios; 188 189 /* Fetch states. */ 190 proplen = of_property_count_u32_elems(np, "states"); 191 if (proplen < 0) { 192 dev_err(dev, "No 'states' property found\n"); 193 return ERR_PTR(-EINVAL); 194 } 195 196 config->states = devm_kcalloc(dev, 197 proplen / 2, 198 sizeof(struct gpio_regulator_state), 199 GFP_KERNEL); 200 if (!config->states) 201 return ERR_PTR(-ENOMEM); 202 203 for (i = 0; i < proplen / 2; i++) { 204 of_property_read_u32_index(np, "states", i * 2, 205 &config->states[i].value); 206 of_property_read_u32_index(np, "states", i * 2 + 1, 207 &config->states[i].gpios); 208 } 209 config->nr_states = i; 210 211 config->type = REGULATOR_VOLTAGE; 212 ret = of_property_read_string(np, "regulator-type", ®type); 213 if (ret >= 0) { 214 if (!strncmp("voltage", regtype, 7)) 215 config->type = REGULATOR_VOLTAGE; 216 else if (!strncmp("current", regtype, 7)) 217 config->type = REGULATOR_CURRENT; 218 else 219 dev_warn(dev, "Unknown regulator-type '%s'\n", 220 regtype); 221 } 222 223 return config; 224} 225 226static const struct regulator_ops gpio_regulator_current_ops = { 227 .get_current_limit = gpio_regulator_get_value, 228 .set_current_limit = gpio_regulator_set_current_limit, 229}; 230 231static int gpio_regulator_probe(struct platform_device *pdev) 232{ 233 struct device *dev = &pdev->dev; 234 struct gpio_regulator_config *config = dev_get_platdata(dev); 235 struct device_node *np = dev->of_node; 236 struct gpio_regulator_data *drvdata; 237 struct regulator_config cfg = { }; 238 struct regulator_dev *rdev; 239 enum gpiod_flags gflags; 240 int ptr, ret, state, i; 241 242 drvdata = devm_kzalloc(dev, sizeof(struct gpio_regulator_data), 243 GFP_KERNEL); 244 if (drvdata == NULL) 245 return -ENOMEM; 246 247 if (np) { 248 config = of_get_gpio_regulator_config(dev, np, 249 &drvdata->desc); 250 if (IS_ERR(config)) 251 return PTR_ERR(config); 252 } 253 254 drvdata->desc.name = devm_kstrdup(dev, config->supply_name, GFP_KERNEL); 255 if (drvdata->desc.name == NULL) { 256 dev_err(dev, "Failed to allocate supply name\n"); 257 return -ENOMEM; 258 } 259 260 drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *), 261 GFP_KERNEL); 262 if (!drvdata->gpiods) 263 return -ENOMEM; 264 for (i = 0; i < config->ngpios; i++) { 265 drvdata->gpiods[i] = devm_gpiod_get_index(dev, 266 NULL, 267 i, 268 config->gflags[i]); 269 if (IS_ERR(drvdata->gpiods[i])) 270 return PTR_ERR(drvdata->gpiods[i]); 271 /* This is good to know */ 272 gpiod_set_consumer_name(drvdata->gpiods[i], drvdata->desc.name); 273 } 274 drvdata->nr_gpios = config->ngpios; 275 276 drvdata->states = devm_kmemdup(dev, 277 config->states, 278 config->nr_states * 279 sizeof(struct gpio_regulator_state), 280 GFP_KERNEL); 281 if (drvdata->states == NULL) { 282 dev_err(dev, "Failed to allocate state data\n"); 283 return -ENOMEM; 284 } 285 drvdata->nr_states = config->nr_states; 286 287 drvdata->desc.owner = THIS_MODULE; 288 drvdata->desc.enable_time = config->startup_delay; 289 290 /* handle regulator type*/ 291 switch (config->type) { 292 case REGULATOR_VOLTAGE: 293 drvdata->desc.type = REGULATOR_VOLTAGE; 294 drvdata->desc.ops = &gpio_regulator_voltage_ops; 295 drvdata->desc.n_voltages = config->nr_states; 296 break; 297 case REGULATOR_CURRENT: 298 drvdata->desc.type = REGULATOR_CURRENT; 299 drvdata->desc.ops = &gpio_regulator_current_ops; 300 break; 301 default: 302 dev_err(dev, "No regulator type set\n"); 303 return -EINVAL; 304 } 305 306 /* build initial state from gpio init data. */ 307 state = 0; 308 for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) { 309 if (config->gflags[ptr] == GPIOD_OUT_HIGH) 310 state |= (1 << ptr); 311 } 312 drvdata->state = state; 313 314 cfg.dev = dev; 315 cfg.init_data = config->init_data; 316 cfg.driver_data = drvdata; 317 cfg.of_node = np; 318 319 /* 320 * The signal will be inverted by the GPIO core if flagged so in the 321 * descriptor. 322 */ 323 if (config->enabled_at_boot) 324 gflags = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE; 325 else 326 gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE; 327 328 cfg.ena_gpiod = gpiod_get_optional(dev, "enable", gflags); 329 if (IS_ERR(cfg.ena_gpiod)) 330 return PTR_ERR(cfg.ena_gpiod); 331 332 rdev = devm_regulator_register(dev, &drvdata->desc, &cfg); 333 if (IS_ERR(rdev)) { 334 ret = PTR_ERR(rdev); 335 dev_err(dev, "Failed to register regulator: %d\n", ret); 336 return ret; 337 } 338 339 platform_set_drvdata(pdev, drvdata); 340 341 return 0; 342} 343 344#if defined(CONFIG_OF) 345static const struct of_device_id regulator_gpio_of_match[] = { 346 { .compatible = "regulator-gpio", }, 347 {}, 348}; 349MODULE_DEVICE_TABLE(of, regulator_gpio_of_match); 350#endif 351 352static struct platform_driver gpio_regulator_driver = { 353 .probe = gpio_regulator_probe, 354 .driver = { 355 .name = "gpio-regulator", 356 .of_match_table = of_match_ptr(regulator_gpio_of_match), 357 }, 358}; 359 360static int __init gpio_regulator_init(void) 361{ 362 return platform_driver_register(&gpio_regulator_driver); 363} 364subsys_initcall(gpio_regulator_init); 365 366static void __exit gpio_regulator_exit(void) 367{ 368 platform_driver_unregister(&gpio_regulator_driver); 369} 370module_exit(gpio_regulator_exit); 371 372MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 373MODULE_DESCRIPTION("gpio voltage regulator"); 374MODULE_LICENSE("GPL"); 375MODULE_ALIAS("platform:gpio-regulator");