xref: /openbsd/sys/dev/fdt/rkpmic.c (revision 72c7c57a)
1 /*	$OpenBSD: rkpmic.c,v 1.14 2024/03/02 19:52:41 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22 
23 #include <dev/ofw/openfirm.h>
24 #include <dev/ofw/ofw_regulator.h>
25 #include <dev/ofw/fdt.h>
26 
27 #include <dev/i2c/i2cvar.h>
28 #include <dev/spi/spivar.h>
29 
30 #include <dev/clock_subr.h>
31 
32 #define RK80X_SECONDS		0x00
33 #define RK80X_MINUTES		0x01
34 #define RK80X_HOURS		0x02
35 #define RK80X_DAYS		0x03
36 #define RK80X_MONTHS		0x04
37 #define RK80X_YEARS		0x05
38 #define RK80X_WEEKS		0x06
39 #define RK80X_NRTC_REGS	7
40 
41 #define RK805_RTC_CTRL		0x10
42 #define RK808_RTC_CTRL		0x10
43 #define RK809_RTC_CTRL		0x0d
44 #define  RK80X_RTC_CTRL_STOP_RTC	0x01
45 
46 #define RK805_RTC_STATUS	0x11
47 #define RK808_RTC_STATUS	0x11
48 #define RK809_RTC_STATUS	0x0e
49 #define  RK80X_RTC_STATUS_POWER_UP	0x80
50 
51 #define RKSPI_CMD_READ		(0 << 7)
52 #define RKSPI_CMD_WRITE		(1 << 7)
53 
54 struct rkpmic_vsel_range {
55 	uint32_t base, delta;
56 	uint8_t vsel_min, vsel_max;
57 };
58 
59 struct rkpmic_regdata {
60 	const char *name;
61 	uint8_t reg, mask;
62 	const struct rkpmic_vsel_range *vsel_range;
63 };
64 
65 /*
66  * Used by RK805 for BUCK1, BUCK2
67  *  0-59:	0.7125V-1.45V, step=12.5mV
68  *  60-62:	1.8V-2.2V, step=200mV
69  *  63:		2.3V
70  */
71 const struct rkpmic_vsel_range rk805_vsel_range1[] = {
72 	{ 712500, 12500, 0, 59 },
73 	{ 1800000, 200000, 60, 62 },
74 	{ 2300000, 0, 63, 63 },
75 	{}
76 };
77 
78 /*
79  * Used by RK805 for BUCK4
80  *  0-27:	0.8V-3.5V, step=100mV
81  */
82 const struct rkpmic_vsel_range rk805_vsel_range2[] = {
83 	{ 800000, 100000, 0, 27 },
84 	{}
85 };
86 
87 /*
88  * Used by RK805 for LDO1-3
89  *  0-26:	0.8V-3.4V, step=100mV
90  */
91 const struct rkpmic_vsel_range rk805_vsel_range3[] = {
92 	{ 800000, 100000, 0, 26 },
93 	{}
94 };
95 
96 const struct rkpmic_regdata rk805_regdata[] = {
97 	{ "DCDC_REG1", 0x2f, 0x3f, rk805_vsel_range1 },
98 	{ "DCDC_REG2", 0x33, 0x3f, rk805_vsel_range1 },
99 	{ "DCDC_REG4", 0x38, 0x1f, rk805_vsel_range2 },
100 	{ "LDO_REG1", 0x3b, 0x1f, rk805_vsel_range3 },
101 	{ "LDO_REG2", 0x3d, 0x1f, rk805_vsel_range3 },
102 	{ "LDO_REG3", 0x3f, 0x1f, rk805_vsel_range3 },
103 	{ }
104 };
105 
106 /*
107  * Used by RK806 for BUCK
108  *  0-159:	0.5V-1.5V, step=6.25mV
109  *  160-236:	1.5V-3.4V, step=25mV
110  *  237-255:	3.4V-3.4V, step=0mV
111  */
112 const struct rkpmic_vsel_range rk806_vsel_range1[] = {
113 	{ 500000, 6250, 0, 159 },
114 	{ 1500000, 25000, 160, 236 },
115 	{ 3400000, 0, 237, 255 },
116 	{}
117 };
118 
119 /*
120  * Used by RK806 for LDO
121  *  0-232:	0.5V-3.4V, step=12.5mV
122  *  233-255:	3.4V-3.4V, step=0mV
123  */
124 const struct rkpmic_vsel_range rk806_vsel_range2[] = {
125 	{ 500000, 12500, 0, 232 },
126 	{ 3400000, 0, 233, 255 },
127 	{}
128 };
129 
130 const struct rkpmic_regdata rk806_regdata[] = {
131 	{ "dcdc-reg1", 0x1a, 0xff, rk806_vsel_range1 },
132 	{ "dcdc-reg2", 0x1b, 0xff, rk806_vsel_range1 },
133 	{ "dcdc-reg3", 0x1c, 0xff, rk806_vsel_range1 },
134 	{ "dcdc-reg4", 0x1d, 0xff, rk806_vsel_range1 },
135 	{ "dcdc-reg5", 0x1e, 0xff, rk806_vsel_range1 },
136 	{ "dcdc-reg6", 0x1f, 0xff, rk806_vsel_range1 },
137 	{ "dcdc-reg7", 0x20, 0xff, rk806_vsel_range1 },
138 	{ "dcdc-reg8", 0x21, 0xff, rk806_vsel_range1 },
139 	{ "dcdc-reg9", 0x22, 0xff, rk806_vsel_range1 },
140 	{ "dcdc-reg10", 0x23, 0xff, rk806_vsel_range1 },
141 	{ "nldo-reg1", 0x43, 0xff, rk806_vsel_range2 },
142 	{ "nldo-reg2", 0x44, 0xff, rk806_vsel_range2 },
143 	{ "nldo-reg3", 0x45, 0xff, rk806_vsel_range2 },
144 	{ "nldo-reg4", 0x46, 0xff, rk806_vsel_range2 },
145 	{ "nldo-reg5", 0x47, 0xff, rk806_vsel_range2 },
146 	{ "pldo-reg1", 0x4e, 0xff, rk806_vsel_range2 },
147 	{ "pldo-reg2", 0x4f, 0xff, rk806_vsel_range2 },
148 	{ "pldo-reg3", 0x50, 0xff, rk806_vsel_range2 },
149 	{ "pldo-reg4", 0x51, 0xff, rk806_vsel_range2 },
150 	{ "pldo-reg5", 0x52, 0xff, rk806_vsel_range2 },
151 	{ "pldo-reg6", 0x53, 0xff, rk806_vsel_range2 },
152 	{ }
153 };
154 
155 /*
156  * Used by RK808 for BUCK1 & BUCK2
157  *  0-63:	0.7125V-1.5V, step=12.5mV
158  */
159 const struct rkpmic_vsel_range rk808_vsel_range1[] = {
160 	{ 712500, 12500, 0, 63 },
161 	{}
162 };
163 
164 /*
165  * Used by RK808 for BUCK4
166  *  0-15:	1.8V-3.3V,step=100mV
167  */
168 const struct rkpmic_vsel_range rk808_vsel_range2[] = {
169 	{ 1800000, 100000, 0, 15 },
170 	{}
171 };
172 
173 /*
174  * Used by RK808 for LDO1-2, 4-5, 8
175  *  0-16:	1.8V-3.4V, step=100mV
176  */
177 const struct rkpmic_vsel_range rk808_vsel_range3[] = {
178 	{ 1800000, 100000, 0, 16 },
179 	{}
180 };
181 
182 /*
183  * Used by RK808 for LDO3
184  *   0-12:	0.8V~2.0V, step=100mV
185  *   13:	2.2V
186  *   15:	2.5V
187  */
188 const struct rkpmic_vsel_range rk808_vsel_range4[] = {
189 	{ 800000, 100000, 0, 12 },
190 	{ 2200000, 0, 13, 13 },
191 	{ 2500000, 0, 15, 15 },
192 	{}
193 };
194 
195 /*
196  * Used by RK808 for LDO6-7
197  *  0-17:	0.8V-2.5V,step=100mV
198  */
199 const struct rkpmic_vsel_range rk808_vsel_range5[] = {
200 	{ 800000, 100000, 0, 17 },
201 	{}
202 };
203 
204 const struct rkpmic_regdata rk808_regdata[] = {
205 	{ "DCDC_REG1", 0x2f, 0x3f, rk808_vsel_range1 },
206 	{ "DCDC_REG2", 0x33, 0x3f, rk808_vsel_range1 },
207 	{ "DCDC_REG4", 0x38, 0x0f, rk808_vsel_range2 },
208 	{ "LDO_REG1", 0x3b, 0x1f, rk808_vsel_range3 },
209 	{ "LDO_REG2", 0x3d, 0x1f, rk808_vsel_range3 },
210 	{ "LDO_REG3", 0x3f, 0x0f, rk808_vsel_range4 },
211 	{ "LDO_REG4", 0x41, 0x1f, rk808_vsel_range3 },
212 	{ "LDO_REG5", 0x43, 0x1f, rk808_vsel_range3 },
213 	{ "LDO_REG6", 0x45, 0x1f, rk808_vsel_range5 },
214 	{ "LDO_REG7", 0x47, 0x1f, rk808_vsel_range5 },
215 	{ "LDO_REG8", 0x49, 0x1f, rk808_vsel_range3 },
216 	{ }
217 };
218 
219 /*
220  * Used by RK809 for BUCK1-3
221  *  0-80:	0.5V-1.5V,step=12.5mV
222  *  81-89:	1.6V-2.4V,step=100mV
223  */
224 const struct rkpmic_vsel_range rk809_vsel_range1[] = {
225 	{ 500000, 12500, 0, 80 },
226 	{ 1600000, 100000, 81, 89 },
227 	{}
228 };
229 
230 /*
231  * Used by RK809 for BUCK4
232  *  0-80:	0.5V-1.5V,step=12.5mV
233  *  81-99:	1.6V-3.4V,step=100mV
234  */
235 const struct rkpmic_vsel_range rk809_vsel_range2[] = {
236 	{ 500000, 12500, 0, 80 },
237 	{ 1600000, 100000, 81, 99 },
238 	{}
239 };
240 
241 /*
242  * Used by RK809 for BUCK5
243  *  0:		1.5V
244  *  1-3:	1.8V-2.2V,step=200mV
245  *  4-5:	2.8V-3.0V,step=200mV
246  *  6-7:	3.3V-3.6V,step=300mV
247  */
248 const struct rkpmic_vsel_range rk809_vsel_range3[] = {
249 	{ 1500000, 0, 0, 0 },
250 	{ 1800000, 200000, 1, 3 },
251 	{ 2800000, 200000, 4, 5 },
252 	{ 3300000, 300000, 6, 7 },
253 	{}
254 };
255 
256 /*
257  * Used by RK809 for LDO1-7
258  *  0-112: 0.6V-3.4V,step=25mV
259  */
260 const struct rkpmic_vsel_range rk809_vsel_range4[] = {
261 	{ 600000, 25000, 0, 112 },
262 	{}
263 };
264 
265 const struct rkpmic_regdata rk809_regdata[] = {
266 	{ "DCDC_REG1", 0xbb, 0x7f, rk809_vsel_range1 },
267 	{ "DCDC_REG2", 0xbe, 0x7f, rk809_vsel_range1 },
268 	{ "DCDC_REG3", 0xc1, 0x7f, rk809_vsel_range1 },
269 	{ "DCDC_REG4", 0xc4, 0x7f, rk809_vsel_range2 },
270 	{ "DCDC_REG5", 0xde, 0x0f, rk809_vsel_range3},
271 	{ "LDO_REG1", 0xcc, 0x7f, rk809_vsel_range4 },
272 	{ "LDO_REG2", 0xce, 0x7f, rk809_vsel_range4 },
273 	{ "LDO_REG3", 0xd0, 0x7f, rk809_vsel_range4 },
274 	{ "LDO_REG4", 0xd2, 0x7f, rk809_vsel_range4 },
275 	{ "LDO_REG5", 0xd4, 0x7f, rk809_vsel_range4 },
276 	{ "LDO_REG6", 0xd6, 0x7f, rk809_vsel_range4 },
277 	{ "LDO_REG7", 0xd8, 0x7f, rk809_vsel_range4 },
278 	{ "LDO_REG8", 0xda, 0x7f, rk809_vsel_range4 },
279 	{ "LDO_REG9", 0xdc, 0x7f, rk809_vsel_range4 },
280 	{ }
281 };
282 
283 /*
284  * Used by RK817 for BOOST
285  *  0-7: 4.7V-5.4V,step=100mV
286  */
287 const struct rkpmic_vsel_range rk817_boost_range[] = {
288 	{ 4700000, 100000, 0, 7 },
289 	{}
290 };
291 
292 const struct rkpmic_regdata rk817_regdata[] = {
293 	{ "DCDC_REG1", 0xbb, 0x7f, rk809_vsel_range1 },
294 	{ "DCDC_REG2", 0xbe, 0x7f, rk809_vsel_range1 },
295 	{ "DCDC_REG3", 0xc1, 0x7f, rk809_vsel_range1 },
296 	{ "DCDC_REG4", 0xc4, 0x7f, rk809_vsel_range2 },
297 	{ "LDO_REG1", 0xcc, 0x7f, rk809_vsel_range4 },
298 	{ "LDO_REG2", 0xce, 0x7f, rk809_vsel_range4 },
299 	{ "LDO_REG3", 0xd0, 0x7f, rk809_vsel_range4 },
300 	{ "LDO_REG4", 0xd2, 0x7f, rk809_vsel_range4 },
301 	{ "LDO_REG5", 0xd4, 0x7f, rk809_vsel_range4 },
302 	{ "LDO_REG6", 0xd6, 0x7f, rk809_vsel_range4 },
303 	{ "LDO_REG7", 0xd8, 0x7f, rk809_vsel_range4 },
304 	{ "LDO_REG8", 0xda, 0x7f, rk809_vsel_range4 },
305 	{ "LDO_REG9", 0xdc, 0x7f, rk809_vsel_range4 },
306 	{ "BOOST", 0xde, 0x07, rk817_boost_range },
307 	{ }
308 };
309 
310 struct rkpmic_softc {
311 	struct device sc_dev;
312 	int sc_node;
313 
314 	i2c_tag_t sc_i2c_tag;
315 	i2c_addr_t sc_i2c_addr;
316 	spi_tag_t sc_spi_tag;
317 	struct spi_config sc_spi_conf;
318 
319 	int sc_rtc_ctrl_reg, sc_rtc_status_reg;
320 	struct todr_chip_handle sc_todr;
321 	const struct rkpmic_regdata *sc_regdata;
322 
323 	int (*sc_read)(struct rkpmic_softc *, uint8_t, void *, size_t);
324 	int (*sc_write)(struct rkpmic_softc *, uint8_t, void *, size_t);
325 };
326 
327 int	rkpmic_i2c_match(struct device *, void *, void *);
328 void	rkpmic_i2c_attach(struct device *, struct device *, void *);
329 int	rkpmic_i2c_read(struct rkpmic_softc *, uint8_t, void *, size_t);
330 int	rkpmic_i2c_write(struct rkpmic_softc *, uint8_t, void *, size_t);
331 
332 int	rkpmic_spi_match(struct device *, void *, void *);
333 void	rkpmic_spi_attach(struct device *, struct device *, void *);
334 int	rkpmic_spi_read(struct rkpmic_softc *, uint8_t, void *, size_t);
335 int	rkpmic_spi_write(struct rkpmic_softc *, uint8_t, void *, size_t);
336 
337 void	rkpmic_attach(struct device *, struct device *, void *);
338 
339 const struct cfattach rkpmic_i2c_ca = {
340 	sizeof(struct rkpmic_softc), rkpmic_i2c_match, rkpmic_i2c_attach
341 };
342 
343 const struct cfattach rkpmic_spi_ca = {
344 	sizeof(struct rkpmic_softc), rkpmic_spi_match, rkpmic_spi_attach
345 };
346 
347 struct cfdriver rkpmic_cd = {
348 	NULL, "rkpmic", DV_DULL
349 };
350 
351 void	rkpmic_attach_regulator(struct rkpmic_softc *, int);
352 uint8_t	rkpmic_reg_read(struct rkpmic_softc *, int);
353 void	rkpmic_reg_write(struct rkpmic_softc *, int, uint8_t);
354 int	rkpmic_clock_read(struct rkpmic_softc *, struct clock_ymdhms *);
355 int	rkpmic_clock_write(struct rkpmic_softc *, struct clock_ymdhms *);
356 int	rkpmic_gettime(struct todr_chip_handle *, struct timeval *);
357 int	rkpmic_settime(struct todr_chip_handle *, struct timeval *);
358 
359 int
360 rkpmic_i2c_match(struct device *parent, void *match, void *aux)
361 {
362 	struct i2c_attach_args *ia = aux;
363 
364 	return (strcmp(ia->ia_name, "rockchip,rk805") == 0 ||
365 	    strcmp(ia->ia_name, "rockchip,rk808") == 0 ||
366 	    strcmp(ia->ia_name, "rockchip,rk809") == 0 ||
367 	    strcmp(ia->ia_name, "rockchip,rk817") == 0);
368 }
369 
370 void
371 rkpmic_i2c_attach(struct device *parent, struct device *self, void *aux)
372 {
373 	struct rkpmic_softc *sc = (struct rkpmic_softc *)self;
374 	struct i2c_attach_args *ia = aux;
375 
376 	sc->sc_i2c_tag = ia->ia_tag;
377 	sc->sc_i2c_addr = ia->ia_addr;
378 	sc->sc_node = *(int *)ia->ia_cookie;
379 	sc->sc_read = rkpmic_i2c_read;
380 	sc->sc_write = rkpmic_i2c_write;
381 
382 	rkpmic_attach(parent, self, aux);
383 }
384 
385 int
386 rkpmic_spi_match(struct device *parent, void *match, void *aux)
387 {
388 	struct spi_attach_args *sa = aux;
389 
390 	return (strcmp(sa->sa_name, "rockchip,rk806") == 0);
391 }
392 
393 void
394 rkpmic_spi_attach(struct device *parent, struct device *self, void *aux)
395 {
396 	struct rkpmic_softc *sc = (struct rkpmic_softc *)self;
397 	struct spi_attach_args *sa = aux;
398 
399 	sc->sc_spi_tag = sa->sa_tag;
400 	sc->sc_node = *(int *)sa->sa_cookie;
401 	sc->sc_read = rkpmic_spi_read;
402 	sc->sc_write = rkpmic_spi_write;
403 
404 	sc->sc_spi_conf.sc_bpw = 8;
405 	sc->sc_spi_conf.sc_freq =
406 	    OF_getpropint(sc->sc_node, "spi-max-frequency", 1000000);
407 	sc->sc_spi_conf.sc_cs = OF_getpropint(sc->sc_node, "reg", 0);
408 
409 	rkpmic_attach(parent, self, aux);
410 }
411 
412 void
413 rkpmic_attach(struct device *parent, struct device *self, void *aux)
414 {
415 	struct rkpmic_softc *sc = (struct rkpmic_softc *)self;
416 	const char *chip;
417 	int node;
418 
419 	if (OF_is_compatible(sc->sc_node, "rockchip,rk805")) {
420 		chip = "RK805";
421 		sc->sc_rtc_ctrl_reg = RK805_RTC_CTRL;
422 		sc->sc_rtc_status_reg = RK805_RTC_STATUS;
423 		sc->sc_regdata = rk805_regdata;
424 	} else if (OF_is_compatible(sc->sc_node, "rockchip,rk806")) {
425 		chip = "RK806";
426 		sc->sc_regdata = rk806_regdata;
427 	} else if (OF_is_compatible(sc->sc_node, "rockchip,rk808")) {
428 		chip = "RK808";
429 		sc->sc_rtc_ctrl_reg = RK808_RTC_CTRL;
430 		sc->sc_rtc_status_reg = RK808_RTC_STATUS;
431 		sc->sc_regdata = rk808_regdata;
432 	} else if (OF_is_compatible(sc->sc_node, "rockchip,rk809")) {
433 		chip = "RK809";
434 		sc->sc_rtc_ctrl_reg = RK809_RTC_CTRL;
435 		sc->sc_rtc_status_reg = RK809_RTC_STATUS;
436 		sc->sc_regdata = rk809_regdata;
437 	} else {
438 		chip = "RK817";
439 		sc->sc_rtc_ctrl_reg = RK809_RTC_CTRL;
440 		sc->sc_rtc_status_reg = RK809_RTC_STATUS;
441 		sc->sc_regdata = rk817_regdata;
442 	}
443 	printf(": %s\n", chip);
444 
445 	if (sc->sc_rtc_ctrl_reg) {
446 		sc->sc_todr.cookie = sc;
447 		sc->sc_todr.todr_gettime = rkpmic_gettime;
448 		sc->sc_todr.todr_settime = rkpmic_settime;
449 		sc->sc_todr.todr_quality = 0;
450 		todr_attach(&sc->sc_todr);
451 	}
452 
453 	node = OF_getnodebyname(sc->sc_node, "regulators");
454 	if (node == 0)
455 		return;
456 	for (node = OF_child(node); node; node = OF_peer(node))
457 		rkpmic_attach_regulator(sc, node);
458 }
459 
460 struct rkpmic_regulator {
461 	struct rkpmic_softc *rr_sc;
462 
463 	uint8_t rr_reg, rr_mask;
464 	const struct rkpmic_vsel_range *rr_vsel_range;
465 
466 	struct regulator_device rr_rd;
467 };
468 
469 uint32_t rkpmic_get_voltage(void *);
470 int	rkpmic_set_voltage(void *, uint32_t);
471 
472 void
473 rkpmic_attach_regulator(struct rkpmic_softc *sc, int node)
474 {
475 	struct rkpmic_regulator *rr;
476 	char name[32];
477 	int i;
478 
479 	name[0] = 0;
480 	OF_getprop(node, "name", name, sizeof(name));
481 	name[sizeof(name) - 1] = 0;
482 	for (i = 0; sc->sc_regdata[i].name; i++) {
483 		if (strcmp(sc->sc_regdata[i].name, name) == 0)
484 			break;
485 	}
486 	if (sc->sc_regdata[i].name == NULL)
487 		return;
488 
489 	rr = malloc(sizeof(*rr), M_DEVBUF, M_WAITOK | M_ZERO);
490 	rr->rr_sc = sc;
491 
492 	rr->rr_reg = sc->sc_regdata[i].reg;
493 	rr->rr_mask = sc->sc_regdata[i].mask;
494 	rr->rr_vsel_range = sc->sc_regdata[i].vsel_range;
495 
496 	rr->rr_rd.rd_node = node;
497 	rr->rr_rd.rd_cookie = rr;
498 	rr->rr_rd.rd_get_voltage = rkpmic_get_voltage;
499 	rr->rr_rd.rd_set_voltage = rkpmic_set_voltage;
500 	regulator_register(&rr->rr_rd);
501 }
502 
503 uint32_t
504 rkpmic_get_voltage(void *cookie)
505 {
506 	struct rkpmic_regulator *rr = cookie;
507 	const struct rkpmic_vsel_range *vsel_range = rr->rr_vsel_range;
508 	uint8_t vsel;
509 	uint32_t ret = 0;
510 
511 	vsel = rkpmic_reg_read(rr->rr_sc, rr->rr_reg) & rr->rr_mask;
512 
513 	while (vsel_range->base) {
514 		ret = vsel_range->base;
515 		if (vsel >= vsel_range->vsel_min &&
516 		    vsel <= vsel_range->vsel_max) {
517 			ret += (vsel - vsel_range->vsel_min) *
518 			    vsel_range->delta;
519 			break;
520 		} else
521 			ret += (vsel_range->vsel_max - vsel_range->vsel_min) *
522 			    vsel_range->delta;
523 		vsel_range++;
524 
525 	}
526 
527 	return ret;
528 }
529 
530 int
531 rkpmic_set_voltage(void *cookie, uint32_t voltage)
532 {
533 	struct rkpmic_regulator *rr = cookie;
534 	const struct rkpmic_vsel_range *vsel_range = rr->rr_vsel_range;
535 	uint32_t vmin, vmax, volt;
536 	uint8_t reg, vsel;
537 
538 	while (vsel_range->base) {
539 		vmin = vsel_range->base;
540 		vmax = vmin + (vsel_range->vsel_max - vsel_range->vsel_min) *
541 		    vsel_range->delta;
542 		if (voltage < vmin)
543 			return EINVAL;
544 		if (voltage <= vmax) {
545 			vsel = vsel_range->vsel_min;
546 			volt = vsel_range->base;
547 			while (vsel <= vsel_range->vsel_max) {
548 				if (volt == voltage)
549 					break;
550 				else {
551 					vsel++;
552 					volt += vsel_range->delta;
553 				}
554 			}
555 			if (volt != voltage)
556 				return EINVAL;
557 			break;
558 		}
559 		vsel_range++;
560 	}
561 
562 	if (vsel_range->base == 0)
563 		return EINVAL;
564 
565 	reg = rkpmic_reg_read(rr->rr_sc, rr->rr_reg);
566 	reg &= ~rr->rr_mask;
567 	reg |= vsel;
568 	rkpmic_reg_write(rr->rr_sc, rr->rr_reg, reg);
569 
570 	return 0;
571 }
572 
573 int
574 rkpmic_gettime(struct todr_chip_handle *handle, struct timeval *tv)
575 {
576 	struct rkpmic_softc *sc = handle->cookie;
577 	struct clock_ymdhms dt;
578 	time_t secs;
579 	int error;
580 
581 	error = rkpmic_clock_read(sc, &dt);
582 	if (error)
583 		return error;
584 
585 	if (dt.dt_sec > 59 || dt.dt_min > 59 || dt.dt_hour > 23 ||
586 	    dt.dt_day > 31 || dt.dt_day == 0 ||
587 	    dt.dt_mon > 12 || dt.dt_mon == 0 ||
588 	    dt.dt_year < POSIX_BASE_YEAR)
589 		return EINVAL;
590 
591 	/*
592 	 * The RTC thinks November has 31 days.  Match what Linux does
593 	 * and undo the damage by considering the calendars to be in
594 	 * sync on January 1st 2016.
595 	 */
596 	secs = clock_ymdhms_to_secs(&dt);
597 	secs += (dt.dt_year - 2016 + (dt.dt_mon == 12 ? 1 : 0)) * 86400;
598 
599 	tv->tv_sec = secs;
600 	tv->tv_usec = 0;
601 	return 0;
602 }
603 
604 int
605 rkpmic_settime(struct todr_chip_handle *handle, struct timeval *tv)
606 {
607 	struct rkpmic_softc *sc = handle->cookie;
608 	struct clock_ymdhms dt;
609 	time_t secs;
610 
611 	/*
612 	 * Take care of the November 31st braindamage here as well.
613 	 * Don't try to be clever, just do the conversion in two
614 	 * steps, first taking care of November 31 in previous years,
615 	 * and then taking care of days in December of the current
616 	 * year.  December 1st turns into November 31st!
617 	 */
618 	secs = tv->tv_sec;
619 	clock_secs_to_ymdhms(secs, &dt);
620 	secs -= (dt.dt_year - 2016) * 86400;
621 	clock_secs_to_ymdhms(secs, &dt);
622 	if (dt.dt_mon == 12) {
623 		dt.dt_day--;
624 		if (dt.dt_day == 0) {
625 			dt.dt_mon = 11;
626 			dt.dt_day = 31;
627 		}
628 	}
629 
630 	return rkpmic_clock_write(sc, &dt);
631 }
632 
633 uint8_t
634 rkpmic_reg_read(struct rkpmic_softc *sc, int reg)
635 {
636 	uint8_t cmd = reg;
637 	uint8_t val;
638 
639 	if (sc->sc_read(sc, cmd, &val, sizeof(val))) {
640 		printf("%s: can't read register 0x%02x\n",
641 		    sc->sc_dev.dv_xname, reg);
642 		val = 0xff;
643 	}
644 
645 	return val;
646 }
647 
648 void
649 rkpmic_reg_write(struct rkpmic_softc *sc, int reg, uint8_t val)
650 {
651 	uint8_t cmd = reg;
652 
653 	if (sc->sc_write(sc, cmd, &val, sizeof(val))) {
654 		printf("%s: can't write register 0x%02x\n",
655 		    sc->sc_dev.dv_xname, reg);
656 	}
657 }
658 
659 int
660 rkpmic_clock_read(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
661 {
662 	uint8_t regs[RK80X_NRTC_REGS];
663 	uint8_t cmd = RK80X_SECONDS;
664 	uint8_t status;
665 	int error;
666 
667 	error = sc->sc_read(sc, cmd, regs, RK80X_NRTC_REGS);
668 
669 	if (error) {
670 		printf("%s: can't read RTC\n", sc->sc_dev.dv_xname);
671 		return error;
672 	}
673 
674 	/*
675 	 * Convert the RK80x's register values into something useable.
676 	 */
677 	dt->dt_sec = FROMBCD(regs[0]);
678 	dt->dt_min = FROMBCD(regs[1]);
679 	dt->dt_hour = FROMBCD(regs[2]);
680 	dt->dt_day = FROMBCD(regs[3]);
681 	dt->dt_mon = FROMBCD(regs[4]);
682 	dt->dt_year = FROMBCD(regs[5]) + 2000;
683 
684 	/* Consider the time to be invalid if the POWER_UP bit is set. */
685 	status = rkpmic_reg_read(sc, sc->sc_rtc_status_reg);
686 	if (status & RK80X_RTC_STATUS_POWER_UP)
687 		return EINVAL;
688 
689 	return 0;
690 }
691 
692 int
693 rkpmic_clock_write(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
694 {
695 	uint8_t regs[RK80X_NRTC_REGS];
696 	uint8_t cmd = RK80X_SECONDS;
697 	int error;
698 
699 	/*
700 	 * Convert our time representation into something the RK80x
701 	 * can understand.
702 	 */
703 	regs[0] = TOBCD(dt->dt_sec);
704 	regs[1] = TOBCD(dt->dt_min);
705 	regs[2] = TOBCD(dt->dt_hour);
706 	regs[3] = TOBCD(dt->dt_day);
707 	regs[4] = TOBCD(dt->dt_mon);
708 	regs[5] = TOBCD(dt->dt_year - 2000);
709 	regs[6] = TOBCD(dt->dt_wday);
710 
711 	/* Stop RTC such that we can write to it. */
712 	rkpmic_reg_write(sc, sc->sc_rtc_ctrl_reg, RK80X_RTC_CTRL_STOP_RTC);
713 
714 	error = sc->sc_write(sc, cmd, regs, RK80X_NRTC_REGS);
715 
716 	/* Restart RTC. */
717 	rkpmic_reg_write(sc, sc->sc_rtc_ctrl_reg, 0);
718 
719 	if (error) {
720 		printf("%s: can't write RTC\n", sc->sc_dev.dv_xname);
721 		return error;
722 	}
723 
724 	/* Clear POWER_UP bit to indicate the time is now valid. */
725 	rkpmic_reg_write(sc, sc->sc_rtc_status_reg, RK80X_RTC_STATUS_POWER_UP);
726 
727 	return 0;
728 }
729 
730 int
731 rkpmic_i2c_read(struct rkpmic_softc *sc, uint8_t cmd, void *buf, size_t buflen)
732 {
733 	int error;
734 
735 	iic_acquire_bus(sc->sc_i2c_tag, I2C_F_POLL);
736 	error = iic_exec(sc->sc_i2c_tag, I2C_OP_READ_WITH_STOP,
737 	    sc->sc_i2c_addr, &cmd, sizeof(cmd), buf, buflen, I2C_F_POLL);
738 	iic_release_bus(sc->sc_i2c_tag, I2C_F_POLL);
739 
740 	return error;
741 }
742 
743 int
744 rkpmic_i2c_write(struct rkpmic_softc *sc, uint8_t cmd, void *buf, size_t buflen)
745 {
746 	int error;
747 
748 	iic_acquire_bus(sc->sc_i2c_tag, I2C_F_POLL);
749 	error = iic_exec(sc->sc_i2c_tag, I2C_OP_WRITE_WITH_STOP,
750 	    sc->sc_i2c_addr, &cmd, sizeof(cmd), buf, buflen, I2C_F_POLL);
751 	iic_release_bus(sc->sc_i2c_tag, I2C_F_POLL);
752 
753 	return error;
754 }
755 
756 int
757 rkpmic_spi_read(struct rkpmic_softc *sc, uint8_t cmd, void *buf, size_t buflen)
758 {
759 	uint8_t cmdbuf[3];
760 	int error;
761 
762 	cmdbuf[0] = RKSPI_CMD_READ | (buflen - 1);
763 	cmdbuf[1] = cmd;  /* 16-bit addr low */
764 	cmdbuf[2] = 0x00; /* 16-bit addr high */
765 
766 	spi_acquire_bus(sc->sc_spi_tag, 0);
767 	spi_config(sc->sc_spi_tag, &sc->sc_spi_conf);
768 	error = spi_transfer(sc->sc_spi_tag, cmdbuf, NULL, sizeof(cmdbuf),
769 	    SPI_KEEP_CS);
770 	if (!error)
771 		error = spi_read(sc->sc_spi_tag, buf, buflen);
772 	spi_release_bus(sc->sc_spi_tag, 0);
773 
774 	return error;
775 }
776 
777 int
778 rkpmic_spi_write(struct rkpmic_softc *sc, uint8_t cmd, void *buf, size_t buflen)
779 {
780 	uint8_t cmdbuf[3];
781 	int error;
782 
783 	cmdbuf[0] = RKSPI_CMD_WRITE | (buflen - 1);
784 	cmdbuf[1] = cmd;  /* 16-bit addr low */
785 	cmdbuf[2] = 0x00; /* 16-bit addr high */
786 
787 	spi_acquire_bus(sc->sc_spi_tag, 0);
788 	spi_config(sc->sc_spi_tag, &sc->sc_spi_conf);
789 	error = spi_transfer(sc->sc_spi_tag, cmdbuf, NULL, sizeof(cmdbuf),
790 	    SPI_KEEP_CS);
791 	if (!error)
792 		error = spi_write(sc->sc_spi_tag, buf, buflen);
793 	spi_release_bus(sc->sc_spi_tag, 0);
794 
795 	return error;
796 }
797