0001
0002
0003
0004
0005
0006
0007
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
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");