1// SPDX-License-Identifier: GPL-2.0
2//
3// System Control and Management Interface (SCMI) based regulator driver
4//
5// Copyright (C) 2020-2021 ARM Ltd.
6//
7// Implements a regulator driver on top of the SCMI Voltage Protocol.
8//
9// The ARM SCMI Protocol aims in general to hide as much as possible all the
10// underlying operational details while providing an abstracted interface for
11// its users to operate upon: as a consequence the resulting operational
12// capabilities and configurability of this regulator device are much more
13// limited than the ones usually available on a standard physical regulator.
14//
15// The supported SCMI regulator ops are restricted to the bare minimum:
16//
17//  - 'status_ops': enable/disable/is_enabled
18//  - 'voltage_ops': get_voltage_sel/set_voltage_sel
19//		     list_voltage/map_voltage
20//
21// Each SCMI regulator instance is associated, through the means of a proper DT
22// entry description, to a specific SCMI Voltage Domain.
23
24#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
26#include <linux/linear_range.h>
27#include <linux/module.h>
28#include <linux/of.h>
29#include <linux/regulator/driver.h>
30#include <linux/regulator/machine.h>
31#include <linux/regulator/of_regulator.h>
32#include <linux/scmi_protocol.h>
33#include <linux/slab.h>
34#include <linux/types.h>
35
36static const struct scmi_voltage_proto_ops *voltage_ops;
37
38struct scmi_regulator {
39	u32 id;
40	struct scmi_device *sdev;
41	struct scmi_protocol_handle *ph;
42	struct regulator_dev *rdev;
43	struct device_node *of_node;
44	struct regulator_desc desc;
45	struct regulator_config conf;
46};
47
48struct scmi_regulator_info {
49	int num_doms;
50	struct scmi_regulator **sregv;
51};
52
53static int scmi_reg_enable(struct regulator_dev *rdev)
54{
55	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
56
57	return voltage_ops->config_set(sreg->ph, sreg->id,
58				       SCMI_VOLTAGE_ARCH_STATE_ON);
59}
60
61static int scmi_reg_disable(struct regulator_dev *rdev)
62{
63	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
64
65	return voltage_ops->config_set(sreg->ph, sreg->id,
66				       SCMI_VOLTAGE_ARCH_STATE_OFF);
67}
68
69static int scmi_reg_is_enabled(struct regulator_dev *rdev)
70{
71	int ret;
72	u32 config;
73	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
74
75	ret = voltage_ops->config_get(sreg->ph, sreg->id, &config);
76	if (ret) {
77		dev_err(&sreg->sdev->dev,
78			"Error %d reading regulator %s status.\n",
79			ret, sreg->desc.name);
80		return ret;
81	}
82
83	return config & SCMI_VOLTAGE_ARCH_STATE_ON;
84}
85
86static int scmi_reg_get_voltage_sel(struct regulator_dev *rdev)
87{
88	int ret;
89	s32 volt_uV;
90	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
91
92	ret = voltage_ops->level_get(sreg->ph, sreg->id, &volt_uV);
93	if (ret)
94		return ret;
95
96	return sreg->desc.ops->map_voltage(rdev, volt_uV, volt_uV);
97}
98
99static int scmi_reg_set_voltage_sel(struct regulator_dev *rdev,
100				    unsigned int selector)
101{
102	s32 volt_uV;
103	struct scmi_regulator *sreg = rdev_get_drvdata(rdev);
104
105	volt_uV = sreg->desc.ops->list_voltage(rdev, selector);
106	if (volt_uV <= 0)
107		return -EINVAL;
108
109	return voltage_ops->level_set(sreg->ph, sreg->id, 0x0, volt_uV);
110}
111
112static const struct regulator_ops scmi_reg_fixed_ops = {
113	.enable = scmi_reg_enable,
114	.disable = scmi_reg_disable,
115	.is_enabled = scmi_reg_is_enabled,
116};
117
118static const struct regulator_ops scmi_reg_linear_ops = {
119	.enable = scmi_reg_enable,
120	.disable = scmi_reg_disable,
121	.is_enabled = scmi_reg_is_enabled,
122	.get_voltage_sel = scmi_reg_get_voltage_sel,
123	.set_voltage_sel = scmi_reg_set_voltage_sel,
124	.list_voltage = regulator_list_voltage_linear,
125	.map_voltage = regulator_map_voltage_linear,
126};
127
128static const struct regulator_ops scmi_reg_discrete_ops = {
129	.enable = scmi_reg_enable,
130	.disable = scmi_reg_disable,
131	.is_enabled = scmi_reg_is_enabled,
132	.get_voltage_sel = scmi_reg_get_voltage_sel,
133	.set_voltage_sel = scmi_reg_set_voltage_sel,
134	.list_voltage = regulator_list_voltage_table,
135	.map_voltage = regulator_map_voltage_iterate,
136};
137
138static int
139scmi_config_linear_regulator_mappings(struct scmi_regulator *sreg,
140				      const struct scmi_voltage_info *vinfo)
141{
142	s32 delta_uV;
143
144	/*
145	 * Note that SCMI voltage domains describable by linear ranges
146	 * (segments) {low, high, step} are guaranteed to come in one single
147	 * triplet by the SCMI Voltage Domain protocol support itself.
148	 */
149
150	delta_uV = (vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH] -
151			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW]);
152
153	/* Rule out buggy negative-intervals answers from fw */
154	if (delta_uV < 0) {
155		dev_err(&sreg->sdev->dev,
156			"Invalid volt-range %d-%duV for domain %d\n",
157			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW],
158			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH],
159			sreg->id);
160		return -EINVAL;
161	}
162
163	if (!delta_uV) {
164		/* Just one fixed voltage exposed by SCMI */
165		sreg->desc.fixed_uV =
166			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW];
167		sreg->desc.n_voltages = 1;
168		sreg->desc.ops = &scmi_reg_fixed_ops;
169	} else {
170		/* One simple linear mapping. */
171		sreg->desc.min_uV =
172			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW];
173		sreg->desc.uV_step =
174			vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_STEP];
175		sreg->desc.linear_min_sel = 0;
176		sreg->desc.n_voltages = (delta_uV / sreg->desc.uV_step) + 1;
177		sreg->desc.ops = &scmi_reg_linear_ops;
178	}
179
180	return 0;
181}
182
183static int
184scmi_config_discrete_regulator_mappings(struct scmi_regulator *sreg,
185					const struct scmi_voltage_info *vinfo)
186{
187	/* Discrete non linear levels are mapped to volt_table */
188	sreg->desc.n_voltages = vinfo->num_levels;
189
190	if (sreg->desc.n_voltages > 1) {
191		sreg->desc.volt_table = (const unsigned int *)vinfo->levels_uv;
192		sreg->desc.ops = &scmi_reg_discrete_ops;
193	} else {
194		sreg->desc.fixed_uV = vinfo->levels_uv[0];
195		sreg->desc.ops = &scmi_reg_fixed_ops;
196	}
197
198	return 0;
199}
200
201static int scmi_regulator_common_init(struct scmi_regulator *sreg)
202{
203	int ret;
204	struct device *dev = &sreg->sdev->dev;
205	const struct scmi_voltage_info *vinfo;
206
207	vinfo = voltage_ops->info_get(sreg->ph, sreg->id);
208	if (!vinfo) {
209		dev_warn(dev, "Failure to get voltage domain %d\n",
210			 sreg->id);
211		return -ENODEV;
212	}
213
214	/*
215	 * Regulator framework does not fully support negative voltages
216	 * so we discard any voltage domain reported as supporting negative
217	 * voltages: as a consequence each levels_uv entry is guaranteed to
218	 * be non-negative from here on.
219	 */
220	if (vinfo->negative_volts_allowed) {
221		dev_warn(dev, "Negative voltages NOT supported...skip %s\n",
222			 sreg->of_node->full_name);
223		return -EOPNOTSUPP;
224	}
225
226	sreg->desc.name = devm_kasprintf(dev, GFP_KERNEL, "%s", vinfo->name);
227	if (!sreg->desc.name)
228		return -ENOMEM;
229
230	sreg->desc.id = sreg->id;
231	sreg->desc.type = REGULATOR_VOLTAGE;
232	sreg->desc.owner = THIS_MODULE;
233	sreg->desc.of_match_full_name = true;
234	sreg->desc.of_match = sreg->of_node->full_name;
235	sreg->desc.regulators_node = "regulators";
236	if (vinfo->segmented)
237		ret = scmi_config_linear_regulator_mappings(sreg, vinfo);
238	else
239		ret = scmi_config_discrete_regulator_mappings(sreg, vinfo);
240	if (ret)
241		return ret;
242
243	/*
244	 * Using the scmi device here to have DT searched from Voltage
245	 * protocol node down.
246	 */
247	sreg->conf.dev = dev;
248
249	/* Store for later retrieval via rdev_get_drvdata() */
250	sreg->conf.driver_data = sreg;
251
252	return 0;
253}
254
255static int process_scmi_regulator_of_node(struct scmi_device *sdev,
256					  struct scmi_protocol_handle *ph,
257					  struct device_node *np,
258					  struct scmi_regulator_info *rinfo)
259{
260	u32 dom, ret;
261
262	ret = of_property_read_u32(np, "reg", &dom);
263	if (ret)
264		return ret;
265
266	if (dom >= rinfo->num_doms)
267		return -ENODEV;
268
269	if (rinfo->sregv[dom]) {
270		dev_err(&sdev->dev,
271			"SCMI Voltage Domain %d already in use. Skipping: %s\n",
272			dom, np->full_name);
273		return -EINVAL;
274	}
275
276	rinfo->sregv[dom] = devm_kzalloc(&sdev->dev,
277					 sizeof(struct scmi_regulator),
278					 GFP_KERNEL);
279	if (!rinfo->sregv[dom])
280		return -ENOMEM;
281
282	rinfo->sregv[dom]->id = dom;
283	rinfo->sregv[dom]->sdev = sdev;
284	rinfo->sregv[dom]->ph = ph;
285
286	/* get hold of good nodes */
287	of_node_get(np);
288	rinfo->sregv[dom]->of_node = np;
289
290	dev_dbg(&sdev->dev,
291		"Found SCMI Regulator entry -- OF node [%d] -> %s\n",
292		dom, np->full_name);
293
294	return 0;
295}
296
297static int scmi_regulator_probe(struct scmi_device *sdev)
298{
299	int d, ret, num_doms;
300	struct device_node *np, *child;
301	const struct scmi_handle *handle = sdev->handle;
302	struct scmi_regulator_info *rinfo;
303	struct scmi_protocol_handle *ph;
304
305	if (!handle)
306		return -ENODEV;
307
308	voltage_ops = handle->devm_protocol_get(sdev,
309						SCMI_PROTOCOL_VOLTAGE, &ph);
310	if (IS_ERR(voltage_ops))
311		return PTR_ERR(voltage_ops);
312
313	num_doms = voltage_ops->num_domains_get(ph);
314	if (!num_doms)
315		return 0;
316
317	if (num_doms < 0) {
318		dev_err(&sdev->dev, "failed to get voltage domains - err:%d\n",
319			num_doms);
320
321		return num_doms;
322	}
323
324	rinfo = devm_kzalloc(&sdev->dev, sizeof(*rinfo), GFP_KERNEL);
325	if (!rinfo)
326		return -ENOMEM;
327
328	/* Allocate pointers array for all possible domains */
329	rinfo->sregv = devm_kcalloc(&sdev->dev, num_doms,
330				    sizeof(void *), GFP_KERNEL);
331	if (!rinfo->sregv)
332		return -ENOMEM;
333
334	rinfo->num_doms = num_doms;
335
336	/*
337	 * Start collecting into rinfo->sregv possibly good SCMI Regulators as
338	 * described by a well-formed DT entry and associated with an existing
339	 * plausible SCMI Voltage Domain number, all belonging to this SCMI
340	 * platform instance node (handle->dev->of_node).
341	 */
342	of_node_get(handle->dev->of_node);
343	np = of_find_node_by_name(handle->dev->of_node, "regulators");
344	for_each_child_of_node(np, child) {
345		ret = process_scmi_regulator_of_node(sdev, ph, child, rinfo);
346		/* abort on any mem issue */
347		if (ret == -ENOMEM) {
348			of_node_put(child);
349			return ret;
350		}
351	}
352	of_node_put(np);
353	/*
354	 * Register a regulator for each valid regulator-DT-entry that we
355	 * can successfully reach via SCMI and has a valid associated voltage
356	 * domain.
357	 */
358	for (d = 0; d < num_doms; d++) {
359		struct scmi_regulator *sreg = rinfo->sregv[d];
360
361		/* Skip empty slots */
362		if (!sreg)
363			continue;
364
365		ret = scmi_regulator_common_init(sreg);
366		/* Skip invalid voltage domains */
367		if (ret)
368			continue;
369
370		sreg->rdev = devm_regulator_register(&sdev->dev, &sreg->desc,
371						     &sreg->conf);
372		if (IS_ERR(sreg->rdev)) {
373			sreg->rdev = NULL;
374			continue;
375		}
376
377		dev_info(&sdev->dev,
378			 "Regulator %s registered for domain [%d]\n",
379			 sreg->desc.name, sreg->id);
380	}
381
382	dev_set_drvdata(&sdev->dev, rinfo);
383
384	return 0;
385}
386
387static void scmi_regulator_remove(struct scmi_device *sdev)
388{
389	int d;
390	struct scmi_regulator_info *rinfo;
391
392	rinfo = dev_get_drvdata(&sdev->dev);
393	if (!rinfo)
394		return;
395
396	for (d = 0; d < rinfo->num_doms; d++) {
397		if (!rinfo->sregv[d])
398			continue;
399		of_node_put(rinfo->sregv[d]->of_node);
400	}
401}
402
403static const struct scmi_device_id scmi_regulator_id_table[] = {
404	{ SCMI_PROTOCOL_VOLTAGE,  "regulator" },
405	{ },
406};
407MODULE_DEVICE_TABLE(scmi, scmi_regulator_id_table);
408
409static struct scmi_driver scmi_drv = {
410	.name		= "scmi-regulator",
411	.probe		= scmi_regulator_probe,
412	.remove		= scmi_regulator_remove,
413	.id_table	= scmi_regulator_id_table,
414};
415
416module_scmi_driver(scmi_drv);
417
418MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
419MODULE_DESCRIPTION("ARM SCMI regulator driver");
420MODULE_LICENSE("GPL v2");
421