Blame view
drivers/regulator/tps6507x-regulator.c
15.6 KB
3fa5b8e08 Regulator: Add TP... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* * tps6507x-regulator.c * * Regulator driver for TPS65073 PMIC * * Copyright (C) 2009 Texas Instrument Incorporated - http://www.ti.com/ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation version 2. * * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, * whether express or implied; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> |
7d14831e2 regulator: tps650... |
25 |
#include <linux/regulator/tps6507x.h> |
3fa5b8e08 Regulator: Add TP... |
26 |
#include <linux/delay.h> |
5a0e3ad6a include cleanup: ... |
27 |
#include <linux/slab.h> |
d183fcc97 mfd: Move TPS6507... |
28 |
#include <linux/mfd/tps6507x.h> |
3fa5b8e08 Regulator: Add TP... |
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
/* DCDC's */ #define TPS6507X_DCDC_1 0 #define TPS6507X_DCDC_2 1 #define TPS6507X_DCDC_3 2 /* LDOs */ #define TPS6507X_LDO_1 3 #define TPS6507X_LDO_2 4 #define TPS6507X_MAX_REG_ID TPS6507X_LDO_2 /* Number of step-down converters available */ #define TPS6507X_NUM_DCDC 3 /* Number of LDO voltage regulators available */ #define TPS6507X_NUM_LDO 2 /* Number of total regulators available */ #define TPS6507X_NUM_REGULATOR (TPS6507X_NUM_DCDC + TPS6507X_NUM_LDO) /* Supported voltage values for regulators (in milliVolts) */ static const u16 VDCDCx_VSEL_table[] = { 725, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, 1550, 1600, 1650, 1700, 1750, 1800, 1850, 1900, 1950, 2000, 2050, 2100, 2150, 2200, 2250, 2300, 2350, 2400, 2450, 2500, 2550, 2600, 2650, 2700, 2750, 2800, 2850, 2900, 3000, 3100, 3200, 3300, }; static const u16 LDO1_VSEL_table[] = { 1000, 1100, 1200, 1250, 1300, 1350, 1400, 1500, 1600, 1800, 2500, 2750, 2800, 3000, 3100, 3300, }; static const u16 LDO2_VSEL_table[] = { 725, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, 1550, 1600, 1650, 1700, 1750, 1800, 1850, 1900, 1950, 2000, 2050, 2100, 2150, 2200, 2250, 2300, 2350, 2400, 2450, 2500, 2550, 2600, 2650, 2700, 2750, 2800, 2850, 2900, 3000, 3100, 3200, 3300, }; |
3fa5b8e08 Regulator: Add TP... |
92 93 94 95 96 97 |
struct tps_info { const char *name; unsigned min_uV; unsigned max_uV; u8 table_len; const u16 *table; |
7d14831e2 regulator: tps650... |
98 99 100 |
/* Does DCDC high or the low register defines output voltage? */ bool defdcdc_default; |
3fa5b8e08 Regulator: Add TP... |
101 |
}; |
7d14831e2 regulator: tps650... |
102 |
static struct tps_info tps6507x_pmic_regs[] = { |
31dd6a267 mfd: Add TPS6507x... |
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
{ .name = "VDCDC1", .min_uV = 725000, .max_uV = 3300000, .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), .table = VDCDCx_VSEL_table, }, { .name = "VDCDC2", .min_uV = 725000, .max_uV = 3300000, .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), .table = VDCDCx_VSEL_table, }, { .name = "VDCDC3", .min_uV = 725000, .max_uV = 3300000, .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), .table = VDCDCx_VSEL_table, }, { .name = "LDO1", .min_uV = 1000000, .max_uV = 3300000, .table_len = ARRAY_SIZE(LDO1_VSEL_table), .table = LDO1_VSEL_table, }, { .name = "LDO2", .min_uV = 725000, .max_uV = 3300000, .table_len = ARRAY_SIZE(LDO2_VSEL_table), .table = LDO2_VSEL_table, }, }; |
4ce5ba5ba regulator: tps605... |
139 |
struct tps6507x_pmic { |
3fa5b8e08 Regulator: Add TP... |
140 |
struct regulator_desc desc[TPS6507X_NUM_REGULATOR]; |
31dd6a267 mfd: Add TPS6507x... |
141 |
struct tps6507x_dev *mfd; |
3fa5b8e08 Regulator: Add TP... |
142 |
struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR]; |
7d14831e2 regulator: tps650... |
143 |
struct tps_info *info[TPS6507X_NUM_REGULATOR]; |
3fa5b8e08 Regulator: Add TP... |
144 145 |
struct mutex io_lock; }; |
4ce5ba5ba regulator: tps605... |
146 |
static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg) |
3fa5b8e08 Regulator: Add TP... |
147 |
{ |
31dd6a267 mfd: Add TPS6507x... |
148 149 150 151 152 153 154 155 156 |
u8 val; int err; err = tps->mfd->read_dev(tps->mfd, reg, 1, &val); if (err) return err; return val; |
3fa5b8e08 Regulator: Add TP... |
157 |
} |
4ce5ba5ba regulator: tps605... |
158 |
static inline int tps6507x_pmic_write(struct tps6507x_pmic *tps, u8 reg, u8 val) |
3fa5b8e08 Regulator: Add TP... |
159 |
{ |
31dd6a267 mfd: Add TPS6507x... |
160 |
return tps->mfd->write_dev(tps->mfd, reg, 1, &val); |
3fa5b8e08 Regulator: Add TP... |
161 |
} |
4ce5ba5ba regulator: tps605... |
162 |
static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) |
3fa5b8e08 Regulator: Add TP... |
163 164 165 166 |
{ int err, data; mutex_lock(&tps->io_lock); |
4ce5ba5ba regulator: tps605... |
167 |
data = tps6507x_pmic_read(tps, reg); |
3fa5b8e08 Regulator: Add TP... |
168 |
if (data < 0) { |
31dd6a267 mfd: Add TPS6507x... |
169 170 |
dev_err(tps->mfd->dev, "Read from reg 0x%x failed ", reg); |
3fa5b8e08 Regulator: Add TP... |
171 172 173 174 175 |
err = data; goto out; } data |= mask; |
4ce5ba5ba regulator: tps605... |
176 |
err = tps6507x_pmic_write(tps, reg, data); |
3fa5b8e08 Regulator: Add TP... |
177 |
if (err) |
31dd6a267 mfd: Add TPS6507x... |
178 179 |
dev_err(tps->mfd->dev, "Write for reg 0x%x failed ", reg); |
3fa5b8e08 Regulator: Add TP... |
180 181 182 183 184 |
out: mutex_unlock(&tps->io_lock); return err; } |
4ce5ba5ba regulator: tps605... |
185 |
static int tps6507x_pmic_clear_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) |
3fa5b8e08 Regulator: Add TP... |
186 187 188 189 |
{ int err, data; mutex_lock(&tps->io_lock); |
4ce5ba5ba regulator: tps605... |
190 |
data = tps6507x_pmic_read(tps, reg); |
3fa5b8e08 Regulator: Add TP... |
191 |
if (data < 0) { |
31dd6a267 mfd: Add TPS6507x... |
192 193 |
dev_err(tps->mfd->dev, "Read from reg 0x%x failed ", reg); |
3fa5b8e08 Regulator: Add TP... |
194 195 196 197 198 |
err = data; goto out; } data &= ~mask; |
4ce5ba5ba regulator: tps605... |
199 |
err = tps6507x_pmic_write(tps, reg, data); |
3fa5b8e08 Regulator: Add TP... |
200 |
if (err) |
31dd6a267 mfd: Add TPS6507x... |
201 202 |
dev_err(tps->mfd->dev, "Write for reg 0x%x failed ", reg); |
3fa5b8e08 Regulator: Add TP... |
203 204 205 206 207 |
out: mutex_unlock(&tps->io_lock); return err; } |
4ce5ba5ba regulator: tps605... |
208 |
static int tps6507x_pmic_reg_read(struct tps6507x_pmic *tps, u8 reg) |
3fa5b8e08 Regulator: Add TP... |
209 210 211 212 |
{ int data; mutex_lock(&tps->io_lock); |
4ce5ba5ba regulator: tps605... |
213 |
data = tps6507x_pmic_read(tps, reg); |
3fa5b8e08 Regulator: Add TP... |
214 |
if (data < 0) |
31dd6a267 mfd: Add TPS6507x... |
215 216 |
dev_err(tps->mfd->dev, "Read from reg 0x%x failed ", reg); |
3fa5b8e08 Regulator: Add TP... |
217 218 219 220 |
mutex_unlock(&tps->io_lock); return data; } |
4ce5ba5ba regulator: tps605... |
221 |
static int tps6507x_pmic_reg_write(struct tps6507x_pmic *tps, u8 reg, u8 val) |
3fa5b8e08 Regulator: Add TP... |
222 223 224 225 |
{ int err; mutex_lock(&tps->io_lock); |
4ce5ba5ba regulator: tps605... |
226 |
err = tps6507x_pmic_write(tps, reg, val); |
3fa5b8e08 Regulator: Add TP... |
227 |
if (err < 0) |
31dd6a267 mfd: Add TPS6507x... |
228 229 |
dev_err(tps->mfd->dev, "Write for reg 0x%x failed ", reg); |
3fa5b8e08 Regulator: Add TP... |
230 231 232 233 |
mutex_unlock(&tps->io_lock); return err; } |
4ce5ba5ba regulator: tps605... |
234 |
static int tps6507x_pmic_dcdc_is_enabled(struct regulator_dev *dev) |
3fa5b8e08 Regulator: Add TP... |
235 |
{ |
4ce5ba5ba regulator: tps605... |
236 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
237 238 239 240 241 242 243 |
int data, dcdc = rdev_get_id(dev); u8 shift; if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) return -EINVAL; shift = TPS6507X_MAX_REG_ID - dcdc; |
4ce5ba5ba regulator: tps605... |
244 |
data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1); |
3fa5b8e08 Regulator: Add TP... |
245 246 247 248 249 250 |
if (data < 0) return data; else return (data & 1<<shift) ? 1 : 0; } |
4ce5ba5ba regulator: tps605... |
251 |
static int tps6507x_pmic_ldo_is_enabled(struct regulator_dev *dev) |
3fa5b8e08 Regulator: Add TP... |
252 |
{ |
4ce5ba5ba regulator: tps605... |
253 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
254 255 256 257 258 259 260 |
int data, ldo = rdev_get_id(dev); u8 shift; if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) return -EINVAL; shift = TPS6507X_MAX_REG_ID - ldo; |
4ce5ba5ba regulator: tps605... |
261 |
data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1); |
3fa5b8e08 Regulator: Add TP... |
262 263 264 265 266 267 |
if (data < 0) return data; else return (data & 1<<shift) ? 1 : 0; } |
4ce5ba5ba regulator: tps605... |
268 |
static int tps6507x_pmic_dcdc_enable(struct regulator_dev *dev) |
3fa5b8e08 Regulator: Add TP... |
269 |
{ |
4ce5ba5ba regulator: tps605... |
270 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
271 272 273 274 275 276 277 |
int dcdc = rdev_get_id(dev); u8 shift; if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) return -EINVAL; shift = TPS6507X_MAX_REG_ID - dcdc; |
4ce5ba5ba regulator: tps605... |
278 |
return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); |
3fa5b8e08 Regulator: Add TP... |
279 |
} |
4ce5ba5ba regulator: tps605... |
280 |
static int tps6507x_pmic_dcdc_disable(struct regulator_dev *dev) |
3fa5b8e08 Regulator: Add TP... |
281 |
{ |
4ce5ba5ba regulator: tps605... |
282 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
283 284 285 286 287 288 289 |
int dcdc = rdev_get_id(dev); u8 shift; if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) return -EINVAL; shift = TPS6507X_MAX_REG_ID - dcdc; |
4ce5ba5ba regulator: tps605... |
290 291 |
return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); |
3fa5b8e08 Regulator: Add TP... |
292 |
} |
4ce5ba5ba regulator: tps605... |
293 |
static int tps6507x_pmic_ldo_enable(struct regulator_dev *dev) |
3fa5b8e08 Regulator: Add TP... |
294 |
{ |
4ce5ba5ba regulator: tps605... |
295 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
296 297 298 299 300 301 302 |
int ldo = rdev_get_id(dev); u8 shift; if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) return -EINVAL; shift = TPS6507X_MAX_REG_ID - ldo; |
4ce5ba5ba regulator: tps605... |
303 |
return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); |
3fa5b8e08 Regulator: Add TP... |
304 |
} |
4ce5ba5ba regulator: tps605... |
305 |
static int tps6507x_pmic_ldo_disable(struct regulator_dev *dev) |
3fa5b8e08 Regulator: Add TP... |
306 |
{ |
4ce5ba5ba regulator: tps605... |
307 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
308 309 310 311 312 313 314 |
int ldo = rdev_get_id(dev); u8 shift; if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) return -EINVAL; shift = TPS6507X_MAX_REG_ID - ldo; |
4ce5ba5ba regulator: tps605... |
315 316 |
return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); |
3fa5b8e08 Regulator: Add TP... |
317 |
} |
4ce5ba5ba regulator: tps605... |
318 |
static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev) |
3fa5b8e08 Regulator: Add TP... |
319 |
{ |
4ce5ba5ba regulator: tps605... |
320 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
321 322 323 324 325 326 327 328 |
int data, dcdc = rdev_get_id(dev); u8 reg; switch (dcdc) { case TPS6507X_DCDC_1: reg = TPS6507X_REG_DEFDCDC1; break; case TPS6507X_DCDC_2: |
7d14831e2 regulator: tps650... |
329 330 331 332 |
if (tps->info[dcdc]->defdcdc_default) reg = TPS6507X_REG_DEFDCDC2_HIGH; else reg = TPS6507X_REG_DEFDCDC2_LOW; |
3fa5b8e08 Regulator: Add TP... |
333 334 |
break; case TPS6507X_DCDC_3: |
7d14831e2 regulator: tps650... |
335 336 337 338 |
if (tps->info[dcdc]->defdcdc_default) reg = TPS6507X_REG_DEFDCDC3_HIGH; else reg = TPS6507X_REG_DEFDCDC3_LOW; |
3fa5b8e08 Regulator: Add TP... |
339 340 341 342 |
break; default: return -EINVAL; } |
4ce5ba5ba regulator: tps605... |
343 |
data = tps6507x_pmic_reg_read(tps, reg); |
3fa5b8e08 Regulator: Add TP... |
344 345 346 347 348 349 |
if (data < 0) return data; data &= TPS6507X_DEFDCDCX_DCDC_MASK; return tps->info[dcdc]->table[data] * 1000; } |
4ce5ba5ba regulator: tps605... |
350 |
static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev, |
3a93f2a9f regulator: Report... |
351 352 |
int min_uV, int max_uV, unsigned *selector) |
3fa5b8e08 Regulator: Add TP... |
353 |
{ |
4ce5ba5ba regulator: tps605... |
354 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
355 356 357 358 359 360 361 362 |
int data, vsel, dcdc = rdev_get_id(dev); u8 reg; switch (dcdc) { case TPS6507X_DCDC_1: reg = TPS6507X_REG_DEFDCDC1; break; case TPS6507X_DCDC_2: |
7d14831e2 regulator: tps650... |
363 364 365 366 |
if (tps->info[dcdc]->defdcdc_default) reg = TPS6507X_REG_DEFDCDC2_HIGH; else reg = TPS6507X_REG_DEFDCDC2_LOW; |
3fa5b8e08 Regulator: Add TP... |
367 368 |
break; case TPS6507X_DCDC_3: |
7d14831e2 regulator: tps650... |
369 370 371 372 |
if (tps->info[dcdc]->defdcdc_default) reg = TPS6507X_REG_DEFDCDC3_HIGH; else reg = TPS6507X_REG_DEFDCDC3_LOW; |
3fa5b8e08 Regulator: Add TP... |
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
break; default: return -EINVAL; } if (min_uV < tps->info[dcdc]->min_uV || min_uV > tps->info[dcdc]->max_uV) return -EINVAL; if (max_uV < tps->info[dcdc]->min_uV || max_uV > tps->info[dcdc]->max_uV) return -EINVAL; for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) { int mV = tps->info[dcdc]->table[vsel]; int uV = mV * 1000; /* Break at the first in-range value */ if (min_uV <= uV && uV <= max_uV) break; } /* write to the register in case we found a match */ if (vsel == tps->info[dcdc]->table_len) return -EINVAL; |
3a93f2a9f regulator: Report... |
397 |
*selector = vsel; |
4ce5ba5ba regulator: tps605... |
398 |
data = tps6507x_pmic_reg_read(tps, reg); |
3fa5b8e08 Regulator: Add TP... |
399 400 401 402 403 |
if (data < 0) return data; data &= ~TPS6507X_DEFDCDCX_DCDC_MASK; data |= vsel; |
4ce5ba5ba regulator: tps605... |
404 |
return tps6507x_pmic_reg_write(tps, reg, data); |
3fa5b8e08 Regulator: Add TP... |
405 |
} |
4ce5ba5ba regulator: tps605... |
406 |
static int tps6507x_pmic_ldo_get_voltage(struct regulator_dev *dev) |
3fa5b8e08 Regulator: Add TP... |
407 |
{ |
4ce5ba5ba regulator: tps605... |
408 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
409 410 411 412 413 414 415 416 417 418 419 420 |
int data, ldo = rdev_get_id(dev); u8 reg, mask; if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) return -EINVAL; else { reg = (ldo == TPS6507X_LDO_1 ? TPS6507X_REG_LDO_CTRL1 : TPS6507X_REG_DEFLDO2); mask = (ldo == TPS6507X_LDO_1 ? TPS6507X_REG_LDO_CTRL1_LDO1_MASK : TPS6507X_REG_DEFLDO2_LDO2_MASK); } |
4ce5ba5ba regulator: tps605... |
421 |
data = tps6507x_pmic_reg_read(tps, reg); |
3fa5b8e08 Regulator: Add TP... |
422 423 424 425 426 427 |
if (data < 0) return data; data &= mask; return tps->info[ldo]->table[data] * 1000; } |
4ce5ba5ba regulator: tps605... |
428 |
static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev, |
3a93f2a9f regulator: Report... |
429 430 |
int min_uV, int max_uV, unsigned *selector) |
3fa5b8e08 Regulator: Add TP... |
431 |
{ |
4ce5ba5ba regulator: tps605... |
432 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 |
int data, vsel, ldo = rdev_get_id(dev); u8 reg, mask; if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) return -EINVAL; else { reg = (ldo == TPS6507X_LDO_1 ? TPS6507X_REG_LDO_CTRL1 : TPS6507X_REG_DEFLDO2); mask = (ldo == TPS6507X_LDO_1 ? TPS6507X_REG_LDO_CTRL1_LDO1_MASK : TPS6507X_REG_DEFLDO2_LDO2_MASK); } if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV) return -EINVAL; if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV) return -EINVAL; for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) { int mV = tps->info[ldo]->table[vsel]; int uV = mV * 1000; /* Break at the first in-range value */ if (min_uV <= uV && uV <= max_uV) break; } if (vsel == tps->info[ldo]->table_len) return -EINVAL; |
3a93f2a9f regulator: Report... |
462 |
*selector = vsel; |
4ce5ba5ba regulator: tps605... |
463 |
data = tps6507x_pmic_reg_read(tps, reg); |
3fa5b8e08 Regulator: Add TP... |
464 465 466 467 468 |
if (data < 0) return data; data &= ~mask; data |= vsel; |
4ce5ba5ba regulator: tps605... |
469 |
return tps6507x_pmic_reg_write(tps, reg, data); |
3fa5b8e08 Regulator: Add TP... |
470 |
} |
4ce5ba5ba regulator: tps605... |
471 |
static int tps6507x_pmic_dcdc_list_voltage(struct regulator_dev *dev, |
3fa5b8e08 Regulator: Add TP... |
472 473 |
unsigned selector) { |
4ce5ba5ba regulator: tps605... |
474 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
475 476 477 478 479 480 481 482 483 484 |
int dcdc = rdev_get_id(dev); if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) return -EINVAL; if (selector >= tps->info[dcdc]->table_len) return -EINVAL; else return tps->info[dcdc]->table[selector] * 1000; } |
4ce5ba5ba regulator: tps605... |
485 |
static int tps6507x_pmic_ldo_list_voltage(struct regulator_dev *dev, |
3fa5b8e08 Regulator: Add TP... |
486 487 |
unsigned selector) { |
4ce5ba5ba regulator: tps605... |
488 |
struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
3fa5b8e08 Regulator: Add TP... |
489 490 491 492 493 494 495 496 497 498 499 500 |
int ldo = rdev_get_id(dev); if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) return -EINVAL; if (selector >= tps->info[ldo]->table_len) return -EINVAL; else return tps->info[ldo]->table[selector] * 1000; } /* Operations permitted on VDCDCx */ |
4ce5ba5ba regulator: tps605... |
501 502 503 504 505 506 507 |
static struct regulator_ops tps6507x_pmic_dcdc_ops = { .is_enabled = tps6507x_pmic_dcdc_is_enabled, .enable = tps6507x_pmic_dcdc_enable, .disable = tps6507x_pmic_dcdc_disable, .get_voltage = tps6507x_pmic_dcdc_get_voltage, .set_voltage = tps6507x_pmic_dcdc_set_voltage, .list_voltage = tps6507x_pmic_dcdc_list_voltage, |
3fa5b8e08 Regulator: Add TP... |
508 509 510 |
}; /* Operations permitted on LDOx */ |
4ce5ba5ba regulator: tps605... |
511 512 513 514 515 516 517 |
static struct regulator_ops tps6507x_pmic_ldo_ops = { .is_enabled = tps6507x_pmic_ldo_is_enabled, .enable = tps6507x_pmic_ldo_enable, .disable = tps6507x_pmic_ldo_disable, .get_voltage = tps6507x_pmic_ldo_get_voltage, .set_voltage = tps6507x_pmic_ldo_set_voltage, .list_voltage = tps6507x_pmic_ldo_list_voltage, |
3fa5b8e08 Regulator: Add TP... |
518 |
}; |
31dd6a267 mfd: Add TPS6507x... |
519 520 |
static __devinit int tps6507x_pmic_probe(struct platform_device *pdev) |
3fa5b8e08 Regulator: Add TP... |
521 |
{ |
31dd6a267 mfd: Add TPS6507x... |
522 |
struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); |
7d14831e2 regulator: tps650... |
523 |
struct tps_info *info = &tps6507x_pmic_regs[0]; |
3fa5b8e08 Regulator: Add TP... |
524 525 |
struct regulator_init_data *init_data; struct regulator_dev *rdev; |
4ce5ba5ba regulator: tps605... |
526 |
struct tps6507x_pmic *tps; |
0bc20bba3 mfd: Add tps6507x... |
527 |
struct tps6507x_board *tps_board; |
3fa5b8e08 Regulator: Add TP... |
528 |
int i; |
56c23492b Regulators: tps65... |
529 |
int error; |
3fa5b8e08 Regulator: Add TP... |
530 |
|
3fa5b8e08 Regulator: Add TP... |
531 |
/** |
0bc20bba3 mfd: Add tps6507x... |
532 533 534 |
* tps_board points to pmic related constants * coming from the board-evm file. */ |
31dd6a267 mfd: Add TPS6507x... |
535 |
tps_board = dev_get_platdata(tps6507x_dev->dev); |
0bc20bba3 mfd: Add tps6507x... |
536 537 538 539 |
if (!tps_board) return -EINVAL; /** |
3fa5b8e08 Regulator: Add TP... |
540 541 542 |
* init_data points to array of regulator_init structures * coming from the board-evm file. */ |
0bc20bba3 mfd: Add tps6507x... |
543 |
init_data = tps_board->tps6507x_pmic_init_data; |
3fa5b8e08 Regulator: Add TP... |
544 |
if (!init_data) |
0bc20bba3 mfd: Add tps6507x... |
545 |
return -EINVAL; |
3fa5b8e08 Regulator: Add TP... |
546 547 548 549 550 551 552 553 |
tps = kzalloc(sizeof(*tps), GFP_KERNEL); if (!tps) return -ENOMEM; mutex_init(&tps->io_lock); /* common for all regulators */ |
31dd6a267 mfd: Add TPS6507x... |
554 |
tps->mfd = tps6507x_dev; |
3fa5b8e08 Regulator: Add TP... |
555 556 557 558 |
for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) { /* Register the regulators */ tps->info[i] = info; |
7d14831e2 regulator: tps650... |
559 560 561 562 563 |
if (init_data->driver_data) { struct tps6507x_reg_platform_data *data = init_data->driver_data; tps->info[i]->defdcdc_default = data->defdcdc_default; } |
3fa5b8e08 Regulator: Add TP... |
564 |
tps->desc[i].name = info->name; |
77fa44d0e regulator: Fix de... |
565 |
tps->desc[i].id = i; |
0fcdb109a regulator: tps650... |
566 |
tps->desc[i].n_voltages = info->table_len; |
3fa5b8e08 Regulator: Add TP... |
567 |
tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? |
4ce5ba5ba regulator: tps605... |
568 |
&tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops); |
3fa5b8e08 Regulator: Add TP... |
569 570 571 572 |
tps->desc[i].type = REGULATOR_VOLTAGE; tps->desc[i].owner = THIS_MODULE; rdev = regulator_register(&tps->desc[i], |
2c043bcbf regulator: pass a... |
573 |
tps6507x_dev->dev, init_data, tps, NULL); |
3fa5b8e08 Regulator: Add TP... |
574 |
if (IS_ERR(rdev)) { |
31dd6a267 mfd: Add TPS6507x... |
575 576 577 578 |
dev_err(tps6507x_dev->dev, "failed to register %s regulator ", pdev->name); |
56c23492b Regulators: tps65... |
579 580 |
error = PTR_ERR(rdev); goto fail; |
3fa5b8e08 Regulator: Add TP... |
581 582 583 584 585 |
} /* Save regulator for cleanup */ tps->rdev[i] = rdev; } |
31dd6a267 mfd: Add TPS6507x... |
586 |
tps6507x_dev->pmic = tps; |
d7399fa88 regulator: tps650... |
587 |
platform_set_drvdata(pdev, tps6507x_dev); |
3fa5b8e08 Regulator: Add TP... |
588 589 |
return 0; |
56c23492b Regulators: tps65... |
590 591 592 593 594 595 596 |
fail: while (--i >= 0) regulator_unregister(tps->rdev[i]); kfree(tps); return error; |
3fa5b8e08 Regulator: Add TP... |
597 |
} |
31dd6a267 mfd: Add TPS6507x... |
598 |
static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) |
3fa5b8e08 Regulator: Add TP... |
599 |
{ |
31dd6a267 mfd: Add TPS6507x... |
600 601 |
struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); struct tps6507x_pmic *tps = tps6507x_dev->pmic; |
3fa5b8e08 Regulator: Add TP... |
602 603 604 605 |
int i; for (i = 0; i < TPS6507X_NUM_REGULATOR; i++) regulator_unregister(tps->rdev[i]); |
3fa5b8e08 Regulator: Add TP... |
606 607 608 609 |
kfree(tps); return 0; } |
31dd6a267 mfd: Add TPS6507x... |
610 |
static struct platform_driver tps6507x_pmic_driver = { |
3fa5b8e08 Regulator: Add TP... |
611 |
.driver = { |
31dd6a267 mfd: Add TPS6507x... |
612 |
.name = "tps6507x-pmic", |
3fa5b8e08 Regulator: Add TP... |
613 614 |
.owner = THIS_MODULE, }, |
4ce5ba5ba regulator: tps605... |
615 616 |
.probe = tps6507x_pmic_probe, .remove = __devexit_p(tps6507x_pmic_remove), |
3fa5b8e08 Regulator: Add TP... |
617 618 619 |
}; /** |
4ce5ba5ba regulator: tps605... |
620 |
* tps6507x_pmic_init |
3fa5b8e08 Regulator: Add TP... |
621 622 623 |
* * Module init function */ |
4ce5ba5ba regulator: tps605... |
624 |
static int __init tps6507x_pmic_init(void) |
3fa5b8e08 Regulator: Add TP... |
625 |
{ |
31dd6a267 mfd: Add TPS6507x... |
626 |
return platform_driver_register(&tps6507x_pmic_driver); |
3fa5b8e08 Regulator: Add TP... |
627 |
} |
4ce5ba5ba regulator: tps605... |
628 |
subsys_initcall(tps6507x_pmic_init); |
3fa5b8e08 Regulator: Add TP... |
629 630 |
/** |
4ce5ba5ba regulator: tps605... |
631 |
* tps6507x_pmic_cleanup |
3fa5b8e08 Regulator: Add TP... |
632 633 634 |
* * Module exit function */ |
4ce5ba5ba regulator: tps605... |
635 |
static void __exit tps6507x_pmic_cleanup(void) |
3fa5b8e08 Regulator: Add TP... |
636 |
{ |
31dd6a267 mfd: Add TPS6507x... |
637 |
platform_driver_unregister(&tps6507x_pmic_driver); |
3fa5b8e08 Regulator: Add TP... |
638 |
} |
4ce5ba5ba regulator: tps605... |
639 |
module_exit(tps6507x_pmic_cleanup); |
3fa5b8e08 Regulator: Add TP... |
640 641 642 |
MODULE_AUTHOR("Texas Instruments"); MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); |
9e108d33e regulator: tps650... |
643 |
MODULE_LICENSE("GPL v2"); |
31dd6a267 mfd: Add TPS6507x... |
644 |
MODULE_ALIAS("platform:tps6507x-pmic"); |