linux/drivers/regulator/cpcap-regulator.c
<<
>>
Prefs
   1/*
   2 * Motorola CPCAP PMIC regulator driver
   3 *
   4 * Based on cpcap-regulator.c from Motorola Linux kernel tree
   5 * Copyright (C) 2009-2011 Motorola, Inc.
   6 *
   7 * Rewritten for mainline kernel to use device tree and regmap
   8 * Copyright (C) 2017 Tony Lindgren <tony@atomide.com>
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License as
  12 * published by the Free Software Foundation version 2.
  13 *
  14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  15 * kind, whether express or implied; without even the implied warranty
  16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 * GNU General Public License for more details.
  18 */
  19
  20#include <linux/err.h>
  21#include <linux/module.h>
  22#include <linux/of.h>
  23#include <linux/of_platform.h>
  24#include <linux/regmap.h>
  25#include <linux/regulator/driver.h>
  26#include <linux/regulator/machine.h>
  27#include <linux/regulator/of_regulator.h>
  28#include <linux/mfd/motorola-cpcap.h>
  29
  30/*
  31 * Resource assignment register bits. These seem to control the state
  32 * idle modes adn are used at least for omap4.
  33 */
  34
  35/* CPCAP_REG_ASSIGN2 bits - Resource Assignment 2 */
  36#define CPCAP_BIT_VSDIO_SEL             BIT(15)
  37#define CPCAP_BIT_VDIG_SEL              BIT(14)
  38#define CPCAP_BIT_VCAM_SEL              BIT(13)
  39#define CPCAP_BIT_SW6_SEL               BIT(12)
  40#define CPCAP_BIT_SW5_SEL               BIT(11)
  41#define CPCAP_BIT_SW4_SEL               BIT(10)
  42#define CPCAP_BIT_SW3_SEL               BIT(9)
  43#define CPCAP_BIT_SW2_SEL               BIT(8)
  44#define CPCAP_BIT_SW1_SEL               BIT(7)
  45
  46/* CPCAP_REG_ASSIGN3 bits - Resource Assignment 3 */
  47#define CPCAP_BIT_VUSBINT2_SEL          BIT(15)
  48#define CPCAP_BIT_VUSBINT1_SEL          BIT(14)
  49#define CPCAP_BIT_VVIB_SEL              BIT(13)
  50#define CPCAP_BIT_VWLAN1_SEL            BIT(12)
  51#define CPCAP_BIT_VRF1_SEL              BIT(11)
  52#define CPCAP_BIT_VHVIO_SEL             BIT(10)
  53#define CPCAP_BIT_VDAC_SEL              BIT(9)
  54#define CPCAP_BIT_VUSB_SEL              BIT(8)
  55#define CPCAP_BIT_VSIM_SEL              BIT(7)
  56#define CPCAP_BIT_VRFREF_SEL            BIT(6)
  57#define CPCAP_BIT_VPLL_SEL              BIT(5)
  58#define CPCAP_BIT_VFUSE_SEL             BIT(4)
  59#define CPCAP_BIT_VCSI_SEL              BIT(3)
  60#define CPCAP_BIT_SPARE_14_2            BIT(2)
  61#define CPCAP_BIT_VWLAN2_SEL            BIT(1)
  62#define CPCAP_BIT_VRF2_SEL              BIT(0)
  63
  64/* CPCAP_REG_ASSIGN4 bits - Resource Assignment 4 */
  65#define CPCAP_BIT_VAUDIO_SEL            BIT(0)
  66
  67/*
  68 * Enable register bits. At least CPCAP_BIT_AUDIO_LOW_PWR is generic,
  69 * and not limited to audio regulator. Let's use the Motorola kernel
  70 * naming for now until we have a better understanding of the other
  71 * enable register bits. No idea why BIT(3) is not defined.
  72 */
  73#define CPCAP_BIT_AUDIO_LOW_PWR         BIT(6)
  74#define CPCAP_BIT_AUD_LOWPWR_SPEED      BIT(5)
  75#define CPCAP_BIT_VAUDIOPRISTBY         BIT(4)
  76#define CPCAP_BIT_VAUDIO_MODE1          BIT(2)
  77#define CPCAP_BIT_VAUDIO_MODE0          BIT(1)
  78#define CPCAP_BIT_V_AUDIO_EN            BIT(0)
  79
  80#define CPCAP_BIT_AUDIO_NORMAL_MODE     0x00
  81
  82/*
  83 * Off mode configuration bit. Used currently only by SW5 on omap4. There's
  84 * the following comment in Motorola Linux kernel tree for it:
  85 *
  86 * When set in the regulator mode, the regulator assignment will be changed
  87 * to secondary when the regulator is disabled. The mode will be set back to
  88 * primary when the regulator is turned on.
  89 */
  90#define CPCAP_REG_OFF_MODE_SEC          BIT(15)
  91
  92/*
  93 * SoC specific configuration for CPCAP regulator. There are at least three
  94 * different SoCs each with their own parameters: omap3, omap4 and tegra2.
  95 *
  96 * The assign_reg and assign_mask seem to allow toggling between primary
  97 * and secondary mode that at least omap4 uses for off mode.
  98 */
  99struct cpcap_regulator {
 100        struct regulator_desc rdesc;
 101        const u16 assign_reg;
 102        const u16 assign_mask;
 103};
 104
 105#define CPCAP_REG(_ID, reg, assignment_reg, assignment_mask, val_tbl,   \
 106                mode_mask, volt_mask, mode_val, off_val,                \
 107                volt_trans_time) {                                      \
 108        .rdesc = {                                                      \
 109                .name = #_ID,                                           \
 110                .of_match = of_match_ptr(#_ID),                         \
 111                .ops = &cpcap_regulator_ops,                            \
 112                .regulators_node = of_match_ptr("regulators"),          \
 113                .type = REGULATOR_VOLTAGE,                              \
 114                .id = CPCAP_##_ID,                                      \
 115                .owner = THIS_MODULE,                                   \
 116                .n_voltages = ARRAY_SIZE(val_tbl),                      \
 117                .volt_table = (val_tbl),                                \
 118                .vsel_reg = (reg),                                      \
 119                .vsel_mask = (volt_mask),                               \
 120                .enable_reg = (reg),                                    \
 121                .enable_mask = (mode_mask),                             \
 122                .enable_val = (mode_val),                               \
 123                .disable_val = (off_val),                               \
 124                .ramp_delay = (volt_trans_time),                        \
 125                .of_map_mode = cpcap_map_mode,                          \
 126        },                                                              \
 127        .assign_reg = (assignment_reg),                                 \
 128        .assign_mask = (assignment_mask),                               \
 129}
 130
 131struct cpcap_ddata {
 132        struct regmap *reg;
 133        struct device *dev;
 134        const struct cpcap_regulator *soc;
 135};
 136
 137enum cpcap_regulator_id {
 138        CPCAP_SW1,
 139        CPCAP_SW2,
 140        CPCAP_SW3,
 141        CPCAP_SW4,
 142        CPCAP_SW5,
 143        CPCAP_SW6,
 144        CPCAP_VCAM,
 145        CPCAP_VCSI,
 146        CPCAP_VDAC,
 147        CPCAP_VDIG,
 148        CPCAP_VFUSE,
 149        CPCAP_VHVIO,
 150        CPCAP_VSDIO,
 151        CPCAP_VPLL,
 152        CPCAP_VRF1,
 153        CPCAP_VRF2,
 154        CPCAP_VRFREF,
 155        CPCAP_VWLAN1,
 156        CPCAP_VWLAN2,
 157        CPCAP_VSIM,
 158        CPCAP_VSIMCARD,
 159        CPCAP_VVIB,
 160        CPCAP_VUSB,
 161        CPCAP_VAUDIO,
 162        CPCAP_NR_REGULATORS,
 163};
 164
 165/*
 166 * We need to also configure regulator idle mode for SoC off mode if
 167 * CPCAP_REG_OFF_MODE_SEC is set.
 168 */
 169static int cpcap_regulator_enable(struct regulator_dev *rdev)
 170{
 171        struct cpcap_regulator *regulator = rdev_get_drvdata(rdev);
 172        int error;
 173
 174        error = regulator_enable_regmap(rdev);
 175        if (error)
 176                return error;
 177
 178        if (rdev->desc->enable_val & CPCAP_REG_OFF_MODE_SEC) {
 179                error = regmap_update_bits(rdev->regmap, regulator->assign_reg,
 180                                           regulator->assign_mask,
 181                                           regulator->assign_mask);
 182                if (error)
 183                        regulator_disable_regmap(rdev);
 184        }
 185
 186        return error;
 187}
 188
 189/*
 190 * We need to also configure regulator idle mode for SoC off mode if
 191 * CPCAP_REG_OFF_MODE_SEC is set.
 192 */
 193static int cpcap_regulator_disable(struct regulator_dev *rdev)
 194{
 195        struct cpcap_regulator *regulator = rdev_get_drvdata(rdev);
 196        int error;
 197
 198        if (rdev->desc->enable_val & CPCAP_REG_OFF_MODE_SEC) {
 199                error = regmap_update_bits(rdev->regmap, regulator->assign_reg,
 200                                           regulator->assign_mask, 0);
 201                if (error)
 202                        return error;
 203        }
 204
 205        error = regulator_disable_regmap(rdev);
 206        if (error && (rdev->desc->enable_val & CPCAP_REG_OFF_MODE_SEC)) {
 207                regmap_update_bits(rdev->regmap, regulator->assign_reg,
 208                                   regulator->assign_mask,
 209                                   regulator->assign_mask);
 210        }
 211
 212        return error;
 213}
 214
 215static unsigned int cpcap_map_mode(unsigned int mode)
 216{
 217        switch (mode) {
 218        case CPCAP_BIT_AUDIO_NORMAL_MODE:
 219                return REGULATOR_MODE_NORMAL;
 220        case CPCAP_BIT_AUDIO_LOW_PWR:
 221                return REGULATOR_MODE_STANDBY;
 222        default:
 223                return REGULATOR_MODE_INVALID;
 224        }
 225}
 226
 227static unsigned int cpcap_regulator_get_mode(struct regulator_dev *rdev)
 228{
 229        int value;
 230
 231        regmap_read(rdev->regmap, rdev->desc->enable_reg, &value);
 232
 233        if (value & CPCAP_BIT_AUDIO_LOW_PWR)
 234                return REGULATOR_MODE_STANDBY;
 235
 236        return REGULATOR_MODE_NORMAL;
 237}
 238
 239static int cpcap_regulator_set_mode(struct regulator_dev *rdev,
 240                                    unsigned int mode)
 241{
 242        int value;
 243
 244        switch (mode) {
 245        case REGULATOR_MODE_NORMAL:
 246                value = CPCAP_BIT_AUDIO_NORMAL_MODE;
 247                break;
 248        case REGULATOR_MODE_STANDBY:
 249                value = CPCAP_BIT_AUDIO_LOW_PWR;
 250                break;
 251        default:
 252                return -EINVAL;
 253        }
 254
 255        return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
 256                                  CPCAP_BIT_AUDIO_LOW_PWR, value);
 257}
 258
 259static const struct regulator_ops cpcap_regulator_ops = {
 260        .enable = cpcap_regulator_enable,
 261        .disable = cpcap_regulator_disable,
 262        .is_enabled = regulator_is_enabled_regmap,
 263        .list_voltage = regulator_list_voltage_table,
 264        .map_voltage = regulator_map_voltage_iterate,
 265        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 266        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 267        .get_mode = cpcap_regulator_get_mode,
 268        .set_mode = cpcap_regulator_set_mode,
 269};
 270
 271static const unsigned int unknown_val_tbl[] = { 0, };
 272static const unsigned int sw2_sw4_val_tbl[] = { 612500, 625000, 637500,
 273                                                650000, 662500, 675000,
 274                                                687500, 700000, 712500,
 275                                                725000, 737500, 750000,
 276                                                762500, 775000, 787500,
 277                                                800000, 812500, 825000,
 278                                                837500, 850000, 862500,
 279                                                875000, 887500, 900000,
 280                                                912500, 925000, 937500,
 281                                                950000, 962500, 975000,
 282                                                987500, 1000000, 1012500,
 283                                                1025000, 1037500, 1050000,
 284                                                1062500, 1075000, 1087500,
 285                                                1100000, 1112500, 1125000,
 286                                                1137500, 1150000, 1162500,
 287                                                1175000, 1187500, 1200000,
 288                                                1212500, 1225000, 1237500,
 289                                                1250000, 1262500, 1275000,
 290                                                1287500, 1300000, 1312500,
 291                                                1325000, 1337500, 1350000,
 292                                                1362500, 1375000, 1387500,
 293                                                1400000, 1412500, 1425000,
 294                                                1437500, 1450000, 1462500, };
 295static const unsigned int sw5_val_tbl[] = { 0, 5050000, };
 296static const unsigned int vcam_val_tbl[] = { 2600000, 2700000, 2800000,
 297                                             2900000, };
 298static const unsigned int vcsi_val_tbl[] = { 1200000, 1800000, };
 299static const unsigned int vdac_val_tbl[] = { 1200000, 1500000, 1800000,
 300                                             2500000,};
 301static const unsigned int vdig_val_tbl[] = { 1200000, 1350000, 1500000,
 302                                             1875000, };
 303static const unsigned int vfuse_val_tbl[] = { 1500000, 1600000, 1700000,
 304                                              1800000, 1900000, 2000000,
 305                                              2100000, 2200000, 2300000,
 306                                              2400000, 2500000, 2600000,
 307                                              2700000, 3150000, };
 308static const unsigned int vhvio_val_tbl[] = { 2775000, };
 309static const unsigned int vsdio_val_tbl[] = { 1500000, 1600000, 1800000,
 310                                              2600000, 2700000, 2800000,
 311                                              2900000, 3000000, };
 312static const unsigned int vpll_val_tbl[] = { 1200000, 1300000, 1400000,
 313                                             1800000, };
 314/* Quirk: 2775000 is before 2500000 for vrf1 regulator */
 315static const unsigned int vrf1_val_tbl[] = { 2775000, 2500000, };
 316static const unsigned int vrf2_val_tbl[] = { 0, 2775000, };
 317static const unsigned int vrfref_val_tbl[] = { 2500000, 2775000, };
 318static const unsigned int vwlan1_val_tbl[] = { 1800000, 1900000, };
 319static const unsigned int vwlan2_val_tbl[] = { 2775000, 3000000, 3300000,
 320                                               3300000, };
 321static const unsigned int vsim_val_tbl[] = { 1800000, 2900000, };
 322static const unsigned int vsimcard_val_tbl[] = { 1800000, 2900000, };
 323static const unsigned int vvib_val_tbl[] = { 1300000, 1800000, 2000000,
 324                                             3000000, };
 325static const unsigned int vusb_val_tbl[] = { 0, 3300000, };
 326static const unsigned int vaudio_val_tbl[] = { 0, 2775000, };
 327
 328/*
 329 * SoC specific configuration for omap4. The data below is comes from Motorola
 330 * Linux kernel tree. It's basically the values of cpcap_regltr_data,
 331 * cpcap_regulator_mode_values and cpcap_regulator_off_mode_values, see
 332 * CPCAP_REG macro above.
 333 *
 334 * SW1 to SW4 and SW6 seems to be unused for mapphone. Note that VSIM and
 335 * VSIMCARD have a shared resource assignment bit.
 336 */
 337static const struct cpcap_regulator omap4_regulators[] = {
 338        CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2,
 339                  CPCAP_BIT_SW1_SEL, unknown_val_tbl,
 340                  0, 0, 0, 0, 0),
 341        CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2,
 342                  CPCAP_BIT_SW2_SEL, unknown_val_tbl,
 343                  0, 0, 0, 0, 0),
 344        CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2,
 345                  CPCAP_BIT_SW3_SEL, unknown_val_tbl,
 346                  0, 0, 0, 0, 0),
 347        CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2,
 348                  CPCAP_BIT_SW4_SEL, unknown_val_tbl,
 349                  0, 0, 0, 0, 0),
 350        CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2,
 351                  CPCAP_BIT_SW5_SEL, sw5_val_tbl,
 352                  0x28, 0, 0x20 | CPCAP_REG_OFF_MODE_SEC, 0, 0),
 353        CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2,
 354                  CPCAP_BIT_SW6_SEL, unknown_val_tbl,
 355                  0, 0, 0, 0, 0),
 356        CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2,
 357                  CPCAP_BIT_VCAM_SEL, vcam_val_tbl,
 358                  0x87, 0x30, 0x3, 0, 420),
 359        CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3,
 360                  CPCAP_BIT_VCSI_SEL, vcsi_val_tbl,
 361                  0x47, 0x10, 0x43, 0x41, 350),
 362        CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3,
 363                  CPCAP_BIT_VDAC_SEL, vdac_val_tbl,
 364                  0x87, 0x30, 0x3, 0, 420),
 365        CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2,
 366                  CPCAP_BIT_VDIG_SEL, vdig_val_tbl,
 367                  0x87, 0x30, 0x82, 0, 420),
 368        CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3,
 369                  CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl,
 370                  0x80, 0xf, 0x80, 0, 420),
 371        CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3,
 372                  CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl,
 373                  0x17, 0, 0, 0x12, 0),
 374        CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2,
 375                  CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl,
 376                  0x87, 0x38, 0x82, 0, 420),
 377        CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3,
 378                  CPCAP_BIT_VPLL_SEL, vpll_val_tbl,
 379                  0x43, 0x18, 0x2, 0, 420),
 380        CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3,
 381                  CPCAP_BIT_VRF1_SEL, vrf1_val_tbl,
 382                  0xac, 0x2, 0x4, 0, 10),
 383        CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3,
 384                  CPCAP_BIT_VRF2_SEL, vrf2_val_tbl,
 385                  0x23, 0x8, 0, 0, 10),
 386        CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3,
 387                  CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl,
 388                  0x23, 0x8, 0, 0, 420),
 389        CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3,
 390                  CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl,
 391                  0x47, 0x10, 0, 0, 420),
 392        CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3,
 393                  CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl,
 394                  0x20c, 0xc0, 0x20c, 0, 420),
 395        CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
 396                  0xffff, vsim_val_tbl,
 397                  0x23, 0x8, 0x3, 0, 420),
 398        CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
 399                  0xffff, vsimcard_val_tbl,
 400                  0x1e80, 0x8, 0x1e00, 0, 420),
 401        CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3,
 402                  CPCAP_BIT_VVIB_SEL, vvib_val_tbl,
 403                  0x1, 0xc, 0x1, 0, 500),
 404        CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3,
 405                  CPCAP_BIT_VUSB_SEL, vusb_val_tbl,
 406                  0x11c, 0x40, 0xc, 0, 0),
 407        CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4,
 408                  CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl,
 409                  0x16, 0x1, 0x4, 0, 0),
 410        { /* sentinel */ },
 411};
 412
 413static const struct cpcap_regulator xoom_regulators[] = {
 414        CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2,
 415                  CPCAP_BIT_SW1_SEL, unknown_val_tbl,
 416                  0, 0, 0, 0, 0),
 417        CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2,
 418                  CPCAP_BIT_SW2_SEL, sw2_sw4_val_tbl,
 419                  0xf00, 0x7f, 0x800, 0, 120),
 420        CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2,
 421                  CPCAP_BIT_SW3_SEL, unknown_val_tbl,
 422                  0, 0, 0, 0, 0),
 423        CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2,
 424                  CPCAP_BIT_SW4_SEL, sw2_sw4_val_tbl,
 425                  0xf00, 0x7f, 0x900, 0, 100),
 426        CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2,
 427                  CPCAP_BIT_SW5_SEL, sw5_val_tbl,
 428                  0x2a, 0, 0x22, 0, 0),
 429        CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2,
 430                  CPCAP_BIT_SW6_SEL, unknown_val_tbl,
 431                  0, 0, 0, 0, 0),
 432        CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2,
 433                  CPCAP_BIT_VCAM_SEL, vcam_val_tbl,
 434                  0x87, 0x30, 0x7, 0, 420),
 435        CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3,
 436                  CPCAP_BIT_VCSI_SEL, vcsi_val_tbl,
 437                  0x47, 0x10, 0x7, 0, 350),
 438        CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3,
 439                  CPCAP_BIT_VDAC_SEL, vdac_val_tbl,
 440                  0x87, 0x30, 0x3, 0, 420),
 441        CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2,
 442                  CPCAP_BIT_VDIG_SEL, vdig_val_tbl,
 443                  0x87, 0x30, 0x5, 0, 420),
 444        CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3,
 445                  CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl,
 446                  0x80, 0xf, 0x80, 0, 420),
 447        CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3,
 448                  CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl,
 449                  0x17, 0, 0x2, 0, 0),
 450        CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2,
 451                  CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl,
 452                  0x87, 0x38, 0x2, 0, 420),
 453        CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3,
 454                  CPCAP_BIT_VPLL_SEL, vpll_val_tbl,
 455                  0x43, 0x18, 0x1, 0, 420),
 456        CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3,
 457                  CPCAP_BIT_VRF1_SEL, vrf1_val_tbl,
 458                  0xac, 0x2, 0xc, 0, 10),
 459        CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3,
 460                  CPCAP_BIT_VRF2_SEL, vrf2_val_tbl,
 461                  0x23, 0x8, 0x3, 0, 10),
 462        CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3,
 463                  CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl,
 464                  0x23, 0x8, 0x3, 0, 420),
 465        CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3,
 466                  CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl,
 467                  0x47, 0x10, 0x5, 0, 420),
 468        CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3,
 469                  CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl,
 470                  0x20c, 0xc0, 0x8, 0, 420),
 471        CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
 472                  0xffff, vsim_val_tbl,
 473                  0x23, 0x8, 0x3, 0, 420),
 474        CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
 475                  0xffff, vsimcard_val_tbl,
 476                  0x1e80, 0x8, 0x1e00, 0, 420),
 477        CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3,
 478                  CPCAP_BIT_VVIB_SEL, vvib_val_tbl,
 479                  0x1, 0xc, 0, 0x1, 500),
 480        CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3,
 481                  CPCAP_BIT_VUSB_SEL, vusb_val_tbl,
 482                  0x11c, 0x40, 0xc, 0, 0),
 483        CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4,
 484                  CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl,
 485                  0x16, 0x1, 0x4, 0, 0),
 486        { /* sentinel */ },
 487};
 488
 489static const struct of_device_id cpcap_regulator_id_table[] = {
 490        {
 491                .compatible = "motorola,cpcap-regulator",
 492        },
 493        {
 494                .compatible = "motorola,mapphone-cpcap-regulator",
 495                .data = omap4_regulators,
 496        },
 497        {
 498                .compatible = "motorola,xoom-cpcap-regulator",
 499                .data = xoom_regulators,
 500        },
 501        {},
 502};
 503MODULE_DEVICE_TABLE(of, cpcap_regulator_id_table);
 504
 505static int cpcap_regulator_probe(struct platform_device *pdev)
 506{
 507        struct cpcap_ddata *ddata;
 508        const struct cpcap_regulator *match_data;
 509        struct regulator_config config;
 510        int i;
 511
 512        match_data = of_device_get_match_data(&pdev->dev);
 513        if (!match_data) {
 514                dev_err(&pdev->dev, "no configuration data found\n");
 515
 516                return -ENODEV;
 517        }
 518
 519        ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
 520        if (!ddata)
 521                return -ENOMEM;
 522
 523        ddata->reg = dev_get_regmap(pdev->dev.parent, NULL);
 524        if (!ddata->reg)
 525                return -ENODEV;
 526
 527        ddata->dev = &pdev->dev;
 528        ddata->soc = match_data;
 529        platform_set_drvdata(pdev, ddata);
 530
 531        memset(&config, 0, sizeof(config));
 532        config.dev = &pdev->dev;
 533        config.regmap = ddata->reg;
 534
 535        for (i = 0; i < CPCAP_NR_REGULATORS; i++) {
 536                const struct cpcap_regulator *regulator = &ddata->soc[i];
 537                struct regulator_dev *rdev;
 538
 539                if (!regulator->rdesc.name)
 540                        break;
 541
 542                if (regulator->rdesc.volt_table == unknown_val_tbl)
 543                        continue;
 544
 545                config.driver_data = (void *)regulator;
 546                rdev = devm_regulator_register(&pdev->dev,
 547                                               &regulator->rdesc,
 548                                               &config);
 549                if (IS_ERR(rdev)) {
 550                        dev_err(&pdev->dev, "failed to register regulator %s\n",
 551                                regulator->rdesc.name);
 552
 553                        return PTR_ERR(rdev);
 554                }
 555        }
 556
 557        return 0;
 558}
 559
 560static struct platform_driver cpcap_regulator_driver = {
 561        .probe          = cpcap_regulator_probe,
 562        .driver         = {
 563                .name   = "cpcap-regulator",
 564                .of_match_table = of_match_ptr(cpcap_regulator_id_table),
 565        },
 566};
 567
 568module_platform_driver(cpcap_regulator_driver);
 569
 570MODULE_ALIAS("platform:cpcap-regulator");
 571MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
 572MODULE_DESCRIPTION("CPCAP regulator driver");
 573MODULE_LICENSE("GPL v2");
 574