1 /* $NetBSD: as3722.c,v 1.22 2021/01/27 02:29:48 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "opt_fdt.h" 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: as3722.c,v 1.22 2021/01/27 02:29:48 thorpej Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/device.h> 38 #include <sys/conf.h> 39 #include <sys/bus.h> 40 #include <sys/kmem.h> 41 #include <sys/wdog.h> 42 43 #include <dev/clock_subr.h> 44 45 #include <dev/sysmon/sysmonvar.h> 46 47 #include <dev/i2c/i2cvar.h> 48 #include <dev/i2c/as3722.h> 49 50 #ifdef FDT 51 #include <dev/fdt/fdtvar.h> 52 #endif 53 54 #define AS3722_I2C_ADDR 0x40 55 56 #define AS3722_START_YEAR 2000 57 58 #define AS3722_SD0_VOLTAGE_REG 0x00 59 60 #define AS3722_SD4_VOLTAGE_REG 0x04 61 62 #define AS3722_GPIO0_CTRL_REG 0x08 63 #define AS3722_GPIO0_CTRL_INVERT __BIT(7) 64 #define AS3722_GPIO0_CTRL_IOSF __BITS(6,3) 65 #define AS3722_GPIO0_CTRL_IOSF_GPIO 0 66 #define AS3722_GPIO0_CTRL_IOSF_WATCHDOG 9 67 #define AS3722_GPIO0_CTRL_MODE __BITS(2,0) 68 #define AS3722_GPIO0_CTRL_MODE_PULLDOWN 5 69 70 #define AS3722_LDO6_VOLTAGE_REG 0x16 71 72 #define AS3722_RESET_CTRL_REG 0x36 73 #define AS3722_RESET_CTRL_POWER_OFF __BIT(1) 74 #define AS3722_RESET_CTRL_FORCE_RESET __BIT(0) 75 76 #define AS3722_WATCHDOG_CTRL_REG 0x38 77 #define AS3722_WATCHDOG_CTRL_MODE __BITS(2,1) 78 #define AS3722_WATCHDOG_CTRL_ON __BIT(0) 79 80 #define AS3722_WATCHDOG_TIMER_REG 0x46 81 #define AS3722_WATCHDOG_TIMER_TIMER __BITS(6,0) 82 83 #define AS3722_WATCHDOG_SIGNAL_REG 0x48 84 #define AS3722_WATCHDOG_SIGNAL_PWM_DIV __BITS(7,6) 85 #define AS3722_WATCHDOG_SIGNAL_SW_SIG __BIT(0) 86 87 #define AS3722_SDCONTROL_REG 0x4d 88 #define AS3722_SDCONTROL_SD4_ENABLE __BIT(4) 89 90 #define AS3722_LDOCONTROL0_REG 0x4e 91 92 #define AS3722_RTC_CONTROL_REG 0x60 93 #define AS3722_RTC_CONTROL_RTC_ON __BIT(2) 94 95 #define AS3722_RTC_SECOND_REG 0x61 96 #define AS3722_RTC_MINUTE_REG 0x62 97 #define AS3722_RTC_HOUR_REG 0x63 98 #define AS3722_RTC_DAY_REG 0x64 99 #define AS3722_RTC_MONTH_REG 0x65 100 #define AS3722_RTC_YEAR_REG 0x66 101 #define AS3722_RTC_ACCESS_REG 0x6f 102 103 #define AS3722_ASIC_ID1_REG 0x90 104 #define AS3722_ASIC_ID2_REG 0x91 105 106 #define AS3722_FUSE7_REG 0xa7 107 #define AS3722_FUSE7_SD0_V_MINUS_200MV __BIT(4) 108 109 struct as3722_softc { 110 device_t sc_dev; 111 i2c_tag_t sc_i2c; 112 i2c_addr_t sc_addr; 113 int sc_phandle; 114 int sc_flags; 115 #define AS3722_FLAG_SD0_V_MINUS_200MV 0x01 116 117 struct sysmon_wdog sc_smw; 118 struct todr_chip_handle sc_todr; 119 }; 120 121 #ifdef FDT 122 static int as3722reg_set_voltage_sd0(device_t, u_int, u_int); 123 static int as3722reg_get_voltage_sd0(device_t, u_int *); 124 static int as3722reg_set_voltage_sd4(device_t, u_int, u_int); 125 static int as3722reg_get_voltage_sd4(device_t, u_int *); 126 static int as3722reg_set_voltage_ldo(device_t, u_int, u_int); 127 static int as3722reg_get_voltage_ldo(device_t, u_int *); 128 129 static const struct as3722regdef { 130 const char *name; 131 u_int vsel_reg; 132 u_int vsel_mask; 133 u_int enable_reg; 134 u_int enable_mask; 135 int (*set)(device_t, u_int, u_int); 136 int (*get)(device_t, u_int *); 137 } as3722regdefs[] = { 138 { .name = "sd0", 139 .vsel_reg = AS3722_SD0_VOLTAGE_REG, 140 .vsel_mask = 0x7f, 141 .set = as3722reg_set_voltage_sd0, 142 .get = as3722reg_get_voltage_sd0 }, 143 { .name = "sd4", 144 .vsel_reg = AS3722_SD4_VOLTAGE_REG, 145 .vsel_mask = 0x7f, 146 .enable_reg = AS3722_SDCONTROL_REG, 147 .enable_mask = AS3722_SDCONTROL_SD4_ENABLE, 148 .set = as3722reg_set_voltage_sd4, 149 .get = as3722reg_get_voltage_sd4 }, 150 { .name = "ldo6", 151 .vsel_reg = AS3722_LDO6_VOLTAGE_REG, 152 .vsel_mask = 0x7f, 153 .enable_reg = AS3722_LDOCONTROL0_REG, 154 .enable_mask = 0x40, 155 .set = as3722reg_set_voltage_ldo, 156 .get = as3722reg_get_voltage_ldo }, 157 }; 158 159 struct as3722reg_softc { 160 device_t sc_dev; 161 int sc_phandle; 162 const struct as3722regdef *sc_regdef; 163 }; 164 165 struct as3722reg_attach_args { 166 const struct as3722regdef *reg_def; 167 int reg_phandle; 168 }; 169 #endif 170 171 #define AS3722_WATCHDOG_DEFAULT_PERIOD 10 172 173 static int as3722_match(device_t, cfdata_t, void *); 174 static void as3722_attach(device_t, device_t, void *); 175 176 static void as3722_wdt_attach(struct as3722_softc *); 177 static int as3722_wdt_setmode(struct sysmon_wdog *); 178 static int as3722_wdt_tickle(struct sysmon_wdog *); 179 180 static void as3722_rtc_attach(struct as3722_softc *); 181 static int as3722_rtc_gettime(todr_chip_handle_t, struct clock_ymdhms *); 182 static int as3722_rtc_settime(todr_chip_handle_t, struct clock_ymdhms *); 183 184 #ifdef FDT 185 static void as3722_regulator_attach(struct as3722_softc *); 186 static int as3722reg_match(device_t, cfdata_t, void *); 187 static void as3722reg_attach(device_t, device_t, void *); 188 189 static int as3722reg_acquire(device_t); 190 static void as3722reg_release(device_t); 191 static int as3722reg_enable(device_t, bool); 192 static int as3722reg_set_voltage(device_t, u_int, u_int); 193 static int as3722reg_get_voltage(device_t, u_int *); 194 195 static struct fdtbus_regulator_controller_func as3722reg_funcs = { 196 .acquire = as3722reg_acquire, 197 .release = as3722reg_release, 198 .enable = as3722reg_enable, 199 .set_voltage = as3722reg_set_voltage, 200 .get_voltage = as3722reg_get_voltage, 201 }; 202 203 static void as3722_power_reset(device_t); 204 static void as3722_power_poweroff(device_t); 205 206 static struct fdtbus_power_controller_func as3722power_funcs = { 207 .reset = as3722_power_reset, 208 .poweroff = as3722_power_poweroff, 209 }; 210 #endif 211 212 static int as3722_read(struct as3722_softc *, uint8_t, uint8_t *, int); 213 static int as3722_write(struct as3722_softc *, uint8_t, uint8_t, int); 214 static int as3722_set_clear(struct as3722_softc *, uint8_t, uint8_t, 215 uint8_t, int); 216 217 CFATTACH_DECL_NEW(as3722pmic, sizeof(struct as3722_softc), 218 as3722_match, as3722_attach, NULL, NULL); 219 220 #ifdef FDT 221 CFATTACH_DECL_NEW(as3722reg, sizeof(struct as3722reg_softc), 222 as3722reg_match, as3722reg_attach, NULL, NULL); 223 #endif 224 225 static const struct device_compatible_entry compat_data[] = { 226 { .compat = "ams,as3722" }, 227 DEVICE_COMPAT_EOL 228 }; 229 230 static int 231 as3722_match(device_t parent, cfdata_t match, void *aux) 232 { 233 struct i2c_attach_args *ia = aux; 234 uint8_t reg, id1; 235 int error, match_result; 236 237 if (iic_use_direct_match(ia, match, compat_data, &match_result)) 238 return match_result; 239 240 if (ia->ia_addr != AS3722_I2C_ADDR) 241 return 0; 242 243 iic_acquire_bus(ia->ia_tag, 0); 244 reg = AS3722_ASIC_ID1_REG; 245 error = iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr, 246 ®, 1, &id1, 1, 0); 247 iic_release_bus(ia->ia_tag, 0); 248 249 if (error == 0 && id1 == 0x0c) 250 return I2C_MATCH_ADDRESS_AND_PROBE; 251 252 return 0; 253 } 254 255 static void 256 as3722_attach(device_t parent, device_t self, void *aux) 257 { 258 struct as3722_softc * const sc = device_private(self); 259 struct i2c_attach_args *ia = aux; 260 261 sc->sc_dev = self; 262 sc->sc_i2c = ia->ia_tag; 263 sc->sc_addr = ia->ia_addr; 264 sc->sc_phandle = ia->ia_cookie; 265 266 aprint_naive("\n"); 267 aprint_normal(": AMS AS3722\n"); 268 269 as3722_wdt_attach(sc); 270 as3722_rtc_attach(sc); 271 #ifdef FDT 272 as3722_regulator_attach(sc); 273 274 fdtbus_register_power_controller(self, sc->sc_phandle, 275 &as3722power_funcs); 276 #endif 277 } 278 279 static void 280 as3722_wdt_attach(struct as3722_softc *sc) 281 { 282 int error; 283 284 iic_acquire_bus(sc->sc_i2c, 0); 285 error = as3722_write(sc, AS3722_GPIO0_CTRL_REG, 286 __SHIFTIN(AS3722_GPIO0_CTRL_IOSF_GPIO, 287 AS3722_GPIO0_CTRL_IOSF) | 288 __SHIFTIN(AS3722_GPIO0_CTRL_MODE_PULLDOWN, 289 AS3722_GPIO0_CTRL_MODE), 290 0); 291 error += as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG, 292 __SHIFTIN(1, AS3722_WATCHDOG_CTRL_MODE), 0, 0); 293 iic_release_bus(sc->sc_i2c, 0); 294 295 if (error) { 296 aprint_error_dev(sc->sc_dev, "couldn't setup watchdog\n"); 297 return; 298 } 299 300 sc->sc_smw.smw_name = device_xname(sc->sc_dev); 301 sc->sc_smw.smw_cookie = sc; 302 sc->sc_smw.smw_setmode = as3722_wdt_setmode; 303 sc->sc_smw.smw_tickle = as3722_wdt_tickle; 304 sc->sc_smw.smw_period = AS3722_WATCHDOG_DEFAULT_PERIOD; 305 306 aprint_normal_dev(sc->sc_dev, "default watchdog period is %u seconds\n", 307 sc->sc_smw.smw_period); 308 309 if (sysmon_wdog_register(&sc->sc_smw) != 0) 310 aprint_error_dev(sc->sc_dev, "couldn't register with sysmon\n"); 311 } 312 313 static void 314 as3722_rtc_attach(struct as3722_softc *sc) 315 { 316 int error; 317 318 iic_acquire_bus(sc->sc_i2c, 0); 319 error = as3722_set_clear(sc, AS3722_RTC_CONTROL_REG, 320 AS3722_RTC_CONTROL_RTC_ON, 0, 0); 321 iic_release_bus(sc->sc_i2c, 0); 322 323 if (error) { 324 aprint_error_dev(sc->sc_dev, "couldn't setup RTC\n"); 325 return; 326 } 327 328 sc->sc_todr.todr_gettime_ymdhms = as3722_rtc_gettime; 329 sc->sc_todr.todr_settime_ymdhms = as3722_rtc_settime; 330 sc->sc_todr.cookie = sc; 331 #ifdef FDT 332 fdtbus_todr_attach(sc->sc_dev, sc->sc_phandle, &sc->sc_todr); 333 #else 334 todr_attach(&sc->sc_todr); 335 #endif 336 } 337 338 static int 339 as3722_read(struct as3722_softc *sc, uint8_t reg, uint8_t *val, int flags) 340 { 341 return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, 342 ®, 1, val, 1, flags); 343 } 344 345 static int 346 as3722_write(struct as3722_softc *sc, uint8_t reg, uint8_t val, int flags) 347 { 348 uint8_t buf[2] = { reg, val }; 349 return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 350 NULL, 0, buf, 2, flags); 351 } 352 353 static int 354 as3722_set_clear(struct as3722_softc *sc, uint8_t reg, uint8_t set, 355 uint8_t clr, int flags) 356 { 357 uint8_t old, new; 358 int error; 359 360 error = as3722_read(sc, reg, &old, flags); 361 if (error) { 362 return error; 363 } 364 new = set | (old & ~clr); 365 366 return as3722_write(sc, reg, new, flags); 367 } 368 369 static int 370 as3722_wdt_setmode(struct sysmon_wdog *smw) 371 { 372 struct as3722_softc * const sc = smw->smw_cookie; 373 int error; 374 375 const int flags = 0; 376 377 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 378 iic_acquire_bus(sc->sc_i2c, flags); 379 error = as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG, 380 0, AS3722_WATCHDOG_CTRL_ON, flags); 381 iic_release_bus(sc->sc_i2c, flags); 382 return error; 383 } 384 385 if (smw->smw_period == WDOG_PERIOD_DEFAULT) { 386 smw->smw_period = AS3722_WATCHDOG_DEFAULT_PERIOD; 387 } 388 if (smw->smw_period < 1 || smw->smw_period > 128) { 389 return EINVAL; 390 } 391 sc->sc_smw.smw_period = smw->smw_period; 392 393 iic_acquire_bus(sc->sc_i2c, flags); 394 error = as3722_set_clear(sc, AS3722_WATCHDOG_TIMER_REG, 395 __SHIFTIN(sc->sc_smw.smw_period - 1, AS3722_WATCHDOG_TIMER_TIMER), 396 AS3722_WATCHDOG_TIMER_TIMER, flags); 397 if (error == 0) { 398 error = as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG, 399 AS3722_WATCHDOG_CTRL_ON, 0, flags); 400 } 401 iic_release_bus(sc->sc_i2c, flags); 402 403 return error; 404 } 405 406 static int 407 as3722_wdt_tickle(struct sysmon_wdog *smw) 408 { 409 struct as3722_softc * const sc = smw->smw_cookie; 410 int error; 411 412 const int flags = 0; 413 414 iic_acquire_bus(sc->sc_i2c, flags); 415 error = as3722_set_clear(sc, AS3722_WATCHDOG_SIGNAL_REG, 416 AS3722_WATCHDOG_SIGNAL_SW_SIG, 0, flags); 417 iic_release_bus(sc->sc_i2c, flags); 418 419 return error; 420 } 421 422 static int 423 as3722_rtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt) 424 { 425 struct as3722_softc * const sc = tch->cookie; 426 uint8_t buf[6]; 427 int error = 0; 428 429 const int flags = 0; 430 431 iic_acquire_bus(sc->sc_i2c, flags); 432 error += as3722_read(sc, AS3722_RTC_SECOND_REG, &buf[0], flags); 433 error += as3722_read(sc, AS3722_RTC_MINUTE_REG, &buf[1], flags); 434 error += as3722_read(sc, AS3722_RTC_HOUR_REG, &buf[2], flags); 435 error += as3722_read(sc, AS3722_RTC_DAY_REG, &buf[3], flags); 436 error += as3722_read(sc, AS3722_RTC_MONTH_REG, &buf[4], flags); 437 error += as3722_read(sc, AS3722_RTC_YEAR_REG, &buf[5], flags); 438 iic_release_bus(sc->sc_i2c, flags); 439 440 if (error) 441 return error; 442 443 dt->dt_sec = bcdtobin(buf[0] & 0x7f); 444 dt->dt_min = bcdtobin(buf[1] & 0x7f); 445 dt->dt_hour = bcdtobin(buf[2] & 0x3f); 446 dt->dt_day = bcdtobin(buf[3] & 0x3f); 447 dt->dt_mon = bcdtobin(buf[4] & 0x1f) - 1; 448 dt->dt_year = AS3722_START_YEAR + bcdtobin(buf[5] & 0x7f); 449 dt->dt_wday = 0; 450 451 return 0; 452 } 453 454 static int 455 as3722_rtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt) 456 { 457 struct as3722_softc * const sc = tch->cookie; 458 uint8_t buf[6]; 459 int error = 0; 460 461 if (dt->dt_year < AS3722_START_YEAR) 462 return EINVAL; 463 464 buf[0] = bintobcd(dt->dt_sec) & 0x7f; 465 buf[1] = bintobcd(dt->dt_min) & 0x7f; 466 buf[2] = bintobcd(dt->dt_hour) & 0x3f; 467 buf[3] = bintobcd(dt->dt_day) & 0x3f; 468 buf[4] = bintobcd(dt->dt_mon + 1) & 0x1f; 469 buf[5] = bintobcd(dt->dt_year - AS3722_START_YEAR) & 0x7f; 470 471 const int flags = 0; 472 473 iic_acquire_bus(sc->sc_i2c, flags); 474 error += as3722_write(sc, AS3722_RTC_SECOND_REG, buf[0], flags); 475 error += as3722_write(sc, AS3722_RTC_MINUTE_REG, buf[1], flags); 476 error += as3722_write(sc, AS3722_RTC_HOUR_REG, buf[2], flags); 477 error += as3722_write(sc, AS3722_RTC_DAY_REG, buf[3], flags); 478 error += as3722_write(sc, AS3722_RTC_MONTH_REG, buf[4], flags); 479 error += as3722_write(sc, AS3722_RTC_YEAR_REG, buf[5], flags); 480 iic_release_bus(sc->sc_i2c, flags); 481 482 return error; 483 } 484 485 #ifdef FDT 486 static void 487 as3722_regulator_attach(struct as3722_softc *sc) 488 { 489 struct as3722reg_attach_args raa; 490 int phandle, child; 491 int error; 492 const int flags = 0; 493 uint8_t tmp; 494 495 iic_acquire_bus(sc->sc_i2c, flags); 496 error = as3722_read(sc, AS3722_FUSE7_REG, &tmp, flags); 497 iic_release_bus(sc->sc_i2c, flags); 498 if (error != 0) { 499 aprint_error_dev(sc->sc_dev, "failed to read Fuse7: %d\n", error); 500 return; 501 } 502 503 if (tmp & AS3722_FUSE7_SD0_V_MINUS_200MV) 504 sc->sc_flags |= AS3722_FLAG_SD0_V_MINUS_200MV; 505 506 phandle = of_find_firstchild_byname(sc->sc_phandle, "regulators"); 507 if (phandle <= 0) 508 return; 509 510 for (int i = 0; i < __arraycount(as3722regdefs); i++) { 511 const struct as3722regdef *regdef = &as3722regdefs[i]; 512 child = of_find_firstchild_byname(phandle, regdef->name); 513 if (child <= 0) 514 continue; 515 raa.reg_def = regdef; 516 raa.reg_phandle = child; 517 config_found(sc->sc_dev, &raa, NULL); 518 } 519 } 520 521 static int 522 as3722reg_match(device_t parent, cfdata_t match, void *aux) 523 { 524 return 1; 525 } 526 527 static void 528 as3722reg_attach(device_t parent, device_t self, void *aux) 529 { 530 struct as3722reg_softc *sc = device_private(self); 531 struct as3722reg_attach_args *raa = aux; 532 char *name = NULL; 533 int len; 534 535 sc->sc_dev = self; 536 sc->sc_phandle = raa->reg_phandle; 537 sc->sc_regdef = raa->reg_def; 538 539 fdtbus_register_regulator_controller(self, sc->sc_phandle, 540 &as3722reg_funcs); 541 542 len = OF_getproplen(sc->sc_phandle, "regulator-name"); 543 if (len > 0) { 544 name = kmem_zalloc(len, KM_SLEEP); 545 OF_getprop(sc->sc_phandle, "regulator-name", name, len); 546 } 547 548 aprint_naive("\n"); 549 if (name) 550 aprint_normal(": %s\n", name); 551 else 552 aprint_normal("\n"); 553 554 if (name) 555 kmem_free(name, len); 556 } 557 558 static int 559 as3722reg_acquire(device_t dev) 560 { 561 return 0; 562 } 563 564 static void 565 as3722reg_release(device_t dev) 566 { 567 } 568 569 static int 570 as3722reg_enable(device_t dev, bool enable) 571 { 572 struct as3722reg_softc *sc = device_private(dev); 573 struct as3722_softc *asc = device_private(device_parent(dev)); 574 const struct as3722regdef *regdef = sc->sc_regdef; 575 const int flags = 0; 576 int error; 577 578 if (!regdef->enable_mask) 579 return enable ? 0 : EINVAL; 580 581 iic_acquire_bus(asc->sc_i2c, flags); 582 if (enable) 583 error = as3722_set_clear(asc, regdef->enable_reg, 584 regdef->enable_mask, 0, flags); 585 else 586 error = as3722_set_clear(asc, regdef->enable_reg, 587 0, regdef->enable_mask, flags); 588 iic_release_bus(asc->sc_i2c, flags); 589 590 return error; 591 } 592 593 static int 594 as3722reg_set_voltage_ldo(device_t dev, u_int min_uvol, u_int max_uvol) 595 { 596 struct as3722reg_softc *sc = device_private(dev); 597 struct as3722_softc *asc = device_private(device_parent(dev)); 598 const struct as3722regdef *regdef = sc->sc_regdef; 599 const int flags = 0; 600 uint8_t set_v = 0x00; 601 u_int uvol; 602 int error; 603 604 for (uint8_t v = 0x01; v <= 0x24; v++) { 605 uvol = 800000 + (v * 25000); 606 if (uvol >= min_uvol && uvol <= max_uvol) { 607 set_v = v; 608 goto done; 609 } 610 } 611 for (uint8_t v = 0x40; v <= 0x7f; v++) { 612 uvol = 1725000 + ((v - 0x40) * 25000); 613 if (uvol >= min_uvol && uvol <= max_uvol) { 614 set_v = v; 615 goto done; 616 } 617 } 618 if (set_v == 0) 619 return ERANGE; 620 621 done: 622 iic_acquire_bus(asc->sc_i2c, flags); 623 error = as3722_set_clear(asc, regdef->vsel_reg, set_v, 624 regdef->vsel_mask, flags); 625 iic_release_bus(asc->sc_i2c, flags); 626 627 return error; 628 } 629 630 static int 631 as3722reg_get_voltage_ldo(device_t dev, u_int *puvol) 632 { 633 struct as3722reg_softc *sc = device_private(dev); 634 struct as3722_softc *asc = device_private(device_parent(dev)); 635 const struct as3722regdef *regdef = sc->sc_regdef; 636 const int flags = 0; 637 uint8_t v; 638 int error; 639 640 iic_acquire_bus(asc->sc_i2c, flags); 641 error = as3722_read(asc, regdef->vsel_reg, &v, flags); 642 iic_release_bus(asc->sc_i2c, flags); 643 if (error != 0) 644 return error; 645 646 v &= regdef->vsel_mask; 647 648 if (v == 0) 649 *puvol = 0; /* LDO off */ 650 else if (v >= 0x01 && v <= 0x24) 651 *puvol = 800000 + (v * 25000); 652 else if (v >= 0x40 && v <= 0x7f) 653 *puvol = 1725000 + ((v - 0x40) * 25000); 654 else 655 return EINVAL; 656 657 return 0; 658 } 659 660 static int 661 as3722reg_set_voltage_sd0(device_t dev, u_int min_uvol, u_int max_uvol) 662 { 663 struct as3722reg_softc *sc = device_private(dev); 664 struct as3722_softc *asc = device_private(device_parent(dev)); 665 const struct as3722regdef *regdef = sc->sc_regdef; 666 const int flags = 0; 667 uint8_t set_v = 0x00; 668 u_int uvol; 669 int error; 670 671 if (asc->sc_flags & AS3722_FLAG_SD0_V_MINUS_200MV) { 672 for (uint8_t v = 0x01; v <= 0x6e; v++) { 673 uvol = 400000 + (v * 10000); 674 if (uvol >= min_uvol && uvol <= max_uvol) { 675 set_v = v; 676 goto done; 677 } 678 } 679 } else { 680 for (uint8_t v = 0x01; v <= 0x5a; v++) { 681 uvol = 600000 + (v * 10000); 682 if (uvol >= min_uvol && uvol <= max_uvol) { 683 set_v = v; 684 goto done; 685 } 686 } 687 } 688 if (set_v == 0) 689 return ERANGE; 690 691 done: 692 iic_acquire_bus(asc->sc_i2c, flags); 693 error = as3722_set_clear(asc, regdef->vsel_reg, set_v, 694 regdef->vsel_mask, flags); 695 iic_release_bus(asc->sc_i2c, flags); 696 697 return error; 698 } 699 700 static int 701 as3722reg_get_voltage_sd0(device_t dev, u_int *puvol) 702 { 703 struct as3722reg_softc *sc = device_private(dev); 704 struct as3722_softc *asc = device_private(device_parent(dev)); 705 const struct as3722regdef *regdef = sc->sc_regdef; 706 const int flags = 0; 707 uint8_t v; 708 int error; 709 710 iic_acquire_bus(asc->sc_i2c, flags); 711 error = as3722_read(asc, regdef->vsel_reg, &v, flags); 712 iic_release_bus(asc->sc_i2c, flags); 713 if (error != 0) 714 return error; 715 716 v &= regdef->vsel_mask; 717 718 if (v == 0) { 719 *puvol = 0; /* DC/DC powered down */ 720 return 0; 721 } 722 if (asc->sc_flags & AS3722_FLAG_SD0_V_MINUS_200MV) { 723 if (v >= 0x01 && v <= 0x6e) { 724 *puvol = 400000 + (v * 10000); 725 return 0; 726 } 727 } else { 728 if (v >= 0x01 && v <= 0x5a) { 729 *puvol = 600000 + (v * 10000); 730 return 0; 731 } 732 } 733 734 return EINVAL; 735 } 736 737 static int 738 as3722reg_set_voltage_sd4(device_t dev, u_int min_uvol, u_int max_uvol) 739 { 740 struct as3722reg_softc *sc = device_private(dev); 741 struct as3722_softc *asc = device_private(device_parent(dev)); 742 const struct as3722regdef *regdef = sc->sc_regdef; 743 const int flags = 0; 744 uint8_t set_v = 0x00; 745 u_int uvol; 746 int error; 747 748 749 for (uint8_t v = 0x01; v <= 0x40; v++) { 750 uvol = 600000 + (v * 12500); 751 if (uvol >= min_uvol && uvol <= max_uvol) { 752 set_v = v; 753 goto done; 754 } 755 } 756 for (uint8_t v = 0x41; v <= 0x70; v++) { 757 uvol = 1400000 + ((v - 0x40) * 25000); 758 if (uvol >= min_uvol && uvol <= max_uvol) { 759 set_v = v; 760 goto done; 761 } 762 } 763 for (uint8_t v = 0x71; v <= 0x7f; v++) { 764 uvol = 2600000 + ((v - 0x70) * 50000); 765 if (uvol >= min_uvol && uvol <= max_uvol) { 766 set_v = v; 767 goto done; 768 } 769 } 770 if (set_v == 0) 771 return ERANGE; 772 773 done: 774 iic_acquire_bus(asc->sc_i2c, flags); 775 error = as3722_set_clear(asc, regdef->vsel_reg, set_v, 776 regdef->vsel_mask, flags); 777 iic_release_bus(asc->sc_i2c, flags); 778 779 return error; 780 } 781 782 static int 783 as3722reg_get_voltage_sd4(device_t dev, u_int *puvol) 784 { 785 struct as3722reg_softc *sc = device_private(dev); 786 struct as3722_softc *asc = device_private(device_parent(dev)); 787 const struct as3722regdef *regdef = sc->sc_regdef; 788 const int flags = 0; 789 uint8_t v; 790 int error; 791 792 iic_acquire_bus(asc->sc_i2c, flags); 793 error = as3722_read(asc, regdef->vsel_reg, &v, flags); 794 iic_release_bus(asc->sc_i2c, flags); 795 if (error != 0) 796 return error; 797 798 v &= regdef->vsel_mask; 799 800 if (v == 0) 801 *puvol = 0; /* DC/DC powered down */ 802 else if (v >= 0x01 && v <= 0x40) 803 *puvol = 600000 + (v * 12500); 804 else if (v >= 0x41 && v <= 0x70) 805 *puvol = 1400000 + (v - 0x40) * 25000; 806 else if (v >= 0x71 && v <= 0x7f) 807 *puvol = 2600000 + (v - 0x70) * 50000; 808 else 809 return EINVAL; 810 811 return 0; 812 } 813 814 static int 815 as3722reg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol) 816 { 817 struct as3722reg_softc *sc = device_private(dev); 818 const struct as3722regdef *regdef = sc->sc_regdef; 819 820 return regdef->set(dev, min_uvol, max_uvol); 821 } 822 823 static int 824 as3722reg_get_voltage(device_t dev, u_int *puvol) 825 { 826 struct as3722reg_softc *sc = device_private(dev); 827 const struct as3722regdef *regdef = sc->sc_regdef; 828 829 return regdef->get(dev, puvol); 830 } 831 832 static void 833 as3722_power_reset(device_t dev) 834 { 835 delay(1000000); 836 as3722_reboot(dev); 837 } 838 839 static void 840 as3722_power_poweroff(device_t dev) 841 { 842 delay(1000000); 843 as3722_poweroff(dev); 844 } 845 #endif 846 847 int 848 as3722_poweroff(device_t dev) 849 { 850 struct as3722_softc * const sc = device_private(dev); 851 int error; 852 853 error = iic_acquire_bus(sc->sc_i2c, 0); 854 if (error == 0) { 855 error = as3722_write(sc, AS3722_RESET_CTRL_REG, 856 AS3722_RESET_CTRL_POWER_OFF, 0); 857 iic_release_bus(sc->sc_i2c, 0); 858 } 859 if (error) { 860 device_printf(dev, "WARNING: unable to power off, error %d\n", 861 error); 862 } 863 864 return error; 865 } 866 867 int 868 as3722_reboot(device_t dev) 869 { 870 struct as3722_softc * const sc = device_private(dev); 871 int error; 872 873 error = iic_acquire_bus(sc->sc_i2c, 0); 874 if (error == 0) { 875 error = as3722_write(sc, AS3722_RESET_CTRL_REG, 876 AS3722_RESET_CTRL_FORCE_RESET, 0); 877 iic_release_bus(sc->sc_i2c, 0); 878 } 879 if (error) { 880 device_printf(dev, "WARNING: unable to reboot, error %d\n", 881 error); 882 } 883 884 return error; 885 } 886