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