170271Stakawata/*- 2148352Snjl * Copyright (c) 2005 Nate Lawson 378662Siwasaki * Copyright (c) 2000 Munehiro Matsuda 470271Stakawata * Copyright (c) 2000 Takanori Watanabe 570271Stakawata * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 670271Stakawata * All rights reserved. 770271Stakawata * 870271Stakawata * Redistribution and use in source and binary forms, with or without 970271Stakawata * modification, are permitted provided that the following conditions 1070271Stakawata * are met: 1170271Stakawata * 1. Redistributions of source code must retain the above copyright 1270271Stakawata * notice, this list of conditions and the following disclaimer. 1370271Stakawata * 2. Redistributions in binary form must reproduce the above copyright 1470271Stakawata * notice, this list of conditions and the following disclaimer in the 1570271Stakawata * documentation and/or other materials provided with the distribution. 1670271Stakawata * 1770271Stakawata * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1870271Stakawata * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1970271Stakawata * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2070271Stakawata * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2170271Stakawata * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2270271Stakawata * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2370271Stakawata * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2470271Stakawata * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2570271Stakawata * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2670271Stakawata * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2770271Stakawata * SUCH DAMAGE. 2870271Stakawata */ 2970271Stakawata 30148352Snjl#include <sys/cdefs.h> 31148352Snjl__FBSDID("$FreeBSD$"); 32148352Snjl 3370271Stakawata#include "opt_acpi.h" 3470271Stakawata#include <sys/param.h> 3570271Stakawata#include <sys/kernel.h> 36129879Sphk#include <sys/module.h> 3770271Stakawata#include <sys/bus.h> 3870271Stakawata#include <sys/ioccom.h> 3970271Stakawata 4070271Stakawata#include <machine/bus.h> 4170271Stakawata#include <sys/rman.h> 4270271Stakawata#include <sys/malloc.h> 4370271Stakawata 44193530Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193530Sjkim 4670271Stakawata#include <dev/acpica/acpivar.h> 4770271Stakawata#include <dev/acpica/acpiio.h> 4870271Stakawata 49227293Sedstatic MALLOC_DEFINE(M_ACPICMBAT, "acpicmbat", 50227293Sed "ACPI control method battery data"); 5185729Siwasaki 52118783Snjl/* Number of times to retry initialization before giving up. */ 53118783Snjl#define ACPI_CMBAT_RETRY_MAX 6 54118783Snjl 55118783Snjl/* Check the battery once a minute. */ 56133615Snjl#define CMBAT_POLLRATE (60 * hz) 5785325Siwasaki 58118783Snjl/* Hooks for the ACPI CA debugging infrastructure */ 5985738Siwasaki#define _COMPONENT ACPI_BATTERY 6091121SmsmithACPI_MODULE_NAME("BATTERY") 6177432Smsmith 62133615Snjl#define ACPI_BATTERY_BST_CHANGE 0x80 63133615Snjl#define ACPI_BATTERY_BIF_CHANGE 0x81 6470340Siwasaki 6585738Siwasakistruct acpi_cmbat_softc { 66118783Snjl device_t dev; 67148352Snjl int flags; 6885738Siwasaki 69118783Snjl struct acpi_bif bif; 70118783Snjl struct acpi_bst bst; 71118783Snjl struct timespec bst_lastupdated; 7285738Siwasaki}; 7385738Siwasaki 74133615SnjlACPI_SERIAL_DECL(cmbat, "ACPI cmbat"); 7585738Siwasaki 76148352Snjlstatic int acpi_cmbat_probe(device_t dev); 77148352Snjlstatic int acpi_cmbat_attach(device_t dev); 78148352Snjlstatic int acpi_cmbat_detach(device_t dev); 79148352Snjlstatic int acpi_cmbat_resume(device_t dev); 80148352Snjlstatic void acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, 81148352Snjl void *context); 82148352Snjlstatic int acpi_cmbat_info_expired(struct timespec *lastupdated); 83148352Snjlstatic void acpi_cmbat_info_updated(struct timespec *lastupdated); 84152705Snjlstatic void acpi_cmbat_get_bst(void *arg); 85152818Snjlstatic void acpi_cmbat_get_bif_task(void *arg); 86152705Snjlstatic void acpi_cmbat_get_bif(void *arg); 87148352Snjlstatic int acpi_cmbat_bst(device_t dev, struct acpi_bst *bstp); 88148352Snjlstatic int acpi_cmbat_bif(device_t dev, struct acpi_bif *bifp); 89148352Snjlstatic void acpi_cmbat_init_battery(void *arg); 9085738Siwasaki 91118926Snjlstatic device_method_t acpi_cmbat_methods[] = { 92118926Snjl /* Device interface */ 93118926Snjl DEVMETHOD(device_probe, acpi_cmbat_probe), 94118926Snjl DEVMETHOD(device_attach, acpi_cmbat_attach), 95132049Snjl DEVMETHOD(device_detach, acpi_cmbat_detach), 96118926Snjl DEVMETHOD(device_resume, acpi_cmbat_resume), 97118926Snjl 98148352Snjl /* ACPI battery interface */ 99148352Snjl DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bif), 100148352Snjl DEVMETHOD(acpi_batt_get_status, acpi_cmbat_bst), 101148352Snjl 102246128Ssbz DEVMETHOD_END 103118926Snjl}; 104118926Snjl 105118926Snjlstatic driver_t acpi_cmbat_driver = { 106148352Snjl "battery", 107118926Snjl acpi_cmbat_methods, 108118926Snjl sizeof(struct acpi_cmbat_softc), 109118926Snjl}; 110118926Snjl 111118926Snjlstatic devclass_t acpi_cmbat_devclass; 112118926SnjlDRIVER_MODULE(acpi_cmbat, acpi, acpi_cmbat_driver, acpi_cmbat_devclass, 0, 0); 113128071SnjlMODULE_DEPEND(acpi_cmbat, acpi, 1, 1, 1); 114118926Snjl 115118926Snjlstatic int 116148352Snjlacpi_cmbat_probe(device_t dev) 117148352Snjl{ 118148352Snjl static char *cmbat_ids[] = { "PNP0C0A", NULL }; 119148352Snjl 120148352Snjl if (acpi_disabled("cmbat") || 121148352Snjl ACPI_ID_PROBE(device_get_parent(dev), dev, cmbat_ids) == NULL) 122148352Snjl return (ENXIO); 123148352Snjl 124148352Snjl device_set_desc(dev, "ACPI Control Method Battery"); 125148352Snjl return (0); 126148352Snjl} 127148352Snjl 128148352Snjlstatic int 129148352Snjlacpi_cmbat_attach(device_t dev) 130148352Snjl{ 131148352Snjl int error; 132148352Snjl ACPI_HANDLE handle; 133148352Snjl struct acpi_cmbat_softc *sc; 134148352Snjl 135148352Snjl sc = device_get_softc(dev); 136148352Snjl handle = acpi_get_handle(dev); 137148352Snjl sc->dev = dev; 138148352Snjl 139148352Snjl timespecclear(&sc->bst_lastupdated); 140148352Snjl 141148352Snjl error = acpi_battery_register(dev); 142148352Snjl if (error != 0) { 143148352Snjl device_printf(dev, "registering battery failed\n"); 144148352Snjl return (error); 145148352Snjl } 146148352Snjl 147148352Snjl /* 148148352Snjl * Install a system notify handler in addition to the device notify. 149148352Snjl * Toshiba notebook uses this alternate notify for its battery. 150148352Snjl */ 151148352Snjl AcpiInstallNotifyHandler(handle, ACPI_ALL_NOTIFY, 152148352Snjl acpi_cmbat_notify_handler, dev); 153148352Snjl 154167814Sjkim AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev); 155148352Snjl 156148352Snjl return (0); 157148352Snjl} 158148352Snjl 159148352Snjlstatic int 160148352Snjlacpi_cmbat_detach(device_t dev) 161148352Snjl{ 162157778Siwasaki ACPI_HANDLE handle; 163148352Snjl 164157778Siwasaki handle = acpi_get_handle(dev); 165157778Siwasaki AcpiRemoveNotifyHandler(handle, ACPI_ALL_NOTIFY, acpi_cmbat_notify_handler); 166148352Snjl acpi_battery_remove(dev); 167148352Snjl return (0); 168148352Snjl} 169148352Snjl 170148352Snjlstatic int 171148352Snjlacpi_cmbat_resume(device_t dev) 172148352Snjl{ 173148352Snjl 174167814Sjkim AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_init_battery, dev); 175148352Snjl return (0); 176148352Snjl} 177148352Snjl 178148352Snjlstatic void 179148352Snjlacpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 180148352Snjl{ 181148352Snjl struct acpi_cmbat_softc *sc; 182148352Snjl device_t dev; 183148352Snjl 184148352Snjl dev = (device_t)context; 185148352Snjl sc = device_get_softc(dev); 186148352Snjl 187148352Snjl switch (notify) { 188148352Snjl case ACPI_NOTIFY_DEVICE_CHECK: 189148352Snjl case ACPI_BATTERY_BST_CHANGE: 190152705Snjl /* 191152705Snjl * Clear the last updated time. The next call to retrieve the 192152705Snjl * battery status will get the new value for us. 193152705Snjl */ 194148352Snjl timespecclear(&sc->bst_lastupdated); 195148352Snjl break; 196148352Snjl case ACPI_NOTIFY_BUS_CHECK: 197148352Snjl case ACPI_BATTERY_BIF_CHANGE: 198152705Snjl /* 199152705Snjl * Queue a callback to get the current battery info from thread 200152705Snjl * context. It's not safe to block in a notify handler. 201152705Snjl */ 202167814Sjkim AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cmbat_get_bif_task, dev); 203148352Snjl break; 204148352Snjl } 205148352Snjl 206148352Snjl acpi_UserNotify("CMBAT", h, notify); 207148352Snjl} 208148352Snjl 209148352Snjlstatic int 21078662Siwasakiacpi_cmbat_info_expired(struct timespec *lastupdated) 21178662Siwasaki{ 212118783Snjl struct timespec curtime; 21378662Siwasaki 214133615Snjl ACPI_SERIAL_ASSERT(cmbat); 215133615Snjl 216118783Snjl if (lastupdated == NULL) 217133615Snjl return (TRUE); 218118783Snjl if (!timespecisset(lastupdated)) 219133615Snjl return (TRUE); 22078662Siwasaki 221118783Snjl getnanotime(&curtime); 222118783Snjl timespecsub(&curtime, lastupdated); 223118783Snjl return (curtime.tv_sec < 0 || 224118783Snjl curtime.tv_sec > acpi_battery_get_info_expire()); 22578662Siwasaki} 22678662Siwasaki 227118926Snjlstatic void 22878662Siwasakiacpi_cmbat_info_updated(struct timespec *lastupdated) 22978662Siwasaki{ 230133615Snjl 231133615Snjl ACPI_SERIAL_ASSERT(cmbat); 232133615Snjl 233118783Snjl if (lastupdated != NULL) 234118783Snjl getnanotime(lastupdated); 23578662Siwasaki} 23678662Siwasaki 23770271Stakawatastatic void 238152705Snjlacpi_cmbat_get_bst(void *arg) 23970271Stakawata{ 240118783Snjl struct acpi_cmbat_softc *sc; 241118783Snjl ACPI_STATUS as; 242123777Snjl ACPI_OBJECT *res; 243118783Snjl ACPI_HANDLE h; 244118783Snjl ACPI_BUFFER bst_buffer; 245152705Snjl device_t dev; 24678662Siwasaki 247133615Snjl ACPI_SERIAL_ASSERT(cmbat); 248133615Snjl 249152705Snjl dev = arg; 250118783Snjl sc = device_get_softc(dev); 251118783Snjl h = acpi_get_handle(dev); 252133615Snjl bst_buffer.Pointer = NULL; 253133615Snjl bst_buffer.Length = ACPI_ALLOCATE_BUFFER; 25485738Siwasaki 255118783Snjl if (!acpi_cmbat_info_expired(&sc->bst_lastupdated)) 256133615Snjl goto end; 25778662Siwasaki 258118783Snjl as = AcpiEvaluateObject(h, "_BST", NULL, &bst_buffer); 259118783Snjl if (ACPI_FAILURE(as)) { 260118783Snjl ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 26188420Siwasaki "error fetching current battery status -- %s\n", 26288420Siwasaki AcpiFormatException(as)); 263118783Snjl goto end; 264118783Snjl } 26570271Stakawata 266118783Snjl res = (ACPI_OBJECT *)bst_buffer.Pointer; 267123777Snjl if (!ACPI_PKG_VALID(res, 4)) { 268118783Snjl ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 26986552Siwasaki "battery status corrupted\n"); 270118783Snjl goto end; 271118783Snjl } 27270271Stakawata 273123777Snjl if (acpi_PkgInt32(res, 0, &sc->bst.state) != 0) 274123777Snjl goto end; 275123777Snjl if (acpi_PkgInt32(res, 1, &sc->bst.rate) != 0) 276123777Snjl goto end; 277123777Snjl if (acpi_PkgInt32(res, 2, &sc->bst.cap) != 0) 278123777Snjl goto end; 279123777Snjl if (acpi_PkgInt32(res, 3, &sc->bst.volt) != 0) 280123777Snjl goto end; 281118783Snjl acpi_cmbat_info_updated(&sc->bst_lastupdated); 282118783Snjl 283216503Savg /* Clear out undefined/extended bits that might be set by hardware. */ 284216503Savg sc->bst.state &= ACPI_BATT_STAT_BST_MASK; 285216503Savg if ((sc->bst.state & ACPI_BATT_STAT_INVALID) == ACPI_BATT_STAT_INVALID) 286216503Savg ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 287216503Savg "battery reports simultaneous charging and discharging\n"); 288216503Savg 289139057Snjl /* XXX If all batteries are critical, perhaps we should suspend. */ 290139057Snjl if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) { 291139057Snjl if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) { 292139057Snjl sc->flags |= ACPI_BATT_STAT_CRITICAL; 293139057Snjl device_printf(dev, "critically low charge!\n"); 294139057Snjl } 295139057Snjl } else 296139057Snjl sc->flags &= ~ACPI_BATT_STAT_CRITICAL; 297136369Snjl 29870271Stakawataend: 299118783Snjl if (bst_buffer.Pointer != NULL) 300118783Snjl AcpiOsFree(bst_buffer.Pointer); 30170271Stakawata} 30270271Stakawata 303152818Snjl/* XXX There should be a cleaner way to do this locking. */ 30470271Stakawatastatic void 305152818Snjlacpi_cmbat_get_bif_task(void *arg) 306152818Snjl{ 307152818Snjl 308152818Snjl ACPI_SERIAL_BEGIN(cmbat); 309152818Snjl acpi_cmbat_get_bif(arg); 310152818Snjl ACPI_SERIAL_END(cmbat); 311152818Snjl} 312152818Snjl 313152818Snjlstatic void 314152705Snjlacpi_cmbat_get_bif(void *arg) 31570271Stakawata{ 316118783Snjl struct acpi_cmbat_softc *sc; 317118783Snjl ACPI_STATUS as; 318123777Snjl ACPI_OBJECT *res; 319118783Snjl ACPI_HANDLE h; 320118783Snjl ACPI_BUFFER bif_buffer; 321152705Snjl device_t dev; 32270271Stakawata 323133615Snjl ACPI_SERIAL_ASSERT(cmbat); 324133615Snjl 325152705Snjl dev = arg; 326118783Snjl sc = device_get_softc(dev); 327118783Snjl h = acpi_get_handle(dev); 328133615Snjl bif_buffer.Pointer = NULL; 329133615Snjl bif_buffer.Length = ACPI_ALLOCATE_BUFFER; 33085738Siwasaki 331118783Snjl as = AcpiEvaluateObject(h, "_BIF", NULL, &bif_buffer); 332118783Snjl if (ACPI_FAILURE(as)) { 333118783Snjl ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 33488420Siwasaki "error fetching current battery info -- %s\n", 33588420Siwasaki AcpiFormatException(as)); 336118783Snjl goto end; 337118783Snjl } 33870271Stakawata 339118783Snjl res = (ACPI_OBJECT *)bif_buffer.Pointer; 340123777Snjl if (!ACPI_PKG_VALID(res, 13)) { 341118783Snjl ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 34286552Siwasaki "battery info corrupted\n"); 343118783Snjl goto end; 344118783Snjl } 34578662Siwasaki 346133615Snjl if (acpi_PkgInt32(res, 0, &sc->bif.units) != 0) 347123777Snjl goto end; 348133615Snjl if (acpi_PkgInt32(res, 1, &sc->bif.dcap) != 0) 349123777Snjl goto end; 350133615Snjl if (acpi_PkgInt32(res, 2, &sc->bif.lfcap) != 0) 351123777Snjl goto end; 352133615Snjl if (acpi_PkgInt32(res, 3, &sc->bif.btech) != 0) 353123777Snjl goto end; 354133615Snjl if (acpi_PkgInt32(res, 4, &sc->bif.dvol) != 0) 355123777Snjl goto end; 356133615Snjl if (acpi_PkgInt32(res, 5, &sc->bif.wcap) != 0) 357123777Snjl goto end; 358133615Snjl if (acpi_PkgInt32(res, 6, &sc->bif.lcap) != 0) 359123777Snjl goto end; 360133615Snjl if (acpi_PkgInt32(res, 7, &sc->bif.gra1) != 0) 361123777Snjl goto end; 362133615Snjl if (acpi_PkgInt32(res, 8, &sc->bif.gra2) != 0) 363123777Snjl goto end; 364123777Snjl if (acpi_PkgStr(res, 9, sc->bif.model, ACPI_CMBAT_MAXSTRLEN) != 0) 365123777Snjl goto end; 366123777Snjl if (acpi_PkgStr(res, 10, sc->bif.serial, ACPI_CMBAT_MAXSTRLEN) != 0) 367123777Snjl goto end; 368123777Snjl if (acpi_PkgStr(res, 11, sc->bif.type, ACPI_CMBAT_MAXSTRLEN) != 0) 369123777Snjl goto end; 370123777Snjl if (acpi_PkgStr(res, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN) != 0) 371123777Snjl goto end; 372118783Snjl 37370271Stakawataend: 374118783Snjl if (bif_buffer.Pointer != NULL) 375118783Snjl AcpiOsFree(bif_buffer.Pointer); 37670271Stakawata} 37770271Stakawata 37870271Stakawatastatic int 379148352Snjlacpi_cmbat_bif(device_t dev, struct acpi_bif *bifp) 38070271Stakawata{ 381118783Snjl struct acpi_cmbat_softc *sc; 38278662Siwasaki 383133615Snjl sc = device_get_softc(dev); 384119974Snjl 385152705Snjl /* 386152705Snjl * Just copy the data. The only value that should change is the 387152705Snjl * last-full capacity, so we only update when we get a notify that says 388152705Snjl * the info has changed. Many systems apparently take a long time to 389152705Snjl * process a _BIF call so we avoid it if possible. 390152705Snjl */ 391133615Snjl ACPI_SERIAL_BEGIN(cmbat); 392148352Snjl bifp->units = sc->bif.units; 393148352Snjl bifp->dcap = sc->bif.dcap; 394148352Snjl bifp->lfcap = sc->bif.lfcap; 395148352Snjl bifp->btech = sc->bif.btech; 396148352Snjl bifp->dvol = sc->bif.dvol; 397148352Snjl bifp->wcap = sc->bif.wcap; 398148352Snjl bifp->lcap = sc->bif.lcap; 399148352Snjl bifp->gra1 = sc->bif.gra1; 400148352Snjl bifp->gra2 = sc->bif.gra2; 401148352Snjl strncpy(bifp->model, sc->bif.model, sizeof(sc->bif.model)); 402148352Snjl strncpy(bifp->serial, sc->bif.serial, sizeof(sc->bif.serial)); 403148352Snjl strncpy(bifp->type, sc->bif.type, sizeof(sc->bif.type)); 404148352Snjl strncpy(bifp->oeminfo, sc->bif.oeminfo, sizeof(sc->bif.oeminfo)); 405133615Snjl ACPI_SERIAL_END(cmbat); 406133615Snjl 407118783Snjl return (0); 40870271Stakawata} 40970271Stakawata 41085325Siwasakistatic int 411148352Snjlacpi_cmbat_bst(device_t dev, struct acpi_bst *bstp) 412132049Snjl{ 413132049Snjl struct acpi_cmbat_softc *sc; 414132049Snjl 415132049Snjl sc = device_get_softc(dev); 416132049Snjl 417133615Snjl ACPI_SERIAL_BEGIN(cmbat); 418148352Snjl if (acpi_BatteryIsPresent(dev)) { 419148352Snjl acpi_cmbat_get_bst(dev); 420148352Snjl bstp->state = sc->bst.state; 421148352Snjl bstp->rate = sc->bst.rate; 422148352Snjl bstp->cap = sc->bst.cap; 423148352Snjl bstp->volt = sc->bst.volt; 424148352Snjl } else 425148352Snjl bstp->state = ACPI_BATT_STAT_NOT_PRESENT; 426133615Snjl ACPI_SERIAL_END(cmbat); 42778662Siwasaki 428118783Snjl return (0); 42970340Siwasaki} 43078662Siwasaki 431106377Siwasakistatic void 432106377Siwasakiacpi_cmbat_init_battery(void *arg) 433106377Siwasaki{ 434133615Snjl struct acpi_cmbat_softc *sc; 435148352Snjl int retry, valid; 436133615Snjl device_t dev; 437106377Siwasaki 438133615Snjl dev = (device_t)arg; 439133615Snjl sc = device_get_softc(dev); 440118783Snjl ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 441118783Snjl "battery initialization start\n"); 442106377Siwasaki 443148352Snjl /* 444148352Snjl * Try repeatedly to get valid data from the battery. Since the 445148352Snjl * embedded controller isn't always ready just after boot, we may have 446148352Snjl * to wait a while. 447148352Snjl */ 448138300Smarks for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10000)) { 449157774Siwasaki /* batteries on DOCK can be ejected w/ DOCK during retrying */ 450157774Siwasaki if (!device_is_attached(dev)) 451157774Siwasaki return; 452157774Siwasaki 453148352Snjl if (!acpi_BatteryIsPresent(dev)) 454118783Snjl continue; 455106377Siwasaki 456152705Snjl /* 457152705Snjl * Only query the battery if this is the first try or the specific 458152705Snjl * type of info is still invalid. 459152705Snjl */ 460133615Snjl ACPI_SERIAL_BEGIN(cmbat); 461152705Snjl if (retry == 0 || !acpi_battery_bst_valid(&sc->bst)) { 462152705Snjl timespecclear(&sc->bst_lastupdated); 463152705Snjl acpi_cmbat_get_bst(dev); 464152705Snjl } 465152705Snjl if (retry == 0 || !acpi_battery_bif_valid(&sc->bif)) 466152705Snjl acpi_cmbat_get_bif(dev); 467152705Snjl 468148352Snjl valid = acpi_battery_bst_valid(&sc->bst) && 469148352Snjl acpi_battery_bif_valid(&sc->bif); 470133615Snjl ACPI_SERIAL_END(cmbat); 471106377Siwasaki 472148352Snjl if (valid) 473133615Snjl break; 474118783Snjl } 475106377Siwasaki 476118783Snjl if (retry == ACPI_CMBAT_RETRY_MAX) { 477118783Snjl ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 478118783Snjl "battery initialization failed, giving up\n"); 479118783Snjl } else { 480118783Snjl ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 481118783Snjl "battery initialization done, tried %d times\n", retry + 1); 482118783Snjl } 483106377Siwasaki} 484