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"); 686