xref: /openbmc/linux/drivers/regulator/max77650-regulator.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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