aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-10-06 11:17:46 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-10-14 22:54:42 -0400
commit0c57067430a2b729bc08c92b17eb4f29d9bbfaae (patch)
tree8e5c5b8fba9f0c020fa526c0d3ce0f321232e79e
parentddffeb8c4d0331609ef2581d84de4d763607bd37 (diff)
regulator: tps51632: Add tps51632 regulator driver
The TPS51632 is a driverless step down controller with serial control. Advanced features such as D-Cap+ architecture with overlapping pulse support and OSR overshoot reduction provide fast transient response, lowest output capacitance and high efficiency. The TPS51632 supports both I2C and DVFS interfaces (through PWM) for dynamic control of the output voltage and current monitor telemetry. Add regulator driver for TPS51632. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--drivers/regulator/Kconfig11
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/tps51632-regulator.c332
-rw-r--r--include/linux/regulator/tps51632-regulator.h47
4 files changed, 391 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 67d47b59a66d..aa9e8a18262d 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -335,6 +335,17 @@ config REGULATOR_PALMAS
335 on the muxing. This is handled automatically in the driver by 335 on the muxing. This is handled automatically in the driver by
336 reading the mux info from OTP. 336 reading the mux info from OTP.
337 337
338config REGULATOR_TPS51632
339 tristate "TI TPS51632 Power Regulator"
340 depends on I2C
341 select REGMAP_I2C
342 help
343 This driver supports TPS51632 voltage regulator chip.
344 The TPS52632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller
345 with Serial VID control and DVFS.
346 The voltage output can be configure through I2C interface or PWM
347 interface.
348
338config REGULATOR_TPS6105X 349config REGULATOR_TPS6105X
339 tristate "TI TPS6105X Power regulators" 350 tristate "TI TPS6105X Power regulators"
340 depends on TPS6105X 351 depends on TPS6105X
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index e431eed8a878..ec1aec460bf6 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
41obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o 41obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
42obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o 42obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
43obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o 43obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
44obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
44obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o 45obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
45obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o 46obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
46obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o 47obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
new file mode 100644
index 000000000000..34603640d6d9
--- /dev/null
+++ b/drivers/regulator/tps51632-regulator.c
@@ -0,0 +1,332 @@
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_10mV 10000
73#define TPS51632_VOLATGE_STEP_20mV 20000
74#define TPS51632_MAX_VSEL 0x7F
75#define TPS51632_MIN_VSEL 0x19
76#define TPS51632_DEFAULT_RAMP_DELAY 6000
77#define TPS51632_VOLT_VSEL(uV) \
78 (DIV_ROUND_UP(uV - TPS51632_MIN_VOLATGE, \
79 TPS51632_VOLATGE_STEP_10mV) + \
80 TPS51632_MIN_VSEL)
81
82/* TPS51632 chip information */
83struct tps51632_chip {
84 struct device *dev;
85 struct regulator_desc desc;
86 struct regulator_dev *rdev;
87 struct regmap *regmap;
88 bool enable_pwm_dvfs;
89};
90
91static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
92{
93 struct tps51632_chip *tps = rdev_get_drvdata(rdev);
94 unsigned int data;
95 int ret;
96 unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
97 int vsel;
98
99 if (tps->enable_pwm_dvfs)
100 reg = TPS51632_VOLTAGE_BASE_REG;
101
102 ret = regmap_read(tps->regmap, reg, &data);
103 if (ret < 0) {
104 dev_err(tps->dev, "reg read failed, err %d\n", ret);
105 return ret;
106 }
107
108 vsel = data & TPS51632_VOUT_MASK;
109
110 if (vsel < TPS51632_MIN_VSEL)
111 return 0;
112 else
113 return vsel - TPS51632_MIN_VSEL;
114}
115
116static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
117 unsigned selector)
118{
119 struct tps51632_chip *tps = rdev_get_drvdata(rdev);
120 int vsel;
121 int ret;
122 unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
123
124 if (tps->enable_pwm_dvfs)
125 reg = TPS51632_VOLTAGE_BASE_REG;
126
127 vsel = selector + TPS51632_MIN_VSEL;
128 if (vsel > TPS51632_MAX_VSEL)
129 return -EINVAL;
130
131 ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_SELECT_REG, vsel);
132 if (ret < 0)
133 dev_err(tps->dev, "reg write failed, err %d\n", ret);
134 return ret;
135}
136
137static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
138 int ramp_delay)
139{
140 struct tps51632_chip *tps = rdev_get_drvdata(rdev);
141 int bit = ramp_delay/6000;
142 int ret;
143
144 if (bit)
145 bit--;
146 ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
147 if (ret < 0)
148 dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
149 return ret;
150}
151
152static struct regulator_ops tps51632_dcdc_ops = {
153 .get_voltage_sel = tps51632_dcdc_get_voltage_sel,
154 .set_voltage_sel = tps51632_dcdc_set_voltage_sel,
155 .list_voltage = regulator_list_voltage_linear,
156 .set_voltage_time_sel = regulator_set_voltage_time_sel,
157 .set_ramp_delay = tps51632_dcdc_set_ramp_delay,
158};
159
160static int __devinit tps51632_init_dcdc(struct tps51632_chip *tps,
161 struct tps51632_regulator_platform_data *pdata)
162{
163 int ret;
164 uint8_t control = 0;
165 int vsel;
166
167 if (!pdata->enable_pwm_dvfs)
168 goto skip_pwm_config;
169
170 control |= TPS51632_DVFS_PWMEN;
171 tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs;
172 vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV);
173 ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel);
174 if (ret < 0) {
175 dev_err(tps->dev, "BASE reg write failed, err %d\n", ret);
176 return ret;
177 }
178
179 if (pdata->dvfs_step_20mV)
180 control |= TPS51632_DVFS_STEP_20;
181
182 if (pdata->max_voltage_uV) {
183 unsigned int vmax;
184 /**
185 * TPS51632 hw behavior: VMAX register can be write only
186 * once as it get locked after first write. The lock get
187 * reset only when device is power-reset.
188 * Write register only when lock bit is not enabled.
189 */
190 ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax);
191 if (ret < 0) {
192 dev_err(tps->dev, "VMAX read failed, err %d\n", ret);
193 return ret;
194 }
195 if (!(vmax & TPS51632_VMAX_LOCK)) {
196 vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV);
197 ret = regmap_write(tps->regmap, TPS51632_VMAX_REG,
198 vsel);
199 if (ret < 0) {
200 dev_err(tps->dev,
201 "VMAX write failed, err %d\n", ret);
202 return ret;
203 }
204 }
205 }
206
207skip_pwm_config:
208 ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
209 if (ret < 0)
210 dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
211 return ret;
212}
213
214static bool rd_wr_reg(struct device *dev, unsigned int reg)
215{
216 if ((reg >= 0x8) && (reg <= 0x10))
217 return false;
218 return true;
219}
220
221static const struct regmap_config tps51632_regmap_config = {
222 .reg_bits = 8,
223 .val_bits = 8,
224 .writeable_reg = rd_wr_reg,
225 .readable_reg = rd_wr_reg,
226 .max_register = TPS51632_MAX_REG - 1,
227 .cache_type = REGCACHE_RBTREE,
228};
229
230static int __devinit tps51632_probe(struct i2c_client *client,
231 const struct i2c_device_id *id)
232{
233 struct tps51632_regulator_platform_data *pdata;
234 struct regulator_dev *rdev;
235 struct tps51632_chip *tps;
236 int ret;
237 struct regulator_config config = { };
238
239 pdata = client->dev.platform_data;
240 if (!pdata) {
241 dev_err(&client->dev, "No Platform data\n");
242 return -EINVAL;
243 }
244
245 tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
246 if (!tps) {
247 dev_err(&client->dev, "Memory allocation failed\n");
248 return -ENOMEM;
249 }
250
251 tps->dev = &client->dev;
252 tps->desc.name = id->name;
253 tps->desc.id = 0;
254 tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
255 tps->desc.min_uV = TPS51632_MIN_VOLATGE;
256 tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV;
257 tps->desc.n_voltages = (TPS51632_MAX_VSEL - TPS51632_MIN_VSEL) + 1;
258 tps->desc.ops = &tps51632_dcdc_ops;
259 tps->desc.type = REGULATOR_VOLTAGE;
260 tps->desc.owner = THIS_MODULE;
261
262 tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
263 if (IS_ERR(tps->regmap)) {
264 ret = PTR_ERR(tps->regmap);
265 dev_err(&client->dev, "regmap init failed, err %d\n", ret);
266 return ret;
267 }
268 i2c_set_clientdata(client, tps);
269
270 ret = tps51632_init_dcdc(tps, pdata);
271 if (ret < 0) {
272 dev_err(tps->dev, "Init failed, err = %d\n", ret);
273 return ret;
274 }
275
276 /* Register the regulators */
277 config.dev = &client->dev;
278 config.init_data = pdata->reg_init_data;
279 config.driver_data = tps;
280 config.regmap = tps->regmap;
281 config.of_node = client->dev.of_node;
282
283 rdev = regulator_register(&tps->desc, &config);
284 if (IS_ERR(rdev)) {
285 dev_err(tps->dev, "regulator register failed\n");
286 return PTR_ERR(rdev);
287 }
288
289 tps->rdev = rdev;
290 return 0;
291}
292
293static int __devexit tps51632_remove(struct i2c_client *client)
294{
295 struct tps51632_chip *tps = i2c_get_clientdata(client);
296
297 regulator_unregister(tps->rdev);
298 return 0;
299}
300
301static const struct i2c_device_id tps51632_id[] = {
302 {.name = "tps51632",},
303 {},
304};
305
306MODULE_DEVICE_TABLE(i2c, tps51632_id);
307
308static struct i2c_driver tps51632_i2c_driver = {
309 .driver = {
310 .name = "tps51632",
311 .owner = THIS_MODULE,
312 },
313 .probe = tps51632_probe,
314 .remove = __devexit_p(tps51632_remove),
315 .id_table = tps51632_id,
316};
317
318static int __init tps51632_init(void)
319{
320 return i2c_add_driver(&tps51632_i2c_driver);
321}
322subsys_initcall(tps51632_init);
323
324static void __exit tps51632_cleanup(void)
325{
326 i2c_del_driver(&tps51632_i2c_driver);
327}
328module_exit(tps51632_cleanup);
329
330MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
331MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
332MODULE_LICENSE("GPL v2");
diff --git a/include/linux/regulator/tps51632-regulator.h b/include/linux/regulator/tps51632-regulator.h
new file mode 100644
index 000000000000..d00841e1a75a
--- /dev/null
+++ b/include/linux/regulator/tps51632-regulator.h
@@ -0,0 +1,47 @@
1/*
2 * tps51632-regulator.h -- TPS51632 regulator
3 *
4 * Interface for regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down
5 * Driverless 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 modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 *
25 */
26
27#ifndef __LINUX_REGULATOR_TPS51632_H
28#define __LINUX_REGULATOR_TPS51632_H
29
30/*
31 * struct tps51632_regulator_platform_data - tps51632 regulator platform data.
32 *
33 * @reg_init_data: The regulator init data.
34 * @enable_pwm_dvfs: Enable PWM DVFS or not.
35 * @dvfs_step_20mV: Step for DVFS is 20mV or 10mV.
36 * @max_voltage_uV: Maximum possible voltage in PWM-DVFS mode.
37 * @base_voltage_uV: Base voltage when PWM-DVFS enabled.
38 */
39struct tps51632_regulator_platform_data {
40 struct regulator_init_data *reg_init_data;
41 bool enable_pwm_dvfs;
42 bool dvfs_step_20mV;
43 int max_voltage_uV;
44 int base_voltage_uV;
45};
46
47#endif /* __LINUX_REGULATOR_TPS51632_H */