13c910ecbSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2811b7006SBeniamino Galvani /*
3811b7006SBeniamino Galvani  * Regulator driver for Ricoh RN5T618 PMIC
4811b7006SBeniamino Galvani  *
5811b7006SBeniamino Galvani  * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
6811b7006SBeniamino Galvani  */
7811b7006SBeniamino Galvani 
8811b7006SBeniamino Galvani #include <linux/mfd/rn5t618.h>
9811b7006SBeniamino Galvani #include <linux/module.h>
10811b7006SBeniamino Galvani #include <linux/of.h>
11811b7006SBeniamino Galvani #include <linux/platform_device.h>
12811b7006SBeniamino Galvani #include <linux/regmap.h>
13811b7006SBeniamino Galvani #include <linux/regulator/driver.h>
14811b7006SBeniamino Galvani #include <linux/regulator/of_regulator.h>
15811b7006SBeniamino Galvani 
16243842b8SBhumika Goyal static const struct regulator_ops rn5t618_reg_ops = {
17811b7006SBeniamino Galvani 	.enable			= regulator_enable_regmap,
18811b7006SBeniamino Galvani 	.disable		= regulator_disable_regmap,
19811b7006SBeniamino Galvani 	.is_enabled		= regulator_is_enabled_regmap,
20811b7006SBeniamino Galvani 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
21811b7006SBeniamino Galvani 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
22811b7006SBeniamino Galvani 	.list_voltage		= regulator_list_voltage_linear,
23811b7006SBeniamino Galvani };
24811b7006SBeniamino Galvani 
25811b7006SBeniamino Galvani #define REG(rid, ereg, emask, vreg, vmask, min, max, step)		\
26d824c7a8SLeonard Crestez 	{								\
27811b7006SBeniamino Galvani 		.name		= #rid,					\
289075cceaSBeniamino Galvani 		.of_match	= of_match_ptr(#rid),			\
299075cceaSBeniamino Galvani 		.regulators_node = of_match_ptr("regulators"),		\
30811b7006SBeniamino Galvani 		.id		= RN5T618_##rid,			\
31811b7006SBeniamino Galvani 		.type		= REGULATOR_VOLTAGE,			\
32811b7006SBeniamino Galvani 		.owner		= THIS_MODULE,				\
33811b7006SBeniamino Galvani 		.ops		= &rn5t618_reg_ops,			\
34811b7006SBeniamino Galvani 		.n_voltages	= ((max) - (min)) / (step) + 1,		\
35811b7006SBeniamino Galvani 		.min_uV		= (min),				\
36811b7006SBeniamino Galvani 		.uV_step	= (step),				\
37811b7006SBeniamino Galvani 		.enable_reg	= RN5T618_##ereg,			\
38811b7006SBeniamino Galvani 		.enable_mask	= (emask),				\
39811b7006SBeniamino Galvani 		.vsel_reg	= RN5T618_##vreg,			\
40811b7006SBeniamino Galvani 		.vsel_mask	= (vmask),				\
41811b7006SBeniamino Galvani 	}
42811b7006SBeniamino Galvani 
43c2293856SAxel Lin static const struct regulator_desc rn5t567_regulators[] = {
44ed6d362dSStefan Agner 	/* DCDC */
45ed6d362dSStefan Agner 	REG(DCDC1, DC1CTL, BIT(0), DC1DAC, 0xff, 600000, 3500000, 12500),
46ed6d362dSStefan Agner 	REG(DCDC2, DC2CTL, BIT(0), DC2DAC, 0xff, 600000, 3500000, 12500),
47ed6d362dSStefan Agner 	REG(DCDC3, DC3CTL, BIT(0), DC3DAC, 0xff, 600000, 3500000, 12500),
48ed6d362dSStefan Agner 	REG(DCDC4, DC4CTL, BIT(0), DC4DAC, 0xff, 600000, 3500000, 12500),
49ed6d362dSStefan Agner 	/* LDO */
50ed6d362dSStefan Agner 	REG(LDO1, LDOEN1, BIT(0), LDO1DAC, 0x7f, 900000, 3500000, 25000),
51ed6d362dSStefan Agner 	REG(LDO2, LDOEN1, BIT(1), LDO2DAC, 0x7f, 900000, 3500000, 25000),
52ed6d362dSStefan Agner 	REG(LDO3, LDOEN1, BIT(2), LDO3DAC, 0x7f, 600000, 3500000, 25000),
53ed6d362dSStefan Agner 	REG(LDO4, LDOEN1, BIT(3), LDO4DAC, 0x7f, 900000, 3500000, 25000),
54ed6d362dSStefan Agner 	REG(LDO5, LDOEN1, BIT(4), LDO5DAC, 0x7f, 900000, 3500000, 25000),
55ed6d362dSStefan Agner 	/* LDO RTC */
56ed6d362dSStefan Agner 	REG(LDORTC1, LDOEN2, BIT(4), LDORTCDAC, 0x7f, 1200000, 3500000, 25000),
57ed6d362dSStefan Agner 	REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
58ed6d362dSStefan Agner };
59ed6d362dSStefan Agner 
60c2293856SAxel Lin static const struct regulator_desc rn5t618_regulators[] = {
61811b7006SBeniamino Galvani 	/* DCDC */
62811b7006SBeniamino Galvani 	REG(DCDC1, DC1CTL, BIT(0), DC1DAC, 0xff, 600000, 3500000, 12500),
63811b7006SBeniamino Galvani 	REG(DCDC2, DC2CTL, BIT(0), DC2DAC, 0xff, 600000, 3500000, 12500),
64811b7006SBeniamino Galvani 	REG(DCDC3, DC3CTL, BIT(0), DC3DAC, 0xff, 600000, 3500000, 12500),
65811b7006SBeniamino Galvani 	/* LDO */
66811b7006SBeniamino Galvani 	REG(LDO1, LDOEN1, BIT(0), LDO1DAC, 0x7f, 900000, 3500000, 25000),
67811b7006SBeniamino Galvani 	REG(LDO2, LDOEN1, BIT(1), LDO2DAC, 0x7f, 900000, 3500000, 25000),
68811b7006SBeniamino Galvani 	REG(LDO3, LDOEN1, BIT(2), LDO3DAC, 0x7f, 600000, 3500000, 25000),
69811b7006SBeniamino Galvani 	REG(LDO4, LDOEN1, BIT(3), LDO4DAC, 0x7f, 900000, 3500000, 25000),
70811b7006SBeniamino Galvani 	REG(LDO5, LDOEN1, BIT(4), LDO5DAC, 0x7f, 900000, 3500000, 25000),
71811b7006SBeniamino Galvani 	/* LDO RTC */
72811b7006SBeniamino Galvani 	REG(LDORTC1, LDOEN2, BIT(4), LDORTCDAC, 0x7f, 1700000, 3500000, 25000),
73811b7006SBeniamino Galvani 	REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
74811b7006SBeniamino Galvani };
75811b7006SBeniamino Galvani 
76c2293856SAxel Lin static const struct regulator_desc rc5t619_regulators[] = {
7783b2a3c2SPierre-Hugues Husson 	/* DCDC */
7883b2a3c2SPierre-Hugues Husson 	REG(DCDC1, DC1CTL, BIT(0), DC1DAC, 0xff, 600000, 3500000, 12500),
7983b2a3c2SPierre-Hugues Husson 	REG(DCDC2, DC2CTL, BIT(0), DC2DAC, 0xff, 600000, 3500000, 12500),
8083b2a3c2SPierre-Hugues Husson 	REG(DCDC3, DC3CTL, BIT(0), DC3DAC, 0xff, 600000, 3500000, 12500),
8183b2a3c2SPierre-Hugues Husson 	REG(DCDC4, DC4CTL, BIT(0), DC4DAC, 0xff, 600000, 3500000, 12500),
8283b2a3c2SPierre-Hugues Husson 	REG(DCDC5, DC5CTL, BIT(0), DC5DAC, 0xff, 600000, 3500000, 12500),
8383b2a3c2SPierre-Hugues Husson 	/* LDO */
8483b2a3c2SPierre-Hugues Husson 	REG(LDO1, LDOEN1, BIT(0), LDO1DAC, 0x7f, 900000, 3500000, 25000),
8583b2a3c2SPierre-Hugues Husson 	REG(LDO2, LDOEN1, BIT(1), LDO2DAC, 0x7f, 900000, 3500000, 25000),
8683b2a3c2SPierre-Hugues Husson 	REG(LDO3, LDOEN1, BIT(2), LDO3DAC, 0x7f, 900000, 3500000, 25000),
8783b2a3c2SPierre-Hugues Husson 	REG(LDO4, LDOEN1, BIT(3), LDO4DAC, 0x7f, 900000, 3500000, 25000),
8883b2a3c2SPierre-Hugues Husson 	REG(LDO5, LDOEN1, BIT(4), LDO5DAC, 0x7f, 600000, 3500000, 25000),
8983b2a3c2SPierre-Hugues Husson 	REG(LDO6, LDOEN1, BIT(5), LDO6DAC, 0x7f, 600000, 3500000, 25000),
9083b2a3c2SPierre-Hugues Husson 	REG(LDO7, LDOEN1, BIT(6), LDO7DAC, 0x7f, 900000, 3500000, 25000),
9183b2a3c2SPierre-Hugues Husson 	REG(LDO8, LDOEN1, BIT(7), LDO8DAC, 0x7f, 900000, 3500000, 25000),
9283b2a3c2SPierre-Hugues Husson 	REG(LDO9, LDOEN2, BIT(0), LDO9DAC, 0x7f, 900000, 3500000, 25000),
933f1a9e63SAndreas Kemnade 	REG(LDO10, LDOEN2, BIT(1), LDO10DAC, 0x7f, 900000, 3500000, 25000),
9483b2a3c2SPierre-Hugues Husson 	/* LDO RTC */
9583b2a3c2SPierre-Hugues Husson 	REG(LDORTC1, LDOEN2, BIT(4), LDORTCDAC, 0x7f, 1700000, 3500000, 25000),
9683b2a3c2SPierre-Hugues Husson 	REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
9783b2a3c2SPierre-Hugues Husson };
9883b2a3c2SPierre-Hugues Husson 
rn5t618_regulator_probe(struct platform_device * pdev)99811b7006SBeniamino Galvani static int rn5t618_regulator_probe(struct platform_device *pdev)
100811b7006SBeniamino Galvani {
101811b7006SBeniamino Galvani 	struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent);
102811b7006SBeniamino Galvani 	struct regulator_config config = { };
103811b7006SBeniamino Galvani 	struct regulator_dev *rdev;
104c2293856SAxel Lin 	const struct regulator_desc *regulators;
1059075cceaSBeniamino Galvani 	int i;
10683b2a3c2SPierre-Hugues Husson 	int num_regulators = 0;
107811b7006SBeniamino Galvani 
108ed6d362dSStefan Agner 	switch (rn5t618->variant) {
109ed6d362dSStefan Agner 	case RN5T567:
110ed6d362dSStefan Agner 		regulators = rn5t567_regulators;
11183b2a3c2SPierre-Hugues Husson 		num_regulators = ARRAY_SIZE(rn5t567_regulators);
112ed6d362dSStefan Agner 		break;
113ed6d362dSStefan Agner 	case RN5T618:
114ed6d362dSStefan Agner 		regulators = rn5t618_regulators;
11583b2a3c2SPierre-Hugues Husson 		num_regulators = ARRAY_SIZE(rn5t618_regulators);
11683b2a3c2SPierre-Hugues Husson 		break;
11783b2a3c2SPierre-Hugues Husson 	case RC5T619:
11883b2a3c2SPierre-Hugues Husson 		regulators = rc5t619_regulators;
11983b2a3c2SPierre-Hugues Husson 		num_regulators = ARRAY_SIZE(rc5t619_regulators);
120ed6d362dSStefan Agner 		break;
121ed6d362dSStefan Agner 	default:
122ed6d362dSStefan Agner 		return -EINVAL;
123ed6d362dSStefan Agner 	}
124ed6d362dSStefan Agner 
1259075cceaSBeniamino Galvani 	config.dev = pdev->dev.parent;
126811b7006SBeniamino Galvani 	config.regmap = rn5t618->regmap;
127811b7006SBeniamino Galvani 
12883b2a3c2SPierre-Hugues Husson 	for (i = 0; i < num_regulators; i++) {
129811b7006SBeniamino Galvani 		rdev = devm_regulator_register(&pdev->dev,
130ed6d362dSStefan Agner 					       &regulators[i],
131811b7006SBeniamino Galvani 					       &config);
132811b7006SBeniamino Galvani 		if (IS_ERR(rdev)) {
133811b7006SBeniamino Galvani 			dev_err(&pdev->dev, "failed to register %s regulator\n",
134ed6d362dSStefan Agner 				regulators[i].name);
135811b7006SBeniamino Galvani 			return PTR_ERR(rdev);
136811b7006SBeniamino Galvani 		}
137811b7006SBeniamino Galvani 	}
138811b7006SBeniamino Galvani 
139811b7006SBeniamino Galvani 	return 0;
140811b7006SBeniamino Galvani }
141811b7006SBeniamino Galvani 
142811b7006SBeniamino Galvani static struct platform_driver rn5t618_regulator_driver = {
143811b7006SBeniamino Galvani 	.probe = rn5t618_regulator_probe,
144811b7006SBeniamino Galvani 	.driver = {
145811b7006SBeniamino Galvani 		.name	= "rn5t618-regulator",
146*259b93b2SDouglas Anderson 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
147811b7006SBeniamino Galvani 	},
148811b7006SBeniamino Galvani };
149811b7006SBeniamino Galvani 
150811b7006SBeniamino Galvani module_platform_driver(rn5t618_regulator_driver);
151811b7006SBeniamino Galvani 
15262a1923cSAndreas Kemnade MODULE_ALIAS("platform:rn5t618-regulator");
153811b7006SBeniamino Galvani MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
154811b7006SBeniamino Galvani MODULE_DESCRIPTION("RN5T618 regulator driver");
155811b7006SBeniamino Galvani MODULE_LICENSE("GPL v2");
156