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 if (gpio_is_valid(data->gpio)) { 109 gpio_set_value_cansleep(data->gpio, data->enable_high); 110 data->is_enabled = true; 111 } 112 113 return 0; 114 } 115 116 static int fixed_voltage_disable(struct regulator_dev *dev) 117 { 118 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 119 120 if (gpio_is_valid(data->gpio)) { 121 gpio_set_value_cansleep(data->gpio, !data->enable_high); 122 data->is_enabled = false; 123 } 124 125 return 0; 126 } 127 128 static int fixed_voltage_enable_time(struct regulator_dev *dev) 129 { 130 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 131 132 return data->startup_delay; 133 } 134 135 static int fixed_voltage_get_voltage(struct regulator_dev *dev) 136 { 137 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 138 139 if (data->microvolts) 140 return data->microvolts; 141 else 142 return -EINVAL; 143 } 144 145 static int fixed_voltage_list_voltage(struct regulator_dev *dev, 146 unsigned selector) 147 { 148 struct fixed_voltage_data *data = rdev_get_drvdata(dev); 149 150 if (selector != 0) 151 return -EINVAL; 152 153 return data->microvolts; 154 } 155 156 static struct regulator_ops fixed_voltage_ops = { 157 .is_enabled = fixed_voltage_is_enabled, 158 .enable = fixed_voltage_enable, 159 .disable = fixed_voltage_disable, 160 .enable_time = fixed_voltage_enable_time, 161 .get_voltage = fixed_voltage_get_voltage, 162 .list_voltage = fixed_voltage_list_voltage, 163 }; 164 165 static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) 166 { 167 struct fixed_voltage_config *config; 168 struct fixed_voltage_data *drvdata; 169 int ret; 170 171 if (pdev->dev.of_node) 172 config = of_get_fixed_voltage_config(&pdev->dev); 173 else 174 config = pdev->dev.platform_data; 175 176 if (!config) 177 return -ENOMEM; 178 179 drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL); 180 if (drvdata == NULL) { 181 dev_err(&pdev->dev, "Failed to allocate device data\n"); 182 ret = -ENOMEM; 183 goto err; 184 } 185 186 drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); 187 if (drvdata->desc.name == NULL) { 188 dev_err(&pdev->dev, "Failed to allocate supply name\n"); 189 ret = -ENOMEM; 190 goto err; 191 } 192 drvdata->desc.type = REGULATOR_VOLTAGE; 193 drvdata->desc.owner = THIS_MODULE; 194 drvdata->desc.ops = &fixed_voltage_ops; 195 196 if (config->microvolts) 197 drvdata->desc.n_voltages = 1; 198 199 drvdata->microvolts = config->microvolts; 200 drvdata->gpio = config->gpio; 201 drvdata->startup_delay = config->startup_delay; 202 203 if (gpio_is_valid(config->gpio)) { 204 drvdata->enable_high = config->enable_high; 205 206 /* FIXME: Remove below print warning 207 * 208 * config->gpio must be set to -EINVAL by platform code if 209 * GPIO control is not required. However, early adopters 210 * not requiring GPIO control may forget to initialize 211 * config->gpio to -EINVAL. This will cause GPIO 0 to be used 212 * for GPIO control. 213 * 214 * This warning will be removed once there are a couple of users 215 * for this driver. 216 */ 217 if (!config->gpio) 218 dev_warn(&pdev->dev, 219 "using GPIO 0 for regulator enable control\n"); 220 221 ret = gpio_request(config->gpio, config->supply_name); 222 if (ret) { 223 dev_err(&pdev->dev, 224 "Could not obtain regulator enable GPIO %d: %d\n", 225 config->gpio, ret); 226 goto err_name; 227 } 228 229 /* set output direction without changing state 230 * to prevent glitch 231 */ 232 drvdata->is_enabled = config->enabled_at_boot; 233 ret = drvdata->is_enabled ? 234 config->enable_high : !config->enable_high; 235 236 ret = gpio_direction_output(config->gpio, ret); 237 if (ret) { 238 dev_err(&pdev->dev, 239 "Could not configure regulator enable GPIO %d direction: %d\n", 240 config->gpio, ret); 241 goto err_gpio; 242 } 243 244 } else { 245 /* Regulator without GPIO control is considered 246 * always enabled 247 */ 248 drvdata->is_enabled = true; 249 } 250 251 drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, 252 config->init_data, drvdata, 253 pdev->dev.of_node); 254 if (IS_ERR(drvdata->dev)) { 255 ret = PTR_ERR(drvdata->dev); 256 dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); 257 goto err_gpio; 258 } 259 260 platform_set_drvdata(pdev, drvdata); 261 262 dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name, 263 drvdata->microvolts); 264 265 return 0; 266 267 err_gpio: 268 if (gpio_is_valid(config->gpio)) 269 gpio_free(config->gpio); 270 err_name: 271 kfree(drvdata->desc.name); 272 err: 273 kfree(drvdata); 274 return ret; 275 } 276 277 static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) 278 { 279 struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev); 280 281 regulator_unregister(drvdata->dev); 282 if (gpio_is_valid(drvdata->gpio)) 283 gpio_free(drvdata->gpio); 284 kfree(drvdata->desc.name); 285 kfree(drvdata); 286 287 return 0; 288 } 289 290 #if defined(CONFIG_OF) 291 static const struct of_device_id fixed_of_match[] __devinitconst = { 292 { .compatible = "regulator-fixed", }, 293 {}, 294 }; 295 MODULE_DEVICE_TABLE(of, fixed_of_match); 296 #else 297 #define fixed_of_match NULL 298 #endif 299 300 static struct platform_driver regulator_fixed_voltage_driver = { 301 .probe = reg_fixed_voltage_probe, 302 .remove = __devexit_p(reg_fixed_voltage_remove), 303 .driver = { 304 .name = "reg-fixed-voltage", 305 .owner = THIS_MODULE, 306 .of_match_table = fixed_of_match, 307 }, 308 }; 309 310 static int __init regulator_fixed_voltage_init(void) 311 { 312 return platform_driver_register(®ulator_fixed_voltage_driver); 313 } 314 subsys_initcall(regulator_fixed_voltage_init); 315 316 static void __exit regulator_fixed_voltage_exit(void) 317 { 318 platform_driver_unregister(®ulator_fixed_voltage_driver); 319 } 320 module_exit(regulator_fixed_voltage_exit); 321 322 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 323 MODULE_DESCRIPTION("Fixed voltage regulator"); 324 MODULE_LICENSE("GPL"); 325 MODULE_ALIAS("platform:reg-fixed-voltage"); 326