1 // SPDX-License-Identifier: GPL-2.0
3 // System Control and Management Interface (SCMI) based regulator driver
5 // Copyright (C) 2020-2021 ARM Ltd.
7 // Implements a regulator driver on top of the SCMI Voltage Protocol.
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.
15 // The supported SCMI regulator ops are restricted to the bare minimum:
17 // - 'status_ops': enable/disable/is_enabled
18 // - 'voltage_ops': get_voltage_sel/set_voltage_sel
19 // list_voltage/map_voltage
21 // Each SCMI regulator instance is associated, through the means of a proper DT
22 // entry description, to a specific SCMI Voltage Domain.
24 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26 #include <linux/linear_range.h>
27 #include <linux/module.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>
36 static const struct scmi_voltage_proto_ops
*voltage_ops
;
38 struct scmi_regulator
{
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
;
48 struct scmi_regulator_info
{
50 struct scmi_regulator
**sregv
;
53 static int scmi_reg_enable(struct regulator_dev
*rdev
)
55 struct scmi_regulator
*sreg
= rdev_get_drvdata(rdev
);
57 return voltage_ops
->config_set(sreg
->ph
, sreg
->id
,
58 SCMI_VOLTAGE_ARCH_STATE_ON
);
61 static int scmi_reg_disable(struct regulator_dev
*rdev
)
63 struct scmi_regulator
*sreg
= rdev_get_drvdata(rdev
);
65 return voltage_ops
->config_set(sreg
->ph
, sreg
->id
,
66 SCMI_VOLTAGE_ARCH_STATE_OFF
);
69 static int scmi_reg_is_enabled(struct regulator_dev
*rdev
)
73 struct scmi_regulator
*sreg
= rdev_get_drvdata(rdev
);
75 ret
= voltage_ops
->config_get(sreg
->ph
, sreg
->id
, &config
);
77 dev_err(&sreg
->sdev
->dev
,
78 "Error %d reading regulator %s status.\n",
79 ret
, sreg
->desc
.name
);
83 return config
& SCMI_VOLTAGE_ARCH_STATE_ON
;
86 static int scmi_reg_get_voltage_sel(struct regulator_dev
*rdev
)
90 struct scmi_regulator
*sreg
= rdev_get_drvdata(rdev
);
92 ret
= voltage_ops
->level_get(sreg
->ph
, sreg
->id
, &volt_uV
);
96 return sreg
->desc
.ops
->map_voltage(rdev
, volt_uV
, volt_uV
);
99 static int scmi_reg_set_voltage_sel(struct regulator_dev
*rdev
,
100 unsigned int selector
)
103 struct scmi_regulator
*sreg
= rdev_get_drvdata(rdev
);
105 volt_uV
= sreg
->desc
.ops
->list_voltage(rdev
, selector
);
109 return voltage_ops
->level_set(sreg
->ph
, sreg
->id
, 0x0, volt_uV
);
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
,
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
,
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
,
139 scmi_config_linear_regulator_mappings(struct scmi_regulator
*sreg
,
140 const struct scmi_voltage_info
*vinfo
)
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.
150 delta_uV
= (vinfo
->levels_uv
[SCMI_VOLTAGE_SEGMENT_HIGH
] -
151 vinfo
->levels_uv
[SCMI_VOLTAGE_SEGMENT_LOW
]);
153 /* Rule out buggy negative-intervals answers from fw */
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
],
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
;
170 /* One simple linear mapping. */
172 vinfo
->levels_uv
[SCMI_VOLTAGE_SEGMENT_LOW
];
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
;
184 scmi_config_discrete_regulator_mappings(struct scmi_regulator
*sreg
,
185 const struct scmi_voltage_info
*vinfo
)
187 /* Discrete non linear levels are mapped to volt_table */
188 sreg
->desc
.n_voltages
= vinfo
->num_levels
;
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
;
194 sreg
->desc
.fixed_uV
= vinfo
->levels_uv
[0];
195 sreg
->desc
.ops
= &scmi_reg_fixed_ops
;
201 static int scmi_regulator_common_init(struct scmi_regulator
*sreg
)
204 struct device
*dev
= &sreg
->sdev
->dev
;
205 const struct scmi_voltage_info
*vinfo
;
207 vinfo
= voltage_ops
->info_get(sreg
->ph
, sreg
->id
);
209 dev_warn(dev
, "Failure to get voltage domain %d\n",
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.
220 if (vinfo
->negative_volts_allowed
) {
221 dev_warn(dev
, "Negative voltages NOT supported...skip %s\n",
222 sreg
->of_node
->full_name
);
226 sreg
->desc
.name
= devm_kasprintf(dev
, GFP_KERNEL
, "%s", vinfo
->name
);
227 if (!sreg
->desc
.name
)
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
);
239 ret
= scmi_config_discrete_regulator_mappings(sreg
, vinfo
);
244 * Using the scmi device here to have DT searched from Voltage
245 * protocol node down.
247 sreg
->conf
.dev
= dev
;
249 /* Store for later retrieval via rdev_get_drvdata() */
250 sreg
->conf
.driver_data
= sreg
;
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
)
262 ret
= of_property_read_u32(np
, "reg", &dom
);
266 if (dom
>= rinfo
->num_doms
)
269 if (rinfo
->sregv
[dom
]) {
271 "SCMI Voltage Domain %d already in use. Skipping: %s\n",
276 rinfo
->sregv
[dom
] = devm_kzalloc(&sdev
->dev
,
277 sizeof(struct scmi_regulator
),
279 if (!rinfo
->sregv
[dom
])
282 rinfo
->sregv
[dom
]->id
= dom
;
283 rinfo
->sregv
[dom
]->sdev
= sdev
;
284 rinfo
->sregv
[dom
]->ph
= ph
;
286 /* get hold of good nodes */
288 rinfo
->sregv
[dom
]->of_node
= np
;
291 "Found SCMI Regulator entry -- OF node [%d] -> %s\n",
297 static int scmi_regulator_probe(struct scmi_device
*sdev
)
299 int d
, ret
, num_doms
;
300 struct device_node
*np
;
301 const struct scmi_handle
*handle
= sdev
->handle
;
302 struct scmi_regulator_info
*rinfo
;
303 struct scmi_protocol_handle
*ph
;
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
);
313 num_doms
= voltage_ops
->num_domains_get(ph
);
318 dev_err(&sdev
->dev
, "failed to get voltage domains - err:%d\n",
324 rinfo
= devm_kzalloc(&sdev
->dev
, sizeof(*rinfo
), GFP_KERNEL
);
328 /* Allocate pointers array for all possible domains */
329 rinfo
->sregv
= devm_kcalloc(&sdev
->dev
, num_doms
,
330 sizeof(void *), GFP_KERNEL
);
334 rinfo
->num_doms
= num_doms
;
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).
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_scoped(np
, child
) {
345 ret
= process_scmi_regulator_of_node(sdev
, ph
, child
, rinfo
);
346 /* abort on any mem issue */
352 * Register a regulator for each valid regulator-DT-entry that we
353 * can successfully reach via SCMI and has a valid associated voltage
356 for (d
= 0; d
< num_doms
; d
++) {
357 struct scmi_regulator
*sreg
= rinfo
->sregv
[d
];
359 /* Skip empty slots */
363 ret
= scmi_regulator_common_init(sreg
);
364 /* Skip invalid voltage domains */
368 sreg
->rdev
= devm_regulator_register(&sdev
->dev
, &sreg
->desc
,
370 if (IS_ERR(sreg
->rdev
)) {
376 "Regulator %s registered for domain [%d]\n",
377 sreg
->desc
.name
, sreg
->id
);
380 dev_set_drvdata(&sdev
->dev
, rinfo
);
385 static void scmi_regulator_remove(struct scmi_device
*sdev
)
388 struct scmi_regulator_info
*rinfo
;
390 rinfo
= dev_get_drvdata(&sdev
->dev
);
394 for (d
= 0; d
< rinfo
->num_doms
; d
++) {
395 if (!rinfo
->sregv
[d
])
397 of_node_put(rinfo
->sregv
[d
]->of_node
);
401 static const struct scmi_device_id scmi_regulator_id_table
[] = {
402 { SCMI_PROTOCOL_VOLTAGE
, "regulator" },
405 MODULE_DEVICE_TABLE(scmi
, scmi_regulator_id_table
);
407 static struct scmi_driver scmi_drv
= {
408 .name
= "scmi-regulator",
409 .probe
= scmi_regulator_probe
,
410 .remove
= scmi_regulator_remove
,
411 .id_table
= scmi_regulator_id_table
,
414 module_scmi_driver(scmi_drv
);
416 MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
417 MODULE_DESCRIPTION("ARM SCMI regulator driver");
418 MODULE_LICENSE("GPL v2");