[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

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