Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// Copyright (C) 2018 BayLibre SAS
  4// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
  5//
  6// Regulator driver for MAXIM 77650/77651 charger/power-supply.
  7
  8#include <linux/of.h>
  9#include <linux/mfd/max77650.h>
 10#include <linux/module.h>
 11#include <linux/platform_device.h>
 12#include <linux/regmap.h>
 13#include <linux/regulator/driver.h>
 14
 15#define MAX77650_REGULATOR_EN_CTRL_MASK		GENMASK(3, 0)
 16#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \
 17		((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)
 18#define MAX77650_REGULATOR_ENABLED		GENMASK(2, 1)
 19#define MAX77650_REGULATOR_DISABLED		BIT(2)
 20
 21#define MAX77650_REGULATOR_V_LDO_MASK		GENMASK(6, 0)
 22#define MAX77650_REGULATOR_V_SBB_MASK		GENMASK(5, 0)
 23#define MAX77651_REGULATOR_V_SBB1_MASK		GENMASK(5, 2)
 24#define MAX77651_REGULATOR_V_SBB1_RANGE_MASK	GENMASK(1, 0)
 25
 26#define MAX77650_REGULATOR_AD_MASK		BIT(3)
 27#define MAX77650_REGULATOR_AD_DISABLED		0x00
 28#define MAX77650_REGULATOR_AD_ENABLED		BIT(3)
 29
 30#define MAX77650_REGULATOR_CURR_LIM_MASK	GENMASK(7, 6)
 31
 32enum {
 33	MAX77650_REGULATOR_ID_LDO = 0,
 34	MAX77650_REGULATOR_ID_SBB0,
 35	MAX77650_REGULATOR_ID_SBB1,
 36	MAX77650_REGULATOR_ID_SBB2,
 37	MAX77650_REGULATOR_NUM_REGULATORS,
 38};
 39
 40struct max77650_regulator_desc {
 41	struct regulator_desc desc;
 42	unsigned int regA;
 43	unsigned int regB;
 44};
 45
 46static const unsigned int max77651_sbb1_volt_range_sel[] = {
 47	0x0, 0x1, 0x2, 0x3
 48};
 49
 50static const struct linear_range max77651_sbb1_volt_ranges[] = {
 51	/* range index 0 */
 52	REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),
 53	/* range index 1 */
 54	REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000),
 55	/* range index 2 */
 56	REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000),
 57	/* range index 3 */
 58	REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000),
 59};
 60
 61static const unsigned int max77650_current_limit_table[] = {
 62	1000000, 866000, 707000, 500000,
 63};
 64
 65static int max77650_regulator_is_enabled(struct regulator_dev *rdev)
 66{
 67	const struct max77650_regulator_desc *rdesc;
 68	struct regmap *map;
 69	int val, rv, en;
 70
 71	rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);
 72	map = rdev_get_regmap(rdev);
 73
 74	rv = regmap_read(map, rdesc->regB, &val);
 75	if (rv)
 76		return rv;
 77
 78	en = MAX77650_REGULATOR_EN_CTRL_BITS(val);
 79
 80	return en != MAX77650_REGULATOR_DISABLED;
 81}
 82
 83static int max77650_regulator_enable(struct regulator_dev *rdev)
 84{
 85	const struct max77650_regulator_desc *rdesc;
 86	struct regmap *map;
 87
 88	rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);
 89	map = rdev_get_regmap(rdev);
 90
 91	return regmap_update_bits(map, rdesc->regB,
 92				  MAX77650_REGULATOR_EN_CTRL_MASK,
 93				  MAX77650_REGULATOR_ENABLED);
 94}
 95
 96static int max77650_regulator_disable(struct regulator_dev *rdev)
 97{
 98	const struct max77650_regulator_desc *rdesc;
 99	struct regmap *map;
100
101	rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);
102	map = rdev_get_regmap(rdev);
103
104	return regmap_update_bits(map, rdesc->regB,
105				  MAX77650_REGULATOR_EN_CTRL_MASK,
106				  MAX77650_REGULATOR_DISABLED);
107}
108
109static const struct regulator_ops max77650_regulator_LDO_ops = {
110	.is_enabled		= max77650_regulator_is_enabled,
111	.enable			= max77650_regulator_enable,
112	.disable		= max77650_regulator_disable,
113	.list_voltage		= regulator_list_voltage_linear,
114	.map_voltage		= regulator_map_voltage_linear,
115	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
116	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
117	.set_active_discharge	= regulator_set_active_discharge_regmap,
118};
119
120static const struct regulator_ops max77650_regulator_SBB_ops = {
121	.is_enabled		= max77650_regulator_is_enabled,
122	.enable			= max77650_regulator_enable,
123	.disable		= max77650_regulator_disable,
124	.list_voltage		= regulator_list_voltage_linear,
125	.map_voltage		= regulator_map_voltage_linear,
126	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
127	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
128	.get_current_limit	= regulator_get_current_limit_regmap,
129	.set_current_limit	= regulator_set_current_limit_regmap,
130	.set_active_discharge	= regulator_set_active_discharge_regmap,
131};
132
133/* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */
134static const struct regulator_ops max77651_SBB1_regulator_ops = {
135	.is_enabled		= max77650_regulator_is_enabled,
136	.enable			= max77650_regulator_enable,
137	.disable		= max77650_regulator_disable,
138	.list_voltage		= regulator_list_voltage_pickable_linear_range,
139	.get_voltage_sel	= regulator_get_voltage_sel_pickable_regmap,
140	.set_voltage_sel	= regulator_set_voltage_sel_pickable_regmap,
141	.get_current_limit	= regulator_get_current_limit_regmap,
142	.set_current_limit	= regulator_set_current_limit_regmap,
143	.set_active_discharge	= regulator_set_active_discharge_regmap,
144};
145
146static const struct max77650_regulator_desc max77650_LDO_desc = {
147	.desc = {
148		.name			= "ldo",
149		.of_match		= of_match_ptr("ldo"),
150		.regulators_node	= of_match_ptr("regulators"),
151		.supply_name		= "in-ldo",
152		.id			= MAX77650_REGULATOR_ID_LDO,
153		.ops			= &max77650_regulator_LDO_ops,
154		.min_uV			= 1350000,
155		.uV_step		= 12500,
156		.n_voltages		= 128,
157		.vsel_step		= 1,
158		.vsel_mask		= MAX77650_REGULATOR_V_LDO_MASK,
159		.vsel_reg		= MAX77650_REG_CNFG_LDO_A,
160		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
161		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
162		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
163		.active_discharge_reg	= MAX77650_REG_CNFG_LDO_B,
164		.enable_time		= 100,
165		.type			= REGULATOR_VOLTAGE,
166		.owner			= THIS_MODULE,
167	},
168	.regA		= MAX77650_REG_CNFG_LDO_A,
169	.regB		= MAX77650_REG_CNFG_LDO_B,
170};
171
172static const struct max77650_regulator_desc max77650_SBB0_desc = {
173	.desc = {
174		.name			= "sbb0",
175		.of_match		= of_match_ptr("sbb0"),
176		.regulators_node	= of_match_ptr("regulators"),
177		.supply_name		= "in-sbb0",
178		.id			= MAX77650_REGULATOR_ID_SBB0,
179		.ops			= &max77650_regulator_SBB_ops,
180		.min_uV			= 800000,
181		.uV_step		= 25000,
182		.n_voltages		= 64,
183		.vsel_step		= 1,
184		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
185		.vsel_reg		= MAX77650_REG_CNFG_SBB0_A,
186		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
187		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
188		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
189		.active_discharge_reg	= MAX77650_REG_CNFG_SBB0_B,
190		.enable_time		= 100,
191		.type			= REGULATOR_VOLTAGE,
192		.owner			= THIS_MODULE,
193		.csel_reg		= MAX77650_REG_CNFG_SBB0_A,
194		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
195		.curr_table		= max77650_current_limit_table,
196		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
197	},
198	.regA		= MAX77650_REG_CNFG_SBB0_A,
199	.regB		= MAX77650_REG_CNFG_SBB0_B,
200};
201
202static const struct max77650_regulator_desc max77650_SBB1_desc = {
203	.desc = {
204		.name			= "sbb1",
205		.of_match		= of_match_ptr("sbb1"),
206		.regulators_node	= of_match_ptr("regulators"),
207		.supply_name		= "in-sbb1",
208		.id			= MAX77650_REGULATOR_ID_SBB1,
209		.ops			= &max77650_regulator_SBB_ops,
210		.min_uV			= 800000,
211		.uV_step		= 12500,
212		.n_voltages		= 64,
213		.vsel_step		= 1,
214		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
215		.vsel_reg		= MAX77650_REG_CNFG_SBB1_A,
216		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
217		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
218		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
219		.active_discharge_reg	= MAX77650_REG_CNFG_SBB1_B,
220		.enable_time		= 100,
221		.type			= REGULATOR_VOLTAGE,
222		.owner			= THIS_MODULE,
223		.csel_reg		= MAX77650_REG_CNFG_SBB1_A,
224		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
225		.curr_table		= max77650_current_limit_table,
226		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
227	},
228	.regA		= MAX77650_REG_CNFG_SBB1_A,
229	.regB		= MAX77650_REG_CNFG_SBB1_B,
230};
231
232static const struct max77650_regulator_desc max77651_SBB1_desc = {
233	.desc = {
234		.name			= "sbb1",
235		.of_match		= of_match_ptr("sbb1"),
236		.regulators_node	= of_match_ptr("regulators"),
237		.supply_name		= "in-sbb1",
238		.id			= MAX77650_REGULATOR_ID_SBB1,
239		.ops			= &max77651_SBB1_regulator_ops,
240		.linear_range_selectors_bitfield	= max77651_sbb1_volt_range_sel,
241		.linear_ranges		= max77651_sbb1_volt_ranges,
242		.n_linear_ranges	= ARRAY_SIZE(max77651_sbb1_volt_ranges),
243		.n_voltages		= 58,
244		.vsel_step		= 1,
245		.vsel_range_mask	= MAX77651_REGULATOR_V_SBB1_RANGE_MASK,
246		.vsel_range_reg		= MAX77650_REG_CNFG_SBB1_A,
247		.vsel_mask		= MAX77651_REGULATOR_V_SBB1_MASK,
248		.vsel_reg		= MAX77650_REG_CNFG_SBB1_A,
249		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
250		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
251		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
252		.active_discharge_reg	= MAX77650_REG_CNFG_SBB1_B,
253		.enable_time		= 100,
254		.type			= REGULATOR_VOLTAGE,
255		.owner			= THIS_MODULE,
256		.csel_reg		= MAX77650_REG_CNFG_SBB1_A,
257		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
258		.curr_table		= max77650_current_limit_table,
259		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
260	},
261	.regA		= MAX77650_REG_CNFG_SBB1_A,
262	.regB		= MAX77650_REG_CNFG_SBB1_B,
263};
264
265static const struct max77650_regulator_desc max77650_SBB2_desc = {
266	.desc = {
267		.name			= "sbb2",
268		.of_match		= of_match_ptr("sbb2"),
269		.regulators_node	= of_match_ptr("regulators"),
270		.supply_name		= "in-sbb0",
271		.id			= MAX77650_REGULATOR_ID_SBB2,
272		.ops			= &max77650_regulator_SBB_ops,
273		.min_uV			= 800000,
274		.uV_step		= 50000,
275		.n_voltages		= 64,
276		.vsel_step		= 1,
277		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
278		.vsel_reg		= MAX77650_REG_CNFG_SBB2_A,
279		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
280		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
281		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
282		.active_discharge_reg	= MAX77650_REG_CNFG_SBB2_B,
283		.enable_time		= 100,
284		.type			= REGULATOR_VOLTAGE,
285		.owner			= THIS_MODULE,
286		.csel_reg		= MAX77650_REG_CNFG_SBB2_A,
287		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
288		.curr_table		= max77650_current_limit_table,
289		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
290	},
291	.regA		= MAX77650_REG_CNFG_SBB2_A,
292	.regB		= MAX77650_REG_CNFG_SBB2_B,
293};
294
295static const struct max77650_regulator_desc max77651_SBB2_desc = {
296	.desc = {
297		.name			= "sbb2",
298		.of_match		= of_match_ptr("sbb2"),
299		.regulators_node	= of_match_ptr("regulators"),
300		.supply_name		= "in-sbb0",
301		.id			= MAX77650_REGULATOR_ID_SBB2,
302		.ops			= &max77650_regulator_SBB_ops,
303		.min_uV			= 2400000,
304		.uV_step		= 50000,
305		.n_voltages		= 64,
306		.vsel_step		= 1,
307		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
308		.vsel_reg		= MAX77650_REG_CNFG_SBB2_A,
309		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
310		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
311		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
312		.active_discharge_reg	= MAX77650_REG_CNFG_SBB2_B,
313		.enable_time		= 100,
314		.type			= REGULATOR_VOLTAGE,
315		.owner			= THIS_MODULE,
316		.csel_reg		= MAX77650_REG_CNFG_SBB2_A,
317		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
318		.curr_table		= max77650_current_limit_table,
319		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
320	},
321	.regA		= MAX77650_REG_CNFG_SBB2_A,
322	.regB		= MAX77650_REG_CNFG_SBB2_B,
323};
324
325static int max77650_regulator_probe(struct platform_device *pdev)
326{
327	const struct max77650_regulator_desc **rdescs;
328	const struct max77650_regulator_desc *rdesc;
329	struct regulator_config config = { };
330	struct device *dev, *parent;
331	struct regulator_dev *rdev;
332	struct regmap *map;
333	unsigned int val;
334	int i, rv;
335
336	dev = &pdev->dev;
337	parent = dev->parent;
338
339	if (!dev->of_node)
340		dev->of_node = parent->of_node;
341
342	rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,
343			      sizeof(*rdescs), GFP_KERNEL);
344	if (!rdescs)
345		return -ENOMEM;
346
347	map = dev_get_regmap(parent, NULL);
348	if (!map)
349		return -ENODEV;
350
351	rv = regmap_read(map, MAX77650_REG_CID, &val);
352	if (rv)
353		return rv;
354
355	rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;
356	rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;
357
358	switch (MAX77650_CID_BITS(val)) {
359	case MAX77650_CID_77650A:
360	case MAX77650_CID_77650C:
361		rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;
362		rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;
363		break;
364	case MAX77650_CID_77651A:
365	case MAX77650_CID_77651B:
366		rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;
367		rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;
368		break;
369	default:
370		return -ENODEV;
371	}
372
373	config.dev = parent;
374
375	for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {
376		rdesc = rdescs[i];
377
378		rdev = devm_regulator_register(dev, &rdesc->desc, &config);
379		if (IS_ERR(rdev))
380			return PTR_ERR(rdev);
381	}
382
383	return 0;
384}
385
386static const struct of_device_id max77650_regulator_of_match[] = {
387	{ .compatible = "maxim,max77650-regulator" },
388	{ }
389};
390MODULE_DEVICE_TABLE(of, max77650_regulator_of_match);
391
392static struct platform_driver max77650_regulator_driver = {
393	.driver = {
394		.name = "max77650-regulator",
395		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
396		.of_match_table = max77650_regulator_of_match,
397	},
398	.probe = max77650_regulator_probe,
399};
400module_platform_driver(max77650_regulator_driver);
401
402MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
403MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
404MODULE_LICENSE("GPL v2");
405MODULE_ALIAS("platform:max77650-regulator");