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