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/delay.h> 29 #include <linux/slab.h> 30 #include <linux/of.h> 31 #include <linux/of_gpio.h> 32 #include <linux/regulator/of_regulator.h> 33 #include <linux/regulator/machine.h> 34 35 struct fixed_voltage_data { 36 struct regulator_desc desc; 37 struct regulator_dev *dev; 38 int microvolts; 39 int gpio; 40 unsigned startup_delay; 41 bool enable_high; 42 bool is_enabled; 43 }; 44 45 46 /** 47 * of_get_fixed_voltage_config - extract fixed_voltage_config structure info 48 * @dev: device requesting for fixed_voltage_config 49 * 50 * Populates fixed_voltage_config structure by extracting data from device 51 * tree node, returns a pointer to the populated structure of NULL if memory 52 * alloc fails. 53 */ 54 static struct fixed_voltage_config * 55 of_get_fixed_voltage_config(struct device *dev) 56 { 57 struct fixed_voltage_config *config; 58 struct device_node *np = dev->of_node; 59 const __be32 *delay; 60 struct regulator_init_data *init_data; 61 62 config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), 63 GFP_KERNEL); 64 if (!config) 65 return NULL; 66 67 config->init_data = of_get_regulator_init_data(dev); 68 if (!config->init_data) 69 return NULL; 70 71 init_data = config->init_data; 72 73 config->supply_name = init_data->constraints.name; 74 if (init_data->constraints.min_uV == init_data->constraints.max_uV) { 75 config->microvolts = init_data->constraints.min_uV; 76 } else { 77 dev_err(dev, 78 "Fixed regulator specified with variable voltages\n"); 79 return NULL; 80 } 81 82 if (init_data->constraints.boot_on) 83 config->enabled_at_boot = true; 84 85 config->gpio = of_get_named_gpio(np, "gpio", 0); 86 delay = of_get_property(np, "startup-delay-us", NULL); 87 if (delay) 88 config->startup_delay = be32_to_cpu(*delay); 89 90 if (of_find_property(np, "enable-active-high", NULL)) 91 config->enable_high = true; 92 93 return config; 94 } 95 96 static int fixed_voltage_is_enabled(struct regulator_dev *dev) 97 { 98 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 99 100 return data->is_enabled; 101 } 102 103 static int fixed_voltage_enable(struct regulator_dev *dev) 104 { 105 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 106 107 if (gpio_is_valid(data->gpio)) { 108 gpio_set_value_cansleep(data->gpio, data->enable_high); 109 data->is_enabled = true; 110 } 111 112 return 0; 113 } 114 115 static int fixed_voltage_disable(struct regulator_dev *dev) 116 { 117 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 118 119 if (gpio_is_valid(data->gpio)) { 120 gpio_set_value_cansleep(data->gpio, !data->enable_high); 121 data->is_enabled = false; 122 } 123 124 return 0; 125 } 126 127 static int fixed_voltage_enable_time(struct regulator_dev *dev) 128 { 129 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 130 131 return data->startup_delay; 132 } 133 134 static int fixed_voltage_get_voltage(struct regulator_dev *dev) 135 { 136 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 137 138 return data->microvolts; 139 } 140 141 static int fixed_voltage_list_voltage(struct regulator_dev *dev, 142 unsigned selector) 143 { 144 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 145 146 if (selector != 0) 147 return -EINVAL; 148 149 return data->microvolts; 150 } 151 152 static struct regulator_ops fixed_voltage_ops = { 153 .is_enabled = fixed_voltage_is_enabled, 154 .enable = fixed_voltage_enable, 155 .disable = fixed_voltage_disable, 156 .enable_time = fixed_voltage_enable_time, 157 .get_voltage = fixed_voltage_get_voltage, 158 .list_voltage = fixed_voltage_list_voltage, 159 }; 160 161 static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) 162 { 163 struct fixed_voltage_config *config; 164 struct fixed_voltage_data *drvdata; 165 int ret; 166 167 if (pdev->dev.of_node) 168 config = of_get_fixed_voltage_config(&pdev->dev); 169 else 170 config = pdev->dev.platform_data; 171 172 if (!config) 173 return -ENOMEM; 174 175 drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL); 176 if (drvdata == NULL) { 177 dev_err(&pdev->dev, "Failed to allocate device data\n"); 178 ret = -ENOMEM; 179 goto err; 180 } 181 182 drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); 183 if (drvdata->desc.name == NULL) { 184 dev_err(&pdev->dev, "Failed to allocate supply name\n"); 185 ret = -ENOMEM; 186 goto err; 187 } 188 drvdata->desc.type = REGULATOR_VOLTAGE; 189 drvdata->desc.owner = THIS_MODULE; 190 drvdata->desc.ops = &fixed_voltage_ops; 191 drvdata->desc.n_voltages = 1; 192 193 drvdata->microvolts = config->microvolts; 194 drvdata->gpio = config->gpio; 195 drvdata->startup_delay = config->startup_delay; 196 197 if (gpio_is_valid(config->gpio)) { 198 drvdata->enable_high = config->enable_high; 199 200 /* FIXME: Remove below print warning 201 * 202 * config->gpio must be set to -EINVAL by platform code if 203 * GPIO control is not required. However, early adopters 204 * not requiring GPIO control may forget to initialize 205 * config->gpio to -EINVAL. This will cause GPIO 0 to be used 206 * for GPIO control. 207 * 208 * This warning will be removed once there are a couple of users 209 * for this driver. 210 */ 211 if (!config->gpio) 212 dev_warn(&pdev->dev, 213 "using GPIO 0 for regulator enable control\n"); 214 215 ret = gpio_request(config->gpio, config->supply_name); 216 if (ret) { 217 dev_err(&pdev->dev, 218 "Could not obtain regulator enable GPIO %d: %d\n", 219 config->gpio, ret); 220 goto err_name; 221 } 222 223 /* set output direction without changing state 224 * to prevent glitch 225 */ 226 drvdata->is_enabled = config->enabled_at_boot; 227 ret = drvdata->is_enabled ? 228 config->enable_high : !config->enable_high; 229 230 ret = gpio_direction_output(config->gpio, ret); 231 if (ret) { 232 dev_err(&pdev->dev, 233 "Could not configure regulator enable GPIO %d direction: %d\n", 234 config->gpio, ret); 235 goto err_gpio; 236 } 237 238 } else { 239 /* Regulator without GPIO control is considered 240 * always enabled 241 */ 242 drvdata->is_enabled = true; 243 } 244 245 drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, 246 config->init_data, drvdata, NULL); 247 if (IS_ERR(drvdata->dev)) { 248 ret = PTR_ERR(drvdata->dev); 249 dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); 250 goto err_gpio; 251 } 252 253 platform_set_drvdata(pdev, drvdata); 254 255 dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name, 256 drvdata->microvolts); 257 258 return 0; 259 260 err_gpio: 261 if (gpio_is_valid(config->gpio)) 262 gpio_free(config->gpio); 263 err_name: 264 kfree(drvdata->desc.name); 265 err: 266 kfree(drvdata); 267 return ret; 268 } 269 270 static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) 271 { 272 struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev); 273 274 regulator_unregister(drvdata->dev); 275 if (gpio_is_valid(drvdata->gpio)) 276 gpio_free(drvdata->gpio); 277 kfree(drvdata->desc.name); 278 kfree(drvdata); 279 280 return 0; 281 } 282 283 #if defined(CONFIG_OF) 284 static const struct of_device_id fixed_of_match[] __devinitconst = { 285 { .compatible = "regulator-fixed", }, 286 {}, 287 }; 288 MODULE_DEVICE_TABLE(of, fixed_of_match); 289 #else 290 #define fixed_of_match NULL 291 #endif 292 293 static struct platform_driver regulator_fixed_voltage_driver = { 294 .probe = reg_fixed_voltage_probe, 295 .remove = __devexit_p(reg_fixed_voltage_remove), 296 .driver = { 297 .name = "reg-fixed-voltage", 298 .owner = THIS_MODULE, 299 .of_match_table = fixed_of_match, 300 }, 301 }; 302 303 static int __init regulator_fixed_voltage_init(void) 304 { 305 return platform_driver_register(®ulator_fixed_voltage_driver); 306 } 307 subsys_initcall(regulator_fixed_voltage_init); 308 309 static void __exit regulator_fixed_voltage_exit(void) 310 { 311 platform_driver_unregister(®ulator_fixed_voltage_driver); 312 } 313 module_exit(regulator_fixed_voltage_exit); 314 315 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 316 MODULE_DESCRIPTION("Fixed voltage regulator"); 317 MODULE_LICENSE("GPL"); 318 MODULE_ALIAS("platform:reg-fixed-voltage"); 319