diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-17 11:08:36 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-17 11:08:36 -0500 |
| commit | 22a80593598736e33080c6877be6ae99ec091e02 (patch) | |
| tree | 9cc8a0c1b982aa7194ff46a5b176fb4cae87051a | |
| parent | 5a865c0606eb44d5d12cabb429751c83712183de (diff) | |
| parent | 6f17c65240e35ae99319c659c74d54100a832f45 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6: (27 commits)
regulator: wm831x_reg_read() failure unnoticed in wm831x_aldo_get_mode()
twl-regulator: Fix reg_disable functionality for 4030 and 6030
twl-regulator: Add turnon delay to reg_enable
twl-regulator: Restore REMAP configuration in regulator probe
twl-regulator: Add turnon-delay and REMAP config to twlreg_info struct
twl-regulator: Define critical regulators as always_on
twl-regulator: Add all twl4030 regulators to twlreg_info
regulator: mc13783-regulator: correct the probing time.
regulator: Fix unbalanced disables/enables in regulator_bulk_{enable,disable} error path
regulator: core.c: Small coding style cleanup (indentation fixup)
drivers/regulator: use PTR_ERR to get error code
regulator: consumer.h - fix build when consumer.h is #included first.
regulator/mc13783: various cleanups
regulator/mc13783: rename source file to match other drivers
Fix some AB3100 regulator issues
regulator: keep index within bounds in da9034_get_ldo12_voltage()
regulator: Ensure val is initialised in 88pm8607 choose_voltage()
regulator: Remove duplicate consts from ab3100
regulator: Handle regulators without suspend mode configuration
regulator: Factor out regulator name pretty printing
...
| -rw-r--r-- | drivers/regulator/88pm8607.c | 685 | ||||
| -rw-r--r-- | drivers/regulator/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/regulator/Makefile | 4 | ||||
| -rw-r--r-- | drivers/regulator/ab3100.c | 33 | ||||
| -rw-r--r-- | drivers/regulator/core.c | 248 | ||||
| -rw-r--r-- | drivers/regulator/da903x.c | 2 | ||||
| -rw-r--r-- | drivers/regulator/lp3971.c | 4 | ||||
| -rw-r--r-- | drivers/regulator/max8660.c | 510 | ||||
| -rw-r--r-- | drivers/regulator/mc13783-regulator.c | 245 | ||||
| -rw-r--r-- | drivers/regulator/mc13783.c | 410 | ||||
| -rw-r--r-- | drivers/regulator/twl-regulator.c | 147 | ||||
| -rw-r--r-- | drivers/regulator/wm831x-dcdc.c | 207 | ||||
| -rw-r--r-- | drivers/regulator/wm831x-ldo.c | 2 | ||||
| -rw-r--r-- | include/linux/mfd/wm831x/pdata.h | 17 | ||||
| -rw-r--r-- | include/linux/regulator/consumer.h | 2 | ||||
| -rw-r--r-- | include/linux/regulator/machine.h | 6 | ||||
| -rw-r--r-- | include/linux/regulator/max8660.h | 57 |
17 files changed, 1981 insertions, 611 deletions
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c new file mode 100644 index 000000000000..04719551381b --- /dev/null +++ b/drivers/regulator/88pm8607.c | |||
| @@ -0,0 +1,685 @@ | |||
| 1 | /* | ||
| 2 | * Regulators driver for Marvell 88PM8607 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Marvell International Ltd. | ||
| 5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/regulator/driver.h> | ||
| 16 | #include <linux/regulator/machine.h> | ||
| 17 | #include <linux/mfd/88pm8607.h> | ||
| 18 | |||
| 19 | struct pm8607_regulator_info { | ||
| 20 | struct regulator_desc desc; | ||
| 21 | struct pm8607_chip *chip; | ||
| 22 | struct regulator_dev *regulator; | ||
| 23 | |||
| 24 | int min_uV; | ||
| 25 | int max_uV; | ||
| 26 | int step_uV; | ||
| 27 | int vol_reg; | ||
| 28 | int vol_shift; | ||
| 29 | int vol_nbits; | ||
| 30 | int update_reg; | ||
| 31 | int update_bit; | ||
| 32 | int enable_reg; | ||
| 33 | int enable_bit; | ||
| 34 | int slope_double; | ||
| 35 | }; | ||
| 36 | |||
| 37 | static inline int check_range(struct pm8607_regulator_info *info, | ||
| 38 | int min_uV, int max_uV) | ||
| 39 | { | ||
| 40 | if (max_uV < info->min_uV || min_uV > info->max_uV || min_uV > max_uV) | ||
| 41 | return -EINVAL; | ||
| 42 | |||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) | ||
| 47 | { | ||
| 48 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 49 | uint8_t chip_id = info->chip->chip_id; | ||
| 50 | int ret = -EINVAL; | ||
| 51 | |||
| 52 | switch (info->desc.id) { | ||
| 53 | case PM8607_ID_BUCK1: | ||
| 54 | ret = (index < 0x1d) ? (index * 25000 + 800000) : | ||
| 55 | ((index < 0x20) ? 1500000 : | ||
| 56 | ((index < 0x40) ? ((index - 0x20) * 25000) : | ||
| 57 | -EINVAL)); | ||
| 58 | break; | ||
| 59 | case PM8607_ID_BUCK3: | ||
| 60 | ret = (index < 0x3d) ? (index * 25000) : | ||
| 61 | ((index < 0x40) ? 1500000 : -EINVAL); | ||
| 62 | if (ret < 0) | ||
| 63 | break; | ||
| 64 | if (info->slope_double) | ||
| 65 | ret <<= 1; | ||
| 66 | break; | ||
| 67 | case PM8607_ID_LDO1: | ||
| 68 | ret = (index == 0) ? 1800000 : | ||
| 69 | ((index == 1) ? 1200000 : | ||
| 70 | ((index == 2) ? 2800000 : -EINVAL)); | ||
| 71 | break; | ||
| 72 | case PM8607_ID_LDO5: | ||
| 73 | ret = (index == 0) ? 2900000 : | ||
| 74 | ((index == 1) ? 3000000 : | ||
| 75 | ((index == 2) ? 3100000 : 3300000)); | ||
| 76 | break; | ||
| 77 | case PM8607_ID_LDO7: | ||
| 78 | case PM8607_ID_LDO8: | ||
| 79 | ret = (index < 3) ? (index * 50000 + 1800000) : | ||
| 80 | ((index < 8) ? (index * 50000 + 2550000) : | ||
| 81 | -EINVAL); | ||
| 82 | break; | ||
| 83 | case PM8607_ID_LDO12: | ||
| 84 | ret = (index < 2) ? (index * 100000 + 1800000) : | ||
| 85 | ((index < 7) ? (index * 100000 + 2500000) : | ||
| 86 | ((index == 7) ? 3300000 : 1200000)); | ||
| 87 | break; | ||
| 88 | case PM8607_ID_LDO2: | ||
| 89 | case PM8607_ID_LDO3: | ||
| 90 | case PM8607_ID_LDO9: | ||
| 91 | switch (chip_id) { | ||
| 92 | case PM8607_CHIP_A0: | ||
| 93 | case PM8607_CHIP_A1: | ||
| 94 | ret = (index < 3) ? (index * 50000 + 1800000) : | ||
| 95 | ((index < 8) ? (index * 50000 + 2550000) : | ||
| 96 | -EINVAL); | ||
| 97 | break; | ||
| 98 | case PM8607_CHIP_B0: | ||
| 99 | ret = (index < 3) ? (index * 50000 + 1800000) : | ||
| 100 | ((index < 7) ? (index * 50000 + 2550000) : | ||
| 101 | 3300000); | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | break; | ||
| 105 | case PM8607_ID_LDO4: | ||
| 106 | switch (chip_id) { | ||
| 107 | case PM8607_CHIP_A0: | ||
| 108 | case PM8607_CHIP_A1: | ||
| 109 | ret = (index < 3) ? (index * 50000 + 1800000) : | ||
| 110 | ((index < 8) ? (index * 50000 + 2550000) : | ||
| 111 | -EINVAL); | ||
| 112 | break; | ||
| 113 | case PM8607_CHIP_B0: | ||
| 114 | ret = (index < 3) ? (index * 50000 + 1800000) : | ||
| 115 | ((index < 6) ? (index * 50000 + 2550000) : | ||
| 116 | ((index == 6) ? 2900000 : 3300000)); | ||
| 117 | break; | ||
| 118 | } | ||
| 119 | break; | ||
| 120 | case PM8607_ID_LDO6: | ||
| 121 | switch (chip_id) { | ||
| 122 | case PM8607_CHIP_A0: | ||
| 123 | case PM8607_CHIP_A1: | ||
| 124 | ret = (index < 3) ? (index * 50000 + 1800000) : | ||
| 125 | ((index < 8) ? (index * 50000 + 2450000) : | ||
| 126 | -EINVAL); | ||
| 127 | break; | ||
| 128 | case PM8607_CHIP_B0: | ||
| 129 | ret = (index < 2) ? (index * 50000 + 1800000) : | ||
| 130 | ((index < 7) ? (index * 50000 + 2500000) : | ||
| 131 | 3300000); | ||
| 132 | break; | ||
| 133 | } | ||
| 134 | break; | ||
| 135 | case PM8607_ID_LDO10: | ||
| 136 | switch (chip_id) { | ||
| 137 | case PM8607_CHIP_A0: | ||
| 138 | case PM8607_CHIP_A1: | ||
| 139 | ret = (index < 3) ? (index * 50000 + 1800000) : | ||
| 140 | ((index < 8) ? (index * 50000 + 2550000) : | ||
| 141 | 1200000); | ||
| 142 | break; | ||
| 143 | case PM8607_CHIP_B0: | ||
| 144 | ret = (index < 3) ? (index * 50000 + 1800000) : | ||
| 145 | ((index < 7) ? (index * 50000 + 2550000) : | ||
| 146 | ((index == 7) ? 3300000 : 1200000)); | ||
| 147 | break; | ||
| 148 | } | ||
| 149 | break; | ||
| 150 | case PM8607_ID_LDO14: | ||
| 151 | switch (chip_id) { | ||
| 152 | case PM8607_CHIP_A0: | ||
| 153 | case PM8607_CHIP_A1: | ||
| 154 | ret = (index < 3) ? (index * 50000 + 1800000) : | ||
| 155 | ((index < 8) ? (index * 50000 + 2550000) : | ||
| 156 | -EINVAL); | ||
| 157 | break; | ||
| 158 | case PM8607_CHIP_B0: | ||
| 159 | ret = (index < 2) ? (index * 50000 + 1800000) : | ||
| 160 | ((index < 7) ? (index * 50000 + 2600000) : | ||
| 161 | 3300000); | ||
| 162 | break; | ||
| 163 | } | ||
| 164 | break; | ||
| 165 | } | ||
| 166 | return ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | ||
| 170 | { | ||
| 171 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 172 | uint8_t chip_id = info->chip->chip_id; | ||
| 173 | int val = -ENOENT; | ||
| 174 | int ret; | ||
| 175 | |||
| 176 | switch (info->desc.id) { | ||
| 177 | case PM8607_ID_BUCK1: | ||
| 178 | if (min_uV >= 800000) /* 800mV ~ 1500mV / 25mV */ | ||
| 179 | val = (min_uV - 775001) / 25000; | ||
| 180 | else { /* 25mV ~ 775mV / 25mV */ | ||
| 181 | val = (min_uV + 249999) / 25000; | ||
| 182 | val += 32; | ||
| 183 | } | ||
| 184 | break; | ||
| 185 | case PM8607_ID_BUCK3: | ||
| 186 | if (info->slope_double) | ||
| 187 | min_uV = min_uV >> 1; | ||
| 188 | val = (min_uV + 249999) / 25000; /* 0mV ~ 1500mV / 25mV */ | ||
| 189 | |||
| 190 | break; | ||
| 191 | case PM8607_ID_LDO1: | ||
| 192 | if (min_uV > 1800000) | ||
| 193 | val = 2; | ||
| 194 | else if (min_uV > 1200000) | ||
| 195 | val = 0; | ||
| 196 | else | ||
| 197 | val = 1; | ||
| 198 | break; | ||
| 199 | case PM8607_ID_LDO5: | ||
| 200 | if (min_uV > 3100000) | ||
| 201 | val = 3; | ||
| 202 | else /* 2900mV ~ 3100mV / 100mV */ | ||
| 203 | val = (min_uV - 2800001) / 100000; | ||
| 204 | break; | ||
| 205 | case PM8607_ID_LDO7: | ||
| 206 | case PM8607_ID_LDO8: | ||
| 207 | if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */ | ||
| 208 | if (min_uV <= 1800000) | ||
| 209 | val = 0; /* 1800mv */ | ||
| 210 | else if (min_uV <= 1900000) | ||
| 211 | val = (min_uV - 1750001) / 50000; | ||
| 212 | else | ||
| 213 | val = 3; /* 2700mV */ | ||
| 214 | } else { /* 2700mV ~ 2900mV / 50mV */ | ||
| 215 | if (min_uV <= 2900000) { | ||
| 216 | val = (min_uV - 2650001) / 50000; | ||
| 217 | val += 3; | ||
| 218 | } else | ||
| 219 | val = -EINVAL; | ||
| 220 | } | ||
| 221 | break; | ||
| 222 | case PM8607_ID_LDO10: | ||
| 223 | if (min_uV > 2850000) | ||
| 224 | val = 7; | ||
| 225 | else if (min_uV <= 1200000) | ||
| 226 | val = 8; | ||
| 227 | else if (min_uV < 2700000) /* 1800mV ~ 1900mV / 50mV */ | ||
| 228 | val = (min_uV - 1750001) / 50000; | ||
| 229 | else { /* 2700mV ~ 2850mV / 50mV */ | ||
| 230 | val = (min_uV - 2650001) / 50000; | ||
| 231 | val += 3; | ||
| 232 | } | ||
| 233 | break; | ||
| 234 | case PM8607_ID_LDO12: | ||
| 235 | if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 100mV */ | ||
| 236 | if (min_uV <= 1200000) | ||
| 237 | val = 8; /* 1200mV */ | ||
| 238 | else if (min_uV <= 1800000) | ||
| 239 | val = 0; /* 1800mV */ | ||
| 240 | else if (min_uV <= 1900000) | ||
| 241 | val = (min_uV - 1700001) / 100000; | ||
| 242 | else | ||
| 243 | val = 2; /* 2700mV */ | ||
| 244 | } else { /* 2700mV ~ 3100mV / 100mV */ | ||
| 245 | if (min_uV <= 3100000) { | ||
| 246 | val = (min_uV - 2600001) / 100000; | ||
| 247 | val += 2; | ||
| 248 | } else if (min_uV <= 3300000) | ||
| 249 | val = 7; | ||
| 250 | else | ||
| 251 | val = -EINVAL; | ||
| 252 | } | ||
| 253 | break; | ||
| 254 | case PM8607_ID_LDO2: | ||
| 255 | case PM8607_ID_LDO3: | ||
| 256 | case PM8607_ID_LDO9: | ||
| 257 | switch (chip_id) { | ||
| 258 | case PM8607_CHIP_A0: | ||
| 259 | case PM8607_CHIP_A1: | ||
| 260 | if (min_uV < 2700000) /* 1800mV ~ 1900mV / 50mV */ | ||
| 261 | if (min_uV <= 1800000) | ||
| 262 | val = 0; | ||
| 263 | else if (min_uV <= 1900000) | ||
| 264 | val = (min_uV - 1750001) / 50000; | ||
| 265 | else | ||
| 266 | val = 3; /* 2700mV */ | ||
| 267 | else { /* 2700mV ~ 2900mV / 50mV */ | ||
| 268 | if (min_uV <= 2900000) { | ||
| 269 | val = (min_uV - 2650001) / 50000; | ||
| 270 | val += 3; | ||
| 271 | } else | ||
| 272 | val = -EINVAL; | ||
| 273 | } | ||
| 274 | break; | ||
| 275 | case PM8607_CHIP_B0: | ||
| 276 | if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */ | ||
| 277 | if (min_uV <= 1800000) | ||
| 278 | val = 0; | ||
| 279 | else if (min_uV <= 1900000) | ||
| 280 | val = (min_uV - 1750001) / 50000; | ||
| 281 | else | ||
| 282 | val = 3; /* 2700mV */ | ||
| 283 | } else { /* 2700mV ~ 2850mV / 50mV */ | ||
| 284 | if (min_uV <= 2850000) { | ||
| 285 | val = (min_uV - 2650001) / 50000; | ||
| 286 | val += 3; | ||
| 287 | } else if (min_uV <= 3300000) | ||
| 288 | val = 7; | ||
| 289 | else | ||
| 290 | val = -EINVAL; | ||
| 291 | } | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | break; | ||
| 295 | case PM8607_ID_LDO4: | ||
| 296 | switch (chip_id) { | ||
| 297 | case PM8607_CHIP_A0: | ||
| 298 | case PM8607_CHIP_A1: | ||
| 299 | if (min_uV < 2700000) /* 1800mV ~ 1900mV / 50mV */ | ||
| 300 | if (min_uV <= 1800000) | ||
| 301 | val = 0; | ||
| 302 | else if (min_uV <= 1900000) | ||
| 303 | val = (min_uV - 1750001) / 50000; | ||
| 304 | else | ||
| 305 | val = 3; /* 2700mV */ | ||
| 306 | else { /* 2700mV ~ 2900mV / 50mV */ | ||
| 307 | if (min_uV <= 2900000) { | ||
| 308 | val = (min_uV - 2650001) / 50000; | ||
| 309 | val += 3; | ||
| 310 | } else | ||
| 311 | val = -EINVAL; | ||
| 312 | } | ||
| 313 | break; | ||
| 314 | case PM8607_CHIP_B0: | ||
| 315 | if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */ | ||
| 316 | if (min_uV <= 1800000) | ||
| 317 | val = 0; | ||
| 318 | else if (min_uV <= 1900000) | ||
| 319 | val = (min_uV - 1750001) / 50000; | ||
| 320 | else | ||
| 321 | val = 3; /* 2700mV */ | ||
| 322 | } else { /* 2700mV ~ 2800mV / 50mV */ | ||
| 323 | if (min_uV <= 2850000) { | ||
| 324 | val = (min_uV - 2650001) / 50000; | ||
| 325 | val += 3; | ||
| 326 | } else if (min_uV <= 2900000) | ||
| 327 | val = 6; | ||
| 328 | else if (min_uV <= 3300000) | ||
| 329 | val = 7; | ||
| 330 | else | ||
| 331 | val = -EINVAL; | ||
| 332 | } | ||
| 333 | break; | ||
| 334 | } | ||
| 335 | break; | ||
| 336 | case PM8607_ID_LDO6: | ||
| 337 | switch (chip_id) { | ||
| 338 | case PM8607_CHIP_A0: | ||
| 339 | case PM8607_CHIP_A1: | ||
| 340 | if (min_uV < 2600000) { /* 1800mV ~ 1900mV / 50mV */ | ||
| 341 | if (min_uV <= 1800000) | ||
| 342 | val = 0; | ||
| 343 | else if (min_uV <= 1900000) | ||
| 344 | val = (min_uV - 1750001) / 50000; | ||
| 345 | else | ||
| 346 | val = 3; /* 2600mV */ | ||
| 347 | } else { /* 2600mV ~ 2800mV / 50mV */ | ||
| 348 | if (min_uV <= 2800000) { | ||
| 349 | val = (min_uV - 2550001) / 50000; | ||
| 350 | val += 3; | ||
| 351 | } else | ||
| 352 | val = -EINVAL; | ||
| 353 | } | ||
| 354 | break; | ||
| 355 | case PM8607_CHIP_B0: | ||
| 356 | if (min_uV < 2600000) { /* 1800mV ~ 1850mV / 50mV */ | ||
| 357 | if (min_uV <= 1800000) | ||
| 358 | val = 0; | ||
| 359 | else if (min_uV <= 1850000) | ||
| 360 | val = (min_uV - 1750001) / 50000; | ||
| 361 | else | ||
| 362 | val = 2; /* 2600mV */ | ||
| 363 | } else { /* 2600mV ~ 2800mV / 50mV */ | ||
| 364 | if (min_uV <= 2800000) { | ||
| 365 | val = (min_uV - 2550001) / 50000; | ||
| 366 | val += 2; | ||
| 367 | } else if (min_uV <= 3300000) | ||
| 368 | val = 7; | ||
| 369 | else | ||
| 370 | val = -EINVAL; | ||
| 371 | } | ||
| 372 | break; | ||
| 373 | } | ||
| 374 | break; | ||
| 375 | case PM8607_ID_LDO14: | ||
| 376 | switch (chip_id) { | ||
| 377 | case PM8607_CHIP_A0: | ||
| 378 | case PM8607_CHIP_A1: | ||
| 379 | if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */ | ||
| 380 | if (min_uV <= 1800000) | ||
| 381 | val = 0; | ||
| 382 | else if (min_uV <= 1900000) | ||
| 383 | val = (min_uV - 1750001) / 50000; | ||
| 384 | else | ||
| 385 | val = 3; /* 2700mV */ | ||
| 386 | } else { /* 2700mV ~ 2900mV / 50mV */ | ||
| 387 | if (min_uV <= 2900000) { | ||
| 388 | val = (min_uV - 2650001) / 50000; | ||
| 389 | val += 3; | ||
| 390 | } else | ||
| 391 | val = -EINVAL; | ||
| 392 | } | ||
| 393 | break; | ||
| 394 | case PM8607_CHIP_B0: | ||
| 395 | if (min_uV < 2700000) { /* 1800mV ~ 1850mV / 50mV */ | ||
| 396 | if (min_uV <= 1800000) | ||
| 397 | val = 0; | ||
| 398 | else if (min_uV <= 1850000) | ||
| 399 | val = (min_uV - 1750001) / 50000; | ||
| 400 | else | ||
| 401 | val = 2; /* 2700mV */ | ||
| 402 | } else { /* 2700mV ~ 2900mV / 50mV */ | ||
| 403 | if (min_uV <= 2900000) { | ||
| 404 | val = (min_uV - 2650001) / 50000; | ||
| 405 | val += 2; | ||
| 406 | } else if (min_uV <= 3300000) | ||
| 407 | val = 7; | ||
| 408 | else | ||
| 409 | val = -EINVAL; | ||
| 410 | } | ||
| 411 | break; | ||
| 412 | } | ||
| 413 | break; | ||
| 414 | } | ||
| 415 | if (val >= 0) { | ||
| 416 | ret = pm8607_list_voltage(rdev, val); | ||
| 417 | if (ret > max_uV) { | ||
| 418 | pr_err("exceed voltage range (%d %d) uV", | ||
| 419 | min_uV, max_uV); | ||
| 420 | return -EINVAL; | ||
| 421 | } | ||
| 422 | } else | ||
| 423 | pr_err("invalid voltage range (%d %d) uV", min_uV, max_uV); | ||
| 424 | return val; | ||
| 425 | } | ||
| 426 | |||
| 427 | static int pm8607_set_voltage(struct regulator_dev *rdev, | ||
| 428 | int min_uV, int max_uV) | ||
| 429 | { | ||
| 430 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 431 | struct pm8607_chip *chip = info->chip; | ||
| 432 | uint8_t val, mask; | ||
| 433 | int ret; | ||
| 434 | |||
| 435 | if (check_range(info, min_uV, max_uV)) { | ||
| 436 | pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); | ||
| 437 | return -EINVAL; | ||
| 438 | } | ||
| 439 | |||
| 440 | ret = choose_voltage(rdev, min_uV, max_uV); | ||
| 441 | if (ret < 0) | ||
| 442 | return -EINVAL; | ||
| 443 | val = (uint8_t)(ret << info->vol_shift); | ||
| 444 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; | ||
| 445 | |||
| 446 | ret = pm8607_set_bits(chip, info->vol_reg, mask, val); | ||
| 447 | if (ret) | ||
| 448 | return ret; | ||
| 449 | switch (info->desc.id) { | ||
| 450 | case PM8607_ID_BUCK1: | ||
| 451 | case PM8607_ID_BUCK3: | ||
| 452 | ret = pm8607_set_bits(chip, info->update_reg, | ||
| 453 | 1 << info->update_bit, | ||
| 454 | 1 << info->update_bit); | ||
| 455 | break; | ||
| 456 | } | ||
| 457 | return ret; | ||
| 458 | } | ||
| 459 | |||
| 460 | static int pm8607_get_voltage(struct regulator_dev *rdev) | ||
| 461 | { | ||
| 462 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 463 | struct pm8607_chip *chip = info->chip; | ||
| 464 | uint8_t val, mask; | ||
| 465 | int ret; | ||
| 466 | |||
| 467 | ret = pm8607_reg_read(chip, info->vol_reg); | ||
| 468 | if (ret < 0) | ||
| 469 | return ret; | ||
| 470 | |||
| 471 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; | ||
| 472 | val = ((unsigned char)ret & mask) >> info->vol_shift; | ||
| 473 | |||
| 474 | return pm8607_list_voltage(rdev, val); | ||
| 475 | } | ||
| 476 | |||
| 477 | static int pm8607_enable(struct regulator_dev *rdev) | ||
| 478 | { | ||
| 479 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 480 | struct pm8607_chip *chip = info->chip; | ||
| 481 | |||
| 482 | return pm8607_set_bits(chip, info->enable_reg, | ||
| 483 | 1 << info->enable_bit, | ||
| 484 | 1 << info->enable_bit); | ||
| 485 | } | ||
| 486 | |||
| 487 | static int pm8607_disable(struct regulator_dev *rdev) | ||
| 488 | { | ||
| 489 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 490 | struct pm8607_chip *chip = info->chip; | ||
| 491 | |||
| 492 | return pm8607_set_bits(chip, info->enable_reg, | ||
| 493 | 1 << info->enable_bit, 0); | ||
| 494 | } | ||
| 495 | |||
| 496 | static int pm8607_is_enabled(struct regulator_dev *rdev) | ||
| 497 | { | ||
| 498 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 499 | struct pm8607_chip *chip = info->chip; | ||
| 500 | int ret; | ||
| 501 | |||
| 502 | ret = pm8607_reg_read(chip, info->enable_reg); | ||
| 503 | if (ret < 0) | ||
| 504 | return ret; | ||
| 505 | |||
| 506 | return !!((unsigned char)ret & (1 << info->enable_bit)); | ||
| 507 | } | ||
| 508 | |||
| 509 | static struct regulator_ops pm8607_regulator_ops = { | ||
| 510 | .set_voltage = pm8607_set_voltage, | ||
| 511 | .get_voltage = pm8607_get_voltage, | ||
| 512 | .enable = pm8607_enable, | ||
| 513 | .disable = pm8607_disable, | ||
| 514 | .is_enabled = pm8607_is_enabled, | ||
| 515 | }; | ||
| 516 | |||
| 517 | #define PM8607_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \ | ||
| 518 | { \ | ||
| 519 | .desc = { \ | ||
| 520 | .name = "BUCK" #_id, \ | ||
| 521 | .ops = &pm8607_regulator_ops, \ | ||
| 522 | .type = REGULATOR_VOLTAGE, \ | ||
| 523 | .id = PM8607_ID_BUCK##_id, \ | ||
| 524 | .owner = THIS_MODULE, \ | ||
| 525 | }, \ | ||
| 526 | .min_uV = (min) * 1000, \ | ||
| 527 | .max_uV = (max) * 1000, \ | ||
| 528 | .step_uV = (step) * 1000, \ | ||
| 529 | .vol_reg = PM8607_##vreg, \ | ||
| 530 | .vol_shift = (0), \ | ||
| 531 | .vol_nbits = (nbits), \ | ||
| 532 | .update_reg = PM8607_##ureg, \ | ||
| 533 | .update_bit = (ubit), \ | ||
| 534 | .enable_reg = PM8607_##ereg, \ | ||
| 535 | .enable_bit = (ebit), \ | ||
| 536 | .slope_double = (0), \ | ||
| 537 | } | ||
| 538 | |||
| 539 | #define PM8607_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit) \ | ||
| 540 | { \ | ||
| 541 | .desc = { \ | ||
| 542 | .name = "LDO" #_id, \ | ||
| 543 | .ops = &pm8607_regulator_ops, \ | ||
| 544 | .type = REGULATOR_VOLTAGE, \ | ||
| 545 | .id = PM8607_ID_LDO##_id, \ | ||
| 546 | .owner = THIS_MODULE, \ | ||
| 547 | }, \ | ||
| 548 | .min_uV = (min) * 1000, \ | ||
| 549 | .max_uV = (max) * 1000, \ | ||
| 550 | .step_uV = (step) * 1000, \ | ||
| 551 | .vol_reg = PM8607_##vreg, \ | ||
| 552 | .vol_shift = (shift), \ | ||
| 553 | .vol_nbits = (nbits), \ | ||
| 554 | .enable_reg = PM8607_##ereg, \ | ||
| 555 | .enable_bit = (ebit), \ | ||
| 556 | .slope_double = (0), \ | ||
| 557 | } | ||
| 558 | |||
| 559 | static struct pm8607_regulator_info pm8607_regulator_info[] = { | ||
| 560 | PM8607_DVC(1, 0, 1500, 25, BUCK1, 6, GO, 0, SUPPLIES_EN11, 0), | ||
| 561 | PM8607_DVC(3, 0, 1500, 25, BUCK3, 6, GO, 2, SUPPLIES_EN11, 2), | ||
| 562 | |||
| 563 | PM8607_LDO(1 , 1200, 2800, 0, LDO1 , 0, 2, SUPPLIES_EN11, 3), | ||
| 564 | PM8607_LDO(2 , 1800, 3300, 0, LDO2 , 0, 3, SUPPLIES_EN11, 4), | ||
| 565 | PM8607_LDO(3 , 1800, 3300, 0, LDO3 , 0, 3, SUPPLIES_EN11, 5), | ||
| 566 | PM8607_LDO(4 , 1800, 3300, 0, LDO4 , 0, 3, SUPPLIES_EN11, 6), | ||
| 567 | PM8607_LDO(5 , 2900, 3300, 0, LDO5 , 0, 2, SUPPLIES_EN11, 7), | ||
| 568 | PM8607_LDO(6 , 1800, 3300, 0, LDO6 , 0, 3, SUPPLIES_EN12, 0), | ||
| 569 | PM8607_LDO(7 , 1800, 2900, 0, LDO7 , 0, 3, SUPPLIES_EN12, 1), | ||
| 570 | PM8607_LDO(8 , 1800, 2900, 0, LDO8 , 0, 3, SUPPLIES_EN12, 2), | ||
| 571 | PM8607_LDO(9 , 1800, 3300, 0, LDO9 , 0, 3, SUPPLIES_EN12, 3), | ||
| 572 | PM8607_LDO(10, 1200, 3300, 0, LDO10, 0, 4, SUPPLIES_EN11, 4), | ||
| 573 | PM8607_LDO(12, 1200, 3300, 0, LDO12, 0, 4, SUPPLIES_EN11, 5), | ||
| 574 | PM8607_LDO(14, 1800, 3300, 0, LDO14, 0, 3, SUPPLIES_EN11, 6), | ||
| 575 | }; | ||
| 576 | |||
| 577 | static inline struct pm8607_regulator_info *find_regulator_info(int id) | ||
| 578 | { | ||
| 579 | struct pm8607_regulator_info *info; | ||
| 580 | int i; | ||
| 581 | |||
| 582 | for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) { | ||
| 583 | info = &pm8607_regulator_info[i]; | ||
| 584 | if (info->desc.id == id) | ||
| 585 | return info; | ||
| 586 | } | ||
| 587 | return NULL; | ||
| 588 | } | ||
| 589 | |||
| 590 | static int __devinit pm8607_regulator_probe(struct platform_device *pdev) | ||
| 591 | { | ||
| 592 | struct pm8607_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
| 593 | struct pm8607_platform_data *pdata = chip->dev->platform_data; | ||
| 594 | struct pm8607_regulator_info *info = NULL; | ||
| 595 | |||
| 596 | info = find_regulator_info(pdev->id); | ||
| 597 | if (info == NULL) { | ||
| 598 | dev_err(&pdev->dev, "invalid regulator ID specified\n"); | ||
| 599 | return -EINVAL; | ||
| 600 | } | ||
| 601 | |||
| 602 | info->chip = chip; | ||
| 603 | |||
| 604 | info->regulator = regulator_register(&info->desc, &pdev->dev, | ||
| 605 | pdata->regulator[pdev->id], info); | ||
| 606 | if (IS_ERR(info->regulator)) { | ||
| 607 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
| 608 | info->desc.name); | ||
| 609 | return PTR_ERR(info->regulator); | ||
| 610 | } | ||
| 611 | |||
| 612 | /* check DVC ramp slope double */ | ||
| 613 | if (info->desc.id == PM8607_ID_BUCK3) | ||
| 614 | if (info->chip->buck3_double) | ||
| 615 | info->slope_double = 1; | ||
| 616 | |||
| 617 | platform_set_drvdata(pdev, info); | ||
| 618 | return 0; | ||
| 619 | } | ||
| 620 | |||
| 621 | static int __devexit pm8607_regulator_remove(struct platform_device *pdev) | ||
| 622 | { | ||
| 623 | struct pm8607_regulator_info *info = platform_get_drvdata(pdev); | ||
| 624 | |||
| 625 | regulator_unregister(info->regulator); | ||
| 626 | return 0; | ||
| 627 | } | ||
| 628 | |||
| 629 | #define PM8607_REGULATOR_DRIVER(_name) \ | ||
| 630 | { \ | ||
| 631 | .driver = { \ | ||
| 632 | .name = "88pm8607-" #_name, \ | ||
| 633 | .owner = THIS_MODULE, \ | ||
| 634 | }, \ | ||
| 635 | .probe = pm8607_regulator_probe, \ | ||
| 636 | .remove = __devexit_p(pm8607_regulator_remove), \ | ||
| 637 | } | ||
| 638 | |||
| 639 | static struct platform_driver pm8607_regulator_driver[] = { | ||
| 640 | PM8607_REGULATOR_DRIVER(buck1), | ||
| 641 | PM8607_REGULATOR_DRIVER(buck2), | ||
| 642 | PM8607_REGULATOR_DRIVER(buck3), | ||
| 643 | PM8607_REGULATOR_DRIVER(ldo1), | ||
| 644 | PM8607_REGULATOR_DRIVER(ldo2), | ||
| 645 | PM8607_REGULATOR_DRIVER(ldo3), | ||
| 646 | PM8607_REGULATOR_DRIVER(ldo4), | ||
| 647 | PM8607_REGULATOR_DRIVER(ldo5), | ||
| 648 | PM8607_REGULATOR_DRIVER(ldo6), | ||
| 649 | PM8607_REGULATOR_DRIVER(ldo7), | ||
| 650 | PM8607_REGULATOR_DRIVER(ldo8), | ||
| 651 | PM8607_REGULATOR_DRIVER(ldo9), | ||
| 652 | PM8607_REGULATOR_DRIVER(ldo10), | ||
| 653 | PM8607_REGULATOR_DRIVER(ldo12), | ||
| 654 | PM8607_REGULATOR_DRIVER(ldo14), | ||
| 655 | }; | ||
| 656 | |||
| 657 | static int __init pm8607_regulator_init(void) | ||
| 658 | { | ||
| 659 | int i, count, ret; | ||
| 660 | |||
| 661 | count = ARRAY_SIZE(pm8607_regulator_driver); | ||
| 662 | for (i = 0; i < count; i++) { | ||
| 663 | ret = platform_driver_register(&pm8607_regulator_driver[i]); | ||
| 664 | if (ret != 0) | ||
| 665 | pr_err("Failed to register regulator driver: %d\n", | ||
| 666 | ret); | ||
| 667 | } | ||
| 668 | return 0; | ||
| 669 | } | ||
| 670 | subsys_initcall(pm8607_regulator_init); | ||
| 671 | |||
| 672 | static void __exit pm8607_regulator_exit(void) | ||
| 673 | { | ||
| 674 | int i, count; | ||
| 675 | |||
| 676 | count = ARRAY_SIZE(pm8607_regulator_driver); | ||
| 677 | for (i = 0; i < count; i++) | ||
| 678 | platform_driver_unregister(&pm8607_regulator_driver[i]); | ||
| 679 | } | ||
| 680 | module_exit(pm8607_regulator_exit); | ||
| 681 | |||
| 682 | MODULE_LICENSE("GPL"); | ||
| 683 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
| 684 | MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC"); | ||
| 685 | MODULE_ALIAS("platform:88pm8607-regulator"); | ||
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 7cfdd65bebb4..262f62eec837 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
| @@ -69,6 +69,13 @@ config REGULATOR_MAX1586 | |||
| 69 | regulator via I2C bus. The provided regulator is suitable | 69 | regulator via I2C bus. The provided regulator is suitable |
| 70 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. | 70 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. |
| 71 | 71 | ||
| 72 | config REGULATOR_MAX8660 | ||
| 73 | tristate "Maxim 8660/8661 voltage regulator" | ||
| 74 | depends on I2C | ||
| 75 | help | ||
| 76 | This driver controls a Maxim 8660/8661 voltage output | ||
| 77 | regulator via I2C bus. | ||
| 78 | |||
| 72 | config REGULATOR_TWL4030 | 79 | config REGULATOR_TWL4030 |
| 73 | bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" | 80 | bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" |
| 74 | depends on TWL4030_CORE | 81 | depends on TWL4030_CORE |
| @@ -157,5 +164,11 @@ config REGULATOR_TPS6507X | |||
| 157 | three step-down converters and two general-purpose LDO voltage regulators. | 164 | three step-down converters and two general-purpose LDO voltage regulators. |
| 158 | It supports TI's software based Class-2 SmartReflex implementation. | 165 | It supports TI's software based Class-2 SmartReflex implementation. |
| 159 | 166 | ||
| 167 | config REGULATOR_88PM8607 | ||
| 168 | bool "Marvell 88PM8607 Power regulators" | ||
| 169 | depends on MFD_88PM8607=y | ||
| 170 | help | ||
| 171 | This driver supports 88PM8607 voltage regulator chips. | ||
| 172 | |||
| 160 | endif | 173 | endif |
| 161 | 174 | ||
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 9ae3cc44e668..b3c806c79415 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
| @@ -12,6 +12,7 @@ obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o | |||
| 12 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o | 12 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o |
| 13 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o | 13 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o |
| 14 | obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o | 14 | obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o |
| 15 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o | ||
| 15 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o | 16 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o |
| 16 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o | 17 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o |
| 17 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o | 18 | obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o |
| @@ -20,10 +21,11 @@ obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o | |||
| 20 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o | 21 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o |
| 21 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o | 22 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o |
| 22 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o | 23 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o |
| 23 | obj-$(CONFIG_REGULATOR_MC13783) += mc13783.o | 24 | obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o |
| 24 | obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o | 25 | obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o |
| 25 | 26 | ||
| 26 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o | 27 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o |
| 27 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o | 28 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o |
| 29 | obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o | ||
| 28 | 30 | ||
| 29 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG | 31 | ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG |
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 49aeee823a25..b349db4504b7 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c | |||
| @@ -81,7 +81,7 @@ static const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = { | |||
| 81 | #define LDO_C_VOLTAGE 2650000 | 81 | #define LDO_C_VOLTAGE 2650000 |
| 82 | #define LDO_D_VOLTAGE 2650000 | 82 | #define LDO_D_VOLTAGE 2650000 |
| 83 | 83 | ||
| 84 | static const int const ldo_e_buck_typ_voltages[] = { | 84 | static const int ldo_e_buck_typ_voltages[] = { |
| 85 | 1800000, | 85 | 1800000, |
| 86 | 1400000, | 86 | 1400000, |
| 87 | 1300000, | 87 | 1300000, |
| @@ -91,7 +91,7 @@ static const int const ldo_e_buck_typ_voltages[] = { | |||
| 91 | 900000, | 91 | 900000, |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | static const int const ldo_f_typ_voltages[] = { | 94 | static const int ldo_f_typ_voltages[] = { |
| 95 | 1800000, | 95 | 1800000, |
| 96 | 1400000, | 96 | 1400000, |
| 97 | 1300000, | 97 | 1300000, |
| @@ -102,21 +102,21 @@ static const int const ldo_f_typ_voltages[] = { | |||
| 102 | 2650000, | 102 | 2650000, |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | static const int const ldo_g_typ_voltages[] = { | 105 | static const int ldo_g_typ_voltages[] = { |
| 106 | 2850000, | 106 | 2850000, |
| 107 | 2750000, | 107 | 2750000, |
| 108 | 1800000, | 108 | 1800000, |
| 109 | 1500000, | 109 | 1500000, |
| 110 | }; | 110 | }; |
| 111 | 111 | ||
| 112 | static const int const ldo_h_typ_voltages[] = { | 112 | static const int ldo_h_typ_voltages[] = { |
| 113 | 2750000, | 113 | 2750000, |
| 114 | 1800000, | 114 | 1800000, |
| 115 | 1500000, | 115 | 1500000, |
| 116 | 1200000, | 116 | 1200000, |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | static const int const ldo_k_typ_voltages[] = { | 119 | static const int ldo_k_typ_voltages[] = { |
| 120 | 2750000, | 120 | 2750000, |
| 121 | 1800000, | 121 | 1800000, |
| 122 | }; | 122 | }; |
| @@ -241,24 +241,12 @@ static int ab3100_disable_regulator(struct regulator_dev *reg) | |||
| 241 | * LDO D is a special regulator. When it is disabled, the entire | 241 | * LDO D is a special regulator. When it is disabled, the entire |
| 242 | * system is shut down. So this is handled specially. | 242 | * system is shut down. So this is handled specially. |
| 243 | */ | 243 | */ |
| 244 | pr_info("Called ab3100_disable_regulator\n"); | ||
| 244 | if (abreg->regreg == AB3100_LDO_D) { | 245 | if (abreg->regreg == AB3100_LDO_D) { |
| 245 | int i; | ||
| 246 | |||
| 247 | dev_info(®->dev, "disabling LDO D - shut down system\n"); | 246 | dev_info(®->dev, "disabling LDO D - shut down system\n"); |
| 248 | /* | ||
| 249 | * Set regulators to default values, ignore any errors, | ||
| 250 | * we're going DOWN | ||
| 251 | */ | ||
| 252 | for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) { | ||
| 253 | (void) ab3100_set_register_interruptible(abreg->ab3100, | ||
| 254 | ab3100_reg_init_order[i], | ||
| 255 | abreg->plfdata->reg_initvals[i]); | ||
| 256 | } | ||
| 257 | |||
| 258 | /* Setting LDO D to 0x00 cuts the power to the SoC */ | 247 | /* Setting LDO D to 0x00 cuts the power to the SoC */ |
| 259 | return ab3100_set_register_interruptible(abreg->ab3100, | 248 | return ab3100_set_register_interruptible(abreg->ab3100, |
| 260 | AB3100_LDO_D, 0x00U); | 249 | AB3100_LDO_D, 0x00U); |
| 261 | |||
| 262 | } | 250 | } |
| 263 | 251 | ||
| 264 | /* | 252 | /* |
| @@ -607,13 +595,6 @@ static int __init ab3100_regulators_probe(struct platform_device *pdev) | |||
| 607 | } | 595 | } |
| 608 | } | 596 | } |
| 609 | 597 | ||
| 610 | if (err) { | ||
| 611 | dev_err(&pdev->dev, | ||
| 612 | "LDO D regulator initialization failed with error %d\n", | ||
| 613 | err); | ||
| 614 | return err; | ||
| 615 | } | ||
| 616 | |||
| 617 | /* Register the regulators */ | 598 | /* Register the regulators */ |
| 618 | for (i = 0; i < AB3100_NUM_REGULATORS; i++) { | 599 | for (i = 0; i < AB3100_NUM_REGULATORS; i++) { |
| 619 | struct ab3100_regulator *reg = &ab3100_regulators[i]; | 600 | struct ab3100_regulator *reg = &ab3100_regulators[i]; |
| @@ -688,7 +669,7 @@ static __init int ab3100_regulators_init(void) | |||
| 688 | 669 | ||
| 689 | static __exit void ab3100_regulators_exit(void) | 670 | static __exit void ab3100_regulators_exit(void) |
| 690 | { | 671 | { |
| 691 | platform_driver_register(&ab3100_regulators_driver); | 672 | platform_driver_unregister(&ab3100_regulators_driver); |
| 692 | } | 673 | } |
| 693 | 674 | ||
| 694 | subsys_initcall(ab3100_regulators_init); | 675 | subsys_initcall(ab3100_regulators_init); |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index efe568deda12..686ef270ecf7 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
| @@ -66,6 +66,16 @@ static unsigned int _regulator_get_mode(struct regulator_dev *rdev); | |||
| 66 | static void _notifier_call_chain(struct regulator_dev *rdev, | 66 | static void _notifier_call_chain(struct regulator_dev *rdev, |
| 67 | unsigned long event, void *data); | 67 | unsigned long event, void *data); |
| 68 | 68 | ||
| 69 | static const char *rdev_get_name(struct regulator_dev *rdev) | ||
| 70 | { | ||
| 71 | if (rdev->constraints && rdev->constraints->name) | ||
| 72 | return rdev->constraints->name; | ||
| 73 | else if (rdev->desc->name) | ||
| 74 | return rdev->desc->name; | ||
| 75 | else | ||
| 76 | return ""; | ||
| 77 | } | ||
| 78 | |||
| 69 | /* gets the regulator for a given consumer device */ | 79 | /* gets the regulator for a given consumer device */ |
| 70 | static struct regulator *get_device_regulator(struct device *dev) | 80 | static struct regulator *get_device_regulator(struct device *dev) |
| 71 | { | 81 | { |
| @@ -96,12 +106,12 @@ static int regulator_check_voltage(struct regulator_dev *rdev, | |||
| 96 | 106 | ||
| 97 | if (!rdev->constraints) { | 107 | if (!rdev->constraints) { |
| 98 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, | 108 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, |
| 99 | rdev->desc->name); | 109 | rdev_get_name(rdev)); |
| 100 | return -ENODEV; | 110 | return -ENODEV; |
| 101 | } | 111 | } |
| 102 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { | 112 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { |
| 103 | printk(KERN_ERR "%s: operation not allowed for %s\n", | 113 | printk(KERN_ERR "%s: operation not allowed for %s\n", |
| 104 | __func__, rdev->desc->name); | 114 | __func__, rdev_get_name(rdev)); |
| 105 | return -EPERM; | 115 | return -EPERM; |
| 106 | } | 116 | } |
| 107 | 117 | ||
| @@ -124,12 +134,12 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, | |||
| 124 | 134 | ||
| 125 | if (!rdev->constraints) { | 135 | if (!rdev->constraints) { |
| 126 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, | 136 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, |
| 127 | rdev->desc->name); | 137 | rdev_get_name(rdev)); |
| 128 | return -ENODEV; | 138 | return -ENODEV; |
| 129 | } | 139 | } |
| 130 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { | 140 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { |
| 131 | printk(KERN_ERR "%s: operation not allowed for %s\n", | 141 | printk(KERN_ERR "%s: operation not allowed for %s\n", |
| 132 | __func__, rdev->desc->name); | 142 | __func__, rdev_get_name(rdev)); |
| 133 | return -EPERM; | 143 | return -EPERM; |
| 134 | } | 144 | } |
| 135 | 145 | ||
| @@ -159,17 +169,17 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode) | |||
| 159 | 169 | ||
| 160 | if (!rdev->constraints) { | 170 | if (!rdev->constraints) { |
| 161 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, | 171 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, |
| 162 | rdev->desc->name); | 172 | rdev_get_name(rdev)); |
| 163 | return -ENODEV; | 173 | return -ENODEV; |
| 164 | } | 174 | } |
| 165 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { | 175 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { |
| 166 | printk(KERN_ERR "%s: operation not allowed for %s\n", | 176 | printk(KERN_ERR "%s: operation not allowed for %s\n", |
| 167 | __func__, rdev->desc->name); | 177 | __func__, rdev_get_name(rdev)); |
| 168 | return -EPERM; | 178 | return -EPERM; |
| 169 | } | 179 | } |
| 170 | if (!(rdev->constraints->valid_modes_mask & mode)) { | 180 | if (!(rdev->constraints->valid_modes_mask & mode)) { |
| 171 | printk(KERN_ERR "%s: invalid mode %x for %s\n", | 181 | printk(KERN_ERR "%s: invalid mode %x for %s\n", |
| 172 | __func__, mode, rdev->desc->name); | 182 | __func__, mode, rdev_get_name(rdev)); |
| 173 | return -EINVAL; | 183 | return -EINVAL; |
| 174 | } | 184 | } |
| 175 | return 0; | 185 | return 0; |
| @@ -180,12 +190,12 @@ static int regulator_check_drms(struct regulator_dev *rdev) | |||
| 180 | { | 190 | { |
| 181 | if (!rdev->constraints) { | 191 | if (!rdev->constraints) { |
| 182 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, | 192 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, |
| 183 | rdev->desc->name); | 193 | rdev_get_name(rdev)); |
| 184 | return -ENODEV; | 194 | return -ENODEV; |
| 185 | } | 195 | } |
| 186 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { | 196 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { |
| 187 | printk(KERN_ERR "%s: operation not allowed for %s\n", | 197 | printk(KERN_ERR "%s: operation not allowed for %s\n", |
| 188 | __func__, rdev->desc->name); | 198 | __func__, rdev_get_name(rdev)); |
| 189 | return -EPERM; | 199 | return -EPERM; |
| 190 | } | 200 | } |
| 191 | return 0; | 201 | return 0; |
| @@ -230,16 +240,8 @@ static ssize_t regulator_name_show(struct device *dev, | |||
| 230 | struct device_attribute *attr, char *buf) | 240 | struct device_attribute *attr, char *buf) |
| 231 | { | 241 | { |
| 232 | struct regulator_dev *rdev = dev_get_drvdata(dev); | 242 | struct regulator_dev *rdev = dev_get_drvdata(dev); |
| 233 | const char *name; | ||
| 234 | 243 | ||
| 235 | if (rdev->constraints && rdev->constraints->name) | 244 | return sprintf(buf, "%s\n", rdev_get_name(rdev)); |
| 236 | name = rdev->constraints->name; | ||
| 237 | else if (rdev->desc->name) | ||
| 238 | name = rdev->desc->name; | ||
| 239 | else | ||
| 240 | name = ""; | ||
| 241 | |||
| 242 | return sprintf(buf, "%s\n", name); | ||
| 243 | } | 245 | } |
| 244 | 246 | ||
| 245 | static ssize_t regulator_print_opmode(char *buf, int mode) | 247 | static ssize_t regulator_print_opmode(char *buf, int mode) |
| @@ -388,7 +390,7 @@ static ssize_t regulator_total_uA_show(struct device *dev, | |||
| 388 | 390 | ||
| 389 | mutex_lock(&rdev->mutex); | 391 | mutex_lock(&rdev->mutex); |
| 390 | list_for_each_entry(regulator, &rdev->consumer_list, list) | 392 | list_for_each_entry(regulator, &rdev->consumer_list, list) |
| 391 | uA += regulator->uA_load; | 393 | uA += regulator->uA_load; |
| 392 | mutex_unlock(&rdev->mutex); | 394 | mutex_unlock(&rdev->mutex); |
| 393 | return sprintf(buf, "%d\n", uA); | 395 | return sprintf(buf, "%d\n", uA); |
| 394 | } | 396 | } |
| @@ -563,7 +565,7 @@ static void drms_uA_update(struct regulator_dev *rdev) | |||
| 563 | 565 | ||
| 564 | /* calc total requested load */ | 566 | /* calc total requested load */ |
| 565 | list_for_each_entry(sibling, &rdev->consumer_list, list) | 567 | list_for_each_entry(sibling, &rdev->consumer_list, list) |
| 566 | current_uA += sibling->uA_load; | 568 | current_uA += sibling->uA_load; |
| 567 | 569 | ||
| 568 | /* now get the optimum mode for our new total regulator load */ | 570 | /* now get the optimum mode for our new total regulator load */ |
| 569 | mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, | 571 | mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, |
| @@ -579,10 +581,29 @@ static int suspend_set_state(struct regulator_dev *rdev, | |||
| 579 | struct regulator_state *rstate) | 581 | struct regulator_state *rstate) |
| 580 | { | 582 | { |
| 581 | int ret = 0; | 583 | int ret = 0; |
| 584 | bool can_set_state; | ||
| 582 | 585 | ||
| 583 | /* enable & disable are mandatory for suspend control */ | 586 | can_set_state = rdev->desc->ops->set_suspend_enable && |
| 584 | if (!rdev->desc->ops->set_suspend_enable || | 587 | rdev->desc->ops->set_suspend_disable; |
| 585 | !rdev->desc->ops->set_suspend_disable) { | 588 | |
| 589 | /* If we have no suspend mode configration don't set anything; | ||
| 590 | * only warn if the driver actually makes the suspend mode | ||
| 591 | * configurable. | ||
| 592 | */ | ||
| 593 | if (!rstate->enabled && !rstate->disabled) { | ||
| 594 | if (can_set_state) | ||
| 595 | printk(KERN_WARNING "%s: No configuration for %s\n", | ||
| 596 | __func__, rdev_get_name(rdev)); | ||
| 597 | return 0; | ||
| 598 | } | ||
| 599 | |||
| 600 | if (rstate->enabled && rstate->disabled) { | ||
| 601 | printk(KERN_ERR "%s: invalid configuration for %s\n", | ||
| 602 | __func__, rdev_get_name(rdev)); | ||
| 603 | return -EINVAL; | ||
| 604 | } | ||
| 605 | |||
| 606 | if (!can_set_state) { | ||
| 586 | printk(KERN_ERR "%s: no way to set suspend state\n", | 607 | printk(KERN_ERR "%s: no way to set suspend state\n", |
| 587 | __func__); | 608 | __func__); |
| 588 | return -EINVAL; | 609 | return -EINVAL; |
| @@ -641,25 +662,43 @@ static void print_constraints(struct regulator_dev *rdev) | |||
| 641 | { | 662 | { |
| 642 | struct regulation_constraints *constraints = rdev->constraints; | 663 | struct regulation_constraints *constraints = rdev->constraints; |
| 643 | char buf[80]; | 664 | char buf[80]; |
| 644 | int count; | 665 | int count = 0; |
| 666 | int ret; | ||
| 645 | 667 | ||
| 646 | if (rdev->desc->type == REGULATOR_VOLTAGE) { | 668 | if (constraints->min_uV && constraints->max_uV) { |
| 647 | if (constraints->min_uV == constraints->max_uV) | 669 | if (constraints->min_uV == constraints->max_uV) |
| 648 | count = sprintf(buf, "%d mV ", | 670 | count += sprintf(buf + count, "%d mV ", |
| 649 | constraints->min_uV / 1000); | 671 | constraints->min_uV / 1000); |
| 650 | else | 672 | else |
| 651 | count = sprintf(buf, "%d <--> %d mV ", | 673 | count += sprintf(buf + count, "%d <--> %d mV ", |
| 652 | constraints->min_uV / 1000, | 674 | constraints->min_uV / 1000, |
| 653 | constraints->max_uV / 1000); | 675 | constraints->max_uV / 1000); |
| 654 | } else { | 676 | } |
| 677 | |||
| 678 | if (!constraints->min_uV || | ||
| 679 | constraints->min_uV != constraints->max_uV) { | ||
| 680 | ret = _regulator_get_voltage(rdev); | ||
| 681 | if (ret > 0) | ||
| 682 | count += sprintf(buf + count, "at %d mV ", ret / 1000); | ||
| 683 | } | ||
| 684 | |||
| 685 | if (constraints->min_uA && constraints->max_uA) { | ||
| 655 | if (constraints->min_uA == constraints->max_uA) | 686 | if (constraints->min_uA == constraints->max_uA) |
| 656 | count = sprintf(buf, "%d mA ", | 687 | count += sprintf(buf + count, "%d mA ", |
| 657 | constraints->min_uA / 1000); | 688 | constraints->min_uA / 1000); |
| 658 | else | 689 | else |
| 659 | count = sprintf(buf, "%d <--> %d mA ", | 690 | count += sprintf(buf + count, "%d <--> %d mA ", |
| 660 | constraints->min_uA / 1000, | 691 | constraints->min_uA / 1000, |
| 661 | constraints->max_uA / 1000); | 692 | constraints->max_uA / 1000); |
| 662 | } | 693 | } |
| 694 | |||
| 695 | if (!constraints->min_uA || | ||
| 696 | constraints->min_uA != constraints->max_uA) { | ||
| 697 | ret = _regulator_get_current_limit(rdev); | ||
| 698 | if (ret > 0) | ||
| 699 | count += sprintf(buf + count, "at %d uA ", ret / 1000); | ||
| 700 | } | ||
| 701 | |||
| 663 | if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) | 702 | if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) |
| 664 | count += sprintf(buf + count, "fast "); | 703 | count += sprintf(buf + count, "fast "); |
| 665 | if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) | 704 | if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) |
| @@ -669,33 +708,30 @@ static void print_constraints(struct regulator_dev *rdev) | |||
| 669 | if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) | 708 | if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) |
| 670 | count += sprintf(buf + count, "standby"); | 709 | count += sprintf(buf + count, "standby"); |
| 671 | 710 | ||
| 672 | printk(KERN_INFO "regulator: %s: %s\n", rdev->desc->name, buf); | 711 | printk(KERN_INFO "regulator: %s: %s\n", rdev_get_name(rdev), buf); |
| 673 | } | 712 | } |
| 674 | 713 | ||
| 675 | /** | 714 | static int machine_constraints_voltage(struct regulator_dev *rdev, |
| 676 | * set_machine_constraints - sets regulator constraints | ||
| 677 | * @rdev: regulator source | ||
| 678 | * @constraints: constraints to apply | ||
| 679 | * | ||
| 680 | * Allows platform initialisation code to define and constrain | ||
| 681 | * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: | ||
| 682 | * Constraints *must* be set by platform code in order for some | ||
| 683 | * regulator operations to proceed i.e. set_voltage, set_current_limit, | ||
| 684 | * set_mode. | ||
| 685 | */ | ||
| 686 | static int set_machine_constraints(struct regulator_dev *rdev, | ||
| 687 | struct regulation_constraints *constraints) | 715 | struct regulation_constraints *constraints) |
| 688 | { | 716 | { |
| 689 | int ret = 0; | ||
| 690 | const char *name; | ||
| 691 | struct regulator_ops *ops = rdev->desc->ops; | 717 | struct regulator_ops *ops = rdev->desc->ops; |
| 718 | const char *name = rdev_get_name(rdev); | ||
| 719 | int ret; | ||
| 692 | 720 | ||
| 693 | if (constraints->name) | 721 | /* do we need to apply the constraint voltage */ |
| 694 | name = constraints->name; | 722 | if (rdev->constraints->apply_uV && |
| 695 | else if (rdev->desc->name) | 723 | rdev->constraints->min_uV == rdev->constraints->max_uV && |
| 696 | name = rdev->desc->name; | 724 | ops->set_voltage) { |
| 697 | else | 725 | ret = ops->set_voltage(rdev, |
| 698 | name = "regulator"; | 726 | rdev->constraints->min_uV, rdev->constraints->max_uV); |
| 727 | if (ret < 0) { | ||
| 728 | printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n", | ||
| 729 | __func__, | ||
| 730 | rdev->constraints->min_uV, name); | ||
| 731 | rdev->constraints = NULL; | ||
| 732 | return ret; | ||
| 733 | } | ||
| 734 | } | ||
| 699 | 735 | ||
| 700 | /* constrain machine-level voltage specs to fit | 736 | /* constrain machine-level voltage specs to fit |
| 701 | * the actual range supported by this regulator. | 737 | * the actual range supported by this regulator. |
| @@ -719,14 +755,13 @@ static int set_machine_constraints(struct regulator_dev *rdev, | |||
| 719 | 755 | ||
| 720 | /* voltage constraints are optional */ | 756 | /* voltage constraints are optional */ |
| 721 | if ((cmin == 0) && (cmax == 0)) | 757 | if ((cmin == 0) && (cmax == 0)) |
| 722 | goto out; | 758 | return 0; |
| 723 | 759 | ||
| 724 | /* else require explicit machine-level constraints */ | 760 | /* else require explicit machine-level constraints */ |
| 725 | if (cmin <= 0 || cmax <= 0 || cmax < cmin) { | 761 | if (cmin <= 0 || cmax <= 0 || cmax < cmin) { |
| 726 | pr_err("%s: %s '%s' voltage constraints\n", | 762 | pr_err("%s: %s '%s' voltage constraints\n", |
| 727 | __func__, "invalid", name); | 763 | __func__, "invalid", name); |
| 728 | ret = -EINVAL; | 764 | return -EINVAL; |
| 729 | goto out; | ||
| 730 | } | 765 | } |
| 731 | 766 | ||
| 732 | /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ | 767 | /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ |
| @@ -748,8 +783,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, | |||
| 748 | if (max_uV < min_uV) { | 783 | if (max_uV < min_uV) { |
| 749 | pr_err("%s: %s '%s' voltage constraints\n", | 784 | pr_err("%s: %s '%s' voltage constraints\n", |
| 750 | __func__, "unsupportable", name); | 785 | __func__, "unsupportable", name); |
| 751 | ret = -EINVAL; | 786 | return -EINVAL; |
| 752 | goto out; | ||
| 753 | } | 787 | } |
| 754 | 788 | ||
| 755 | /* use regulator's subset of machine constraints */ | 789 | /* use regulator's subset of machine constraints */ |
| @@ -767,22 +801,34 @@ static int set_machine_constraints(struct regulator_dev *rdev, | |||
| 767 | } | 801 | } |
| 768 | } | 802 | } |
| 769 | 803 | ||
| 804 | return 0; | ||
| 805 | } | ||
| 806 | |||
| 807 | /** | ||
| 808 | * set_machine_constraints - sets regulator constraints | ||
| 809 | * @rdev: regulator source | ||
| 810 | * @constraints: constraints to apply | ||
| 811 | * | ||
| 812 | * Allows platform initialisation code to define and constrain | ||
| 813 | * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: | ||
| 814 | * Constraints *must* be set by platform code in order for some | ||
| 815 | * regulator operations to proceed i.e. set_voltage, set_current_limit, | ||
| 816 | * set_mode. | ||
| 817 | */ | ||
| 818 | static int set_machine_constraints(struct regulator_dev *rdev, | ||
| 819 | struct regulation_constraints *constraints) | ||
| 820 | { | ||
| 821 | int ret = 0; | ||
| 822 | const char *name; | ||
| 823 | struct regulator_ops *ops = rdev->desc->ops; | ||
| 824 | |||
| 770 | rdev->constraints = constraints; | 825 | rdev->constraints = constraints; |
| 771 | 826 | ||
| 772 | /* do we need to apply the constraint voltage */ | 827 | name = rdev_get_name(rdev); |
| 773 | if (rdev->constraints->apply_uV && | 828 | |
| 774 | rdev->constraints->min_uV == rdev->constraints->max_uV && | 829 | ret = machine_constraints_voltage(rdev, constraints); |
| 775 | ops->set_voltage) { | 830 | if (ret != 0) |
| 776 | ret = ops->set_voltage(rdev, | 831 | goto out; |
| 777 | rdev->constraints->min_uV, rdev->constraints->max_uV); | ||
| 778 | if (ret < 0) { | ||
| 779 | printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n", | ||
| 780 | __func__, | ||
| 781 | rdev->constraints->min_uV, name); | ||
| 782 | rdev->constraints = NULL; | ||
| 783 | goto out; | ||
| 784 | } | ||
| 785 | } | ||
| 786 | 832 | ||
| 787 | /* do we need to setup our suspend state */ | 833 | /* do we need to setup our suspend state */ |
| 788 | if (constraints->initial_state) { | 834 | if (constraints->initial_state) { |
| @@ -903,7 +949,7 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, | |||
| 903 | dev_name(&node->regulator->dev), | 949 | dev_name(&node->regulator->dev), |
| 904 | node->regulator->desc->name, | 950 | node->regulator->desc->name, |
| 905 | supply, | 951 | supply, |
| 906 | dev_name(&rdev->dev), rdev->desc->name); | 952 | dev_name(&rdev->dev), rdev_get_name(rdev)); |
| 907 | return -EBUSY; | 953 | return -EBUSY; |
| 908 | } | 954 | } |
| 909 | 955 | ||
| @@ -1212,7 +1258,7 @@ static int _regulator_enable(struct regulator_dev *rdev) | |||
| 1212 | ret = _regulator_enable(rdev->supply); | 1258 | ret = _regulator_enable(rdev->supply); |
| 1213 | if (ret < 0) { | 1259 | if (ret < 0) { |
| 1214 | printk(KERN_ERR "%s: failed to enable %s: %d\n", | 1260 | printk(KERN_ERR "%s: failed to enable %s: %d\n", |
| 1215 | __func__, rdev->desc->name, ret); | 1261 | __func__, rdev_get_name(rdev), ret); |
| 1216 | return ret; | 1262 | return ret; |
| 1217 | } | 1263 | } |
| 1218 | } | 1264 | } |
| @@ -1238,7 +1284,7 @@ static int _regulator_enable(struct regulator_dev *rdev) | |||
| 1238 | } | 1284 | } |
| 1239 | } else if (ret < 0) { | 1285 | } else if (ret < 0) { |
| 1240 | printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", | 1286 | printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", |
| 1241 | __func__, rdev->desc->name, ret); | 1287 | __func__, rdev_get_name(rdev), ret); |
| 1242 | return ret; | 1288 | return ret; |
| 1243 | } | 1289 | } |
| 1244 | /* Fallthrough on positive return values - already enabled */ | 1290 | /* Fallthrough on positive return values - already enabled */ |
| @@ -1279,7 +1325,7 @@ static int _regulator_disable(struct regulator_dev *rdev) | |||
| 1279 | 1325 | ||
| 1280 | if (WARN(rdev->use_count <= 0, | 1326 | if (WARN(rdev->use_count <= 0, |
| 1281 | "unbalanced disables for %s\n", | 1327 | "unbalanced disables for %s\n", |
| 1282 | rdev->desc->name)) | 1328 | rdev_get_name(rdev))) |
| 1283 | return -EIO; | 1329 | return -EIO; |
| 1284 | 1330 | ||
| 1285 | /* are we the last user and permitted to disable ? */ | 1331 | /* are we the last user and permitted to disable ? */ |
| @@ -1292,7 +1338,7 @@ static int _regulator_disable(struct regulator_dev *rdev) | |||
| 1292 | ret = rdev->desc->ops->disable(rdev); | 1338 | ret = rdev->desc->ops->disable(rdev); |
| 1293 | if (ret < 0) { | 1339 | if (ret < 0) { |
| 1294 | printk(KERN_ERR "%s: failed to disable %s\n", | 1340 | printk(KERN_ERR "%s: failed to disable %s\n", |
| 1295 | __func__, rdev->desc->name); | 1341 | __func__, rdev_get_name(rdev)); |
| 1296 | return ret; | 1342 | return ret; |
| 1297 | } | 1343 | } |
| 1298 | } | 1344 | } |
| @@ -1349,7 +1395,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev) | |||
| 1349 | ret = rdev->desc->ops->disable(rdev); | 1395 | ret = rdev->desc->ops->disable(rdev); |
| 1350 | if (ret < 0) { | 1396 | if (ret < 0) { |
| 1351 | printk(KERN_ERR "%s: failed to force disable %s\n", | 1397 | printk(KERN_ERR "%s: failed to force disable %s\n", |
| 1352 | __func__, rdev->desc->name); | 1398 | __func__, rdev_get_name(rdev)); |
| 1353 | return ret; | 1399 | return ret; |
| 1354 | } | 1400 | } |
| 1355 | /* notify other consumers that power has been forced off */ | 1401 | /* notify other consumers that power has been forced off */ |
| @@ -1766,7 +1812,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) | |||
| 1766 | output_uV = rdev->desc->ops->get_voltage(rdev); | 1812 | output_uV = rdev->desc->ops->get_voltage(rdev); |
| 1767 | if (output_uV <= 0) { | 1813 | if (output_uV <= 0) { |
| 1768 | printk(KERN_ERR "%s: invalid output voltage found for %s\n", | 1814 | printk(KERN_ERR "%s: invalid output voltage found for %s\n", |
| 1769 | __func__, rdev->desc->name); | 1815 | __func__, rdev_get_name(rdev)); |
| 1770 | goto out; | 1816 | goto out; |
| 1771 | } | 1817 | } |
| 1772 | 1818 | ||
| @@ -1777,13 +1823,13 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) | |||
| 1777 | input_uV = rdev->constraints->input_uV; | 1823 | input_uV = rdev->constraints->input_uV; |
| 1778 | if (input_uV <= 0) { | 1824 | if (input_uV <= 0) { |
| 1779 | printk(KERN_ERR "%s: invalid input voltage found for %s\n", | 1825 | printk(KERN_ERR "%s: invalid input voltage found for %s\n", |
| 1780 | __func__, rdev->desc->name); | 1826 | __func__, rdev_get_name(rdev)); |
| 1781 | goto out; | 1827 | goto out; |
| 1782 | } | 1828 | } |
| 1783 | 1829 | ||
| 1784 | /* calc total requested load for this regulator */ | 1830 | /* calc total requested load for this regulator */ |
| 1785 | list_for_each_entry(consumer, &rdev->consumer_list, list) | 1831 | list_for_each_entry(consumer, &rdev->consumer_list, list) |
| 1786 | total_uA_load += consumer->uA_load; | 1832 | total_uA_load += consumer->uA_load; |
| 1787 | 1833 | ||
| 1788 | mode = rdev->desc->ops->get_optimum_mode(rdev, | 1834 | mode = rdev->desc->ops->get_optimum_mode(rdev, |
| 1789 | input_uV, output_uV, | 1835 | input_uV, output_uV, |
| @@ -1791,7 +1837,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) | |||
| 1791 | ret = regulator_check_mode(rdev, mode); | 1837 | ret = regulator_check_mode(rdev, mode); |
| 1792 | if (ret < 0) { | 1838 | if (ret < 0) { |
| 1793 | printk(KERN_ERR "%s: failed to get optimum mode for %s @" | 1839 | printk(KERN_ERR "%s: failed to get optimum mode for %s @" |
| 1794 | " %d uA %d -> %d uV\n", __func__, rdev->desc->name, | 1840 | " %d uA %d -> %d uV\n", __func__, rdev_get_name(rdev), |
| 1795 | total_uA_load, input_uV, output_uV); | 1841 | total_uA_load, input_uV, output_uV); |
| 1796 | goto out; | 1842 | goto out; |
| 1797 | } | 1843 | } |
| @@ -1799,7 +1845,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) | |||
| 1799 | ret = rdev->desc->ops->set_mode(rdev, mode); | 1845 | ret = rdev->desc->ops->set_mode(rdev, mode); |
| 1800 | if (ret < 0) { | 1846 | if (ret < 0) { |
| 1801 | printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n", | 1847 | printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n", |
| 1802 | __func__, mode, rdev->desc->name); | 1848 | __func__, mode, rdev_get_name(rdev)); |
| 1803 | goto out; | 1849 | goto out; |
| 1804 | } | 1850 | } |
| 1805 | ret = mode; | 1851 | ret = mode; |
| @@ -1852,9 +1898,9 @@ static void _notifier_call_chain(struct regulator_dev *rdev, | |||
| 1852 | 1898 | ||
| 1853 | /* now notify regulator we supply */ | 1899 | /* now notify regulator we supply */ |
| 1854 | list_for_each_entry(_rdev, &rdev->supply_list, slist) { | 1900 | list_for_each_entry(_rdev, &rdev->supply_list, slist) { |
| 1855 | mutex_lock(&_rdev->mutex); | 1901 | mutex_lock(&_rdev->mutex); |
| 1856 | _notifier_call_chain(_rdev, event, data); | 1902 | _notifier_call_chain(_rdev, event, data); |
| 1857 | mutex_unlock(&_rdev->mutex); | 1903 | mutex_unlock(&_rdev->mutex); |
| 1858 | } | 1904 | } |
| 1859 | } | 1905 | } |
| 1860 | 1906 | ||
| @@ -1885,9 +1931,9 @@ int regulator_bulk_get(struct device *dev, int num_consumers, | |||
| 1885 | consumers[i].consumer = regulator_get(dev, | 1931 | consumers[i].consumer = regulator_get(dev, |
| 1886 | consumers[i].supply); | 1932 | consumers[i].supply); |
| 1887 | if (IS_ERR(consumers[i].consumer)) { | 1933 | if (IS_ERR(consumers[i].consumer)) { |
| 1888 | dev_err(dev, "Failed to get supply '%s'\n", | ||
| 1889 | consumers[i].supply); | ||
| 1890 | ret = PTR_ERR(consumers[i].consumer); | 1934 | ret = PTR_ERR(consumers[i].consumer); |
| 1935 | dev_err(dev, "Failed to get supply '%s': %d\n", | ||
| 1936 | consumers[i].supply, ret); | ||
| 1891 | consumers[i].consumer = NULL; | 1937 | consumers[i].consumer = NULL; |
| 1892 | goto err; | 1938 | goto err; |
| 1893 | } | 1939 | } |
| @@ -1930,8 +1976,8 @@ int regulator_bulk_enable(int num_consumers, | |||
| 1930 | return 0; | 1976 | return 0; |
| 1931 | 1977 | ||
| 1932 | err: | 1978 | err: |
| 1933 | printk(KERN_ERR "Failed to enable %s\n", consumers[i].supply); | 1979 | printk(KERN_ERR "Failed to enable %s: %d\n", consumers[i].supply, ret); |
| 1934 | for (i = 0; i < num_consumers; i++) | 1980 | for (--i; i >= 0; --i) |
| 1935 | regulator_disable(consumers[i].consumer); | 1981 | regulator_disable(consumers[i].consumer); |
| 1936 | 1982 | ||
| 1937 | return ret; | 1983 | return ret; |
| @@ -1965,8 +2011,9 @@ int regulator_bulk_disable(int num_consumers, | |||
| 1965 | return 0; | 2011 | return 0; |
| 1966 | 2012 | ||
| 1967 | err: | 2013 | err: |
| 1968 | printk(KERN_ERR "Failed to disable %s\n", consumers[i].supply); | 2014 | printk(KERN_ERR "Failed to disable %s: %d\n", consumers[i].supply, |
| 1969 | for (i = 0; i < num_consumers; i++) | 2015 | ret); |
| 2016 | for (--i; i >= 0; --i) | ||
| 1970 | regulator_enable(consumers[i].consumer); | 2017 | regulator_enable(consumers[i].consumer); |
| 1971 | 2018 | ||
| 1972 | return ret; | 2019 | return ret; |
| @@ -2316,7 +2363,7 @@ int regulator_suspend_prepare(suspend_state_t state) | |||
| 2316 | 2363 | ||
| 2317 | if (ret < 0) { | 2364 | if (ret < 0) { |
| 2318 | printk(KERN_ERR "%s: failed to prepare %s\n", | 2365 | printk(KERN_ERR "%s: failed to prepare %s\n", |
| 2319 | __func__, rdev->desc->name); | 2366 | __func__, rdev_get_name(rdev)); |
| 2320 | goto out; | 2367 | goto out; |
| 2321 | } | 2368 | } |
| 2322 | } | 2369 | } |
| @@ -2429,12 +2476,7 @@ static int __init regulator_init_complete(void) | |||
| 2429 | ops = rdev->desc->ops; | 2476 | ops = rdev->desc->ops; |
| 2430 | c = rdev->constraints; | 2477 | c = rdev->constraints; |
| 2431 | 2478 | ||
| 2432 | if (c && c->name) | 2479 | name = rdev_get_name(rdev); |
| 2433 | name = c->name; | ||
| 2434 | else if (rdev->desc->name) | ||
| 2435 | name = rdev->desc->name; | ||
| 2436 | else | ||
| 2437 | name = "regulator"; | ||
| 2438 | 2480 | ||
| 2439 | if (!ops->disable || (c && c->always_on)) | 2481 | if (!ops->disable || (c && c->always_on)) |
| 2440 | continue; | 2482 | continue; |
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index aa224d936e0d..f8c4661a7a81 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c | |||
| @@ -331,7 +331,7 @@ static int da9034_get_ldo12_voltage(struct regulator_dev *rdev) | |||
| 331 | static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, | 331 | static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, |
| 332 | unsigned selector) | 332 | unsigned selector) |
| 333 | { | 333 | { |
| 334 | if (selector > ARRAY_SIZE(da9034_ldo12_data)) | 334 | if (selector >= ARRAY_SIZE(da9034_ldo12_data)) |
| 335 | return -EINVAL; | 335 | return -EINVAL; |
| 336 | return da9034_ldo12_data[selector] * 1000; | 336 | return da9034_ldo12_data[selector] * 1000; |
| 337 | } | 337 | } |
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 7803a320543b..76d08c282f9c 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c | |||
| @@ -446,8 +446,8 @@ static int setup_regulators(struct lp3971 *lp3971, | |||
| 446 | lp3971->rdev[i] = regulator_register(®ulators[id], | 446 | lp3971->rdev[i] = regulator_register(®ulators[id], |
| 447 | lp3971->dev, pdata->regulators[i].initdata, lp3971); | 447 | lp3971->dev, pdata->regulators[i].initdata, lp3971); |
| 448 | 448 | ||
| 449 | err = IS_ERR(lp3971->rdev[i]); | 449 | if (IS_ERR(lp3971->rdev[i])) { |
| 450 | if (err) { | 450 | err = PTR_ERR(lp3971->rdev[i]); |
| 451 | dev_err(lp3971->dev, "regulator init failed: %d\n", | 451 | dev_err(lp3971->dev, "regulator init failed: %d\n", |
| 452 | err); | 452 | err); |
| 453 | goto error; | 453 | goto error; |
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c new file mode 100644 index 000000000000..acc2fb7b6087 --- /dev/null +++ b/drivers/regulator/max8660.c | |||
| @@ -0,0 +1,510 @@ | |||
| 1 | /* | ||
| 2 | * max8660.c -- Voltage regulation for the Maxim 8660/8661 | ||
| 3 | * | ||
| 4 | * based on max1586.c and wm8400-regulator.c | ||
| 5 | * | ||
| 6 | * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation; version 2 of the License. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along with | ||
| 18 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | ||
| 19 | * Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | * | ||
| 21 | * Some info: | ||
| 22 | * | ||
| 23 | * Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8660-MAX8661.pdf | ||
| 24 | * | ||
| 25 | * This chip is a bit nasty because it is a write-only device. Thus, the driver | ||
| 26 | * uses shadow registers to keep track of its values. The main problem appears | ||
| 27 | * to be the initialization: When Linux boots up, we cannot know if the chip is | ||
| 28 | * in the default state or not, so we would have to pass such information in | ||
| 29 | * platform_data. As this adds a bit of complexity to the driver, this is left | ||
| 30 | * out for now until it is really needed. | ||
| 31 | * | ||
| 32 | * [A|S|M]DTV1 registers are currently not used, but [A|S|M]DTV2. | ||
| 33 | * | ||
| 34 | * If the driver is feature complete, it might be worth to check if one set of | ||
| 35 | * functions for V3-V7 is sufficient. For maximum flexibility during | ||
| 36 | * development, they are separated for now. | ||
| 37 | * | ||
| 38 | */ | ||
| 39 | |||
| 40 | #include <linux/module.h> | ||
| 41 | #include <linux/err.h> | ||
| 42 | #include <linux/i2c.h> | ||
| 43 | #include <linux/platform_device.h> | ||
| 44 | #include <linux/regulator/driver.h> | ||
| 45 | #include <linux/regulator/max8660.h> | ||
| 46 | |||
| 47 | #define MAX8660_DCDC_MIN_UV 725000 | ||
| 48 | #define MAX8660_DCDC_MAX_UV 1800000 | ||
| 49 | #define MAX8660_DCDC_STEP 25000 | ||
| 50 | #define MAX8660_DCDC_MAX_SEL 0x2b | ||
| 51 | |||
| 52 | #define MAX8660_LDO5_MIN_UV 1700000 | ||
| 53 | #define MAX8660_LDO5_MAX_UV 2000000 | ||
| 54 | #define MAX8660_LDO5_STEP 25000 | ||
| 55 | #define MAX8660_LDO5_MAX_SEL 0x0c | ||
| 56 | |||
| 57 | #define MAX8660_LDO67_MIN_UV 1800000 | ||
| 58 | #define MAX8660_LDO67_MAX_UV 3300000 | ||
| 59 | #define MAX8660_LDO67_STEP 100000 | ||
| 60 | #define MAX8660_LDO67_MAX_SEL 0x0f | ||
| 61 | |||
| 62 | enum { | ||
| 63 | MAX8660_OVER1, | ||
| 64 | MAX8660_OVER2, | ||
| 65 | MAX8660_VCC1, | ||
| 66 | MAX8660_ADTV1, | ||
| 67 | MAX8660_ADTV2, | ||
| 68 | MAX8660_SDTV1, | ||
| 69 | MAX8660_SDTV2, | ||
| 70 | MAX8660_MDTV1, | ||
| 71 | MAX8660_MDTV2, | ||
| 72 | MAX8660_L12VCR, | ||
| 73 | MAX8660_FPWM, | ||
| 74 | MAX8660_N_REGS, /* not a real register */ | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct max8660 { | ||
| 78 | struct i2c_client *client; | ||
| 79 | u8 shadow_regs[MAX8660_N_REGS]; /* as chip is write only */ | ||
| 80 | struct regulator_dev *rdev[]; | ||
| 81 | }; | ||
| 82 | |||
| 83 | static int max8660_write(struct max8660 *max8660, u8 reg, u8 mask, u8 val) | ||
| 84 | { | ||
| 85 | static const u8 max8660_addresses[MAX8660_N_REGS] = | ||
| 86 | { 0x10, 0x12, 0x20, 0x23, 0x24, 0x29, 0x2a, 0x32, 0x33, 0x39, 0x80 }; | ||
| 87 | |||
| 88 | int ret; | ||
| 89 | u8 reg_val = (max8660->shadow_regs[reg] & mask) | val; | ||
| 90 | dev_vdbg(&max8660->client->dev, "Writing reg %02x with %02x\n", | ||
| 91 | max8660_addresses[reg], reg_val); | ||
| 92 | |||
| 93 | ret = i2c_smbus_write_byte_data(max8660->client, | ||
| 94 | max8660_addresses[reg], reg_val); | ||
| 95 | if (ret == 0) | ||
| 96 | max8660->shadow_regs[reg] = reg_val; | ||
| 97 | |||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | |||
| 102 | /* | ||
| 103 | * DCDC functions | ||
| 104 | */ | ||
| 105 | |||
| 106 | static int max8660_dcdc_is_enabled(struct regulator_dev *rdev) | ||
| 107 | { | ||
| 108 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 109 | u8 val = max8660->shadow_regs[MAX8660_OVER1]; | ||
| 110 | u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4; | ||
| 111 | return !!(val & mask); | ||
| 112 | } | ||
| 113 | |||
| 114 | static int max8660_dcdc_enable(struct regulator_dev *rdev) | ||
| 115 | { | ||
| 116 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 117 | u8 bit = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4; | ||
| 118 | return max8660_write(max8660, MAX8660_OVER1, 0xff, bit); | ||
| 119 | } | ||
| 120 | |||
| 121 | static int max8660_dcdc_disable(struct regulator_dev *rdev) | ||
| 122 | { | ||
| 123 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 124 | u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? ~1 : ~4; | ||
| 125 | return max8660_write(max8660, MAX8660_OVER1, mask, 0); | ||
| 126 | } | ||
| 127 | |||
| 128 | static int max8660_dcdc_list(struct regulator_dev *rdev, unsigned selector) | ||
| 129 | { | ||
| 130 | if (selector > MAX8660_DCDC_MAX_SEL) | ||
| 131 | return -EINVAL; | ||
| 132 | return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int max8660_dcdc_get(struct regulator_dev *rdev) | ||
| 136 | { | ||
| 137 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 138 | u8 reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2; | ||
| 139 | u8 selector = max8660->shadow_regs[reg]; | ||
| 140 | return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP; | ||
| 141 | } | ||
| 142 | |||
| 143 | static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV) | ||
| 144 | { | ||
| 145 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 146 | u8 reg, selector, bits; | ||
| 147 | int ret; | ||
| 148 | |||
| 149 | if (min_uV < MAX8660_DCDC_MIN_UV || min_uV > MAX8660_DCDC_MAX_UV) | ||
| 150 | return -EINVAL; | ||
| 151 | if (max_uV < MAX8660_DCDC_MIN_UV || max_uV > MAX8660_DCDC_MAX_UV) | ||
| 152 | return -EINVAL; | ||
| 153 | |||
| 154 | selector = (min_uV - (MAX8660_DCDC_MIN_UV - MAX8660_DCDC_STEP + 1)) | ||
| 155 | / MAX8660_DCDC_STEP; | ||
| 156 | |||
| 157 | ret = max8660_dcdc_list(rdev, selector); | ||
| 158 | if (ret < 0 || ret > max_uV) | ||
| 159 | return -EINVAL; | ||
| 160 | |||
| 161 | reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2; | ||
| 162 | ret = max8660_write(max8660, reg, 0, selector); | ||
| 163 | if (ret) | ||
| 164 | return ret; | ||
| 165 | |||
| 166 | /* Select target voltage register and activate regulation */ | ||
| 167 | bits = (rdev_get_id(rdev) == MAX8660_V3) ? 0x03 : 0x30; | ||
| 168 | return max8660_write(max8660, MAX8660_VCC1, 0xff, bits); | ||
| 169 | } | ||
| 170 | |||
| 171 | static struct regulator_ops max8660_dcdc_ops = { | ||
| 172 | .is_enabled = max8660_dcdc_is_enabled, | ||
| 173 | .list_voltage = max8660_dcdc_list, | ||
| 174 | .set_voltage = max8660_dcdc_set, | ||
| 175 | .get_voltage = max8660_dcdc_get, | ||
| 176 | }; | ||
| 177 | |||
| 178 | |||
| 179 | /* | ||
| 180 | * LDO5 functions | ||
| 181 | */ | ||
| 182 | |||
| 183 | static int max8660_ldo5_list(struct regulator_dev *rdev, unsigned selector) | ||
| 184 | { | ||
| 185 | if (selector > MAX8660_LDO5_MAX_SEL) | ||
| 186 | return -EINVAL; | ||
| 187 | return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP; | ||
| 188 | } | ||
| 189 | |||
| 190 | static int max8660_ldo5_get(struct regulator_dev *rdev) | ||
| 191 | { | ||
| 192 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 193 | u8 selector = max8660->shadow_regs[MAX8660_MDTV2]; | ||
| 194 | |||
| 195 | return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP; | ||
| 196 | } | ||
| 197 | |||
| 198 | static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV) | ||
| 199 | { | ||
| 200 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 201 | u8 selector; | ||
| 202 | int ret; | ||
| 203 | |||
| 204 | if (min_uV < MAX8660_LDO5_MIN_UV || min_uV > MAX8660_LDO5_MAX_UV) | ||
| 205 | return -EINVAL; | ||
| 206 | if (max_uV < MAX8660_LDO5_MIN_UV || max_uV > MAX8660_LDO5_MAX_UV) | ||
| 207 | return -EINVAL; | ||
| 208 | |||
| 209 | selector = (min_uV - (MAX8660_LDO5_MIN_UV - MAX8660_LDO5_STEP + 1)) | ||
| 210 | / MAX8660_LDO5_STEP; | ||
| 211 | ret = max8660_ldo5_list(rdev, selector); | ||
| 212 | if (ret < 0 || ret > max_uV) | ||
| 213 | return -EINVAL; | ||
| 214 | |||
| 215 | ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector); | ||
| 216 | if (ret) | ||
| 217 | return ret; | ||
| 218 | |||
| 219 | /* Select target voltage register and activate regulation */ | ||
| 220 | return max8660_write(max8660, MAX8660_VCC1, 0xff, 0xc0); | ||
| 221 | } | ||
| 222 | |||
| 223 | static struct regulator_ops max8660_ldo5_ops = { | ||
| 224 | .list_voltage = max8660_ldo5_list, | ||
| 225 | .set_voltage = max8660_ldo5_set, | ||
| 226 | .get_voltage = max8660_ldo5_get, | ||
| 227 | }; | ||
| 228 | |||
| 229 | |||
| 230 | /* | ||
| 231 | * LDO67 functions | ||
| 232 | */ | ||
| 233 | |||
| 234 | static int max8660_ldo67_is_enabled(struct regulator_dev *rdev) | ||
| 235 | { | ||
| 236 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 237 | u8 val = max8660->shadow_regs[MAX8660_OVER2]; | ||
| 238 | u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4; | ||
| 239 | return !!(val & mask); | ||
| 240 | } | ||
| 241 | |||
| 242 | static int max8660_ldo67_enable(struct regulator_dev *rdev) | ||
| 243 | { | ||
| 244 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 245 | u8 bit = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4; | ||
| 246 | return max8660_write(max8660, MAX8660_OVER2, 0xff, bit); | ||
| 247 | } | ||
| 248 | |||
| 249 | static int max8660_ldo67_disable(struct regulator_dev *rdev) | ||
| 250 | { | ||
| 251 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 252 | u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? ~2 : ~4; | ||
| 253 | return max8660_write(max8660, MAX8660_OVER2, mask, 0); | ||
| 254 | } | ||
| 255 | |||
| 256 | static int max8660_ldo67_list(struct regulator_dev *rdev, unsigned selector) | ||
| 257 | { | ||
| 258 | if (selector > MAX8660_LDO67_MAX_SEL) | ||
| 259 | return -EINVAL; | ||
| 260 | return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int max8660_ldo67_get(struct regulator_dev *rdev) | ||
| 264 | { | ||
| 265 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 266 | u8 shift = (rdev_get_id(rdev) == MAX8660_V6) ? 0 : 4; | ||
| 267 | u8 selector = (max8660->shadow_regs[MAX8660_L12VCR] >> shift) & 0xf; | ||
| 268 | |||
| 269 | return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP; | ||
| 270 | } | ||
| 271 | |||
| 272 | static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, int max_uV) | ||
| 273 | { | ||
| 274 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | ||
| 275 | u8 selector; | ||
| 276 | int ret; | ||
| 277 | |||
| 278 | if (min_uV < MAX8660_LDO67_MIN_UV || min_uV > MAX8660_LDO67_MAX_UV) | ||
| 279 | return -EINVAL; | ||
| 280 | if (max_uV < MAX8660_LDO67_MIN_UV || max_uV > MAX8660_LDO67_MAX_UV) | ||
| 281 | return -EINVAL; | ||
| 282 | |||
| 283 | selector = (min_uV - (MAX8660_LDO67_MIN_UV - MAX8660_LDO67_STEP + 1)) | ||
| 284 | / MAX8660_LDO67_STEP; | ||
| 285 | |||
| 286 | ret = max8660_ldo67_list(rdev, selector); | ||
| 287 | if (ret < 0 || ret > max_uV) | ||
| 288 | return -EINVAL; | ||
| 289 | |||
| 290 | if (rdev_get_id(rdev) == MAX8660_V6) | ||
| 291 | return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector); | ||
| 292 | else | ||
| 293 | return max8660_write(max8660, MAX8660_L12VCR, 0x0f, selector << 4); | ||
| 294 | } | ||
| 295 | |||
| 296 | static struct regulator_ops max8660_ldo67_ops = { | ||
| 297 | .is_enabled = max8660_ldo67_is_enabled, | ||
| 298 | .enable = max8660_ldo67_enable, | ||
| 299 | .disable = max8660_ldo67_disable, | ||
| 300 | .list_voltage = max8660_ldo67_list, | ||
| 301 | .get_voltage = max8660_ldo67_get, | ||
| 302 | .set_voltage = max8660_ldo67_set, | ||
| 303 | }; | ||
| 304 | |||
| 305 | static struct regulator_desc max8660_reg[] = { | ||
| 306 | { | ||
| 307 | .name = "V3(DCDC)", | ||
| 308 | .id = MAX8660_V3, | ||
| 309 | .ops = &max8660_dcdc_ops, | ||
| 310 | .type = REGULATOR_VOLTAGE, | ||
| 311 | .n_voltages = MAX8660_DCDC_MAX_SEL + 1, | ||
| 312 | .owner = THIS_MODULE, | ||
| 313 | }, | ||
| 314 | { | ||
| 315 | .name = "V4(DCDC)", | ||
| 316 | .id = MAX8660_V4, | ||
| 317 | .ops = &max8660_dcdc_ops, | ||
| 318 | .type = REGULATOR_VOLTAGE, | ||
| 319 | .n_voltages = MAX8660_DCDC_MAX_SEL + 1, | ||
| 320 | .owner = THIS_MODULE, | ||
| 321 | }, | ||
| 322 | { | ||
| 323 | .name = "V5(LDO)", | ||
| 324 | .id = MAX8660_V5, | ||
| 325 | .ops = &max8660_ldo5_ops, | ||
| 326 | .type = REGULATOR_VOLTAGE, | ||
| 327 | .n_voltages = MAX8660_LDO5_MAX_SEL + 1, | ||
| 328 | .owner = THIS_MODULE, | ||
| 329 | }, | ||
| 330 | { | ||
| 331 | .name = "V6(LDO)", | ||
| 332 | .id = MAX8660_V6, | ||
| 333 | .ops = &max8660_ldo67_ops, | ||
| 334 | .type = REGULATOR_VOLTAGE, | ||
| 335 | .n_voltages = MAX8660_LDO67_MAX_SEL + 1, | ||
| 336 | .owner = THIS_MODULE, | ||
| 337 | }, | ||
| 338 | { | ||
| 339 | .name = "V7(LDO)", | ||
| 340 | .id = MAX8660_V7, | ||
| 341 | .ops = &max8660_ldo67_ops, | ||
| 342 | .type = REGULATOR_VOLTAGE, | ||
| 343 | .n_voltages = MAX8660_LDO67_MAX_SEL + 1, | ||
| 344 | .owner = THIS_MODULE, | ||
| 345 | }, | ||
| 346 | }; | ||
| 347 | |||
| 348 | static int max8660_probe(struct i2c_client *client, | ||
| 349 | const struct i2c_device_id *i2c_id) | ||
| 350 | { | ||
| 351 | struct regulator_dev **rdev; | ||
| 352 | struct max8660_platform_data *pdata = client->dev.platform_data; | ||
| 353 | struct max8660 *max8660; | ||
| 354 | int boot_on, i, id, ret = -EINVAL; | ||
| 355 | |||
| 356 | if (pdata->num_subdevs > MAX8660_V_END) { | ||
| 357 | dev_err(&client->dev, "Too much regulators found!\n"); | ||
| 358 | goto out; | ||
| 359 | } | ||
| 360 | |||
| 361 | max8660 = kzalloc(sizeof(struct max8660) + | ||
| 362 | sizeof(struct regulator_dev *) * MAX8660_V_END, | ||
| 363 | GFP_KERNEL); | ||
| 364 | if (!max8660) { | ||
| 365 | ret = -ENOMEM; | ||
| 366 | goto out; | ||
| 367 | } | ||
| 368 | |||
| 369 | max8660->client = client; | ||
| 370 | rdev = max8660->rdev; | ||
| 371 | |||
| 372 | if (pdata->en34_is_high) { | ||
| 373 | /* Simulate always on */ | ||
| 374 | max8660->shadow_regs[MAX8660_OVER1] = 5; | ||
| 375 | } else { | ||
| 376 | /* Otherwise devices can be toggled via software */ | ||
| 377 | max8660_dcdc_ops.enable = max8660_dcdc_enable; | ||
| 378 | max8660_dcdc_ops.disable = max8660_dcdc_disable; | ||
| 379 | } | ||
| 380 | |||
| 381 | /* | ||
| 382 | * First, set up shadow registers to prevent glitches. As some | ||
| 383 | * registers are shared between regulators, everything must be properly | ||
| 384 | * set up for all regulators in advance. | ||
| 385 | */ | ||
| 386 | max8660->shadow_regs[MAX8660_ADTV1] = | ||
| 387 | max8660->shadow_regs[MAX8660_ADTV2] = | ||
| 388 | max8660->shadow_regs[MAX8660_SDTV1] = | ||
| 389 | max8660->shadow_regs[MAX8660_SDTV2] = 0x1b; | ||
| 390 | max8660->shadow_regs[MAX8660_MDTV1] = | ||
| 391 | max8660->shadow_regs[MAX8660_MDTV2] = 0x04; | ||
| 392 | |||
| 393 | for (i = 0; i < pdata->num_subdevs; i++) { | ||
| 394 | |||
| 395 | if (!pdata->subdevs[i].platform_data) | ||
| 396 | goto err_free; | ||
| 397 | |||
| 398 | boot_on = pdata->subdevs[i].platform_data->constraints.boot_on; | ||
| 399 | |||
| 400 | switch (pdata->subdevs[i].id) { | ||
| 401 | case MAX8660_V3: | ||
| 402 | if (boot_on) | ||
| 403 | max8660->shadow_regs[MAX8660_OVER1] |= 1; | ||
| 404 | break; | ||
| 405 | |||
| 406 | case MAX8660_V4: | ||
| 407 | if (boot_on) | ||
| 408 | max8660->shadow_regs[MAX8660_OVER1] |= 4; | ||
| 409 | break; | ||
| 410 | |||
| 411 | case MAX8660_V5: | ||
| 412 | break; | ||
| 413 | |||
| 414 | case MAX8660_V6: | ||
| 415 | if (boot_on) | ||
| 416 | max8660->shadow_regs[MAX8660_OVER2] |= 2; | ||
| 417 | break; | ||
| 418 | |||
| 419 | case MAX8660_V7: | ||
| 420 | if (!strcmp(i2c_id->name, "max8661")) { | ||
| 421 | dev_err(&client->dev, "Regulator not on this chip!\n"); | ||
| 422 | goto err_free; | ||
| 423 | } | ||
| 424 | |||
| 425 | if (boot_on) | ||
| 426 | max8660->shadow_regs[MAX8660_OVER2] |= 4; | ||
| 427 | break; | ||
| 428 | |||
| 429 | default: | ||
| 430 | dev_err(&client->dev, "invalid regulator %s\n", | ||
| 431 | pdata->subdevs[i].name); | ||
| 432 | goto err_free; | ||
| 433 | } | ||
| 434 | } | ||
| 435 | |||
| 436 | /* Finally register devices */ | ||
| 437 | for (i = 0; i < pdata->num_subdevs; i++) { | ||
| 438 | |||
| 439 | id = pdata->subdevs[i].id; | ||
| 440 | |||
| 441 | rdev[i] = regulator_register(&max8660_reg[id], &client->dev, | ||
| 442 | pdata->subdevs[i].platform_data, | ||
| 443 | max8660); | ||
| 444 | if (IS_ERR(rdev[i])) { | ||
| 445 | ret = PTR_ERR(rdev[i]); | ||
| 446 | dev_err(&client->dev, "failed to register %s\n", | ||
| 447 | max8660_reg[id].name); | ||
| 448 | goto err_unregister; | ||
| 449 | } | ||
| 450 | } | ||
| 451 | |||
| 452 | i2c_set_clientdata(client, rdev); | ||
| 453 | dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n"); | ||
| 454 | return 0; | ||
| 455 | |||
| 456 | err_unregister: | ||
| 457 | while (--i >= 0) | ||
| 458 | regulator_unregister(rdev[i]); | ||
| 459 | err_free: | ||
| 460 | kfree(max8660); | ||
| 461 | out: | ||
| 462 | return ret; | ||
| 463 | } | ||
| 464 | |||
| 465 | static int max8660_remove(struct i2c_client *client) | ||
| 466 | { | ||
| 467 | struct regulator_dev **rdev = i2c_get_clientdata(client); | ||
| 468 | int i; | ||
| 469 | |||
| 470 | for (i = 0; i < MAX8660_V_END; i++) | ||
| 471 | if (rdev[i]) | ||
| 472 | regulator_unregister(rdev[i]); | ||
| 473 | kfree(rdev); | ||
| 474 | i2c_set_clientdata(client, NULL); | ||
| 475 | |||
| 476 | return 0; | ||
| 477 | } | ||
| 478 | |||
| 479 | static const struct i2c_device_id max8660_id[] = { | ||
| 480 | { "max8660", 0 }, | ||
| 481 | { "max8661", 0 }, | ||
| 482 | { } | ||
| 483 | }; | ||
| 484 | MODULE_DEVICE_TABLE(i2c, max8660_id); | ||
| 485 | |||
| 486 | static struct i2c_driver max8660_driver = { | ||
| 487 | .probe = max8660_probe, | ||
| 488 | .remove = max8660_remove, | ||
| 489 | .driver = { | ||
| 490 | .name = "max8660", | ||
| 491 | }, | ||
| 492 | .id_table = max8660_id, | ||
| 493 | }; | ||
| 494 | |||
| 495 | static int __init max8660_init(void) | ||
| 496 | { | ||
| 497 | return i2c_add_driver(&max8660_driver); | ||
| 498 | } | ||
| 499 | subsys_initcall(max8660_init); | ||
| 500 | |||
| 501 | static void __exit max8660_exit(void) | ||
| 502 | { | ||
| 503 | i2c_del_driver(&max8660_driver); | ||
| 504 | } | ||
| 505 | module_exit(max8660_exit); | ||
| 506 | |||
| 507 | /* Module information */ | ||
| 508 | MODULE_DESCRIPTION("MAXIM 8660/8661 voltage regulator driver"); | ||
| 509 | MODULE_AUTHOR("Wolfram Sang"); | ||
| 510 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c new file mode 100644 index 000000000000..39c495300045 --- /dev/null +++ b/drivers/regulator/mc13783-regulator.c | |||
| @@ -0,0 +1,245 @@ | |||
| 1 | /* | ||
| 2 | * Regulator Driver for Freescale MC13783 PMIC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/mfd/mc13783.h> | ||
| 12 | #include <linux/regulator/machine.h> | ||
| 13 | #include <linux/regulator/driver.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/err.h> | ||
| 18 | |||
| 19 | #define MC13783_REG_SWITCHERS4 28 | ||
| 20 | #define MC13783_REG_SWITCHERS4_PLLEN (1 << 18) | ||
| 21 | |||
| 22 | #define MC13783_REG_SWITCHERS5 29 | ||
| 23 | #define MC13783_REG_SWITCHERS5_SW3EN (1 << 20) | ||
| 24 | |||
| 25 | #define MC13783_REG_REGULATORMODE0 32 | ||
| 26 | #define MC13783_REG_REGULATORMODE0_VAUDIOEN (1 << 0) | ||
| 27 | #define MC13783_REG_REGULATORMODE0_VIOHIEN (1 << 3) | ||
| 28 | #define MC13783_REG_REGULATORMODE0_VIOLOEN (1 << 6) | ||
| 29 | #define MC13783_REG_REGULATORMODE0_VDIGEN (1 << 9) | ||
| 30 | #define MC13783_REG_REGULATORMODE0_VGENEN (1 << 12) | ||
| 31 | #define MC13783_REG_REGULATORMODE0_VRFDIGEN (1 << 15) | ||
| 32 | #define MC13783_REG_REGULATORMODE0_VRFREFEN (1 << 18) | ||
| 33 | #define MC13783_REG_REGULATORMODE0_VRFCPEN (1 << 21) | ||
| 34 | |||
| 35 | #define MC13783_REG_REGULATORMODE1 33 | ||
| 36 | #define MC13783_REG_REGULATORMODE1_VSIMEN (1 << 0) | ||
| 37 | #define MC13783_REG_REGULATORMODE1_VESIMEN (1 << 3) | ||
| 38 | #define MC13783_REG_REGULATORMODE1_VCAMEN (1 << 6) | ||
| 39 | #define MC13783_REG_REGULATORMODE1_VRFBGEN (1 << 9) | ||
| 40 | #define MC13783_REG_REGULATORMODE1_VVIBEN (1 << 11) | ||
| 41 | #define MC13783_REG_REGULATORMODE1_VRF1EN (1 << 12) | ||
| 42 | #define MC13783_REG_REGULATORMODE1_VRF2EN (1 << 15) | ||
| 43 | #define MC13783_REG_REGULATORMODE1_VMMC1EN (1 << 18) | ||
| 44 | #define MC13783_REG_REGULATORMODE1_VMMC2EN (1 << 21) | ||
| 45 | |||
| 46 | #define MC13783_REG_POWERMISC 34 | ||
| 47 | #define MC13783_REG_POWERMISC_GPO1EN (1 << 6) | ||
| 48 | #define MC13783_REG_POWERMISC_GPO2EN (1 << 8) | ||
| 49 | #define MC13783_REG_POWERMISC_GPO3EN (1 << 10) | ||
| 50 | #define MC13783_REG_POWERMISC_GPO4EN (1 << 12) | ||
| 51 | |||
| 52 | struct mc13783_regulator { | ||
| 53 | struct regulator_desc desc; | ||
| 54 | int reg; | ||
| 55 | int enable_bit; | ||
| 56 | }; | ||
| 57 | |||
| 58 | static struct regulator_ops mc13783_regulator_ops; | ||
| 59 | |||
| 60 | #define MC13783_DEFINE(prefix, _name, _reg) \ | ||
| 61 | [MC13783_ ## prefix ## _ ## _name] = { \ | ||
| 62 | .desc = { \ | ||
| 63 | .name = #prefix "_" #_name, \ | ||
| 64 | .ops = &mc13783_regulator_ops, \ | ||
| 65 | .type = REGULATOR_VOLTAGE, \ | ||
| 66 | .id = MC13783_ ## prefix ## _ ## _name, \ | ||
| 67 | .owner = THIS_MODULE, \ | ||
| 68 | }, \ | ||
| 69 | .reg = MC13783_REG_ ## _reg, \ | ||
| 70 | .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ | ||
| 71 | } | ||
| 72 | |||
| 73 | #define MC13783_DEFINE_SW(_name, _reg) MC13783_DEFINE(SW, _name, _reg) | ||
| 74 | #define MC13783_DEFINE_REGU(_name, _reg) MC13783_DEFINE(REGU, _name, _reg) | ||
| 75 | |||
| 76 | static struct mc13783_regulator mc13783_regulators[] = { | ||
| 77 | MC13783_DEFINE_SW(SW3, SWITCHERS5), | ||
| 78 | MC13783_DEFINE_SW(PLL, SWITCHERS4), | ||
| 79 | |||
| 80 | MC13783_DEFINE_REGU(VAUDIO, REGULATORMODE0), | ||
| 81 | MC13783_DEFINE_REGU(VIOHI, REGULATORMODE0), | ||
| 82 | MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0), | ||
| 83 | MC13783_DEFINE_REGU(VDIG, REGULATORMODE0), | ||
| 84 | MC13783_DEFINE_REGU(VGEN, REGULATORMODE0), | ||
| 85 | MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0), | ||
| 86 | MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0), | ||
| 87 | MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0), | ||
| 88 | MC13783_DEFINE_REGU(VSIM, REGULATORMODE1), | ||
| 89 | MC13783_DEFINE_REGU(VESIM, REGULATORMODE1), | ||
| 90 | MC13783_DEFINE_REGU(VCAM, REGULATORMODE1), | ||
| 91 | MC13783_DEFINE_REGU(VRFBG, REGULATORMODE1), | ||
| 92 | MC13783_DEFINE_REGU(VVIB, REGULATORMODE1), | ||
| 93 | MC13783_DEFINE_REGU(VRF1, REGULATORMODE1), | ||
| 94 | MC13783_DEFINE_REGU(VRF2, REGULATORMODE1), | ||
| 95 | MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1), | ||
| 96 | MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1), | ||
| 97 | MC13783_DEFINE_REGU(GPO1, POWERMISC), | ||
| 98 | MC13783_DEFINE_REGU(GPO2, POWERMISC), | ||
| 99 | MC13783_DEFINE_REGU(GPO3, POWERMISC), | ||
| 100 | MC13783_DEFINE_REGU(GPO4, POWERMISC), | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct mc13783_regulator_priv { | ||
| 104 | struct mc13783 *mc13783; | ||
| 105 | struct regulator_dev *regulators[]; | ||
| 106 | }; | ||
| 107 | |||
| 108 | static int mc13783_regulator_enable(struct regulator_dev *rdev) | ||
| 109 | { | ||
| 110 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
| 111 | int id = rdev_get_id(rdev); | ||
| 112 | int ret; | ||
| 113 | |||
| 114 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
| 115 | |||
| 116 | mc13783_lock(priv->mc13783); | ||
| 117 | ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg, | ||
| 118 | mc13783_regulators[id].enable_bit, | ||
| 119 | mc13783_regulators[id].enable_bit); | ||
| 120 | mc13783_unlock(priv->mc13783); | ||
| 121 | |||
| 122 | return ret; | ||
| 123 | } | ||
| 124 | |||
| 125 | static int mc13783_regulator_disable(struct regulator_dev *rdev) | ||
| 126 | { | ||
| 127 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
| 128 | int id = rdev_get_id(rdev); | ||
| 129 | int ret; | ||
| 130 | |||
| 131 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
| 132 | |||
| 133 | mc13783_lock(priv->mc13783); | ||
| 134 | ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg, | ||
| 135 | mc13783_regulators[id].enable_bit, 0); | ||
| 136 | mc13783_unlock(priv->mc13783); | ||
| 137 | |||
| 138 | return ret; | ||
| 139 | } | ||
| 140 | |||
| 141 | static int mc13783_regulator_is_enabled(struct regulator_dev *rdev) | ||
| 142 | { | ||
| 143 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
| 144 | int ret, id = rdev_get_id(rdev); | ||
| 145 | unsigned int val; | ||
| 146 | |||
| 147 | mc13783_lock(priv->mc13783); | ||
| 148 | ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val); | ||
| 149 | mc13783_unlock(priv->mc13783); | ||
| 150 | |||
| 151 | if (ret) | ||
| 152 | return ret; | ||
| 153 | |||
| 154 | return (val & mc13783_regulators[id].enable_bit) != 0; | ||
| 155 | } | ||
| 156 | |||
| 157 | static struct regulator_ops mc13783_regulator_ops = { | ||
| 158 | .enable = mc13783_regulator_enable, | ||
| 159 | .disable = mc13783_regulator_disable, | ||
| 160 | .is_enabled = mc13783_regulator_is_enabled, | ||
| 161 | }; | ||
| 162 | |||
| 163 | static int __devinit mc13783_regulator_probe(struct platform_device *pdev) | ||
| 164 | { | ||
| 165 | struct mc13783_regulator_priv *priv; | ||
| 166 | struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent); | ||
| 167 | struct mc13783_regulator_platform_data *pdata = | ||
| 168 | dev_get_platdata(&pdev->dev); | ||
| 169 | struct mc13783_regulator_init_data *init_data; | ||
| 170 | int i, ret; | ||
| 171 | |||
| 172 | dev_dbg(&pdev->dev, "mc13783_regulator_probe id %d\n", pdev->id); | ||
| 173 | |||
| 174 | priv = kzalloc(sizeof(*priv) + | ||
| 175 | pdata->num_regulators * sizeof(priv->regulators[0]), | ||
| 176 | GFP_KERNEL); | ||
| 177 | if (!priv) | ||
| 178 | return -ENOMEM; | ||
| 179 | |||
| 180 | priv->mc13783 = mc13783; | ||
| 181 | |||
| 182 | for (i = 0; i < pdata->num_regulators; i++) { | ||
| 183 | init_data = &pdata->regulators[i]; | ||
| 184 | priv->regulators[i] = regulator_register( | ||
| 185 | &mc13783_regulators[init_data->id].desc, | ||
| 186 | &pdev->dev, init_data->init_data, priv); | ||
| 187 | |||
| 188 | if (IS_ERR(priv->regulators[i])) { | ||
| 189 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
| 190 | mc13783_regulators[i].desc.name); | ||
| 191 | ret = PTR_ERR(priv->regulators[i]); | ||
| 192 | goto err; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | platform_set_drvdata(pdev, priv); | ||
| 197 | |||
| 198 | return 0; | ||
| 199 | err: | ||
| 200 | while (--i >= 0) | ||
| 201 | regulator_unregister(priv->regulators[i]); | ||
| 202 | |||
| 203 | kfree(priv); | ||
| 204 | |||
| 205 | return ret; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int __devexit mc13783_regulator_remove(struct platform_device *pdev) | ||
| 209 | { | ||
| 210 | struct mc13783_regulator_priv *priv = platform_get_drvdata(pdev); | ||
| 211 | struct mc13783_regulator_platform_data *pdata = | ||
| 212 | dev_get_platdata(&pdev->dev); | ||
| 213 | int i; | ||
| 214 | |||
| 215 | for (i = 0; i < pdata->num_regulators; i++) | ||
| 216 | regulator_unregister(priv->regulators[i]); | ||
| 217 | |||
| 218 | return 0; | ||
| 219 | } | ||
| 220 | |||
| 221 | static struct platform_driver mc13783_regulator_driver = { | ||
| 222 | .driver = { | ||
| 223 | .name = "mc13783-regulator", | ||
| 224 | .owner = THIS_MODULE, | ||
| 225 | }, | ||
| 226 | .remove = __devexit_p(mc13783_regulator_remove), | ||
| 227 | .probe = mc13783_regulator_probe, | ||
| 228 | }; | ||
| 229 | |||
| 230 | static int __init mc13783_regulator_init(void) | ||
| 231 | { | ||
| 232 | return platform_driver_register(&mc13783_regulator_driver); | ||
| 233 | } | ||
| 234 | subsys_initcall(mc13783_regulator_init); | ||
| 235 | |||
| 236 | static void __exit mc13783_regulator_exit(void) | ||
| 237 | { | ||
| 238 | platform_driver_unregister(&mc13783_regulator_driver); | ||
| 239 | } | ||
| 240 | module_exit(mc13783_regulator_exit); | ||
| 241 | |||
| 242 | MODULE_LICENSE("GPL v2"); | ||
| 243 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de"); | ||
| 244 | MODULE_DESCRIPTION("Regulator Driver for Freescale MC13783 PMIC"); | ||
| 245 | MODULE_ALIAS("platform:mc13783-regulator"); | ||
diff --git a/drivers/regulator/mc13783.c b/drivers/regulator/mc13783.c deleted file mode 100644 index 710211f67449..000000000000 --- a/drivers/regulator/mc13783.c +++ /dev/null | |||
| @@ -1,410 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Regulator Driver for Freescale MC13783 PMIC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/mfd/mc13783-private.h> | ||
| 12 | #include <linux/regulator/machine.h> | ||
| 13 | #include <linux/regulator/driver.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/mfd/mc13783.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/err.h> | ||
| 19 | |||
| 20 | struct mc13783_regulator { | ||
| 21 | struct regulator_desc desc; | ||
| 22 | int reg; | ||
| 23 | int enable_bit; | ||
| 24 | }; | ||
| 25 | |||
| 26 | static struct regulator_ops mc13783_regulator_ops; | ||
| 27 | |||
| 28 | static struct mc13783_regulator mc13783_regulators[] = { | ||
| 29 | [MC13783_SW_SW3] = { | ||
| 30 | .desc = { | ||
| 31 | .name = "SW_SW3", | ||
| 32 | .ops = &mc13783_regulator_ops, | ||
| 33 | .type = REGULATOR_VOLTAGE, | ||
| 34 | .id = MC13783_SW_SW3, | ||
| 35 | .owner = THIS_MODULE, | ||
| 36 | }, | ||
| 37 | .reg = MC13783_REG_SWITCHERS_5, | ||
| 38 | .enable_bit = MC13783_SWCTRL_SW3_EN, | ||
| 39 | }, | ||
| 40 | [MC13783_SW_PLL] = { | ||
| 41 | .desc = { | ||
| 42 | .name = "SW_PLL", | ||
| 43 | .ops = &mc13783_regulator_ops, | ||
| 44 | .type = REGULATOR_VOLTAGE, | ||
| 45 | .id = MC13783_SW_PLL, | ||
| 46 | .owner = THIS_MODULE, | ||
| 47 | }, | ||
| 48 | .reg = MC13783_REG_SWITCHERS_4, | ||
| 49 | .enable_bit = MC13783_SWCTRL_PLL_EN, | ||
| 50 | }, | ||
| 51 | [MC13783_REGU_VAUDIO] = { | ||
| 52 | .desc = { | ||
| 53 | .name = "REGU_VAUDIO", | ||
| 54 | .ops = &mc13783_regulator_ops, | ||
| 55 | .type = REGULATOR_VOLTAGE, | ||
| 56 | .id = MC13783_REGU_VAUDIO, | ||
| 57 | .owner = THIS_MODULE, | ||
| 58 | }, | ||
| 59 | .reg = MC13783_REG_REGULATOR_MODE_0, | ||
| 60 | .enable_bit = MC13783_REGCTRL_VAUDIO_EN, | ||
| 61 | }, | ||
| 62 | [MC13783_REGU_VIOHI] = { | ||
| 63 | .desc = { | ||
| 64 | .name = "REGU_VIOHI", | ||
| 65 | .ops = &mc13783_regulator_ops, | ||
| 66 | .type = REGULATOR_VOLTAGE, | ||
| 67 | .id = MC13783_REGU_VIOHI, | ||
| 68 | .owner = THIS_MODULE, | ||
| 69 | }, | ||
| 70 | .reg = MC13783_REG_REGULATOR_MODE_0, | ||
| 71 | .enable_bit = MC13783_REGCTRL_VIOHI_EN, | ||
| 72 | }, | ||
| 73 | [MC13783_REGU_VIOLO] = { | ||
| 74 | .desc = { | ||
| 75 | .name = "REGU_VIOLO", | ||
| 76 | .ops = &mc13783_regulator_ops, | ||
| 77 | .type = REGULATOR_VOLTAGE, | ||
| 78 | .id = MC13783_REGU_VIOLO, | ||
| 79 | .owner = THIS_MODULE, | ||
| 80 | }, | ||
| 81 | .reg = MC13783_REG_REGULATOR_MODE_0, | ||
| 82 | .enable_bit = MC13783_REGCTRL_VIOLO_EN, | ||
| 83 | }, | ||
| 84 | [MC13783_REGU_VDIG] = { | ||
| 85 | .desc = { | ||
| 86 | .name = "REGU_VDIG", | ||
| 87 | .ops = &mc13783_regulator_ops, | ||
| 88 | .type = REGULATOR_VOLTAGE, | ||
| 89 | .id = MC13783_REGU_VDIG, | ||
| 90 | .owner = THIS_MODULE, | ||
| 91 | }, | ||
| 92 | .reg = MC13783_REG_REGULATOR_MODE_0, | ||
| 93 | .enable_bit = MC13783_REGCTRL_VDIG_EN, | ||
| 94 | }, | ||
| 95 | [MC13783_REGU_VGEN] = { | ||
| 96 | .desc = { | ||
| 97 | .name = "REGU_VGEN", | ||
| 98 | .ops = &mc13783_regulator_ops, | ||
| 99 | .type = REGULATOR_VOLTAGE, | ||
| 100 | .id = MC13783_REGU_VGEN, | ||
| 101 | .owner = THIS_MODULE, | ||
| 102 | }, | ||
| 103 | .reg = MC13783_REG_REGULATOR_MODE_0, | ||
| 104 | .enable_bit = MC13783_REGCTRL_VGEN_EN, | ||
| 105 | }, | ||
| 106 | [MC13783_REGU_VRFDIG] = { | ||
| 107 | .desc = { | ||
| 108 | .name = "REGU_VRFDIG", | ||
| 109 | .ops = &mc13783_regulator_ops, | ||
| 110 | .type = REGULATOR_VOLTAGE, | ||
| 111 | .id = MC13783_REGU_VRFDIG, | ||
| 112 | .owner = THIS_MODULE, | ||
| 113 | }, | ||
| 114 | .reg = MC13783_REG_REGULATOR_MODE_0, | ||
| 115 | .enable_bit = MC13783_REGCTRL_VRFDIG_EN, | ||
| 116 | }, | ||
| 117 | [MC13783_REGU_VRFREF] = { | ||
| 118 | .desc = { | ||
| 119 | .name = "REGU_VRFREF", | ||
| 120 | .ops = &mc13783_regulator_ops, | ||
| 121 | .type = REGULATOR_VOLTAGE, | ||
| 122 | .id = MC13783_REGU_VRFREF, | ||
| 123 | .owner = THIS_MODULE, | ||
| 124 | }, | ||
| 125 | .reg = MC13783_REG_REGULATOR_MODE_0, | ||
| 126 | .enable_bit = MC13783_REGCTRL_VRFREF_EN, | ||
| 127 | }, | ||
| 128 | [MC13783_REGU_VRFCP] = { | ||
| 129 | .desc = { | ||
| 130 | .name = "REGU_VRFCP", | ||
| 131 | .ops = &mc13783_regulator_ops, | ||
| 132 | .type = REGULATOR_VOLTAGE, | ||
| 133 | .id = MC13783_REGU_VRFCP, | ||
| 134 | .owner = THIS_MODULE, | ||
| 135 | }, | ||
| 136 | .reg = MC13783_REG_REGULATOR_MODE_0, | ||
| 137 | .enable_bit = MC13783_REGCTRL_VRFCP_EN, | ||
| 138 | }, | ||
| 139 | [MC13783_REGU_VSIM] = { | ||
| 140 | .desc = { | ||
| 141 | .name = "REGU_VSIM", | ||
| 142 | .ops = &mc13783_regulator_ops, | ||
| 143 | .type = REGULATOR_VOLTAGE, | ||
| 144 | .id = MC13783_REGU_VSIM, | ||
| 145 | .owner = THIS_MODULE, | ||
| 146 | }, | ||
| 147 | .reg = MC13783_REG_REGULATOR_MODE_1, | ||
| 148 | .enable_bit = MC13783_REGCTRL_VSIM_EN, | ||
| 149 | }, | ||
| 150 | [MC13783_REGU_VESIM] = { | ||
| 151 | .desc = { | ||
| 152 | .name = "REGU_VESIM", | ||
| 153 | .ops = &mc13783_regulator_ops, | ||
| 154 | .type = REGULATOR_VOLTAGE, | ||
| 155 | .id = MC13783_REGU_VESIM, | ||
| 156 | .owner = THIS_MODULE, | ||
| 157 | }, | ||
| 158 | .reg = MC13783_REG_REGULATOR_MODE_1, | ||
| 159 | .enable_bit = MC13783_REGCTRL_VESIM_EN, | ||
| 160 | }, | ||
| 161 | [MC13783_REGU_VCAM] = { | ||
| 162 | .desc = { | ||
| 163 | .name = "REGU_VCAM", | ||
| 164 | .ops = &mc13783_regulator_ops, | ||
| 165 | .type = REGULATOR_VOLTAGE, | ||
| 166 | .id = MC13783_REGU_VCAM, | ||
| 167 | .owner = THIS_MODULE, | ||
| 168 | }, | ||
| 169 | .reg = MC13783_REG_REGULATOR_MODE_1, | ||
| 170 | .enable_bit = MC13783_REGCTRL_VCAM_EN, | ||
| 171 | }, | ||
| 172 | [MC13783_REGU_VRFBG] = { | ||
| 173 | .desc = { | ||
| 174 | .name = "REGU_VRFBG", | ||
| 175 | .ops = &mc13783_regulator_ops, | ||
| 176 | .type = REGULATOR_VOLTAGE, | ||
| 177 | .id = MC13783_REGU_VRFBG, | ||
| 178 | .owner = THIS_MODULE, | ||
| 179 | }, | ||
| 180 | .reg = MC13783_REG_REGULATOR_MODE_1, | ||
| 181 | .enable_bit = MC13783_REGCTRL_VRFBG_EN, | ||
| 182 | }, | ||
| 183 | [MC13783_REGU_VVIB] = { | ||
| 184 | .desc = { | ||
| 185 | .name = "REGU_VVIB", | ||
| 186 | .ops = &mc13783_regulator_ops, | ||
| 187 | .type = REGULATOR_VOLTAGE, | ||
| 188 | .id = MC13783_REGU_VVIB, | ||
| 189 | .owner = THIS_MODULE, | ||
| 190 | }, | ||
| 191 | .reg = MC13783_REG_REGULATOR_MODE_1, | ||
| 192 | .enable_bit = MC13783_REGCTRL_VVIB_EN, | ||
| 193 | }, | ||
| 194 | [MC13783_REGU_VRF1] = { | ||
| 195 | .desc = { | ||
| 196 | .name = "REGU_VRF1", | ||
| 197 | .ops = &mc13783_regulator_ops, | ||
| 198 | .type = REGULATOR_VOLTAGE, | ||
| 199 | .id = MC13783_REGU_VRF1, | ||
| 200 | .owner = THIS_MODULE, | ||
| 201 | }, | ||
| 202 | .reg = MC13783_REG_REGULATOR_MODE_1, | ||
| 203 | .enable_bit = MC13783_REGCTRL_VRF1_EN, | ||
| 204 | }, | ||
| 205 | [MC13783_REGU_VRF2] = { | ||
| 206 | .desc = { | ||
| 207 | .name = "REGU_VRF2", | ||
| 208 | .ops = &mc13783_regulator_ops, | ||
| 209 | .type = REGULATOR_VOLTAGE, | ||
| 210 | .id = MC13783_REGU_VRF2, | ||
| 211 | .owner = THIS_MODULE, | ||
| 212 | }, | ||
| 213 | .reg = MC13783_REG_REGULATOR_MODE_1, | ||
| 214 | .enable_bit = MC13783_REGCTRL_VRF2_EN, | ||
| 215 | }, | ||
| 216 | [MC13783_REGU_VMMC1] = { | ||
| 217 | .desc = { | ||
| 218 | .name = "REGU_VMMC1", | ||
| 219 | .ops = &mc13783_regulator_ops, | ||
| 220 | .type = REGULATOR_VOLTAGE, | ||
| 221 | .id = MC13783_REGU_VMMC1, | ||
| 222 | .owner = THIS_MODULE, | ||
| 223 | }, | ||
| 224 | .reg = MC13783_REG_REGULATOR_MODE_1, | ||
| 225 | .enable_bit = MC13783_REGCTRL_VMMC1_EN, | ||
| 226 | }, | ||
| 227 | [MC13783_REGU_VMMC2] = { | ||
| 228 | .desc = { | ||
| 229 | .name = "REGU_VMMC2", | ||
| 230 | .ops = &mc13783_regulator_ops, | ||
| 231 | .type = REGULATOR_VOLTAGE, | ||
| 232 | .id = MC13783_REGU_VMMC2, | ||
| 233 | .owner = THIS_MODULE, | ||
| 234 | }, | ||
| 235 | .reg = MC13783_REG_REGULATOR_MODE_1, | ||
| 236 | .enable_bit = MC13783_REGCTRL_VMMC2_EN, | ||
| 237 | }, | ||
| 238 | [MC13783_REGU_GPO1] = { | ||
| 239 | .desc = { | ||
| 240 | .name = "REGU_GPO1", | ||
| 241 | .ops = &mc13783_regulator_ops, | ||
| 242 | .type = REGULATOR_VOLTAGE, | ||
| 243 | .id = MC13783_REGU_GPO1, | ||
| 244 | .owner = THIS_MODULE, | ||
| 245 | }, | ||
| 246 | .reg = MC13783_REG_POWER_MISCELLANEOUS, | ||
| 247 | .enable_bit = MC13783_REGCTRL_GPO1_EN, | ||
| 248 | }, | ||
| 249 | [MC13783_REGU_GPO2] = { | ||
| 250 | .desc = { | ||
| 251 | .name = "REGU_GPO2", | ||
| 252 | .ops = &mc13783_regulator_ops, | ||
| 253 | .type = REGULATOR_VOLTAGE, | ||
| 254 | .id = MC13783_REGU_GPO2, | ||
| 255 | .owner = THIS_MODULE, | ||
| 256 | }, | ||
| 257 | .reg = MC13783_REG_POWER_MISCELLANEOUS, | ||
| 258 | .enable_bit = MC13783_REGCTRL_GPO2_EN, | ||
| 259 | }, | ||
| 260 | [MC13783_REGU_GPO3] = { | ||
| 261 | .desc = { | ||
| 262 | .name = "REGU_GPO3", | ||
| 263 | .ops = &mc13783_regulator_ops, | ||
| 264 | .type = REGULATOR_VOLTAGE, | ||
| 265 | .id = MC13783_REGU_GPO3, | ||
| 266 | .owner = THIS_MODULE, | ||
| 267 | }, | ||
| 268 | .reg = MC13783_REG_POWER_MISCELLANEOUS, | ||
| 269 | .enable_bit = MC13783_REGCTRL_GPO3_EN, | ||
| 270 | }, | ||
| 271 | [MC13783_REGU_GPO4] = { | ||
| 272 | .desc = { | ||
| 273 | .name = "REGU_GPO4", | ||
| 274 | .ops = &mc13783_regulator_ops, | ||
| 275 | .type = REGULATOR_VOLTAGE, | ||
| 276 | .id = MC13783_REGU_GPO4, | ||
| 277 | .owner = THIS_MODULE, | ||
| 278 | }, | ||
| 279 | .reg = MC13783_REG_POWER_MISCELLANEOUS, | ||
| 280 | .enable_bit = MC13783_REGCTRL_GPO4_EN, | ||
| 281 | }, | ||
| 282 | }; | ||
| 283 | |||
| 284 | struct mc13783_priv { | ||
| 285 | struct regulator_desc desc[ARRAY_SIZE(mc13783_regulators)]; | ||
| 286 | struct mc13783 *mc13783; | ||
| 287 | struct regulator_dev *regulators[0]; | ||
| 288 | }; | ||
| 289 | |||
| 290 | static int mc13783_enable(struct regulator_dev *rdev) | ||
| 291 | { | ||
| 292 | struct mc13783_priv *priv = rdev_get_drvdata(rdev); | ||
| 293 | int id = rdev_get_id(rdev); | ||
| 294 | |||
| 295 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
| 296 | |||
| 297 | return mc13783_set_bits(priv->mc13783, mc13783_regulators[id].reg, | ||
| 298 | mc13783_regulators[id].enable_bit, | ||
| 299 | mc13783_regulators[id].enable_bit); | ||
| 300 | } | ||
| 301 | |||
| 302 | static int mc13783_disable(struct regulator_dev *rdev) | ||
| 303 | { | ||
| 304 | struct mc13783_priv *priv = rdev_get_drvdata(rdev); | ||
| 305 | int id = rdev_get_id(rdev); | ||
| 306 | |||
| 307 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
| 308 | |||
| 309 | return mc13783_set_bits(priv->mc13783, mc13783_regulators[id].reg, | ||
| 310 | mc13783_regulators[id].enable_bit, 0); | ||
| 311 | } | ||
| 312 | |||
| 313 | static int mc13783_is_enabled(struct regulator_dev *rdev) | ||
| 314 | { | ||
| 315 | struct mc13783_priv *priv = rdev_get_drvdata(rdev); | ||
| 316 | int ret, id = rdev_get_id(rdev); | ||
| 317 | unsigned int val; | ||
| 318 | |||
| 319 | ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val); | ||
| 320 | if (ret) | ||
| 321 | return ret; | ||
| 322 | |||
| 323 | return (val & mc13783_regulators[id].enable_bit) != 0; | ||
| 324 | } | ||
| 325 | |||
| 326 | static struct regulator_ops mc13783_regulator_ops = { | ||
| 327 | .enable = mc13783_enable, | ||
| 328 | .disable = mc13783_disable, | ||
| 329 | .is_enabled = mc13783_is_enabled, | ||
| 330 | }; | ||
| 331 | |||
| 332 | static int __devinit mc13783_regulator_probe(struct platform_device *pdev) | ||
| 333 | { | ||
| 334 | struct mc13783_priv *priv; | ||
| 335 | struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent); | ||
| 336 | struct mc13783_regulator_init_data *init_data; | ||
| 337 | int i, ret; | ||
| 338 | |||
| 339 | dev_dbg(&pdev->dev, "mc13783_regulator_probe id %d\n", pdev->id); | ||
| 340 | |||
| 341 | priv = kzalloc(sizeof(*priv) + mc13783->num_regulators * sizeof(void *), | ||
| 342 | GFP_KERNEL); | ||
| 343 | if (!priv) | ||
| 344 | return -ENOMEM; | ||
| 345 | |||
| 346 | priv->mc13783 = mc13783; | ||
| 347 | |||
| 348 | for (i = 0; i < mc13783->num_regulators; i++) { | ||
| 349 | init_data = &mc13783->regulators[i]; | ||
| 350 | priv->regulators[i] = regulator_register( | ||
| 351 | &mc13783_regulators[init_data->id].desc, | ||
| 352 | &pdev->dev, init_data->init_data, priv); | ||
| 353 | |||
| 354 | if (IS_ERR(priv->regulators[i])) { | ||
| 355 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
| 356 | mc13783_regulators[i].desc.name); | ||
| 357 | ret = PTR_ERR(priv->regulators[i]); | ||
| 358 | goto err; | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | platform_set_drvdata(pdev, priv); | ||
| 363 | |||
| 364 | return 0; | ||
| 365 | err: | ||
| 366 | while (--i >= 0) | ||
| 367 | regulator_unregister(priv->regulators[i]); | ||
| 368 | |||
| 369 | kfree(priv); | ||
| 370 | |||
| 371 | return ret; | ||
| 372 | } | ||
| 373 | |||
| 374 | static int __devexit mc13783_regulator_remove(struct platform_device *pdev) | ||
| 375 | { | ||
| 376 | struct mc13783_priv *priv = platform_get_drvdata(pdev); | ||
| 377 | struct mc13783 *mc13783 = priv->mc13783; | ||
| 378 | int i; | ||
| 379 | |||
| 380 | for (i = 0; i < mc13783->num_regulators; i++) | ||
| 381 | regulator_unregister(priv->regulators[i]); | ||
| 382 | |||
| 383 | return 0; | ||
| 384 | } | ||
| 385 | |||
| 386 | static struct platform_driver mc13783_regulator_driver = { | ||
| 387 | .driver = { | ||
| 388 | .name = "mc13783-regulator", | ||
| 389 | .owner = THIS_MODULE, | ||
| 390 | }, | ||
| 391 | .remove = __devexit_p(mc13783_regulator_remove), | ||
| 392 | }; | ||
| 393 | |||
| 394 | static int __init mc13783_regulator_init(void) | ||
| 395 | { | ||
| 396 | return platform_driver_probe(&mc13783_regulator_driver, | ||
| 397 | mc13783_regulator_probe); | ||
| 398 | } | ||
| 399 | subsys_initcall(mc13783_regulator_init); | ||
| 400 | |||
| 401 | static void __exit mc13783_regulator_exit(void) | ||
| 402 | { | ||
| 403 | platform_driver_unregister(&mc13783_regulator_driver); | ||
| 404 | } | ||
| 405 | module_exit(mc13783_regulator_exit); | ||
| 406 | |||
| 407 | MODULE_LICENSE("GPL"); | ||
| 408 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de"); | ||
| 409 | MODULE_DESCRIPTION("Regulator Driver for Freescale MC13783 PMIC"); | ||
| 410 | MODULE_ALIAS("platform:mc13783-regulator"); | ||
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 7ea1c3a31081..7e674859bd59 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
| 15 | #include <linux/delay.h> | ||
| 15 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 16 | #include <linux/regulator/driver.h> | 17 | #include <linux/regulator/driver.h> |
| 17 | #include <linux/regulator/machine.h> | 18 | #include <linux/regulator/machine.h> |
| @@ -40,6 +41,12 @@ struct twlreg_info { | |||
| 40 | u8 table_len; | 41 | u8 table_len; |
| 41 | const u16 *table; | 42 | const u16 *table; |
| 42 | 43 | ||
| 44 | /* regulator specific turn-on delay */ | ||
| 45 | u16 delay; | ||
| 46 | |||
| 47 | /* State REMAP default configuration */ | ||
| 48 | u8 remap; | ||
| 49 | |||
| 43 | /* chip constraints on regulator behavior */ | 50 | /* chip constraints on regulator behavior */ |
| 44 | u16 min_mV; | 51 | u16 min_mV; |
| 45 | 52 | ||
| @@ -128,6 +135,7 @@ static int twlreg_enable(struct regulator_dev *rdev) | |||
| 128 | { | 135 | { |
| 129 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 136 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
| 130 | int grp; | 137 | int grp; |
| 138 | int ret; | ||
| 131 | 139 | ||
| 132 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); | 140 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); |
| 133 | if (grp < 0) | 141 | if (grp < 0) |
| @@ -138,7 +146,11 @@ static int twlreg_enable(struct regulator_dev *rdev) | |||
| 138 | else | 146 | else |
| 139 | grp |= P1_GRP_6030; | 147 | grp |= P1_GRP_6030; |
| 140 | 148 | ||
| 141 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | 149 | ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); |
| 150 | |||
| 151 | udelay(info->delay); | ||
| 152 | |||
| 153 | return ret; | ||
| 142 | } | 154 | } |
| 143 | 155 | ||
| 144 | static int twlreg_disable(struct regulator_dev *rdev) | 156 | static int twlreg_disable(struct regulator_dev *rdev) |
| @@ -151,9 +163,9 @@ static int twlreg_disable(struct regulator_dev *rdev) | |||
| 151 | return grp; | 163 | return grp; |
| 152 | 164 | ||
| 153 | if (twl_class_is_4030()) | 165 | if (twl_class_is_4030()) |
| 154 | grp &= ~P1_GRP_4030; | 166 | grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030); |
| 155 | else | 167 | else |
| 156 | grp &= ~P1_GRP_6030; | 168 | grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030); |
| 157 | 169 | ||
| 158 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | 170 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); |
| 159 | } | 171 | } |
| @@ -294,6 +306,18 @@ static const u16 VSIM_VSEL_table[] = { | |||
| 294 | static const u16 VDAC_VSEL_table[] = { | 306 | static const u16 VDAC_VSEL_table[] = { |
| 295 | 1200, 1300, 1800, 1800, | 307 | 1200, 1300, 1800, 1800, |
| 296 | }; | 308 | }; |
| 309 | static const u16 VDD1_VSEL_table[] = { | ||
| 310 | 800, 1450, | ||
| 311 | }; | ||
| 312 | static const u16 VDD2_VSEL_table[] = { | ||
| 313 | 800, 1450, 1500, | ||
| 314 | }; | ||
| 315 | static const u16 VIO_VSEL_table[] = { | ||
| 316 | 1800, 1850, | ||
| 317 | }; | ||
| 318 | static const u16 VINTANA2_VSEL_table[] = { | ||
| 319 | 2500, 2750, | ||
| 320 | }; | ||
| 297 | static const u16 VAUX1_6030_VSEL_table[] = { | 321 | static const u16 VAUX1_6030_VSEL_table[] = { |
| 298 | 1000, 1300, 1800, 2500, | 322 | 1000, 1300, 1800, 2500, |
| 299 | 2800, 2900, 3000, 3000, | 323 | 2800, 2900, 3000, 3000, |
| @@ -414,20 +438,30 @@ static struct regulator_ops twlfixed_ops = { | |||
| 414 | 438 | ||
| 415 | /*----------------------------------------------------------------------*/ | 439 | /*----------------------------------------------------------------------*/ |
| 416 | 440 | ||
| 417 | #define TWL4030_ADJUSTABLE_LDO(label, offset, num) \ | 441 | #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \ |
| 418 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030) | 442 | TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \ |
| 419 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num) \ | 443 | remap_conf, TWL4030) |
| 420 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030) | 444 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ |
| 421 | #define TWL6030_ADJUSTABLE_LDO(label, offset, num) \ | 445 | remap_conf) \ |
| 422 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL6030) | 446 | TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ |
| 423 | #define TWL6030_FIXED_LDO(label, offset, mVolts, num) \ | 447 | remap_conf, TWL4030) |
| 424 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL6030) | 448 | #define TWL6030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \ |
| 425 | 449 | remap_conf) \ | |
| 426 | #define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \ | 450 | TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \ |
| 451 | remap_conf, TWL6030) | ||
| 452 | #define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ | ||
| 453 | remap_conf) \ | ||
| 454 | TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ | ||
| 455 | remap_conf, TWL6030) | ||
| 456 | |||
| 457 | #define TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf, \ | ||
| 458 | family) { \ | ||
| 427 | .base = offset, \ | 459 | .base = offset, \ |
| 428 | .id = num, \ | 460 | .id = num, \ |
| 429 | .table_len = ARRAY_SIZE(label##_VSEL_table), \ | 461 | .table_len = ARRAY_SIZE(label##_VSEL_table), \ |
| 430 | .table = label##_VSEL_table, \ | 462 | .table = label##_VSEL_table, \ |
| 463 | .delay = turnon_delay, \ | ||
| 464 | .remap = remap_conf, \ | ||
| 431 | .desc = { \ | 465 | .desc = { \ |
| 432 | .name = #label, \ | 466 | .name = #label, \ |
| 433 | .id = family##_REG_##label, \ | 467 | .id = family##_REG_##label, \ |
| @@ -438,10 +472,13 @@ static struct regulator_ops twlfixed_ops = { | |||
| 438 | }, \ | 472 | }, \ |
| 439 | } | 473 | } |
| 440 | 474 | ||
| 441 | #define TWL_FIXED_LDO(label, offset, mVolts, num, family) { \ | 475 | #define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ |
| 476 | family) { \ | ||
| 442 | .base = offset, \ | 477 | .base = offset, \ |
| 443 | .id = num, \ | 478 | .id = num, \ |
| 444 | .min_mV = mVolts, \ | 479 | .min_mV = mVolts, \ |
| 480 | .delay = turnon_delay, \ | ||
| 481 | .remap = remap_conf, \ | ||
| 445 | .desc = { \ | 482 | .desc = { \ |
| 446 | .name = #label, \ | 483 | .name = #label, \ |
| 447 | .id = family##_REG_##label, \ | 484 | .id = family##_REG_##label, \ |
| @@ -457,43 +494,41 @@ static struct regulator_ops twlfixed_ops = { | |||
| 457 | * software control over them after boot. | 494 | * software control over them after boot. |
| 458 | */ | 495 | */ |
| 459 | static struct twlreg_info twl_regs[] = { | 496 | static struct twlreg_info twl_regs[] = { |
| 460 | TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1), | 497 | TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1, 100, 0x08), |
| 461 | TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2), | 498 | TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2, 100, 0x08), |
| 462 | TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2), | 499 | TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2, 100, 0x08), |
| 463 | TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3), | 500 | TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3, 100, 0x08), |
| 464 | TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4), | 501 | TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4, 100, 0x08), |
| 465 | TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5), | 502 | TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5, 100, 0x08), |
| 466 | TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6), | 503 | TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6, 100, 0x08), |
| 467 | /* | 504 | TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7, 100, 0x00), |
| 468 | TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7), | 505 | TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8, 100, 0x08), |
| 469 | */ | 506 | TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00), |
| 470 | TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8), | 507 | TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08), |
| 471 | TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9), | 508 | TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08), |
| 472 | TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10), | 509 | TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08), |
| 473 | /* | 510 | TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08), |
| 474 | TWL4030_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11), | 511 | TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08), |
| 475 | TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12), | 512 | TWL4030_ADJUSTABLE_LDO(VDD1, 0x55, 15, 1000, 0x08), |
| 476 | TWL4030_ADJUSTABLE_LDO(VINTDIG, 0x47, 13), | 513 | TWL4030_ADJUSTABLE_LDO(VDD2, 0x63, 16, 1000, 0x08), |
| 477 | TWL4030_SMPS(VIO, 0x4b, 14), | 514 | TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08), |
| 478 | TWL4030_SMPS(VDD1, 0x55, 15), | 515 | TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08), |
| 479 | TWL4030_SMPS(VDD2, 0x63, 16), | 516 | TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08), |
| 480 | */ | ||
| 481 | TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17), | ||
| 482 | TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), | ||
| 483 | TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), | ||
| 484 | /* VUSBCP is managed *only* by the USB subchip */ | 517 | /* VUSBCP is managed *only* by the USB subchip */ |
| 485 | 518 | ||
| 486 | /* 6030 REG with base as PMC Slave Misc : 0x0030 */ | 519 | /* 6030 REG with base as PMC Slave Misc : 0x0030 */ |
| 487 | TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1), | 520 | /* Turnon-delay and remap configuration values for 6030 are not |
| 488 | TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2), | 521 | verified since the specification is not public */ |
| 489 | TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3), | 522 | TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1, 0, 0x08), |
| 490 | TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4), | 523 | TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2, 0, 0x08), |
| 491 | TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5), | 524 | TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3, 0, 0x08), |
| 492 | TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7), | 525 | TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4, 0, 0x08), |
| 493 | TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15), | 526 | TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5, 0, 0x08), |
| 494 | TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16), | 527 | TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7, 0, 0x08), |
| 495 | TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17), | 528 | TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x08), |
| 496 | TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18) | 529 | TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x08), |
| 530 | TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x08), | ||
| 531 | TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x08) | ||
| 497 | }; | 532 | }; |
| 498 | 533 | ||
| 499 | static int twlreg_probe(struct platform_device *pdev) | 534 | static int twlreg_probe(struct platform_device *pdev) |
| @@ -525,6 +560,19 @@ static int twlreg_probe(struct platform_device *pdev) | |||
| 525 | c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE | 560 | c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE |
| 526 | | REGULATOR_CHANGE_MODE | 561 | | REGULATOR_CHANGE_MODE |
| 527 | | REGULATOR_CHANGE_STATUS; | 562 | | REGULATOR_CHANGE_STATUS; |
| 563 | switch (pdev->id) { | ||
| 564 | case TWL4030_REG_VIO: | ||
| 565 | case TWL4030_REG_VDD1: | ||
| 566 | case TWL4030_REG_VDD2: | ||
| 567 | case TWL4030_REG_VPLL1: | ||
| 568 | case TWL4030_REG_VINTANA1: | ||
| 569 | case TWL4030_REG_VINTANA2: | ||
| 570 | case TWL4030_REG_VINTDIG: | ||
| 571 | c->always_on = true; | ||
| 572 | break; | ||
| 573 | default: | ||
| 574 | break; | ||
| 575 | } | ||
| 528 | 576 | ||
| 529 | rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); | 577 | rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); |
| 530 | if (IS_ERR(rdev)) { | 578 | if (IS_ERR(rdev)) { |
| @@ -534,6 +582,9 @@ static int twlreg_probe(struct platform_device *pdev) | |||
| 534 | } | 582 | } |
| 535 | platform_set_drvdata(pdev, rdev); | 583 | platform_set_drvdata(pdev, rdev); |
| 536 | 584 | ||
| 585 | twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP, | ||
| 586 | info->remap); | ||
| 587 | |||
| 537 | /* NOTE: many regulators support short-circuit IRQs (presentable | 588 | /* NOTE: many regulators support short-circuit IRQs (presentable |
| 538 | * as REGULATOR_OVER_CURRENT notifications?) configured via: | 589 | * as REGULATOR_OVER_CURRENT notifications?) configured via: |
| 539 | * - SC_CONFIG | 590 | * - SC_CONFIG |
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 2eefc1a0cf08..0a6577577e8d 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
| 20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 21 | #include <linux/regulator/driver.h> | 21 | #include <linux/regulator/driver.h> |
| 22 | #include <linux/regulator/machine.h> | ||
| 23 | #include <linux/gpio.h> | ||
| 22 | 24 | ||
| 23 | #include <linux/mfd/wm831x/core.h> | 25 | #include <linux/mfd/wm831x/core.h> |
| 24 | #include <linux/mfd/wm831x/regulator.h> | 26 | #include <linux/mfd/wm831x/regulator.h> |
| @@ -39,6 +41,7 @@ | |||
| 39 | #define WM831X_DCDC_CONTROL_2 1 | 41 | #define WM831X_DCDC_CONTROL_2 1 |
| 40 | #define WM831X_DCDC_ON_CONFIG 2 | 42 | #define WM831X_DCDC_ON_CONFIG 2 |
| 41 | #define WM831X_DCDC_SLEEP_CONTROL 3 | 43 | #define WM831X_DCDC_SLEEP_CONTROL 3 |
| 44 | #define WM831X_DCDC_DVS_CONTROL 4 | ||
| 42 | 45 | ||
| 43 | /* | 46 | /* |
| 44 | * Shared | 47 | * Shared |
| @@ -50,6 +53,10 @@ struct wm831x_dcdc { | |||
| 50 | int base; | 53 | int base; |
| 51 | struct wm831x *wm831x; | 54 | struct wm831x *wm831x; |
| 52 | struct regulator_dev *regulator; | 55 | struct regulator_dev *regulator; |
| 56 | int dvs_gpio; | ||
| 57 | int dvs_gpio_state; | ||
| 58 | int on_vsel; | ||
| 59 | int dvs_vsel; | ||
| 53 | }; | 60 | }; |
| 54 | 61 | ||
| 55 | static int wm831x_dcdc_is_enabled(struct regulator_dev *rdev) | 62 | static int wm831x_dcdc_is_enabled(struct regulator_dev *rdev) |
| @@ -240,11 +247,9 @@ static int wm831x_buckv_list_voltage(struct regulator_dev *rdev, | |||
| 240 | return -EINVAL; | 247 | return -EINVAL; |
| 241 | } | 248 | } |
| 242 | 249 | ||
| 243 | static int wm831x_buckv_set_voltage_int(struct regulator_dev *rdev, int reg, | 250 | static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev, |
| 244 | int min_uV, int max_uV) | 251 | int min_uV, int max_uV) |
| 245 | { | 252 | { |
| 246 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | ||
| 247 | struct wm831x *wm831x = dcdc->wm831x; | ||
| 248 | u16 vsel; | 253 | u16 vsel; |
| 249 | 254 | ||
| 250 | if (min_uV < 600000) | 255 | if (min_uV < 600000) |
| @@ -257,39 +262,126 @@ static int wm831x_buckv_set_voltage_int(struct regulator_dev *rdev, int reg, | |||
| 257 | if (wm831x_buckv_list_voltage(rdev, vsel) > max_uV) | 262 | if (wm831x_buckv_list_voltage(rdev, vsel) > max_uV) |
| 258 | return -EINVAL; | 263 | return -EINVAL; |
| 259 | 264 | ||
| 260 | return wm831x_set_bits(wm831x, reg, WM831X_DC1_ON_VSEL_MASK, vsel); | 265 | return vsel; |
| 266 | } | ||
| 267 | |||
| 268 | static int wm831x_buckv_select_max_voltage(struct regulator_dev *rdev, | ||
| 269 | int min_uV, int max_uV) | ||
| 270 | { | ||
| 271 | u16 vsel; | ||
| 272 | |||
| 273 | if (max_uV < 600000 || max_uV > 1800000) | ||
| 274 | return -EINVAL; | ||
| 275 | |||
| 276 | vsel = ((max_uV - 600000) / 12500) + 8; | ||
| 277 | |||
| 278 | if (wm831x_buckv_list_voltage(rdev, vsel) < min_uV || | ||
| 279 | wm831x_buckv_list_voltage(rdev, vsel) < max_uV) | ||
| 280 | return -EINVAL; | ||
| 281 | |||
| 282 | return vsel; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) | ||
| 286 | { | ||
| 287 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | ||
| 288 | |||
| 289 | if (state == dcdc->dvs_gpio_state) | ||
| 290 | return 0; | ||
| 291 | |||
| 292 | dcdc->dvs_gpio_state = state; | ||
| 293 | gpio_set_value(dcdc->dvs_gpio, state); | ||
| 294 | |||
| 295 | /* Should wait for DVS state change to be asserted if we have | ||
| 296 | * a GPIO for it, for now assume the device is configured | ||
| 297 | * for the fastest possible transition. | ||
| 298 | */ | ||
| 299 | |||
| 300 | return 0; | ||
| 261 | } | 301 | } |
| 262 | 302 | ||
| 263 | static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, | 303 | static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, |
| 264 | int min_uV, int max_uV) | 304 | int min_uV, int max_uV) |
| 265 | { | 305 | { |
| 266 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | 306 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); |
| 267 | u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG; | 307 | struct wm831x *wm831x = dcdc->wm831x; |
| 308 | int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG; | ||
| 309 | int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL; | ||
| 310 | int vsel, ret; | ||
| 311 | |||
| 312 | vsel = wm831x_buckv_select_min_voltage(rdev, min_uV, max_uV); | ||
| 313 | if (vsel < 0) | ||
| 314 | return vsel; | ||
| 315 | |||
| 316 | /* If this value is already set then do a GPIO update if we can */ | ||
| 317 | if (dcdc->dvs_gpio && dcdc->on_vsel == vsel) | ||
| 318 | return wm831x_buckv_set_dvs(rdev, 0); | ||
| 319 | |||
| 320 | if (dcdc->dvs_gpio && dcdc->dvs_vsel == vsel) | ||
| 321 | return wm831x_buckv_set_dvs(rdev, 1); | ||
| 322 | |||
| 323 | /* Always set the ON status to the minimum voltage */ | ||
| 324 | ret = wm831x_set_bits(wm831x, on_reg, WM831X_DC1_ON_VSEL_MASK, vsel); | ||
| 325 | if (ret < 0) | ||
| 326 | return ret; | ||
| 327 | dcdc->on_vsel = vsel; | ||
| 328 | |||
| 329 | if (!dcdc->dvs_gpio) | ||
| 330 | return ret; | ||
| 331 | |||
| 332 | /* Kick the voltage transition now */ | ||
| 333 | ret = wm831x_buckv_set_dvs(rdev, 0); | ||
| 334 | if (ret < 0) | ||
| 335 | return ret; | ||
| 336 | |||
| 337 | /* Set the high voltage as the DVS voltage. This is optimised | ||
| 338 | * for CPUfreq usage, most processors will keep the maximum | ||
| 339 | * voltage constant and lower the minimum with the frequency. */ | ||
| 340 | vsel = wm831x_buckv_select_max_voltage(rdev, min_uV, max_uV); | ||
| 341 | if (vsel < 0) { | ||
| 342 | /* This should never happen - at worst the same vsel | ||
| 343 | * should be chosen */ | ||
| 344 | WARN_ON(vsel < 0); | ||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | /* Don't bother if it's the same VSEL we're already using */ | ||
| 349 | if (vsel == dcdc->on_vsel) | ||
| 350 | return 0; | ||
| 268 | 351 | ||
| 269 | return wm831x_buckv_set_voltage_int(rdev, reg, min_uV, max_uV); | 352 | ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, vsel); |
| 353 | if (ret == 0) | ||
| 354 | dcdc->dvs_vsel = vsel; | ||
| 355 | else | ||
| 356 | dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n", | ||
| 357 | ret); | ||
| 358 | |||
| 359 | return 0; | ||
| 270 | } | 360 | } |
| 271 | 361 | ||
| 272 | static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev, | 362 | static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev, |
| 273 | int uV) | 363 | int uV) |
| 274 | { | 364 | { |
| 275 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | 365 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); |
| 366 | struct wm831x *wm831x = dcdc->wm831x; | ||
| 276 | u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; | 367 | u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; |
| 368 | int vsel; | ||
| 369 | |||
| 370 | vsel = wm831x_buckv_select_min_voltage(rdev, uV, uV); | ||
| 371 | if (vsel < 0) | ||
| 372 | return vsel; | ||
| 277 | 373 | ||
| 278 | return wm831x_buckv_set_voltage_int(rdev, reg, uV, uV); | 374 | return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel); |
| 279 | } | 375 | } |
| 280 | 376 | ||
| 281 | static int wm831x_buckv_get_voltage(struct regulator_dev *rdev) | 377 | static int wm831x_buckv_get_voltage(struct regulator_dev *rdev) |
| 282 | { | 378 | { |
| 283 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | 379 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); |
| 284 | struct wm831x *wm831x = dcdc->wm831x; | ||
| 285 | u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG; | ||
| 286 | int val; | ||
| 287 | 380 | ||
| 288 | val = wm831x_reg_read(wm831x, reg); | 381 | if (dcdc->dvs_gpio && dcdc->dvs_gpio_state) |
| 289 | if (val < 0) | 382 | return wm831x_buckv_list_voltage(rdev, dcdc->dvs_vsel); |
| 290 | return val; | 383 | else |
| 291 | 384 | return wm831x_buckv_list_voltage(rdev, dcdc->on_vsel); | |
| 292 | return wm831x_buckv_list_voltage(rdev, val & WM831X_DC1_ON_VSEL_MASK); | ||
| 293 | } | 385 | } |
| 294 | 386 | ||
| 295 | /* Current limit options */ | 387 | /* Current limit options */ |
| @@ -346,6 +438,64 @@ static struct regulator_ops wm831x_buckv_ops = { | |||
| 346 | .set_suspend_mode = wm831x_dcdc_set_suspend_mode, | 438 | .set_suspend_mode = wm831x_dcdc_set_suspend_mode, |
| 347 | }; | 439 | }; |
| 348 | 440 | ||
| 441 | /* | ||
| 442 | * Set up DVS control. We just log errors since we can still run | ||
| 443 | * (with reduced performance) if we fail. | ||
| 444 | */ | ||
| 445 | static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, | ||
| 446 | struct wm831x_buckv_pdata *pdata) | ||
| 447 | { | ||
| 448 | struct wm831x *wm831x = dcdc->wm831x; | ||
| 449 | int ret; | ||
| 450 | u16 ctrl; | ||
| 451 | |||
| 452 | if (!pdata || !pdata->dvs_gpio) | ||
| 453 | return; | ||
| 454 | |||
| 455 | switch (pdata->dvs_control_src) { | ||
| 456 | case 1: | ||
| 457 | ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT; | ||
| 458 | break; | ||
| 459 | case 2: | ||
| 460 | ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT; | ||
| 461 | break; | ||
| 462 | default: | ||
| 463 | dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n", | ||
| 464 | pdata->dvs_control_src, dcdc->name); | ||
| 465 | return; | ||
| 466 | } | ||
| 467 | |||
| 468 | ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL, | ||
| 469 | WM831X_DC1_DVS_SRC_MASK, ctrl); | ||
| 470 | if (ret < 0) { | ||
| 471 | dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n", | ||
| 472 | dcdc->name, ret); | ||
| 473 | return; | ||
| 474 | } | ||
| 475 | |||
| 476 | ret = gpio_request(pdata->dvs_gpio, "DCDC DVS"); | ||
| 477 | if (ret < 0) { | ||
| 478 | dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", | ||
| 479 | dcdc->name, ret); | ||
| 480 | return; | ||
| 481 | } | ||
| 482 | |||
| 483 | /* gpiolib won't let us read the GPIO status so pick the higher | ||
| 484 | * of the two existing voltages so we take it as platform data. | ||
| 485 | */ | ||
| 486 | dcdc->dvs_gpio_state = pdata->dvs_init_state; | ||
| 487 | |||
| 488 | ret = gpio_direction_output(pdata->dvs_gpio, dcdc->dvs_gpio_state); | ||
| 489 | if (ret < 0) { | ||
| 490 | dev_err(wm831x->dev, "Failed to enable %s DVS GPIO: %d\n", | ||
| 491 | dcdc->name, ret); | ||
| 492 | gpio_free(pdata->dvs_gpio); | ||
| 493 | return; | ||
| 494 | } | ||
| 495 | |||
| 496 | dcdc->dvs_gpio = pdata->dvs_gpio; | ||
| 497 | } | ||
| 498 | |||
| 349 | static __devinit int wm831x_buckv_probe(struct platform_device *pdev) | 499 | static __devinit int wm831x_buckv_probe(struct platform_device *pdev) |
| 350 | { | 500 | { |
| 351 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | 501 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); |
| @@ -384,6 +534,23 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) | |||
| 384 | dcdc->desc.ops = &wm831x_buckv_ops; | 534 | dcdc->desc.ops = &wm831x_buckv_ops; |
| 385 | dcdc->desc.owner = THIS_MODULE; | 535 | dcdc->desc.owner = THIS_MODULE; |
| 386 | 536 | ||
| 537 | ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG); | ||
| 538 | if (ret < 0) { | ||
| 539 | dev_err(wm831x->dev, "Failed to read ON VSEL: %d\n", ret); | ||
| 540 | goto err; | ||
| 541 | } | ||
| 542 | dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK; | ||
| 543 | |||
| 544 | ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG); | ||
| 545 | if (ret < 0) { | ||
| 546 | dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret); | ||
| 547 | goto err; | ||
| 548 | } | ||
| 549 | dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK; | ||
| 550 | |||
| 551 | if (pdata->dcdc[id]) | ||
| 552 | wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data); | ||
| 553 | |||
| 387 | dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, | 554 | dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, |
| 388 | pdata->dcdc[id], dcdc); | 555 | pdata->dcdc[id], dcdc); |
| 389 | if (IS_ERR(dcdc->regulator)) { | 556 | if (IS_ERR(dcdc->regulator)) { |
| @@ -422,6 +589,8 @@ err_uv: | |||
| 422 | err_regulator: | 589 | err_regulator: |
| 423 | regulator_unregister(dcdc->regulator); | 590 | regulator_unregister(dcdc->regulator); |
| 424 | err: | 591 | err: |
| 592 | if (dcdc->dvs_gpio) | ||
| 593 | gpio_free(dcdc->dvs_gpio); | ||
| 425 | kfree(dcdc); | 594 | kfree(dcdc); |
| 426 | return ret; | 595 | return ret; |
| 427 | } | 596 | } |
| @@ -434,6 +603,8 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev) | |||
| 434 | wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "HC"), dcdc); | 603 | wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "HC"), dcdc); |
| 435 | wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc); | 604 | wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc); |
| 436 | regulator_unregister(dcdc->regulator); | 605 | regulator_unregister(dcdc->regulator); |
| 606 | if (dcdc->dvs_gpio) | ||
| 607 | gpio_free(dcdc->dvs_gpio); | ||
| 437 | kfree(dcdc); | 608 | kfree(dcdc); |
| 438 | 609 | ||
| 439 | return 0; | 610 | return 0; |
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 902db56ce099..61e02ac2fda3 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c | |||
| @@ -470,7 +470,7 @@ static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev) | |||
| 470 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 470 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
| 471 | struct wm831x *wm831x = ldo->wm831x; | 471 | struct wm831x *wm831x = ldo->wm831x; |
| 472 | int on_reg = ldo->base + WM831X_LDO_ON_CONTROL; | 472 | int on_reg = ldo->base + WM831X_LDO_ON_CONTROL; |
| 473 | unsigned int ret; | 473 | int ret; |
| 474 | 474 | ||
| 475 | ret = wm831x_reg_read(wm831x, on_reg); | 475 | ret = wm831x_reg_read(wm831x, on_reg); |
| 476 | if (ret < 0) | 476 | if (ret < 0) |
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h index 415c228743d5..fd322aca33ba 100644 --- a/include/linux/mfd/wm831x/pdata.h +++ b/include/linux/mfd/wm831x/pdata.h | |||
| @@ -41,6 +41,23 @@ struct wm831x_battery_pdata { | |||
| 41 | int timeout; /** Charge cycle timeout, in minutes */ | 41 | int timeout; /** Charge cycle timeout, in minutes */ |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | /** | ||
| 45 | * Configuration for the WM831x DC-DC BuckWise convertors. This | ||
| 46 | * should be passed as driver_data in the regulator_init_data. | ||
| 47 | * | ||
| 48 | * Currently all the configuration is for the fast DVS switching | ||
| 49 | * support of the devices. This allows MFPs on the device to be | ||
| 50 | * configured as an input to switch between two output voltages, | ||
| 51 | * allowing voltage transitions without the expense of an access over | ||
| 52 | * I2C or SPI buses. | ||
| 53 | */ | ||
| 54 | struct wm831x_buckv_pdata { | ||
| 55 | int dvs_gpio; /** CPU GPIO to use for DVS switching */ | ||
| 56 | int dvs_control_src; /** Hardware DVS source to use (1 or 2) */ | ||
| 57 | int dvs_init_state; /** DVS state to expect on startup */ | ||
| 58 | int dvs_state_gpio; /** CPU GPIO to use for monitoring status */ | ||
| 59 | }; | ||
| 60 | |||
| 44 | /* Sources for status LED configuration. Values are register values | 61 | /* Sources for status LED configuration. Values are register values |
| 45 | * plus 1 to allow for a zero default for preserve. | 62 | * plus 1 to allow for a zero default for preserve. |
| 46 | */ | 63 | */ |
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 490c5b37b6d7..030d92255c7a 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h | |||
| @@ -35,6 +35,8 @@ | |||
| 35 | #ifndef __LINUX_REGULATOR_CONSUMER_H_ | 35 | #ifndef __LINUX_REGULATOR_CONSUMER_H_ |
| 36 | #define __LINUX_REGULATOR_CONSUMER_H_ | 36 | #define __LINUX_REGULATOR_CONSUMER_H_ |
| 37 | 37 | ||
| 38 | #include <linux/device.h> | ||
| 39 | |||
| 38 | /* | 40 | /* |
| 39 | * Regulator operating modes. | 41 | * Regulator operating modes. |
| 40 | * | 42 | * |
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 87f5f176d4ef..234a8476cba8 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h | |||
| @@ -43,16 +43,20 @@ struct regulator; | |||
| 43 | /** | 43 | /** |
| 44 | * struct regulator_state - regulator state during low power system states | 44 | * struct regulator_state - regulator state during low power system states |
| 45 | * | 45 | * |
| 46 | * This describes a regulators state during a system wide low power state. | 46 | * This describes a regulators state during a system wide low power |
| 47 | * state. One of enabled or disabled must be set for the | ||
| 48 | * configuration to be applied. | ||
| 47 | * | 49 | * |
| 48 | * @uV: Operating voltage during suspend. | 50 | * @uV: Operating voltage during suspend. |
| 49 | * @mode: Operating mode during suspend. | 51 | * @mode: Operating mode during suspend. |
| 50 | * @enabled: Enabled during suspend. | 52 | * @enabled: Enabled during suspend. |
| 53 | * @disabled: Disabled during suspend. | ||
| 51 | */ | 54 | */ |
| 52 | struct regulator_state { | 55 | struct regulator_state { |
| 53 | int uV; /* suspend voltage */ | 56 | int uV; /* suspend voltage */ |
| 54 | unsigned int mode; /* suspend regulator operating mode */ | 57 | unsigned int mode; /* suspend regulator operating mode */ |
| 55 | int enabled; /* is regulator enabled in this suspend state */ | 58 | int enabled; /* is regulator enabled in this suspend state */ |
| 59 | int disabled; /* is the regulator disbled in this suspend state */ | ||
| 56 | }; | 60 | }; |
| 57 | 61 | ||
| 58 | /** | 62 | /** |
diff --git a/include/linux/regulator/max8660.h b/include/linux/regulator/max8660.h new file mode 100644 index 000000000000..9936763621c7 --- /dev/null +++ b/include/linux/regulator/max8660.h | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* | ||
| 2 | * max8660.h -- Voltage regulation for the Maxim 8660/8661 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __LINUX_REGULATOR_MAX8660_H | ||
| 21 | #define __LINUX_REGULATOR_MAX8660_H | ||
| 22 | |||
| 23 | #include <linux/regulator/machine.h> | ||
| 24 | |||
| 25 | enum { | ||
| 26 | MAX8660_V3, | ||
| 27 | MAX8660_V4, | ||
| 28 | MAX8660_V5, | ||
| 29 | MAX8660_V6, | ||
| 30 | MAX8660_V7, | ||
| 31 | MAX8660_V_END, | ||
| 32 | }; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * max8660_subdev_data - regulator subdev data | ||
| 36 | * @id: regulator id | ||
| 37 | * @name: regulator name | ||
| 38 | * @platform_data: regulator init data | ||
| 39 | */ | ||
| 40 | struct max8660_subdev_data { | ||
| 41 | int id; | ||
| 42 | char *name; | ||
| 43 | struct regulator_init_data *platform_data; | ||
| 44 | }; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * max8660_platform_data - platform data for max8660 | ||
| 48 | * @num_subdevs: number of regulators used | ||
| 49 | * @subdevs: pointer to regulators used | ||
| 50 | * @en34_is_high: if EN34 is driven high, regulators cannot be en-/disabled. | ||
| 51 | */ | ||
| 52 | struct max8660_platform_data { | ||
| 53 | int num_subdevs; | ||
| 54 | struct max8660_subdev_data *subdevs; | ||
| 55 | unsigned en34_is_high:1; | ||
| 56 | }; | ||
| 57 | #endif | ||
