1// SPDX-License-Identifier: GPL-2.0-only
2
3#include <linux/bitops.h>
4#include <linux/kernel.h>
5#include <linux/module.h>
6#include <linux/of.h>
7#include <linux/platform_device.h>
8#include <linux/regmap.h>
9#include <linux/regulator/consumer.h>
10#include <linux/regulator/driver.h>
11
12enum {
13	DSV_OUT_VLCM = 0,
14	DSV_OUT_VPOS,
15	DSV_OUT_VNEG,
16	DSV_OUT_MAX
17};
18
19#define RT4831_REG_DSVEN	0x09
20#define RT4831_REG_VLCM		0x0c
21#define RT4831_REG_VPOS		0x0d
22#define RT4831_REG_VNEG		0x0e
23#define RT4831_REG_FLAGS	0x0f
24
25#define RT4831_VOLT_MASK	GENMASK(5, 0)
26#define RT4831_DSVMODE_SHIFT	5
27#define RT4831_DSVMODE_MASK	GENMASK(7, 5)
28#define RT4831_POSADEN_MASK	BIT(4)
29#define RT4831_NEGADEN_MASK	BIT(3)
30#define RT4831_POSEN_MASK	BIT(2)
31#define RT4831_NEGEN_MASK	BIT(1)
32
33#define RT4831_OTP_MASK		BIT(6)
34#define RT4831_LCMOVP_MASK	BIT(5)
35#define RT4831_VPOSSCP_MASK	BIT(3)
36#define RT4831_VNEGSCP_MASK	BIT(2)
37
38#define DSV_MODE_NORMAL		(0x4 << RT4831_DSVMODE_SHIFT)
39#define DSV_MODE_BYPASS		(0x6 << RT4831_DSVMODE_SHIFT)
40#define STEP_UV			50000
41#define VLCM_MIN_UV		4000000
42#define VLCM_MAX_UV		7150000
43#define VLCM_N_VOLTAGES		((VLCM_MAX_UV - VLCM_MIN_UV) / STEP_UV + 1)
44#define VPN_MIN_UV		4000000
45#define VPN_MAX_UV		6500000
46#define VPN_N_VOLTAGES		((VPN_MAX_UV - VPN_MIN_UV) / STEP_UV + 1)
47
48static int rt4831_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
49{
50	struct regmap *regmap = rdev_get_regmap(rdev);
51	int rid = rdev_get_id(rdev);
52	unsigned int val, events = 0;
53	int ret;
54
55	ret = regmap_read(regmap, RT4831_REG_FLAGS, &val);
56	if (ret)
57		return ret;
58
59	if (val & RT4831_OTP_MASK)
60		events |= REGULATOR_ERROR_OVER_TEMP;
61
62	if (rid == DSV_OUT_VLCM && (val & RT4831_LCMOVP_MASK))
63		events |= REGULATOR_ERROR_OVER_CURRENT;
64
65	if (rid == DSV_OUT_VPOS && (val & RT4831_VPOSSCP_MASK))
66		events |= REGULATOR_ERROR_OVER_CURRENT;
67
68	if (rid == DSV_OUT_VNEG && (val & RT4831_VNEGSCP_MASK))
69		events |= REGULATOR_ERROR_OVER_CURRENT;
70
71	*flags = events;
72	return 0;
73}
74
75static const struct regulator_ops rt4831_dsvlcm_ops = {
76	.list_voltage = regulator_list_voltage_linear,
77	.set_voltage_sel = regulator_set_voltage_sel_regmap,
78	.get_voltage_sel = regulator_get_voltage_sel_regmap,
79	.set_bypass = regulator_set_bypass_regmap,
80	.get_bypass = regulator_get_bypass_regmap,
81	.get_error_flags = rt4831_get_error_flags,
82};
83
84static const struct regulator_ops rt4831_dsvpn_ops = {
85	.list_voltage = regulator_list_voltage_linear,
86	.set_voltage_sel = regulator_set_voltage_sel_regmap,
87	.get_voltage_sel = regulator_get_voltage_sel_regmap,
88	.enable = regulator_enable_regmap,
89	.disable = regulator_disable_regmap,
90	.is_enabled = regulator_is_enabled_regmap,
91	.set_active_discharge = regulator_set_active_discharge_regmap,
92	.get_error_flags = rt4831_get_error_flags,
93};
94
95static const struct regulator_desc rt4831_regulator_descs[] = {
96	{
97		.name = "DSVLCM",
98		.ops = &rt4831_dsvlcm_ops,
99		.of_match = of_match_ptr("DSVLCM"),
100		.regulators_node = of_match_ptr("regulators"),
101		.type = REGULATOR_VOLTAGE,
102		.id = DSV_OUT_VLCM,
103		.n_voltages = VLCM_N_VOLTAGES,
104		.min_uV = VLCM_MIN_UV,
105		.uV_step = STEP_UV,
106		.vsel_reg = RT4831_REG_VLCM,
107		.vsel_mask = RT4831_VOLT_MASK,
108		.bypass_reg = RT4831_REG_DSVEN,
109		.bypass_mask = RT4831_DSVMODE_MASK,
110		.bypass_val_on = DSV_MODE_BYPASS,
111		.bypass_val_off = DSV_MODE_NORMAL,
112		.owner = THIS_MODULE,
113	},
114	{
115		.name = "DSVP",
116		.ops = &rt4831_dsvpn_ops,
117		.of_match = of_match_ptr("DSVP"),
118		.regulators_node = of_match_ptr("regulators"),
119		.type = REGULATOR_VOLTAGE,
120		.id = DSV_OUT_VPOS,
121		.n_voltages = VPN_N_VOLTAGES,
122		.min_uV = VPN_MIN_UV,
123		.uV_step = STEP_UV,
124		.vsel_reg = RT4831_REG_VPOS,
125		.vsel_mask = RT4831_VOLT_MASK,
126		.enable_reg = RT4831_REG_DSVEN,
127		.enable_mask = RT4831_POSEN_MASK,
128		.active_discharge_reg = RT4831_REG_DSVEN,
129		.active_discharge_mask = RT4831_POSADEN_MASK,
130		.active_discharge_on = RT4831_POSADEN_MASK,
131		.owner = THIS_MODULE,
132	},
133	{
134		.name = "DSVN",
135		.ops = &rt4831_dsvpn_ops,
136		.of_match = of_match_ptr("DSVN"),
137		.regulators_node = of_match_ptr("regulators"),
138		.type = REGULATOR_VOLTAGE,
139		.id = DSV_OUT_VNEG,
140		.n_voltages = VPN_N_VOLTAGES,
141		.min_uV = VPN_MIN_UV,
142		.uV_step = STEP_UV,
143		.vsel_reg = RT4831_REG_VNEG,
144		.vsel_mask = RT4831_VOLT_MASK,
145		.enable_reg = RT4831_REG_DSVEN,
146		.enable_mask = RT4831_NEGEN_MASK,
147		.active_discharge_reg = RT4831_REG_DSVEN,
148		.active_discharge_mask = RT4831_NEGADEN_MASK,
149		.active_discharge_on = RT4831_NEGADEN_MASK,
150		.owner = THIS_MODULE,
151	}
152};
153
154static int rt4831_regulator_probe(struct platform_device *pdev)
155{
156	struct regmap *regmap;
157	struct regulator_dev *rdev;
158	struct regulator_config config = {};
159	int i, ret;
160
161	regmap = dev_get_regmap(pdev->dev.parent, NULL);
162	if (!regmap) {
163		dev_err(&pdev->dev, "Failed to init regmap\n");
164		return -ENODEV;
165	}
166
167	/* Configure DSV mode to normal by default */
168	ret = regmap_update_bits(regmap, RT4831_REG_DSVEN, RT4831_DSVMODE_MASK, DSV_MODE_NORMAL);
169	if (ret) {
170		dev_err(&pdev->dev, "Failed to configure dsv mode to normal\n");
171		return ret;
172	}
173
174	config.dev = pdev->dev.parent;
175	config.regmap = regmap;
176
177	for (i = 0; i < DSV_OUT_MAX; i++) {
178		rdev = devm_regulator_register(&pdev->dev, rt4831_regulator_descs + i, &config);
179		if (IS_ERR(rdev)) {
180			dev_err(&pdev->dev, "Failed to register %d regulator\n", i);
181			return PTR_ERR(rdev);
182		}
183	}
184
185	return 0;
186}
187
188static const struct platform_device_id rt4831_regulator_match[] = {
189	{ "rt4831-regulator", 0 },
190	{}
191};
192MODULE_DEVICE_TABLE(platform, rt4831_regulator_match);
193
194static struct platform_driver rt4831_regulator_driver = {
195	.driver = {
196		.name = "rt4831-regulator",
197		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
198	},
199	.id_table = rt4831_regulator_match,
200	.probe = rt4831_regulator_probe,
201};
202module_platform_driver(rt4831_regulator_driver);
203
204MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
205MODULE_LICENSE("GPL v2");
206