1 /* $NetBSD: as3722.c,v 1.27 2025/09/17 13:49:13 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2015 Jared D. McNeill <jmcneill (at) 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.27 2025/09/17 13:49:13 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 #ifdef FDT 114 int sc_phandle; 115 #endif 116 int sc_flags; 117 #define AS3722_FLAG_SD0_V_MINUS_200MV 0x01 118 119 struct sysmon_wdog sc_smw; 120 struct todr_chip_handle sc_todr; 121 }; 122 123 #ifdef FDT 124 static int as3722reg_set_voltage_sd0(device_t, u_int, u_int); 125 static int as3722reg_get_voltage_sd0(device_t, u_int *); 126 static int as3722reg_set_voltage_sd4(device_t, u_int, u_int); 127 static int as3722reg_get_voltage_sd4(device_t, u_int *); 128 static int as3722reg_set_voltage_ldo(device_t, u_int, u_int); 129 static int as3722reg_get_voltage_ldo(device_t, u_int *); 130 131 static const struct as3722regdef { 132 const char *name; 133 u_int vsel_reg; 134 u_int vsel_mask; 135 u_int enable_reg; 136 u_int enable_mask; 137 int (*set)(device_t, u_int, u_int); 138 int (*get)(device_t, u_int *); 139 } as3722regdefs[] = { 140 { .name = "sd0", 141 .vsel_reg = AS3722_SD0_VOLTAGE_REG, 142 .vsel_mask = 0x7f, 143 .set = as3722reg_set_voltage_sd0, 144 .get = as3722reg_get_voltage_sd0 }, 145 { .name = "sd4", 146 .vsel_reg = AS3722_SD4_VOLTAGE_REG, 147 .vsel_mask = 0x7f, 148 .enable_reg = AS3722_SDCONTROL_REG, 149 .enable_mask = AS3722_SDCONTROL_SD4_ENABLE, 150 .set = as3722reg_set_voltage_sd4, 151 .get = as3722reg_get_voltage_sd4 }, 152 { .name = "ldo6", 153 .vsel_reg = AS3722_LDO6_VOLTAGE_REG, 154 .vsel_mask = 0x7f, 155 .enable_reg = AS3722_LDOCONTROL0_REG, 156 .enable_mask = 0x40, 157 .set = as3722reg_set_voltage_ldo, 158 .get = as3722reg_get_voltage_ldo }, 159 }; 160 161 struct as3722reg_softc { 162 device_t sc_dev; 163 int sc_phandle; 164 const struct as3722regdef *sc_regdef; 165 }; 166 167 struct as3722reg_attach_args { 168 const struct as3722regdef *reg_def; 169 int reg_phandle; 170 }; 171 #endif 172 173 #define AS3722_WATCHDOG_DEFAULT_PERIOD 10 174 175 static int as3722_match(device_t, cfdata_t, void *); 176 static void as3722_attach(device_t, device_t, void *); 177 178 static void as3722_wdt_attach(struct as3722_softc *); 179 static int as3722_wdt_setmode(struct sysmon_wdog *); 180 static int as3722_wdt_tickle(struct sysmon_wdog *); 181 182 static void as3722_rtc_attach(struct as3722_softc *); 183 static int as3722_rtc_gettime(todr_chip_handle_t, struct clock_ymdhms *); 184 static int as3722_rtc_settime(todr_chip_handle_t, struct clock_ymdhms *); 185 186 #ifdef FDT 187 static void as3722_regulator_attach(struct as3722_softc *); 188 static int as3722reg_match(device_t, cfdata_t, void *); 189 static void as3722reg_attach(device_t, device_t, void *); 190 191 static int as3722reg_acquire(device_t); 192 static void as3722reg_release(device_t); 193 static int as3722reg_enable(device_t, bool); 194 static int as3722reg_set_voltage(device_t, u_int, u_int); 195 static int as3722reg_get_voltage(device_t, u_int *); 196 197 static struct fdtbus_regulator_controller_func as3722reg_funcs = { 198 .acquire = as3722reg_acquire, 199 .release = as3722reg_release, 200 .enable = as3722reg_enable, 201 .set_voltage = as3722reg_set_voltage, 202 .get_voltage = as3722reg_get_voltage, 203 }; 204 205 static void as3722_power_reset(device_t); 206 static void as3722_power_poweroff(device_t); 207 208 static struct fdtbus_power_controller_func as3722power_funcs = { 209 .reset = as3722_power_reset, 210 .poweroff = as3722_power_poweroff, 211 }; 212 #endif 213 214 static int as3722_read(struct as3722_softc *, uint8_t, uint8_t *, int); 215 static int as3722_write(struct as3722_softc *, uint8_t, uint8_t, int); 216 static int as3722_set_clear(struct as3722_softc *, uint8_t, uint8_t, 217 uint8_t, int); 218 219 CFATTACH_DECL_NEW(as3722pmic, sizeof(struct as3722_softc), 220 as3722_match, as3722_attach, NULL, NULL); 221 222 #ifdef FDT 223 CFATTACH_DECL_NEW(as3722reg, sizeof(struct as3722reg_softc), 224 as3722reg_match, as3722reg_attach, NULL, NULL); 225 #endif 226 227 static const struct device_compatible_entry compat_data[] = { 228 { .compat = "ams,as3722" }, 229 DEVICE_COMPAT_EOL 230 }; 231 232 static int 233 as3722_match(device_t parent, cfdata_t match, void *aux) 234 { 235 struct i2c_attach_args *ia = aux; 236 uint8_t reg, id1; 237 int error, match_result; 238 239 if (iic_use_direct_match(ia, match, compat_data, &match_result)) 240 return match_result; 241 242 if (ia->ia_addr != AS3722_I2C_ADDR) 243 return 0; 244 245 iic_acquire_bus(ia->ia_tag, 0); 246 reg = AS3722_ASIC_ID1_REG; 247 error = iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr, 248 ®, 1, &id1, 1, 0); 249 iic_release_bus(ia->ia_tag, 0); 250 251 if (error == 0 && id1 == 0x0c) 252 return I2C_MATCH_ADDRESS_AND_PROBE; 253 254 return 0; 255 } 256 257 static void 258 as3722_attach(device_t parent, device_t self, void *aux) 259 { 260 struct as3722_softc * const sc = device_private(self); 261 struct i2c_attach_args *ia = aux; 262 263 sc->sc_dev = self; 264 sc->sc_i2c = ia->ia_tag; 265 sc->sc_addr = ia->ia_addr; 266 267 #ifdef FDT 268 if (devhandle_type(device_handle(self)) == DEVHANDLE_TYPE_OF) { 269 sc->sc_phandle = devhandle_to_of(device_handle(self)); 270 } 271 #endif 272 273 aprint_naive("\n"); 274 aprint_normal(": AMS AS3722\n"); 275 276 as3722_wdt_attach(sc); 277 as3722_rtc_attach(sc); 278 #ifdef FDT 279 as3722_regulator_attach(sc); 280 281 fdtbus_register_power_controller(self, sc->sc_phandle, 282 &as3722power_funcs); 283 #endif 284 } 285 286 static void 287 as3722_wdt_attach(struct as3722_softc *sc) 288 { 289 int error; 290 291 iic_acquire_bus(sc->sc_i2c, 0); 292 error = as3722_write(sc, AS3722_GPIO0_CTRL_REG, 293 __SHIFTIN(AS3722_GPIO0_CTRL_IOSF_GPIO, 294 AS3722_GPIO0_CTRL_IOSF) | 295 __SHIFTIN(AS3722_GPIO0_CTRL_MODE_PULLDOWN, 296 AS3722_GPIO0_CTRL_MODE), 297 0); 298 error += as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG, 299 __SHIFTIN(1, AS3722_WATCHDOG_CTRL_MODE), 0, 0); 300 iic_release_bus(sc->sc_i2c, 0); 301 302 if (error) { 303 aprint_error_dev(sc->sc_dev, "couldn't setup watchdog\n"); 304 return; 305 } 306 307 sc->sc_smw.smw_name = device_xname(sc->sc_dev); 308 sc->sc_smw.smw_cookie = sc; 309 sc->sc_smw.smw_setmode = as3722_wdt_setmode; 310 sc->sc_smw.smw_tickle = as3722_wdt_tickle; 311 sc->sc_smw.smw_period = AS3722_WATCHDOG_DEFAULT_PERIOD; 312 313 aprint_normal_dev(sc->sc_dev, "default watchdog period is %u seconds\n", 314 sc->sc_smw.smw_period); 315 316 if (sysmon_wdog_register(&sc->sc_smw) != 0) 317 aprint_error_dev(sc->sc_dev, "couldn't register with sysmon\n"); 318 } 319 320 static void 321 as3722_rtc_attach(struct as3722_softc *sc) 322 { 323 int error; 324 325 iic_acquire_bus(sc->sc_i2c, 0); 326 error = as3722_set_clear(sc, AS3722_RTC_CONTROL_REG, 327 AS3722_RTC_CONTROL_RTC_ON, 0, 0); 328 iic_release_bus(sc->sc_i2c, 0); 329 330 if (error) { 331 aprint_error_dev(sc->sc_dev, "couldn't setup RTC\n"); 332 return; 333 } 334 335 sc->sc_todr.todr_gettime_ymdhms = as3722_rtc_gettime; 336 sc->sc_todr.todr_settime_ymdhms = as3722_rtc_settime; 337 sc->sc_todr.todr_dev = sc->sc_dev; 338 todr_attach(&sc->sc_todr); 339 } 340 341 static int 342 as3722_read(struct as3722_softc *sc, uint8_t reg, uint8_t *val, int flags) 343 { 344 return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, 345 ®, 1, val, 1, flags); 346 } 347 348 static int 349 as3722_write(struct as3722_softc *sc, uint8_t reg, uint8_t val, int flags) 350 { 351 uint8_t buf[2] = { reg, val }; 352 return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 353 NULL, 0, buf, 2, flags); 354 } 355 356 static int 357 as3722_set_clear(struct as3722_softc *sc, uint8_t reg, uint8_t set, 358 uint8_t clr, int flags) 359 { 360 uint8_t old, new; 361 int error; 362 363 error = as3722_read(sc, reg, &old, flags); 364 if (error) { 365 return error; 366 } 367 new = set | (old & ~clr); 368 369 return as3722_write(sc, reg, new, flags); 370 } 371 372 static int 373 as3722_wdt_setmode(struct sysmon_wdog *smw) 374 { 375 struct as3722_softc * const sc = smw->smw_cookie; 376 int error; 377 378 const int flags = 0; 379 380 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 381 iic_acquire_bus(sc->sc_i2c, flags); 382 error = as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG, 383 0, AS3722_WATCHDOG_CTRL_ON, flags); 384 iic_release_bus(sc->sc_i2c, flags); 385 return error; 386 } 387 388 if (smw->smw_period == WDOG_PERIOD_DEFAULT) { 389 smw->smw_period = AS3722_WATCHDOG_DEFAULT_PERIOD; 390 } 391 if (smw->smw_period < 1 || smw->smw_period > 128) { 392 return EINVAL; 393 } 394 sc->sc_smw.smw_period = smw->smw_period; 395 396 iic_acquire_bus(sc->sc_i2c, flags); 397 error = as3722_set_clear(sc, AS3722_WATCHDOG_TIMER_REG, 398 __SHIFTIN(sc->sc_smw.smw_period - 1, AS3722_WATCHDOG_TIMER_TIMER), 399 AS3722_WATCHDOG_TIMER_TIMER, flags); 400 if (error == 0) { 401 error = as3722_set_clear(sc, AS3722_WATCHDOG_CTRL_REG, 402 AS3722_WATCHDOG_CTRL_ON, 0, flags); 403 } 404 iic_release_bus(sc->sc_i2c, flags); 405 406 return error; 407 } 408 409 static int 410 as3722_wdt_tickle(struct sysmon_wdog *smw) 411 { 412 struct as3722_softc * const sc = smw->smw_cookie; 413 int error; 414 415 const int flags = 0; 416 417 iic_acquire_bus(sc->sc_i2c, flags); 418 error = as3722_set_clear(sc, AS3722_WATCHDOG_SIGNAL_REG, 419 AS3722_WATCHDOG_SIGNAL_SW_SIG, 0, flags); 420 iic_release_bus(sc->sc_i2c, flags); 421 422 return error; 423 } 424 425 static int 426 as3722_rtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt) 427 { 428 struct as3722_softc * const sc = device_private(tch->todr_dev); 429 uint8_t buf[6]; 430 int error = 0; 431 432 const int flags = 0; 433 434 iic_acquire_bus(sc->sc_i2c, flags); 435 error += as3722_read(sc, AS3722_RTC_SECOND_REG, &buf[0], flags); 436 error += as3722_read(sc, AS3722_RTC_MINUTE_REG, &buf[1], flags); 437 error += as3722_read(sc, AS3722_RTC_HOUR_REG, &buf[2], flags); 438 error += as3722_read(sc, AS3722_RTC_DAY_REG, &buf[3], flags); 439 error += as3722_read(sc, AS3722_RTC_MONTH_REG, &buf[4], flags); 440 error += as3722_read(sc, AS3722_RTC_YEAR_REG, &buf[5], flags); 441 iic_release_bus(sc->sc_i2c, flags); 442 443 if (error) 444 return error; 445 446 dt->dt_sec = bcdtobin(buf[0] & 0x7f); 447 dt->dt_min = bcdtobin(buf[1] & 0x7f); 448 dt->dt_hour = bcdtobin(buf[2] & 0x3f); 449 dt->dt_day = bcdtobin(buf[3] & 0x3f); 450 dt->dt_mon = bcdtobin(buf[4] & 0x1f) - 1; 451 dt->dt_year = AS3722_START_YEAR + bcdtobin(buf[5] & 0x7f); 452 dt->dt_wday = 0; 453 454 return 0; 455 } 456 457 static int 458 as3722_rtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt) 459 { 460 struct as3722_softc * const sc = device_private(tch->todr_dev); 461 uint8_t buf[6]; 462 int error = 0; 463 464 if (dt->dt_year < AS3722_START_YEAR) 465 return EINVAL; 466 467 buf[0] = bintobcd(dt->dt_sec) & 0x7f; 468 buf[1] = bintobcd(dt->dt_min) & 0x7f; 469 buf[2] = bintobcd(dt->dt_hour) & 0x3f; 470 buf[3] = bintobcd(dt->dt_day) & 0x3f; 471 buf[4] = bintobcd(dt->dt_mon + 1) & 0x1f; 472 buf[5] = bintobcd(dt->dt_year - AS3722_START_YEAR) & 0x7f; 473 474 const int flags = 0; 475 476 iic_acquire_bus(sc->sc_i2c, flags); 477 error += as3722_write(sc, AS3722_RTC_SECOND_REG, buf[0], flags); 478 error += as3722_write(sc, AS3722_RTC_MINUTE_REG, buf[1], flags); 479 error += as3722_write(sc, AS3722_RTC_HOUR_REG, buf[2], flags); 480 error += as3722_write(sc, AS3722_RTC_DAY_REG, buf[3], flags); 481 error += as3722_write(sc, AS3722_RTC_MONTH_REG, buf[4], flags); 482 error += as3722_write(sc, AS3722_RTC_YEAR_REG, buf[5], flags); 483 iic_release_bus(sc->sc_i2c, flags); 484 485 return error; 486 } 487 488 #ifdef FDT 489 static void 490 as3722_regulator_attach(struct as3722_softc *sc) 491 { 492 struct as3722reg_attach_args raa; 493 int phandle, child; 494 int error; 495 const int flags = 0; 496 uint8_t tmp; 497 498 iic_acquire_bus(sc->sc_i2c, flags); 499 error = as3722_read(sc, AS3722_FUSE7_REG, &tmp, flags); 500 iic_release_bus(sc->sc_i2c, flags); 501 if (error != 0) { 502 aprint_error_dev(sc->sc_dev, "failed to read Fuse7: %d\n", error); 503 return; 504 } 505 506 if (tmp & AS3722_FUSE7_SD0_V_MINUS_200MV) 507 sc->sc_flags |= AS3722_FLAG_SD0_V_MINUS_200MV; 508 509 phandle = of_find_firstchild_byname(sc->sc_phandle, "regulators"); 510 if (phandle <= 0) 511 return; 512 513 for (int i = 0; i < __arraycount(as3722regdefs); i++) { 514 const struct as3722regdef *regdef = &as3722regdefs[i]; 515 child = of_find_firstchild_byname(phandle, regdef->name); 516 if (child <= 0) 517 continue; 518 raa.reg_def = regdef; 519 raa.reg_phandle = child; 520 config_found(sc->sc_dev, &raa, NULL, CFARGS_NONE); 521 } 522 } 523 524 static int 525 as3722reg_match(device_t parent, cfdata_t match, void *aux) 526 { 527 return 1; 528 } 529 530 static void 531 as3722reg_attach(device_t parent, device_t self, void *aux) 532 { 533 struct as3722reg_softc *sc = device_private(self); 534 struct as3722reg_attach_args *raa = aux; 535 char *name = NULL; 536 int len; 537 538 sc->sc_dev = self; 539 sc->sc_phandle = raa->reg_phandle; 540 sc->sc_regdef = raa->reg_def; 541 542 fdtbus_register_regulator_controller(self, sc->sc_phandle, 543 &as3722reg_funcs); 544 545 len = OF_getproplen(sc->sc_phandle, "regulator-name"); 546 if (len > 0) { 547 name = kmem_zalloc(len, KM_SLEEP); 548 OF_getprop(sc->sc_phandle, "regulator-name", name, len); 549 } 550 551 aprint_naive("\n"); 552 if (name) 553 aprint_normal(": %s\n", name); 554 else 555 aprint_normal("\n"); 556 557 if (name) 558 kmem_free(name, len); 559 } 560 561 static int 562 as3722reg_acquire(device_t dev) 563 { 564 return 0; 565 } 566 567 static void 568 as3722reg_release(device_t dev) 569 { 570 } 571 572 static int 573 as3722reg_enable(device_t dev, bool enable) 574 { 575 struct as3722reg_softc *sc = device_private(dev); 576 struct as3722_softc *asc = device_private(device_parent(dev)); 577 const struct as3722regdef *regdef = sc->sc_regdef; 578 const int flags = 0; 579 int error; 580 581 if (!regdef->enable_mask) 582 return enable ? 0 : EINVAL; 583 584 iic_acquire_bus(asc->sc_i2c, flags); 585 if (enable) 586 error = as3722_set_clear(asc, regdef->enable_reg, 587 regdef->enable_mask, 0, flags); 588 else 589 error = as3722_set_clear(asc, regdef->enable_reg, 590 0, regdef->enable_mask, flags); 591 iic_release_bus(asc->sc_i2c, flags); 592 593 return error; 594 } 595 596 static int 597 as3722reg_set_voltage_ldo(device_t dev, u_int min_uvol, u_int max_uvol) 598 { 599 struct as3722reg_softc *sc = device_private(dev); 600 struct as3722_softc *asc = device_private(device_parent(dev)); 601 const struct as3722regdef *regdef = sc->sc_regdef; 602 const int flags = 0; 603 uint8_t set_v = 0x00; 604 u_int uvol; 605 int error; 606 607 for (uint8_t v = 0x01; v <= 0x24; v++) { 608 uvol = 800000 + (v * 25000); 609 if (uvol >= min_uvol && uvol <= max_uvol) { 610 set_v = v; 611 goto done; 612 } 613 } 614 for (uint8_t v = 0x40; v <= 0x7f; v++) { 615 uvol = 1725000 + ((v - 0x40) * 25000); 616 if (uvol >= min_uvol && uvol <= max_uvol) { 617 set_v = v; 618 goto done; 619 } 620 } 621 if (set_v == 0) 622 return ERANGE; 623 624 done: 625 iic_acquire_bus(asc->sc_i2c, flags); 626 error = as3722_set_clear(asc, regdef->vsel_reg, set_v, 627 regdef->vsel_mask, flags); 628 iic_release_bus(asc->sc_i2c, flags); 629 630 return error; 631 } 632 633 static int 634 as3722reg_get_voltage_ldo(device_t dev, u_int *puvol) 635 { 636 struct as3722reg_softc *sc = device_private(dev); 637 struct as3722_softc *asc = device_private(device_parent(dev)); 638 const struct as3722regdef *regdef = sc->sc_regdef; 639 const int flags = 0; 640 uint8_t v; 641 int error; 642 643 iic_acquire_bus(asc->sc_i2c, flags); 644 error = as3722_read(asc, regdef->vsel_reg, &v, flags); 645 iic_release_bus(asc->sc_i2c, flags); 646 if (error != 0) 647 return error; 648 649 v &= regdef->vsel_mask; 650 651 if (v == 0) 652 *puvol = 0; /* LDO off */ 653 else if (v >= 0x01 && v <= 0x24) 654 *puvol = 800000 + (v * 25000); 655 else if (v >= 0x40 && v <= 0x7f) 656 *puvol = 1725000 + ((v - 0x40) * 25000); 657 else 658 return EINVAL; 659 660 return 0; 661 } 662 663 static int 664 as3722reg_set_voltage_sd0(device_t dev, u_int min_uvol, u_int max_uvol) 665 { 666 struct as3722reg_softc *sc = device_private(dev); 667 struct as3722_softc *asc = device_private(device_parent(dev)); 668 const struct as3722regdef *regdef = sc->sc_regdef; 669 const int flags = 0; 670 uint8_t set_v = 0x00; 671 u_int uvol; 672 int error; 673 674 if (asc->sc_flags & AS3722_FLAG_SD0_V_MINUS_200MV) { 675 for (uint8_t v = 0x01; v <= 0x6e; v++) { 676 uvol = 400000 + (v * 10000); 677 if (uvol >= min_uvol && uvol <= max_uvol) { 678 set_v = v; 679 goto done; 680 } 681 } 682 } else { 683 for (uint8_t v = 0x01; v <= 0x5a; v++) { 684 uvol = 600000 + (v * 10000); 685 if (uvol >= min_uvol && uvol <= max_uvol) { 686 set_v = v; 687 goto done; 688 } 689 } 690 } 691 if (set_v == 0) 692 return ERANGE; 693 694 done: 695 iic_acquire_bus(asc->sc_i2c, flags); 696 error = as3722_set_clear(asc, regdef->vsel_reg, set_v, 697 regdef->vsel_mask, flags); 698 iic_release_bus(asc->sc_i2c, flags); 699 700 return error; 701 } 702 703 static int 704 as3722reg_get_voltage_sd0(device_t dev, u_int *puvol) 705 { 706 struct as3722reg_softc *sc = device_private(dev); 707 struct as3722_softc *asc = device_private(device_parent(dev)); 708 const struct as3722regdef *regdef = sc->sc_regdef; 709 const int flags = 0; 710 uint8_t v; 711 int error; 712 713 iic_acquire_bus(asc->sc_i2c, flags); 714 error = as3722_read(asc, regdef->vsel_reg, &v, flags); 715 iic_release_bus(asc->sc_i2c, flags); 716 if (error != 0) 717 return error; 718 719 v &= regdef->vsel_mask; 720 721 if (v == 0) { 722 *puvol = 0; /* DC/DC powered down */ 723 return 0; 724 } 725 if (asc->sc_flags & AS3722_FLAG_SD0_V_MINUS_200MV) { 726 if (v >= 0x01 && v <= 0x6e) { 727 *puvol = 400000 + (v * 10000); 728 return 0; 729 } 730 } else { 731 if (v >= 0x01 && v <= 0x5a) { 732 *puvol = 600000 + (v * 10000); 733 return 0; 734 } 735 } 736 737 return EINVAL; 738 } 739 740 static int 741 as3722reg_set_voltage_sd4(device_t dev, u_int min_uvol, u_int max_uvol) 742 { 743 struct as3722reg_softc *sc = device_private(dev); 744 struct as3722_softc *asc = device_private(device_parent(dev)); 745 const struct as3722regdef *regdef = sc->sc_regdef; 746 const int flags = 0; 747 uint8_t set_v = 0x00; 748 u_int uvol; 749 int error; 750 751 752 for (uint8_t v = 0x01; v <= 0x40; v++) { 753 uvol = 600000 + (v * 12500); 754 if (uvol >= min_uvol && uvol <= max_uvol) { 755 set_v = v; 756 goto done; 757 } 758 } 759 for (uint8_t v = 0x41; v <= 0x70; v++) { 760 uvol = 1400000 + ((v - 0x40) * 25000); 761 if (uvol >= min_uvol && uvol <= max_uvol) { 762 set_v = v; 763 goto done; 764 } 765 } 766 for (uint8_t v = 0x71; v <= 0x7f; v++) { 767 uvol = 2600000 + ((v - 0x70) * 50000); 768 if (uvol >= min_uvol && uvol <= max_uvol) { 769 set_v = v; 770 goto done; 771 } 772 } 773 if (set_v == 0) 774 return ERANGE; 775 776 done: 777 iic_acquire_bus(asc->sc_i2c, flags); 778 error = as3722_set_clear(asc, regdef->vsel_reg, set_v, 779 regdef->vsel_mask, flags); 780 iic_release_bus(asc->sc_i2c, flags); 781 782 return error; 783 } 784 785 static int 786 as3722reg_get_voltage_sd4(device_t dev, u_int *puvol) 787 { 788 struct as3722reg_softc *sc = device_private(dev); 789 struct as3722_softc *asc = device_private(device_parent(dev)); 790 const struct as3722regdef *regdef = sc->sc_regdef; 791 const int flags = 0; 792 uint8_t v; 793 int error; 794 795 iic_acquire_bus(asc->sc_i2c, flags); 796 error = as3722_read(asc, regdef->vsel_reg, &v, flags); 797 iic_release_bus(asc->sc_i2c, flags); 798 if (error != 0) 799 return error; 800 801 v &= regdef->vsel_mask; 802 803 if (v == 0) 804 *puvol = 0; /* DC/DC powered down */ 805 else if (v >= 0x01 && v <= 0x40) 806 *puvol = 600000 + (v * 12500); 807 else if (v >= 0x41 && v <= 0x70) 808 *puvol = 1400000 + (v - 0x40) * 25000; 809 else if (v >= 0x71 && v <= 0x7f) 810 *puvol = 2600000 + (v - 0x70) * 50000; 811 else 812 return EINVAL; 813 814 return 0; 815 } 816 817 static int 818 as3722reg_set_voltage(device_t dev, u_int min_uvol, u_int max_uvol) 819 { 820 struct as3722reg_softc *sc = device_private(dev); 821 const struct as3722regdef *regdef = sc->sc_regdef; 822 823 return regdef->set(dev, min_uvol, max_uvol); 824 } 825 826 static int 827 as3722reg_get_voltage(device_t dev, u_int *puvol) 828 { 829 struct as3722reg_softc *sc = device_private(dev); 830 const struct as3722regdef *regdef = sc->sc_regdef; 831 832 return regdef->get(dev, puvol); 833 } 834 835 static void 836 as3722_power_reset(device_t dev) 837 { 838 delay(1000000); 839 as3722_reboot(dev); 840 } 841 842 static void 843 as3722_power_poweroff(device_t dev) 844 { 845 delay(1000000); 846 as3722_poweroff(dev); 847 } 848 #endif 849 850 int 851 as3722_poweroff(device_t dev) 852 { 853 struct as3722_softc * const sc = device_private(dev); 854 int error; 855 856 error = iic_acquire_bus(sc->sc_i2c, 0); 857 if (error == 0) { 858 error = as3722_write(sc, AS3722_RESET_CTRL_REG, 859 AS3722_RESET_CTRL_POWER_OFF, 0); 860 iic_release_bus(sc->sc_i2c, 0); 861 } 862 if (error) { 863 device_printf(dev, "WARNING: unable to power off, error %d\n", 864 error); 865 } 866 867 return error; 868 } 869 870 int 871 as3722_reboot(device_t dev) 872 { 873 struct as3722_softc * const sc = device_private(dev); 874 int error; 875 876 error = iic_acquire_bus(sc->sc_i2c, 0); 877 if (error == 0) { 878 error = as3722_write(sc, AS3722_RESET_CTRL_REG, 879 AS3722_RESET_CTRL_FORCE_RESET, 0); 880 iic_release_bus(sc->sc_i2c, 0); 881 } 882 if (error) { 883 device_printf(dev, "WARNING: unable to reboot, error %d\n", 884 error); 885 } 886 887 return error; 888 } 889