Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * max8907-regulator.c -- support regulators in max8907
  4 *
  5 * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
  6 * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved.
  7 *
  8 * Portions based on drivers/regulator/tps65910-regulator.c,
  9 *     Copyright 2010 Texas Instruments Inc.
 10 *     Author: Graeme Gregory <gg@slimlogic.co.uk>
 11 *     Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
 
 
 
 
 12 */
 13
 14#include <linux/err.h>
 15#include <linux/init.h>
 16#include <linux/mfd/core.h>
 17#include <linux/mfd/max8907.h>
 18#include <linux/module.h>
 19#include <linux/of.h>
 20#include <linux/platform_device.h>
 21#include <linux/regulator/driver.h>
 22#include <linux/regulator/machine.h>
 23#include <linux/regulator/of_regulator.h>
 24#include <linux/regmap.h>
 25#include <linux/slab.h>
 26
 27#define MAX8907_II2RR_VERSION_MASK	0xF0
 28#define MAX8907_II2RR_VERSION_REV_A	0x00
 29#define MAX8907_II2RR_VERSION_REV_B	0x10
 30#define MAX8907_II2RR_VERSION_REV_C	0x30
 31
 32struct max8907_regulator {
 33	struct regulator_desc desc[MAX8907_NUM_REGULATORS];
 34};
 35
 36#define REG_MBATT() \
 37	[MAX8907_MBATT] = { \
 38		.name = "MBATT", \
 39		.supply_name = "mbatt", \
 40		.id = MAX8907_MBATT, \
 41		.ops = &max8907_mbatt_ops, \
 42		.type = REGULATOR_VOLTAGE, \
 43		.owner = THIS_MODULE, \
 44	}
 45
 46#define REG_LDO(ids, supply, base, min, max, step) \
 47	[MAX8907_##ids] = { \
 48		.name = #ids, \
 49		.supply_name = supply, \
 50		.id = MAX8907_##ids, \
 51		.n_voltages = ((max) - (min)) / (step) + 1, \
 52		.ops = &max8907_ldo_ops, \
 53		.type = REGULATOR_VOLTAGE, \
 54		.owner = THIS_MODULE, \
 55		.min_uV = (min), \
 56		.uV_step = (step), \
 57		.vsel_reg = (base) + MAX8907_VOUT, \
 58		.vsel_mask = 0x3f, \
 59		.enable_reg = (base) + MAX8907_CTL, \
 60		.enable_mask = MAX8907_MASK_LDO_EN, \
 61	}
 62
 63#define REG_FIXED(ids, supply, voltage) \
 64	[MAX8907_##ids] = { \
 65		.name = #ids, \
 66		.supply_name = supply, \
 67		.id = MAX8907_##ids, \
 68		.n_voltages = 1, \
 69		.ops = &max8907_fixed_ops, \
 70		.type = REGULATOR_VOLTAGE, \
 71		.owner = THIS_MODULE, \
 72		.min_uV = (voltage), \
 73	}
 74
 75#define REG_OUT5V(ids, supply, base, voltage) \
 76	[MAX8907_##ids] = { \
 77		.name = #ids, \
 78		.supply_name = supply, \
 79		.id = MAX8907_##ids, \
 80		.n_voltages = 1, \
 81		.ops = &max8907_out5v_ops, \
 82		.type = REGULATOR_VOLTAGE, \
 83		.owner = THIS_MODULE, \
 84		.min_uV = (voltage), \
 85		.enable_reg = (base), \
 86		.enable_mask = MAX8907_MASK_OUT5V_EN, \
 87	}
 88
 89#define REG_BBAT(ids, supply, base, min, max, step) \
 90	[MAX8907_##ids] = { \
 91		.name = #ids, \
 92		.supply_name = supply, \
 93		.id = MAX8907_##ids, \
 94		.n_voltages = ((max) - (min)) / (step) + 1, \
 95		.ops = &max8907_bbat_ops, \
 96		.type = REGULATOR_VOLTAGE, \
 97		.owner = THIS_MODULE, \
 98		.min_uV = (min), \
 99		.uV_step = (step), \
100		.vsel_reg = (base), \
101		.vsel_mask = MAX8907_MASK_VBBATTCV, \
102	}
103
104#define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \
105			750000, 3900000, 50000)
106#define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \
107			650000, 2225000, 25000)
108
109static const struct regulator_ops max8907_mbatt_ops = {
110};
111
112static const struct regulator_ops max8907_ldo_ops = {
113	.list_voltage = regulator_list_voltage_linear,
114	.set_voltage_sel = regulator_set_voltage_sel_regmap,
115	.get_voltage_sel = regulator_get_voltage_sel_regmap,
116	.enable = regulator_enable_regmap,
117	.disable = regulator_disable_regmap,
118	.is_enabled = regulator_is_enabled_regmap,
119};
120
121static const struct regulator_ops max8907_ldo_hwctl_ops = {
122	.list_voltage = regulator_list_voltage_linear,
123	.set_voltage_sel = regulator_set_voltage_sel_regmap,
124	.get_voltage_sel = regulator_get_voltage_sel_regmap,
125};
126
127static const struct regulator_ops max8907_fixed_ops = {
128	.list_voltage = regulator_list_voltage_linear,
129};
130
131static const struct regulator_ops max8907_out5v_ops = {
132	.list_voltage = regulator_list_voltage_linear,
133	.enable = regulator_enable_regmap,
134	.disable = regulator_disable_regmap,
135	.is_enabled = regulator_is_enabled_regmap,
136};
137
138static const struct regulator_ops max8907_out5v_hwctl_ops = {
139	.list_voltage = regulator_list_voltage_linear,
140};
141
142static const struct regulator_ops max8907_bbat_ops = {
143	.list_voltage = regulator_list_voltage_linear,
144	.set_voltage_sel = regulator_set_voltage_sel_regmap,
145	.get_voltage_sel = regulator_get_voltage_sel_regmap,
146};
147
148static const struct regulator_desc max8907_regulators[] = {
149	REG_MBATT(),
150	REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000),
151	REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500),
152	REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000),
153	LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1),
154	LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2),
155	LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3),
156	LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4),
157	LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5),
158	LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6),
159	LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7),
160	LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8),
161	LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9),
162	LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10),
163	LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11),
164	LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12),
165	LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13),
166	LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14),
167	LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15),
168	LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16),
169	LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17),
170	LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18),
171	LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19),
172	LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20),
173	REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000),
174	REG_OUT5V(OUT33V, "mbatt",  MAX8907_REG_OUT33VEN, 3300000),
175	REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG,
176						2400000, 3000000, 200000),
177	REG_FIXED(SDBY, "MBATT", 1200000),
178	REG_FIXED(VRTC, "MBATT", 3300000),
179};
180
181#ifdef CONFIG_OF
182
183#define MATCH(_name, _id) \
184	[MAX8907_##_id] = { \
185		.name = #_name, \
186		.driver_data = (void *)&max8907_regulators[MAX8907_##_id], \
187	}
188
189static struct of_regulator_match max8907_matches[] = {
190	MATCH(mbatt, MBATT),
191	MATCH(sd1, SD1),
192	MATCH(sd2, SD2),
193	MATCH(sd3, SD3),
194	MATCH(ldo1, LDO1),
195	MATCH(ldo2, LDO2),
196	MATCH(ldo3, LDO3),
197	MATCH(ldo4, LDO4),
198	MATCH(ldo5, LDO5),
199	MATCH(ldo6, LDO6),
200	MATCH(ldo7, LDO7),
201	MATCH(ldo8, LDO8),
202	MATCH(ldo9, LDO9),
203	MATCH(ldo10, LDO10),
204	MATCH(ldo11, LDO11),
205	MATCH(ldo12, LDO12),
206	MATCH(ldo13, LDO13),
207	MATCH(ldo14, LDO14),
208	MATCH(ldo15, LDO15),
209	MATCH(ldo16, LDO16),
210	MATCH(ldo17, LDO17),
211	MATCH(ldo18, LDO18),
212	MATCH(ldo19, LDO19),
213	MATCH(ldo20, LDO20),
214	MATCH(out5v, OUT5V),
215	MATCH(out33v, OUT33V),
216	MATCH(bbat, BBAT),
217	MATCH(sdby, SDBY),
218	MATCH(vrtc, VRTC),
219};
220
221static int max8907_regulator_parse_dt(struct platform_device *pdev)
222{
223	struct device_node *np, *regulators;
224	int ret;
225
226	np = pdev->dev.parent->of_node;
227	if (!np)
228		return 0;
229
230	regulators = of_get_child_by_name(np, "regulators");
231	if (!regulators) {
232		dev_err(&pdev->dev, "regulators node not found\n");
233		return -EINVAL;
234	}
235
236	ret = of_regulator_match(&pdev->dev, regulators, max8907_matches,
237				 ARRAY_SIZE(max8907_matches));
238	of_node_put(regulators);
239	if (ret < 0) {
240		dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
241			ret);
242		return ret;
243	}
244
245	return 0;
246}
247
248static inline struct regulator_init_data *match_init_data(int index)
249{
250	return max8907_matches[index].init_data;
251}
252
253static inline struct device_node *match_of_node(int index)
254{
255	return max8907_matches[index].of_node;
256}
257#else
258static int max8907_regulator_parse_dt(struct platform_device *pdev)
259{
260	return 0;
261}
262
263static inline struct regulator_init_data *match_init_data(int index)
264{
265	return NULL;
266}
267
268static inline struct device_node *match_of_node(int index)
269{
270	return NULL;
271}
272#endif
273
274static int max8907_regulator_probe(struct platform_device *pdev)
275{
276	struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
277	struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
278	int ret;
279	struct max8907_regulator *pmic;
280	unsigned int val;
281	int i;
282	struct regulator_config config = {};
283	struct regulator_init_data *idata;
284	const char *mbatt_rail_name = NULL;
285
286	ret = max8907_regulator_parse_dt(pdev);
287	if (ret)
288		return ret;
289
290	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
291	if (!pmic)
292		return -ENOMEM;
293
294	platform_set_drvdata(pdev, pmic);
295
296	memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
297
298	/* Backwards compatibility with MAX8907B; SD1 uses different voltages */
299	ret = regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
300	if (ret)
301		return ret;
302
303	if ((val & MAX8907_II2RR_VERSION_MASK) ==
304	    MAX8907_II2RR_VERSION_REV_B) {
305		pmic->desc[MAX8907_SD1].min_uV = 637500;
306		pmic->desc[MAX8907_SD1].uV_step = 12500;
307		pmic->desc[MAX8907_SD1].n_voltages =
308						(1425000 - 637500) / 12500 + 1;
309	}
310
311	for (i = 0; i < MAX8907_NUM_REGULATORS; i++) {
312		struct regulator_dev *rdev;
313
314		config.dev = pdev->dev.parent;
315		if (pdata)
316			idata = pdata->init_data[i];
317		else
318			idata = match_init_data(i);
319		config.init_data = idata;
320		config.driver_data = pmic;
321		config.regmap = max8907->regmap_gen;
322		config.of_node = match_of_node(i);
323
324		switch (pmic->desc[i].id) {
325		case MAX8907_MBATT:
326			if (idata && idata->constraints.name)
327				mbatt_rail_name = idata->constraints.name;
328			else
329				mbatt_rail_name = pmic->desc[i].name;
330			break;
331		case MAX8907_BBAT:
332		case MAX8907_SDBY:
333		case MAX8907_VRTC:
334			idata->supply_regulator = mbatt_rail_name;
335			break;
336		}
337
338		if (pmic->desc[i].ops == &max8907_ldo_ops) {
339			ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
340				    &val);
341			if (ret)
342				return ret;
343
344			if ((val & MAX8907_MASK_LDO_SEQ) !=
345			    MAX8907_MASK_LDO_SEQ)
346				pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
347		} else if (pmic->desc[i].ops == &max8907_out5v_ops) {
348			ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
349				    &val);
350			if (ret)
351				return ret;
352
353			if ((val & (MAX8907_MASK_OUT5V_VINEN |
354						MAX8907_MASK_OUT5V_ENSRC)) !=
355			    MAX8907_MASK_OUT5V_ENSRC)
356				pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
357		}
358
359		rdev = devm_regulator_register(&pdev->dev,
360						&pmic->desc[i], &config);
361		if (IS_ERR(rdev)) {
362			dev_err(&pdev->dev,
363				"failed to register %s regulator\n",
364				pmic->desc[i].name);
365			return PTR_ERR(rdev);
366		}
367	}
368
369	return 0;
370}
371
372static struct platform_driver max8907_regulator_driver = {
373	.driver = {
374		   .name = "max8907-regulator",
375		   .probe_type = PROBE_PREFER_ASYNCHRONOUS,
376		   },
377	.probe = max8907_regulator_probe,
378};
379
380static int __init max8907_regulator_init(void)
381{
382	return platform_driver_register(&max8907_regulator_driver);
383}
384
385subsys_initcall(max8907_regulator_init);
386
387static void __exit max8907_reg_exit(void)
388{
389	platform_driver_unregister(&max8907_regulator_driver);
390}
391
392module_exit(max8907_reg_exit);
393
394MODULE_DESCRIPTION("MAX8907 regulator driver");
395MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
396MODULE_LICENSE("GPL v2");
397MODULE_ALIAS("platform:max8907-regulator");
v4.10.11
 
  1/*
  2 * max8907-regulator.c -- support regulators in max8907
  3 *
  4 * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
  5 * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved.
  6 *
  7 * Portions based on drivers/regulator/tps65910-regulator.c,
  8 *     Copyright 2010 Texas Instruments Inc.
  9 *     Author: Graeme Gregory <gg@slimlogic.co.uk>
 10 *     Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
 11 *
 12 * This program is free software; you can redistribute it and/or modify
 13 * it under the terms of the GNU General Public License version 2 as
 14 * published by the Free Software Foundation.
 15 */
 16
 17#include <linux/err.h>
 18#include <linux/init.h>
 19#include <linux/mfd/core.h>
 20#include <linux/mfd/max8907.h>
 21#include <linux/module.h>
 22#include <linux/of.h>
 23#include <linux/platform_device.h>
 24#include <linux/regulator/driver.h>
 25#include <linux/regulator/machine.h>
 26#include <linux/regulator/of_regulator.h>
 27#include <linux/regmap.h>
 28#include <linux/slab.h>
 29
 30#define MAX8907_II2RR_VERSION_MASK	0xF0
 31#define MAX8907_II2RR_VERSION_REV_A	0x00
 32#define MAX8907_II2RR_VERSION_REV_B	0x10
 33#define MAX8907_II2RR_VERSION_REV_C	0x30
 34
 35struct max8907_regulator {
 36	struct regulator_desc desc[MAX8907_NUM_REGULATORS];
 37};
 38
 39#define REG_MBATT() \
 40	[MAX8907_MBATT] = { \
 41		.name = "MBATT", \
 42		.supply_name = "mbatt", \
 43		.id = MAX8907_MBATT, \
 44		.ops = &max8907_mbatt_ops, \
 45		.type = REGULATOR_VOLTAGE, \
 46		.owner = THIS_MODULE, \
 47	}
 48
 49#define REG_LDO(ids, supply, base, min, max, step) \
 50	[MAX8907_##ids] = { \
 51		.name = #ids, \
 52		.supply_name = supply, \
 53		.id = MAX8907_##ids, \
 54		.n_voltages = ((max) - (min)) / (step) + 1, \
 55		.ops = &max8907_ldo_ops, \
 56		.type = REGULATOR_VOLTAGE, \
 57		.owner = THIS_MODULE, \
 58		.min_uV = (min), \
 59		.uV_step = (step), \
 60		.vsel_reg = (base) + MAX8907_VOUT, \
 61		.vsel_mask = 0x3f, \
 62		.enable_reg = (base) + MAX8907_CTL, \
 63		.enable_mask = MAX8907_MASK_LDO_EN, \
 64	}
 65
 66#define REG_FIXED(ids, supply, voltage) \
 67	[MAX8907_##ids] = { \
 68		.name = #ids, \
 69		.supply_name = supply, \
 70		.id = MAX8907_##ids, \
 71		.n_voltages = 1, \
 72		.ops = &max8907_fixed_ops, \
 73		.type = REGULATOR_VOLTAGE, \
 74		.owner = THIS_MODULE, \
 75		.min_uV = (voltage), \
 76	}
 77
 78#define REG_OUT5V(ids, supply, base, voltage) \
 79	[MAX8907_##ids] = { \
 80		.name = #ids, \
 81		.supply_name = supply, \
 82		.id = MAX8907_##ids, \
 83		.n_voltages = 1, \
 84		.ops = &max8907_out5v_ops, \
 85		.type = REGULATOR_VOLTAGE, \
 86		.owner = THIS_MODULE, \
 87		.min_uV = (voltage), \
 88		.enable_reg = (base), \
 89		.enable_mask = MAX8907_MASK_OUT5V_EN, \
 90	}
 91
 92#define REG_BBAT(ids, supply, base, min, max, step) \
 93	[MAX8907_##ids] = { \
 94		.name = #ids, \
 95		.supply_name = supply, \
 96		.id = MAX8907_##ids, \
 97		.n_voltages = ((max) - (min)) / (step) + 1, \
 98		.ops = &max8907_bbat_ops, \
 99		.type = REGULATOR_VOLTAGE, \
100		.owner = THIS_MODULE, \
101		.min_uV = (min), \
102		.uV_step = (step), \
103		.vsel_reg = (base), \
104		.vsel_mask = MAX8907_MASK_VBBATTCV, \
105	}
106
107#define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \
108			750000, 3900000, 50000)
109#define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \
110			650000, 2225000, 25000)
111
112static struct regulator_ops max8907_mbatt_ops = {
113};
114
115static struct regulator_ops max8907_ldo_ops = {
116	.list_voltage = regulator_list_voltage_linear,
117	.set_voltage_sel = regulator_set_voltage_sel_regmap,
118	.get_voltage_sel = regulator_get_voltage_sel_regmap,
119	.enable = regulator_enable_regmap,
120	.disable = regulator_disable_regmap,
121	.is_enabled = regulator_is_enabled_regmap,
122};
123
124static struct regulator_ops max8907_ldo_hwctl_ops = {
125	.list_voltage = regulator_list_voltage_linear,
126	.set_voltage_sel = regulator_set_voltage_sel_regmap,
127	.get_voltage_sel = regulator_get_voltage_sel_regmap,
128};
129
130static struct regulator_ops max8907_fixed_ops = {
131	.list_voltage = regulator_list_voltage_linear,
132};
133
134static struct regulator_ops max8907_out5v_ops = {
135	.list_voltage = regulator_list_voltage_linear,
136	.enable = regulator_enable_regmap,
137	.disable = regulator_disable_regmap,
138	.is_enabled = regulator_is_enabled_regmap,
139};
140
141static struct regulator_ops max8907_out5v_hwctl_ops = {
142	.list_voltage = regulator_list_voltage_linear,
143};
144
145static struct regulator_ops max8907_bbat_ops = {
146	.list_voltage = regulator_list_voltage_linear,
147	.set_voltage_sel = regulator_set_voltage_sel_regmap,
148	.get_voltage_sel = regulator_get_voltage_sel_regmap,
149};
150
151static struct regulator_desc max8907_regulators[] = {
152	REG_MBATT(),
153	REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000),
154	REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500),
155	REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000),
156	LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1),
157	LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2),
158	LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3),
159	LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4),
160	LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5),
161	LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6),
162	LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7),
163	LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8),
164	LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9),
165	LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10),
166	LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11),
167	LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12),
168	LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13),
169	LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14),
170	LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15),
171	LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16),
172	LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17),
173	LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18),
174	LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19),
175	LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20),
176	REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000),
177	REG_OUT5V(OUT33V, "mbatt",  MAX8907_REG_OUT33VEN, 3300000),
178	REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG,
179						2400000, 3000000, 200000),
180	REG_FIXED(SDBY, "MBATT", 1200000),
181	REG_FIXED(VRTC, "MBATT", 3300000),
182};
183
184#ifdef CONFIG_OF
185
186#define MATCH(_name, _id) \
187	[MAX8907_##_id] = { \
188		.name = #_name, \
189		.driver_data = (void *)&max8907_regulators[MAX8907_##_id], \
190	}
191
192static struct of_regulator_match max8907_matches[] = {
193	MATCH(mbatt, MBATT),
194	MATCH(sd1, SD1),
195	MATCH(sd2, SD2),
196	MATCH(sd3, SD3),
197	MATCH(ldo1, LDO1),
198	MATCH(ldo2, LDO2),
199	MATCH(ldo3, LDO3),
200	MATCH(ldo4, LDO4),
201	MATCH(ldo5, LDO5),
202	MATCH(ldo6, LDO6),
203	MATCH(ldo7, LDO7),
204	MATCH(ldo8, LDO8),
205	MATCH(ldo9, LDO9),
206	MATCH(ldo10, LDO10),
207	MATCH(ldo11, LDO11),
208	MATCH(ldo12, LDO12),
209	MATCH(ldo13, LDO13),
210	MATCH(ldo14, LDO14),
211	MATCH(ldo15, LDO15),
212	MATCH(ldo16, LDO16),
213	MATCH(ldo17, LDO17),
214	MATCH(ldo18, LDO18),
215	MATCH(ldo19, LDO19),
216	MATCH(ldo20, LDO20),
217	MATCH(out5v, OUT5V),
218	MATCH(out33v, OUT33V),
219	MATCH(bbat, BBAT),
220	MATCH(sdby, SDBY),
221	MATCH(vrtc, VRTC),
222};
223
224static int max8907_regulator_parse_dt(struct platform_device *pdev)
225{
226	struct device_node *np, *regulators;
227	int ret;
228
229	np = pdev->dev.parent->of_node;
230	if (!np)
231		return 0;
232
233	regulators = of_get_child_by_name(np, "regulators");
234	if (!regulators) {
235		dev_err(&pdev->dev, "regulators node not found\n");
236		return -EINVAL;
237	}
238
239	ret = of_regulator_match(&pdev->dev, regulators, max8907_matches,
240				 ARRAY_SIZE(max8907_matches));
241	of_node_put(regulators);
242	if (ret < 0) {
243		dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
244			ret);
245		return ret;
246	}
247
248	return 0;
249}
250
251static inline struct regulator_init_data *match_init_data(int index)
252{
253	return max8907_matches[index].init_data;
254}
255
256static inline struct device_node *match_of_node(int index)
257{
258	return max8907_matches[index].of_node;
259}
260#else
261static int max8907_regulator_parse_dt(struct platform_device *pdev)
262{
263	return 0;
264}
265
266static inline struct regulator_init_data *match_init_data(int index)
267{
268	return NULL;
269}
270
271static inline struct device_node *match_of_node(int index)
272{
273	return NULL;
274}
275#endif
276
277static int max8907_regulator_probe(struct platform_device *pdev)
278{
279	struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
280	struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
281	int ret;
282	struct max8907_regulator *pmic;
283	unsigned int val;
284	int i;
285	struct regulator_config config = {};
286	struct regulator_init_data *idata;
287	const char *mbatt_rail_name = NULL;
288
289	ret = max8907_regulator_parse_dt(pdev);
290	if (ret)
291		return ret;
292
293	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
294	if (!pmic)
295		return -ENOMEM;
296
297	platform_set_drvdata(pdev, pmic);
298
299	memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
300
301	/* Backwards compatibility with MAX8907B; SD1 uses different voltages */
302	regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
 
 
 
303	if ((val & MAX8907_II2RR_VERSION_MASK) ==
304	    MAX8907_II2RR_VERSION_REV_B) {
305		pmic->desc[MAX8907_SD1].min_uV = 637500;
306		pmic->desc[MAX8907_SD1].uV_step = 12500;
307		pmic->desc[MAX8907_SD1].n_voltages =
308						(1425000 - 637500) / 12500 + 1;
309	}
310
311	for (i = 0; i < MAX8907_NUM_REGULATORS; i++) {
312		struct regulator_dev *rdev;
313
314		config.dev = pdev->dev.parent;
315		if (pdata)
316			idata = pdata->init_data[i];
317		else
318			idata = match_init_data(i);
319		config.init_data = idata;
320		config.driver_data = pmic;
321		config.regmap = max8907->regmap_gen;
322		config.of_node = match_of_node(i);
323
324		switch (pmic->desc[i].id) {
325		case MAX8907_MBATT:
326			if (idata && idata->constraints.name)
327				mbatt_rail_name = idata->constraints.name;
328			else
329				mbatt_rail_name = pmic->desc[i].name;
330			break;
331		case MAX8907_BBAT:
332		case MAX8907_SDBY:
333		case MAX8907_VRTC:
334			idata->supply_regulator = mbatt_rail_name;
335			break;
336		}
337
338		if (pmic->desc[i].ops == &max8907_ldo_ops) {
339			regmap_read(config.regmap, pmic->desc[i].enable_reg,
340				    &val);
 
 
 
341			if ((val & MAX8907_MASK_LDO_SEQ) !=
342			    MAX8907_MASK_LDO_SEQ)
343				pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
344		} else if (pmic->desc[i].ops == &max8907_out5v_ops) {
345			regmap_read(config.regmap, pmic->desc[i].enable_reg,
346				    &val);
 
 
 
347			if ((val & (MAX8907_MASK_OUT5V_VINEN |
348						MAX8907_MASK_OUT5V_ENSRC)) !=
349			    MAX8907_MASK_OUT5V_ENSRC)
350				pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
351		}
352
353		rdev = devm_regulator_register(&pdev->dev,
354						&pmic->desc[i], &config);
355		if (IS_ERR(rdev)) {
356			dev_err(&pdev->dev,
357				"failed to register %s regulator\n",
358				pmic->desc[i].name);
359			return PTR_ERR(rdev);
360		}
361	}
362
363	return 0;
364}
365
366static struct platform_driver max8907_regulator_driver = {
367	.driver = {
368		   .name = "max8907-regulator",
 
369		   },
370	.probe = max8907_regulator_probe,
371};
372
373static int __init max8907_regulator_init(void)
374{
375	return platform_driver_register(&max8907_regulator_driver);
376}
377
378subsys_initcall(max8907_regulator_init);
379
380static void __exit max8907_reg_exit(void)
381{
382	platform_driver_unregister(&max8907_regulator_driver);
383}
384
385module_exit(max8907_reg_exit);
386
387MODULE_DESCRIPTION("MAX8907 regulator driver");
388MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
389MODULE_LICENSE("GPL v2");
390MODULE_ALIAS("platform:max8907-regulator");