1 1.14 macallan /* $NetBSD: smartbat.c,v 1.14 2012/11/01 15:54:28 macallan Exp $ */ 2 1.1 macallan 3 1.1 macallan /*- 4 1.1 macallan * Copyright (c) 2007 Michael Lorenz 5 1.3 macallan * 2008 Magnus Henoch 6 1.1 macallan * All rights reserved. 7 1.1 macallan * 8 1.1 macallan * Redistribution and use in source and binary forms, with or without 9 1.1 macallan * modification, are permitted provided that the following conditions 10 1.1 macallan * are met: 11 1.1 macallan * 1. Redistributions of source code must retain the above copyright 12 1.1 macallan * notice, this list of conditions and the following disclaimer. 13 1.1 macallan * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 macallan * notice, this list of conditions and the following disclaimer in the 15 1.1 macallan * documentation and/or other materials provided with the distribution. 16 1.1 macallan * 17 1.1 macallan * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 1.1 macallan * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 1.1 macallan * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 1.1 macallan * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 1.1 macallan * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 1.1 macallan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 1.1 macallan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 macallan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 1.1 macallan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 1.1 macallan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 macallan * POSSIBILITY OF SUCH DAMAGE. 28 1.1 macallan */ 29 1.1 macallan 30 1.1 macallan #include <sys/cdefs.h> 31 1.14 macallan __KERNEL_RCSID(0, "$NetBSD: smartbat.c,v 1.14 2012/11/01 15:54:28 macallan Exp $"); 32 1.1 macallan 33 1.1 macallan #include <sys/param.h> 34 1.1 macallan #include <sys/systm.h> 35 1.1 macallan #include <sys/kernel.h> 36 1.1 macallan #include <sys/device.h> 37 1.1 macallan #include <sys/proc.h> 38 1.1 macallan 39 1.1 macallan #include <dev/sysmon/sysmonvar.h> 40 1.1 macallan #include <dev/sysmon/sysmon_taskq.h> 41 1.1 macallan 42 1.1 macallan #include <macppc/dev/pmuvar.h> 43 1.1 macallan #include <macppc/dev/batteryvar.h> 44 1.6 dyoung #include <sys/bus.h> 45 1.1 macallan #include "opt_battery.h" 46 1.1 macallan 47 1.1 macallan #ifdef SMARTBAT_DEBUG 48 1.1 macallan #define DPRINTF printf 49 1.9 macallan #define static /* static */ 50 1.1 macallan #else 51 1.1 macallan #define DPRINTF while (0) printf 52 1.1 macallan #endif 53 1.1 macallan 54 1.3 macallan #define BAT_AC_PRESENT 0 55 1.9 macallan 56 1.9 macallan #define BAT_PRESENT 0 57 1.9 macallan #define BAT_VOLTAGE 1 58 1.9 macallan #define BAT_CURRENT 2 59 1.9 macallan #define BAT_MAX_CHARGE 3 60 1.9 macallan #define BAT_CHARGE 4 61 1.9 macallan #define BAT_CHARGING 5 62 1.10 macallan #define BAT_CHARGE_STATE 6 63 1.10 macallan #define BAT_FULL 7 64 1.10 macallan #define BAT_NSENSORS 8 /* number of sensors */ 65 1.1 macallan 66 1.1 macallan struct smartbat_softc { 67 1.8 macallan device_t sc_dev; 68 1.1 macallan struct pmu_ops *sc_pmu_ops; 69 1.1 macallan int sc_num; 70 1.1 macallan 71 1.1 macallan /* envsys stuff */ 72 1.9 macallan struct sysmon_envsys *sc_bat_sme; 73 1.9 macallan envsys_data_t sc_bat_sensor[BAT_NSENSORS]; 74 1.9 macallan struct sysmon_envsys *sc_ac_sme; 75 1.9 macallan envsys_data_t sc_ac_sensor[1]; 76 1.3 macallan struct sysmon_pswitch sc_sm_acpower; 77 1.9 macallan int sc_have_ac; 78 1.3 macallan 79 1.3 macallan /* battery status */ 80 1.3 macallan int sc_flags; 81 1.3 macallan int sc_oflags; 82 1.3 macallan int sc_voltage; 83 1.3 macallan int sc_charge; 84 1.3 macallan int sc_max_charge; 85 1.14 macallan int sc_warn; 86 1.14 macallan int sc_low; 87 1.3 macallan int sc_draw; 88 1.3 macallan int sc_time; 89 1.3 macallan uint32_t sc_timestamp; 90 1.1 macallan }; 91 1.1 macallan 92 1.5 matt static void smartbat_attach(device_t, device_t, void *); 93 1.5 matt static int smartbat_match(device_t, cfdata_t, void *); 94 1.3 macallan static void smartbat_setup_envsys(struct smartbat_softc *); 95 1.3 macallan static void smartbat_refresh(struct sysmon_envsys *, envsys_data_t *); 96 1.13 macallan static void smartbat_get_limits(struct sysmon_envsys *, envsys_data_t *, 97 1.13 macallan sysmon_envsys_lim_t *, uint32_t *); 98 1.9 macallan static void smartbat_refresh_ac(struct sysmon_envsys *, envsys_data_t *); 99 1.3 macallan static void smartbat_poll(void *); 100 1.3 macallan static int smartbat_update(struct smartbat_softc *, int); 101 1.1 macallan 102 1.8 macallan CFATTACH_DECL_NEW(smartbat, sizeof(struct smartbat_softc), 103 1.1 macallan smartbat_match, smartbat_attach, NULL, NULL); 104 1.1 macallan 105 1.1 macallan static int 106 1.5 matt smartbat_match(device_t parent, cfdata_t cf, void *aux) 107 1.1 macallan { 108 1.1 macallan struct battery_attach_args *baa = aux; 109 1.1 macallan 110 1.1 macallan if (baa->baa_type == BATTERY_TYPE_SMART) 111 1.1 macallan return 1; 112 1.1 macallan 113 1.1 macallan return 0; 114 1.1 macallan } 115 1.1 macallan 116 1.1 macallan static void 117 1.5 matt smartbat_attach(device_t parent, device_t self, void *aux) 118 1.1 macallan { 119 1.1 macallan struct battery_attach_args *baa = aux; 120 1.5 matt struct smartbat_softc *sc = device_private(self); 121 1.1 macallan 122 1.8 macallan sc->sc_dev = self; 123 1.1 macallan sc->sc_pmu_ops = baa->baa_pmu_ops; 124 1.1 macallan sc->sc_num = baa->baa_num; 125 1.1 macallan 126 1.9 macallan /* 127 1.9 macallan * we can have more than one instance but only the first one needs 128 1.9 macallan * to report AC status 129 1.9 macallan */ 130 1.10 macallan sc->sc_have_ac = FALSE; 131 1.10 macallan if (sc->sc_num == 0) 132 1.10 macallan sc->sc_have_ac = TRUE; 133 1.10 macallan 134 1.1 macallan printf(" addr %d: smart battery\n", sc->sc_num); 135 1.1 macallan 136 1.14 macallan sc->sc_charge = 0; 137 1.14 macallan sc->sc_max_charge = 0; 138 1.3 macallan smartbat_update(sc, 1); 139 1.3 macallan /* trigger a status update */ 140 1.3 macallan sc->sc_oflags = ~sc->sc_flags; 141 1.3 macallan 142 1.3 macallan smartbat_setup_envsys(sc); 143 1.3 macallan 144 1.9 macallan if (sc->sc_have_ac) { 145 1.9 macallan memset(&sc->sc_sm_acpower, 0, sizeof(struct sysmon_pswitch)); 146 1.9 macallan sc->sc_sm_acpower.smpsw_name = "AC Power"; 147 1.9 macallan sc->sc_sm_acpower.smpsw_type = PSWITCH_TYPE_ACADAPTER; 148 1.9 macallan if (sysmon_pswitch_register(&sc->sc_sm_acpower) != 0) 149 1.9 macallan printf("%s: unable to register AC power status with " \ 150 1.9 macallan "sysmon\n", 151 1.9 macallan device_xname(sc->sc_dev)); 152 1.10 macallan sc->sc_pmu_ops->register_callback(sc->sc_pmu_ops->cookie, 153 1.10 macallan smartbat_poll, sc); 154 1.9 macallan } 155 1.3 macallan } 156 1.3 macallan 157 1.3 macallan 158 1.3 macallan static void 159 1.3 macallan smartbat_setup_envsys(struct smartbat_softc *sc) 160 1.3 macallan { 161 1.3 macallan int i; 162 1.3 macallan 163 1.9 macallan if (sc->sc_have_ac) { 164 1.9 macallan 165 1.9 macallan #define INITDATA(index, unit, string) \ 166 1.9 macallan sc->sc_ac_sensor[index].units = unit; \ 167 1.9 macallan sc->sc_ac_sensor[index].state = ENVSYS_SINVALID; \ 168 1.9 macallan snprintf(sc->sc_ac_sensor[index].desc, \ 169 1.9 macallan sizeof(sc->sc_ac_sensor[index].desc), "%s", string); 170 1.9 macallan 171 1.9 macallan INITDATA(BAT_AC_PRESENT, ENVSYS_INDICATOR, "connected"); 172 1.9 macallan #undef INITDATA 173 1.9 macallan 174 1.9 macallan sc->sc_ac_sme = sysmon_envsys_create(); 175 1.9 macallan 176 1.9 macallan if (sysmon_envsys_sensor_attach(sc->sc_ac_sme, 177 1.9 macallan &sc->sc_ac_sensor[0])) { 178 1.9 macallan sysmon_envsys_destroy(sc->sc_ac_sme); 179 1.9 macallan return; 180 1.9 macallan } 181 1.9 macallan 182 1.9 macallan sc->sc_ac_sme->sme_name = "AC Adaptor"; 183 1.9 macallan sc->sc_ac_sme->sme_cookie = sc; 184 1.9 macallan sc->sc_ac_sme->sme_refresh = smartbat_refresh_ac; 185 1.9 macallan sc->sc_ac_sme->sme_class = SME_CLASS_ACADAPTER; 186 1.9 macallan 187 1.9 macallan if (sysmon_envsys_register(sc->sc_ac_sme)) { 188 1.9 macallan aprint_error("%s: unable to register AC with sysmon\n", 189 1.9 macallan device_xname(sc->sc_dev)); 190 1.9 macallan sysmon_envsys_destroy(sc->sc_ac_sme); 191 1.9 macallan } 192 1.9 macallan } 193 1.9 macallan 194 1.9 macallan sc->sc_bat_sme = sysmon_envsys_create(); 195 1.9 macallan 196 1.9 macallan #define INITDATA(index, unit, string) \ 197 1.9 macallan sc->sc_bat_sensor[index].units = unit; \ 198 1.9 macallan sc->sc_bat_sensor[index].state = ENVSYS_SINVALID; \ 199 1.9 macallan snprintf(sc->sc_bat_sensor[index].desc, \ 200 1.9 macallan sizeof(sc->sc_bat_sensor[index].desc), "%s", string); 201 1.3 macallan 202 1.3 macallan INITDATA(BAT_PRESENT, ENVSYS_INDICATOR, "Battery present"); 203 1.3 macallan INITDATA(BAT_VOLTAGE, ENVSYS_SVOLTS_DC, "Battery voltage"); 204 1.3 macallan INITDATA(BAT_CURRENT, ENVSYS_SAMPS, "Battery current"); 205 1.10 macallan INITDATA(BAT_MAX_CHARGE, ENVSYS_SWATTHOUR, "Battery design cap"); 206 1.10 macallan INITDATA(BAT_CHARGE, ENVSYS_SWATTHOUR, "Battery charge"); 207 1.3 macallan INITDATA(BAT_CHARGING, ENVSYS_BATTERY_CHARGE, "Battery charging"); 208 1.9 macallan INITDATA(BAT_CHARGE_STATE, ENVSYS_BATTERY_CAPACITY, 209 1.9 macallan "Battery charge state"); 210 1.3 macallan INITDATA(BAT_FULL, ENVSYS_INDICATOR, "Battery full"); 211 1.3 macallan #undef INITDATA 212 1.10 macallan 213 1.11 macallan sc->sc_bat_sensor[BAT_CHARGE_STATE].value_cur = 214 1.11 macallan ENVSYS_BATTERY_CAPACITY_NORMAL; 215 1.10 macallan sc->sc_bat_sensor[BAT_CHARGE_STATE].state = ENVSYS_SVALID; 216 1.10 macallan sc->sc_bat_sensor[BAT_CHARGING].value_cur = TRUE; 217 1.10 macallan sc->sc_bat_sensor[BAT_CHARGING].state = ENVSYS_SVALID; 218 1.10 macallan sc->sc_bat_sensor[BAT_CHARGING].value_cur = TRUE; 219 1.10 macallan sc->sc_bat_sensor[BAT_CHARGING].state = ENVSYS_SVALID; 220 1.10 macallan 221 1.13 macallan for (i = 0; i < BAT_NSENSORS; i++) 222 1.13 macallan sc->sc_bat_sensor[i].flags = ENVSYS_FMONNOTSUPP; 223 1.13 macallan 224 1.13 macallan sc->sc_bat_sensor[BAT_CHARGE].flags = 225 1.13 macallan ENVSYS_FMONLIMITS | ENVSYS_FPERCENT | ENVSYS_FVALID_MAX; 226 1.13 macallan sc->sc_bat_sensor[BAT_CHARGE_STATE].flags = ENVSYS_FMONSTCHANGED; 227 1.13 macallan 228 1.3 macallan for (i = 0; i < BAT_NSENSORS; i++) { 229 1.9 macallan if (sysmon_envsys_sensor_attach(sc->sc_bat_sme, 230 1.9 macallan &sc->sc_bat_sensor[i])) { 231 1.9 macallan sysmon_envsys_destroy(sc->sc_bat_sme); 232 1.3 macallan return; 233 1.3 macallan } 234 1.3 macallan } 235 1.3 macallan 236 1.14 macallan sc->sc_low = sc->sc_max_charge * 1000 / 100 * 10; /* 10% */ 237 1.14 macallan sc->sc_warn = sc->sc_max_charge * 1000 / 100 * 20; /* 20% */ 238 1.14 macallan 239 1.14 macallan 240 1.9 macallan sc->sc_bat_sme->sme_name = device_xname(sc->sc_dev); 241 1.9 macallan sc->sc_bat_sme->sme_cookie = sc; 242 1.9 macallan sc->sc_bat_sme->sme_refresh = smartbat_refresh; 243 1.9 macallan sc->sc_bat_sme->sme_class = SME_CLASS_BATTERY; 244 1.13 macallan sc->sc_bat_sme->sme_flags = SME_POLL_ONLY | SME_INIT_REFRESH; 245 1.13 macallan sc->sc_bat_sme->sme_get_limits = smartbat_get_limits; 246 1.3 macallan 247 1.9 macallan if (sysmon_envsys_register(sc->sc_bat_sme)) { 248 1.3 macallan aprint_error("%s: unable to register with sysmon\n", 249 1.8 macallan device_xname(sc->sc_dev)); 250 1.9 macallan sysmon_envsys_destroy(sc->sc_bat_sme); 251 1.3 macallan } 252 1.3 macallan } 253 1.3 macallan 254 1.3 macallan static void 255 1.3 macallan smartbat_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 256 1.3 macallan { 257 1.3 macallan struct smartbat_softc *sc = sme->sme_cookie; 258 1.13 macallan int which = edata->sensor, present, ch; 259 1.3 macallan 260 1.3 macallan smartbat_update(sc, 0); 261 1.4 macallan present = (sc->sc_flags & PMU_PWR_BATT_PRESENT) != 0; 262 1.13 macallan ch = sc->sc_charge * 100 / sc->sc_max_charge; 263 1.3 macallan 264 1.4 macallan if (present) { 265 1.13 macallan edata->state = ENVSYS_SVALID; 266 1.4 macallan switch (which) { 267 1.4 macallan case BAT_PRESENT: 268 1.4 macallan edata->value_cur = present; 269 1.4 macallan break; 270 1.4 macallan case BAT_VOLTAGE: 271 1.4 macallan edata->value_cur = sc->sc_voltage * 1000; 272 1.4 macallan break; 273 1.4 macallan case BAT_CURRENT: 274 1.4 macallan edata->value_cur = sc->sc_draw * 1000; 275 1.4 macallan break; 276 1.4 macallan case BAT_MAX_CHARGE: 277 1.4 macallan edata->value_cur = sc->sc_max_charge * 1000; 278 1.4 macallan break; 279 1.4 macallan case BAT_CHARGE: 280 1.4 macallan edata->value_cur = sc->sc_charge * 1000; 281 1.13 macallan edata->value_max = sc->sc_max_charge * 1000; 282 1.13 macallan if (ch < 6) { 283 1.13 macallan edata->state = ENVSYS_SCRITICAL; 284 1.14 macallan } else if (edata->value_cur < sc->sc_low) { 285 1.13 macallan edata->state = ENVSYS_SCRITUNDER; 286 1.14 macallan } else if (edata->value_cur < sc->sc_warn) { 287 1.13 macallan edata->state = ENVSYS_SWARNUNDER; 288 1.13 macallan } 289 1.4 macallan break; 290 1.4 macallan case BAT_CHARGING: 291 1.4 macallan if ((sc->sc_flags & PMU_PWR_BATT_CHARGING) && 292 1.4 macallan (sc->sc_flags & PMU_PWR_AC_PRESENT)) 293 1.4 macallan edata->value_cur = 1; 294 1.4 macallan else 295 1.4 macallan edata->value_cur = 0; 296 1.10 macallan break; 297 1.10 macallan case BAT_CHARGE_STATE: 298 1.11 macallan { 299 1.14 macallan int chr = sc->sc_charge * 1000; 300 1.14 macallan 301 1.11 macallan if (ch < 6) { 302 1.11 macallan edata->value_cur = 303 1.11 macallan ENVSYS_BATTERY_CAPACITY_CRITICAL; 304 1.14 macallan } else if (chr < sc->sc_low) { 305 1.11 macallan edata->value_cur = 306 1.13 macallan ENVSYS_BATTERY_CAPACITY_LOW; 307 1.14 macallan } else if (chr < sc->sc_warn) { 308 1.11 macallan edata->value_cur = 309 1.13 macallan ENVSYS_BATTERY_CAPACITY_WARNING; 310 1.11 macallan } else { 311 1.11 macallan edata->value_cur = 312 1.11 macallan ENVSYS_BATTERY_CAPACITY_NORMAL; 313 1.11 macallan } 314 1.11 macallan } 315 1.4 macallan break; 316 1.4 macallan case BAT_FULL: 317 1.4 macallan edata->value_cur = (sc->sc_flags & PMU_PWR_BATT_FULL); 318 1.4 macallan break; 319 1.4 macallan } 320 1.4 macallan } else { 321 1.4 macallan /* battery isn't there */ 322 1.4 macallan switch (which) { 323 1.4 macallan case BAT_PRESENT: 324 1.4 macallan edata->value_cur = present; 325 1.4 macallan edata->state = ENVSYS_SVALID; 326 1.4 macallan break; 327 1.11 macallan case BAT_CHARGE_STATE: 328 1.11 macallan /* 329 1.11 macallan * envsys crashes if this isn't a valid value even 330 1.11 macallan * when the sensor itself is invalid 331 1.11 macallan */ 332 1.11 macallan edata->value_cur = ENVSYS_BATTERY_CAPACITY_NORMAL; 333 1.11 macallan edata->state = ENVSYS_SINVALID; 334 1.11 macallan break; 335 1.4 macallan default: 336 1.4 macallan edata->state = ENVSYS_SINVALID; 337 1.3 macallan edata->value_cur = 0; 338 1.4 macallan } 339 1.3 macallan } 340 1.3 macallan } 341 1.3 macallan 342 1.9 macallan static void 343 1.13 macallan smartbat_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 344 1.13 macallan sysmon_envsys_lim_t *limits, uint32_t *props) 345 1.13 macallan { 346 1.13 macallan struct smartbat_softc *sc = sme->sme_cookie; 347 1.13 macallan 348 1.13 macallan if (edata->sensor != BAT_CHARGE) 349 1.13 macallan return; 350 1.13 macallan 351 1.14 macallan limits->sel_critmin = sc->sc_low; 352 1.14 macallan limits->sel_warnmin = sc->sc_warn; 353 1.13 macallan 354 1.13 macallan *props |= PROP_BATTCAP | PROP_BATTWARN | PROP_DRIVER_LIMITS; 355 1.13 macallan } 356 1.13 macallan 357 1.13 macallan static void 358 1.9 macallan smartbat_refresh_ac(struct sysmon_envsys *sme, envsys_data_t *edata) 359 1.9 macallan { 360 1.9 macallan struct smartbat_softc *sc = sme->sme_cookie; 361 1.9 macallan int which = edata->sensor; 362 1.9 macallan 363 1.9 macallan smartbat_update(sc, 0); 364 1.9 macallan switch (which) { 365 1.9 macallan case BAT_AC_PRESENT: 366 1.13 macallan edata->value_cur = 367 1.13 macallan ((sc->sc_flags & PMU_PWR_AC_PRESENT) != 0); 368 1.9 macallan edata->state = ENVSYS_SVALID; 369 1.9 macallan break; 370 1.11 macallan default: 371 1.13 macallan edata->value_cur = 0; 372 1.11 macallan edata->state = ENVSYS_SINVALID; 373 1.9 macallan } 374 1.9 macallan } 375 1.9 macallan 376 1.3 macallan /* 377 1.3 macallan * Thanks to Paul Mackerras and Fabio Riccardi's Linux implementation 378 1.3 macallan * for a clear description of the PMU results. 379 1.3 macallan */ 380 1.3 macallan static int 381 1.3 macallan smartbat_update(struct smartbat_softc *sc, int out) 382 1.3 macallan { 383 1.3 macallan int len; 384 1.3 macallan uint8_t buf[16]; 385 1.14 macallan int8_t *sbuf = (int8_t *)buf; 386 1.3 macallan uint8_t battery_number; 387 1.3 macallan 388 1.3 macallan if (sc->sc_timestamp == time_second) 389 1.3 macallan return 0; 390 1.3 macallan sc->sc_timestamp = time_second; 391 1.3 macallan 392 1.3 macallan /* sc_num starts from 0, but we need to start from 1 */ 393 1.3 macallan battery_number = sc->sc_num + 1; 394 1.3 macallan len = sc->sc_pmu_ops->do_command(sc->sc_pmu_ops->cookie, 395 1.3 macallan PMU_SMART_BATTERY_STATE, 396 1.3 macallan 1, &battery_number, 397 1.3 macallan 16, buf); 398 1.3 macallan 399 1.3 macallan if (len < 0) { 400 1.9 macallan DPRINTF("%s: couldn't get battery data\n", 401 1.9 macallan device_xname(sc->sc_dev)); 402 1.3 macallan /* XXX: the return value is never checked */ 403 1.3 macallan return -1; 404 1.3 macallan } 405 1.3 macallan 406 1.3 macallan /* Now, buf[0] is the command number, which we already know. 407 1.3 macallan That's why all indexes are off by one compared to 408 1.3 macallan pm_battery_info_smart in pm_direct.c. 409 1.3 macallan */ 410 1.3 macallan sc->sc_flags = buf[2]; 411 1.3 macallan 412 1.3 macallan /* XXX: are these all valid for smart batteries? */ 413 1.3 macallan if (out) { 414 1.3 macallan printf(" flags: %x", buf[2]); 415 1.3 macallan if (buf[2] & PMU_PWR_AC_PRESENT) 416 1.3 macallan printf(" AC"); 417 1.3 macallan if (buf[2] & PMU_PWR_BATT_CHARGING) 418 1.3 macallan printf(" charging"); 419 1.3 macallan if (buf[2] & PMU_PWR_BATT_PRESENT) 420 1.3 macallan printf(" present"); 421 1.3 macallan if (buf[2] & PMU_PWR_BATT_FULL) 422 1.3 macallan printf(" full"); 423 1.3 macallan printf("\n"); 424 1.3 macallan } 425 1.3 macallan 426 1.3 macallan switch(buf[1]) { 427 1.3 macallan case 3: 428 1.3 macallan case 4: 429 1.3 macallan sc->sc_charge = buf[3]; 430 1.3 macallan sc->sc_max_charge = buf[4]; 431 1.14 macallan sc->sc_draw = sbuf[5]; 432 1.3 macallan sc->sc_voltage = buf[6]; 433 1.3 macallan break; 434 1.3 macallan case 5: 435 1.3 macallan sc->sc_charge = ((buf[3] << 8) | (buf[4])); 436 1.3 macallan sc->sc_max_charge = ((buf[5] << 8) | (buf[6])); 437 1.14 macallan sc->sc_draw = sbuf[7]; 438 1.3 macallan sc->sc_voltage = ((buf[9] << 8) | (buf[8])); 439 1.3 macallan break; 440 1.3 macallan default: 441 1.3 macallan /* XXX - Error condition */ 442 1.9 macallan DPRINTF("%s: why is buf[1] %x?\n", device_xname(sc->sc_dev), 443 1.9 macallan buf[1]); 444 1.3 macallan sc->sc_charge = 0; 445 1.3 macallan sc->sc_max_charge = 0; 446 1.3 macallan sc->sc_draw = 0; 447 1.3 macallan sc->sc_voltage = 0; 448 1.3 macallan break; 449 1.3 macallan } 450 1.3 macallan 451 1.3 macallan return 1; 452 1.3 macallan } 453 1.3 macallan 454 1.3 macallan static void 455 1.3 macallan smartbat_poll(void *cookie) 456 1.3 macallan { 457 1.3 macallan struct smartbat_softc *sc = cookie; 458 1.3 macallan 459 1.3 macallan smartbat_update(sc, 0); 460 1.3 macallan if ((sc->sc_flags & PMU_PWR_AC_PRESENT) == sc->sc_oflags) 461 1.3 macallan return; 462 1.3 macallan 463 1.3 macallan sc->sc_oflags = sc->sc_flags & PMU_PWR_AC_PRESENT; 464 1.13 macallan sc->sc_ac_sensor[0].value_cur = sc->sc_oflags ? 1 : 0; 465 1.3 macallan sysmon_pswitch_event(&sc->sc_sm_acpower, 466 1.3 macallan sc->sc_oflags ? PSWITCH_EVENT_PRESSED : 467 1.3 macallan PSWITCH_EVENT_RELEASED); 468 1.1 macallan } 469