Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2#include <linux/i2c.h>
  3#include <linux/module.h>
  4#include <linux/platform_device.h>
  5#include <linux/regmap.h>
  6#include <linux/regulator/driver.h>
  7
  8#include <linux/mfd/88pm886.h>
  9
 10static const struct regmap_config pm886_regulator_regmap_config = {
 11	.reg_bits = 8,
 12	.val_bits = 8,
 13	.max_register = PM886_REG_BUCK5_VOUT,
 14};
 15
 16static const struct regulator_ops pm886_ldo_ops = {
 17	.list_voltage = regulator_list_voltage_table,
 18	.map_voltage = regulator_map_voltage_iterate,
 19	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 20	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 21	.enable = regulator_enable_regmap,
 22	.disable = regulator_disable_regmap,
 23	.is_enabled = regulator_is_enabled_regmap,
 24};
 25
 26static const struct regulator_ops pm886_buck_ops = {
 27	.list_voltage = regulator_list_voltage_linear_range,
 28	.map_voltage = regulator_map_voltage_linear_range,
 29	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 30	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 31	.enable = regulator_enable_regmap,
 32	.disable = regulator_disable_regmap,
 33	.is_enabled = regulator_is_enabled_regmap,
 34};
 35
 36static const unsigned int pm886_ldo_volt_table1[] = {
 37	1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000,
 38};
 39
 40static const unsigned int pm886_ldo_volt_table2[] = {
 41	1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000,
 42	2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,
 43};
 44
 45static const unsigned int pm886_ldo_volt_table3[] = {
 46	1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000,
 47};
 48
 49static const struct linear_range pm886_buck_volt_ranges1[] = {
 50	REGULATOR_LINEAR_RANGE(600000, 0, 79, 12500),
 51	REGULATOR_LINEAR_RANGE(1600000, 80, 84, 50000),
 52};
 53
 54static const struct linear_range pm886_buck_volt_ranges2[] = {
 55	REGULATOR_LINEAR_RANGE(600000, 0, 79, 12500),
 56	REGULATOR_LINEAR_RANGE(1600000, 80, 114, 50000),
 57};
 58
 59static struct regulator_desc pm886_regulators[] = {
 60	{
 61		.name = "LDO1",
 62		.regulators_node = "regulators",
 63		.of_match = "ldo1",
 64		.ops = &pm886_ldo_ops,
 65		.type = REGULATOR_VOLTAGE,
 66		.enable_reg = PM886_REG_LDO_EN1,
 67		.enable_mask = BIT(0),
 68		.volt_table = pm886_ldo_volt_table1,
 69		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1),
 70		.vsel_reg = PM886_REG_LDO1_VOUT,
 71		.vsel_mask = PM886_LDO_VSEL_MASK,
 72	},
 73	{
 74		.name = "LDO2",
 75		.regulators_node = "regulators",
 76		.of_match = "ldo2",
 77		.ops = &pm886_ldo_ops,
 78		.type = REGULATOR_VOLTAGE,
 79		.enable_reg = PM886_REG_LDO_EN1,
 80		.enable_mask = BIT(1),
 81		.volt_table = pm886_ldo_volt_table1,
 82		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1),
 83		.vsel_reg = PM886_REG_LDO2_VOUT,
 84		.vsel_mask = PM886_LDO_VSEL_MASK,
 85	},
 86	{
 87		.name = "LDO3",
 88		.regulators_node = "regulators",
 89		.of_match = "ldo3",
 90		.ops = &pm886_ldo_ops,
 91		.type = REGULATOR_VOLTAGE,
 92		.enable_reg = PM886_REG_LDO_EN1,
 93		.enable_mask = BIT(2),
 94		.volt_table = pm886_ldo_volt_table1,
 95		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1),
 96		.vsel_reg = PM886_REG_LDO3_VOUT,
 97		.vsel_mask = PM886_LDO_VSEL_MASK,
 98	},
 99	{
100		.name = "LDO4",
101		.regulators_node = "regulators",
102		.of_match = "ldo4",
103		.ops = &pm886_ldo_ops,
104		.type = REGULATOR_VOLTAGE,
105		.enable_reg = PM886_REG_LDO_EN1,
106		.enable_mask = BIT(3),
107		.volt_table = pm886_ldo_volt_table2,
108		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
109		.vsel_reg = PM886_REG_LDO4_VOUT,
110		.vsel_mask = PM886_LDO_VSEL_MASK,
111	},
112	{
113		.name = "LDO5",
114		.regulators_node = "regulators",
115		.of_match = "ldo5",
116		.ops = &pm886_ldo_ops,
117		.type = REGULATOR_VOLTAGE,
118		.enable_reg = PM886_REG_LDO_EN1,
119		.enable_mask = BIT(4),
120		.volt_table = pm886_ldo_volt_table2,
121		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
122		.vsel_reg = PM886_REG_LDO5_VOUT,
123		.vsel_mask = PM886_LDO_VSEL_MASK,
124	},
125	{
126		.name = "LDO6",
127		.regulators_node = "regulators",
128		.of_match = "ldo6",
129		.ops = &pm886_ldo_ops,
130		.type = REGULATOR_VOLTAGE,
131		.enable_reg = PM886_REG_LDO_EN1,
132		.enable_mask = BIT(5),
133		.volt_table = pm886_ldo_volt_table2,
134		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
135		.vsel_reg = PM886_REG_LDO6_VOUT,
136		.vsel_mask = PM886_LDO_VSEL_MASK,
137	},
138	{
139		.name = "LDO7",
140		.regulators_node = "regulators",
141		.of_match = "ldo7",
142		.ops = &pm886_ldo_ops,
143		.type = REGULATOR_VOLTAGE,
144		.enable_reg = PM886_REG_LDO_EN1,
145		.enable_mask = BIT(6),
146		.volt_table = pm886_ldo_volt_table2,
147		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
148		.vsel_reg = PM886_REG_LDO7_VOUT,
149		.vsel_mask = PM886_LDO_VSEL_MASK,
150	},
151	{
152		.name = "LDO8",
153		.regulators_node = "regulators",
154		.of_match = "ldo8",
155		.ops = &pm886_ldo_ops,
156		.type = REGULATOR_VOLTAGE,
157		.enable_reg = PM886_REG_LDO_EN1,
158		.enable_mask = BIT(7),
159		.volt_table = pm886_ldo_volt_table2,
160		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
161		.vsel_reg = PM886_REG_LDO8_VOUT,
162		.vsel_mask = PM886_LDO_VSEL_MASK,
163	},
164	{
165		.name = "LDO9",
166		.regulators_node = "regulators",
167		.of_match = "ldo9",
168		.ops = &pm886_ldo_ops,
169		.type = REGULATOR_VOLTAGE,
170		.enable_reg = PM886_REG_LDO_EN2,
171		.enable_mask = BIT(0),
172		.volt_table = pm886_ldo_volt_table2,
173		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
174		.vsel_reg = PM886_REG_LDO9_VOUT,
175		.vsel_mask = PM886_LDO_VSEL_MASK,
176	},
177	{
178		.name = "LDO10",
179		.regulators_node = "regulators",
180		.of_match = "ldo10",
181		.ops = &pm886_ldo_ops,
182		.type = REGULATOR_VOLTAGE,
183		.enable_reg = PM886_REG_LDO_EN2,
184		.enable_mask = BIT(1),
185		.volt_table = pm886_ldo_volt_table2,
186		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
187		.vsel_reg = PM886_REG_LDO10_VOUT,
188		.vsel_mask = PM886_LDO_VSEL_MASK,
189	},
190	{
191		.name = "LDO11",
192		.regulators_node = "regulators",
193		.of_match = "ldo11",
194		.ops = &pm886_ldo_ops,
195		.type = REGULATOR_VOLTAGE,
196		.enable_reg = PM886_REG_LDO_EN2,
197		.enable_mask = BIT(2),
198		.volt_table = pm886_ldo_volt_table2,
199		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
200		.vsel_reg = PM886_REG_LDO11_VOUT,
201		.vsel_mask = PM886_LDO_VSEL_MASK,
202	},
203	{
204		.name = "LDO12",
205		.regulators_node = "regulators",
206		.of_match = "ldo12",
207		.ops = &pm886_ldo_ops,
208		.type = REGULATOR_VOLTAGE,
209		.enable_reg = PM886_REG_LDO_EN2,
210		.enable_mask = BIT(3),
211		.volt_table = pm886_ldo_volt_table2,
212		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
213		.vsel_reg = PM886_REG_LDO12_VOUT,
214		.vsel_mask = PM886_LDO_VSEL_MASK,
215	},
216	{
217		.name = "LDO13",
218		.regulators_node = "regulators",
219		.of_match = "ldo13",
220		.ops = &pm886_ldo_ops,
221		.type = REGULATOR_VOLTAGE,
222		.enable_reg = PM886_REG_LDO_EN2,
223		.enable_mask = BIT(4),
224		.volt_table = pm886_ldo_volt_table2,
225		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
226		.vsel_reg = PM886_REG_LDO13_VOUT,
227		.vsel_mask = PM886_LDO_VSEL_MASK,
228	},
229	{
230		.name = "LDO14",
231		.regulators_node = "regulators",
232		.of_match = "ldo14",
233		.ops = &pm886_ldo_ops,
234		.type = REGULATOR_VOLTAGE,
235		.enable_reg = PM886_REG_LDO_EN2,
236		.enable_mask = BIT(5),
237		.volt_table = pm886_ldo_volt_table2,
238		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
239		.vsel_reg = PM886_REG_LDO14_VOUT,
240		.vsel_mask = PM886_LDO_VSEL_MASK,
241	},
242	{
243		.name = "LDO15",
244		.regulators_node = "regulators",
245		.of_match = "ldo15",
246		.ops = &pm886_ldo_ops,
247		.type = REGULATOR_VOLTAGE,
248		.enable_reg = PM886_REG_LDO_EN2,
249		.enable_mask = BIT(6),
250		.volt_table = pm886_ldo_volt_table2,
251		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),
252		.vsel_reg = PM886_REG_LDO15_VOUT,
253		.vsel_mask = PM886_LDO_VSEL_MASK,
254	},
255	{
256		.name = "LDO16",
257		.regulators_node = "regulators",
258		.of_match = "ldo16",
259		.ops = &pm886_ldo_ops,
260		.type = REGULATOR_VOLTAGE,
261		.enable_reg = PM886_REG_LDO_EN2,
262		.enable_mask = BIT(7),
263		.volt_table = pm886_ldo_volt_table3,
264		.n_voltages = ARRAY_SIZE(pm886_ldo_volt_table3),
265		.vsel_reg = PM886_REG_LDO16_VOUT,
266		.vsel_mask = PM886_LDO_VSEL_MASK,
267	},
268	{
269		.name = "buck1",
270		.regulators_node = "regulators",
271		.of_match = "buck1",
272		.ops = &pm886_buck_ops,
273		.type = REGULATOR_VOLTAGE,
274		.n_voltages = 85,
275		.linear_ranges = pm886_buck_volt_ranges1,
276		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges1),
277		.vsel_reg = PM886_REG_BUCK1_VOUT,
278		.vsel_mask = PM886_BUCK_VSEL_MASK,
279		.enable_reg = PM886_REG_BUCK_EN,
280		.enable_mask = BIT(0),
281	},
282	{
283		.name = "buck2",
284		.regulators_node = "regulators",
285		.of_match = "buck2",
286		.ops = &pm886_buck_ops,
287		.type = REGULATOR_VOLTAGE,
288		.n_voltages = 115,
289		.linear_ranges = pm886_buck_volt_ranges2,
290		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),
291		.vsel_reg = PM886_REG_BUCK2_VOUT,
292		.vsel_mask = PM886_BUCK_VSEL_MASK,
293		.enable_reg = PM886_REG_BUCK_EN,
294		.enable_mask = BIT(1),
295	},
296	{
297		.name = "buck3",
298		.regulators_node = "regulators",
299		.of_match = "buck3",
300		.ops = &pm886_buck_ops,
301		.type = REGULATOR_VOLTAGE,
302		.n_voltages = 115,
303		.linear_ranges = pm886_buck_volt_ranges2,
304		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),
305		.vsel_reg = PM886_REG_BUCK3_VOUT,
306		.vsel_mask = PM886_BUCK_VSEL_MASK,
307		.enable_reg = PM886_REG_BUCK_EN,
308		.enable_mask = BIT(2),
309	},
310	{
311		.name = "buck4",
312		.regulators_node = "regulators",
313		.of_match = "buck4",
314		.ops = &pm886_buck_ops,
315		.type = REGULATOR_VOLTAGE,
316		.n_voltages = 115,
317		.linear_ranges = pm886_buck_volt_ranges2,
318		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),
319		.vsel_reg = PM886_REG_BUCK4_VOUT,
320		.vsel_mask = PM886_BUCK_VSEL_MASK,
321		.enable_reg = PM886_REG_BUCK_EN,
322		.enable_mask = BIT(3),
323	},
324	{
325		.name = "buck5",
326		.regulators_node = "regulators",
327		.of_match = "buck5",
328		.ops = &pm886_buck_ops,
329		.type = REGULATOR_VOLTAGE,
330		.n_voltages = 115,
331		.linear_ranges = pm886_buck_volt_ranges2,
332		.n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),
333		.vsel_reg = PM886_REG_BUCK5_VOUT,
334		.vsel_mask = PM886_BUCK_VSEL_MASK,
335		.enable_reg = PM886_REG_BUCK_EN,
336		.enable_mask = BIT(4),
337	},
338};
339
340static int pm886_regulator_probe(struct platform_device *pdev)
341{
342	struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent);
343	struct regulator_config rcfg = { };
344	struct device *dev = &pdev->dev;
345	struct regulator_desc *rdesc;
346	struct regulator_dev *rdev;
347	struct i2c_client *page;
348	struct regmap *regmap;
349
350	page = devm_i2c_new_dummy_device(dev, chip->client->adapter,
351			chip->client->addr + PM886_PAGE_OFFSET_REGULATORS);
352	if (IS_ERR(page))
353		return dev_err_probe(dev, PTR_ERR(page),
354				"Failed to initialize regulators client\n");
355
356	regmap = devm_regmap_init_i2c(page, &pm886_regulator_regmap_config);
357	if (IS_ERR(regmap))
358		return dev_err_probe(dev, PTR_ERR(regmap),
359				"Failed to initialize regulators regmap\n");
360	rcfg.regmap = regmap;
361
362	rcfg.dev = dev->parent;
363
364	for (int i = 0; i < ARRAY_SIZE(pm886_regulators); i++) {
365		rdesc = &pm886_regulators[i];
366		rdev = devm_regulator_register(dev, rdesc, &rcfg);
367		if (IS_ERR(rdev))
368			return dev_err_probe(dev, PTR_ERR(rdev),
369					"Failed to register %s\n", rdesc->name);
370	}
371
372	return 0;
373}
374
375static const struct platform_device_id pm886_regulator_id_table[] = {
376	{ "88pm886-regulator", },
377	{ }
378};
379MODULE_DEVICE_TABLE(platform, pm886_regulator_id_table);
380
381static struct platform_driver pm886_regulator_driver = {
382	.driver = {
383		.name = "88pm886-regulator",
384	},
385	.probe = pm886_regulator_probe,
386	.id_table = pm886_regulator_id_table,
387};
388module_platform_driver(pm886_regulator_driver);
389
390MODULE_DESCRIPTION("Marvell 88PM886 PMIC regulator driver");
391MODULE_AUTHOR("Karel Balej <balejk@matfyz.cz>");
392MODULE_LICENSE("GPL");