brintos

brintos / linux-shallow public Read only

0
0
Text · 9.8 KiB · 65927fa Raw
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", &regtype);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