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