Lines Matching +full:regulator +full:- +full:fixed +full:- +full:domain
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.
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
21 // Each SCMI regulator instance is associated, through the means of a proper DT
22 // entry description, to a specific SCMI Voltage Domain.
29 #include <linux/regulator/driver.h>
30 #include <linux/regulator/machine.h>
31 #include <linux/regulator/of_regulator.h>
57 return voltage_ops->config_set(sreg->ph, sreg->id, in scmi_reg_enable()
65 return voltage_ops->config_set(sreg->ph, sreg->id, in scmi_reg_disable()
75 ret = voltage_ops->config_get(sreg->ph, sreg->id, &config); in scmi_reg_is_enabled()
77 dev_err(&sreg->sdev->dev, in scmi_reg_is_enabled()
78 "Error %d reading regulator %s status.\n", in scmi_reg_is_enabled()
79 ret, sreg->desc.name); in scmi_reg_is_enabled()
92 ret = voltage_ops->level_get(sreg->ph, sreg->id, &volt_uV); in scmi_reg_get_voltage_sel()
96 return sreg->desc.ops->map_voltage(rdev, volt_uV, volt_uV); in scmi_reg_get_voltage_sel()
105 volt_uV = sreg->desc.ops->list_voltage(rdev, selector); in scmi_reg_set_voltage_sel()
107 return -EINVAL; in scmi_reg_set_voltage_sel()
109 return voltage_ops->level_set(sreg->ph, sreg->id, 0x0, volt_uV); in scmi_reg_set_voltage_sel()
147 * triplet by the SCMI Voltage Domain protocol support itself. in scmi_config_linear_regulator_mappings()
150 delta_uV = (vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH] - in scmi_config_linear_regulator_mappings()
151 vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW]); in scmi_config_linear_regulator_mappings()
153 /* Rule out buggy negative-intervals answers from fw */ in scmi_config_linear_regulator_mappings()
155 dev_err(&sreg->sdev->dev, in scmi_config_linear_regulator_mappings()
156 "Invalid volt-range %d-%duV for domain %d\n", in scmi_config_linear_regulator_mappings()
157 vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW], in scmi_config_linear_regulator_mappings()
158 vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_HIGH], in scmi_config_linear_regulator_mappings()
159 sreg->id); in scmi_config_linear_regulator_mappings()
160 return -EINVAL; in scmi_config_linear_regulator_mappings()
164 /* Just one fixed voltage exposed by SCMI */ in scmi_config_linear_regulator_mappings()
165 sreg->desc.fixed_uV = in scmi_config_linear_regulator_mappings()
166 vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW]; in scmi_config_linear_regulator_mappings()
167 sreg->desc.n_voltages = 1; in scmi_config_linear_regulator_mappings()
168 sreg->desc.ops = &scmi_reg_fixed_ops; in scmi_config_linear_regulator_mappings()
171 sreg->desc.min_uV = in scmi_config_linear_regulator_mappings()
172 vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_LOW]; in scmi_config_linear_regulator_mappings()
173 sreg->desc.uV_step = in scmi_config_linear_regulator_mappings()
174 vinfo->levels_uv[SCMI_VOLTAGE_SEGMENT_STEP]; in scmi_config_linear_regulator_mappings()
175 sreg->desc.linear_min_sel = 0; in scmi_config_linear_regulator_mappings()
176 sreg->desc.n_voltages = (delta_uV / sreg->desc.uV_step) + 1; in scmi_config_linear_regulator_mappings()
177 sreg->desc.ops = &scmi_reg_linear_ops; in scmi_config_linear_regulator_mappings()
188 sreg->desc.n_voltages = vinfo->num_levels; in scmi_config_discrete_regulator_mappings()
190 if (sreg->desc.n_voltages > 1) { in scmi_config_discrete_regulator_mappings()
191 sreg->desc.volt_table = (const unsigned int *)vinfo->levels_uv; in scmi_config_discrete_regulator_mappings()
192 sreg->desc.ops = &scmi_reg_discrete_ops; in scmi_config_discrete_regulator_mappings()
194 sreg->desc.fixed_uV = vinfo->levels_uv[0]; in scmi_config_discrete_regulator_mappings()
195 sreg->desc.ops = &scmi_reg_fixed_ops; in scmi_config_discrete_regulator_mappings()
204 struct device *dev = &sreg->sdev->dev; in scmi_regulator_common_init()
207 vinfo = voltage_ops->info_get(sreg->ph, sreg->id); in scmi_regulator_common_init()
209 dev_warn(dev, "Failure to get voltage domain %d\n", in scmi_regulator_common_init()
210 sreg->id); in scmi_regulator_common_init()
211 return -ENODEV; in scmi_regulator_common_init()
215 * Regulator framework does not fully support negative voltages in scmi_regulator_common_init()
216 * so we discard any voltage domain reported as supporting negative in scmi_regulator_common_init()
218 * be non-negative from here on. in scmi_regulator_common_init()
220 if (vinfo->negative_volts_allowed) { in scmi_regulator_common_init()
222 sreg->of_node->full_name); in scmi_regulator_common_init()
223 return -EOPNOTSUPP; in scmi_regulator_common_init()
226 sreg->desc.name = devm_kasprintf(dev, GFP_KERNEL, "%s", vinfo->name); in scmi_regulator_common_init()
227 if (!sreg->desc.name) in scmi_regulator_common_init()
228 return -ENOMEM; in scmi_regulator_common_init()
230 sreg->desc.id = sreg->id; in scmi_regulator_common_init()
231 sreg->desc.type = REGULATOR_VOLTAGE; in scmi_regulator_common_init()
232 sreg->desc.owner = THIS_MODULE; in scmi_regulator_common_init()
233 sreg->desc.of_match_full_name = true; in scmi_regulator_common_init()
234 sreg->desc.of_match = sreg->of_node->full_name; in scmi_regulator_common_init()
235 sreg->desc.regulators_node = "regulators"; in scmi_regulator_common_init()
236 if (vinfo->segmented) in scmi_regulator_common_init()
247 sreg->conf.dev = dev; in scmi_regulator_common_init()
250 sreg->conf.driver_data = sreg; in scmi_regulator_common_init()
266 if (dom >= rinfo->num_doms) in process_scmi_regulator_of_node()
267 return -ENODEV; in process_scmi_regulator_of_node()
269 if (rinfo->sregv[dom]) { in process_scmi_regulator_of_node()
270 dev_err(&sdev->dev, in process_scmi_regulator_of_node()
271 "SCMI Voltage Domain %d already in use. Skipping: %s\n", in process_scmi_regulator_of_node()
272 dom, np->full_name); in process_scmi_regulator_of_node()
273 return -EINVAL; in process_scmi_regulator_of_node()
276 rinfo->sregv[dom] = devm_kzalloc(&sdev->dev, in process_scmi_regulator_of_node()
279 if (!rinfo->sregv[dom]) in process_scmi_regulator_of_node()
280 return -ENOMEM; in process_scmi_regulator_of_node()
282 rinfo->sregv[dom]->id = dom; in process_scmi_regulator_of_node()
283 rinfo->sregv[dom]->sdev = sdev; in process_scmi_regulator_of_node()
284 rinfo->sregv[dom]->ph = ph; in process_scmi_regulator_of_node()
288 rinfo->sregv[dom]->of_node = np; in process_scmi_regulator_of_node()
290 dev_dbg(&sdev->dev, in process_scmi_regulator_of_node()
291 "Found SCMI Regulator entry -- OF node [%d] -> %s\n", in process_scmi_regulator_of_node()
292 dom, np->full_name); in process_scmi_regulator_of_node()
301 const struct scmi_handle *handle = sdev->handle; in scmi_regulator_probe()
306 return -ENODEV; in scmi_regulator_probe()
308 voltage_ops = handle->devm_protocol_get(sdev, in scmi_regulator_probe()
313 num_doms = voltage_ops->num_domains_get(ph); in scmi_regulator_probe()
318 dev_err(&sdev->dev, "failed to get voltage domains - err:%d\n", in scmi_regulator_probe()
324 rinfo = devm_kzalloc(&sdev->dev, sizeof(*rinfo), GFP_KERNEL); in scmi_regulator_probe()
326 return -ENOMEM; in scmi_regulator_probe()
329 rinfo->sregv = devm_kcalloc(&sdev->dev, num_doms, in scmi_regulator_probe()
331 if (!rinfo->sregv) in scmi_regulator_probe()
332 return -ENOMEM; in scmi_regulator_probe()
334 rinfo->num_doms = num_doms; in scmi_regulator_probe()
337 * Start collecting into rinfo->sregv possibly good SCMI Regulators as in scmi_regulator_probe()
338 * described by a well-formed DT entry and associated with an existing in scmi_regulator_probe()
339 * plausible SCMI Voltage Domain number, all belonging to this SCMI in scmi_regulator_probe()
340 * platform instance node (handle->dev->of_node). in scmi_regulator_probe()
342 of_node_get(handle->dev->of_node); in scmi_regulator_probe()
343 np = of_find_node_by_name(handle->dev->of_node, "regulators"); in scmi_regulator_probe()
347 if (ret == -ENOMEM) in scmi_regulator_probe()
352 * Register a regulator for each valid regulator-DT-entry that we in scmi_regulator_probe()
354 * domain. in scmi_regulator_probe()
357 struct scmi_regulator *sreg = rinfo->sregv[d]; in scmi_regulator_probe()
368 sreg->rdev = devm_regulator_register(&sdev->dev, &sreg->desc, in scmi_regulator_probe()
369 &sreg->conf); in scmi_regulator_probe()
370 if (IS_ERR(sreg->rdev)) { in scmi_regulator_probe()
371 sreg->rdev = NULL; in scmi_regulator_probe()
375 dev_info(&sdev->dev, in scmi_regulator_probe()
376 "Regulator %s registered for domain [%d]\n", in scmi_regulator_probe()
377 sreg->desc.name, sreg->id); in scmi_regulator_probe()
380 dev_set_drvdata(&sdev->dev, rinfo); in scmi_regulator_probe()
390 rinfo = dev_get_drvdata(&sdev->dev); in scmi_regulator_remove()
394 for (d = 0; d < rinfo->num_doms; d++) { in scmi_regulator_remove()
395 if (!rinfo->sregv[d]) in scmi_regulator_remove()
397 of_node_put(rinfo->sregv[d]->of_node); in scmi_regulator_remove()
402 { SCMI_PROTOCOL_VOLTAGE, "regulator" },
408 .name = "scmi-regulator",
417 MODULE_DESCRIPTION("ARM SCMI regulator driver");