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 regulator_dev *rdev; 321 322 rdev = regulator_register(®ulators[pdev->id], &pdev->dev, 323 pdev->dev.platform_data, pdev->dev.driver_data); 324 325 if (IS_ERR(rdev)) 326 return PTR_ERR(rdev); 327 328 return 0; 329 } 330 331 static int __devexit wm8400_regulator_remove(struct platform_device *pdev) 332 { 333 struct regulator_dev *rdev = platform_get_drvdata(pdev); 334 335 regulator_unregister(rdev); 336 337 return 0; 338 } 339 340 static struct platform_driver wm8400_regulator_driver = { 341 .driver = { 342 .name = "wm8400-regulator", 343 }, 344 .probe = wm8400_regulator_probe, 345 .remove = __devexit_p(wm8400_regulator_remove), 346 }; 347 348 /** 349 * wm8400_register_regulator - enable software control of a WM8400 regulator 350 * 351 * This function enables software control of a WM8400 regulator via 352 * the regulator API. It is intended to be called from the 353 * platform_init() callback of the WM8400 MFD driver. 354 * 355 * @param dev The WM8400 device to operate on. 356 * @param reg The regulator to control. 357 * @param initdata Regulator initdata for the regulator. 358 */ 359 int wm8400_register_regulator(struct device *dev, int reg, 360 struct regulator_init_data *initdata) 361 { 362 struct wm8400 *wm8400 = dev->driver_data; 363 364 if (wm8400->regulators[reg].name) 365 return -EBUSY; 366 367 initdata->driver_data = wm8400; 368 369 wm8400->regulators[reg].name = "wm8400-regulator"; 370 wm8400->regulators[reg].id = reg; 371 wm8400->regulators[reg].dev.parent = dev; 372 wm8400->regulators[reg].dev.driver_data = wm8400; 373 wm8400->regulators[reg].dev.platform_data = initdata; 374 375 return platform_device_register(&wm8400->regulators[reg]); 376 } 377 EXPORT_SYMBOL_GPL(wm8400_register_regulator); 378 379 static int __init wm8400_regulator_init(void) 380 { 381 return platform_driver_register(&wm8400_regulator_driver); 382 } 383 module_init(wm8400_regulator_init); 384 385 static void __exit wm8400_regulator_exit(void) 386 { 387 platform_driver_unregister(&wm8400_regulator_driver); 388 } 389 module_exit(wm8400_regulator_exit); 390 391 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 392 MODULE_DESCRIPTION("WM8400 regulator driver"); 393 MODULE_LICENSE("GPL"); 394 MODULE_ALIAS("platform:wm8400-regulator"); 395