392 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * gpio-regulator.c4 *5 * Copyright 2011 Heiko Stuebner <heiko@sntech.de>6 *7 * based on fixed.c8 *9 * Copyright 2008 Wolfson Microelectronics PLC.10 *11 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>12 *13 * Copyright (c) 2009 Nokia Corporation14 * Roger Quadros <ext-roger.quadros@nokia.com>15 *16 * This is useful for systems with mixed controllable and17 * non-controllable regulators, as well as for allowing testing on18 * 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 else183 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 else219 dev_warn(dev, "Unknown regulator-type '%s'\n",220 regtype);221 }222 223 if (of_property_present(np, "vin-supply"))224 config->input_supply = "vin";225 226 return config;227}228 229static const struct regulator_ops gpio_regulator_current_ops = {230 .get_current_limit = gpio_regulator_get_value,231 .set_current_limit = gpio_regulator_set_current_limit,232};233 234static int gpio_regulator_probe(struct platform_device *pdev)235{236 struct device *dev = &pdev->dev;237 struct gpio_regulator_config *config = dev_get_platdata(dev);238 struct device_node *np = dev->of_node;239 struct gpio_regulator_data *drvdata;240 struct regulator_config cfg = { };241 struct regulator_dev *rdev;242 enum gpiod_flags gflags;243 int ptr, ret, state, i;244 245 drvdata = devm_kzalloc(dev, sizeof(struct gpio_regulator_data),246 GFP_KERNEL);247 if (drvdata == NULL)248 return -ENOMEM;249 250 if (np) {251 config = of_get_gpio_regulator_config(dev, np,252 &drvdata->desc);253 if (IS_ERR(config))254 return PTR_ERR(config);255 }256 257 drvdata->desc.name = devm_kstrdup(dev, config->supply_name, GFP_KERNEL);258 if (drvdata->desc.name == NULL) {259 dev_err(dev, "Failed to allocate supply name\n");260 return -ENOMEM;261 }262 263 drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *),264 GFP_KERNEL);265 266 if (config->input_supply) {267 drvdata->desc.supply_name = devm_kstrdup(&pdev->dev,268 config->input_supply,269 GFP_KERNEL);270 if (!drvdata->desc.supply_name) {271 dev_err(&pdev->dev,272 "Failed to allocate input supply\n");273 return -ENOMEM;274 }275 }276 277 if (!drvdata->gpiods)278 return -ENOMEM;279 for (i = 0; i < config->ngpios; i++) {280 drvdata->gpiods[i] = devm_gpiod_get_index(dev,281 NULL,282 i,283 config->gflags[i]);284 if (IS_ERR(drvdata->gpiods[i]))285 return PTR_ERR(drvdata->gpiods[i]);286 /* This is good to know */287 gpiod_set_consumer_name(drvdata->gpiods[i], drvdata->desc.name);288 }289 drvdata->nr_gpios = config->ngpios;290 291 drvdata->states = devm_kmemdup(dev,292 config->states,293 config->nr_states *294 sizeof(struct gpio_regulator_state),295 GFP_KERNEL);296 if (drvdata->states == NULL) {297 dev_err(dev, "Failed to allocate state data\n");298 return -ENOMEM;299 }300 drvdata->nr_states = config->nr_states;301 302 drvdata->desc.owner = THIS_MODULE;303 drvdata->desc.enable_time = config->startup_delay;304 305 /* handle regulator type*/306 switch (config->type) {307 case REGULATOR_VOLTAGE:308 drvdata->desc.type = REGULATOR_VOLTAGE;309 drvdata->desc.ops = &gpio_regulator_voltage_ops;310 drvdata->desc.n_voltages = config->nr_states;311 break;312 case REGULATOR_CURRENT:313 drvdata->desc.type = REGULATOR_CURRENT;314 drvdata->desc.ops = &gpio_regulator_current_ops;315 break;316 default:317 dev_err(dev, "No regulator type set\n");318 return -EINVAL;319 }320 321 /* build initial state from gpio init data. */322 state = 0;323 for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) {324 if (config->gflags[ptr] == GPIOD_OUT_HIGH)325 state |= (1 << ptr);326 }327 drvdata->state = state;328 329 cfg.dev = dev;330 cfg.init_data = config->init_data;331 cfg.driver_data = drvdata;332 cfg.of_node = np;333 334 /*335 * The signal will be inverted by the GPIO core if flagged so in the336 * descriptor.337 */338 if (config->enabled_at_boot)339 gflags = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE;340 else341 gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE;342 343 cfg.ena_gpiod = gpiod_get_optional(dev, "enable", gflags);344 if (IS_ERR(cfg.ena_gpiod))345 return PTR_ERR(cfg.ena_gpiod);346 347 rdev = devm_regulator_register(dev, &drvdata->desc, &cfg);348 if (IS_ERR(rdev)) {349 ret = PTR_ERR(rdev);350 dev_err(dev, "Failed to register regulator: %d\n", ret);351 return ret;352 }353 354 platform_set_drvdata(pdev, drvdata);355 356 return 0;357}358 359#if defined(CONFIG_OF)360static const struct of_device_id regulator_gpio_of_match[] = {361 { .compatible = "regulator-gpio", },362 {},363};364MODULE_DEVICE_TABLE(of, regulator_gpio_of_match);365#endif366 367static struct platform_driver gpio_regulator_driver = {368 .probe = gpio_regulator_probe,369 .driver = {370 .name = "gpio-regulator",371 .probe_type = PROBE_PREFER_ASYNCHRONOUS,372 .of_match_table = of_match_ptr(regulator_gpio_of_match),373 },374};375 376static int __init gpio_regulator_init(void)377{378 return platform_driver_register(&gpio_regulator_driver);379}380subsys_initcall(gpio_regulator_init);381 382static void __exit gpio_regulator_exit(void)383{384 platform_driver_unregister(&gpio_regulator_driver);385}386module_exit(gpio_regulator_exit);387 388MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");389MODULE_DESCRIPTION("gpio voltage regulator");390MODULE_LICENSE("GPL");391MODULE_ALIAS("platform:gpio-regulator");392