1 /* 2 * Regulator support for WM8400 3 * 4 * Copyright 2008 Wolfson Microelectronics PLC. 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of the 11 * License, or (at your option) any later version. 12 * 13 */ 14 15 #include <linux/bug.h> 16 #include <linux/err.h> 17 #include <linux/kernel.h> 18 #include <linux/module.h> 19 #include <linux/regulator/driver.h> 20 #include <linux/mfd/wm8400-private.h> 21 22 static int wm8400_ldo_is_enabled(struct regulator_dev *dev) 23 { 24 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 25 u16 val; 26 27 val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev)); 28 return (val & WM8400_LDO1_ENA) != 0; 29 } 30 31 static int wm8400_ldo_enable(struct regulator_dev *dev) 32 { 33 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 34 35 return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev), 36 WM8400_LDO1_ENA, WM8400_LDO1_ENA); 37 } 38 39 static int wm8400_ldo_disable(struct regulator_dev *dev) 40 { 41 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 42 43 return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev), 44 WM8400_LDO1_ENA, 0); 45 } 46 47 static int wm8400_ldo_list_voltage(struct regulator_dev *dev, 48 unsigned selector) 49 { 50 if (selector > WM8400_LDO1_VSEL_MASK) 51 return -EINVAL; 52 53 if (selector < 15) 54 return 900000 + (selector * 50000); 55 else 56 return 1600000 + ((selector - 14) * 100000); 57 } 58 59 static int wm8400_ldo_get_voltage_sel(struct regulator_dev *dev) 60 { 61 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 62 u16 val; 63 64 val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev)); 65 val &= WM8400_LDO1_VSEL_MASK; 66 67 return val; 68 } 69 70 static int wm8400_ldo_set_voltage(struct regulator_dev *dev, 71 int min_uV, int max_uV, unsigned *selector) 72 { 73 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 74 u16 val; 75 76 if (min_uV < 900000 || min_uV > 3300000) 77 return -EINVAL; 78 79 if (min_uV < 1700000) { 80 /* Steps of 50mV from 900mV; */ 81 val = (min_uV - 850001) / 50000; 82 83 if ((val * 50000) + 900000 > max_uV) 84 return -EINVAL; 85 BUG_ON((val * 50000) + 900000 < min_uV); 86 } else { 87 /* Steps of 100mV from 1700mV */ 88 val = ((min_uV - 1600001) / 100000); 89 90 if ((val * 100000) + 1700000 > max_uV) 91 return -EINVAL; 92 BUG_ON((val * 100000) + 1700000 < min_uV); 93 94 val += 0xf; 95 } 96 97 *selector = val; 98 99 return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev), 100 WM8400_LDO1_VSEL_MASK, val); 101 } 102 103 static struct regulator_ops wm8400_ldo_ops = { 104 .is_enabled = wm8400_ldo_is_enabled, 105 .enable = wm8400_ldo_enable, 106 .disable = wm8400_ldo_disable, 107 .list_voltage = wm8400_ldo_list_voltage, 108 .get_voltage_sel = wm8400_ldo_get_voltage_sel, 109 .set_voltage = wm8400_ldo_set_voltage, 110 }; 111 112 static int wm8400_dcdc_is_enabled(struct regulator_dev *dev) 113 { 114 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 115 int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; 116 u16 val; 117 118 val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset); 119 return (val & WM8400_DC1_ENA) != 0; 120 } 121 122 static int wm8400_dcdc_enable(struct regulator_dev *dev) 123 { 124 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 125 int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; 126 127 return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 128 WM8400_DC1_ENA, WM8400_DC1_ENA); 129 } 130 131 static int wm8400_dcdc_disable(struct regulator_dev *dev) 132 { 133 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 134 int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; 135 136 return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 137 WM8400_DC1_ENA, 0); 138 } 139 140 static int wm8400_dcdc_list_voltage(struct regulator_dev *dev, 141 unsigned selector) 142 { 143 if (selector > WM8400_DC1_VSEL_MASK) 144 return -EINVAL; 145 146 return 850000 + (selector * 25000); 147 } 148 149 static int wm8400_dcdc_get_voltage_sel(struct regulator_dev *dev) 150 { 151 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 152 u16 val; 153 int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; 154 155 val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset); 156 val &= WM8400_DC1_VSEL_MASK; 157 158 return val; 159 } 160 161 static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, 162 int min_uV, int max_uV, unsigned *selector) 163 { 164 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 165 u16 val; 166 int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; 167 168 if (min_uV < 850000) 169 return -EINVAL; 170 171 val = (min_uV - 825001) / 25000; 172 173 if (850000 + (25000 * val) > max_uV) 174 return -EINVAL; 175 BUG_ON(850000 + (25000 * val) < min_uV); 176 177 *selector = val; 178 179 return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 180 WM8400_DC1_VSEL_MASK, val); 181 } 182 183 static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev) 184 { 185 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 186 int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; 187 u16 data[2]; 188 int ret; 189 190 ret = wm8400_block_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 2, 191 data); 192 if (ret != 0) 193 return 0; 194 195 /* Datasheet: hibernate */ 196 if (data[0] & WM8400_DC1_SLEEP) 197 return REGULATOR_MODE_STANDBY; 198 199 /* Datasheet: standby */ 200 if (!(data[0] & WM8400_DC1_ACTIVE)) 201 return REGULATOR_MODE_IDLE; 202 203 /* Datasheet: active with or without force PWM */ 204 if (data[1] & WM8400_DC1_FRC_PWM) 205 return REGULATOR_MODE_FAST; 206 else 207 return REGULATOR_MODE_NORMAL; 208 } 209 210 static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode) 211 { 212 struct wm8400 *wm8400 = rdev_get_drvdata(dev); 213 int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2; 214 int ret; 215 216 switch (mode) { 217 case REGULATOR_MODE_FAST: 218 /* Datasheet: active with force PWM */ 219 ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset, 220 WM8400_DC1_FRC_PWM, WM8400_DC1_FRC_PWM); 221 if (ret != 0) 222 return ret; 223 224 return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 225 WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP, 226 WM8400_DC1_ACTIVE); 227 228 case REGULATOR_MODE_NORMAL: 229 /* Datasheet: active */ 230 ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset, 231 WM8400_DC1_FRC_PWM, 0); 232 if (ret != 0) 233 return ret; 234 235 return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 236 WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP, 237 WM8400_DC1_ACTIVE); 238 239 case REGULATOR_MODE_IDLE: 240 /* Datasheet: standby */ 241 ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 242 WM8400_DC1_ACTIVE, 0); 243 if (ret != 0) 244 return ret; 245 return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 246 WM8400_DC1_SLEEP, 0); 247 248 default: 249 return -EINVAL; 250 } 251 } 252 253 static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev, 254 int input_uV, int output_uV, 255 int load_uA) 256 { 257 return REGULATOR_MODE_NORMAL; 258 } 259 260 static struct regulator_ops wm8400_dcdc_ops = { 261 .is_enabled = wm8400_dcdc_is_enabled, 262 .enable = wm8400_dcdc_enable, 263 .disable = wm8400_dcdc_disable, 264 .list_voltage = wm8400_dcdc_list_voltage, 265 .get_voltage_sel = wm8400_dcdc_get_voltage_sel, 266 .set_voltage = wm8400_dcdc_set_voltage, 267 .get_mode = wm8400_dcdc_get_mode, 268 .set_mode = wm8400_dcdc_set_mode, 269 .get_optimum_mode = wm8400_dcdc_get_optimum_mode, 270 }; 271 272 static struct regulator_desc regulators[] = { 273 { 274 .name = "LDO1", 275 .id = WM8400_LDO1, 276 .ops = &wm8400_ldo_ops, 277 .n_voltages = WM8400_LDO1_VSEL_MASK + 1, 278 .type = REGULATOR_VOLTAGE, 279 .owner = THIS_MODULE, 280 }, 281 { 282 .name = "LDO2", 283 .id = WM8400_LDO2, 284 .ops = &wm8400_ldo_ops, 285 .n_voltages = WM8400_LDO2_VSEL_MASK + 1, 286 .type = REGULATOR_VOLTAGE, 287 .owner = THIS_MODULE, 288 }, 289 { 290 .name = "LDO3", 291 .id = WM8400_LDO3, 292 .ops = &wm8400_ldo_ops, 293 .n_voltages = WM8400_LDO3_VSEL_MASK + 1, 294 .type = REGULATOR_VOLTAGE, 295 .owner = THIS_MODULE, 296 }, 297 { 298 .name = "LDO4", 299 .id = WM8400_LDO4, 300 .ops = &wm8400_ldo_ops, 301 .n_voltages = WM8400_LDO4_VSEL_MASK + 1, 302 .type = REGULATOR_VOLTAGE, 303 .owner = THIS_MODULE, 304 }, 305 { 306 .name = "DCDC1", 307 .id = WM8400_DCDC1, 308 .ops = &wm8400_dcdc_ops, 309 .n_voltages = WM8400_DC1_VSEL_MASK + 1, 310 .type = REGULATOR_VOLTAGE, 311 .owner = THIS_MODULE, 312 }, 313 { 314 .name = "DCDC2", 315 .id = WM8400_DCDC2, 316 .ops = &wm8400_dcdc_ops, 317 .n_voltages = WM8400_DC2_VSEL_MASK + 1, 318 .type = REGULATOR_VOLTAGE, 319 .owner = THIS_MODULE, 320 }, 321 }; 322 323 static int __devinit wm8400_regulator_probe(struct platform_device *pdev) 324 { 325 struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]); 326 struct regulator_dev *rdev; 327 328 rdev = regulator_register(®ulators[pdev->id], &pdev->dev, 329 pdev->dev.platform_data, wm8400); 330 331 if (IS_ERR(rdev)) 332 return PTR_ERR(rdev); 333 334 platform_set_drvdata(pdev, rdev); 335 336 return 0; 337 } 338 339 static int __devexit wm8400_regulator_remove(struct platform_device *pdev) 340 { 341 struct regulator_dev *rdev = platform_get_drvdata(pdev); 342 343 platform_set_drvdata(pdev, NULL); 344 regulator_unregister(rdev); 345 346 return 0; 347 } 348 349 static struct platform_driver wm8400_regulator_driver = { 350 .driver = { 351 .name = "wm8400-regulator", 352 }, 353 .probe = wm8400_regulator_probe, 354 .remove = __devexit_p(wm8400_regulator_remove), 355 }; 356 357 /** 358 * wm8400_register_regulator - enable software control of a WM8400 regulator 359 * 360 * This function enables software control of a WM8400 regulator via 361 * the regulator API. It is intended to be called from the 362 * platform_init() callback of the WM8400 MFD driver. 363 * 364 * @param dev The WM8400 device to operate on. 365 * @param reg The regulator to control. 366 * @param initdata Regulator initdata for the regulator. 367 */ 368 int wm8400_register_regulator(struct device *dev, int reg, 369 struct regulator_init_data *initdata) 370 { 371 struct wm8400 *wm8400 = dev_get_drvdata(dev); 372 373 if (wm8400->regulators[reg].name) 374 return -EBUSY; 375 376 initdata->driver_data = wm8400; 377 378 wm8400->regulators[reg].name = "wm8400-regulator"; 379 wm8400->regulators[reg].id = reg; 380 wm8400->regulators[reg].dev.parent = dev; 381 wm8400->regulators[reg].dev.platform_data = initdata; 382 383 return platform_device_register(&wm8400->regulators[reg]); 384 } 385 EXPORT_SYMBOL_GPL(wm8400_register_regulator); 386 387 static int __init wm8400_regulator_init(void) 388 { 389 return platform_driver_register(&wm8400_regulator_driver); 390 } 391 subsys_initcall(wm8400_regulator_init); 392 393 static void __exit wm8400_regulator_exit(void) 394 { 395 platform_driver_unregister(&wm8400_regulator_driver); 396 } 397 module_exit(wm8400_regulator_exit); 398 399 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 400 MODULE_DESCRIPTION("WM8400 regulator driver"); 401 MODULE_LICENSE("GPL"); 402 MODULE_ALIAS("platform:wm8400-regulator"); 403