aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/regulator/Kconfig6
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/tps6586x-regulator.c387
3 files changed, 394 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6c14afd258b0..93bf5fe5660c 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -229,5 +229,11 @@ config REGULATOR_AB8500
229 This driver supports the regulators found on the ST-Ericsson mixed 229 This driver supports the regulators found on the ST-Ericsson mixed
230 signal AB8500 PMIC 230 signal AB8500 PMIC
231 231
232config REGULATOR_TPS6586X
233 tristate "TI TPS6586X Power regulators"
234 depends on I2C
235 help
236 This driver supports TPS6586X voltage regulator chips.
237
232endif 238endif
233 239
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index fc696c50ee56..8285fd832e16 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
24obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o 24obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
25obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o 25obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
26obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o 26obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
27obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
27obj-$(CONFIG_REGULATOR_DA903X) += da903x.o 28obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
28obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o 29obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
29obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o 30obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
new file mode 100644
index 000000000000..76cc41ecbdf7
--- /dev/null
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -0,0 +1,387 @@
1/*
2 * Regulator driver for TI TPS6586x
3 *
4 * Copyright (C) 2010 Compulab Ltd.
5 * Author: Mike Rapoport <mike@compulab.co.il>
6 *
7 * Based on da903x
8 * Copyright (C) 2006-2008 Marvell International Ltd.
9 * Copyright (C) 2008 Compulab Ltd.
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 version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#define DEBUG
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/err.h>
20#include <linux/slab.h>
21#include <linux/platform_device.h>
22#include <linux/regulator/driver.h>
23#include <linux/regulator/machine.h>
24#include <linux/mfd/tps6586x.h>
25
26/* supply control and voltage setting */
27#define TPS6586X_SUPPLYENA 0x10
28#define TPS6586X_SUPPLYENB 0x11
29#define TPS6586X_SUPPLYENC 0x12
30#define TPS6586X_SUPPLYEND 0x13
31#define TPS6586X_SUPPLYENE 0x14
32#define TPS6586X_VCC1 0x20
33#define TPS6586X_VCC2 0x21
34#define TPS6586X_SM1V1 0x23
35#define TPS6586X_SM1V2 0x24
36#define TPS6586X_SM1SL 0x25
37#define TPS6586X_SM0V1 0x26
38#define TPS6586X_SM0V2 0x27
39#define TPS6586X_SM0SL 0x28
40#define TPS6586X_LDO2AV1 0x29
41#define TPS6586X_LDO2AV2 0x2A
42#define TPS6586X_LDO2BV1 0x2F
43#define TPS6586X_LDO2BV2 0x30
44#define TPS6586X_LDO4V1 0x32
45#define TPS6586X_LDO4V2 0x33
46
47/* converter settings */
48#define TPS6586X_SUPPLYV1 0x41
49#define TPS6586X_SUPPLYV2 0x42
50#define TPS6586X_SUPPLYV3 0x43
51#define TPS6586X_SUPPLYV4 0x44
52#define TPS6586X_SUPPLYV5 0x45
53#define TPS6586X_SUPPLYV6 0x46
54#define TPS6586X_SMODE1 0x47
55#define TPS6586X_SMODE2 0x48
56
57struct tps6586x_regulator {
58 struct regulator_desc desc;
59
60 int volt_reg;
61 int volt_shift;
62 int volt_nbits;
63 int enable_bit[2];
64 int enable_reg[2];
65
66 int *voltages;
67
68 /* for DVM regulators */
69 int go_reg;
70 int go_bit;
71};
72
73static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
74{
75 return rdev_get_dev(rdev)->parent->parent;
76}
77
78static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev,
79 unsigned selector)
80{
81 struct tps6586x_regulator *info = rdev_get_drvdata(rdev);
82
83 return info->voltages[selector];
84}
85
86
87static int __tps6586x_ldo_set_voltage(struct device *parent,
88 struct tps6586x_regulator *ri,
89 int min_uV, int max_uV)
90{
91 int val, uV;
92 uint8_t mask;
93
94 for (val = 0; val < ri->desc.n_voltages; val++) {
95 uV = ri->voltages[val] * 1000;
96
97 /* LDO0 has minimal voltage 1.2 rather than 1.25 */
98 if (ri->desc.id == TPS6586X_ID_LDO_0 && val == 0)
99 uV -= 50 * 1000;
100
101 /* use the first in-range value */
102 if (min_uV <= uV && uV <= max_uV) {
103
104 val <<= ri->volt_shift;
105 mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
106
107 return tps6586x_update(parent, ri->volt_reg, val, mask);
108 }
109 }
110
111 return -EINVAL;
112}
113
114static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev,
115 int min_uV, int max_uV)
116{
117 struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
118 struct device *parent = to_tps6586x_dev(rdev);
119
120 return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV);
121}
122
123static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev)
124{
125 struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
126 struct device *parent = to_tps6586x_dev(rdev);
127 uint8_t val, mask;
128 int ret;
129
130 ret = tps6586x_read(parent, ri->volt_reg, &val);
131 if (ret)
132 return ret;
133
134 mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
135 val = (val & mask) >> ri->volt_shift;
136
137 if (val > ri->desc.n_voltages)
138 BUG();
139
140 return ri->voltages[val];
141}
142
143static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev,
144 int min_uV, int max_uV)
145{
146 struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
147 struct device *parent = to_tps6586x_dev(rdev);
148 int ret;
149
150 ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV);
151 if (ret)
152 return ret;
153
154 return tps6586x_set_bits(parent, ri->go_reg, ri->go_bit);
155}
156
157static int tps6586x_regulator_enable(struct regulator_dev *rdev)
158{
159 struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
160 struct device *parent = to_tps6586x_dev(rdev);
161
162 return tps6586x_set_bits(parent, ri->enable_reg[0],
163 1 << ri->enable_bit[0]);
164}
165