[BACK]Return to zaurus_apm.c CVS log [TXT][DIR] Up to [local] / sys / arch / zaurus / dev

Annotation of sys/arch/zaurus/dev/zaurus_apm.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: zaurus_apm.c,v 1.13 2006/12/12 23:14:28 dim Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: #include <sys/param.h>
        !            20: #include <sys/systm.h>
        !            21: #include <sys/kernel.h>
        !            22: #include <sys/timeout.h>
        !            23: #include <sys/conf.h>
        !            24: #include <sys/sysctl.h>
        !            25:
        !            26: #include <arm/xscale/pxa2x0reg.h>
        !            27: #include <arm/xscale/pxa2x0var.h>
        !            28: #include <arm/xscale/pxa2x0_apm.h>
        !            29: #include <arm/xscale/pxa2x0_gpio.h>
        !            30:
        !            31: #include <zaurus/dev/zaurus_scoopvar.h>
        !            32: #include <zaurus/dev/zaurus_sspvar.h>
        !            33: void zssp_init(void);  /* XXX */
        !            34:
        !            35: #include <zaurus/dev/zaurus_apm.h>
        !            36:
        !            37: #if defined(APMDEBUG)
        !            38: #define DPRINTF(x)     printf x
        !            39: #else
        !            40: #define        DPRINTF(x)      /**/
        !            41: #endif
        !            42:
        !            43: struct zapm_softc {
        !            44:        struct pxa2x0_apm_softc sc;
        !            45:        struct timeout sc_poll;
        !            46:        struct timeval sc_lastbattchk;
        !            47:        int     sc_suspended;
        !            48:        int     sc_ac_on;
        !            49:        int     sc_charging;
        !            50:        int     sc_discharging;
        !            51:        int     sc_batt_full;
        !            52:        int     sc_batt_volt;
        !            53:        u_int   sc_event;
        !            54: };
        !            55:
        !            56: int    apm_match(struct device *, void *, void *);
        !            57: void   apm_attach(struct device *, struct device *, void *);
        !            58:
        !            59: struct cfattach apm_pxaip_ca = {
        !            60:         sizeof (struct zapm_softc), apm_match, apm_attach
        !            61: };
        !            62: extern struct cfdriver apm_cd;
        !            63:
        !            64: /* MAX1111 command word */
        !            65: #define MAXCTRL_PD0            (1<<0)
        !            66: #define MAXCTRL_PD1            (1<<1)
        !            67: #define MAXCTRL_SGL            (1<<2)
        !            68: #define MAXCTRL_UNI            (1<<3)
        !            69: #define MAXCTRL_SEL_SHIFT      4
        !            70: #define MAXCTRL_STR            (1<<7)
        !            71:
        !            72: /* MAX1111 ADC channels */
        !            73: #define        BATT_THM                2
        !            74: #define        BATT_AD                 4
        !            75: #define JK_VAD                 6
        !            76:
        !            77: /* battery-related GPIO pins */
        !            78: #define GPIO_AC_IN_C3000       115     /* 0=AC connected */
        !            79: #define GPIO_CHRG_CO_C3000     101     /* 1=battery full */
        !            80: #define GPIO_BATT_COVER_C3000  90      /* 0=unlocked */
        !            81:
        !            82: /*
        !            83:  * Battery-specific information
        !            84:  */
        !            85:
        !            86: struct battery_threshold {
        !            87:        int     bt_volt;
        !            88:        int     bt_life;
        !            89:        int     bt_state;
        !            90: };
        !            91:
        !            92: struct battery_info {
        !            93:        int     bi_minutes;             /* 100% life time */
        !            94:        const   struct battery_threshold *bi_thres;
        !            95: };
        !            96:
        !            97: const struct battery_threshold zaurus_battery_life_c3000[] = {
        !            98: #if 0
        !            99:        {224,   125,    APM_BATT_HIGH}, /* XXX unverified */
        !           100: #endif
        !           101:        {194,   100,    APM_BATT_HIGH},
        !           102:        {188,   75,     APM_BATT_HIGH},
        !           103:        {184,   50,     APM_BATT_HIGH},
        !           104:        {180,   25,     APM_BATT_LOW},
        !           105:        {178,   5,      APM_BATT_LOW},
        !           106:        {0,     0,      APM_BATT_CRITICAL},
        !           107: };
        !           108:
        !           109: const struct battery_info zaurus_battery_c3000 = {
        !           110:        180 /* minutes; pessimistic estimate */,
        !           111:        zaurus_battery_life_c3000
        !           112: };
        !           113:
        !           114: const struct battery_info *zaurus_main_battery = &zaurus_battery_c3000;
        !           115:
        !           116: /* Restart charging this many times before accepting BATT_FULL. */
        !           117: #define MIN_BATT_FULL 2
        !           118:
        !           119: /* Discharge 100 ms before reading the voltage if AC is connected. */
        !           120: #define DISCHARGE_TIMEOUT (hz / 10)
        !           121:
        !           122: /* Check battery voltage and "kick charging" every minute. */
        !           123: const  struct timeval zapm_battchkrate = { 60, 0 };
        !           124:
        !           125: /* Prototypes */
        !           126:
        !           127: #if 0
        !           128: void   zapm_shutdown(void *);
        !           129: #endif
        !           130: int    zapm_acintr(void *);
        !           131: int    zapm_bcintr(void *);
        !           132: int    zapm_ac_on(void);
        !           133: int    max1111_adc_value(int);
        !           134: int    max1111_adc_value_avg(int, int);
        !           135: #if 0
        !           136: int    zapm_jkvad_voltage(void);
        !           137: int    zapm_batt_temp(void);
        !           138: #endif
        !           139: int    zapm_batt_volt(void);
        !           140: int    zapm_batt_state(int);
        !           141: int    zapm_batt_life(int);
        !           142: int    zapm_batt_minutes(int);
        !           143: void   zapm_enable_charging(struct zapm_softc *, int);
        !           144: int    zapm_charge_complete(struct zapm_softc *);
        !           145: void   zapm_poll(void *);
        !           146: int    zapm_get_event(struct pxa2x0_apm_softc *, u_int *);
        !           147: void   zapm_power_info(struct pxa2x0_apm_softc *, struct apm_power_info *);
        !           148: void   zapm_suspend(struct pxa2x0_apm_softc *);
        !           149: int    zapm_resume(struct pxa2x0_apm_softc *);
        !           150: void   pxa2x0_setperf(int);
        !           151: int    pxa2x0_cpuspeed(int *);
        !           152:
        !           153:
        !           154: int
        !           155: apm_match(struct device *parent, void *match, void *aux)
        !           156: {
        !           157:        return (1);
        !           158: }
        !           159:
        !           160: void
        !           161: apm_attach(struct device *parent, struct device *self, void *aux)
        !           162: {
        !           163:        struct zapm_softc *sc = (struct zapm_softc *)self;
        !           164:
        !           165:        pxa2x0_gpio_set_function(GPIO_AC_IN_C3000, GPIO_IN);
        !           166:        pxa2x0_gpio_set_function(GPIO_CHRG_CO_C3000, GPIO_IN);
        !           167:        pxa2x0_gpio_set_function(GPIO_BATT_COVER_C3000, GPIO_IN);
        !           168:
        !           169:        (void)pxa2x0_gpio_intr_establish(GPIO_AC_IN_C3000,
        !           170:            IST_EDGE_BOTH, IPL_BIO, zapm_acintr, sc, "apm_ac");
        !           171:        (void)pxa2x0_gpio_intr_establish(GPIO_BATT_COVER_C3000,
        !           172:            IST_EDGE_BOTH, IPL_BIO, zapm_bcintr, sc, "apm_bc");
        !           173:
        !           174:        sc->sc_event = APM_NOEVENT;
        !           175:        sc->sc.sc_get_event = zapm_get_event;
        !           176:        sc->sc.sc_power_info = zapm_power_info;
        !           177:        sc->sc.sc_suspend = zapm_suspend;
        !           178:        sc->sc.sc_resume = zapm_resume;
        !           179:
        !           180:        timeout_set(&sc->sc_poll, &zapm_poll, sc);
        !           181:
        !           182:        /* Get initial battery voltage. */
        !           183:        zapm_enable_charging(sc, 0);
        !           184:        if (zapm_ac_on()) {
        !           185:                /* C3000: discharge 100 ms when AC is on. */
        !           186:                scoop_discharge_battery(1);
        !           187:                delay(100000);
        !           188:        }
        !           189:        sc->sc_batt_volt = zapm_batt_volt();
        !           190:        scoop_discharge_battery(0);
        !           191:
        !           192:        pxa2x0_apm_attach_sub(&sc->sc);
        !           193:
        !           194: #if 0
        !           195:        (void)shutdownhook_establish(zapm_shutdown, NULL);
        !           196: #endif
        !           197:
        !           198:        cpu_setperf = pxa2x0_setperf;
        !           199:        cpu_cpuspeed = pxa2x0_cpuspeed;
        !           200: }
        !           201:
        !           202: #if 0
        !           203: void
        !           204: zapm_shutdown(void *v)
        !           205: {
        !           206:        struct zapm_softc *sc = v;
        !           207:
        !           208:        zapm_enable_charging(sc, 0);
        !           209: }
        !           210: #endif
        !           211:
        !           212: int
        !           213: zapm_acintr(void *v)
        !           214: {
        !           215:        zapm_poll(v);
        !           216:        return (1);
        !           217: }
        !           218:
        !           219: int
        !           220: zapm_bcintr(void *v)
        !           221: {
        !           222:        zapm_poll(v);
        !           223:        return (1);
        !           224: }
        !           225:
        !           226: int
        !           227: zapm_ac_on(void)
        !           228: {
        !           229:        return (!pxa2x0_gpio_get_bit(GPIO_AC_IN_C3000));
        !           230: }
        !           231:
        !           232: int
        !           233: max1111_adc_value(int chan)
        !           234: {
        !           235:
        !           236:        return ((int)zssp_ic_send(ZSSP_IC_MAX1111, MAXCTRL_PD0 |
        !           237:            MAXCTRL_PD1 | MAXCTRL_SGL | MAXCTRL_UNI |
        !           238:            (chan << MAXCTRL_SEL_SHIFT) | MAXCTRL_STR));
        !           239: }
        !           240:
        !           241: /* XXX simplify */
        !           242: int
        !           243: max1111_adc_value_avg(int chan, int pause)
        !           244: {
        !           245:        int val[5];
        !           246:        int i, j, k, x;
        !           247:        int sum = 0;
        !           248:
        !           249:        for (i = 0; i < 5; i++) {
        !           250:                val[i] = max1111_adc_value(chan);
        !           251:                if (i != 4)
        !           252:                        delay(pause * 1000);
        !           253:        }
        !           254:
        !           255:        x = val[0];
        !           256:        j = 0;
        !           257:        for (i = 1; i < 5; i++) {
        !           258:                if (x < val[i]) {
        !           259:                        x = val[i];
        !           260:                        j = i;
        !           261:                }
        !           262:        }
        !           263:
        !           264:        x = val[4];
        !           265:        k = 4;
        !           266:        for (i = 3; i >= 0; i--) {
        !           267:                if (x > val[i]) {
        !           268:                        x = val[i];
        !           269:                        k = i;
        !           270:                }
        !           271:        }
        !           272:
        !           273:        for (i = 0; i < 5; i++) {
        !           274:                if (i == j || i == k)
        !           275:                        continue;
        !           276:                sum += val[i];
        !           277:        }
        !           278:
        !           279:        return (sum / 3);
        !           280: }
        !           281:
        !           282: #if 0
        !           283: /*
        !           284:  * Return the voltage available for charging.  This will be zero,
        !           285:  * unless A/C power is connected.
        !           286:  */
        !           287: int
        !           288: zapm_jkvad_voltage(void)
        !           289: {
        !           290:
        !           291:        return (max1111_adc_value_avg(JK_VAD, 10));
        !           292: }
        !           293:
        !           294: int
        !           295: zapm_batt_temp(void)
        !           296: {
        !           297:        int temp;
        !           298:
        !           299:        scoop_battery_temp_adc(1);
        !           300:        delay(10000);
        !           301:        temp = max1111_adc_value_avg(BATT_THM, 1);
        !           302:        scoop_battery_temp_adc(0);
        !           303:
        !           304:        return (temp);
        !           305: }
        !           306: #endif
        !           307:
        !           308: int
        !           309: zapm_batt_volt(void)
        !           310: {
        !           311:
        !           312:        return (max1111_adc_value_avg(BATT_AD, 10));
        !           313: }
        !           314:
        !           315: int
        !           316: zapm_batt_state(int volt)
        !           317: {
        !           318:        const struct battery_threshold *bthr;
        !           319:        int i;
        !           320:
        !           321:        bthr = zaurus_main_battery->bi_thres;
        !           322:
        !           323:        for (i = 0; bthr[i].bt_volt > 0; i++)
        !           324:                if (bthr[i].bt_volt <= volt)
        !           325:                        break;
        !           326:
        !           327:        return (bthr[i].bt_state);
        !           328: }
        !           329:
        !           330: int
        !           331: zapm_batt_life(int volt)
        !           332: {
        !           333:        const struct battery_threshold *bthr;
        !           334:        int i;
        !           335:
        !           336:        bthr = zaurus_main_battery->bi_thres;
        !           337:
        !           338:        for (i = 0; bthr[i].bt_volt > 0; i++)
        !           339:                if (bthr[i].bt_volt <= volt)
        !           340:                        break;
        !           341:
        !           342:        if (i == 0)
        !           343:                return (bthr[i].bt_life);
        !           344:
        !           345:        return (bthr[i].bt_life +
        !           346:            ((volt - bthr[i].bt_volt) * 100) /
        !           347:            (bthr[i-1].bt_volt - bthr[i].bt_volt) *
        !           348:            (bthr[i-1].bt_life - bthr[i].bt_life) / 100);
        !           349: }
        !           350:
        !           351: int
        !           352: zapm_batt_minutes(int life)
        !           353: {
        !           354:
        !           355:        return (zaurus_main_battery->bi_minutes * life / 100);
        !           356: }
        !           357:
        !           358: void
        !           359: zapm_enable_charging(struct zapm_softc *sc, int enable)
        !           360: {
        !           361:
        !           362:        scoop_discharge_battery(0);
        !           363:        scoop_charge_battery(enable, 0);
        !           364:        scoop_led_set(SCOOP_LED_ORANGE, enable);
        !           365: }
        !           366:
        !           367: /*
        !           368:  * Return non-zero if the charge complete signal indicates that the
        !           369:  * battery is fully charged.  Restart charging to clear this signal.
        !           370:  */
        !           371: int
        !           372: zapm_charge_complete(struct zapm_softc *sc)
        !           373: {
        !           374:
        !           375:        if (sc->sc_charging && sc->sc_batt_full < MIN_BATT_FULL) {
        !           376:                if (pxa2x0_gpio_get_bit(GPIO_CHRG_CO_C3000) != 0) {
        !           377:                        if (++sc->sc_batt_full < MIN_BATT_FULL) {
        !           378:                                DPRINTF(("battery almost full\n"));
        !           379:                                zapm_enable_charging(sc, 0);
        !           380:                                delay(15000);
        !           381:                                zapm_enable_charging(sc, 1);
        !           382:                        }
        !           383:                } else if (sc->sc_batt_full > 0) {
        !           384:                        /* false alarm */
        !           385:                        sc->sc_batt_full = 0;
        !           386:                        zapm_enable_charging(sc, 0);
        !           387:                        delay(15000);
        !           388:                        zapm_enable_charging(sc, 1);
        !           389:                }
        !           390:        }
        !           391:
        !           392:        return (sc->sc_batt_full >= MIN_BATT_FULL);
        !           393: }
        !           394:
        !           395: /*
        !           396:  * Poll power-management related GPIO inputs, update battery life
        !           397:  * in softc, and/or control battery charging.
        !           398:  */
        !           399: void
        !           400: zapm_poll(void *v)
        !           401: {
        !           402:        struct zapm_softc *sc = v;
        !           403:        int ac_on;
        !           404:        int bc_lock;
        !           405:        int charging;
        !           406:        int volt;
        !           407:        int s;
        !           408:
        !           409:        s = splhigh();
        !           410:
        !           411:        /* Check positition of battery compartment lock switch. */
        !           412:        bc_lock = pxa2x0_gpio_get_bit(GPIO_BATT_COVER_C3000) ? 1 : 0;
        !           413:
        !           414:        /* Stop discharging. */
        !           415:        if (sc->sc_discharging) {
        !           416:                sc->sc_discharging = 0;
        !           417:                volt = zapm_batt_volt();
        !           418:                ac_on = zapm_ac_on();
        !           419:                charging = 0;
        !           420:                DPRINTF(("zapm_poll: discharge off volt %d\n", volt));
        !           421:        } else {
        !           422:                ac_on = zapm_ac_on();
        !           423:                charging = sc->sc_charging;
        !           424:                volt = sc->sc_batt_volt;
        !           425:        }
        !           426:
        !           427:        /* Start or stop charging as necessary. */
        !           428:        if (ac_on && bc_lock) {
        !           429:                if (charging) {
        !           430:                        if (zapm_charge_complete(sc)) {
        !           431:                                DPRINTF(("zapm_poll: batt full\n"));
        !           432:                                charging = 0;
        !           433:                                zapm_enable_charging(sc, 0);
        !           434:                        }
        !           435:                } else if (!zapm_charge_complete(sc)) {
        !           436:                        charging = 1;
        !           437:                        volt = zapm_batt_volt();
        !           438:                        zapm_enable_charging(sc, 1);
        !           439:                        DPRINTF(("zapm_poll: start charging volt %d\n", volt));
        !           440:                }
        !           441:        } else {
        !           442:                if (charging) {
        !           443:                        charging = 0;
        !           444:                        zapm_enable_charging(sc, 0);
        !           445:                        timerclear(&sc->sc_lastbattchk);
        !           446:                        DPRINTF(("zapm_poll: stop charging\n"));
        !           447:                }
        !           448:                sc->sc_batt_full = 0;
        !           449:        }
        !           450:
        !           451:        /*
        !           452:         * Restart charging once in a while.  Discharge a few milliseconds
        !           453:         * before updating the voltage in our softc if A/C is connected.
        !           454:         */
        !           455:        if (bc_lock && ratecheck(&sc->sc_lastbattchk, &zapm_battchkrate)) {
        !           456:                if (sc->sc_suspended) {
        !           457:                        DPRINTF(("zapm_poll: suspended %lu %lu\n",
        !           458:                            sc->sc_lastbattchk.tv_sec,
        !           459:                            pxa2x0_rtc_getsecs()));
        !           460:                        if (charging) {
        !           461:                                zapm_enable_charging(sc, 0);
        !           462:                                delay(15000);
        !           463:                                zapm_enable_charging(sc, 1);
        !           464:                                pxa2x0_rtc_setalarm(pxa2x0_rtc_getsecs() +
        !           465:                                    zapm_battchkrate.tv_sec + 1);
        !           466:                        }
        !           467:                } else if (ac_on && sc->sc_batt_full == 0) {
        !           468:                        DPRINTF(("zapm_poll: discharge on\n"));
        !           469:                        if (charging)
        !           470:                                zapm_enable_charging(sc, 0);
        !           471:                        sc->sc_discharging = 1;
        !           472:                        scoop_discharge_battery(1);
        !           473:                        timeout_add(&sc->sc_poll, DISCHARGE_TIMEOUT);
        !           474:                } else if (!ac_on) {
        !           475:                        volt = zapm_batt_volt();
        !           476:                        DPRINTF(("zapm_poll: volt %d\n", volt));
        !           477:                }
        !           478:        }
        !           479:
        !           480:        /* Update the cached power state in our softc. */
        !           481:        if (ac_on != sc->sc_ac_on || charging != sc->sc_charging ||
        !           482:            volt != sc->sc_batt_volt) {
        !           483:                sc->sc_ac_on = ac_on;
        !           484:                sc->sc_charging = charging;
        !           485:                sc->sc_batt_volt = volt;
        !           486:                if (sc->sc_event == APM_NOEVENT)
        !           487:                        sc->sc_event = APM_POWER_CHANGE;
        !           488:        }
        !           489:
        !           490:        /* Detect battery low conditions. */
        !           491:        if (!ac_on) {
        !           492:                if (zapm_batt_life(volt) < 5)
        !           493:                        sc->sc_event = APM_BATTERY_LOW;
        !           494:                if (zapm_batt_state(volt) == APM_BATT_CRITICAL)
        !           495:                        sc->sc_event = APM_CRIT_SUSPEND_REQ;
        !           496:        }
        !           497:
        !           498: #ifdef APMDEBUG
        !           499:        if (sc->sc_event != APM_NOEVENT)
        !           500:                DPRINTF(("zapm_poll: power event %d\n", sc->sc_event));
        !           501: #endif
        !           502:        splx(s);
        !           503: }
        !           504:
        !           505: /*
        !           506:  * apm_thread() calls this routine approximately once per second.
        !           507:  */
        !           508: int
        !           509: zapm_get_event(struct pxa2x0_apm_softc *pxa_sc, u_int *typep)
        !           510: {
        !           511:        struct zapm_softc *sc = (struct zapm_softc *)pxa_sc;
        !           512:        int s;
        !           513:
        !           514:        s = splsoftclock();
        !           515:
        !           516:        /* Don't interfere with discharging. */
        !           517:        if (sc->sc_discharging)
        !           518:                *typep = sc->sc_event;
        !           519:        else if (sc->sc_event == APM_NOEVENT) {
        !           520:                zapm_poll(sc);
        !           521:                *typep = sc->sc_event;
        !           522:        }
        !           523:        sc->sc_event = APM_NOEVENT;
        !           524:
        !           525:        splx(s);
        !           526:        return (*typep == APM_NOEVENT);
        !           527: }
        !           528:
        !           529: /*
        !           530:  * Return power status to the generic APM driver.
        !           531:  */
        !           532: void
        !           533: zapm_power_info(struct pxa2x0_apm_softc *pxa_sc, struct apm_power_info *power)
        !           534: {
        !           535:        struct zapm_softc *sc = (struct zapm_softc *)pxa_sc;
        !           536:        int s;
        !           537:        int ac_on;
        !           538:        int volt;
        !           539:        int charging;
        !           540:
        !           541:        s = splsoftclock();
        !           542:        ac_on = sc->sc_ac_on;
        !           543:        volt = sc->sc_batt_volt;
        !           544:        charging = sc->sc_charging;
        !           545:        splx(s);
        !           546:
        !           547:        power->ac_state = ac_on ? APM_AC_ON : APM_AC_OFF;
        !           548:        if (charging)
        !           549:                power->battery_state = APM_BATT_CHARGING;
        !           550:        else
        !           551:                power->battery_state = zapm_batt_state(volt);
        !           552:
        !           553:        power->battery_life = zapm_batt_life(volt);
        !           554:        power->minutes_left = zapm_batt_minutes(power->battery_life);
        !           555: }
        !           556:
        !           557: /*
        !           558:  * Called before suspending when all powerhooks are done.
        !           559:  */
        !           560: void
        !           561: zapm_suspend(struct pxa2x0_apm_softc *pxa_sc)
        !           562: {
        !           563:        struct zapm_softc *sc = (struct zapm_softc *)pxa_sc;
        !           564:
        !           565:        /* Poll in suspended mode and forget the discharge timeout. */
        !           566:        sc->sc_suspended = 1;
        !           567:        timeout_del(&sc->sc_poll);
        !           568:
        !           569:        /* Make sure charging is enabled and RTC alarm is set. */
        !           570:        timerclear(&sc->sc_lastbattchk);
        !           571:
        !           572:        zapm_poll(sc);
        !           573:
        !           574: #if 0
        !           575:        pxa2x0_rtc_setalarm(pxa2x0_rtc_getsecs() + 5);
        !           576: #endif
        !           577:        pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1);
        !           578: }
        !           579:
        !           580: /*
        !           581:  * Called after wake-up from suspend with interrupts still disabled,
        !           582:  * before any powerhooks are done.
        !           583:  */
        !           584: int
        !           585: zapm_resume(struct pxa2x0_apm_softc *pxa_sc)
        !           586: {
        !           587:        struct zapm_softc *sc = (struct zapm_softc *)pxa_sc;
        !           588:        int     a, b;
        !           589:        u_int   wsrc;
        !           590:        int     wakeup = 0;
        !           591:
        !           592:        /* C3000 */
        !           593:        a = pxa2x0_gpio_get_bit(97) ? 1 : 0;
        !           594:        b = pxa2x0_gpio_get_bit(96) ? 2 : 0;
        !           595:
        !           596:        wsrc = pxa2x0_wakeup_status();
        !           597:
        !           598:        /* Resume only if the lid is not closed. */
        !           599:        if ((a | b) != 3 && (wsrc & PXA2X0_WAKEUP_POWERON) != 0) {
        !           600:                int timeout = 100; /* 10 ms */
        !           601:                /* C3000 */
        !           602:                while (timeout-- > 0 && pxa2x0_gpio_get_bit(95) != 0) {
        !           603:                        if (timeout == 0) {
        !           604:                                wakeup = 1;
        !           605:                                break;
        !           606:                        }
        !           607:                        delay(100);
        !           608:                }
        !           609:        }
        !           610:
        !           611:        /* Initialize the SSP unit before using the MAX1111 again. */
        !           612:        zssp_init();
        !           613:
        !           614:        zapm_poll(sc);
        !           615:
        !           616:        if (wakeup) {
        !           617:                /* Resume normal polling. */
        !           618:                sc->sc_suspended = 0;
        !           619:
        !           620:                pxa2x0_rtc_setalarm(0);
        !           621:        } else {
        !           622: #if 0
        !           623:                DPRINTF(("zapm_resume: suspended %lu %lu\n",
        !           624:                    sc->sc_lastbattchk.tv_sec, pxa2x0_rtc_getsecs()));
        !           625:                pxa2x0_rtc_setalarm(pxa2x0_rtc_getsecs() + 5);
        !           626: #endif
        !           627:        }
        !           628:
        !           629:        return (wakeup);
        !           630: }
        !           631:
        !           632: void
        !           633: zapm_poweroff(void)
        !           634: {
        !           635:        struct pxa2x0_apm_softc *sc;
        !           636:
        !           637:        KASSERT(apm_cd.cd_ndevs > 0 && apm_cd.cd_devs[0] != NULL);
        !           638:        sc = apm_cd.cd_devs[0];
        !           639:
        !           640:        dopowerhooks(PWR_SUSPEND);
        !           641:
        !           642:        /* XXX enable charging during suspend */
        !           643:
        !           644:        /* XXX keep power LED state during suspend */
        !           645:
        !           646:        /* XXX do the same thing for GPIO 43 (BTTXD) */
        !           647:
        !           648:        /* XXX scoop power down */
        !           649:
        !           650:        /* XXX set PGSRn and GPDRn */
        !           651:
        !           652:        pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1);
        !           653:
        !           654:        do {
        !           655:                pxa2x0_apm_sleep(sc);
        !           656:        }
        !           657:        while (!zapm_resume(sc));
        !           658:
        !           659:        zapm_restart();
        !           660:
        !           661:        /* NOTREACHED */
        !           662:        dopowerhooks(PWR_RESUME);
        !           663: }
        !           664:
        !           665: /*
        !           666:  * Do a GPIO reset, immediately causing the processor to begin the normal
        !           667:  * boot sequence.  See 2.7 Reset in the PXA27x Developer's Manual for the
        !           668:  * summary of effects of this kind of reset.
        !           669:  */
        !           670: void
        !           671: zapm_restart(void)
        !           672: {
        !           673:        if (apm_cd.cd_ndevs > 0 && apm_cd.cd_devs[0] != NULL) {
        !           674:                struct pxa2x0_apm_softc *sc = apm_cd.cd_devs[0];
        !           675:                int rv;
        !           676:
        !           677:                /*
        !           678:                 * Reduce the ROM Delay Next Access and ROM Delay First
        !           679:                 * Access times for synchronous flash connected to nCS1.
        !           680:                 */
        !           681:                rv = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh,
        !           682:                    MEMCTL_MSC0);
        !           683:                if ((rv & 0xffff0000) == 0x7ff00000)
        !           684:                        bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh,
        !           685:                            MEMCTL_MSC0, (rv & 0xffff) | 0x7ee00000);
        !           686:        }
        !           687:
        !           688:        /* External reset circuit presumably asserts nRESET_GPIO. */
        !           689:        pxa2x0_gpio_set_function(89, GPIO_OUT | GPIO_SET);
        !           690:        delay(1000000);
        !           691: }

CVSweb