This source file includes following definitions.
- mcp16502_of_map_mode
- mcp16502_gpio_set_mode
- mcp16502_get_reg
- mcp16502_get_mode
- _mcp16502_set_mode
- mcp16502_set_mode
- mcp16502_get_status
- mcp16502_suspend_get_target_reg
- mcp16502_set_suspend_voltage
- mcp16502_set_suspend_mode
- mcp16502_set_suspend_enable
- mcp16502_set_suspend_disable
- mcp16502_probe
- mcp16502_suspend_noirq
- mcp16502_resume_noirq
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 #include <linux/gpio.h>
  12 #include <linux/i2c.h>
  13 #include <linux/init.h>
  14 #include <linux/kernel.h>
  15 #include <linux/module.h>
  16 #include <linux/of.h>
  17 #include <linux/regmap.h>
  18 #include <linux/regulator/driver.h>
  19 #include <linux/suspend.h>
  20 #include <linux/gpio/consumer.h>
  21 
  22 #define VDD_LOW_SEL 0x0D
  23 #define VDD_HIGH_SEL 0x3F
  24 
  25 #define MCP16502_FLT BIT(7)
  26 #define MCP16502_ENS BIT(0)
  27 
  28 
  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 #define MCP16502_BASE(i) (((i) + 1) << 4)
  58 #define MCP16502_STAT_BASE(i) ((i) + 5)
  59 
  60 #define MCP16502_OFFSET_MODE_A 0
  61 #define MCP16502_OFFSET_MODE_LPM 1
  62 #define MCP16502_OFFSET_MODE_HIB 2
  63 
  64 #define MCP16502_OPMODE_ACTIVE REGULATOR_MODE_NORMAL
  65 #define MCP16502_OPMODE_LPM REGULATOR_MODE_IDLE
  66 #define MCP16502_OPMODE_HIB REGULATOR_MODE_STANDBY
  67 
  68 #define MCP16502_MODE_AUTO_PFM 0
  69 #define MCP16502_MODE_FPWM BIT(6)
  70 
  71 #define MCP16502_VSEL 0x3F
  72 #define MCP16502_EN BIT(7)
  73 #define MCP16502_MODE BIT(6)
  74 
  75 #define MCP16502_MIN_REG 0x0
  76 #define MCP16502_MAX_REG 0x65
  77 
  78 static unsigned int mcp16502_of_map_mode(unsigned int mode)
  79 {
  80         if (mode == REGULATOR_MODE_NORMAL || mode == REGULATOR_MODE_IDLE)
  81                 return mode;
  82 
  83         return REGULATOR_MODE_INVALID;
  84 }
  85 
  86 #define MCP16502_REGULATOR(_name, _id, _ranges, _ops)                   \
  87         [_id] = {                                                       \
  88                 .name                   = _name,                        \
  89                 .regulators_node        = of_match_ptr("regulators"),   \
  90                 .id                     = _id,                          \
  91                 .ops                    = &(_ops),                      \
  92                 .type                   = REGULATOR_VOLTAGE,            \
  93                 .owner                  = THIS_MODULE,                  \
  94                 .n_voltages             = MCP16502_VSEL + 1,            \
  95                 .linear_ranges          = _ranges,                      \
  96                 .n_linear_ranges        = ARRAY_SIZE(_ranges),          \
  97                 .of_match               = of_match_ptr(_name),          \
  98                 .of_map_mode            = mcp16502_of_map_mode,         \
  99                 .vsel_reg               = (((_id) + 1) << 4),           \
 100                 .vsel_mask              = MCP16502_VSEL,                \
 101                 .enable_reg             = (((_id) + 1) << 4),           \
 102                 .enable_mask            = MCP16502_EN,                  \
 103         }
 104 
 105 enum {
 106         BUCK1 = 0,
 107         BUCK2,
 108         BUCK3,
 109         BUCK4,
 110         LDO1,
 111         LDO2,
 112         NUM_REGULATORS
 113 };
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 struct mcp16502 {
 122         struct gpio_desc *lpm;
 123 };
 124 
 125 
 126 
 127 
 128 
 129 
 130 static void mcp16502_gpio_set_mode(struct mcp16502 *mcp, int mode)
 131 {
 132         switch (mode) {
 133         case MCP16502_OPMODE_ACTIVE:
 134                 gpiod_set_value(mcp->lpm, 0);
 135                 break;
 136         case MCP16502_OPMODE_LPM:
 137         case MCP16502_OPMODE_HIB:
 138                 gpiod_set_value(mcp->lpm, 1);
 139                 break;
 140         default:
 141                 pr_err("%s: %d invalid\n", __func__, mode);
 142         }
 143 }
 144 
 145 
 146 
 147 
 148 
 149 
 150 
 151 static int mcp16502_get_reg(struct regulator_dev *rdev, int opmode)
 152 {
 153         int reg = MCP16502_BASE(rdev_get_id(rdev));
 154 
 155         switch (opmode) {
 156         case MCP16502_OPMODE_ACTIVE:
 157                 return reg + MCP16502_OFFSET_MODE_A;
 158         case MCP16502_OPMODE_LPM:
 159                 return reg + MCP16502_OFFSET_MODE_LPM;
 160         case MCP16502_OPMODE_HIB:
 161                 return reg + MCP16502_OFFSET_MODE_HIB;
 162         default:
 163                 return -EINVAL;
 164         }
 165 }
 166 
 167 
 168 
 169 
 170 
 171 
 172 
 173 
 174 
 175 
 176 static unsigned int mcp16502_get_mode(struct regulator_dev *rdev)
 177 {
 178         unsigned int val;
 179         int ret, reg;
 180 
 181         reg = mcp16502_get_reg(rdev, MCP16502_OPMODE_ACTIVE);
 182         if (reg < 0)
 183                 return reg;
 184 
 185         ret = regmap_read(rdev->regmap, reg, &val);
 186         if (ret)
 187                 return ret;
 188 
 189         switch (val & MCP16502_MODE) {
 190         case MCP16502_MODE_FPWM:
 191                 return REGULATOR_MODE_NORMAL;
 192         case MCP16502_MODE_AUTO_PFM:
 193                 return REGULATOR_MODE_IDLE;
 194         default:
 195                 return REGULATOR_MODE_INVALID;
 196         }
 197 }
 198 
 199 
 200 
 201 
 202 
 203 
 204 
 205 
 206 static int _mcp16502_set_mode(struct regulator_dev *rdev, unsigned int mode,
 207                               unsigned int op_mode)
 208 {
 209         int val;
 210         int reg;
 211 
 212         reg = mcp16502_get_reg(rdev, op_mode);
 213         if (reg < 0)
 214                 return reg;
 215 
 216         switch (mode) {
 217         case REGULATOR_MODE_NORMAL:
 218                 val = MCP16502_MODE_FPWM;
 219                 break;
 220         case REGULATOR_MODE_IDLE:
 221                 val = MCP16502_MODE_AUTO_PFM;
 222                 break;
 223         default:
 224                 return -EINVAL;
 225         }
 226 
 227         reg = regmap_update_bits(rdev->regmap, reg, MCP16502_MODE, val);
 228         return reg;
 229 }
 230 
 231 
 232 
 233 
 234 static int mcp16502_set_mode(struct regulator_dev *rdev, unsigned int mode)
 235 {
 236         return _mcp16502_set_mode(rdev, mode, MCP16502_OPMODE_ACTIVE);
 237 }
 238 
 239 
 240 
 241 
 242 static int mcp16502_get_status(struct regulator_dev *rdev)
 243 {
 244         int ret;
 245         unsigned int val;
 246 
 247         ret = regmap_read(rdev->regmap, MCP16502_STAT_BASE(rdev_get_id(rdev)),
 248                           &val);
 249         if (ret)
 250                 return ret;
 251 
 252         if (val & MCP16502_FLT)
 253                 return REGULATOR_STATUS_ERROR;
 254         else if (val & MCP16502_ENS)
 255                 return REGULATOR_STATUS_ON;
 256         else if (!(val & MCP16502_ENS))
 257                 return REGULATOR_STATUS_OFF;
 258 
 259         return REGULATOR_STATUS_UNDEFINED;
 260 }
 261 
 262 #ifdef CONFIG_SUSPEND
 263 
 264 
 265 
 266 
 267 static int mcp16502_suspend_get_target_reg(struct regulator_dev *rdev)
 268 {
 269         switch (pm_suspend_target_state) {
 270         case PM_SUSPEND_STANDBY:
 271                 return mcp16502_get_reg(rdev, MCP16502_OPMODE_LPM);
 272         case PM_SUSPEND_ON:
 273         case PM_SUSPEND_MEM:
 274                 return mcp16502_get_reg(rdev, MCP16502_OPMODE_HIB);
 275         default:
 276                 dev_err(&rdev->dev, "invalid suspend target: %d\n",
 277                         pm_suspend_target_state);
 278         }
 279 
 280         return -EINVAL;
 281 }
 282 
 283 
 284 
 285 
 286 static int mcp16502_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 287 {
 288         int sel = regulator_map_voltage_linear_range(rdev, uV, uV);
 289         int reg = mcp16502_suspend_get_target_reg(rdev);
 290 
 291         if (sel < 0)
 292                 return sel;
 293 
 294         if (reg < 0)
 295                 return reg;
 296 
 297         return regmap_update_bits(rdev->regmap, reg, MCP16502_VSEL, sel);
 298 }
 299 
 300 
 301 
 302 
 303 static int mcp16502_set_suspend_mode(struct regulator_dev *rdev,
 304                                      unsigned int mode)
 305 {
 306         switch (pm_suspend_target_state) {
 307         case PM_SUSPEND_STANDBY:
 308                 return _mcp16502_set_mode(rdev, mode, MCP16502_OPMODE_LPM);
 309         case PM_SUSPEND_ON:
 310         case PM_SUSPEND_MEM:
 311                 return _mcp16502_set_mode(rdev, mode, MCP16502_OPMODE_HIB);
 312         default:
 313                 dev_err(&rdev->dev, "invalid suspend target: %d\n",
 314                         pm_suspend_target_state);
 315         }
 316 
 317         return -EINVAL;
 318 }
 319 
 320 
 321 
 322 
 323 static int mcp16502_set_suspend_enable(struct regulator_dev *rdev)
 324 {
 325         int reg = mcp16502_suspend_get_target_reg(rdev);
 326 
 327         if (reg < 0)
 328                 return reg;
 329 
 330         return regmap_update_bits(rdev->regmap, reg, MCP16502_EN, MCP16502_EN);
 331 }
 332 
 333 
 334 
 335 
 336 static int mcp16502_set_suspend_disable(struct regulator_dev *rdev)
 337 {
 338         int reg = mcp16502_suspend_get_target_reg(rdev);
 339 
 340         if (reg < 0)
 341                 return reg;
 342 
 343         return regmap_update_bits(rdev->regmap, reg, MCP16502_EN, 0);
 344 }
 345 #endif 
 346 
 347 static const struct regulator_ops mcp16502_buck_ops = {
 348         .list_voltage                   = regulator_list_voltage_linear_range,
 349         .map_voltage                    = regulator_map_voltage_linear_range,
 350         .get_voltage_sel                = regulator_get_voltage_sel_regmap,
 351         .set_voltage_sel                = regulator_set_voltage_sel_regmap,
 352         .enable                         = regulator_enable_regmap,
 353         .disable                        = regulator_disable_regmap,
 354         .is_enabled                     = regulator_is_enabled_regmap,
 355         .get_status                     = mcp16502_get_status,
 356 
 357         .set_mode                       = mcp16502_set_mode,
 358         .get_mode                       = mcp16502_get_mode,
 359 
 360 #ifdef CONFIG_SUSPEND
 361         .set_suspend_voltage            = mcp16502_set_suspend_voltage,
 362         .set_suspend_mode               = mcp16502_set_suspend_mode,
 363         .set_suspend_enable             = mcp16502_set_suspend_enable,
 364         .set_suspend_disable            = mcp16502_set_suspend_disable,
 365 #endif 
 366 };
 367 
 368 
 369 
 370 
 371 static const struct regulator_ops mcp16502_ldo_ops = {
 372         .list_voltage                   = regulator_list_voltage_linear_range,
 373         .map_voltage                    = regulator_map_voltage_linear_range,
 374         .get_voltage_sel                = regulator_get_voltage_sel_regmap,
 375         .set_voltage_sel                = regulator_set_voltage_sel_regmap,
 376         .enable                         = regulator_enable_regmap,
 377         .disable                        = regulator_disable_regmap,
 378         .is_enabled                     = regulator_is_enabled_regmap,
 379         .get_status                     = mcp16502_get_status,
 380 
 381 #ifdef CONFIG_SUSPEND
 382         .set_suspend_voltage            = mcp16502_set_suspend_voltage,
 383         .set_suspend_enable             = mcp16502_set_suspend_enable,
 384         .set_suspend_disable            = mcp16502_set_suspend_disable,
 385 #endif 
 386 };
 387 
 388 static const struct of_device_id mcp16502_ids[] = {
 389         { .compatible = "microchip,mcp16502", },
 390         {}
 391 };
 392 MODULE_DEVICE_TABLE(of, mcp16502_ids);
 393 
 394 static const struct regulator_linear_range b1l12_ranges[] = {
 395         REGULATOR_LINEAR_RANGE(1200000, VDD_LOW_SEL, VDD_HIGH_SEL, 50000),
 396 };
 397 
 398 static const struct regulator_linear_range b234_ranges[] = {
 399         REGULATOR_LINEAR_RANGE(600000, VDD_LOW_SEL, VDD_HIGH_SEL, 25000),
 400 };
 401 
 402 static const struct regulator_desc mcp16502_desc[] = {
 403         
 404         MCP16502_REGULATOR("VDD_IO", BUCK1, b1l12_ranges, mcp16502_buck_ops),
 405         MCP16502_REGULATOR("VDD_DDR", BUCK2, b234_ranges, mcp16502_buck_ops),
 406         MCP16502_REGULATOR("VDD_CORE", BUCK3, b234_ranges, mcp16502_buck_ops),
 407         MCP16502_REGULATOR("VDD_OTHER", BUCK4, b234_ranges, mcp16502_buck_ops),
 408         MCP16502_REGULATOR("LDO1", LDO1, b1l12_ranges, mcp16502_ldo_ops),
 409         MCP16502_REGULATOR("LDO2", LDO2, b1l12_ranges, mcp16502_ldo_ops)
 410 };
 411 
 412 static const struct regmap_range mcp16502_ranges[] = {
 413         regmap_reg_range(MCP16502_MIN_REG, MCP16502_MAX_REG)
 414 };
 415 
 416 static const struct regmap_access_table mcp16502_yes_reg_table = {
 417         .yes_ranges = mcp16502_ranges,
 418         .n_yes_ranges = ARRAY_SIZE(mcp16502_ranges),
 419 };
 420 
 421 static const struct regmap_config mcp16502_regmap_config = {
 422         .reg_bits       = 8,
 423         .val_bits       = 8,
 424         .max_register   = MCP16502_MAX_REG,
 425         .cache_type     = REGCACHE_NONE,
 426         .rd_table       = &mcp16502_yes_reg_table,
 427         .wr_table       = &mcp16502_yes_reg_table,
 428 };
 429 
 430 static int mcp16502_probe(struct i2c_client *client,
 431                           const struct i2c_device_id *id)
 432 {
 433         struct regulator_config config = { };
 434         struct regulator_dev *rdev;
 435         struct device *dev;
 436         struct mcp16502 *mcp;
 437         struct regmap *rmap;
 438         int i, ret;
 439 
 440         dev = &client->dev;
 441         config.dev = dev;
 442 
 443         mcp = devm_kzalloc(dev, sizeof(*mcp), GFP_KERNEL);
 444         if (!mcp)
 445                 return -ENOMEM;
 446 
 447         rmap = devm_regmap_init_i2c(client, &mcp16502_regmap_config);
 448         if (IS_ERR(rmap)) {
 449                 ret = PTR_ERR(rmap);
 450                 dev_err(dev, "regmap init failed: %d\n", ret);
 451                 return ret;
 452         }
 453 
 454         i2c_set_clientdata(client, mcp);
 455         config.regmap = rmap;
 456         config.driver_data = mcp;
 457 
 458         mcp->lpm = devm_gpiod_get(dev, "lpm", GPIOD_OUT_LOW);
 459         if (IS_ERR(mcp->lpm)) {
 460                 dev_err(dev, "failed to get lpm pin: %ld\n", PTR_ERR(mcp->lpm));
 461                 return PTR_ERR(mcp->lpm);
 462         }
 463 
 464         for (i = 0; i < NUM_REGULATORS; i++) {
 465                 rdev = devm_regulator_register(dev, &mcp16502_desc[i], &config);
 466                 if (IS_ERR(rdev)) {
 467                         dev_err(dev,
 468                                 "failed to register %s regulator %ld\n",
 469                                 mcp16502_desc[i].name, PTR_ERR(rdev));
 470                         return PTR_ERR(rdev);
 471                 }
 472         }
 473 
 474         mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_ACTIVE);
 475 
 476         return 0;
 477 }
 478 
 479 #ifdef CONFIG_PM_SLEEP
 480 static int mcp16502_suspend_noirq(struct device *dev)
 481 {
 482         struct i2c_client *client = to_i2c_client(dev);
 483         struct mcp16502 *mcp = i2c_get_clientdata(client);
 484 
 485         mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_LPM);
 486 
 487         return 0;
 488 }
 489 
 490 static int mcp16502_resume_noirq(struct device *dev)
 491 {
 492         struct i2c_client *client = to_i2c_client(dev);
 493         struct mcp16502 *mcp = i2c_get_clientdata(client);
 494 
 495         mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_ACTIVE);
 496 
 497         return 0;
 498 }
 499 #endif
 500 
 501 #ifdef CONFIG_PM
 502 static const struct dev_pm_ops mcp16502_pm_ops = {
 503         SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mcp16502_suspend_noirq,
 504                                       mcp16502_resume_noirq)
 505 };
 506 #endif
 507 static const struct i2c_device_id mcp16502_i2c_id[] = {
 508         { "mcp16502", 0 },
 509         { }
 510 };
 511 MODULE_DEVICE_TABLE(i2c, mcp16502_i2c_id);
 512 
 513 static struct i2c_driver mcp16502_drv = {
 514         .probe          = mcp16502_probe,
 515         .driver         = {
 516                 .name   = "mcp16502-regulator",
 517                 .of_match_table = of_match_ptr(mcp16502_ids),
 518 #ifdef CONFIG_PM
 519                 .pm = &mcp16502_pm_ops,
 520 #endif
 521         },
 522         .id_table       = mcp16502_i2c_id,
 523 };
 524 
 525 module_i2c_driver(mcp16502_drv);
 526 
 527 MODULE_LICENSE("GPL v2");
 528 MODULE_DESCRIPTION("MCP16502 PMIC driver");
 529 MODULE_AUTHOR("Andrei Stefanescu andrei.stefanescu@microchip.com");