Skip to content

Commit a273188

Browse files
ssekar15broonie
authored andcommitted
regulator: mp5416: add mp5416 regulator driver
Adding regulator driver for the device mp5416. The MP5416 PMIC device contains four DC-DC buck converters and five regulators, accessed over I2C. Signed-off-by: Saravanan Sekar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 65c3851 commit a273188

File tree

3 files changed

+256
-0
lines changed

3 files changed

+256
-0
lines changed

drivers/regulator/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,16 @@ config REGULATOR_MCP16502
613613
through the regulator interface. In addition it enables
614614
suspend-to-ram/standby transition.
615615

616+
config REGULATOR_MP5416
617+
tristate "Monolithic MP5416 PMIC"
618+
depends on I2C && OF
619+
select REGMAP_I2C
620+
help
621+
Say y here to support the MP5416 PMIC. This will enable supports
622+
the software controllable 4 buck and 4 LDO regulators.
623+
Say M here if you want to include support for the regulator as a
624+
module.
625+
616626
config REGULATOR_MP8859
617627
tristate "MPS MP8859 regulator driver"
618628
depends on I2C

drivers/regulator/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
7878
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
7979
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
8080
obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o
81+
obj-$(CONFIG_REGULATOR_MP5416) += mp5416.o
8182
obj-$(CONFIG_REGULATOR_MP8859) += mp8859.o
8283
obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
8384
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o

drivers/regulator/mp5416.c

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
//
3+
// mp5416.c - regulator driver for mps mp5416
4+
//
5+
// Copyright 2020 Monolithic Power Systems, Inc
6+
//
7+
// Author: Saravanan Sekar <[email protected]>
8+
9+
#include <linux/kernel.h>
10+
#include <linux/module.h>
11+
#include <linux/init.h>
12+
#include <linux/err.h>
13+
#include <linux/platform_device.h>
14+
#include <linux/regmap.h>
15+
#include <linux/regulator/driver.h>
16+
#include <linux/i2c.h>
17+
18+
#define MP5416_REG_CTL0 0x00
19+
#define MP5416_REG_CTL1 0x01
20+
#define MP5416_REG_CTL2 0x02
21+
#define MP5416_REG_ILIM 0x03
22+
#define MP5416_REG_BUCK1 0x04
23+
#define MP5416_REG_BUCK2 0x05
24+
#define MP5416_REG_BUCK3 0x06
25+
#define MP5416_REG_BUCK4 0x07
26+
#define MP5416_REG_LDO1 0x08
27+
#define MP5416_REG_LDO2 0x09
28+
#define MP5416_REG_LDO3 0x0a
29+
#define MP5416_REG_LDO4 0x0b
30+
31+
#define MP5416_REGULATOR_EN BIT(7)
32+
#define MP5416_MASK_VSET 0x7f
33+
#define MP5416_MASK_BUCK1_ILIM 0xc0
34+
#define MP5416_MASK_BUCK2_ILIM 0x0c
35+
#define MP5416_MASK_BUCK3_ILIM 0x30
36+
#define MP5416_MASK_BUCK4_ILIM 0x03
37+
#define MP5416_MASK_DVS_SLEWRATE 0xc0
38+
39+
/* values in uV */
40+
#define MP5416_VOLT1_MIN 600000
41+
#define MP5416_VOLT1_MAX 2187500
42+
#define MP5416_VOLT1_STEP 12500
43+
#define MP5416_VOLT2_MIN 800000
44+
#define MP5416_VOLT2_MAX 3975000
45+
#define MP5416_VOLT2_STEP 25000
46+
47+
#define MP5416_VOLT1_RANGE \
48+
((MP5416_VOLT1_MAX - MP5416_VOLT1_MIN)/MP5416_VOLT1_STEP + 1)
49+
#define MP5416_VOLT2_RANGE \
50+
((MP5416_VOLT2_MAX - MP5416_VOLT2_MIN)/MP5416_VOLT2_STEP + 1)
51+
52+
#define MP5416BUCK(_name, _id, _ilim, _dreg, _dval, _vsel) \
53+
[MP5416_BUCK ## _id] = { \
54+
.id = MP5416_BUCK ## _id, \
55+
.name = _name, \
56+
.of_match = _name, \
57+
.regulators_node = "regulators", \
58+
.ops = &mp5416_buck_ops, \
59+
.min_uV = MP5416_VOLT ##_vsel## _MIN, \
60+
.uV_step = MP5416_VOLT ##_vsel## _STEP, \
61+
.n_voltages = MP5416_VOLT ##_vsel## _RANGE, \
62+
.curr_table = _ilim, \
63+
.n_current_limits = ARRAY_SIZE(_ilim), \
64+
.csel_reg = MP5416_REG_ILIM, \
65+
.csel_mask = MP5416_MASK_BUCK ## _id ##_ILIM, \
66+
.vsel_reg = MP5416_REG_BUCK ## _id, \
67+
.vsel_mask = MP5416_MASK_VSET, \
68+
.enable_reg = MP5416_REG_BUCK ## _id, \
69+
.enable_mask = MP5416_REGULATOR_EN, \
70+
.active_discharge_on = _dval, \
71+
.active_discharge_reg = _dreg, \
72+
.active_discharge_mask = _dval, \
73+
.owner = THIS_MODULE, \
74+
}
75+
76+
#define MP5416LDO(_name, _id) \
77+
[MP5416_LDO ## _id] = { \
78+
.id = MP5416_LDO ## _id, \
79+
.name = _name, \
80+
.of_match = _name, \
81+
.regulators_node = "regulators", \
82+
.ops = &mp5416_ldo_ops, \
83+
.min_uV = MP5416_VOLT2_MIN, \
84+
.uV_step = MP5416_VOLT2_STEP, \
85+
.n_voltages = MP5416_VOLT2_RANGE, \
86+
.vsel_reg = MP5416_REG_LDO ##_id, \
87+
.vsel_mask = MP5416_MASK_VSET, \
88+
.enable_reg = MP5416_REG_LDO ##_id, \
89+
.enable_mask = MP5416_REGULATOR_EN, \
90+
.active_discharge_on = BIT(_id), \
91+
.active_discharge_reg = MP5416_REG_CTL2, \
92+
.active_discharge_mask = BIT(_id), \
93+
.owner = THIS_MODULE, \
94+
}
95+
96+
enum mp5416_regulators {
97+
MP5416_BUCK1,
98+
MP5416_BUCK2,
99+
MP5416_BUCK3,
100+
MP5416_BUCK4,
101+
MP5416_LDO1,
102+
MP5416_LDO2,
103+
MP5416_LDO3,
104+
MP5416_LDO4,
105+
MP5416_MAX_REGULATORS,
106+
};
107+
108+
static const struct regmap_config mp5416_regmap_config = {
109+
.reg_bits = 8,
110+
.val_bits = 8,
111+
.max_register = 0x0d,
112+
};
113+
114+
/* Current limits array (in uA)
115+
* ILIM1 & ILIM3
116+
*/
117+
static const unsigned int mp5416_I_limits1[] = {
118+
3800000, 4600000, 5600000, 6800000
119+
};
120+
121+
/* ILIM2 & ILIM4 */
122+
static const unsigned int mp5416_I_limits2[] = {
123+
2200000, 3200000, 4200000, 5200000
124+
};
125+
126+
static int mp5416_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay);
127+
128+
static const struct regulator_ops mp5416_ldo_ops = {
129+
.enable = regulator_enable_regmap,
130+
.disable = regulator_disable_regmap,
131+
.is_enabled = regulator_is_enabled_regmap,
132+
.list_voltage = regulator_list_voltage_linear,
133+
.map_voltage = regulator_map_voltage_linear,
134+
.get_voltage_sel = regulator_get_voltage_sel_regmap,
135+
.set_voltage_sel = regulator_set_voltage_sel_regmap,
136+
.set_active_discharge = regulator_set_active_discharge_regmap,
137+
};
138+
139+
static const struct regulator_ops mp5416_buck_ops = {
140+
.enable = regulator_enable_regmap,
141+
.disable = regulator_disable_regmap,
142+
.is_enabled = regulator_is_enabled_regmap,
143+
.list_voltage = regulator_list_voltage_linear,
144+
.map_voltage = regulator_map_voltage_linear,
145+
.get_voltage_sel = regulator_get_voltage_sel_regmap,
146+
.set_voltage_sel = regulator_set_voltage_sel_regmap,
147+
.set_active_discharge = regulator_set_active_discharge_regmap,
148+
.get_current_limit = regulator_get_current_limit_regmap,
149+
.set_current_limit = regulator_set_current_limit_regmap,
150+
.set_ramp_delay = mp5416_set_ramp_delay,
151+
};
152+
153+
static struct regulator_desc mp5416_regulators_desc[MP5416_MAX_REGULATORS] = {
154+
MP5416BUCK("buck1", 1, mp5416_I_limits1, MP5416_REG_CTL1, BIT(0), 1),
155+
MP5416BUCK("buck2", 2, mp5416_I_limits2, MP5416_REG_CTL1, BIT(1), 2),
156+
MP5416BUCK("buck3", 3, mp5416_I_limits1, MP5416_REG_CTL1, BIT(2), 1),
157+
MP5416BUCK("buck4", 4, mp5416_I_limits2, MP5416_REG_CTL2, BIT(5), 2),
158+
MP5416LDO("ldo1", 1),
159+
MP5416LDO("ldo2", 2),
160+
MP5416LDO("ldo3", 3),
161+
MP5416LDO("ldo4", 4),
162+
};
163+
164+
/*
165+
* DVS ramp rate BUCK1 to BUCK4
166+
* 00: 32mV/us
167+
* 01: 16mV/us
168+
* 10: 8mV/us
169+
* 11: 4mV/us
170+
*/
171+
static int mp5416_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
172+
{
173+
unsigned int ramp_val;
174+
175+
if (ramp_delay > 32000 || ramp_delay < 0)
176+
return -EINVAL;
177+
178+
if (ramp_delay <= 4000)
179+
ramp_val = 3;
180+
else if (ramp_delay <= 8000)
181+
ramp_val = 2;
182+
else if (ramp_delay <= 16000)
183+
ramp_val = 1;
184+
else
185+
ramp_val = 0;
186+
187+
return regmap_update_bits(rdev->regmap, MP5416_REG_CTL2,
188+
MP5416_MASK_DVS_SLEWRATE, ramp_val << 6);
189+
}
190+
191+
static int mp5416_i2c_probe(struct i2c_client *client)
192+
{
193+
struct device *dev = &client->dev;
194+
struct regulator_config config = { NULL, };
195+
struct regulator_dev *rdev;
196+
struct regmap *regmap;
197+
int i;
198+
199+
regmap = devm_regmap_init_i2c(client, &mp5416_regmap_config);
200+
if (IS_ERR(regmap)) {
201+
dev_err(dev, "Failed to allocate regmap!\n");
202+
return PTR_ERR(regmap);
203+
}
204+
205+
config.dev = dev;
206+
config.regmap = regmap;
207+
208+
for (i = 0; i < MP5416_MAX_REGULATORS; i++) {
209+
rdev = devm_regulator_register(dev,
210+
&mp5416_regulators_desc[i],
211+
&config);
212+
if (IS_ERR(rdev)) {
213+
dev_err(dev, "Failed to register regulator!\n");
214+
return PTR_ERR(rdev);
215+
}
216+
}
217+
218+
return 0;
219+
}
220+
221+
static const struct of_device_id mp5416_of_match[] = {
222+
{ .compatible = "mps,mp5416" },
223+
{},
224+
};
225+
MODULE_DEVICE_TABLE(of, mp5416_of_match);
226+
227+
static const struct i2c_device_id mp5416_id[] = {
228+
{ "mp5416", },
229+
{ },
230+
};
231+
MODULE_DEVICE_TABLE(i2c, mp5416_id);
232+
233+
static struct i2c_driver mp5416_regulator_driver = {
234+
.driver = {
235+
.name = "mp5416",
236+
.of_match_table = of_match_ptr(mp5416_of_match),
237+
},
238+
.probe_new = mp5416_i2c_probe,
239+
.id_table = mp5416_id,
240+
};
241+
module_i2c_driver(mp5416_regulator_driver);
242+
243+
MODULE_AUTHOR("Saravanan Sekar <[email protected]>");
244+
MODULE_DESCRIPTION("MP5416 PMIC regulator driver");
245+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)