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, dev->of_node); 68 if (!config->init_data) 69 return NULL; 70 71 init_data = config->init_data; 72 init_data->constraints.apply_uV = 0; 73 74 config->supply_name = init_data->constraints.name; 75 if (init_data->constraints.min_uV == init_data->constraints.max_uV) { 76 config->microvolts = init_data->constraints.min_uV; 77 } else { 78 dev_err(dev, 79 "Fixed regulator specified with variable voltages\n"); 80 return NULL; 81 } 82 83 if (init_data->constraints.boot_on) 84 config->enabled_at_boot = true; 85 86 config->gpio = of_get_named_gpio(np, "gpio", 0); 87 delay = of_get_property(np, "startup-delay-us", NULL); 88 if (delay) 89 config->startup_delay = be32_to_cpu(*delay); 90 91 if (of_find_property(np, "enable-active-high", NULL)) 92 config->enable_high = true; 93 94 return config; 95 } 96 97 static int fixed_voltage_is_enabled(struct regulator_dev *dev) 98 { 99 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 100 101 return data->is_enabled; 102 } 103 104 static int fixed_voltage_enable(struct regulator_dev *dev) 105 { 106 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 107 108 gpio_set_value_cansleep(data->gpio, data->enable_high); 109 data->is_enabled = true; 110 111 return 0; 112 } 113 114 static int fixed_voltage_disable(struct regulator_dev *dev) 115 { 116 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 117 118 gpio_set_value_cansleep(data->gpio, !data->enable_high); 119 data->is_enabled = false; 120 121 return 0; 122 } 123 124 static int fixed_voltage_enable_time(struct regulator_dev *dev) 125 { 126 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 127 128 return data->startup_delay; 129 } 130 131 static int fixed_voltage_get_voltage(struct regulator_dev *dev) 132 { 133 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 134 135 if (data->microvolts) 136 return data->microvolts; 137 else 138 return -EINVAL; 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_gpio_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 struct regulator_ops fixed_voltage_ops = { 162 .get_voltage = fixed_voltage_get_voltage, 163 .list_voltage = fixed_voltage_list_voltage, 164 }; 165 166 static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) 167 { 168 struct fixed_voltage_config *config; 169 struct fixed_voltage_data *drvdata; 170 struct regulator_config cfg = { }; 171 int ret; 172 173 if (pdev->dev.of_node) 174 config = of_get_fixed_voltage_config(&pdev->dev); 175 else 176 config = pdev->dev.platform_data; 177 178 if (!config) 179 return -ENOMEM; 180 181 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data), 182 GFP_KERNEL); 183 if (drvdata == NULL) { 184 dev_err(&pdev->dev, "Failed to allocate device data\n"); 185 ret = -ENOMEM; 186 goto err; 187 } 188 189 drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); 190 if (drvdata->desc.name == NULL) { 191 dev_err(&pdev->dev, "Failed to allocate supply name\n"); 192 ret = -ENOMEM; 193 goto err; 194 } 195 drvdata->desc.type = REGULATOR_VOLTAGE; 196 drvdata->desc.owner = THIS_MODULE; 197 198 if (config->microvolts) 199 drvdata->desc.n_voltages = 1; 200 201 drvdata->microvolts = config->microvolts; 202 drvdata->gpio = config->gpio; 203 drvdata->startup_delay = config->startup_delay; 204 205 if (gpio_is_valid(config->gpio)) { 206 int gpio_flag; 207 drvdata->enable_high = config->enable_high; 208 209 /* FIXME: Remove below print warning 210 * 211 * config->gpio must be set to -EINVAL by platform code if 212 * GPIO control is not required. However, early adopters 213 * not requiring GPIO control may forget to initialize 214 * config->gpio to -EINVAL. This will cause GPIO 0 to be used 215 * for GPIO control. 216 * 217 * This warning will be removed once there are a couple of users 218 * for this driver. 219 */ 220 if (!config->gpio) 221 dev_warn(&pdev->dev, 222 "using GPIO 0 for regulator enable control\n"); 223 224 /* 225 * set output direction without changing state 226 * to prevent glitch 227 */ 228 drvdata->is_enabled = config->enabled_at_boot; 229 ret = drvdata->is_enabled ? 230 config->enable_high : !config->enable_high; 231 gpio_flag = ret ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; 232 233 if (config->gpio_is_open_drain) 234 gpio_flag |= GPIOF_OPEN_DRAIN; 235 236 ret = gpio_request_one(config->gpio, gpio_flag, 237 config->supply_name); 238 if (ret) { 239 dev_err(&pdev->dev, 240 "Could not obtain regulator enable GPIO %d: %d\n", 241 config->gpio, ret); 242 goto err_name; 243 } 244 245 drvdata->desc.ops = &fixed_voltage_gpio_ops; 246 247 } else { 248 drvdata->desc.ops = &fixed_voltage_ops; 249 } 250 251 cfg.dev = &pdev->dev; 252 cfg.init_data = config->init_data; 253 cfg.driver_data = drvdata; 254 cfg.of_node = pdev->dev.of_node; 255 256 drvdata->dev = regulator_register(&drvdata->desc, &cfg); 257 if (IS_ERR(drvdata->dev)) { 258 ret = PTR_ERR(drvdata->dev); 259 dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); 260 goto err_gpio; 261 } 262 263 platform_set_drvdata(pdev, drvdata); 264 265 dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name, 266 drvdata->microvolts); 267 268 return 0; 269 270 err_gpio: 271 if (gpio_is_valid(config->gpio)) 272 gpio_free(config->gpio); 273 err_name: 274 kfree(drvdata->desc.name); 275 err: 276 return ret; 277 } 278 279 static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) 280 { 281 struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev); 282 283 regulator_unregister(drvdata->dev); 284 if (gpio_is_valid(drvdata->gpio)) 285 gpio_free(drvdata->gpio); 286 kfree(drvdata->desc.name); 287 288 return 0; 289 } 290 291 #if defined(CONFIG_OF) 292 static const struct of_device_id fixed_of_match[] __devinitconst = { 293 { .compatible = "regulator-fixed", }, 294 {}, 295 }; 296 MODULE_DEVICE_TABLE(of, fixed_of_match); 297 #else 298 #define fixed_of_match NULL 299 #endif 300 301 static struct platform_driver regulator_fixed_voltage_driver = { 302 .probe = reg_fixed_voltage_probe, 303 .remove = __devexit_p(reg_fixed_voltage_remove), 304 .driver = { 305 .name = "reg-fixed-voltage", 306 .owner = THIS_MODULE, 307 .of_match_table = fixed_of_match, 308 }, 309 }; 310 311 static int __init regulator_fixed_voltage_init(void) 312 { 313 return platform_driver_register(®ulator_fixed_voltage_driver); 314 } 315 subsys_initcall(regulator_fixed_voltage_init); 316 317 static void __exit regulator_fixed_voltage_exit(void) 318 { 319 platform_driver_unregister(®ulator_fixed_voltage_driver); 320 } 321 module_exit(regulator_fixed_voltage_exit); 322 323 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 324 MODULE_DESCRIPTION("Fixed voltage regulator"); 325 MODULE_LICENSE("GPL"); 326 MODULE_ALIAS("platform:reg-fixed-voltage"); 327