1ad651f17SEmmanuel Vadot /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3ad651f17SEmmanuel Vadot  *
4ad651f17SEmmanuel Vadot  * Copyright (c) 2018-2021 Emmanuel Vadot <manu@FreeBSD.org>
5ad651f17SEmmanuel Vadot  *
6ad651f17SEmmanuel Vadot  * Redistribution and use in source and binary forms, with or without
7ad651f17SEmmanuel Vadot  * modification, are permitted provided that the following conditions
8ad651f17SEmmanuel Vadot  * are met:
9ad651f17SEmmanuel Vadot  * 1. Redistributions of source code must retain the above copyright
10ad651f17SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer.
11ad651f17SEmmanuel Vadot  * 2. Redistributions in binary form must reproduce the above copyright
12ad651f17SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer in the
13ad651f17SEmmanuel Vadot  *    documentation and/or other materials provided with the distribution.
14ad651f17SEmmanuel Vadot  *
15ad651f17SEmmanuel Vadot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16ad651f17SEmmanuel Vadot  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17ad651f17SEmmanuel Vadot  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ad651f17SEmmanuel Vadot  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19ad651f17SEmmanuel Vadot  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20ad651f17SEmmanuel Vadot  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21ad651f17SEmmanuel Vadot  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22ad651f17SEmmanuel Vadot  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23ad651f17SEmmanuel Vadot  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24ad651f17SEmmanuel Vadot  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25ad651f17SEmmanuel Vadot  * SUCH DAMAGE.
26ad651f17SEmmanuel Vadot  */
27ad651f17SEmmanuel Vadot 
28ad651f17SEmmanuel Vadot #include <sys/param.h>
29ad651f17SEmmanuel Vadot #include <sys/bus.h>
30ad651f17SEmmanuel Vadot #include <sys/systm.h>
31ad651f17SEmmanuel Vadot #include <sys/clock.h>
32ad651f17SEmmanuel Vadot 
33ad651f17SEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
34ad651f17SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
35ad651f17SEmmanuel Vadot 
36b2f0caf1SEmmanuel Vadot #include <dev/regulator/regulator.h>
37ad651f17SEmmanuel Vadot 
38ad651f17SEmmanuel Vadot #include <dev/iicbus/pmic/rockchip/rk8xx.h>
39ad651f17SEmmanuel Vadot 
40ad651f17SEmmanuel Vadot #include "regdev_if.h"
41ad651f17SEmmanuel Vadot 
42ad651f17SEmmanuel Vadot static int rk8xx_regnode_status(struct regnode *regnode, int *status);
43ad651f17SEmmanuel Vadot static int rk8xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
44ad651f17SEmmanuel Vadot     int max_uvolt, int *udelay);
45ad651f17SEmmanuel Vadot static int rk8xx_regnode_get_voltage(struct regnode *regnode, int *uvolt);
46ad651f17SEmmanuel Vadot 
47ad651f17SEmmanuel Vadot /* #define	dprintf(sc, format, arg...)	device_printf(sc->base_dev, "%s: " format, __func__, arg) */
4889f8aa7dSEmmanuel Vadot #define	dprintf(sc, format, arg...) (sc = sc)
49ad651f17SEmmanuel Vadot 
50ad651f17SEmmanuel Vadot static int
rk8xx_regnode_init(struct regnode * regnode)51ad651f17SEmmanuel Vadot rk8xx_regnode_init(struct regnode *regnode)
52ad651f17SEmmanuel Vadot {
53ad651f17SEmmanuel Vadot 	struct rk8xx_reg_sc *sc;
54ad651f17SEmmanuel Vadot 	struct regnode_std_param *param;
55ad651f17SEmmanuel Vadot 	int rv, udelay, uvolt, status;
56ad651f17SEmmanuel Vadot 
57ad651f17SEmmanuel Vadot 	sc = regnode_get_softc(regnode);
58ad651f17SEmmanuel Vadot 	dprintf(sc, "Regulator %s init called\n", sc->def->name);
59ad651f17SEmmanuel Vadot 	param = regnode_get_stdparam(regnode);
60ad651f17SEmmanuel Vadot 	if (param->min_uvolt == 0)
61ad651f17SEmmanuel Vadot 		return (0);
62ad651f17SEmmanuel Vadot 
63ad651f17SEmmanuel Vadot 	/* Check that the regulator is preset to the correct voltage */
64ad651f17SEmmanuel Vadot 	rv  = rk8xx_regnode_get_voltage(regnode, &uvolt);
65ad651f17SEmmanuel Vadot 	if (rv != 0)
66ad651f17SEmmanuel Vadot 		return(rv);
67ad651f17SEmmanuel Vadot 
68ad651f17SEmmanuel Vadot 	if (uvolt >= param->min_uvolt && uvolt <= param->max_uvolt)
69ad651f17SEmmanuel Vadot 		return(0);
70ad651f17SEmmanuel Vadot 	/*
71ad651f17SEmmanuel Vadot 	 * Set the regulator at the correct voltage if it is not enabled.
72ad651f17SEmmanuel Vadot 	 * Do not enable it, this is will be done either by a
73ad651f17SEmmanuel Vadot 	 * consumer or by regnode_set_constraint if boot_on is true
74ad651f17SEmmanuel Vadot 	 */
75ad651f17SEmmanuel Vadot 	rv = rk8xx_regnode_status(regnode, &status);
76ad651f17SEmmanuel Vadot 	if (rv != 0 || status == REGULATOR_STATUS_ENABLED)
77ad651f17SEmmanuel Vadot 		return (rv);
78ad651f17SEmmanuel Vadot 
79ad651f17SEmmanuel Vadot 	rv = rk8xx_regnode_set_voltage(regnode, param->min_uvolt,
80ad651f17SEmmanuel Vadot 	    param->max_uvolt, &udelay);
81ad651f17SEmmanuel Vadot 	if (udelay != 0)
82ad651f17SEmmanuel Vadot 		DELAY(udelay);
83ad651f17SEmmanuel Vadot 
84ad651f17SEmmanuel Vadot 	return (rv);
85ad651f17SEmmanuel Vadot }
86ad651f17SEmmanuel Vadot 
87ad651f17SEmmanuel Vadot static int
rk8xx_regnode_enable(struct regnode * regnode,bool enable,int * udelay)88ad651f17SEmmanuel Vadot rk8xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
89ad651f17SEmmanuel Vadot {
90ad651f17SEmmanuel Vadot 	struct rk8xx_reg_sc *sc;
91ad651f17SEmmanuel Vadot 	uint8_t val;
92ad651f17SEmmanuel Vadot 
93ad651f17SEmmanuel Vadot 	sc = regnode_get_softc(regnode);
94ad651f17SEmmanuel Vadot 
95ad651f17SEmmanuel Vadot 	dprintf(sc, "%sabling regulator %s\n",
96ad651f17SEmmanuel Vadot 	    enable ? "En" : "Dis",
97ad651f17SEmmanuel Vadot 	    sc->def->name);
98ad651f17SEmmanuel Vadot 	rk8xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
99ad651f17SEmmanuel Vadot 	if (enable)
100ad651f17SEmmanuel Vadot 		val |= sc->def->enable_mask;
101ad651f17SEmmanuel Vadot 	else
102ad651f17SEmmanuel Vadot 		val &= ~sc->def->enable_mask;
103ad651f17SEmmanuel Vadot 	rk8xx_write(sc->base_dev, sc->def->enable_reg, &val, 1);
104ad651f17SEmmanuel Vadot 
105ad651f17SEmmanuel Vadot 	*udelay = 0;
106ad651f17SEmmanuel Vadot 
107ad651f17SEmmanuel Vadot 	return (0);
108ad651f17SEmmanuel Vadot }
109ad651f17SEmmanuel Vadot 
110ad651f17SEmmanuel Vadot static void
rk8xx_regnode_reg_to_voltage(struct rk8xx_reg_sc * sc,uint8_t val,int * uv)111ad651f17SEmmanuel Vadot rk8xx_regnode_reg_to_voltage(struct rk8xx_reg_sc *sc, uint8_t val, int *uv)
112ad651f17SEmmanuel Vadot {
11366a3e513SSøren Schmidt 	struct rk8xx_softc *sc1;
11466a3e513SSøren Schmidt 
11566a3e513SSøren Schmidt 	sc1 = device_get_softc(sc->base_dev);
11666a3e513SSøren Schmidt 	if (sc1->type == RK809 || sc1->type == RK817) {
11766a3e513SSøren Schmidt 		if (sc->def->voltage_step2) {
11866a3e513SSøren Schmidt 			int change;
11966a3e513SSøren Schmidt 
12066a3e513SSøren Schmidt 			change =
12166a3e513SSøren Schmidt 			    ((sc->def->voltage_min2 - sc->def->voltage_min) /
12266a3e513SSøren Schmidt 			    sc->def->voltage_step);
12366a3e513SSøren Schmidt 			if (val > change) {
12466a3e513SSøren Schmidt 				if (val < sc->def->voltage_nstep) {
12566a3e513SSøren Schmidt 					*uv = sc->def->voltage_min2 +
12666a3e513SSøren Schmidt 					    (val - change) *
12766a3e513SSøren Schmidt 					    sc->def->voltage_step2;
12866a3e513SSøren Schmidt 				} else
12966a3e513SSøren Schmidt 					*uv = sc->def->voltage_max2;
13066a3e513SSøren Schmidt 				return;
13166a3e513SSøren Schmidt 			}
13266a3e513SSøren Schmidt 		}
13366a3e513SSøren Schmidt 		if (val < sc->def->voltage_nstep)
13466a3e513SSøren Schmidt 			*uv = sc->def->voltage_min + val * sc->def->voltage_step;
13566a3e513SSøren Schmidt 		else
13666a3e513SSøren Schmidt 			*uv = sc->def->voltage_max;
13766a3e513SSøren Schmidt 
13866a3e513SSøren Schmidt 	} else {
139ad651f17SEmmanuel Vadot 		if (val < sc->def->voltage_nstep)
140ad651f17SEmmanuel Vadot 			*uv = sc->def->voltage_min + val * sc->def->voltage_step;
141ad651f17SEmmanuel Vadot 		else
142ad651f17SEmmanuel Vadot 			*uv = sc->def->voltage_min +
143ad651f17SEmmanuel Vadot 			    (sc->def->voltage_nstep * sc->def->voltage_step);
144ad651f17SEmmanuel Vadot 	}
14566a3e513SSøren Schmidt }
146ad651f17SEmmanuel Vadot 
147ad651f17SEmmanuel Vadot static int
rk8xx_regnode_voltage_to_reg(struct rk8xx_reg_sc * sc,int min_uvolt,int max_uvolt,uint8_t * val)148ad651f17SEmmanuel Vadot rk8xx_regnode_voltage_to_reg(struct rk8xx_reg_sc *sc, int min_uvolt,
149ad651f17SEmmanuel Vadot     int max_uvolt, uint8_t *val)
150ad651f17SEmmanuel Vadot {
151ad651f17SEmmanuel Vadot 	uint8_t nval;
152ad651f17SEmmanuel Vadot 	int nstep, uvolt;
15366a3e513SSøren Schmidt 	struct rk8xx_softc *sc1;
154ad651f17SEmmanuel Vadot 
15566a3e513SSøren Schmidt 	sc1 = device_get_softc(sc->base_dev);
156ad651f17SEmmanuel Vadot 	nval = 0;
157ad651f17SEmmanuel Vadot 	uvolt = sc->def->voltage_min;
158ad651f17SEmmanuel Vadot 
159ad651f17SEmmanuel Vadot 	for (nstep = 0; nstep < sc->def->voltage_nstep && uvolt < min_uvolt;
160ad651f17SEmmanuel Vadot 	     nstep++) {
161ad651f17SEmmanuel Vadot 		++nval;
16266a3e513SSøren Schmidt 		if (sc1->type == RK809 || sc1->type == RK817) {
16366a3e513SSøren Schmidt 			if (sc->def->voltage_step2) {
16466a3e513SSøren Schmidt 				if (uvolt < sc->def->voltage_min2)
16566a3e513SSøren Schmidt 					uvolt += sc->def->voltage_step;
16666a3e513SSøren Schmidt 				else
16766a3e513SSøren Schmidt 					uvolt += sc->def->voltage_step2;
16866a3e513SSøren Schmidt 			} else
16966a3e513SSøren Schmidt 				uvolt += sc->def->voltage_step;
17066a3e513SSøren Schmidt 		} else
171ad651f17SEmmanuel Vadot 			uvolt += sc->def->voltage_step;
172ad651f17SEmmanuel Vadot 	}
173ad651f17SEmmanuel Vadot 	if (uvolt > max_uvolt)
174ad651f17SEmmanuel Vadot 		return (EINVAL);
175ad651f17SEmmanuel Vadot 
176ad651f17SEmmanuel Vadot 	*val = nval;
177ad651f17SEmmanuel Vadot 	return (0);
178ad651f17SEmmanuel Vadot }
179ad651f17SEmmanuel Vadot 
180ad651f17SEmmanuel Vadot static int
rk8xx_regnode_status(struct regnode * regnode,int * status)181ad651f17SEmmanuel Vadot rk8xx_regnode_status(struct regnode *regnode, int *status)
182ad651f17SEmmanuel Vadot {
183ad651f17SEmmanuel Vadot 	struct rk8xx_reg_sc *sc;
184ad651f17SEmmanuel Vadot 	uint8_t val;
185ad651f17SEmmanuel Vadot 
186ad651f17SEmmanuel Vadot 	sc = regnode_get_softc(regnode);
187ad651f17SEmmanuel Vadot 
188ad651f17SEmmanuel Vadot 	*status = 0;
189ad651f17SEmmanuel Vadot 	rk8xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
190ad651f17SEmmanuel Vadot 	if (val & sc->def->enable_mask)
191ad651f17SEmmanuel Vadot 		*status = REGULATOR_STATUS_ENABLED;
192ad651f17SEmmanuel Vadot 
193ad651f17SEmmanuel Vadot 	return (0);
194ad651f17SEmmanuel Vadot }
195ad651f17SEmmanuel Vadot 
196ad651f17SEmmanuel Vadot static int
rk8xx_regnode_set_voltage(struct regnode * regnode,int min_uvolt,int max_uvolt,int * udelay)197ad651f17SEmmanuel Vadot rk8xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
198ad651f17SEmmanuel Vadot     int max_uvolt, int *udelay)
199ad651f17SEmmanuel Vadot {
200ad651f17SEmmanuel Vadot 	struct rk8xx_reg_sc *sc;
20166a3e513SSøren Schmidt 	uint8_t val, old;
202ad651f17SEmmanuel Vadot 	int uvolt;
20366a3e513SSøren Schmidt 	struct rk8xx_softc *sc1;
204ad651f17SEmmanuel Vadot 
205ad651f17SEmmanuel Vadot 	sc = regnode_get_softc(regnode);
20666a3e513SSøren Schmidt 	sc1 = device_get_softc(sc->base_dev);
207ad651f17SEmmanuel Vadot 
208ad651f17SEmmanuel Vadot 	if (!sc->def->voltage_step)
209ad651f17SEmmanuel Vadot 		return (ENXIO);
210ad651f17SEmmanuel Vadot 
211ad651f17SEmmanuel Vadot 	dprintf(sc, "Setting %s to %d<->%d uvolts\n",
212ad651f17SEmmanuel Vadot 	    sc->def->name,
213ad651f17SEmmanuel Vadot 	    min_uvolt,
214ad651f17SEmmanuel Vadot 	    max_uvolt);
215ad651f17SEmmanuel Vadot 	rk8xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
21666a3e513SSøren Schmidt 	old = val;
217ad651f17SEmmanuel Vadot 	if (rk8xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
218ad651f17SEmmanuel Vadot 		return (ERANGE);
219ad651f17SEmmanuel Vadot 
22066a3e513SSøren Schmidt 	if (sc1->type == RK809 || sc1->type == RK817)
22166a3e513SSøren Schmidt 		val |= (old &= ~sc->def->voltage_mask);
22266a3e513SSøren Schmidt 
223ad651f17SEmmanuel Vadot 	rk8xx_write(sc->base_dev, sc->def->voltage_reg, &val, 1);
224ad651f17SEmmanuel Vadot 
225ad651f17SEmmanuel Vadot 	rk8xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
226ad651f17SEmmanuel Vadot 
227ad651f17SEmmanuel Vadot 	*udelay = 0;
228ad651f17SEmmanuel Vadot 
229ad651f17SEmmanuel Vadot 	rk8xx_regnode_reg_to_voltage(sc, val, &uvolt);
230ad651f17SEmmanuel Vadot 	dprintf(sc, "Regulator %s set to %d uvolt\n",
231ad651f17SEmmanuel Vadot 	  sc->def->name,
232ad651f17SEmmanuel Vadot 	  uvolt);
233ad651f17SEmmanuel Vadot 
234ad651f17SEmmanuel Vadot 	return (0);
235ad651f17SEmmanuel Vadot }
236ad651f17SEmmanuel Vadot 
237ad651f17SEmmanuel Vadot static int
rk8xx_regnode_get_voltage(struct regnode * regnode,int * uvolt)238ad651f17SEmmanuel Vadot rk8xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
239ad651f17SEmmanuel Vadot {
240ad651f17SEmmanuel Vadot 	struct rk8xx_reg_sc *sc;
241ad651f17SEmmanuel Vadot 	uint8_t val;
242ad651f17SEmmanuel Vadot 
243ad651f17SEmmanuel Vadot 	sc = regnode_get_softc(regnode);
244ad651f17SEmmanuel Vadot 
245ad651f17SEmmanuel Vadot 	if (sc->def->voltage_min ==  sc->def->voltage_max) {
246ad651f17SEmmanuel Vadot 		*uvolt = sc->def->voltage_min;
247ad651f17SEmmanuel Vadot 		return (0);
248ad651f17SEmmanuel Vadot 	}
249ad651f17SEmmanuel Vadot 
250ad651f17SEmmanuel Vadot 	if (!sc->def->voltage_step)
251ad651f17SEmmanuel Vadot 		return (ENXIO);
252ad651f17SEmmanuel Vadot 
253ad651f17SEmmanuel Vadot 	rk8xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
254ad651f17SEmmanuel Vadot 	rk8xx_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
255ad651f17SEmmanuel Vadot 
256ad651f17SEmmanuel Vadot 	dprintf(sc, "Regulator %s is at %d uvolt\n",
257ad651f17SEmmanuel Vadot 	  sc->def->name,
258ad651f17SEmmanuel Vadot 	  *uvolt);
259ad651f17SEmmanuel Vadot 
260ad651f17SEmmanuel Vadot 	return (0);
261ad651f17SEmmanuel Vadot }
262ad651f17SEmmanuel Vadot 
263ad651f17SEmmanuel Vadot static regnode_method_t rk8xx_regnode_methods[] = {
264ad651f17SEmmanuel Vadot 	/* Regulator interface */
265ad651f17SEmmanuel Vadot 	REGNODEMETHOD(regnode_init,		rk8xx_regnode_init),
266ad651f17SEmmanuel Vadot 	REGNODEMETHOD(regnode_enable,		rk8xx_regnode_enable),
267ad651f17SEmmanuel Vadot 	REGNODEMETHOD(regnode_status,		rk8xx_regnode_status),
268ad651f17SEmmanuel Vadot 	REGNODEMETHOD(regnode_set_voltage,	rk8xx_regnode_set_voltage),
269ad651f17SEmmanuel Vadot 	REGNODEMETHOD(regnode_get_voltage,	rk8xx_regnode_get_voltage),
270ad651f17SEmmanuel Vadot 	REGNODEMETHOD(regnode_check_voltage,	regnode_method_check_voltage),
271ad651f17SEmmanuel Vadot 	REGNODEMETHOD_END
272ad651f17SEmmanuel Vadot };
273ad651f17SEmmanuel Vadot DEFINE_CLASS_1(rk8xx_regnode, rk8xx_regnode_class, rk8xx_regnode_methods,
274ad651f17SEmmanuel Vadot     sizeof(struct rk8xx_reg_sc), regnode_class);
275ad651f17SEmmanuel Vadot 
27698c60dc3SEmmanuel Vadot static struct rk8xx_reg_sc *
rk8xx_reg_attach(device_t dev,phandle_t node,struct rk8xx_regdef * def)277ad651f17SEmmanuel Vadot rk8xx_reg_attach(device_t dev, phandle_t node,
278ad651f17SEmmanuel Vadot     struct rk8xx_regdef *def)
279ad651f17SEmmanuel Vadot {
280ad651f17SEmmanuel Vadot 	struct rk8xx_reg_sc *reg_sc;
281ad651f17SEmmanuel Vadot 	struct regnode_init_def initdef;
282ad651f17SEmmanuel Vadot 	struct regnode *regnode;
283ad651f17SEmmanuel Vadot 
284ad651f17SEmmanuel Vadot 	memset(&initdef, 0, sizeof(initdef));
285ad651f17SEmmanuel Vadot 	if (regulator_parse_ofw_stdparam(dev, node, &initdef) != 0) {
286ad651f17SEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
287ad651f17SEmmanuel Vadot 		return (NULL);
288ad651f17SEmmanuel Vadot 	}
289ad651f17SEmmanuel Vadot 	if (initdef.std_param.min_uvolt == 0)
290ad651f17SEmmanuel Vadot 		initdef.std_param.min_uvolt = def->voltage_min;
291ad651f17SEmmanuel Vadot 	if (initdef.std_param.max_uvolt == 0)
292ad651f17SEmmanuel Vadot 		initdef.std_param.max_uvolt = def->voltage_max;
293ad651f17SEmmanuel Vadot 	initdef.id = def->id;
294ad651f17SEmmanuel Vadot 	initdef.ofw_node = node;
295ad651f17SEmmanuel Vadot 
296ad651f17SEmmanuel Vadot 	regnode = regnode_create(dev, &rk8xx_regnode_class, &initdef);
297ad651f17SEmmanuel Vadot 	if (regnode == NULL) {
298ad651f17SEmmanuel Vadot 		device_printf(dev, "cannot create regulator\n");
299ad651f17SEmmanuel Vadot 		return (NULL);
300ad651f17SEmmanuel Vadot 	}
301ad651f17SEmmanuel Vadot 
302ad651f17SEmmanuel Vadot 	reg_sc = regnode_get_softc(regnode);
303ad651f17SEmmanuel Vadot 	reg_sc->regnode = regnode;
304ad651f17SEmmanuel Vadot 	reg_sc->base_dev = dev;
305ad651f17SEmmanuel Vadot 	reg_sc->def = def;
306ad651f17SEmmanuel Vadot 	reg_sc->xref = OF_xref_from_node(node);
307ad651f17SEmmanuel Vadot 	reg_sc->param = regnode_get_stdparam(regnode);
308ad651f17SEmmanuel Vadot 
309ad651f17SEmmanuel Vadot 	regnode_register(regnode);
310ad651f17SEmmanuel Vadot 
311ad651f17SEmmanuel Vadot 	return (reg_sc);
312ad651f17SEmmanuel Vadot }
313ad651f17SEmmanuel Vadot 
31498c60dc3SEmmanuel Vadot void
rk8xx_attach_regulators(struct rk8xx_softc * sc)31598c60dc3SEmmanuel Vadot rk8xx_attach_regulators(struct rk8xx_softc *sc)
31698c60dc3SEmmanuel Vadot {
31798c60dc3SEmmanuel Vadot 	struct rk8xx_reg_sc *reg;
31898c60dc3SEmmanuel Vadot 	struct reg_list *regp;
31998c60dc3SEmmanuel Vadot 	phandle_t rnode, child;
32098c60dc3SEmmanuel Vadot 	int i;
32198c60dc3SEmmanuel Vadot 
32298c60dc3SEmmanuel Vadot 	TAILQ_INIT(&sc->regs);
32398c60dc3SEmmanuel Vadot 
32498c60dc3SEmmanuel Vadot 	rnode = ofw_bus_find_child(ofw_bus_get_node(sc->dev), "regulators");
32598c60dc3SEmmanuel Vadot 	if (rnode > 0) {
32698c60dc3SEmmanuel Vadot 		for (i = 0; i < sc->nregs; i++) {
32798c60dc3SEmmanuel Vadot 			child = ofw_bus_find_child(rnode,
32898c60dc3SEmmanuel Vadot 			    sc->regdefs[i].name);
32998c60dc3SEmmanuel Vadot 			if (child == 0)
33098c60dc3SEmmanuel Vadot 				continue;
33198c60dc3SEmmanuel Vadot 			if (OF_hasprop(child, "regulator-name") != 1)
33298c60dc3SEmmanuel Vadot 				continue;
33398c60dc3SEmmanuel Vadot 			reg = rk8xx_reg_attach(sc->dev, child, &sc->regdefs[i]);
33498c60dc3SEmmanuel Vadot 			if (reg == NULL) {
33598c60dc3SEmmanuel Vadot 				device_printf(sc->dev,
33698c60dc3SEmmanuel Vadot 				    "cannot attach regulator %s\n",
33798c60dc3SEmmanuel Vadot 				    sc->regdefs[i].name);
33898c60dc3SEmmanuel Vadot 				continue;
33998c60dc3SEmmanuel Vadot 			}
34098c60dc3SEmmanuel Vadot 			regp = malloc(sizeof(*regp), M_DEVBUF, M_WAITOK | M_ZERO);
34198c60dc3SEmmanuel Vadot 			regp->reg = reg;
34298c60dc3SEmmanuel Vadot 			TAILQ_INSERT_TAIL(&sc->regs, regp, next);
34398c60dc3SEmmanuel Vadot 			if (bootverbose)
34498c60dc3SEmmanuel Vadot 				device_printf(sc->dev, "Regulator %s attached\n",
34598c60dc3SEmmanuel Vadot 				    sc->regdefs[i].name);
34698c60dc3SEmmanuel Vadot 		}
34798c60dc3SEmmanuel Vadot 	}
34898c60dc3SEmmanuel Vadot }
34998c60dc3SEmmanuel Vadot 
350ad651f17SEmmanuel Vadot int
rk8xx_map(device_t dev,phandle_t xref,int ncells,pcell_t * cells,intptr_t * id)351ad651f17SEmmanuel Vadot rk8xx_map(device_t dev, phandle_t xref, int ncells,
352ad651f17SEmmanuel Vadot     pcell_t *cells, intptr_t *id)
353ad651f17SEmmanuel Vadot {
354ad651f17SEmmanuel Vadot 	struct rk8xx_softc *sc;
355ad651f17SEmmanuel Vadot 	struct reg_list *regp;
356ad651f17SEmmanuel Vadot 
357ad651f17SEmmanuel Vadot 	sc = device_get_softc(dev);
358ad651f17SEmmanuel Vadot 
359ad651f17SEmmanuel Vadot 	TAILQ_FOREACH(regp, &sc->regs, next) {
360ad651f17SEmmanuel Vadot 		if (regp->reg->xref == xref) {
361ad651f17SEmmanuel Vadot 			*id = regp->reg->def->id;
362ad651f17SEmmanuel Vadot 			return (0);
363ad651f17SEmmanuel Vadot 		}
364ad651f17SEmmanuel Vadot 	}
365ad651f17SEmmanuel Vadot 
366ad651f17SEmmanuel Vadot 	return (ERANGE);
367ad651f17SEmmanuel Vadot }
368