Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * isl6271a-regulator.c
0004  *
0005  * Support for Intersil ISL6271A voltage regulator
0006  *
0007  * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/init.h>
0013 #include <linux/err.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/regulator/driver.h>
0016 #include <linux/i2c.h>
0017 #include <linux/slab.h>
0018 
0019 #define ISL6271A_VOLTAGE_MIN    850000
0020 #define ISL6271A_VOLTAGE_MAX    1600000
0021 #define ISL6271A_VOLTAGE_STEP   50000
0022 
0023 /* PMIC details */
0024 struct isl_pmic {
0025     struct i2c_client   *client;
0026     struct mutex        mtx;
0027 };
0028 
0029 static int isl6271a_get_voltage_sel(struct regulator_dev *dev)
0030 {
0031     struct isl_pmic *pmic = rdev_get_drvdata(dev);
0032     int idx;
0033 
0034     mutex_lock(&pmic->mtx);
0035 
0036     idx = i2c_smbus_read_byte(pmic->client);
0037     if (idx < 0)
0038         dev_err(&pmic->client->dev, "Error getting voltage\n");
0039 
0040     mutex_unlock(&pmic->mtx);
0041     return idx;
0042 }
0043 
0044 static int isl6271a_set_voltage_sel(struct regulator_dev *dev,
0045                     unsigned selector)
0046 {
0047     struct isl_pmic *pmic = rdev_get_drvdata(dev);
0048     int err;
0049 
0050     mutex_lock(&pmic->mtx);
0051 
0052     err = i2c_smbus_write_byte(pmic->client, selector);
0053     if (err < 0)
0054         dev_err(&pmic->client->dev, "Error setting voltage\n");
0055 
0056     mutex_unlock(&pmic->mtx);
0057     return err;
0058 }
0059 
0060 static const struct regulator_ops isl_core_ops = {
0061     .get_voltage_sel = isl6271a_get_voltage_sel,
0062     .set_voltage_sel = isl6271a_set_voltage_sel,
0063     .list_voltage   = regulator_list_voltage_linear,
0064     .map_voltage    = regulator_map_voltage_linear,
0065 };
0066 
0067 static const struct regulator_ops isl_fixed_ops = {
0068     .list_voltage   = regulator_list_voltage_linear,
0069 };
0070 
0071 static const struct regulator_desc isl_rd[] = {
0072     {
0073         .name       = "Core Buck",
0074         .id     = 0,
0075         .n_voltages = 16,
0076         .ops        = &isl_core_ops,
0077         .type       = REGULATOR_VOLTAGE,
0078         .owner      = THIS_MODULE,
0079         .min_uV     = ISL6271A_VOLTAGE_MIN,
0080         .uV_step    = ISL6271A_VOLTAGE_STEP,
0081     }, {
0082         .name       = "LDO1",
0083         .id     = 1,
0084         .n_voltages = 1,
0085         .ops        = &isl_fixed_ops,
0086         .type       = REGULATOR_VOLTAGE,
0087         .owner      = THIS_MODULE,
0088         .min_uV     = 1100000,
0089     }, {
0090         .name       = "LDO2",
0091         .id     = 2,
0092         .n_voltages = 1,
0093         .ops        = &isl_fixed_ops,
0094         .type       = REGULATOR_VOLTAGE,
0095         .owner      = THIS_MODULE,
0096         .min_uV     = 1300000,
0097     },
0098 };
0099 
0100 static int isl6271a_probe(struct i2c_client *i2c,
0101                      const struct i2c_device_id *id)
0102 {
0103     struct regulator_dev *rdev;
0104     struct regulator_config config = { };
0105     struct regulator_init_data *init_data   = dev_get_platdata(&i2c->dev);
0106     struct isl_pmic *pmic;
0107     int i;
0108 
0109     if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
0110         return -EIO;
0111 
0112     pmic = devm_kzalloc(&i2c->dev, sizeof(struct isl_pmic), GFP_KERNEL);
0113     if (!pmic)
0114         return -ENOMEM;
0115 
0116     pmic->client = i2c;
0117 
0118     mutex_init(&pmic->mtx);
0119 
0120     for (i = 0; i < 3; i++) {
0121         config.dev = &i2c->dev;
0122         if (i == 0)
0123             config.init_data = init_data;
0124         else
0125             config.init_data = NULL;
0126         config.driver_data = pmic;
0127 
0128         rdev = devm_regulator_register(&i2c->dev, &isl_rd[i], &config);
0129         if (IS_ERR(rdev)) {
0130             dev_err(&i2c->dev, "failed to register %s\n", id->name);
0131             return PTR_ERR(rdev);
0132         }
0133     }
0134 
0135     i2c_set_clientdata(i2c, pmic);
0136 
0137     return 0;
0138 }
0139 
0140 static const struct i2c_device_id isl6271a_id[] = {
0141     {.name = "isl6271a", 0 },
0142     { },
0143 };
0144 
0145 MODULE_DEVICE_TABLE(i2c, isl6271a_id);
0146 
0147 static struct i2c_driver isl6271a_i2c_driver = {
0148     .driver = {
0149         .name = "isl6271a",
0150     },
0151     .probe = isl6271a_probe,
0152     .id_table = isl6271a_id,
0153 };
0154 
0155 static int __init isl6271a_init(void)
0156 {
0157     return i2c_add_driver(&isl6271a_i2c_driver);
0158 }
0159 
0160 static void __exit isl6271a_cleanup(void)
0161 {
0162     i2c_del_driver(&isl6271a_i2c_driver);
0163 }
0164 
0165 subsys_initcall(isl6271a_init);
0166 module_exit(isl6271a_cleanup);
0167 
0168 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
0169 MODULE_DESCRIPTION("Intersil ISL6271A voltage regulator driver");
0170 MODULE_LICENSE("GPL v2");