Exemplo n.º 1
0
/*
 * Called after wake-up from suspend with interrupts still disabled,
 * before any powerhooks are done.
 */
int
zapm_resume(struct pxa2x0_apm_softc *pxa_sc)
{
	struct zapm_softc *sc = (struct zapm_softc *)pxa_sc;
	int	a, b;
	u_int	wsrc;
	int	wakeup = 0;

	/* C3000 */
	a = pxa2x0_gpio_get_bit(97) ? 1 : 0;
	b = pxa2x0_gpio_get_bit(96) ? 2 : 0;

	wsrc = pxa2x0_wakeup_status();

	/* Resume only if the lid is not closed. */
	if ((a | b) != 3 && (wsrc & PXA2X0_WAKEUP_POWERON) != 0) {
		int timeout = 100; /* 10 ms */
		/* C3000 */
		while (timeout-- > 0 && pxa2x0_gpio_get_bit(95) != 0) {
			if (timeout == 0) {
				wakeup = 1;
				break;
			}
			delay(100);
		}
	}

	/* Initialize the SSP unit before using the MAX1111 again. */
	zssp_init();

	zapm_poll(sc);

	if (wakeup) {
		/* Resume normal polling. */
		sc->sc_suspended = 0;

		pxa2x0_rtc_setalarm(0);
	} else {
#if 0
		DPRINTF(("zapm_resume: suspended %lu %lu\n",
		    sc->sc_lastbattchk.tv_sec, pxa2x0_rtc_getsecs()));
		pxa2x0_rtc_setalarm(pxa2x0_rtc_getsecs() + 5);
#endif
	}

	return (wakeup);
}
Exemplo n.º 2
0
/*
 * Called before suspending when all powerhooks are done.
 */
void
zapm_suspend(struct pxa2x0_apm_softc *pxa_sc)
{
	struct zapm_softc *sc = (struct zapm_softc *)pxa_sc;

	/* Poll in suspended mode and forget the discharge timeout. */
	sc->sc_suspended = 1;
	timeout_del(&sc->sc_poll);

	/* Make sure charging is enabled and RTC alarm is set. */
	timerclear(&sc->sc_lastbattchk);

	zapm_poll(sc);

#if 0
	pxa2x0_rtc_setalarm(pxa2x0_rtc_getsecs() + 5);
#endif
	pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1);
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
0
/*
 * 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);
}