コード例 #1
0
/*
 * Poll power-management related GPIO inputs, update battery life
 * in softc, and/or control battery charging.
 */
void
zapm_poll(void *v)
{
	struct zapm_softc *sc = v;
	int ac_on;
	int bc_lock;
	int charging;
	int volt;
	int s;

	s = splhigh();

	/* Check positition of battery compartment lock switch. */
	bc_lock = pxa2x0_gpio_get_bit(GPIO_BATT_COVER_C3000) ? 1 : 0;

	/* Stop discharging. */
	if (sc->sc_discharging) {
		sc->sc_discharging = 0;
		volt = zapm_batt_volt();
		ac_on = zapm_ac_on();
		charging = 0;
		DPRINTF(("zapm_poll: discharge off volt %d\n", volt));
	} else {
		ac_on = zapm_ac_on();
		charging = sc->sc_charging;
		volt = sc->sc_batt_volt;
	}

	/* Start or stop charging as necessary. */
	if (ac_on && bc_lock) {
		if (charging) {
			if (zapm_charge_complete(sc)) {
				DPRINTF(("zapm_poll: batt full\n"));
				charging = 0;
				zapm_enable_charging(sc, 0);
			}
		} else if (!zapm_charge_complete(sc)) {
			charging = 1;
			volt = zapm_batt_volt();
			zapm_enable_charging(sc, 1);
			DPRINTF(("zapm_poll: start charging volt %d\n", volt));
		}
	} else {
		if (charging) {
			charging = 0;
			zapm_enable_charging(sc, 0);
			timerclear(&sc->sc_lastbattchk);
			DPRINTF(("zapm_poll: stop charging\n"));
		}
		sc->sc_batt_full = 0;
	}

	/*
	 * Restart charging once in a while.  Discharge a few milliseconds
	 * before updating the voltage in our softc if A/C is connected.
	 */
	if (bc_lock && ratecheck(&sc->sc_lastbattchk, &zapm_battchkrate)) {
		if (sc->sc_suspended) {
			DPRINTF(("zapm_poll: suspended %lu %lu\n",
			    sc->sc_lastbattchk.tv_sec,
			    pxa2x0_rtc_getsecs()));
			if (charging) {
				zapm_enable_charging(sc, 0);
				delay(15000);
				zapm_enable_charging(sc, 1);
				pxa2x0_rtc_setalarm(pxa2x0_rtc_getsecs() +
				    zapm_battchkrate.tv_sec + 1);
			}
		} else if (ac_on && sc->sc_batt_full == 0) {
			DPRINTF(("zapm_poll: discharge on\n"));
			if (charging)
				zapm_enable_charging(sc, 0);
			sc->sc_discharging = 1;
			scoop_discharge_battery(1);
			timeout_add(&sc->sc_poll, DISCHARGE_TIMEOUT);
		} else if (!ac_on) {
			volt = zapm_batt_volt();
			DPRINTF(("zapm_poll: volt %d\n", volt));
		}
	}

	/* Update the cached power state in our softc. */
	if (ac_on != sc->sc_ac_on || charging != sc->sc_charging ||
	    volt != sc->sc_batt_volt) {
		sc->sc_ac_on = ac_on;
		sc->sc_charging = charging;
		sc->sc_batt_volt = volt;
		if (sc->sc_event == APM_NOEVENT)
			sc->sc_event = APM_POWER_CHANGE;
	}

	/* Detect battery low conditions. */
	if (!ac_on) {
		if (zapm_batt_life(volt) < 5)
			sc->sc_event = APM_BATTERY_LOW;
		if (zapm_batt_state(volt) == APM_BATT_CRITICAL)
			sc->sc_event = APM_CRIT_SUSPEND_REQ;
	}

#ifdef APMDEBUG
	if (sc->sc_event != APM_NOEVENT)
		DPRINTF(("zapm_poll: power event %d\n", sc->sc_event));
#endif
	splx(s);
}
コード例 #2
0
ファイル: zapm.c プロジェクト: ryo/netbsd-src
/*
 * Poll power-management related GPIO inputs, update battery life
 * in softc, and/or control battery charging.
 */
