1bcc61f1cSBartosz Golaszewski // SPDX-License-Identifier: GPL-2.0
2bcc61f1cSBartosz Golaszewski //
3bcc61f1cSBartosz Golaszewski // Copyright (C) 2018 BayLibre SAS
4bcc61f1cSBartosz Golaszewski // Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
5bcc61f1cSBartosz Golaszewski //
6bcc61f1cSBartosz Golaszewski // Regulator driver for MAXIM 77650/77651 charger/power-supply.
7bcc61f1cSBartosz Golaszewski
85358db54SAxel Lin #include <linux/of.h>
9bcc61f1cSBartosz Golaszewski #include <linux/mfd/max77650.h>
10bcc61f1cSBartosz Golaszewski #include <linux/module.h>
11bcc61f1cSBartosz Golaszewski #include <linux/platform_device.h>
12bcc61f1cSBartosz Golaszewski #include <linux/regmap.h>
13bcc61f1cSBartosz Golaszewski #include <linux/regulator/driver.h>
14bcc61f1cSBartosz Golaszewski
15bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_EN_CTRL_MASK GENMASK(3, 0)
16bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \
17bcc61f1cSBartosz Golaszewski ((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)
18bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_ENABLED GENMASK(2, 1)
19bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_DISABLED BIT(2)
20bcc61f1cSBartosz Golaszewski
21bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0)
22bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0)
233df4235aSAxel Lin #define MAX77651_REGULATOR_V_SBB1_MASK GENMASK(5, 2)
243df4235aSAxel Lin #define MAX77651_REGULATOR_V_SBB1_RANGE_MASK GENMASK(1, 0)
25bcc61f1cSBartosz Golaszewski
26bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_AD_MASK BIT(3)
27bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_AD_DISABLED 0x00
28bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_AD_ENABLED BIT(3)
29bcc61f1cSBartosz Golaszewski
30bcc61f1cSBartosz Golaszewski #define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6)
31bcc61f1cSBartosz Golaszewski
32bcc61f1cSBartosz Golaszewski enum {
33bcc61f1cSBartosz Golaszewski MAX77650_REGULATOR_ID_LDO = 0,
34bcc61f1cSBartosz Golaszewski MAX77650_REGULATOR_ID_SBB0,
35bcc61f1cSBartosz Golaszewski MAX77650_REGULATOR_ID_SBB1,
36bcc61f1cSBartosz Golaszewski MAX77650_REGULATOR_ID_SBB2,
37bcc61f1cSBartosz Golaszewski MAX77650_REGULATOR_NUM_REGULATORS,
38bcc61f1cSBartosz Golaszewski };
39bcc61f1cSBartosz Golaszewski
40bcc61f1cSBartosz Golaszewski struct max77650_regulator_desc {
41bcc61f1cSBartosz Golaszewski struct regulator_desc desc;
42bcc61f1cSBartosz Golaszewski unsigned int regA;
43bcc61f1cSBartosz Golaszewski unsigned int regB;
44bcc61f1cSBartosz Golaszewski };
45bcc61f1cSBartosz Golaszewski
4659dec1f0SNathan Chancellor static struct max77650_regulator_desc max77651_SBB1_desc;
4759dec1f0SNathan Chancellor
483df4235aSAxel Lin static const unsigned int max77651_sbb1_volt_range_sel[] = {
493df4235aSAxel Lin 0x0, 0x1, 0x2, 0x3
50bcc61f1cSBartosz Golaszewski };
51bcc61f1cSBartosz Golaszewski
5260ab7f41SMatti Vaittinen static const struct linear_range max77651_sbb1_volt_ranges[] = {
533df4235aSAxel Lin /* range index 0 */
543df4235aSAxel Lin REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),
553df4235aSAxel Lin /* range index 1 */
563df4235aSAxel Lin REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000),
573df4235aSAxel Lin /* range index 2 */
583df4235aSAxel Lin REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000),
593df4235aSAxel Lin /* range index 3 */
603df4235aSAxel Lin REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000),
613df4235aSAxel Lin };
62bcc61f1cSBartosz Golaszewski
636c98ac2aSAxel Lin static const unsigned int max77650_current_limit_table[] = {
64bcc61f1cSBartosz Golaszewski 1000000, 866000, 707000, 500000,
65bcc61f1cSBartosz Golaszewski };
66bcc61f1cSBartosz Golaszewski
max77650_regulator_is_enabled(struct regulator_dev * rdev)67bcc61f1cSBartosz Golaszewski static int max77650_regulator_is_enabled(struct regulator_dev *rdev)
68bcc61f1cSBartosz Golaszewski {
69bcc61f1cSBartosz Golaszewski struct max77650_regulator_desc *rdesc;
70bcc61f1cSBartosz Golaszewski struct regmap *map;
71bcc61f1cSBartosz Golaszewski int val, rv, en;
72bcc61f1cSBartosz Golaszewski
73bcc61f1cSBartosz Golaszewski rdesc = rdev_get_drvdata(rdev);
74bcc61f1cSBartosz Golaszewski map = rdev_get_regmap(rdev);
75bcc61f1cSBartosz Golaszewski
76bcc61f1cSBartosz Golaszewski rv = regmap_read(map, rdesc->regB, &val);
77bcc61f1cSBartosz Golaszewski if (rv)
78bcc61f1cSBartosz Golaszewski return rv;
79bcc61f1cSBartosz Golaszewski
80bcc61f1cSBartosz Golaszewski en = MAX77650_REGULATOR_EN_CTRL_BITS(val);
81bcc61f1cSBartosz Golaszewski
82bcc61f1cSBartosz Golaszewski return en != MAX77650_REGULATOR_DISABLED;
83bcc61f1cSBartosz Golaszewski }
84bcc61f1cSBartosz Golaszewski
max77650_regulator_enable(struct regulator_dev * rdev)85bcc61f1cSBartosz Golaszewski static int max77650_regulator_enable(struct regulator_dev *rdev)
86bcc61f1cSBartosz Golaszewski {
87bcc61f1cSBartosz Golaszewski struct max77650_regulator_desc *rdesc;
88bcc61f1cSBartosz Golaszewski struct regmap *map;
89bcc61f1cSBartosz Golaszewski
90bcc61f1cSBartosz Golaszewski rdesc = rdev_get_drvdata(rdev);
91bcc61f1cSBartosz Golaszewski map = rdev_get_regmap(rdev);
92bcc61f1cSBartosz Golaszewski
93bcc61f1cSBartosz Golaszewski return regmap_update_bits(map, rdesc->regB,
94bcc61f1cSBartosz Golaszewski MAX77650_REGULATOR_EN_CTRL_MASK,
95bcc61f1cSBartosz Golaszewski MAX77650_REGULATOR_ENABLED);
96bcc61f1cSBartosz Golaszewski }
97bcc61f1cSBartosz Golaszewski
max77650_regulator_disable(struct regulator_dev * rdev)98bcc61f1cSBartosz Golaszewski static int max77650_regulator_disable(struct regulator_dev *rdev)
99bcc61f1cSBartosz Golaszewski {
100bcc61f1cSBartosz Golaszewski struct max77650_regulator_desc *rdesc;
101bcc61f1cSBartosz Golaszewski struct regmap *map;
102bcc61f1cSBartosz Golaszewski
103bcc61f1cSBartosz Golaszewski rdesc = rdev_get_drvdata(rdev);
104bcc61f1cSBartosz Golaszewski map = rdev_get_regmap(rdev);
105bcc61f1cSBartosz Golaszewski
106bcc61f1cSBartosz Golaszewski return regmap_update_bits(map, rdesc->regB,
107bcc61f1cSBartosz Golaszewski MAX77650_REGULATOR_EN_CTRL_MASK,
108bcc61f1cSBartosz Golaszewski MAX77650_REGULATOR_DISABLED);
109bcc61f1cSBartosz Golaszewski }
110bcc61f1cSBartosz Golaszewski
111bcc61f1cSBartosz Golaszewski static const struct regulator_ops max77650_regulator_LDO_ops = {
112bcc61f1cSBartosz Golaszewski .is_enabled = max77650_regulator_is_enabled,
113bcc61f1cSBartosz Golaszewski .enable = max77650_regulator_enable,
114bcc61f1cSBartosz Golaszewski .disable = max77650_regulator_disable,
115bcc61f1cSBartosz Golaszewski .list_voltage = regulator_list_voltage_linear,
116bcc61f1cSBartosz Golaszewski .map_voltage = regulator_map_voltage_linear,
117bcc61f1cSBartosz Golaszewski .get_voltage_sel = regulator_get_voltage_sel_regmap,
1183c7577d4SBartosz Golaszewski .set_voltage_sel = regulator_set_voltage_sel_regmap,
119bcc61f1cSBartosz Golaszewski .set_active_discharge = regulator_set_active_discharge_regmap,
120bcc61f1cSBartosz Golaszewski };
121bcc61f1cSBartosz Golaszewski
122bcc61f1cSBartosz Golaszewski static const struct regulator_ops max77650_regulator_SBB_ops = {
123bcc61f1cSBartosz Golaszewski .is_enabled = max77650_regulator_is_enabled,
124bcc61f1cSBartosz Golaszewski .enable = max77650_regulator_enable,
125bcc61f1cSBartosz Golaszewski .disable = max77650_regulator_disable,
126bcc61f1cSBartosz Golaszewski .list_voltage = regulator_list_voltage_linear,
127bcc61f1cSBartosz Golaszewski .map_voltage = regulator_map_voltage_linear,
128bcc61f1cSBartosz Golaszewski .get_voltage_sel = regulator_get_voltage_sel_regmap,
1293c7577d4SBartosz Golaszewski .set_voltage_sel = regulator_set_voltage_sel_regmap,
1306c98ac2aSAxel Lin .get_current_limit = regulator_get_current_limit_regmap,
1316c98ac2aSAxel Lin .set_current_limit = regulator_set_current_limit_regmap,
132bcc61f1cSBartosz Golaszewski .set_active_discharge = regulator_set_active_discharge_regmap,
133bcc61f1cSBartosz Golaszewski };
134bcc61f1cSBartosz Golaszewski
1353df4235aSAxel Lin /* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */
136bcc61f1cSBartosz Golaszewski static const struct regulator_ops max77651_SBB1_regulator_ops = {
137bcc61f1cSBartosz Golaszewski .is_enabled = max77650_regulator_is_enabled,
138bcc61f1cSBartosz Golaszewski .enable = max77650_regulator_enable,
139bcc61f1cSBartosz Golaszewski .disable = max77650_regulator_disable,
1403df4235aSAxel Lin .list_voltage = regulator_list_voltage_pickable_linear_range,
1413df4235aSAxel Lin .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
1423c7577d4SBartosz Golaszewski .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
1436c98ac2aSAxel Lin .get_current_limit = regulator_get_current_limit_regmap,
1446c98ac2aSAxel Lin .set_current_limit = regulator_set_current_limit_regmap,
145bcc61f1cSBartosz Golaszewski .set_active_discharge = regulator_set_active_discharge_regmap,
146bcc61f1cSBartosz Golaszewski };
147bcc61f1cSBartosz Golaszewski
148bcc61f1cSBartosz Golaszewski static struct max77650_regulator_desc max77650_LDO_desc = {
149bcc61f1cSBartosz Golaszewski .desc = {
150bcc61f1cSBartosz Golaszewski .name = "ldo",
151bcc61f1cSBartosz Golaszewski .of_match = of_match_ptr("ldo"),
152bcc61f1cSBartosz Golaszewski .regulators_node = of_match_ptr("regulators"),
153bcc61f1cSBartosz Golaszewski .supply_name = "in-ldo",
154bcc61f1cSBartosz Golaszewski .id = MAX77650_REGULATOR_ID_LDO,
155bcc61f1cSBartosz Golaszewski .ops = &max77650_regulator_LDO_ops,
156bcc61f1cSBartosz Golaszewski .min_uV = 1350000,
157bcc61f1cSBartosz Golaszewski .uV_step = 12500,
158bcc61f1cSBartosz Golaszewski .n_voltages = 128,
1593c7577d4SBartosz Golaszewski .vsel_step = 1,
160bcc61f1cSBartosz Golaszewski .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK,
161bcc61f1cSBartosz Golaszewski .vsel_reg = MAX77650_REG_CNFG_LDO_A,
162bcc61f1cSBartosz Golaszewski .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
163bcc61f1cSBartosz Golaszewski .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
164bcc61f1cSBartosz Golaszewski .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
165bcc61f1cSBartosz Golaszewski .active_discharge_reg = MAX77650_REG_CNFG_LDO_B,
166bcc61f1cSBartosz Golaszewski .enable_time = 100,
167bcc61f1cSBartosz Golaszewski .type = REGULATOR_VOLTAGE,
168721efb50SAxel Lin .owner = THIS_MODULE,
169bcc61f1cSBartosz Golaszewski },
170bcc61f1cSBartosz Golaszewski .regA = MAX77650_REG_CNFG_LDO_A,
171bcc61f1cSBartosz Golaszewski .regB = MAX77650_REG_CNFG_LDO_B,
172bcc61f1cSBartosz Golaszewski };
173bcc61f1cSBartosz Golaszewski
174bcc61f1cSBartosz Golaszewski static struct max77650_regulator_desc max77650_SBB0_desc = {
175bcc61f1cSBartosz Golaszewski .desc = {
176bcc61f1cSBartosz Golaszewski .name = "sbb0",
177bcc61f1cSBartosz Golaszewski .of_match = of_match_ptr("sbb0"),
178bcc61f1cSBartosz Golaszewski .regulators_node = of_match_ptr("regulators"),
179bcc61f1cSBartosz Golaszewski .supply_name = "in-sbb0",
180bcc61f1cSBartosz Golaszewski .id = MAX77650_REGULATOR_ID_SBB0,
181bcc61f1cSBartosz Golaszewski .ops = &max77650_regulator_SBB_ops,
182bcc61f1cSBartosz Golaszewski .min_uV = 800000,
183bcc61f1cSBartosz Golaszewski .uV_step = 25000,
184bcc61f1cSBartosz Golaszewski .n_voltages = 64,
1853c7577d4SBartosz Golaszewski .vsel_step = 1,
186bcc61f1cSBartosz Golaszewski .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
187bcc61f1cSBartosz Golaszewski .vsel_reg = MAX77650_REG_CNFG_SBB0_A,
188bcc61f1cSBartosz Golaszewski .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
189bcc61f1cSBartosz Golaszewski .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
190bcc61f1cSBartosz Golaszewski .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
191bcc61f1cSBartosz Golaszewski .active_discharge_reg = MAX77650_REG_CNFG_SBB0_B,
192bcc61f1cSBartosz Golaszewski .enable_time = 100,
193bcc61f1cSBartosz Golaszewski .type = REGULATOR_VOLTAGE,
194721efb50SAxel Lin .owner = THIS_MODULE,
1956c98ac2aSAxel Lin .csel_reg = MAX77650_REG_CNFG_SBB0_A,
1966c98ac2aSAxel Lin .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
1976c98ac2aSAxel Lin .curr_table = max77650_current_limit_table,
1986c98ac2aSAxel Lin .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
199bcc61f1cSBartosz Golaszewski },
200bcc61f1cSBartosz Golaszewski .regA = MAX77650_REG_CNFG_SBB0_A,
201bcc61f1cSBartosz Golaszewski .regB = MAX77650_REG_CNFG_SBB0_B,
202bcc61f1cSBartosz Golaszewski };
203bcc61f1cSBartosz Golaszewski
204bcc61f1cSBartosz Golaszewski static struct max77650_regulator_desc max77650_SBB1_desc = {
205bcc61f1cSBartosz Golaszewski .desc = {
206bcc61f1cSBartosz Golaszewski .name = "sbb1",
207bcc61f1cSBartosz Golaszewski .of_match = of_match_ptr("sbb1"),
208bcc61f1cSBartosz Golaszewski .regulators_node = of_match_ptr("regulators"),
209bcc61f1cSBartosz Golaszewski .supply_name = "in-sbb1",
210bcc61f1cSBartosz Golaszewski .id = MAX77650_REGULATOR_ID_SBB1,
211bcc61f1cSBartosz Golaszewski .ops = &max77650_regulator_SBB_ops,
212bcc61f1cSBartosz Golaszewski .min_uV = 800000,
213bcc61f1cSBartosz Golaszewski .uV_step = 12500,
214bcc61f1cSBartosz Golaszewski .n_voltages = 64,
2153c7577d4SBartosz Golaszewski .vsel_step = 1,
216bcc61f1cSBartosz Golaszewski .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
217bcc61f1cSBartosz Golaszewski .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
218bcc61f1cSBartosz Golaszewski .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
219bcc61f1cSBartosz Golaszewski .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
220bcc61f1cSBartosz Golaszewski .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
221bcc61f1cSBartosz Golaszewski .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,
222bcc61f1cSBartosz Golaszewski .enable_time = 100,
223bcc61f1cSBartosz Golaszewski .type = REGULATOR_VOLTAGE,
224721efb50SAxel Lin .owner = THIS_MODULE,
2256c98ac2aSAxel Lin .csel_reg = MAX77650_REG_CNFG_SBB1_A,
2266c98ac2aSAxel Lin .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
2276c98ac2aSAxel Lin .curr_table = max77650_current_limit_table,
2286c98ac2aSAxel Lin .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
229bcc61f1cSBartosz Golaszewski },
230bcc61f1cSBartosz Golaszewski .regA = MAX77650_REG_CNFG_SBB1_A,
231bcc61f1cSBartosz Golaszewski .regB = MAX77650_REG_CNFG_SBB1_B,
232bcc61f1cSBartosz Golaszewski };
233bcc61f1cSBartosz Golaszewski
234bcc61f1cSBartosz Golaszewski static struct max77650_regulator_desc max77651_SBB1_desc = {
235bcc61f1cSBartosz Golaszewski .desc = {
236bcc61f1cSBartosz Golaszewski .name = "sbb1",
237bcc61f1cSBartosz Golaszewski .of_match = of_match_ptr("sbb1"),
238bcc61f1cSBartosz Golaszewski .regulators_node = of_match_ptr("regulators"),
239bcc61f1cSBartosz Golaszewski .supply_name = "in-sbb1",
240bcc61f1cSBartosz Golaszewski .id = MAX77650_REGULATOR_ID_SBB1,
241bcc61f1cSBartosz Golaszewski .ops = &max77651_SBB1_regulator_ops,
242*269cb04bSChen-Yu Tsai .linear_range_selectors_bitfield = max77651_sbb1_volt_range_sel,
2433df4235aSAxel Lin .linear_ranges = max77651_sbb1_volt_ranges,
2443df4235aSAxel Lin .n_linear_ranges = ARRAY_SIZE(max77651_sbb1_volt_ranges),
2453df4235aSAxel Lin .n_voltages = 58,
2463c7577d4SBartosz Golaszewski .vsel_step = 1,
2473df4235aSAxel Lin .vsel_range_mask = MAX77651_REGULATOR_V_SBB1_RANGE_MASK,
2483df4235aSAxel Lin .vsel_range_reg = MAX77650_REG_CNFG_SBB1_A,
2493df4235aSAxel Lin .vsel_mask = MAX77651_REGULATOR_V_SBB1_MASK,
250bcc61f1cSBartosz Golaszewski .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
251bcc61f1cSBartosz Golaszewski .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
252bcc61f1cSBartosz Golaszewski .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
253bcc61f1cSBartosz Golaszewski .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
254bcc61f1cSBartosz Golaszewski .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,
255bcc61f1cSBartosz Golaszewski .enable_time = 100,
256bcc61f1cSBartosz Golaszewski .type = REGULATOR_VOLTAGE,
257721efb50SAxel Lin .owner = THIS_MODULE,
2586c98ac2aSAxel Lin .csel_reg = MAX77650_REG_CNFG_SBB1_A,
2596c98ac2aSAxel Lin .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
2606c98ac2aSAxel Lin .curr_table = max77650_current_limit_table,
2616c98ac2aSAxel Lin .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
262bcc61f1cSBartosz Golaszewski },
263bcc61f1cSBartosz Golaszewski .regA = MAX77650_REG_CNFG_SBB1_A,
264bcc61f1cSBartosz Golaszewski .regB = MAX77650_REG_CNFG_SBB1_B,
265bcc61f1cSBartosz Golaszewski };
266bcc61f1cSBartosz Golaszewski
267bcc61f1cSBartosz Golaszewski static struct max77650_regulator_desc max77650_SBB2_desc = {
268bcc61f1cSBartosz Golaszewski .desc = {
269bcc61f1cSBartosz Golaszewski .name = "sbb2",
270bcc61f1cSBartosz Golaszewski .of_match = of_match_ptr("sbb2"),
271bcc61f1cSBartosz Golaszewski .regulators_node = of_match_ptr("regulators"),
272bcc61f1cSBartosz Golaszewski .supply_name = "in-sbb0",
273bcc61f1cSBartosz Golaszewski .id = MAX77650_REGULATOR_ID_SBB2,
274bcc61f1cSBartosz Golaszewski .ops = &max77650_regulator_SBB_ops,
275bcc61f1cSBartosz Golaszewski .min_uV = 800000,
276bcc61f1cSBartosz Golaszewski .uV_step = 50000,
277bcc61f1cSBartosz Golaszewski .n_voltages = 64,
2783c7577d4SBartosz Golaszewski .vsel_step = 1,
279bcc61f1cSBartosz Golaszewski .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
280bcc61f1cSBartosz Golaszewski .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
281bcc61f1cSBartosz Golaszewski .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
282bcc61f1cSBartosz Golaszewski .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
283bcc61f1cSBartosz Golaszewski .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
284bcc61f1cSBartosz Golaszewski .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,
285bcc61f1cSBartosz Golaszewski .enable_time = 100,
286bcc61f1cSBartosz Golaszewski .type = REGULATOR_VOLTAGE,
287721efb50SAxel Lin .owner = THIS_MODULE,
2886c98ac2aSAxel Lin .csel_reg = MAX77650_REG_CNFG_SBB2_A,
2896c98ac2aSAxel Lin .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
2906c98ac2aSAxel Lin .curr_table = max77650_current_limit_table,
2916c98ac2aSAxel Lin .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
292bcc61f1cSBartosz Golaszewski },
293bcc61f1cSBartosz Golaszewski .regA = MAX77650_REG_CNFG_SBB2_A,
294bcc61f1cSBartosz Golaszewski .regB = MAX77650_REG_CNFG_SBB2_B,
295bcc61f1cSBartosz Golaszewski };
296bcc61f1cSBartosz Golaszewski
297bcc61f1cSBartosz Golaszewski static struct max77650_regulator_desc max77651_SBB2_desc = {
298bcc61f1cSBartosz Golaszewski .desc = {
299bcc61f1cSBartosz Golaszewski .name = "sbb2",
300bcc61f1cSBartosz Golaszewski .of_match = of_match_ptr("sbb2"),
301bcc61f1cSBartosz Golaszewski .regulators_node = of_match_ptr("regulators"),
302bcc61f1cSBartosz Golaszewski .supply_name = "in-sbb0",
303bcc61f1cSBartosz Golaszewski .id = MAX77650_REGULATOR_ID_SBB2,
304bcc61f1cSBartosz Golaszewski .ops = &max77650_regulator_SBB_ops,
305bcc61f1cSBartosz Golaszewski .min_uV = 2400000,
306bcc61f1cSBartosz Golaszewski .uV_step = 50000,
307bcc61f1cSBartosz Golaszewski .n_voltages = 64,
3083c7577d4SBartosz Golaszewski .vsel_step = 1,
309bcc61f1cSBartosz Golaszewski .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
310bcc61f1cSBartosz Golaszewski .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
311bcc61f1cSBartosz Golaszewski .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
312bcc61f1cSBartosz Golaszewski .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
313bcc61f1cSBartosz Golaszewski .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
314bcc61f1cSBartosz Golaszewski .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,
315bcc61f1cSBartosz Golaszewski .enable_time = 100,
316bcc61f1cSBartosz Golaszewski .type = REGULATOR_VOLTAGE,
317721efb50SAxel Lin .owner = THIS_MODULE,
3186c98ac2aSAxel Lin .csel_reg = MAX77650_REG_CNFG_SBB2_A,
3196c98ac2aSAxel Lin .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
3206c98ac2aSAxel Lin .curr_table = max77650_current_limit_table,
3216c98ac2aSAxel Lin .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
322bcc61f1cSBartosz Golaszewski },
323bcc61f1cSBartosz Golaszewski .regA = MAX77650_REG_CNFG_SBB2_A,
324bcc61f1cSBartosz Golaszewski .regB = MAX77650_REG_CNFG_SBB2_B,
325bcc61f1cSBartosz Golaszewski };
326bcc61f1cSBartosz Golaszewski
max77650_regulator_probe(struct platform_device * pdev)327bcc61f1cSBartosz Golaszewski static int max77650_regulator_probe(struct platform_device *pdev)
328bcc61f1cSBartosz Golaszewski {
329bcc61f1cSBartosz Golaszewski struct max77650_regulator_desc **rdescs;
330bcc61f1cSBartosz Golaszewski struct max77650_regulator_desc *rdesc;
331bcc61f1cSBartosz Golaszewski struct regulator_config config = { };
332bcc61f1cSBartosz Golaszewski struct device *dev, *parent;
333bcc61f1cSBartosz Golaszewski struct regulator_dev *rdev;
334bcc61f1cSBartosz Golaszewski struct regmap *map;
335bcc61f1cSBartosz Golaszewski unsigned int val;
336bcc61f1cSBartosz Golaszewski int i, rv;
337bcc61f1cSBartosz Golaszewski
338bcc61f1cSBartosz Golaszewski dev = &pdev->dev;
339bcc61f1cSBartosz Golaszewski parent = dev->parent;
340bcc61f1cSBartosz Golaszewski
341bcc61f1cSBartosz Golaszewski if (!dev->of_node)
342bcc61f1cSBartosz Golaszewski dev->of_node = parent->of_node;
343bcc61f1cSBartosz Golaszewski
344bcc61f1cSBartosz Golaszewski rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,
345bcc61f1cSBartosz Golaszewski sizeof(*rdescs), GFP_KERNEL);
346bcc61f1cSBartosz Golaszewski if (!rdescs)
347bcc61f1cSBartosz Golaszewski return -ENOMEM;
348bcc61f1cSBartosz Golaszewski
349bcc61f1cSBartosz Golaszewski map = dev_get_regmap(parent, NULL);
350bcc61f1cSBartosz Golaszewski if (!map)
351bcc61f1cSBartosz Golaszewski return -ENODEV;
352bcc61f1cSBartosz Golaszewski
353bcc61f1cSBartosz Golaszewski rv = regmap_read(map, MAX77650_REG_CID, &val);
354bcc61f1cSBartosz Golaszewski if (rv)
355bcc61f1cSBartosz Golaszewski return rv;
356bcc61f1cSBartosz Golaszewski
357bcc61f1cSBartosz Golaszewski rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;
358bcc61f1cSBartosz Golaszewski rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;
359bcc61f1cSBartosz Golaszewski
360bcc61f1cSBartosz Golaszewski switch (MAX77650_CID_BITS(val)) {
361bcc61f1cSBartosz Golaszewski case MAX77650_CID_77650A:
362bcc61f1cSBartosz Golaszewski case MAX77650_CID_77650C:
363bcc61f1cSBartosz Golaszewski rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;
364bcc61f1cSBartosz Golaszewski rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;
365bcc61f1cSBartosz Golaszewski break;
366bcc61f1cSBartosz Golaszewski case MAX77650_CID_77651A:
367bcc61f1cSBartosz Golaszewski case MAX77650_CID_77651B:
368bcc61f1cSBartosz Golaszewski rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;
369bcc61f1cSBartosz Golaszewski rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;
370bcc61f1cSBartosz Golaszewski break;
371bcc61f1cSBartosz Golaszewski default:
372bcc61f1cSBartosz Golaszewski return -ENODEV;
373bcc61f1cSBartosz Golaszewski }
374bcc61f1cSBartosz Golaszewski
375bcc61f1cSBartosz Golaszewski config.dev = parent;
376bcc61f1cSBartosz Golaszewski
377bcc61f1cSBartosz Golaszewski for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {
378bcc61f1cSBartosz Golaszewski rdesc = rdescs[i];
379bcc61f1cSBartosz Golaszewski config.driver_data = rdesc;
380bcc61f1cSBartosz Golaszewski
381bcc61f1cSBartosz Golaszewski rdev = devm_regulator_register(dev, &rdesc->desc, &config);
382bcc61f1cSBartosz Golaszewski if (IS_ERR(rdev))
383bcc61f1cSBartosz Golaszewski return PTR_ERR(rdev);
384bcc61f1cSBartosz Golaszewski }
385bcc61f1cSBartosz Golaszewski
386bcc61f1cSBartosz Golaszewski return 0;
387bcc61f1cSBartosz Golaszewski }
388bcc61f1cSBartosz Golaszewski
389100a2110SBartosz Golaszewski static const struct of_device_id max77650_regulator_of_match[] = {
390100a2110SBartosz Golaszewski { .compatible = "maxim,max77650-regulator" },
391100a2110SBartosz Golaszewski { }
392100a2110SBartosz Golaszewski };
393100a2110SBartosz Golaszewski MODULE_DEVICE_TABLE(of, max77650_regulator_of_match);
394100a2110SBartosz Golaszewski
395bcc61f1cSBartosz Golaszewski static struct platform_driver max77650_regulator_driver = {
396bcc61f1cSBartosz Golaszewski .driver = {
397bcc61f1cSBartosz Golaszewski .name = "max77650-regulator",
398d3b81d97SDouglas Anderson .probe_type = PROBE_PREFER_ASYNCHRONOUS,
399100a2110SBartosz Golaszewski .of_match_table = max77650_regulator_of_match,
400bcc61f1cSBartosz Golaszewski },
401bcc61f1cSBartosz Golaszewski .probe = max77650_regulator_probe,
402bcc61f1cSBartosz Golaszewski };
403bcc61f1cSBartosz Golaszewski module_platform_driver(max77650_regulator_driver);
404bcc61f1cSBartosz Golaszewski
405bcc61f1cSBartosz Golaszewski MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
406bcc61f1cSBartosz Golaszewski MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
407bcc61f1cSBartosz Golaszewski MODULE_LICENSE("GPL v2");
408ba2bf340SBartosz Golaszewski MODULE_ALIAS("platform:max77650-regulator");
409