Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // pv88060-regulator.c - Regulator device driver for PV88060
0004 // Copyright (C) 2015  Powerventure Semiconductor Ltd.
0005 
0006 #include <linux/err.h>
0007 #include <linux/i2c.h>
0008 #include <linux/module.h>
0009 #include <linux/init.h>
0010 #include <linux/slab.h>
0011 #include <linux/regulator/driver.h>
0012 #include <linux/regulator/machine.h>
0013 #include <linux/regmap.h>
0014 #include <linux/irq.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/regulator/of_regulator.h>
0017 #include "pv88060-regulator.h"
0018 
0019 #define PV88060_MAX_REGULATORS  14
0020 
0021 /* PV88060 REGULATOR IDs */
0022 enum {
0023     /* BUCKs */
0024     PV88060_ID_BUCK1,
0025 
0026     /* LDOs */
0027     PV88060_ID_LDO1,
0028     PV88060_ID_LDO2,
0029     PV88060_ID_LDO3,
0030     PV88060_ID_LDO4,
0031     PV88060_ID_LDO5,
0032     PV88060_ID_LDO6,
0033     PV88060_ID_LDO7,
0034 
0035     /* SWTs */
0036     PV88060_ID_SW1,
0037     PV88060_ID_SW2,
0038     PV88060_ID_SW3,
0039     PV88060_ID_SW4,
0040     PV88060_ID_SW5,
0041     PV88060_ID_SW6,
0042 };
0043 
0044 struct pv88060_regulator {
0045     struct regulator_desc desc;
0046     unsigned int conf;      /* buck configuration register */
0047 };
0048 
0049 struct pv88060 {
0050     struct device *dev;
0051     struct regmap *regmap;
0052     struct regulator_dev *rdev[PV88060_MAX_REGULATORS];
0053 };
0054 
0055 static const struct regmap_config pv88060_regmap_config = {
0056     .reg_bits = 8,
0057     .val_bits = 8,
0058 };
0059 
0060 /* Current limits array (in uA) for BUCK1
0061  * Entry indexes corresponds to register values.
0062  */
0063 
0064 static const unsigned int pv88060_buck1_limits[] = {
0065     1496000, 2393000, 3291000, 4189000
0066 };
0067 
0068 static unsigned int pv88060_buck_get_mode(struct regulator_dev *rdev)
0069 {
0070     struct pv88060_regulator *info = rdev_get_drvdata(rdev);
0071     unsigned int data;
0072     int ret, mode = 0;
0073 
0074     ret = regmap_read(rdev->regmap, info->conf, &data);
0075     if (ret < 0)
0076         return ret;
0077 
0078     switch (data & PV88060_BUCK_MODE_MASK) {
0079     case PV88060_BUCK_MODE_SYNC:
0080         mode = REGULATOR_MODE_FAST;
0081         break;
0082     case PV88060_BUCK_MODE_AUTO:
0083         mode = REGULATOR_MODE_NORMAL;
0084         break;
0085     case PV88060_BUCK_MODE_SLEEP:
0086         mode = REGULATOR_MODE_STANDBY;
0087         break;
0088     }
0089 
0090     return mode;
0091 }
0092 
0093 static int pv88060_buck_set_mode(struct regulator_dev *rdev,
0094                     unsigned int mode)
0095 {
0096     struct pv88060_regulator *info = rdev_get_drvdata(rdev);
0097     int val = 0;
0098 
0099     switch (mode) {
0100     case REGULATOR_MODE_FAST:
0101         val = PV88060_BUCK_MODE_SYNC;
0102         break;
0103     case REGULATOR_MODE_NORMAL:
0104         val = PV88060_BUCK_MODE_AUTO;
0105         break;
0106     case REGULATOR_MODE_STANDBY:
0107         val = PV88060_BUCK_MODE_SLEEP;
0108         break;
0109     default:
0110         return -EINVAL;
0111     }
0112 
0113     return regmap_update_bits(rdev->regmap, info->conf,
0114                     PV88060_BUCK_MODE_MASK, val);
0115 }
0116 
0117 static const struct regulator_ops pv88060_buck_ops = {
0118     .get_mode = pv88060_buck_get_mode,
0119     .set_mode = pv88060_buck_set_mode,
0120     .enable = regulator_enable_regmap,
0121     .disable = regulator_disable_regmap,
0122     .is_enabled = regulator_is_enabled_regmap,
0123     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0124     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0125     .list_voltage = regulator_list_voltage_linear,
0126     .set_current_limit = regulator_set_current_limit_regmap,
0127     .get_current_limit = regulator_get_current_limit_regmap,
0128 };
0129 
0130 static const struct regulator_ops pv88060_ldo_ops = {
0131     .enable = regulator_enable_regmap,
0132     .disable = regulator_disable_regmap,
0133     .is_enabled = regulator_is_enabled_regmap,
0134     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0135     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0136     .list_voltage = regulator_list_voltage_linear,
0137 };
0138 
0139 static const struct regulator_ops pv88060_sw_ops = {
0140     .enable = regulator_enable_regmap,
0141     .disable = regulator_disable_regmap,
0142     .is_enabled = regulator_is_enabled_regmap,
0143 };
0144 
0145 #define PV88060_BUCK(chip, regl_name, min, step, max, limits_array) \
0146 {\
0147     .desc   =   {\
0148         .id = chip##_ID_##regl_name,\
0149         .name = __stringify(chip##_##regl_name),\
0150         .of_match = of_match_ptr(#regl_name),\
0151         .regulators_node = of_match_ptr("regulators"),\
0152         .type = REGULATOR_VOLTAGE,\
0153         .owner = THIS_MODULE,\
0154         .ops = &pv88060_buck_ops,\
0155         .min_uV = min,\
0156         .uV_step = step,\
0157         .n_voltages = ((max) - (min))/(step) + 1,\
0158         .enable_reg = PV88060_REG_##regl_name##_CONF0,\
0159         .enable_mask = PV88060_BUCK_EN, \
0160         .vsel_reg = PV88060_REG_##regl_name##_CONF0,\
0161         .vsel_mask = PV88060_VBUCK_MASK,\
0162         .curr_table = limits_array,\
0163         .n_current_limits = ARRAY_SIZE(limits_array),\
0164         .csel_reg = PV88060_REG_##regl_name##_CONF1,\
0165         .csel_mask = PV88060_BUCK_ILIM_MASK,\
0166     },\
0167     .conf = PV88060_REG_##regl_name##_CONF1,\
0168 }
0169 
0170 #define PV88060_LDO(chip, regl_name, min, step, max) \
0171 {\
0172     .desc   =   {\
0173         .id = chip##_ID_##regl_name,\
0174         .name = __stringify(chip##_##regl_name),\
0175         .of_match = of_match_ptr(#regl_name),\
0176         .regulators_node = of_match_ptr("regulators"),\
0177         .type = REGULATOR_VOLTAGE,\
0178         .owner = THIS_MODULE,\
0179         .ops = &pv88060_ldo_ops,\
0180         .min_uV = min, \
0181         .uV_step = step, \
0182         .n_voltages = (step) ? ((max - min) / step + 1) : 1, \
0183         .enable_reg = PV88060_REG_##regl_name##_CONF, \
0184         .enable_mask = PV88060_LDO_EN, \
0185         .vsel_reg = PV88060_REG_##regl_name##_CONF, \
0186         .vsel_mask = PV88060_VLDO_MASK, \
0187     },\
0188 }
0189 
0190 #define PV88060_SW(chip, regl_name, max) \
0191 {\
0192     .desc   =   {\
0193         .id = chip##_ID_##regl_name,\
0194         .name = __stringify(chip##_##regl_name),\
0195         .of_match = of_match_ptr(#regl_name),\
0196         .regulators_node = of_match_ptr("regulators"),\
0197         .type = REGULATOR_VOLTAGE,\
0198         .owner = THIS_MODULE,\
0199         .ops = &pv88060_sw_ops,\
0200         .fixed_uV = max,\
0201         .n_voltages = 1,\
0202         .enable_reg = PV88060_REG_##regl_name##_CONF,\
0203         .enable_mask = PV88060_SW_EN,\
0204     },\
0205 }
0206 
0207 static const struct pv88060_regulator pv88060_regulator_info[] = {
0208     PV88060_BUCK(PV88060, BUCK1, 2800000, 12500, 4387500,
0209         pv88060_buck1_limits),
0210     PV88060_LDO(PV88060, LDO1, 1200000, 50000, 3350000),
0211     PV88060_LDO(PV88060, LDO2, 1200000, 50000, 3350000),
0212     PV88060_LDO(PV88060, LDO3, 1200000, 50000, 3350000),
0213     PV88060_LDO(PV88060, LDO4, 1200000, 50000, 3350000),
0214     PV88060_LDO(PV88060, LDO5, 1200000, 50000, 3350000),
0215     PV88060_LDO(PV88060, LDO6, 1200000, 50000, 3350000),
0216     PV88060_LDO(PV88060, LDO7, 1200000, 50000, 3350000),
0217     PV88060_SW(PV88060, SW1, 5000000),
0218     PV88060_SW(PV88060, SW2, 5000000),
0219     PV88060_SW(PV88060, SW3, 5000000),
0220     PV88060_SW(PV88060, SW4, 5000000),
0221     PV88060_SW(PV88060, SW5, 5000000),
0222     PV88060_SW(PV88060, SW6, 5000000),
0223 };
0224 
0225 static irqreturn_t pv88060_irq_handler(int irq, void *data)
0226 {
0227     struct pv88060 *chip = data;
0228     int i, reg_val, err, ret = IRQ_NONE;
0229 
0230     err = regmap_read(chip->regmap, PV88060_REG_EVENT_A, &reg_val);
0231     if (err < 0)
0232         goto error_i2c;
0233 
0234     if (reg_val & PV88060_E_VDD_FLT) {
0235         for (i = 0; i < PV88060_MAX_REGULATORS; i++) {
0236             if (chip->rdev[i] != NULL)
0237                 regulator_notifier_call_chain(chip->rdev[i],
0238                     REGULATOR_EVENT_UNDER_VOLTAGE,
0239                     NULL);
0240         }
0241 
0242         err = regmap_write(chip->regmap, PV88060_REG_EVENT_A,
0243             PV88060_E_VDD_FLT);
0244         if (err < 0)
0245             goto error_i2c;
0246 
0247         ret = IRQ_HANDLED;
0248     }
0249 
0250     if (reg_val & PV88060_E_OVER_TEMP) {
0251         for (i = 0; i < PV88060_MAX_REGULATORS; i++) {
0252             if (chip->rdev[i] != NULL)
0253                 regulator_notifier_call_chain(chip->rdev[i],
0254                     REGULATOR_EVENT_OVER_TEMP,
0255                     NULL);
0256         }
0257 
0258         err = regmap_write(chip->regmap, PV88060_REG_EVENT_A,
0259             PV88060_E_OVER_TEMP);
0260         if (err < 0)
0261             goto error_i2c;
0262 
0263         ret = IRQ_HANDLED;
0264     }
0265 
0266     return ret;
0267 
0268 error_i2c:
0269     dev_err(chip->dev, "I2C error : %d\n", err);
0270     return IRQ_NONE;
0271 }
0272 
0273 /*
0274  * I2C driver interface functions
0275  */
0276 static int pv88060_i2c_probe(struct i2c_client *i2c)
0277 {
0278     struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
0279     struct pv88060 *chip;
0280     struct regulator_config config = { };
0281     int error, i, ret = 0;
0282 
0283     chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88060), GFP_KERNEL);
0284     if (!chip)
0285         return -ENOMEM;
0286 
0287     chip->dev = &i2c->dev;
0288     chip->regmap = devm_regmap_init_i2c(i2c, &pv88060_regmap_config);
0289     if (IS_ERR(chip->regmap)) {
0290         error = PTR_ERR(chip->regmap);
0291         dev_err(chip->dev, "Failed to allocate register map: %d\n",
0292             error);
0293         return error;
0294     }
0295 
0296     i2c_set_clientdata(i2c, chip);
0297 
0298     if (i2c->irq != 0) {
0299         ret = regmap_write(chip->regmap, PV88060_REG_MASK_A, 0xFF);
0300         if (ret < 0) {
0301             dev_err(chip->dev,
0302                 "Failed to mask A reg: %d\n", ret);
0303             return ret;
0304         }
0305 
0306         ret = regmap_write(chip->regmap, PV88060_REG_MASK_B, 0xFF);
0307         if (ret < 0) {
0308             dev_err(chip->dev,
0309                 "Failed to mask B reg: %d\n", ret);
0310             return ret;
0311         }
0312 
0313         ret = regmap_write(chip->regmap, PV88060_REG_MASK_C, 0xFF);
0314         if (ret < 0) {
0315             dev_err(chip->dev,
0316                 "Failed to mask C reg: %d\n", ret);
0317             return ret;
0318         }
0319 
0320         ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
0321                     pv88060_irq_handler,
0322                     IRQF_TRIGGER_LOW|IRQF_ONESHOT,
0323                     "pv88060", chip);
0324         if (ret != 0) {
0325             dev_err(chip->dev, "Failed to request IRQ: %d\n",
0326                 i2c->irq);
0327             return ret;
0328         }
0329 
0330         ret = regmap_update_bits(chip->regmap, PV88060_REG_MASK_A,
0331             PV88060_M_VDD_FLT | PV88060_M_OVER_TEMP, 0);
0332         if (ret < 0) {
0333             dev_err(chip->dev,
0334                 "Failed to update mask reg: %d\n", ret);
0335             return ret;
0336         }
0337 
0338     } else {
0339         dev_warn(chip->dev, "No IRQ configured\n");
0340     }
0341 
0342     config.dev = chip->dev;
0343     config.regmap = chip->regmap;
0344 
0345     for (i = 0; i < PV88060_MAX_REGULATORS; i++) {
0346         if (init_data)
0347             config.init_data = &init_data[i];
0348 
0349         config.driver_data = (void *)&pv88060_regulator_info[i];
0350         chip->rdev[i] = devm_regulator_register(chip->dev,
0351             &pv88060_regulator_info[i].desc, &config);
0352         if (IS_ERR(chip->rdev[i])) {
0353             dev_err(chip->dev,
0354                 "Failed to register PV88060 regulator\n");
0355             return PTR_ERR(chip->rdev[i]);
0356         }
0357     }
0358 
0359     return 0;
0360 }
0361 
0362 static const struct i2c_device_id pv88060_i2c_id[] = {
0363     {"pv88060", 0},
0364     {},
0365 };
0366 MODULE_DEVICE_TABLE(i2c, pv88060_i2c_id);
0367 
0368 #ifdef CONFIG_OF
0369 static const struct of_device_id pv88060_dt_ids[] = {
0370     { .compatible = "pvs,pv88060", .data = &pv88060_i2c_id[0] },
0371     {},
0372 };
0373 MODULE_DEVICE_TABLE(of, pv88060_dt_ids);
0374 #endif
0375 
0376 static struct i2c_driver pv88060_regulator_driver = {
0377     .driver = {
0378         .name = "pv88060",
0379         .of_match_table = of_match_ptr(pv88060_dt_ids),
0380     },
0381     .probe_new = pv88060_i2c_probe,
0382     .id_table = pv88060_i2c_id,
0383 };
0384 
0385 module_i2c_driver(pv88060_regulator_driver);
0386 
0387 MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
0388 MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88060");
0389 MODULE_LICENSE("GPL");