xref: /openbsd-src/sys/dev/fdt/rkpmic.c (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 /*	$OpenBSD: rkpmic.c,v 1.9 2021/10/24 17:52:27 mpi 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 
29 #include <dev/clock_subr.h>
30 
31 extern todr_chip_handle_t todr_handle;
32 
33 #define RK80X_SECONDS		0x00
34 #define RK80X_MINUTES		0x01
35 #define RK80X_HOURS		0x02
36 #define RK80X_DAYS		0x03
37 #define RK80X_MONTHS		0x04
38 #define RK80X_YEARS		0x05
39 #define RK80X_WEEKS		0x06
40 #define RK80X_NRTC_REGS	7
41 
42 #define RK805_RTC_CTRL		0x10
43 #define RK808_RTC_CTRL		0x10
44 #define RK809_RTC_CTRL		0x0d
45 #define  RK80X_RTC_CTRL_STOP_RTC	0x01
46 
47 #define RK805_RTC_STATUS	0x11
48 #define RK808_RTC_STATUS	0x11
49 #define RK809_RTC_STATUS	0x0e
50 #define  RK80X_RTC_STATUS_POWER_UP	0x80
51 
52 struct rkpmic_vsel_range {
53 	uint32_t base, delta;
54 	uint8_t vsel_min, vsel_max;
55 };
56 
57 struct rkpmic_regdata {
58 	const char *name;
59 	uint8_t reg, mask;
60 	struct rkpmic_vsel_range *vsel_range;
61 };
62 
63 /*
64  * Used by RK805 for BUCK1, BUCK2
65  *  0-59:	0.7125V-1.45V, step=12.5mV
66  *  60-62:	1.8V-2.2V, step=200mV
67  *  63:		2.3V
68  */
69 struct rkpmic_vsel_range rk805_vsel_range1[] = {
70 	{ 712500, 12500, 0, 59 },
71 	{ 1800000, 200000, 60, 62 },
72 	{ 2300000, 0, 63, 63 },
73 	{}
74 };
75 
76 /*
77  * Used by RK805 for BUCK4
78  *  0-27:	0.8V-3.5V, step=100mV
79  */
80 struct rkpmic_vsel_range rk805_vsel_range2[] = {
81 	{ 800000, 100000, 0, 27 },
82 	{}
83 };
84 
85 /*
86  * Used by RK805 for LDO1-3
87  *  0-26:	0.8V-3.4V, step=100mV
88  */
89 struct rkpmic_vsel_range rk805_vsel_range3[] = {
90 	{ 800000, 100000, 0, 26 },
91 	{}
92 };
93 
94 struct rkpmic_regdata rk805_regdata[] = {
95 	{ "DCDC_REG1", 0x2f, 0x3f, rk805_vsel_range1 },
96 	{ "DCDC_REG2", 0x33, 0x3f, rk805_vsel_range1 },
97 	{ "DCDC_REG4", 0x38, 0x1f, rk805_vsel_range2 },
98 	{ "LDO_REG1", 0x3b, 0x1f, rk805_vsel_range3 },
99 	{ "LDO_REG2", 0x3d, 0x1f, rk805_vsel_range3 },
100 	{ "LDO_REG3", 0x3f, 0x1f, rk805_vsel_range3 },
101 	{ }
102 };
103 
104 /*
105  * Used by RK808 for BUCK1 & BUCK2
106  *  0-63:	0.7125V-1.5V, step=12.5mV
107  */
108 struct rkpmic_vsel_range rk808_vsel_range1[] = {
109 	{ 712500, 12500, 0, 63 },
110 	{}
111 };
112 
113 /*
114  * Used by RK808 for BUCK4
115  *  0-15:	1.8V-3.3V,step=100mV
116  */
117 struct rkpmic_vsel_range rk808_vsel_range2[] = {
118 	{ 1800000, 100000, 0, 15 },
119 	{}
120 };
121 
122 /*
123  * Used by RK808 for LDO1-2, 4-5, 8
124  *  0-16:	1.8V-3.4V, step=100mV
125  */
126 struct rkpmic_vsel_range rk808_vsel_range3[] = {
127 	{ 1800000, 100000, 0, 16 },
128 	{}
129 };
130 
131 /*
132  * Used by RK808 for LDO3
133  *   0-12:	0.8V~2.0V, step=100mV
134  *   13:	2.2V
135  *   15:	2.5V
136  */
137 struct rkpmic_vsel_range rk808_vsel_range4[] = {
138 	{ 800000, 100000, 0, 12 },
139 	{ 2200000, 0, 13, 13 },
140 	{ 2500000, 0, 15, 15 },
141 	{}
142 };
143 
144 /*
145  * Used by RK808 for LDO6-7
146  *  0-17:	0.8V-2.5V,step=100mV
147  */
148 struct rkpmic_vsel_range rk808_vsel_range5[] = {
149 	{ 800000, 100000, 0, 17 },
150 	{}
151 };
152 
153 struct rkpmic_regdata rk808_regdata[] = {
154 	{ "DCDC_REG1", 0x2f, 0x3f, rk808_vsel_range1 },
155 	{ "DCDC_REG2", 0x33, 0x3f, rk808_vsel_range1 },
156 	{ "DCDC_REG4", 0x38, 0x0f, rk808_vsel_range2 },
157 	{ "LDO_REG1", 0x3b, 0x1f, rk808_vsel_range3 },
158 	{ "LDO_REG2", 0x3d, 0x1f, rk808_vsel_range3 },
159 	{ "LDO_REG3", 0x3f, 0x0f, rk808_vsel_range4 },
160 	{ "LDO_REG4", 0x41, 0x1f, rk808_vsel_range3 },
161 	{ "LDO_REG5", 0x43, 0x1f, rk808_vsel_range3 },
162 	{ "LDO_REG6", 0x45, 0x1f, rk808_vsel_range5 },
163 	{ "LDO_REG7", 0x47, 0x1f, rk808_vsel_range5 },
164 	{ "LDO_REG8", 0x49, 0x1f, rk808_vsel_range3 },
165 	{ }
166 };
167 
168 /*
169  * Used by RK809 for BUCK1-3
170  *  0-80:	0.5V-1.5V,step=12.5mV
171  *  81-89:	1.6V-2.4V,step=100mV
172  */
173 struct rkpmic_vsel_range rk809_vsel_range1[] = {
174 	{ 500000, 12500, 0, 80 },
175 	{ 1600000, 100000, 81, 89 },
176 	{}
177 };
178 
179 /*
180  * Used by RK809 for BUCK4
181  *  0-80:	0.5V-1.5V,step=12.5mV
182  *  81-99:	1.6V-3.4V,step=100mV
183  */
184 struct rkpmic_vsel_range rk809_vsel_range2[] = {
185 	{ 500000, 12500, 0, 80 },
186 	{ 1600000, 100000, 81, 99 },
187 	{}
188 };
189 
190 /*
191  * Used by RK809 for BUCK5
192  *  0:		1.5V
193  *  1-3:	1.8V-2.2V,step=200mV
194  *  4-5:	2.8V-3.0V,step=200mV
195  *  6-7:	3.3V-3.6V,step=300mV
196  */
197 struct rkpmic_vsel_range rk809_vsel_range3[] = {
198 	{ 1500000, 0, 0, 0 },
199 	{ 1800000, 200000, 1, 3 },
200 	{ 2800000, 200000, 4, 5 },
201 	{ 3300000, 300000, 6, 7 },
202 	{}
203 };
204 
205 /*
206  * Used by RK809 for LDO1-7
207  *  0-112: 0.6V-3.4V,step=25mV
208  */
209 struct rkpmic_vsel_range rk809_vsel_range4[] = {
210 	{ 600000, 25000, 0, 112 },
211 	{}
212 };
213 
214 struct rkpmic_regdata rk809_regdata[] = {
215 	{ "DCDC_REG1", 0xbb, 0x7f, rk809_vsel_range1 },
216 	{ "DCDC_REG2", 0xbe, 0x7f, rk809_vsel_range1 },
217 	{ "DCDC_REG3", 0xc1, 0x7f, rk809_vsel_range1 },
218 	{ "DCDC_REG4", 0xc4, 0x7f, rk809_vsel_range2 },
219 	{ "DCDC_REG5", 0xde, 0x0f, rk809_vsel_range3},
220 	{ "LDO_REG1", 0xcc, 0x7f, rk809_vsel_range4 },
221 	{ "LDO_REG2", 0xce, 0x7f, rk809_vsel_range4 },
222 	{ "LDO_REG3", 0xd0, 0x7f, rk809_vsel_range4 },
223 	{ "LDO_REG4", 0xd2, 0x7f, rk809_vsel_range4 },
224 	{ "LDO_REG5", 0xd4, 0x7f, rk809_vsel_range4 },
225 	{ "LDO_REG6", 0xd6, 0x7f, rk809_vsel_range4 },
226 	{ "LDO_REG7", 0xd8, 0x7f, rk809_vsel_range4 },
227 	{ "LDO_REG8", 0xda, 0x7f, rk809_vsel_range4 },
228 	{ "LDO_REG9", 0xdc, 0x7f, rk809_vsel_range4 },
229 	{ }
230 };
231 
232 struct rkpmic_softc {
233 	struct device sc_dev;
234 	i2c_tag_t sc_tag;
235 	i2c_addr_t sc_addr;
236 
237 	int sc_rtc_ctrl_reg, sc_rtc_status_reg;
238 	struct todr_chip_handle sc_todr;
239 	struct rkpmic_regdata *sc_regdata;
240 };
241 
242 int	rkpmic_match(struct device *, void *, void *);
243 void	rkpmic_attach(struct device *, struct device *, void *);
244 
245 const struct cfattach rkpmic_ca = {
246 	sizeof(struct rkpmic_softc), rkpmic_match, rkpmic_attach
247 };
248 
249 struct cfdriver rkpmic_cd = {
250 	NULL, "rkpmic", DV_DULL
251 };
252 
253 void	rkpmic_attach_regulator(struct rkpmic_softc *, int);
254 uint8_t	rkpmic_reg_read(struct rkpmic_softc *, int);
255 void	rkpmic_reg_write(struct rkpmic_softc *, int, uint8_t);
256 int	rkpmic_clock_read(struct rkpmic_softc *, struct clock_ymdhms *);
257 int	rkpmic_clock_write(struct rkpmic_softc *, struct clock_ymdhms *);
258 int	rkpmic_gettime(struct todr_chip_handle *, struct timeval *);
259 int	rkpmic_settime(struct todr_chip_handle *, struct timeval *);
260 
261 int
262 rkpmic_match(struct device *parent, void *match, void *aux)
263 {
264 	struct i2c_attach_args *ia = aux;
265 
266 	return (strcmp(ia->ia_name, "rockchip,rk805") == 0 ||
267 	    strcmp(ia->ia_name, "rockchip,rk808") == 0 ||
268 	    strcmp(ia->ia_name, "rockchip,rk809") == 0);
269 }
270 
271 void
272 rkpmic_attach(struct device *parent, struct device *self, void *aux)
273 {
274 	struct rkpmic_softc *sc = (struct rkpmic_softc *)self;
275 	struct i2c_attach_args *ia = aux;
276 	int node = *(int *)ia->ia_cookie;
277 	const char *chip;
278 
279 	sc->sc_tag = ia->ia_tag;
280 	sc->sc_addr = ia->ia_addr;
281 
282 	sc->sc_todr.cookie = sc;
283 	sc->sc_todr.todr_gettime = rkpmic_gettime;
284 	sc->sc_todr.todr_settime = rkpmic_settime;
285 	if (todr_handle == NULL)
286 		todr_handle = &sc->sc_todr;
287 
288 	if (OF_is_compatible(node, "rockchip,rk805")) {
289 		chip = "RK805";
290 		sc->sc_rtc_ctrl_reg = RK805_RTC_CTRL;
291 		sc->sc_rtc_status_reg = RK805_RTC_STATUS;
292 		sc->sc_regdata = rk805_regdata;
293 	} else if (OF_is_compatible(node, "rockchip,rk808")) {
294 		chip = "RK808";
295 		sc->sc_rtc_ctrl_reg = RK808_RTC_CTRL;
296 		sc->sc_rtc_status_reg = RK808_RTC_STATUS;
297 		sc->sc_regdata = rk808_regdata;
298 	} else {
299 		chip = "RK809";
300 		sc->sc_rtc_ctrl_reg = RK809_RTC_CTRL;
301 		sc->sc_rtc_status_reg = RK809_RTC_STATUS;
302 		sc->sc_regdata = rk809_regdata;
303 	}
304 	printf(": %s\n", chip);
305 
306 	node = OF_getnodebyname(node, "regulators");
307 	if (node == 0)
308 		return;
309 	for (node = OF_child(node); node; node = OF_peer(node))
310 		rkpmic_attach_regulator(sc, node);
311 }
312 
313 struct rkpmic_regulator {
314 	struct rkpmic_softc *rr_sc;
315 
316 	uint8_t rr_reg, rr_mask;
317 	struct rkpmic_vsel_range *rr_vsel_range;
318 
319 	struct regulator_device rr_rd;
320 };
321 
322 uint32_t rkpmic_get_voltage(void *);
323 int	rkpmic_set_voltage(void *, uint32_t);
324 
325 void
326 rkpmic_attach_regulator(struct rkpmic_softc *sc, int node)
327 {
328 	struct rkpmic_regulator *rr;
329 	char name[32];
330 	int i;
331 
332 	name[0] = 0;
333 	OF_getprop(node, "name", name, sizeof(name));
334 	name[sizeof(name) - 1] = 0;
335 	for (i = 0; sc->sc_regdata[i].name; i++) {
336 		if (strcmp(sc->sc_regdata[i].name, name) == 0)
337 			break;
338 	}
339 	if (sc->sc_regdata[i].name == NULL)
340 		return;
341 
342 	rr = malloc(sizeof(*rr), M_DEVBUF, M_WAITOK | M_ZERO);
343 	rr->rr_sc = sc;
344 
345 	rr->rr_reg = sc->sc_regdata[i].reg;
346 	rr->rr_mask = sc->sc_regdata[i].mask;
347 	rr->rr_vsel_range = sc->sc_regdata[i].vsel_range;
348 
349 	rr->rr_rd.rd_node = node;
350 	rr->rr_rd.rd_cookie = rr;
351 	rr->rr_rd.rd_get_voltage = rkpmic_get_voltage;
352 	rr->rr_rd.rd_set_voltage = rkpmic_set_voltage;
353 	regulator_register(&rr->rr_rd);
354 }
355 
356 uint32_t
357 rkpmic_get_voltage(void *cookie)
358 {
359 	struct rkpmic_regulator *rr = cookie;
360 	struct rkpmic_vsel_range *vsel_range = rr->rr_vsel_range;
361 	uint8_t vsel;
362 	uint32_t ret = 0;
363 
364 	vsel = rkpmic_reg_read(rr->rr_sc, rr->rr_reg) & rr->rr_mask;
365 
366 	while (vsel_range->base) {
367 		ret = vsel_range->base;
368 		if (vsel >= vsel_range->vsel_min &&
369 		    vsel <= vsel_range->vsel_max) {
370 			ret += (vsel - vsel_range->vsel_min) *
371 			    vsel_range->delta;
372 			break;
373 		} else
374 			ret += (vsel_range->vsel_max - vsel_range->vsel_min) *
375 			    vsel_range->delta;
376 		vsel_range++;
377 
378 	}
379 
380 	return ret;
381 }
382 
383 int
384 rkpmic_set_voltage(void *cookie, uint32_t voltage)
385 {
386 	struct rkpmic_regulator *rr = cookie;
387 	struct rkpmic_vsel_range *vsel_range = rr->rr_vsel_range;
388 	uint32_t vmin, vmax, volt;
389 	uint8_t reg, vsel;
390 
391 	while (vsel_range->base) {
392 		vmin = vsel_range->base;
393 		vmax = vmin + (vsel_range->vsel_max - vsel_range->vsel_min) *
394 		    vsel_range->delta;
395 		if (voltage < vmin)
396 			return EINVAL;
397 		if (voltage <= vmax) {
398 			vsel = vsel_range->vsel_min;
399 			volt = vsel_range->base;
400 			while (vsel <= vsel_range->vsel_max) {
401 				if (volt == voltage)
402 					break;
403 				else {
404 					vsel++;
405 					volt += vsel_range->delta;
406 				}
407 			}
408 			if (volt != voltage)
409 				return EINVAL;
410 			break;
411 		}
412 		vsel_range++;
413 	}
414 
415 	if (vsel_range->base == 0)
416 		return EINVAL;
417 
418 	reg = rkpmic_reg_read(rr->rr_sc, rr->rr_reg);
419 	reg &= ~rr->rr_mask;
420 	reg |= vsel;
421 	rkpmic_reg_write(rr->rr_sc, rr->rr_reg, reg);
422 
423 	return 0;
424 }
425 
426 int
427 rkpmic_gettime(struct todr_chip_handle *handle, struct timeval *tv)
428 {
429 	struct rkpmic_softc *sc = handle->cookie;
430 	struct clock_ymdhms dt;
431 	time_t secs;
432 	int error;
433 
434 	error = rkpmic_clock_read(sc, &dt);
435 	if (error)
436 		return error;
437 
438 	if (dt.dt_sec > 59 || dt.dt_min > 59 || dt.dt_hour > 23 ||
439 	    dt.dt_day > 31 || dt.dt_day == 0 ||
440 	    dt.dt_mon > 12 || dt.dt_mon == 0 ||
441 	    dt.dt_year < POSIX_BASE_YEAR)
442 		return EINVAL;
443 
444 	/*
445 	 * The RTC thinks November has 31 days.  Match what Linux does
446 	 * and undo the damage by considering the calenders to be in
447 	 * sync on January 1st 2016.
448 	 */
449 	secs = clock_ymdhms_to_secs(&dt);
450 	secs += (dt.dt_year - 2016 + (dt.dt_mon == 12 ? 1 : 0)) * 86400;
451 
452 	tv->tv_sec = secs;
453 	tv->tv_usec = 0;
454 	return 0;
455 }
456 
457 int
458 rkpmic_settime(struct todr_chip_handle *handle, struct timeval *tv)
459 {
460 	struct rkpmic_softc *sc = handle->cookie;
461 	struct clock_ymdhms dt;
462 	time_t secs;
463 
464 	/*
465 	 * Take care of the November 31st braindamage here as well.
466 	 * Don't try to be clever, just do the conversion in two
467 	 * steps, first taking care of November 31 in previous years,
468 	 * and then taking care of days in December of the current
469 	 * year.  Decmber 1st turns into November 31st!
470 	 */
471 	secs = tv->tv_sec;
472 	clock_secs_to_ymdhms(secs, &dt);
473 	secs -= (dt.dt_year - 2016) * 86400;
474 	clock_secs_to_ymdhms(secs, &dt);
475 	if (dt.dt_mon == 12) {
476 		dt.dt_day--;
477 		if (dt.dt_day == 0) {
478 			dt.dt_mon = 11;
479 			dt.dt_day = 31;
480 		}
481 	}
482 
483 	return rkpmic_clock_write(sc, &dt);
484 }
485 
486 uint8_t
487 rkpmic_reg_read(struct rkpmic_softc *sc, int reg)
488 {
489 	uint8_t cmd = reg;
490 	uint8_t val;
491 	int error;
492 
493 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
494 	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
495 	    &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL);
496 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
497 
498 	if (error) {
499 		printf("%s: can't read register 0x%02x\n",
500 		    sc->sc_dev.dv_xname, reg);
501 		val = 0xff;
502 	}
503 
504 	return val;
505 }
506 
507 void
508 rkpmic_reg_write(struct rkpmic_softc *sc, int reg, uint8_t val)
509 {
510 	uint8_t cmd = reg;
511 	int error;
512 
513 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
514 	error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
515 	    &cmd, sizeof cmd, &val, sizeof val, I2C_F_POLL);
516 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
517 
518 	if (error) {
519 		printf("%s: can't write register 0x%02x\n",
520 		    sc->sc_dev.dv_xname, reg);
521 	}
522 }
523 
524 int
525 rkpmic_clock_read(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
526 {
527 	uint8_t regs[RK80X_NRTC_REGS];
528 	uint8_t cmd = RK80X_SECONDS;
529 	uint8_t status;
530 	int error;
531 
532 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
533 	error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
534 	    &cmd, sizeof(cmd), regs, RK80X_NRTC_REGS, I2C_F_POLL);
535 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
536 
537 	if (error) {
538 		printf("%s: can't read RTC\n", sc->sc_dev.dv_xname);
539 		return error;
540 	}
541 
542 	/*
543 	 * Convert the RK80x's register values into something useable.
544 	 */
545 	dt->dt_sec = FROMBCD(regs[0]);
546 	dt->dt_min = FROMBCD(regs[1]);
547 	dt->dt_hour = FROMBCD(regs[2]);
548 	dt->dt_day = FROMBCD(regs[3]);
549 	dt->dt_mon = FROMBCD(regs[4]);
550 	dt->dt_year = FROMBCD(regs[5]) + 2000;
551 
552 	/* Consider the time to be invalid if the POWER_UP bit is set. */
553 	status = rkpmic_reg_read(sc, sc->sc_rtc_status_reg);
554 	if (status & RK80X_RTC_STATUS_POWER_UP)
555 		return EINVAL;
556 
557 	return 0;
558 }
559 
560 int
561 rkpmic_clock_write(struct rkpmic_softc *sc, struct clock_ymdhms *dt)
562 {
563 	uint8_t regs[RK80X_NRTC_REGS];
564 	uint8_t cmd = RK80X_SECONDS;
565 	int error;
566 
567 	/*
568 	 * Convert our time representation into something the RK80x
569 	 * can understand.
570 	 */
571 	regs[0] = TOBCD(dt->dt_sec);
572 	regs[1] = TOBCD(dt->dt_min);
573 	regs[2] = TOBCD(dt->dt_hour);
574 	regs[3] = TOBCD(dt->dt_day);
575 	regs[4] = TOBCD(dt->dt_mon);
576 	regs[5] = TOBCD(dt->dt_year - 2000);
577 	regs[6] = TOBCD(dt->dt_wday);
578 
579 	/* Stop RTC such that we can write to it. */
580 	rkpmic_reg_write(sc, sc->sc_rtc_ctrl_reg, RK80X_RTC_CTRL_STOP_RTC);
581 
582 	iic_acquire_bus(sc->sc_tag, I2C_F_POLL);
583 	error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
584 	    &cmd, sizeof(cmd), regs, RK80X_NRTC_REGS, I2C_F_POLL);
585 	iic_release_bus(sc->sc_tag, I2C_F_POLL);
586 
587 	/* Restart RTC. */
588 	rkpmic_reg_write(sc, sc->sc_rtc_ctrl_reg, 0);
589 
590 	if (error) {
591 		printf("%s: can't write RTC\n", sc->sc_dev.dv_xname);
592 		return error;
593 	}
594 
595 	/* Clear POWER_UP bit to indicate the time is now valid. */
596 	rkpmic_reg_write(sc, sc->sc_rtc_status_reg, RK80X_RTC_STATUS_POWER_UP);
597 
598 	return 0;
599 }
600