1 /*- 2 * Copyright (c) 2015-2016 Emmanuel Vadot <manu@freebsd.org> 3 * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 /* 31 * X-Power AXP209 PMU for Allwinner SoCs 32 */ 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/eventhandler.h> 36 #include <sys/kernel.h> 37 #include <sys/module.h> 38 #include <sys/clock.h> 39 #include <sys/time.h> 40 #include <sys/bus.h> 41 #include <sys/proc.h> 42 #include <sys/gpio.h> 43 #include <sys/reboot.h> 44 #include <sys/resource.h> 45 #include <sys/rman.h> 46 #include <sys/sysctl.h> 47 48 #include <dev/iicbus/iicbus.h> 49 #include <dev/iicbus/iiconf.h> 50 51 #include <dev/gpio/gpiobusvar.h> 52 53 #include <dev/ofw/openfirm.h> 54 #include <dev/ofw/ofw_bus.h> 55 #include <dev/ofw/ofw_bus_subr.h> 56 57 #include <arm/allwinner/axp209reg.h> 58 59 #include "iicbus_if.h" 60 #include "gpio_if.h" 61 62 struct axp209_softc { 63 device_t dev; 64 uint32_t addr; 65 struct resource * res[1]; 66 void * intrcookie; 67 struct intr_config_hook intr_hook; 68 device_t gpiodev; 69 struct mtx mtx; 70 }; 71 72 /* GPIO3 is different, don't expose it for now */ 73 static const struct { 74 const char *name; 75 uint8_t ctrl_reg; 76 } axp209_pins[] = { 77 { "GPIO0", AXP209_GPIO0_CTRL }, 78 { "GPIO1", AXP209_GPIO1_CTRL }, 79 { "GPIO2", AXP209_GPIO2_CTRL }, 80 }; 81 82 static struct resource_spec axp_res_spec[] = { 83 { SYS_RES_IRQ, 0, RF_ACTIVE }, 84 { -1, 0, 0 } 85 }; 86 87 #define AXP_LOCK(sc) mtx_lock(&(sc)->mtx) 88 #define AXP_UNLOCK(sc) mtx_unlock(&(sc)->mtx) 89 90 static int 91 axp209_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size) 92 { 93 struct axp209_softc *sc = device_get_softc(dev); 94 struct iic_msg msg[2]; 95 96 msg[0].slave = sc->addr; 97 msg[0].flags = IIC_M_WR; 98 msg[0].len = 1; 99 msg[0].buf = ® 100 101 msg[1].slave = sc->addr; 102 msg[1].flags = IIC_M_RD; 103 msg[1].len = size; 104 msg[1].buf = data; 105 106 return (iicbus_transfer(dev, msg, 2)); 107 } 108 109 static int 110 axp209_write(device_t dev, uint8_t reg, uint8_t data) 111 { 112 uint8_t buffer[2]; 113 struct axp209_softc *sc = device_get_softc(dev); 114 struct iic_msg msg; 115 116 buffer[0] = reg; 117 buffer[1] = data; 118 119 msg.slave = sc->addr; 120 msg.flags = IIC_M_WR; 121 msg.len = 2; 122 msg.buf = buffer; 123 124 return (iicbus_transfer(dev, &msg, 1)); 125 } 126 127 static int 128 axp209_sysctl(SYSCTL_HANDLER_ARGS) 129 { 130 device_t dev = arg1; 131 enum axp209_sensor sensor = arg2; 132 uint8_t data[2]; 133 int val, error; 134 135 switch (sensor) { 136 case AXP209_TEMP: 137 error = axp209_read(dev, AXP209_TEMPMON, data, 2); 138 if (error != 0) 139 return (error); 140 141 /* Temperature is between -144.7C and 264.8C, step +0.1C */ 142 val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) - 143 AXP209_TEMPMON_MIN + AXP209_0C_TO_K; 144 break; 145 case AXP209_ACVOLT: 146 error = axp209_read(dev, AXP209_ACIN_VOLTAGE, data, 2); 147 if (error != 0) 148 return (error); 149 150 val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) * 151 AXP209_VOLT_STEP; 152 break; 153 case AXP209_ACCURRENT: 154 error = axp209_read(dev, AXP209_ACIN_CURRENT, data, 2); 155 if (error != 0) 156 return (error); 157 158 val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) * 159 AXP209_ACCURRENT_STEP; 160 break; 161 case AXP209_VBUSVOLT: 162 error = axp209_read(dev, AXP209_VBUS_VOLTAGE, data, 2); 163 if (error != 0) 164 return (error); 165 166 val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) * 167 AXP209_VOLT_STEP; 168 break; 169 case AXP209_VBUSCURRENT: 170 error = axp209_read(dev, AXP209_VBUS_CURRENT, data, 2); 171 if (error != 0) 172 return (error); 173 174 val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) * 175 AXP209_VBUSCURRENT_STEP; 176 break; 177 case AXP209_BATVOLT: 178 error = axp209_read(dev, AXP209_BAT_VOLTAGE, data, 2); 179 if (error != 0) 180 return (error); 181 182 val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) * 183 AXP209_BATVOLT_STEP; 184 break; 185 case AXP209_BATCHARGECURRENT: 186 error = axp209_read(dev, AXP209_BAT_CHARGE_CURRENT, data, 2); 187 if (error != 0) 188 return (error); 189 190 val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) * 191 AXP209_BATCURRENT_STEP; 192 break; 193 case AXP209_BATDISCHARGECURRENT: 194 error = axp209_read(dev, AXP209_BAT_DISCHARGE_CURRENT, data, 2); 195 if (error != 0) 196 return (error); 197 198 val = (AXP209_SENSOR_BAT_H(data[0]) | 199 AXP209_SENSOR_BAT_L(data[1])) * AXP209_BATCURRENT_STEP; 200 break; 201 default: 202 return (ENOENT); 203 } 204 205 return sysctl_handle_opaque(oidp, &val, sizeof(val), req); 206 } 207 208 static void 209 axp209_shutdown(void *devp, int howto) 210 { 211 device_t dev; 212 213 if (!(howto & RB_POWEROFF)) 214 return; 215 dev = (device_t)devp; 216 217 if (bootverbose) 218 device_printf(dev, "Shutdown AXP209\n"); 219 220 axp209_write(dev, AXP209_SHUTBAT, AXP209_SHUTBAT_SHUTDOWN); 221 } 222 223 static void 224 axp_intr(void *arg) 225 { 226 struct axp209_softc *sc; 227 uint8_t reg; 228 229 sc = arg; 230 231 axp209_read(sc->dev, AXP209_IRQ1_STATUS, ®, 1); 232 if (reg) { 233 if (reg & AXP209_IRQ1_AC_OVERVOLT) 234 devctl_notify("PMU", "AC", "overvoltage", NULL); 235 if (reg & AXP209_IRQ1_VBUS_OVERVOLT) 236 devctl_notify("PMU", "USB", "overvoltage", NULL); 237 if (reg & AXP209_IRQ1_VBUS_LOW) 238 devctl_notify("PMU", "USB", "undervoltage", NULL); 239 if (reg & AXP209_IRQ1_AC_CONN) 240 devctl_notify("PMU", "AC", "plugged", NULL); 241 if (reg & AXP209_IRQ1_AC_DISCONN) 242 devctl_notify("PMU", "AC", "unplugged", NULL); 243 if (reg & AXP209_IRQ1_VBUS_CONN) 244 devctl_notify("PMU", "USB", "plugged", NULL); 245 if (reg & AXP209_IRQ1_VBUS_DISCONN) 246 devctl_notify("PMU", "USB", "unplugged", NULL); 247 axp209_write(sc->dev, AXP209_IRQ1_STATUS, AXP209_IRQ_ACK); 248 } 249 250 axp209_read(sc->dev, AXP209_IRQ2_STATUS, ®, 1); 251 if (reg) { 252 if (reg & AXP209_IRQ2_BATT_CHARGED) 253 devctl_notify("PMU", "Battery", "charged", NULL); 254 if (reg & AXP209_IRQ2_BATT_CHARGING) 255 devctl_notify("PMU", "Battery", "charging", NULL); 256 if (reg & AXP209_IRQ2_BATT_CONN) 257 devctl_notify("PMU", "Battery", "connected", NULL); 258 if (reg & AXP209_IRQ2_BATT_DISCONN) 259 devctl_notify("PMU", "Battery", "disconnected", NULL); 260 if (reg & AXP209_IRQ2_BATT_TEMP_LOW) 261 devctl_notify("PMU", "Battery", "low temp", NULL); 262 if (reg & AXP209_IRQ2_BATT_TEMP_OVER) 263 devctl_notify("PMU", "Battery", "high temp", NULL); 264 axp209_write(sc->dev, AXP209_IRQ2_STATUS, AXP209_IRQ_ACK); 265 } 266 267 axp209_read(sc->dev, AXP209_IRQ3_STATUS, ®, 1); 268 if (reg) { 269 if (reg & AXP209_IRQ3_PEK_SHORT) 270 shutdown_nice(RB_POWEROFF); 271 axp209_write(sc->dev, AXP209_IRQ3_STATUS, AXP209_IRQ_ACK); 272 } 273 274 axp209_read(sc->dev, AXP209_IRQ4_STATUS, ®, 1); 275 if (reg) { 276 axp209_write(sc->dev, AXP209_IRQ4_STATUS, AXP209_IRQ_ACK); 277 } 278 279 axp209_read(sc->dev, AXP209_IRQ5_STATUS, ®, 1); 280 if (reg) { 281 axp209_write(sc->dev, AXP209_IRQ5_STATUS, AXP209_IRQ_ACK); 282 } 283 } 284 285 static device_t 286 axp209_gpio_get_bus(device_t dev) 287 { 288 struct axp209_softc *sc; 289 290 sc = device_get_softc(dev); 291 292 return (sc->gpiodev); 293 } 294 295 static int 296 axp209_gpio_pin_max(device_t dev, int *maxpin) 297 { 298 *maxpin = nitems(axp209_pins) - 1; 299 300 return (0); 301 } 302 303 static int 304 axp209_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 305 { 306 if (pin >= nitems(axp209_pins)) 307 return (EINVAL); 308 309 snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name); 310 311 return (0); 312 } 313 314 static int 315 axp209_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 316 { 317 if (pin >= nitems(axp209_pins)) 318 return (EINVAL); 319 320 *caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 321 322 return (0); 323 } 324 325 static int 326 axp209_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 327 { 328 struct axp209_softc *sc; 329 uint8_t data, func; 330 int error; 331 332 if (pin >= nitems(axp209_pins)) 333 return (EINVAL); 334 335 sc = device_get_softc(dev); 336 337 AXP_LOCK(sc); 338 error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1); 339 if (error == 0) { 340 func = data & AXP209_GPIO_FUNC_MASK; 341 if (func == AXP209_GPIO_FUNC_INPUT) 342 *flags = GPIO_PIN_INPUT; 343 else if (func == AXP209_GPIO_FUNC_DRVLO || 344 func == AXP209_GPIO_FUNC_DRVHI) 345 *flags = GPIO_PIN_OUTPUT; 346 else 347 *flags = 0; 348 } 349 AXP_UNLOCK(sc); 350 351 return (error); 352 } 353 354 static int 355 axp209_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 356 { 357 struct axp209_softc *sc; 358 uint8_t data; 359 int error; 360 361 if (pin >= nitems(axp209_pins)) 362 return (EINVAL); 363 364 sc = device_get_softc(dev); 365 366 AXP_LOCK(sc); 367 error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1); 368 if (error == 0) { 369 data &= ~AXP209_GPIO_FUNC_MASK; 370 if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) { 371 if ((flags & GPIO_PIN_OUTPUT) == 0) 372 data |= AXP209_GPIO_FUNC_INPUT; 373 } 374 error = axp209_write(dev, axp209_pins[pin].ctrl_reg, data); 375 } 376 AXP_UNLOCK(sc); 377 378 return (error); 379 } 380 381 static int 382 axp209_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 383 { 384 struct axp209_softc *sc; 385 uint8_t data, func; 386 int error; 387 388 if (pin >= nitems(axp209_pins)) 389 return (EINVAL); 390 391 sc = device_get_softc(dev); 392 393 AXP_LOCK(sc); 394 error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1); 395 if (error == 0) { 396 func = data & AXP209_GPIO_FUNC_MASK; 397 switch (func) { 398 case AXP209_GPIO_FUNC_DRVLO: 399 *val = 0; 400 break; 401 case AXP209_GPIO_FUNC_DRVHI: 402 *val = 1; 403 break; 404 case AXP209_GPIO_FUNC_INPUT: 405 error = axp209_read(dev, AXP209_GPIO_STATUS, &data, 1); 406 if (error == 0) 407 *val = (data & AXP209_GPIO_DATA(pin)) ? 1 : 0; 408 break; 409 default: 410 error = EIO; 411 break; 412 } 413 } 414 AXP_UNLOCK(sc); 415 416 return (error); 417 } 418 419 static int 420 axp209_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val) 421 { 422 struct axp209_softc *sc; 423 uint8_t data, func; 424 int error; 425 426 if (pin >= nitems(axp209_pins)) 427 return (EINVAL); 428 429 sc = device_get_softc(dev); 430 431 AXP_LOCK(sc); 432 error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1); 433 if (error == 0) { 434 func = data & AXP209_GPIO_FUNC_MASK; 435 switch (func) { 436 case AXP209_GPIO_FUNC_DRVLO: 437 case AXP209_GPIO_FUNC_DRVHI: 438 /* GPIO2 can't be set to 1 */ 439 if (pin == 2 && val == 1) { 440 error = EINVAL; 441 break; 442 } 443 data &= ~AXP209_GPIO_FUNC_MASK; 444 data |= val; 445 break; 446 default: 447 error = EIO; 448 break; 449 } 450 } 451 if (error == 0) 452 error = axp209_write(dev, axp209_pins[pin].ctrl_reg, data); 453 AXP_UNLOCK(sc); 454 455 return (error); 456 } 457 458 459 static int 460 axp209_gpio_pin_toggle(device_t dev, uint32_t pin) 461 { 462 struct axp209_softc *sc; 463 uint8_t data, func; 464 int error; 465 466 if (pin >= nitems(axp209_pins)) 467 return (EINVAL); 468 469 sc = device_get_softc(dev); 470 471 AXP_LOCK(sc); 472 error = axp209_read(dev, axp209_pins[pin].ctrl_reg, &data, 1); 473 if (error == 0) { 474 func = data & AXP209_GPIO_FUNC_MASK; 475 switch (func) { 476 case AXP209_GPIO_FUNC_DRVLO: 477 /* Pin 2 can't be set to 1*/ 478 if (pin == 2) { 479 error = EINVAL; 480 break; 481 } 482 data &= ~AXP209_GPIO_FUNC_MASK; 483 data |= AXP209_GPIO_FUNC_DRVHI; 484 break; 485 case AXP209_GPIO_FUNC_DRVHI: 486 data &= ~AXP209_GPIO_FUNC_MASK; 487 data |= AXP209_GPIO_FUNC_DRVLO; 488 break; 489 default: 490 error = EIO; 491 break; 492 } 493 } 494 if (error == 0) 495 error = axp209_write(dev, axp209_pins[pin].ctrl_reg, data); 496 AXP_UNLOCK(sc); 497 498 return (error); 499 } 500 501 static int 502 axp209_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, 503 int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags) 504 { 505 if (gpios[0] >= nitems(axp209_pins)) 506 return (EINVAL); 507 508 *pin = gpios[0]; 509 *flags = gpios[1]; 510 511 return (0); 512 } 513 514 static phandle_t 515 axp209_get_node(device_t dev, device_t bus) 516 { 517 return (ofw_bus_get_node(dev)); 518 } 519 520 static void 521 axp209_start(void *pdev) 522 { 523 device_t dev; 524 struct axp209_softc *sc; 525 const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"}; 526 uint8_t data; 527 uint8_t pwr_src; 528 529 dev = pdev; 530 531 sc = device_get_softc(dev); 532 sc->addr = iicbus_get_addr(dev); 533 sc->dev = dev; 534 535 if (bootverbose) { 536 /* 537 * Read the Power State register. 538 * Shift the AC presence into bit 0. 539 * Shift the Battery presence into bit 1. 540 */ 541 axp209_read(dev, AXP209_PSR, &data, 1); 542 pwr_src = ((data & AXP209_PSR_ACIN) >> AXP209_PSR_ACIN_SHIFT) | 543 ((data & AXP209_PSR_VBUS) >> (AXP209_PSR_VBUS_SHIFT - 1)); 544 545 device_printf(dev, "AXP209 Powered by %s\n", 546 pwr_name[pwr_src]); 547 } 548 549 /* Only enable interrupts that we are interested in */ 550 axp209_write(dev, AXP209_IRQ1_ENABLE, 551 AXP209_IRQ1_AC_OVERVOLT | 552 AXP209_IRQ1_AC_DISCONN | 553 AXP209_IRQ1_AC_CONN | 554 AXP209_IRQ1_VBUS_OVERVOLT | 555 AXP209_IRQ1_VBUS_DISCONN | 556 AXP209_IRQ1_VBUS_CONN); 557 axp209_write(dev, AXP209_IRQ2_ENABLE, 558 AXP209_IRQ2_BATT_CONN | 559 AXP209_IRQ2_BATT_DISCONN | 560 AXP209_IRQ2_BATT_CHARGE_ACCT_ON | 561 AXP209_IRQ2_BATT_CHARGE_ACCT_OFF | 562 AXP209_IRQ2_BATT_CHARGING | 563 AXP209_IRQ2_BATT_CHARGED | 564 AXP209_IRQ2_BATT_TEMP_OVER | 565 AXP209_IRQ2_BATT_TEMP_LOW); 566 axp209_write(dev, AXP209_IRQ3_ENABLE, 567 AXP209_IRQ3_PEK_SHORT | AXP209_IRQ3_PEK_LONG); 568 axp209_write(dev, AXP209_IRQ4_ENABLE, AXP209_IRQ4_APS_LOW_2); 569 axp209_write(dev, AXP209_IRQ5_ENABLE, 0x0); 570 571 EVENTHANDLER_REGISTER(shutdown_final, axp209_shutdown, dev, 572 SHUTDOWN_PRI_LAST); 573 574 /* Enable ADC sensors */ 575 if (axp209_write(dev, AXP209_ADC_ENABLE1, 576 AXP209_ADC1_BATVOLT | AXP209_ADC1_BATCURRENT | 577 AXP209_ADC1_ACVOLT | AXP209_ADC1_ACCURRENT | 578 AXP209_ADC1_VBUSVOLT | AXP209_ADC1_VBUSCURRENT) != -1) { 579 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 580 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 581 OID_AUTO, "acvolt", 582 CTLTYPE_INT | CTLFLAG_RD, 583 dev, AXP209_ACVOLT, axp209_sysctl, "I", 584 "AC Voltage (microVolt)"); 585 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 586 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 587 OID_AUTO, "accurrent", 588 CTLTYPE_INT | CTLFLAG_RD, 589 dev, AXP209_ACCURRENT, axp209_sysctl, "I", 590 "AC Current (microAmpere)"); 591 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 592 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 593 OID_AUTO, "vbusvolt", 594 CTLTYPE_INT | CTLFLAG_RD, 595 dev, AXP209_VBUSVOLT, axp209_sysctl, "I", 596 "VBUS Voltage (microVolt)"); 597 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 598 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 599 OID_AUTO, "vbuscurrent", 600 CTLTYPE_INT | CTLFLAG_RD, 601 dev, AXP209_VBUSCURRENT, axp209_sysctl, "I", 602 "VBUS Current (microAmpere)"); 603 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 604 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 605 OID_AUTO, "batvolt", 606 CTLTYPE_INT | CTLFLAG_RD, 607 dev, AXP209_BATVOLT, axp209_sysctl, "I", 608 "Battery Voltage (microVolt)"); 609 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 610 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 611 OID_AUTO, "batchargecurrent", 612 CTLTYPE_INT | CTLFLAG_RD, 613 dev, AXP209_BATCHARGECURRENT, axp209_sysctl, "I", 614 "Battery Charging Current (microAmpere)"); 615 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 616 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 617 OID_AUTO, "batdischargecurrent", 618 CTLTYPE_INT | CTLFLAG_RD, 619 dev, AXP209_BATDISCHARGECURRENT, axp209_sysctl, "I", 620 "Battery Discharging Current (microAmpere)"); 621 } else { 622 device_printf(dev, "Couldn't enable ADC sensors\n"); 623 } 624 625 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 626 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 627 OID_AUTO, "temp", 628 CTLTYPE_INT | CTLFLAG_RD, 629 dev, AXP209_TEMP, axp209_sysctl, "IK", "Internal temperature"); 630 631 if ((bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE, 632 NULL, axp_intr, sc, &sc->intrcookie))) 633 device_printf(dev, "unable to register interrupt handler\n"); 634 635 config_intrhook_disestablish(&sc->intr_hook); 636 } 637 638 static int 639 axp209_probe(device_t dev) 640 { 641 642 if (!ofw_bus_status_okay(dev)) 643 return (ENXIO); 644 645 if (!ofw_bus_is_compatible(dev, "x-powers,axp209")) 646 return (ENXIO); 647 648 device_set_desc(dev, "X-Powers AXP209 Power Management Unit"); 649 650 return (BUS_PROBE_DEFAULT); 651 } 652 653 static int 654 axp209_attach(device_t dev) 655 { 656 struct axp209_softc *sc; 657 658 sc = device_get_softc(dev); 659 mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); 660 661 if (bus_alloc_resources(dev, axp_res_spec, sc->res) != 0) { 662 device_printf(dev, "can't allocate device resources\n"); 663 return (ENXIO); 664 } 665 666 sc->intr_hook.ich_func = axp209_start; 667 sc->intr_hook.ich_arg = dev; 668 669 if (config_intrhook_establish(&sc->intr_hook) != 0) 670 return (ENOMEM); 671 672 sc->gpiodev = gpiobus_attach_bus(dev); 673 674 return (0); 675 } 676 677 static device_method_t axp209_methods[] = { 678 DEVMETHOD(device_probe, axp209_probe), 679 DEVMETHOD(device_attach, axp209_attach), 680 681 /* GPIO interface */ 682 DEVMETHOD(gpio_get_bus, axp209_gpio_get_bus), 683 DEVMETHOD(gpio_pin_max, axp209_gpio_pin_max), 684 DEVMETHOD(gpio_pin_getname, axp209_gpio_pin_getname), 685 DEVMETHOD(gpio_pin_getcaps, axp209_gpio_pin_getcaps), 686 DEVMETHOD(gpio_pin_getflags, axp209_gpio_pin_getflags), 687 DEVMETHOD(gpio_pin_setflags, axp209_gpio_pin_setflags), 688 DEVMETHOD(gpio_pin_get, axp209_gpio_pin_get), 689 DEVMETHOD(gpio_pin_set, axp209_gpio_pin_set), 690 DEVMETHOD(gpio_pin_toggle, axp209_gpio_pin_toggle), 691 DEVMETHOD(gpio_map_gpios, axp209_gpio_map_gpios), 692 693 /* OFW bus interface */ 694 DEVMETHOD(ofw_bus_get_node, axp209_get_node), 695 696 DEVMETHOD_END 697 }; 698 699 static driver_t axp209_driver = { 700 "axp209_pmu", 701 axp209_methods, 702 sizeof(struct axp209_softc), 703 }; 704 705 static devclass_t axp209_devclass; 706 extern devclass_t ofwgpiobus_devclass, gpioc_devclass; 707 extern driver_t ofw_gpiobus_driver, gpioc_driver; 708 709 EARLY_DRIVER_MODULE(axp209, iicbus, axp209_driver, axp209_devclass, 710 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 711 EARLY_DRIVER_MODULE(ofw_gpiobus, axp209_pmu, ofw_gpiobus_driver, 712 ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 713 DRIVER_MODULE(gpioc, axp209_pmu, gpioc_driver, gpioc_devclass, 714 0, 0); 715 MODULE_VERSION(axp209, 1); 716 MODULE_DEPEND(axp209, iicbus, 1, 1, 1); 717