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