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