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