regulator: palmas: Fix warning message
[linux-2.6.git] / drivers / regulator / tps51632-regulator.c
1 /*
2  * tps51632-regulator.c -- TI tps51632
3  *
4  * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless
5  * Controller with serial VID control and DVFS.
6  *
7  * Copyright (c) 2012, NVIDIA Corporation.
8  *
9  * Author: Laxman Dewangan <ldewangan@nvidia.com>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation version 2.
14  *
15  * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
16  * whether express or implied; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23  * 02111-1307, USA
24  */
25
26 #include <linux/err.h>
27 #include <linux/i2c.h>
28 #include <linux/init.h>
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/platform_device.h>
32 #include <linux/regmap.h>
33 #include <linux/regulator/driver.h>
34 #include <linux/regulator/machine.h>
35 #include <linux/regulator/tps51632-regulator.h>
36 #include <linux/slab.h>
37
38 /* Register definitions */
39 #define TPS51632_VOLTAGE_SELECT_REG             0x0
40 #define TPS51632_VOLTAGE_BASE_REG               0x1
41 #define TPS51632_OFFSET_REG                     0x2
42 #define TPS51632_IMON_REG                       0x3
43 #define TPS51632_VMAX_REG                       0x4
44 #define TPS51632_DVFS_CONTROL_REG               0x5
45 #define TPS51632_POWER_STATE_REG                0x6
46 #define TPS51632_SLEW_REGS                      0x7
47 #define TPS51632_FAULT_REG                      0x14
48
49 #define TPS51632_MAX_REG                        0x15
50
51 #define TPS51632_VOUT_MASK              0x7F
52 #define TPS51632_VOUT_OFFSET_MASK       0x1F
53 #define TPS51632_VMAX_MASK              0x7F
54 #define TPS51632_VMAX_LOCK              0x80
55
56 /* TPS51632_DVFS_CONTROL_REG */
57 #define TPS51632_DVFS_PWMEN             0x1
58 #define TPS51632_DVFS_STEP_20           0x2
59 #define TPS51632_DVFS_VMAX_PG           0x4
60 #define TPS51632_DVFS_PWMRST            0x8
61 #define TPS51632_DVFS_OCA_EN            0x10
62 #define TPS51632_DVFS_FCCM              0x20
63
64 /* TPS51632_POWER_STATE_REG */
65 #define TPS51632_POWER_STATE_MASK               0x03
66 #define TPS51632_POWER_STATE_MULTI_PHASE_CCM    0x0
67 #define TPS51632_POWER_STATE_SINGLE_PHASE_CCM   0x1
68 #define TPS51632_POWER_STATE_SINGLE_PHASE_DCM   0x2
69
70 #define TPS51632_MIN_VOLATGE    500000
71 #define TPS51632_MAX_VOLATGE    1520000
72 #define TPS51632_VOLATGE_STEP   10000
73 #define TPS51632_MAX_SEL        0x7F
74
75 /* TPS51632 chip information */
76 struct tps51632_chip {
77         struct device *dev;
78         struct regulator_desc desc;
79         struct regulator_dev *rdev;
80         struct regmap *regmap;
81
82         bool pwm_enabled;
83         unsigned int change_uv_per_us;
84 };
85
86 static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
87 {
88         struct tps51632_chip *tps = rdev_get_drvdata(rdev);
89         unsigned int data;
90         int ret;
91         unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
92
93         if (tps->pwm_enabled)
94                 reg = TPS51632_VOLTAGE_BASE_REG;
95         ret = regmap_read(tps->regmap, reg, &data);
96         if (ret < 0) {
97                 dev_err(tps->dev, "reg read failed, err %d\n", ret);
98                 return ret;
99         }
100         return data & TPS51632_VOUT_MASK;
101 }
102
103 static int tps51632_dcdc_set_voltage(struct regulator_dev *rdev,
104              int min_uV, int max_uV, unsigned *selector)
105 {
106         struct tps51632_chip *tps = rdev_get_drvdata(rdev);
107         int vsel;
108         int ret;
109
110         if ((max_uV < min_uV) || (max_uV < TPS51632_MIN_VOLATGE) ||
111                         (min_uV > TPS51632_MAX_VOLATGE))
112                 return -EINVAL;
113
114         vsel = DIV_ROUND_UP(min_uV - TPS51632_MIN_VOLATGE,
115                         TPS51632_VOLATGE_STEP) + 0x19;
116         if (selector)
117                 *selector = (vsel & TPS51632_VOUT_MASK);
118
119         ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_SELECT_REG, vsel);
120         if (ret < 0)
121                 dev_err(tps->dev, "reg write failed, err %d\n", ret);
122         return ret;
123 }
124
125 static int tps51632_dcdc_list_voltage(struct regulator_dev *rdev,
126                                         unsigned selector)
127 {
128         if (selector > TPS51632_MAX_SEL)
129                 return -EINVAL;
130
131         return TPS51632_MIN_VOLATGE + (selector - 0x19) * TPS51632_VOLATGE_STEP;
132 }
133
134 static int tps51632_dcdc_set_voltage_time_sel(struct regulator_dev *rdev,
135                 unsigned int old_selector, unsigned int new_selector)
136 {
137         struct tps51632_chip *tps = rdev_get_drvdata(rdev);
138         int old_uV, new_uV;
139
140         old_uV = tps51632_dcdc_list_voltage(rdev, old_selector);
141         if (old_uV < 0)
142                 return old_uV;
143
144         new_uV = tps51632_dcdc_list_voltage(rdev, new_selector);
145         if (new_uV < 0)
146                 return new_uV;
147
148         return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us);
149 }
150
151 static struct regulator_ops tps51632_dcdc_ops = {
152         .get_voltage_sel        = tps51632_dcdc_get_voltage_sel,
153         .set_voltage            = tps51632_dcdc_set_voltage,
154         .list_voltage           = tps51632_dcdc_list_voltage,
155         .set_voltage_time_sel   = tps51632_dcdc_set_voltage_time_sel,
156 };
157
158 static int __devinit tps51632_init_dcdc(struct tps51632_chip *tps,
159                 struct tps51632_regulator_platform_data *pdata)
160 {
161         int ret;
162         uint8_t control = 0;
163         int vsel;
164         unsigned int vmax;
165
166         if (pdata->enable_pwm) {
167                 control = TPS51632_DVFS_PWMEN;
168                 tps->pwm_enabled = pdata->enable_pwm;
169                 vsel = DIV_ROUND_UP(pdata->base_voltage_uV -
170                         TPS51632_MIN_VOLATGE, TPS51632_VOLATGE_STEP) + 0x19;
171                 ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG,
172                                                         vsel);
173                 if (ret < 0) {
174                         dev_err(tps->dev, "BASE reg write failed, err %d\n",
175                                         ret);
176                         return ret;
177                 }
178         }
179         if (pdata->dvfs_step_20mV)
180                 control = TPS51632_DVFS_STEP_20;
181         if (pdata->enable_vmax_alarm)
182                 control = TPS51632_DVFS_VMAX_PG;
183         if (pdata->enable_overcurrent_alram)
184                 control = TPS51632_DVFS_OCA_EN;
185         if (pdata->max_voltage_uV) {
186                 /**
187                  * TPS51632 hw behavior: VMAX register can be write only
188                  * once as it get locked after first write. The lock get
189                  * reset only when device is power-reset.
190                  * Write register only when lock bit is not enabled.
191                  */
192                 ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax);
193                 if (ret < 0) {
194                         dev_err(tps->dev, "VMAX read failed, err %d\n", ret);
195                         return ret;
196                 }
197                 if (vmax & TPS51632_VMAX_LOCK)
198                         goto skip_vmax_config;
199
200                 vsel = DIV_ROUND_UP(pdata->max_voltage_uV -
201                         TPS51632_MIN_VOLATGE, TPS51632_VOLATGE_STEP) + 0x19;
202                 ret = regmap_write(tps->regmap, TPS51632_VMAX_REG, vsel);
203                 if (ret < 0) {
204                         dev_err(tps->dev, "VMAX write failed, err %d\n", ret);
205                         return ret;
206                 }
207         }
208
209 skip_vmax_config:
210         ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
211         if (ret < 0) {
212                 dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
213                 return ret;
214         }
215
216         tps->change_uv_per_us = max(6000u, pdata->slew_rate_uv_per_us);
217
218         vsel = BIT(tps->change_uv_per_us/6000 - 1);
219
220         ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, vsel);
221         if (ret < 0)
222                 dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
223         return ret;
224 }
225
226 static const struct regmap_config tps51632_regmap_config = {
227         .reg_bits               = 8,
228         .val_bits               = 8,
229         .max_register           = TPS51632_MAX_REG - 1,
230         .cache_type             = REGCACHE_RBTREE,
231 };
232
233 static int __devinit tps51632_probe(struct i2c_client *client,
234                                 const struct i2c_device_id *id)
235 {
236         struct tps51632_regulator_platform_data *pdata;
237         struct regulator_dev *rdev;
238         struct tps51632_chip *tps;
239         int ret;
240
241         pdata = client->dev.platform_data;
242         if (!pdata) {
243                 dev_err(&client->dev, "No Platform data\n");
244                 return -EINVAL;
245         }
246
247         tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
248         if (!tps) {
249                 dev_err(&client->dev, "Memory allocation failed\n");
250                 return -ENOMEM;
251         }
252
253         tps->dev = &client->dev;
254         tps->desc.name = id->name;
255         tps->desc.id = 0;
256         tps->desc.ops = &tps51632_dcdc_ops;
257         tps->desc.type = REGULATOR_VOLTAGE;
258         tps->desc.owner = THIS_MODULE;
259         tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
260         if (IS_ERR(tps->regmap)) {
261                 ret = PTR_ERR(tps->regmap);
262                 dev_err(&client->dev, "regmap init failed, err %d\n", ret);
263                 return ret;
264         }
265         i2c_set_clientdata(client, tps);
266
267         ret = tps51632_init_dcdc(tps, pdata);
268         if (ret < 0) {
269                 dev_err(tps->dev, "Init failed, err = %d\n", ret);
270                 return ret;
271         }
272
273         /* Register the regulators */
274         rdev = regulator_register(&tps->desc, &client->dev,
275                         pdata->reg_init_data, tps, NULL);
276         if (IS_ERR(rdev)) {
277                 dev_err(tps->dev, "regulator register failed\n");
278                 return PTR_ERR(rdev);
279         }
280
281         tps->rdev = rdev;
282         return 0;
283 }
284
285 static int __devexit tps51632_remove(struct i2c_client *client)
286 {
287         struct tps51632_chip *tps = i2c_get_clientdata(client);
288
289         regulator_unregister(tps->rdev);
290         return 0;
291 }
292
293 static const struct i2c_device_id tps51632_id[] = {
294         {.name = "tps51632",},
295         {},
296 };
297
298 MODULE_DEVICE_TABLE(i2c, tps51632_id);
299
300 static struct i2c_driver tps51632_i2c_driver = {
301         .driver = {
302                 .name = "tps51632",
303                 .owner = THIS_MODULE,
304         },
305         .probe = tps51632_probe,
306         .remove = __devexit_p(tps51632_remove),
307         .id_table = tps51632_id,
308 };
309
310 static int __init tps51632_init(void)
311 {
312         return i2c_add_driver(&tps51632_i2c_driver);
313 }
314 subsys_initcall(tps51632_init);
315
316 static void __exit tps51632_cleanup(void)
317 {
318         i2c_del_driver(&tps51632_i2c_driver);
319 }
320 module_exit(tps51632_cleanup);
321
322 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
323 MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
324 MODULE_LICENSE("GPL v2");