1 /* 2 * fixed.c 3 * 4 * Copyright 2008 Wolfson Microelectronics PLC. 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * Copyright (c) 2009 Nokia Corporation 9 * Roger Quadros <ext-roger.quadros@nokia.com> 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of the 14 * License, or (at your option) any later version. 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/fixed.h> 27 #include <linux/gpio.h> 28 #include <linux/slab.h> 29 #include <linux/of.h> 30 #include <linux/of_gpio.h> 31 #include <linux/regulator/of_regulator.h> 32 #include <linux/regulator/machine.h> 33 #include <linux/acpi.h> 34 #include <linux/property.h> 35 #include <linux/gpio/consumer.h> 36 37 struct fixed_voltage_data { 38 struct regulator_desc desc; 39 struct regulator_dev *dev; 40 }; 41 42 43 /** 44 * of_get_fixed_voltage_config - extract fixed_voltage_config structure info 45 * @dev: device requesting for fixed_voltage_config 46 * @desc: regulator description 47 * 48 * Populates fixed_voltage_config structure by extracting data from device 49 * tree node, returns a pointer to the populated structure of NULL if memory 50 * alloc fails. 51 */ 52 static struct fixed_voltage_config * 53 of_get_fixed_voltage_config(struct device *dev, 54 const struct regulator_desc *desc) 55 { 56 struct fixed_voltage_config *config; 57 struct device_node *np = dev->of_node; 58 struct regulator_init_data *init_data; 59 60 config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), 61 GFP_KERNEL); 62 if (!config) 63 return ERR_PTR(-ENOMEM); 64 65 config->init_data = of_get_regulator_init_data(dev, dev->of_node, desc); 66 if (!config->init_data) 67 return ERR_PTR(-EINVAL); 68 69 init_data = config->init_data; 70 init_data->constraints.apply_uV = 0; 71 72 config->supply_name = init_data->constraints.name; 73 if (init_data->constraints.min_uV == init_data->constraints.max_uV) { 74 config->microvolts = init_data->constraints.min_uV; 75 } else { 76 dev_err(dev, 77 "Fixed regulator specified with variable voltages\n"); 78 return ERR_PTR(-EINVAL); 79 } 80 81 if (init_data->constraints.boot_on) 82 config->enabled_at_boot = true; 83 84 config->gpio = of_get_named_gpio(np, "gpio", 0); 85 if ((config->gpio < 0) && (config->gpio != -ENOENT)) 86 return ERR_PTR(config->gpio); 87 88 of_property_read_u32(np, "startup-delay-us", &config->startup_delay); 89 90 config->enable_high = of_property_read_bool(np, "enable-active-high"); 91 config->gpio_is_open_drain = of_property_read_bool(np, 92 "gpio-open-drain"); 93 94 if (of_find_property(np, "vin-supply", NULL)) 95 config->input_supply = "vin"; 96 97 return config; 98 } 99 100 /** 101 * acpi_get_fixed_voltage_config - extract fixed_voltage_config structure info 102 * @dev: device requesting for fixed_voltage_config 103 * @desc: regulator description 104 * 105 * Populates fixed_voltage_config structure by extracting data through ACPI 106 * interface, returns a pointer to the populated structure of NULL if memory 107 * alloc fails. 108 */ 109 static struct fixed_voltage_config * 110 acpi_get_fixed_voltage_config(struct device *dev, 111 const struct regulator_desc *desc) 112 { 113 struct fixed_voltage_config *config; 114 const char *supply_name; 115 struct gpio_desc *gpiod; 116 int ret; 117 118 config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL); 119 if (!config) 120 return ERR_PTR(-ENOMEM); 121 122 ret = device_property_read_string(dev, "supply-name", &supply_name); 123 if (!ret) 124 config->supply_name = supply_name; 125 126 gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS); 127 if (IS_ERR(gpiod)) 128 return ERR_PTR(-ENODEV); 129 130 config->gpio = desc_to_gpio(gpiod); 131 config->enable_high = device_property_read_bool(dev, 132 "enable-active-high"); 133 gpiod_put(gpiod); 134 135 return config; 136 } 137 138 static struct regulator_ops fixed_voltage_ops = { 139 }; 140 141 static int reg_fixed_voltage_probe(struct platform_device *pdev) 142 { 143 struct fixed_voltage_config *config; 144 struct fixed_voltage_data *drvdata; 145 struct regulator_config cfg = { }; 146 int ret; 147 148 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data), 149 GFP_KERNEL); 150 if (!drvdata) 151 return -ENOMEM; 152 153 if (pdev->dev.of_node) { 154 config = of_get_fixed_voltage_config(&pdev->dev, 155 &drvdata->desc); 156 if (IS_ERR(config)) 157 return PTR_ERR(config); 158 } else if (ACPI_HANDLE(&pdev->dev)) { 159 config = acpi_get_fixed_voltage_config(&pdev->dev, 160 &drvdata->desc); 161 if (IS_ERR(config)) 162 return PTR_ERR(config); 163 } else { 164 config = dev_get_platdata(&pdev->dev); 165 } 166 167 if (!config) 168 return -ENOMEM; 169 170 drvdata->desc.name = devm_kstrdup(&pdev->dev, 171 config->supply_name, 172 GFP_KERNEL); 173 if (drvdata->desc.name == NULL) { 174 dev_err(&pdev->dev, "Failed to allocate supply name\n"); 175 return -ENOMEM; 176 } 177 drvdata->desc.type = REGULATOR_VOLTAGE; 178 drvdata->desc.owner = THIS_MODULE; 179 drvdata->desc.ops = &fixed_voltage_ops; 180 181 drvdata->desc.enable_time = config->startup_delay; 182 183 if (config->input_supply) { 184 drvdata->desc.supply_name = devm_kstrdup(&pdev->dev, 185 config->input_supply, 186 GFP_KERNEL); 187 if (!drvdata->desc.supply_name) { 188 dev_err(&pdev->dev, 189 "Failed to allocate input supply\n"); 190 return -ENOMEM; 191 } 192 } 193 194 if (config->microvolts) 195 drvdata->desc.n_voltages = 1; 196 197 drvdata->desc.fixed_uV = config->microvolts; 198 199 if (gpio_is_valid(config->gpio)) { 200 cfg.ena_gpio = config->gpio; 201 if (pdev->dev.of_node) 202 cfg.ena_gpio_initialized = true; 203 } 204 cfg.ena_gpio_invert = !config->enable_high; 205 if (config->enabled_at_boot) { 206 if (config->enable_high) 207 cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; 208 else 209 cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; 210 } else { 211 if (config->enable_high) 212 cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; 213 else 214 cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; 215 } 216 if (config->gpio_is_open_drain) 217 cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN; 218 219 cfg.dev = &pdev->dev; 220 cfg.init_data = config->init_data; 221 cfg.driver_data = drvdata; 222 cfg.of_node = pdev->dev.of_node; 223 224 drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc, 225 &cfg); 226 if (IS_ERR(drvdata->dev)) { 227 ret = PTR_ERR(drvdata->dev); 228 dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); 229 return ret; 230 } 231 232 platform_set_drvdata(pdev, drvdata); 233 234 dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name, 235 drvdata->desc.fixed_uV); 236 237 return 0; 238 } 239 240 #if defined(CONFIG_OF) 241 static const struct of_device_id fixed_of_match[] = { 242 { .compatible = "regulator-fixed", }, 243 {}, 244 }; 245 MODULE_DEVICE_TABLE(of, fixed_of_match); 246 #endif 247 248 static struct platform_driver regulator_fixed_voltage_driver = { 249 .probe = reg_fixed_voltage_probe, 250 .driver = { 251 .name = "reg-fixed-voltage", 252 .of_match_table = of_match_ptr(fixed_of_match), 253 }, 254 }; 255 256 static int __init regulator_fixed_voltage_init(void) 257 { 258 return platform_driver_register(®ulator_fixed_voltage_driver); 259 } 260 subsys_initcall(regulator_fixed_voltage_init); 261 262 static void __exit regulator_fixed_voltage_exit(void) 263 { 264 platform_driver_unregister(®ulator_fixed_voltage_driver); 265 } 266 module_exit(regulator_fixed_voltage_exit); 267 268 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 269 MODULE_DESCRIPTION("Fixed voltage regulator"); 270 MODULE_LICENSE("GPL"); 271 MODULE_ALIAS("platform:reg-fixed-voltage"); 272