root/drivers/regulator/pv88090-regulator.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pv88090_buck_get_mode
  2. pv88090_buck_set_mode
  3. pv88090_irq_handler
  4. pv88090_i2c_probe

   1 // SPDX-License-Identifier: GPL-2.0+
   2 //
   3 // pv88090-regulator.c - Regulator device driver for PV88090
   4 // Copyright (C) 2015  Powerventure Semiconductor Ltd.
   5 
   6 #include <linux/err.h>
   7 #include <linux/i2c.h>
   8 #include <linux/module.h>
   9 #include <linux/init.h>
  10 #include <linux/slab.h>
  11 #include <linux/regulator/driver.h>
  12 #include <linux/regulator/machine.h>
  13 #include <linux/regmap.h>
  14 #include <linux/irq.h>
  15 #include <linux/interrupt.h>
  16 #include <linux/regulator/of_regulator.h>
  17 #include "pv88090-regulator.h"
  18 
  19 #define PV88090_MAX_REGULATORS  5
  20 
  21 /* PV88090 REGULATOR IDs */
  22 enum {
  23         /* BUCKs */
  24         PV88090_ID_BUCK1,
  25         PV88090_ID_BUCK2,
  26         PV88090_ID_BUCK3,
  27 
  28         /* LDOs */
  29         PV88090_ID_LDO1,
  30         PV88090_ID_LDO2,
  31 };
  32 
  33 struct pv88090_regulator {
  34         struct regulator_desc desc;
  35         unsigned int conf;
  36         unsigned int conf2;
  37 };
  38 
  39 struct pv88090 {
  40         struct device *dev;
  41         struct regmap *regmap;
  42         struct regulator_dev *rdev[PV88090_MAX_REGULATORS];
  43 };
  44 
  45 struct pv88090_buck_voltage {
  46         int min_uV;
  47         int max_uV;
  48         int uV_step;
  49 };
  50 
  51 static const struct regmap_config pv88090_regmap_config = {
  52         .reg_bits = 8,
  53         .val_bits = 8,
  54 };
  55 
  56 /* Current limits array (in uA) for BUCK1, BUCK2, BUCK3.
  57  *  Entry indexes corresponds to register values.
  58  */
  59 
  60 static const unsigned int pv88090_buck1_limits[] = {
  61          220000,  440000,  660000,  880000, 1100000, 1320000, 1540000, 1760000,
  62         1980000, 2200000, 2420000, 2640000, 2860000, 3080000, 3300000, 3520000,
  63         3740000, 3960000, 4180000, 4400000, 4620000, 4840000, 5060000, 5280000,
  64         5500000, 5720000, 5940000, 6160000, 6380000, 6600000, 6820000, 7040000
  65 };
  66 
  67 static const unsigned int pv88090_buck23_limits[] = {
  68         1496000, 2393000, 3291000, 4189000
  69 };
  70 
  71 static const struct pv88090_buck_voltage pv88090_buck_vol[3] = {
  72         {
  73                 .min_uV = 600000,
  74                 .max_uV = 1393750,
  75                 .uV_step = 6250,
  76         },
  77 
  78         {
  79                 .min_uV = 1400000,
  80                 .max_uV = 2193750,
  81                 .uV_step = 6250,
  82         },
  83         {
  84                 .min_uV = 1250000,
  85                 .max_uV = 2837500,
  86                 .uV_step = 12500,
  87         },
  88 };
  89 
  90 static unsigned int pv88090_buck_get_mode(struct regulator_dev *rdev)
  91 {
  92         struct pv88090_regulator *info = rdev_get_drvdata(rdev);
  93         unsigned int data;
  94         int ret, mode = 0;
  95 
  96         ret = regmap_read(rdev->regmap, info->conf, &data);
  97         if (ret < 0)
  98                 return ret;
  99 
 100         switch (data & PV88090_BUCK1_MODE_MASK) {
 101         case PV88090_BUCK_MODE_SYNC:
 102                 mode = REGULATOR_MODE_FAST;
 103                 break;
 104         case PV88090_BUCK_MODE_AUTO:
 105                 mode = REGULATOR_MODE_NORMAL;
 106                 break;
 107         case PV88090_BUCK_MODE_SLEEP:
 108                 mode = REGULATOR_MODE_STANDBY;
 109                 break;
 110         }
 111 
 112         return mode;
 113 }
 114 
 115 static int pv88090_buck_set_mode(struct regulator_dev *rdev,
 116                                         unsigned int mode)
 117 {
 118         struct pv88090_regulator *info = rdev_get_drvdata(rdev);
 119         int val = 0;
 120 
 121         switch (mode) {
 122         case REGULATOR_MODE_FAST:
 123                 val = PV88090_BUCK_MODE_SYNC;
 124                 break;
 125         case REGULATOR_MODE_NORMAL:
 126                 val = PV88090_BUCK_MODE_AUTO;
 127                 break;
 128         case REGULATOR_MODE_STANDBY:
 129                 val = PV88090_BUCK_MODE_SLEEP;
 130                 break;
 131         default:
 132                 return -EINVAL;
 133         }
 134 
 135         return regmap_update_bits(rdev->regmap, info->conf,
 136                                         PV88090_BUCK1_MODE_MASK, val);
 137 }
 138 
 139 static const struct regulator_ops pv88090_buck_ops = {
 140         .get_mode = pv88090_buck_get_mode,
 141         .set_mode = pv88090_buck_set_mode,
 142         .enable = regulator_enable_regmap,
 143         .disable = regulator_disable_regmap,
 144         .is_enabled = regulator_is_enabled_regmap,
 145         .set_voltage_sel = regulator_set_voltage_sel_regmap,
 146         .get_voltage_sel = regulator_get_voltage_sel_regmap,
 147         .list_voltage = regulator_list_voltage_linear,
 148         .set_current_limit = regulator_set_current_limit_regmap,
 149         .get_current_limit = regulator_get_current_limit_regmap,
 150 };
 151 
 152 static const struct regulator_ops pv88090_ldo_ops = {
 153         .enable = regulator_enable_regmap,
 154         .disable = regulator_disable_regmap,
 155         .is_enabled = regulator_is_enabled_regmap,
 156         .set_voltage_sel = regulator_set_voltage_sel_regmap,
 157         .get_voltage_sel = regulator_get_voltage_sel_regmap,
 158         .list_voltage = regulator_list_voltage_linear,
 159 };
 160 
 161 #define PV88090_BUCK(chip, regl_name, min, step, max, limits_array) \
 162 {\
 163         .desc   =       {\
 164                 .id = chip##_ID_##regl_name,\
 165                 .name = __stringify(chip##_##regl_name),\
 166                 .of_match = of_match_ptr(#regl_name),\
 167                 .regulators_node = of_match_ptr("regulators"),\
 168                 .type = REGULATOR_VOLTAGE,\
 169                 .owner = THIS_MODULE,\
 170                 .ops = &pv88090_buck_ops,\
 171                 .min_uV = min, \
 172                 .uV_step = step, \
 173                 .n_voltages = ((max) - (min))/(step) + 1, \
 174                 .enable_reg = PV88090_REG_##regl_name##_CONF0, \
 175                 .enable_mask = PV88090_##regl_name##_EN, \
 176                 .vsel_reg = PV88090_REG_##regl_name##_CONF0, \
 177                 .vsel_mask = PV88090_V##regl_name##_MASK, \
 178                 .curr_table = limits_array, \
 179                 .n_current_limits = ARRAY_SIZE(limits_array), \
 180                 .csel_reg = PV88090_REG_##regl_name##_CONF1, \
 181                 .csel_mask = PV88090_##regl_name##_ILIM_MASK, \
 182         },\
 183         .conf = PV88090_REG_##regl_name##_CONF1, \
 184         .conf2 = PV88090_REG_##regl_name##_CONF2, \
 185 }
 186 
 187 #define PV88090_LDO(chip, regl_name, min, step, max) \
 188 {\
 189         .desc   =       {\
 190                 .id = chip##_ID_##regl_name,\
 191                 .name = __stringify(chip##_##regl_name),\
 192                 .of_match = of_match_ptr(#regl_name),\
 193                 .regulators_node = of_match_ptr("regulators"),\
 194                 .type = REGULATOR_VOLTAGE,\
 195                 .owner = THIS_MODULE,\
 196                 .ops = &pv88090_ldo_ops,\
 197                 .min_uV = min, \
 198                 .uV_step = step, \
 199                 .n_voltages = ((max) - (min))/(step) + 1, \
 200                 .enable_reg = PV88090_REG_##regl_name##_CONT, \
 201                 .enable_mask = PV88090_##regl_name##_EN, \
 202                 .vsel_reg = PV88090_REG_##regl_name##_CONT, \
 203                 .vsel_mask = PV88090_V##regl_name##_MASK, \
 204         },\
 205 }
 206 
 207 static struct pv88090_regulator pv88090_regulator_info[] = {
 208         PV88090_BUCK(PV88090, BUCK1, 600000, 6250, 1393750,
 209                 pv88090_buck1_limits),
 210         PV88090_BUCK(PV88090, BUCK2, 600000, 6250, 1393750,
 211                 pv88090_buck23_limits),
 212         PV88090_BUCK(PV88090, BUCK3, 600000, 6250, 1393750,
 213                 pv88090_buck23_limits),
 214         PV88090_LDO(PV88090, LDO1, 1200000, 50000, 4350000),
 215         PV88090_LDO(PV88090, LDO2,  650000, 25000, 2225000),
 216 };
 217 
 218 static irqreturn_t pv88090_irq_handler(int irq, void *data)
 219 {
 220         struct pv88090 *chip = data;
 221         int i, reg_val, err, ret = IRQ_NONE;
 222 
 223         err = regmap_read(chip->regmap, PV88090_REG_EVENT_A, &reg_val);
 224         if (err < 0)
 225                 goto error_i2c;
 226 
 227         if (reg_val & PV88090_E_VDD_FLT) {
 228                 for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
 229                         if (chip->rdev[i] != NULL) {
 230                                 regulator_lock(chip->rdev[i]);
 231                                 regulator_notifier_call_chain(chip->rdev[i],
 232                                         REGULATOR_EVENT_UNDER_VOLTAGE,
 233                                         NULL);
 234                                 regulator_unlock(chip->rdev[i]);
 235                         }
 236                 }
 237 
 238                 err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
 239                         PV88090_E_VDD_FLT);
 240                 if (err < 0)
 241                         goto error_i2c;
 242 
 243                 ret = IRQ_HANDLED;
 244         }
 245 
 246         if (reg_val & PV88090_E_OVER_TEMP) {
 247                 for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
 248                         if (chip->rdev[i] != NULL) {
 249                                 regulator_lock(chip->rdev[i]);
 250                                 regulator_notifier_call_chain(chip->rdev[i],
 251                                         REGULATOR_EVENT_OVER_TEMP,
 252                                         NULL);
 253                                 regulator_unlock(chip->rdev[i]);
 254                         }
 255                 }
 256 
 257                 err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
 258                         PV88090_E_OVER_TEMP);
 259                 if (err < 0)
 260                         goto error_i2c;
 261 
 262                 ret = IRQ_HANDLED;
 263         }
 264 
 265         return ret;
 266 
 267 error_i2c:
 268         dev_err(chip->dev, "I2C error : %d\n", err);
 269         return IRQ_NONE;
 270 }
 271 
 272 /*
 273  * I2C driver interface functions
 274  */
 275 static int pv88090_i2c_probe(struct i2c_client *i2c,
 276                 const struct i2c_device_id *id)
 277 {
 278         struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
 279         struct pv88090 *chip;
 280         struct regulator_config config = { };
 281         int error, i, ret = 0;
 282         unsigned int conf2, range, index;
 283 
 284         chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88090), GFP_KERNEL);
 285         if (!chip)
 286                 return -ENOMEM;
 287 
 288         chip->dev = &i2c->dev;
 289         chip->regmap = devm_regmap_init_i2c(i2c, &pv88090_regmap_config);
 290         if (IS_ERR(chip->regmap)) {
 291                 error = PTR_ERR(chip->regmap);
 292                 dev_err(chip->dev, "Failed to allocate register map: %d\n",
 293                         error);
 294                 return error;
 295         }
 296 
 297         i2c_set_clientdata(i2c, chip);
 298 
 299         if (i2c->irq != 0) {
 300                 ret = regmap_write(chip->regmap, PV88090_REG_MASK_A, 0xFF);
 301                 if (ret < 0) {
 302                         dev_err(chip->dev,
 303                                 "Failed to mask A reg: %d\n", ret);
 304                         return ret;
 305                 }
 306 
 307                 ret = regmap_write(chip->regmap, PV88090_REG_MASK_B, 0xFF);
 308                 if (ret < 0) {
 309                         dev_err(chip->dev,
 310                                 "Failed to mask B reg: %d\n", ret);
 311                         return ret;
 312                 }
 313 
 314                 ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
 315                                         pv88090_irq_handler,
 316                                         IRQF_TRIGGER_LOW|IRQF_ONESHOT,
 317                                         "pv88090", chip);
 318                 if (ret != 0) {
 319                         dev_err(chip->dev, "Failed to request IRQ: %d\n",
 320                                 i2c->irq);
 321                         return ret;
 322                 }
 323 
 324                 ret = regmap_update_bits(chip->regmap, PV88090_REG_MASK_A,
 325                         PV88090_M_VDD_FLT | PV88090_M_OVER_TEMP, 0);
 326                 if (ret < 0) {
 327                         dev_err(chip->dev,
 328                                 "Failed to update mask reg: %d\n", ret);
 329                         return ret;
 330                 }
 331 
 332         } else {
 333                 dev_warn(chip->dev, "No IRQ configured\n");
 334         }
 335 
 336         config.dev = chip->dev;
 337         config.regmap = chip->regmap;
 338 
 339         for (i = 0; i < PV88090_MAX_REGULATORS; i++) {
 340                 if (init_data)
 341                         config.init_data = &init_data[i];
 342 
 343                 if (i == PV88090_ID_BUCK2 || i == PV88090_ID_BUCK3) {
 344                         ret = regmap_read(chip->regmap,
 345                                 pv88090_regulator_info[i].conf2, &conf2);
 346                         if (ret < 0)
 347                                 return ret;
 348 
 349                         conf2 = (conf2 >> PV88090_BUCK_VDAC_RANGE_SHIFT) &
 350                                 PV88090_BUCK_VDAC_RANGE_MASK;
 351 
 352                         ret = regmap_read(chip->regmap,
 353                                 PV88090_REG_BUCK_FOLD_RANGE, &range);
 354                         if (ret < 0)
 355                                 return ret;
 356 
 357                         range = (range >>
 358                                  (PV88090_BUCK_VRANGE_GAIN_SHIFT + i - 1)) &
 359                                 PV88090_BUCK_VRANGE_GAIN_MASK;
 360                         index = ((range << 1) | conf2);
 361                         if (index > PV88090_ID_BUCK3) {
 362                                 dev_err(chip->dev,
 363                                         "Invalid index(%d)\n", index);
 364                                 return -EINVAL;
 365                         }
 366 
 367                         pv88090_regulator_info[i].desc.min_uV
 368                                 = pv88090_buck_vol[index].min_uV;
 369                         pv88090_regulator_info[i].desc.uV_step
 370                                 = pv88090_buck_vol[index].uV_step;
 371                         pv88090_regulator_info[i].desc.n_voltages
 372                                 = ((pv88090_buck_vol[index].max_uV)
 373                                 - (pv88090_buck_vol[index].min_uV))
 374                                 /(pv88090_buck_vol[index].uV_step) + 1;
 375                 }
 376 
 377                 config.driver_data = (void *)&pv88090_regulator_info[i];
 378                 chip->rdev[i] = devm_regulator_register(chip->dev,
 379                         &pv88090_regulator_info[i].desc, &config);
 380                 if (IS_ERR(chip->rdev[i])) {
 381                         dev_err(chip->dev,
 382                                 "Failed to register PV88090 regulator\n");
 383                         return PTR_ERR(chip->rdev[i]);
 384                 }
 385         }
 386 
 387         return 0;
 388 }
 389 
 390 static const struct i2c_device_id pv88090_i2c_id[] = {
 391         {"pv88090", 0},
 392         {},
 393 };
 394 MODULE_DEVICE_TABLE(i2c, pv88090_i2c_id);
 395 
 396 #ifdef CONFIG_OF
 397 static const struct of_device_id pv88090_dt_ids[] = {
 398         { .compatible = "pvs,pv88090", .data = &pv88090_i2c_id[0] },
 399         {},
 400 };
 401 MODULE_DEVICE_TABLE(of, pv88090_dt_ids);
 402 #endif
 403 
 404 static struct i2c_driver pv88090_regulator_driver = {
 405         .driver = {
 406                 .name = "pv88090",
 407                 .of_match_table = of_match_ptr(pv88090_dt_ids),
 408         },
 409         .probe = pv88090_i2c_probe,
 410         .id_table = pv88090_i2c_id,
 411 };
 412 
 413 module_i2c_driver(pv88090_regulator_driver);
 414 
 415 MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
 416 MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88090");
 417 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */