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