• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
36 static const struct scmi_voltage_proto_ops *voltage_ops;
37 
38 struct 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 
48 struct scmi_regulator_info {
49 	int num_doms;
50 	struct scmi_regulator **sregv;
51 };
52 
scmi_reg_enable(struct regulator_dev * rdev)53 static 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 
scmi_reg_disable(struct regulator_dev * rdev)61 static 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 
scmi_reg_is_enabled(struct regulator_dev * rdev)69 static 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 
scmi_reg_get_voltage_sel(struct regulator_dev * rdev)86 static 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 
scmi_reg_set_voltage_sel(struct regulator_dev * rdev,unsigned int selector)99 static 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 
112 static 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 
118 static 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 
128 static 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 
138 static int
scmi_config_linear_regulator_mappings(struct scmi_regulator * sreg,const struct scmi_voltage_info * vinfo)139 scmi_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 
183 static int
scmi_config_discrete_regulator_mappings(struct scmi_regulator * sreg,const struct scmi_voltage_info * vinfo)184 scmi_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 
scmi_regulator_common_init(struct scmi_regulator * sreg)201 static 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 
process_scmi_regulator_of_node(struct scmi_device * sdev,struct scmi_protocol_handle * ph,struct device_node * np,struct scmi_regulator_info * rinfo)255 static 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 
scmi_regulator_probe(struct scmi_device * sdev)297 static 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 
scmi_regulator_remove(struct scmi_device * sdev)387 static 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 
403 static const struct scmi_device_id scmi_regulator_id_table[] = {
404 	{ SCMI_PROTOCOL_VOLTAGE,  "regulator" },
405 	{ },
406 };
407 MODULE_DEVICE_TABLE(scmi, scmi_regulator_id_table);
408 
409 static 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 
416 module_scmi_driver(scmi_drv);
417 
418 MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
419 MODULE_DESCRIPTION("ARM SCMI regulator driver");
420 MODULE_LICENSE("GPL v2");
421