Skip to content

Commit d2a2e72

Browse files
glneobroonie
authored andcommitted
regulator: tps65086: Add regulator driver for the TPS65086 PMIC
Add support for TPS65086 PMIC regulators. The regulators set consists of 3 Step-down Controllers, 3 Step-down Converters, 3 LDOs, 3 Load Switches, and a Sink and Source LDO. The output voltages are configurable and are meant to supply power to a SoC and/or other components. Signed-off-by: Andrew F. Davis <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 8005c49 commit d2a2e72

File tree

3 files changed

+258
-0
lines changed

3 files changed

+258
-0
lines changed

drivers/regulator/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,13 @@ config REGULATOR_TPS6507X
680680
three step-down converters and two general-purpose LDO voltage regulators.
681681
It supports TI's software based Class-2 SmartReflex implementation.
682682

683+
config REGULATOR_TPS65086
684+
tristate "TI TPS65086 Power regulators"
685+
depends on MFD_TPS65086
686+
help
687+
This driver provides support for the voltage regulators on
688+
TI TPS65086 PMICs.
689+
683690
config REGULATOR_TPS65090
684691
tristate "TI TPS65090 Power regulator"
685692
depends on MFD_TPS65090

drivers/regulator/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
8585
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
8686
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
8787
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
88+
obj-$(CONFIG_REGULATOR_TPS65086) += tps65086-regulator.o
8889
obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o
8990
obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o
9091
obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/*
2+
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
3+
*
4+
* Author: Andrew F. Davis <[email protected]>
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public License version 2 as
8+
* published by the Free Software Foundation.
9+
*
10+
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
11+
* kind, whether expressed or implied; without even the implied warranty
12+
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License version 2 for more details.
14+
*
15+
* Based on the TPS65912 driver
16+
*/
17+
18+
#include <linux/module.h>
19+
#include <linux/of_device.h>
20+
#include <linux/platform_device.h>
21+
#include <linux/regulator/driver.h>
22+
#include <linux/regulator/of_regulator.h>
23+
24+
#include <linux/mfd/tps65086.h>
25+
26+
enum tps65086_regulators { BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, LDOA1,
27+
LDOA2, LDOA3, SWA1, SWB1, SWB2, VTT };
28+
29+
#define TPS65086_REGULATOR(_name, _of, _id, _nv, _vr, _vm, _er, _em, _lr, _dr, _dm) \
30+
[_id] = { \
31+
.desc = { \
32+
.name = _name, \
33+
.of_match = of_match_ptr(_of), \
34+
.of_parse_cb = tps65086_of_parse_cb, \
35+
.id = _id, \
36+
.ops = &reg_ops, \
37+
.n_voltages = _nv, \
38+
.type = REGULATOR_VOLTAGE, \
39+
.owner = THIS_MODULE, \
40+
.vsel_reg = _vr, \
41+
.vsel_mask = _vm, \
42+
.enable_reg = _er, \
43+
.enable_mask = _em, \
44+
.volt_table = NULL, \
45+
.linear_ranges = _lr, \
46+
.n_linear_ranges = ARRAY_SIZE(_lr), \
47+
}, \
48+
.decay_reg = _dr, \
49+
.decay_mask = _dm, \
50+
}
51+
52+
#define TPS65086_SWITCH(_name, _of, _id, _er, _em) \
53+
[_id] = { \
54+
.desc = { \
55+
.name = _name, \
56+
.of_match = of_match_ptr(_of), \
57+
.of_parse_cb = tps65086_of_parse_cb, \
58+
.id = _id, \
59+
.ops = &switch_ops, \
60+
.type = REGULATOR_VOLTAGE, \
61+
.owner = THIS_MODULE, \
62+
.enable_reg = _er, \
63+
.enable_mask = _em, \
64+
}, \
65+
}
66+
67+
struct tps65086_regulator {
68+
struct regulator_desc desc;
69+
unsigned int decay_reg;
70+
unsigned int decay_mask;
71+
};
72+
73+
static const struct regulator_linear_range tps65086_buck126_10mv_ranges[] = {
74+
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
75+
REGULATOR_LINEAR_RANGE(410000, 0x1, 0x7F, 10000),
76+
};
77+
78+
static const struct regulator_linear_range tps65086_buck126_25mv_ranges[] = {
79+
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
80+
REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x18, 0),
81+
REGULATOR_LINEAR_RANGE(1025000, 0x19, 0x7F, 25000),
82+
};
83+
84+
static const struct regulator_linear_range tps65086_buck345_ranges[] = {
85+
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
86+
REGULATOR_LINEAR_RANGE(425000, 0x1, 0x7F, 25000),
87+
};
88+
89+
static const struct regulator_linear_range tps65086_ldoa1_ranges[] = {
90+
REGULATOR_LINEAR_RANGE(1350000, 0x0, 0x0, 0),
91+
REGULATOR_LINEAR_RANGE(1500000, 0x1, 0x7, 100000),
92+
REGULATOR_LINEAR_RANGE(2300000, 0x8, 0xA, 100000),
93+
REGULATOR_LINEAR_RANGE(2700000, 0xB, 0xD, 150000),
94+
REGULATOR_LINEAR_RANGE(3300000, 0xE, 0xE, 0),
95+
};
96+
97+
static const struct regulator_linear_range tps65086_ldoa23_ranges[] = {
98+
REGULATOR_LINEAR_RANGE(700000, 0x0, 0xD, 50000),
99+
REGULATOR_LINEAR_RANGE(1400000, 0xE, 0xF, 100000),
100+
};
101+
102+
/* Operations permitted on regulators */
103+
static struct regulator_ops reg_ops = {
104+
.enable = regulator_enable_regmap,
105+
.disable = regulator_disable_regmap,
106+
.is_enabled = regulator_is_enabled_regmap,
107+
.set_voltage_sel = regulator_set_voltage_sel_regmap,
108+
.map_voltage = regulator_map_voltage_linear_range,
109+
.get_voltage_sel = regulator_get_voltage_sel_regmap,
110+
.list_voltage = regulator_list_voltage_linear_range,
111+
};
112+
113+
/* Operations permitted on load switches */
114+
static struct regulator_ops switch_ops = {
115+
.enable = regulator_enable_regmap,
116+
.disable = regulator_disable_regmap,
117+
.is_enabled = regulator_is_enabled_regmap,
118+
};
119+
120+
static int tps65086_of_parse_cb(struct device_node *dev,
121+
const struct regulator_desc *desc,
122+
struct regulator_config *config);
123+
124+
static struct tps65086_regulator regulators[] = {
125+
TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL,
126+
BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0),
127+
tps65086_buck126_10mv_ranges, TPS65086_BUCK1CTRL,
128+
BIT(0)),
129+
TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL,
130+
BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1),
131+
tps65086_buck126_10mv_ranges, TPS65086_BUCK2CTRL,
132+
BIT(0)),
133+
TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID,
134+
BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2),
135+
tps65086_buck345_ranges, TPS65086_BUCK3DECAY,
136+
BIT(0)),
137+
TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID,
138+
BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0),
139+
tps65086_buck345_ranges, TPS65086_BUCK4VID,
140+
BIT(0)),
141+
TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID,
142+
BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0),
143+
tps65086_buck345_ranges, TPS65086_BUCK5CTRL,
144+
BIT(0)),
145+
TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID,
146+
BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0),
147+
tps65086_buck126_10mv_ranges, TPS65086_BUCK6CTRL,
148+
BIT(0)),
149+
TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL,
150+
VDOA1_VID_MASK, TPS65086_LDOA1CTRL, BIT(0),
151+
tps65086_ldoa1_ranges, 0, 0),
152+
TPS65086_REGULATOR("LDOA2", "ldoa2", LDOA2, 0x10, TPS65086_LDOA2VID,
153+
VDOA23_VID_MASK, TPS65086_LDOA2CTRL, BIT(0),
154+
tps65086_ldoa23_ranges, 0, 0),
155+
TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID,
156+
VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0),
157+
tps65086_ldoa23_ranges, 0, 0),
158+
TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)),
159+
TPS65086_SWITCH("SWB1", "swa2", SWB1, TPS65086_SWVTT_EN, BIT(6)),
160+
TPS65086_SWITCH("SWB2", "swa3", SWB2, TPS65086_SWVTT_EN, BIT(7)),
161+
TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)),
162+
};
163+
164+
static inline bool has_25mv_mode(int id)
165+
{
166+
switch (id) {
167+
case BUCK1:
168+
case BUCK2:
169+
case BUCK6:
170+
return true;
171+
default:
172+
return false;
173+
}
174+
}
175+
176+
static int tps65086_of_parse_cb(struct device_node *dev,
177+
const struct regulator_desc *desc,
178+
struct regulator_config *config)
179+
{
180+
int ret;
181+
182+
/* Check for 25mV step mode */
183+
if (has_25mv_mode(desc->id) &&
184+
of_property_read_bool(config->of_node, "ti,regulator-step-size-25mv")) {
185+
regulators[desc->id].desc.linear_ranges =
186+
tps65086_buck126_25mv_ranges;
187+
regulators[desc->id].desc.n_linear_ranges =
188+
ARRAY_SIZE(tps65086_buck126_25mv_ranges);
189+
}
190+
191+
/* Check for decay mode */
192+
if (desc->id <= BUCK6 && of_property_read_bool(config->of_node, "ti,regulator-decay")) {
193+
ret = regmap_write_bits(config->regmap,
194+
regulators[desc->id].decay_reg,
195+
regulators[desc->id].decay_mask,
196+
regulators[desc->id].decay_mask);
197+
if (ret) {
198+
dev_err(config->dev, "Error setting decay\n");
199+
return ret;
200+
}
201+
}
202+
203+
return 0;
204+
}
205+
206+
static int tps65086_regulator_probe(struct platform_device *pdev)
207+
{
208+
struct tps65086 *tps = dev_get_drvdata(pdev->dev.parent);
209+
struct regulator_config config = { };
210+
struct regulator_dev *rdev;
211+
int i;
212+
213+
platform_set_drvdata(pdev, tps);
214+
215+
config.dev = &pdev->dev;
216+
config.driver_data = tps;
217+
config.of_node = pdev->dev.of_node;
218+
config.regmap = tps->regmap;
219+
220+
for (i = 0; i < ARRAY_SIZE(regulators); i++) {
221+
rdev = devm_regulator_register(&pdev->dev, &regulators[i].desc,
222+
&config);
223+
if (IS_ERR(rdev)) {
224+
dev_err(tps->dev, "failed to register %s regulator\n",
225+
pdev->name);
226+
return PTR_ERR(rdev);
227+
}
228+
}
229+
230+
return 0;
231+
}
232+
233+
static const struct platform_device_id tps65086_regulator_id_table[] = {
234+
{ "tps65086-regulator", },
235+
{ /* sentinel */ }
236+
};
237+
MODULE_DEVICE_TABLE(platform, tps65086_regulator_id_table);
238+
239+
static struct platform_driver tps65086_regulator_driver = {
240+
.driver = {
241+
.name = "tps65086-regulator",
242+
},
243+
.probe = tps65086_regulator_probe,
244+
.id_table = tps65086_regulator_id_table,
245+
};
246+
module_platform_driver(tps65086_regulator_driver);
247+
248+
MODULE_AUTHOR("Andrew F. Davis <[email protected]>");
249+
MODULE_DESCRIPTION("TPS65086 Regulator driver");
250+
MODULE_LICENSE("GPL v2");

0 commit comments

Comments
 (0)