static void
zapm_poll1(void *v, int do_suspend)
{
	struct zapm_softc *sc = (struct zapm_softc *)v;
	int ac_state;
	int bc_lock;
	int charging;
	int volt;

	if (!mutex_tryenter(&sc->sc_mtx))
		return;

	ac_state = zapm_get_ac_state(sc);
	bc_lock = zapm_get_battery_compartment_state(sc);

	/* Stop discharging. */
	if (sc->discharging) {
		sc->discharging = 0;
		charging = 0;
		volt = zapm_get_battery_volt();
		DPRINTF(("zapm_poll: discharge off volt %d\n", volt));
	} else {
		charging = sc->battery_state & APM_BATT_FLAG_CHARGING;
		volt = sc->battery_volt;
	}

	/* Start or stop charging as necessary. */
	if (ac_state && bc_lock) {
		int charge_completed = zapm_charge_complete(sc);
		if (charging) {
			if (charge_completed) {
				DPRINTF(("zapm_poll: battery is full\n"));
				charging = 0;
				zapm_set_charging(sc, 0);
			}
		} else if (!charge_completed) {
			charging = APM_BATT_FLAG_CHARGING;
			volt = zapm_get_battery_volt();
			zapm_set_charging(sc, 1);
			DPRINTF(("zapm_poll: start charging volt %d\n", volt));
		}
	} else {
		if (charging) {
			charging = 0;
			zapm_set_charging(sc, 0);
			timerclear(&sc->sc_lastbattchk);
			DPRINTF(("zapm_poll: stop charging\n"));
		}
		sc->battery_full_cnt = 0;
	}

	/*
	 * Restart charging once in a while.  Discharge a few milliseconds
	 * before updating the voltage in our softc if A/C is connected.
	 */
	if (bc_lock && ratecheck(&sc->sc_lastbattchk, &zapm_battchkrate)) {
		if (do_suspend && sc->suspended) {
			/* XXX */
#if 0
			DPRINTF(("zapm_poll: suspended %lu %lu\n",
			    sc->lastbattchk.tv_sec,
			    pxa2x0_rtc_getsecs()));
			if (charging) {
				zapm_set_charging(sc, 0);
				delay(15000);
				zapm_set_charging(sc, 1);
				pxa2x0_rtc_setalarm(pxa2x0_rtc_getsecs() +
				    zapm_battchkrate.tv_sec + 1);
			}
#endif
		} else if (ac_state && sc->battery_full_cnt == 0) {
			DPRINTF(("zapm_poll: discharge on\n"));
			if (charging)
				zapm_set_charging(sc, 0);
			sc->discharging = 1;
			if (ZAURUS_ISC1000 || ZAURUS_ISC3000)
				scoop_discharge_battery(1);
			callout_schedule(&sc->sc_discharge_poll,
			    DISCHARGE_TIMEOUT);
		} else if (!ac_state) {
			volt = zapm_get_battery_volt();
			DPRINTF(("zapm_poll: volt %d\n", volt));
		}
	}

	/* Update the cached power state in our softc. */
	if ((ac_state != sc->ac_state)
	 || (charging != (sc->battery_state & APM_BATT_FLAG_CHARGING))) {
		config_hook_call(CONFIG_HOOK_PMEVENT,
		    CONFIG_HOOK_PMEVENT_AC,
		    (void *)((ac_state == APM_AC_OFF)
		        ? CONFIG_HOOK_AC_OFF
		        : (charging ? CONFIG_HOOK_AC_ON_CHARGE
		                    : CONFIG_HOOK_AC_ON_NOCHARGE)));
	}
	if (volt != sc->battery_volt) {
		sc->battery_volt = volt;
		sc->battery_life = zapm_battery_life(volt);
		config_hook_call(CONFIG_HOOK_PMEVENT,
		    CONFIG_HOOK_PMEVENT_BATTERY,
		    (void *)zapm_battery_state(volt));
	}

	mutex_exit(&sc->sc_mtx);
}