[BACK]Return to pxa2x0_apm.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / xscale

Annotation of sys/arch/arm/xscale/pxa2x0_apm.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pxa2x0_apm.c,v 1.28 2007/03/29 18:42:38 uwe Exp $     */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 2001 Alexander Guy.  All rights reserved.
        !             5:  * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved.
        !             6:  * Copyright (c) 1995 John T. Kohl.  All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by the University of
        !            19:  *     California, Berkeley and its contributors.
        !            20:  * 4. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  */
        !            37:
        !            38: #include <sys/param.h>
        !            39: #include <sys/systm.h>
        !            40: #include <sys/kernel.h>
        !            41: #include <sys/kthread.h>
        !            42: #include <sys/lock.h>
        !            43: #include <sys/mount.h>         /* for vfs_syncwait() */
        !            44: #include <sys/proc.h>
        !            45: #include <sys/device.h>
        !            46: #include <sys/fcntl.h>
        !            47: #include <sys/ioctl.h>
        !            48: #include <sys/event.h>
        !            49:
        !            50: #include <machine/conf.h>
        !            51: #include <machine/cpu.h>
        !            52: #include <machine/apmvar.h>
        !            53:
        !            54: #include <arm/xscale/pxa2x0reg.h>
        !            55: #include <arm/xscale/pxa2x0var.h>
        !            56: #include <arm/xscale/pxa2x0_apm.h>
        !            57: #include <arm/xscale/pxa2x0_gpio.h>
        !            58:
        !            59: #if defined(APMDEBUG)
        !            60: #define DPRINTF(x)     printf x
        !            61: #else
        !            62: #define        DPRINTF(x)      /**/
        !            63: #endif
        !            64:
        !            65: #define APM_LOCK(sc)    lockmgr(&(sc)->sc_lock, LK_EXCLUSIVE, NULL)
        !            66: #define APM_UNLOCK(sc)  lockmgr(&(sc)->sc_lock, LK_RELEASE, NULL)
        !            67:
        !            68: struct cfdriver apm_cd = {
        !            69:        NULL, "apm", DV_DULL
        !            70: };
        !            71:
        !            72: #define        APMUNIT(dev)    (minor(dev)&0xf0)
        !            73: #define        APMDEV(dev)     (minor(dev)&0x0f)
        !            74: #define APMDEV_NORMAL  0
        !            75: #define APMDEV_CTL     8
        !            76:
        !            77: int    apm_userstandbys;
        !            78: int    apm_suspends;
        !            79: int    apm_battlow;
        !            80:
        !            81: /* battery percentage at which we get verbose in our warnings.  This
        !            82:    value can be changed using sysctl(8), value machdep.apmwarn.
        !            83:    Setting it to zero kills all warnings */
        !            84: int    cpu_apmwarn = 10;
        !            85:
        !            86: void   apm_power_print(struct pxa2x0_apm_softc *, struct apm_power_info *);
        !            87: void   apm_power_info(struct pxa2x0_apm_softc *, struct apm_power_info *);
        !            88: void   apm_suspend(struct pxa2x0_apm_softc *);
        !            89: void   apm_resume(struct pxa2x0_apm_softc *);
        !            90: int    apm_get_event(struct pxa2x0_apm_softc *, u_int *);
        !            91: int    apm_handle_event(struct pxa2x0_apm_softc *, u_int);
        !            92: void   apm_thread_create(void *);
        !            93: void   apm_thread(void *);
        !            94:
        !            95: extern int perflevel;
        !            96: int    freq;
        !            97: void   pxa2x0_setperf(int speed);
        !            98: int    pxa2x0_cpuspeed(int *speed);
        !            99:
        !           100: int    apm_record_event(struct pxa2x0_apm_softc *, u_int);
        !           101: void   filt_apmrdetach(struct knote *kn);
        !           102: int    filt_apmread(struct knote *kn, long hint);
        !           103: int    apmkqfilter(dev_t dev, struct knote *kn);
        !           104:
        !           105: struct filterops apmread_filtops =
        !           106:        { 1, NULL, filt_apmrdetach, filt_apmread};
        !           107:
        !           108: /*
        !           109:  * Flags to control kernel display
        !           110:  *     SCFLAG_NOPRINT:         do not output APM power messages due to
        !           111:  *                             a power change event.
        !           112:  *
        !           113:  *     SCFLAG_PCTPRINT:        do not output APM power messages due to
        !           114:  *                             to a power change event unless the battery
        !           115:  *                             percentage changes.
        !           116:  */
        !           117:
        !           118: #define SCFLAG_NOPRINT 0x0008000
        !           119: #define SCFLAG_PCTPRINT        0x0004000
        !           120: #define SCFLAG_PRINT   (SCFLAG_NOPRINT|SCFLAG_PCTPRINT)
        !           121:
        !           122: #define        SCFLAG_OREAD    (1 << 0)
        !           123: #define        SCFLAG_OWRITE   (1 << 1)
        !           124: #define        SCFLAG_OPEN     (SCFLAG_OREAD|SCFLAG_OWRITE)
        !           125:
        !           126: /* This structure must be kept in sync with pxa2x0_apm_asm.S. */
        !           127: struct pxa2x0_memcfg {
        !           128:        /* SDRAM refresh */
        !           129:        u_int32_t mdrefr_high;          /* 0x00 */
        !           130:        u_int32_t mdrefr_low;           /* 0x04 */
        !           131:        u_int32_t mdrefr_low2;          /* 0x08 */
        !           132:        /* Synchronous, static, or VLIO interfaces */
        !           133:        u_int32_t msc_high[3];          /* 0x0c */
        !           134:        u_int32_t msc_low[3];           /* 0x18 */
        !           135:        /* XXX move up */
        !           136:        u_int32_t mdrefr_91;            /* 0x24 */
        !           137: };
        !           138:
        !           139: /* XXX */
        !           140: #define MDREFR_C3000   (MDREFR_K0DB2 | MDREFR_E1PIN | MDREFR_K1RUN | \
        !           141:                         MDREFR_K1DB2 | MDREFR_K2DB2 | MDREFR_APD)
        !           142: #define MSC0_HIGH \
        !           143:                ( 7 << MSC_RRR_SHIFT << 16) | \
        !           144:                (15 << MSC_RDN_SHIFT << 16) | \
        !           145:                (15 << MSC_RDF_SHIFT << 16) | \
        !           146:                (MSC_RT_NONBURST     << 16) | \
        !           147:                ( 2 << MSC_RRR_SHIFT)       | \
        !           148:                (13 << MSC_RDN_SHIFT)       | \
        !           149:                (13 << MSC_RDF_SHIFT)       | \
        !           150:                MSC_RBW /* PXA271 */        | \
        !           151:                MSC_RT_NONBURST
        !           152: #define MSC1_HIGH \
        !           153:                ( 7 << MSC_RRR_SHIFT << 16) | \
        !           154:                (15 << MSC_RDN_SHIFT << 16) | \
        !           155:                (15 << MSC_RDF_SHIFT << 16) | \
        !           156:                (MSC_RT_VLIO         << 16) | \
        !           157:                ( 3 << MSC_RRR_SHIFT)       | \
        !           158:                ( 4 << MSC_RDN_SHIFT)       | \
        !           159:                (13 << MSC_RDF_SHIFT)       | \
        !           160:                MSC_RT_VLIO
        !           161: #define MSC2_HIGH \
        !           162:                ( 7 << MSC_RRR_SHIFT << 16) | \
        !           163:                (15 << MSC_RDN_SHIFT << 16) | \
        !           164:                (15 << MSC_RDF_SHIFT << 16) | \
        !           165:                (MSC_RT_NONBURST     << 16) | \
        !           166:                ( 3 << MSC_RRR_SHIFT)       | \
        !           167:                ( 4 << MSC_RDN_SHIFT)       | \
        !           168:                (13 << MSC_RDF_SHIFT)       | \
        !           169:                MSC_RT_VLIO
        !           170: #define MSC0_LOW \
        !           171:                ( 7 << MSC_RRR_SHIFT << 16) | \
        !           172:                (15 << MSC_RDN_SHIFT << 16) | \
        !           173:                (15 << MSC_RDF_SHIFT << 16) | \
        !           174:                (MSC_RT_NONBURST     << 16) | \
        !           175:                ( 1 << MSC_RRR_SHIFT)       | \
        !           176:                ( 8 << MSC_RDN_SHIFT)       | \
        !           177:                ( 8 << MSC_RDF_SHIFT)       | \
        !           178:                MSC_RBW /* PXA271 */        | \
        !           179:                MSC_RT_NONBURST
        !           180: #define MSC1_LOW \
        !           181:                ( 7 << MSC_RRR_SHIFT << 16) | \
        !           182:                (15 << MSC_RDN_SHIFT << 16) | \
        !           183:                (15 << MSC_RDF_SHIFT << 16) | \
        !           184:                (MSC_RT_VLIO         << 16) | \
        !           185:                ( 1 << MSC_RRR_SHIFT)       | \
        !           186:                ( 2 << MSC_RDN_SHIFT)       | \
        !           187:                ( 6 << MSC_RDF_SHIFT)       | \
        !           188:                MSC_RT_VLIO
        !           189: #define MSC2_LOW \
        !           190:                ( 7 << MSC_RRR_SHIFT << 16) | \
        !           191:                (15 << MSC_RDN_SHIFT << 16) | \
        !           192:                (15 << MSC_RDF_SHIFT << 16) | \
        !           193:                (MSC_RT_NONBURST     << 16) | \
        !           194:                ( 1 << MSC_RRR_SHIFT)       | \
        !           195:                ( 2 << MSC_RDN_SHIFT)       | \
        !           196:                ( 6 << MSC_RDF_SHIFT)       | \
        !           197:                MSC_RT_VLIO
        !           198: struct pxa2x0_memcfg pxa2x0_memcfg = {
        !           199:        (MDREFR_C3000 | 0x030),
        !           200:        (MDREFR_C3000 | 0x00b),
        !           201:        (MDREFR_C3000 | 0x017),
        !           202:        { MSC0_HIGH, MSC1_HIGH, MSC2_HIGH },
        !           203:        { MSC1_LOW, MSC1_LOW, MSC2_LOW },
        !           204:        (MDREFR_C3000 | 0x013)
        !           205: };
        !           206:
        !           207: #define PI2C_RETRY_COUNT       10
        !           208: /* XXX varies depending on voltage regulator IC. */
        !           209: #define PI2C_VOLTAGE_LOW       0x13    /* 1.00V */
        !           210: #define PI2C_VOLTAGE_HIGH      0x1a    /* 1.35V */
        !           211:
        !           212: void   pxa2x0_pi2c_open(bus_space_tag_t, bus_space_handle_t);
        !           213: void   pxa2x0_pi2c_close(bus_space_tag_t, bus_space_handle_t);
        !           214: int    pxa2x0_pi2c_read(bus_space_tag_t, bus_space_handle_t, u_char, u_char *);
        !           215: int    pxa2x0_pi2c_write(bus_space_tag_t, bus_space_handle_t, u_char, u_char);
        !           216: int    pxa2x0_pi2c_getvoltage(bus_space_tag_t, bus_space_handle_t, u_char *);
        !           217: int    pxa2x0_pi2c_setvoltage(bus_space_tag_t, bus_space_handle_t, u_char);
        !           218: #if 0
        !           219: void   pxa2x0_pi2c_print(struct pxa2x0_apm_softc *);
        !           220: #endif
        !           221:
        !           222: /* XXX used in pxa2x0_apm_asm.S */
        !           223: bus_space_handle_t pxa2x0_gpio_ioh;
        !           224: bus_space_handle_t pxa2x0_clkman_ioh;
        !           225: bus_space_handle_t pxa2x0_memctl_ioh;
        !           226:
        !           227: /* pxa2x0_apm_asm.S */
        !           228: void   pxa27x_run_mode(void);
        !           229: void   pxa27x_fastbus_run_mode(int, u_int32_t);
        !           230: void   pxa27x_frequency_change(int, int, struct pxa2x0_memcfg *);
        !           231: void   pxa2x0_cpu_suspend(void);
        !           232: void   pxa2x0_cpu_resume(void);
        !           233: void   pxa27x_cpu_speed_high(void);
        !           234: void   pxa27x_cpu_speed_low(void);
        !           235: void   pxa27x_cpu_speed_91(void);
        !           236: void   pxa27x_cpu_speed_208(void);
        !           237:
        !           238: void
        !           239: apm_power_print(struct pxa2x0_apm_softc *sc, struct apm_power_info *powerp)
        !           240: {
        !           241:
        !           242:        if (powerp->battery_life != APM_BATT_LIFE_UNKNOWN)
        !           243:                printf("%s: battery life expectancy %d%%\n",
        !           244:                    sc->sc_dev.dv_xname, powerp->battery_life);
        !           245:
        !           246:        printf("%s: AC ", sc->sc_dev.dv_xname);
        !           247:        switch (powerp->ac_state) {
        !           248:        case APM_AC_OFF:
        !           249:                printf("off,");
        !           250:                break;
        !           251:        case APM_AC_ON:
        !           252:                printf("on,");
        !           253:                break;
        !           254:        case APM_AC_BACKUP:
        !           255:                printf("backup power,");
        !           256:                break;
        !           257:        default:
        !           258:        case APM_AC_UNKNOWN:
        !           259:                printf("unknown,");
        !           260:                break;
        !           261:        }
        !           262:
        !           263:        printf(" battery is ");
        !           264:        switch (powerp->battery_state) {
        !           265:        case APM_BATT_HIGH:
        !           266:                printf("high");
        !           267:                break;
        !           268:        case APM_BATT_LOW:
        !           269:                printf("low");
        !           270:                break;
        !           271:        case APM_BATT_CRITICAL:
        !           272:                printf("CRITICAL");
        !           273:                break;
        !           274:        case APM_BATT_CHARGING:
        !           275:                printf("charging");
        !           276:                break;
        !           277:        case APM_BATT_UNKNOWN:
        !           278:                printf("unknown");
        !           279:                break;
        !           280:        default:
        !           281:                printf("undecoded (%x)", powerp->battery_state);
        !           282:                break;
        !           283:        }
        !           284:
        !           285:        printf("\n");
        !           286: }
        !           287:
        !           288: void
        !           289: apm_power_info(struct pxa2x0_apm_softc *sc,
        !           290:     struct apm_power_info *power)
        !           291: {
        !           292:
        !           293:        power->ac_state = APM_AC_UNKNOWN;
        !           294:        power->battery_state = APM_BATT_UNKNOWN;
        !           295:        power->battery_life = 0 /* APM_BATT_LIFE_UNKNOWN */;
        !           296:        power->minutes_left = 0;
        !           297:
        !           298:        if (sc->sc_power_info != NULL)
        !           299:                sc->sc_power_info(sc, power);
        !           300: }
        !           301:
        !           302: void
        !           303: apm_suspend(struct pxa2x0_apm_softc *sc)
        !           304: {
        !           305:
        !           306:        resettodr();
        !           307:
        !           308:        dopowerhooks(PWR_SUSPEND);
        !           309:
        !           310:        if (cold)
        !           311:                vfs_syncwait(0);
        !           312:
        !           313:        if (sc->sc_suspend == NULL)
        !           314:                pxa2x0_wakeup_config(PXA2X0_WAKEUP_ALL, 1);
        !           315:        else
        !           316:                sc->sc_suspend(sc);
        !           317:
        !           318:        pxa2x0_apm_sleep(sc);
        !           319: }
        !           320:
        !           321: void
        !           322: apm_resume(struct pxa2x0_apm_softc *sc)
        !           323: {
        !           324:
        !           325:        dopowerhooks(PWR_RESUME);
        !           326:
        !           327:        inittodr(0);
        !           328:
        !           329:        /*
        !           330:         * Clear the OTG Peripheral hold after running the pxaudc and pxaohci
        !           331:         * powerhooks to re-enable their operation. See 3.8.1.2
        !           332:         */
        !           333:        /* XXX ifdef NPXAUDC > 0 */
        !           334:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSSR, PSSR_OTGPH);
        !           335: }
        !           336:
        !           337: int
        !           338: apm_get_event(struct pxa2x0_apm_softc *sc, u_int *typep)
        !           339: {
        !           340:
        !           341:        if (sc->sc_get_event != NULL)
        !           342:                return (sc->sc_get_event(sc, typep));
        !           343:
        !           344:        *typep = APM_NOEVENT;
        !           345:        return (1);
        !           346: }
        !           347:
        !           348: int
        !           349: apm_handle_event(struct pxa2x0_apm_softc *sc, u_int type)
        !           350: {
        !           351:        struct  apm_power_info power;
        !           352:        int     ret = 0;
        !           353:
        !           354:        switch (type) {
        !           355:        case APM_NOEVENT:
        !           356:                ret = 1;
        !           357:                break;
        !           358:        case APM_CRIT_SUSPEND_REQ:
        !           359:                DPRINTF(("suspend required immediately\n"));
        !           360: #if 0
        !           361:                /* XXX apmd would make us suspend again after resume. */
        !           362:                (void)apm_record_event(sc, type);
        !           363: #endif
        !           364:                /*
        !           365:                 * We ignore APM_CRIT_RESUME and just suspend here as usual
        !           366:                 * to simplify the actual apm_get_event() implementation.
        !           367:                 */
        !           368:                apm_suspends++;
        !           369:                ret = 1;
        !           370:                break;
        !           371:        case APM_USER_SUSPEND_REQ:
        !           372:        case APM_SUSPEND_REQ:
        !           373:                DPRINTF(("suspend requested\n"));
        !           374:                if (apm_record_event(sc, type)) {
        !           375:                        DPRINTF(("suspend ourselves\n"));
        !           376:                        apm_suspends++;
        !           377:                }
        !           378:                break;
        !           379:        case APM_POWER_CHANGE:
        !           380:                DPRINTF(("power status change\n"));
        !           381:                apm_power_info(sc, &power);
        !           382:                if (power.battery_life != APM_BATT_LIFE_UNKNOWN &&
        !           383:                    power.battery_life < cpu_apmwarn &&
        !           384:                    (sc->sc_flags & SCFLAG_PRINT) != SCFLAG_NOPRINT &&
        !           385:                    ((sc->sc_flags & SCFLAG_PRINT) != SCFLAG_PCTPRINT ||
        !           386:                    sc->sc_batt_life != power.battery_life)) {
        !           387:                        sc->sc_batt_life = power.battery_life;
        !           388:                        apm_power_print(sc, &power);
        !           389:                }
        !           390:                apm_record_event(sc, type);
        !           391:                break;
        !           392:        case APM_BATTERY_LOW:
        !           393:                DPRINTF(("Battery low!\n"));
        !           394:                apm_battlow++;
        !           395:                apm_record_event(sc, type);
        !           396:                break;
        !           397:        default:
        !           398:                DPRINTF(("apm_handle_event: unsupported event, code %d\n",
        !           399:                    type));
        !           400:        }
        !           401:
        !           402:        return (ret);
        !           403: }
        !           404:
        !           405: void
        !           406: apm_thread_create(void *v)
        !           407: {
        !           408:        struct pxa2x0_apm_softc *sc = v;
        !           409:
        !           410:        if (kthread_create(apm_thread, sc, &sc->sc_thread,
        !           411:            "%s", sc->sc_dev.dv_xname)) {
        !           412:                /* apm_disconnect(sc); */
        !           413:                printf("%s: failed to create kernel thread, disabled",
        !           414:                    sc->sc_dev.dv_xname);
        !           415:        }
        !           416: }
        !           417:
        !           418: void
        !           419: apm_thread(void *v)
        !           420: {
        !           421:        struct pxa2x0_apm_softc *sc = v;
        !           422:        u_int   type;
        !           423:
        !           424:        for (;;) {
        !           425:                APM_LOCK(sc);
        !           426:
        !           427:                while (1) {
        !           428:                        if (apm_get_event(sc, &type) != 0)
        !           429:                                break;
        !           430:                        if (apm_handle_event(sc, type) != 0)
        !           431:                                break;
        !           432:                }
        !           433:                if (apm_suspends || apm_userstandbys /* || apm_battlow*/) {
        !           434:                        apm_suspend(sc);
        !           435:                        apm_resume(sc);
        !           436:                }
        !           437:                apm_battlow = apm_suspends = apm_userstandbys = 0;
        !           438:
        !           439:                APM_UNLOCK(sc);
        !           440:                tsleep(&lbolt, PWAIT, "apmev", 0);
        !           441:        }
        !           442: }
        !           443:
        !           444: int
        !           445: apmopen(dev_t dev, int flag, int mode, struct proc *p)
        !           446: {
        !           447:        struct pxa2x0_apm_softc *sc;
        !           448:        int error = 0;
        !           449:
        !           450:        /* apm0 only */
        !           451:        if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
        !           452:            !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
        !           453:                return (ENXIO);
        !           454:
        !           455:        DPRINTF(("apmopen: dev %d pid %d flag %x mode %x\n",
        !           456:            APMDEV(dev), p->p_pid, flag, mode));
        !           457:
        !           458:        switch (APMDEV(dev)) {
        !           459:        case APMDEV_CTL:
        !           460:                if (!(flag & FWRITE)) {
        !           461:                        error = EINVAL;
        !           462:                        break;
        !           463:                }
        !           464:                if (sc->sc_flags & SCFLAG_OWRITE) {
        !           465:                        error = EBUSY;
        !           466:                        break;
        !           467:                }
        !           468:                sc->sc_flags |= SCFLAG_OWRITE;
        !           469:                break;
        !           470:        case APMDEV_NORMAL:
        !           471:                if (!(flag & FREAD) || (flag & FWRITE)) {
        !           472:                        error = EINVAL;
        !           473:                        break;
        !           474:                }
        !           475:                sc->sc_flags |= SCFLAG_OREAD;
        !           476:                break;
        !           477:        default:
        !           478:                error = ENXIO;
        !           479:                break;
        !           480:        }
        !           481:        return (error);
        !           482: }
        !           483:
        !           484: int
        !           485: apmclose(dev_t dev, int flag, int mode, struct proc *p)
        !           486: {
        !           487:        struct pxa2x0_apm_softc *sc;
        !           488:
        !           489:        /* apm0 only */
        !           490:        if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
        !           491:            !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
        !           492:                return (ENXIO);
        !           493:
        !           494:        DPRINTF(("apmclose: pid %d flag %x mode %x\n", p->p_pid, flag, mode));
        !           495:
        !           496:        switch (APMDEV(dev)) {
        !           497:        case APMDEV_CTL:
        !           498:                sc->sc_flags &= ~SCFLAG_OWRITE;
        !           499:                break;
        !           500:        case APMDEV_NORMAL:
        !           501:                sc->sc_flags &= ~SCFLAG_OREAD;
        !           502:                break;
        !           503:        }
        !           504:        return (0);
        !           505: }
        !           506:
        !           507: int
        !           508: apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
        !           509: {
        !           510:        struct pxa2x0_apm_softc *sc;
        !           511:        struct apm_power_info *power;
        !           512:        int error = 0;
        !           513:
        !           514:        /* apm0 only */
        !           515:        if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
        !           516:            !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
        !           517:                return (ENXIO);
        !           518:
        !           519:        switch (cmd) {
        !           520:                /* some ioctl names from linux */
        !           521:        case APM_IOC_STANDBY:
        !           522:                if ((flag & FWRITE) == 0)
        !           523:                        error = EBADF;
        !           524:                else
        !           525:                        apm_userstandbys++;
        !           526:                break;
        !           527:        case APM_IOC_SUSPEND:
        !           528:                if ((flag & FWRITE) == 0)
        !           529:                        error = EBADF;
        !           530:                else
        !           531:                        apm_suspends++; /* XXX */
        !           532:                break;
        !           533:        case APM_IOC_PRN_CTL:
        !           534:                if ((flag & FWRITE) == 0)
        !           535:                        error = EBADF;
        !           536:                else {
        !           537:                        int flag = *(int *)data;
        !           538:                        DPRINTF(( "APM_IOC_PRN_CTL: %d\n", flag ));
        !           539:                        switch (flag) {
        !           540:                        case APM_PRINT_ON:      /* enable printing */
        !           541:                                sc->sc_flags &= ~SCFLAG_PRINT;
        !           542:                                break;
        !           543:                        case APM_PRINT_OFF: /* disable printing */
        !           544:                                sc->sc_flags &= ~SCFLAG_PRINT;
        !           545:                                sc->sc_flags |= SCFLAG_NOPRINT;
        !           546:                                break;
        !           547:                        case APM_PRINT_PCT: /* disable some printing */
        !           548:                                sc->sc_flags &= ~SCFLAG_PRINT;
        !           549:                                sc->sc_flags |= SCFLAG_PCTPRINT;
        !           550:                                break;
        !           551:                        default:
        !           552:                                error = EINVAL;
        !           553:                                break;
        !           554:                        }
        !           555:                }
        !           556:                break;
        !           557:        case APM_IOC_DEV_CTL:
        !           558:                if ((flag & FWRITE) == 0)
        !           559:                        error = EBADF;
        !           560:                break;
        !           561:        case APM_IOC_GETPOWER:
        !           562:                power = (struct apm_power_info *)data;
        !           563:                apm_power_info(sc, power);
        !           564:                break;
        !           565:
        !           566:        default:
        !           567:                error = ENOTTY;
        !           568:        }
        !           569:
        !           570:        return (error);
        !           571: }
        !           572:
        !           573: int
        !           574: apm_record_event(struct pxa2x0_apm_softc *sc, u_int type)
        !           575: {
        !           576:        static int apm_evindex;
        !           577:
        !           578:        /* skip if no user waiting */
        !           579:        if ((sc->sc_flags & SCFLAG_OPEN) == 0)
        !           580:                return (1);
        !           581:
        !           582:        apm_evindex++;
        !           583:        KNOTE(&sc->sc_note, APM_EVENT_COMPOSE(type, apm_evindex));
        !           584:
        !           585:        return (0);
        !           586: }
        !           587:
        !           588: void
        !           589: filt_apmrdetach(struct knote *kn)
        !           590: {
        !           591:        struct pxa2x0_apm_softc *sc =
        !           592:            (struct pxa2x0_apm_softc *)kn->kn_hook;
        !           593:
        !           594:        SLIST_REMOVE(&sc->sc_note, kn, knote, kn_selnext);
        !           595: }
        !           596:
        !           597: int
        !           598: filt_apmread(struct knote *kn, long hint)
        !           599: {
        !           600:        /* XXX weird kqueue_scan() semantics */
        !           601:        if (hint && !kn->kn_data)
        !           602:                kn->kn_data = (int)hint;
        !           603:
        !           604:        return (1);
        !           605: }
        !           606:
        !           607: int
        !           608: apmkqfilter(dev_t dev, struct knote *kn)
        !           609: {
        !           610:        struct pxa2x0_apm_softc *sc;
        !           611:
        !           612:        /* apm0 only */
        !           613:        if (!apm_cd.cd_ndevs || APMUNIT(dev) != 0 ||
        !           614:            !(sc = apm_cd.cd_devs[APMUNIT(dev)]))
        !           615:                return (ENXIO);
        !           616:
        !           617:        switch (kn->kn_filter) {
        !           618:        case EVFILT_READ:
        !           619:                kn->kn_fop = &apmread_filtops;
        !           620:                break;
        !           621:        default:
        !           622:                return (1);
        !           623:        }
        !           624:
        !           625:        kn->kn_hook = (caddr_t)sc;
        !           626:        SLIST_INSERT_HEAD(&sc->sc_note, kn, kn_selnext);
        !           627:
        !           628:        return (0);
        !           629: }
        !           630:
        !           631: void
        !           632: pxa2x0_apm_attach_sub(struct pxa2x0_apm_softc *sc)
        !           633: {
        !           634:
        !           635:        sc->sc_iot = &pxa2x0_bs_tag;
        !           636:
        !           637:        if (bus_space_map(sc->sc_iot, PXA2X0_POWMAN_BASE,
        !           638:            PXA2X0_POWMAN_SIZE, 0, &sc->sc_pm_ioh)) {
        !           639:                printf("pxa2x0_apm_attach_sub: failed to map POWMAN\n");
        !           640:                return;
        !           641:        }
        !           642:
        !           643:        lockinit(&sc->sc_lock, PWAIT, "apmlk", 0, 0);
        !           644:
        !           645:        kthread_create_deferred(apm_thread_create, sc);
        !           646:
        !           647:        printf("\n");
        !           648:
        !           649:        if (bus_space_map(sc->sc_iot, PXA2X0_CLKMAN_BASE, PXA2X0_CLKMAN_SIZE,
        !           650:            0, &pxa2x0_clkman_ioh)) {
        !           651:                printf("%s: failed to map CLKMAN\n", sc->sc_dev.dv_xname);
        !           652:                return;
        !           653:        }
        !           654:
        !           655:        if (bus_space_map(sc->sc_iot, PXA2X0_MEMCTL_BASE, PXA2X0_MEMCTL_SIZE,
        !           656:            0, &pxa2x0_memctl_ioh)) {
        !           657:                printf("%s: failed to map MEMCTL\n", sc->sc_dev.dv_xname);
        !           658:                return;
        !           659:        }
        !           660:        sc->sc_memctl_ioh = pxa2x0_memctl_ioh;
        !           661:
        !           662:        if (bus_space_map(sc->sc_iot, PXA2X0_GPIO_BASE, PXA2X0_GPIO_SIZE,
        !           663:            0, &pxa2x0_gpio_ioh)) {
        !           664:                printf("%s: can't map GPIO\n", sc->sc_dev.dv_xname);
        !           665:                return;
        !           666:        }
        !           667:
        !           668:        /* Clear all reset status flags. */
        !           669:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_RCSR,
        !           670:            RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR);
        !           671: }
        !           672:
        !           673: void
        !           674: pxa2x0_wakeup_config(u_int wsrc, int enable)
        !           675: {
        !           676:        struct pxa2x0_apm_softc *sc;
        !           677:        u_int32_t prer;
        !           678:        u_int32_t pfer;
        !           679:        u_int32_t pkwr;
        !           680:
        !           681:        if (apm_cd.cd_ndevs < 1 || apm_cd.cd_devs[0] == NULL)
        !           682:                return;
        !           683:        sc = apm_cd.cd_devs[0];
        !           684:
        !           685:        prer = pfer = pkwr = 0;
        !           686:
        !           687:        if ((wsrc & PXA2X0_WAKEUP_POWERON) != 0) {
        !           688:                prer |= (1<<0);
        !           689:                pfer |= (1<<0);
        !           690:                pkwr |= (1<<12); /* XXX */
        !           691:        }
        !           692:
        !           693:        if ((wsrc & PXA2X0_WAKEUP_GPIORST) != 0)
        !           694:                pfer |= (1<<1);
        !           695:        if ((wsrc & PXA2X0_WAKEUP_SD) != 0)
        !           696:                prer |= (1<<9);
        !           697:        if ((wsrc & PXA2X0_WAKEUP_RC) != 0)
        !           698:                prer |= (1<<13);
        !           699:        if ((wsrc & PXA2X0_WAKEUP_SYNC) != 0)
        !           700:                pkwr |= (1<<1);
        !           701:        if ((wsrc & PXA2X0_WAKEUP_KEYNS0) != 0)
        !           702:                prer |= (1<<12);
        !           703:        if ((wsrc & PXA2X0_WAKEUP_KEYNS1) != 0)
        !           704:                pkwr |= (1<<2);
        !           705:        if ((wsrc & PXA2X0_WAKEUP_KEYNS2) != 0)
        !           706:                pkwr |= (1<<9);
        !           707:        if ((wsrc & PXA2X0_WAKEUP_KEYNS3) != 0)
        !           708:                pkwr |= (1<<3);
        !           709:        if ((wsrc & PXA2X0_WAKEUP_KEYNS4) != 0)
        !           710:                pkwr |= (1<<4);
        !           711:        if ((wsrc & PXA2X0_WAKEUP_KEYNS5) != 0)
        !           712:                pkwr |= (1<<6);
        !           713:        if ((wsrc & PXA2X0_WAKEUP_KEYNS6) != 0)
        !           714:                pkwr |= (1<<7);
        !           715:        if ((wsrc & PXA2X0_WAKEUP_CF0) != 0)
        !           716:                pkwr |= (1<<11);
        !           717:        if ((wsrc & PXA2X0_WAKEUP_CF1) != 0)
        !           718:                pkwr |= (1<<10);
        !           719:        if ((wsrc & PXA2X0_WAKEUP_USBD) != 0)
        !           720:                prer |= (1<<24);
        !           721:
        !           722:        if ((wsrc & PXA2X0_WAKEUP_LOCKSW) != 0) {
        !           723:                prer |= (1<<15);
        !           724:                pfer |= (1<<15);
        !           725:        }
        !           726:
        !           727:        if ((wsrc & PXA2X0_WAKEUP_JACKIN) != 0) {
        !           728:                prer |= (1<<23);
        !           729:                pfer |= (1<<23);
        !           730:        }
        !           731:
        !           732:        if ((wsrc & PXA2X0_WAKEUP_CHRGFULL) != 0)
        !           733:                pkwr |= (1<<18);
        !           734:        if ((wsrc & PXA2X0_WAKEUP_RTC) != 0)
        !           735:                prer |= (1<<31);
        !           736:
        !           737:        if (enable) {
        !           738:                sc->sc_wakeon |= wsrc;
        !           739:                prer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
        !           740:                    POWMAN_PRER);
        !           741:                pfer |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
        !           742:                    POWMAN_PFER);
        !           743:                pkwr |= bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
        !           744:                    POWMAN_PKWR);
        !           745:        } else {
        !           746:                sc->sc_wakeon &= ~wsrc;
        !           747:                prer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
        !           748:                    POWMAN_PRER) & ~prer;
        !           749:                pfer = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
        !           750:                    POWMAN_PFER) & ~pfer;
        !           751:                pkwr = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
        !           752:                    POWMAN_PKWR) & ~pkwr;
        !           753:        }
        !           754:
        !           755:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKWR, pkwr);
        !           756:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PRER, prer);
        !           757:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PFER, pfer);
        !           758:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PWER,
        !           759:            prer | pfer);
        !           760: }
        !           761:
        !           762: u_int
        !           763: pxa2x0_wakeup_status(void)
        !           764: {
        !           765:        struct pxa2x0_apm_softc *sc;
        !           766:        u_int32_t rv;
        !           767:        u_int   wsrc;
        !           768:
        !           769:        if (apm_cd.cd_ndevs < 1 || apm_cd.cd_devs[0] == NULL)
        !           770:                return (0);
        !           771:
        !           772:        sc = apm_cd.cd_devs[0];
        !           773:        wsrc = 0;
        !           774:
        !           775:        rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR);
        !           776:        if ((rv & (1<<0)) != 0)
        !           777:                wsrc |= PXA2X0_WAKEUP_POWERON;
        !           778:        if ((rv & (1<<1)) != 0)
        !           779:                wsrc |= PXA2X0_WAKEUP_GPIORST;
        !           780:        if ((rv & (1<<9)) != 0)
        !           781:                wsrc |= PXA2X0_WAKEUP_SD;
        !           782:        if ((rv & (1<<12)) != 0)
        !           783:                wsrc |= PXA2X0_WAKEUP_KEYNS0;
        !           784:        if ((rv & (1<<13)) != 0)
        !           785:                wsrc |= PXA2X0_WAKEUP_RC;
        !           786:        if ((rv & (1<<15)) != 0)
        !           787:                wsrc |= PXA2X0_WAKEUP_LOCKSW;
        !           788:        if ((rv & (1<<23)) != 0)
        !           789:                wsrc |= PXA2X0_WAKEUP_JACKIN;
        !           790:        if ((rv & (1<<24)) != 0)
        !           791:                wsrc |= PXA2X0_WAKEUP_USBD;
        !           792:        if ((rv & (1<<31)) != 0)
        !           793:                wsrc |= PXA2X0_WAKEUP_RTC;
        !           794:
        !           795:        rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR);
        !           796:        if ((rv & (1<<1)) != 0)
        !           797:                wsrc |= PXA2X0_WAKEUP_SYNC;
        !           798:        if ((rv & (1<<2)) != 0)
        !           799:                wsrc |= PXA2X0_WAKEUP_KEYNS1;
        !           800:        if ((rv & (1<<9)) != 0)
        !           801:                wsrc |= PXA2X0_WAKEUP_KEYNS2;
        !           802:        if ((rv & (1<<3)) != 0)
        !           803:                wsrc |= PXA2X0_WAKEUP_KEYNS3;
        !           804:        if ((rv & (1<<4)) != 0)
        !           805:                wsrc |= PXA2X0_WAKEUP_KEYNS4;
        !           806:        if ((rv & (1<<6)) != 0)
        !           807:                wsrc |= PXA2X0_WAKEUP_KEYNS5;
        !           808:        if ((rv & (1<<7)) != 0)
        !           809:                wsrc |= PXA2X0_WAKEUP_KEYNS6;
        !           810:        if ((rv & (1<<10)) != 0)
        !           811:                wsrc |= PXA2X0_WAKEUP_CF1;
        !           812:        if ((rv & (1<<11)) != 0)
        !           813:                wsrc |= PXA2X0_WAKEUP_CF0;
        !           814:        if ((rv & (1<<12)) != 0)
        !           815:                wsrc |= PXA2X0_WAKEUP_POWERON;
        !           816:        if ((rv & (1<<18)) != 0)
        !           817:                wsrc |= PXA2X0_WAKEUP_CHRGFULL;
        !           818:
        !           819:        return (wsrc);
        !           820: }
        !           821:
        !           822: struct pxa2x0_sleep_data {
        !           823:        /* OS timer registers */
        !           824:        u_int32_t sd_osmr0, sd_osmr1, sd_osmr2, sd_osmr3;
        !           825:        u_int32_t sd_oscr0;
        !           826:        u_int32_t sd_osmr4, sd_osmr5;
        !           827:        u_int32_t sd_oscr4;
        !           828:        u_int32_t sd_omcr4, sd_omcr5;
        !           829:        u_int32_t sd_oier;
        !           830:        /* GPIO registers */
        !           831:        u_int32_t sd_gpdr0, sd_gpdr1, sd_gpdr2, sd_gpdr3;
        !           832:        u_int32_t sd_grer0, sd_grer1, sd_grer2, sd_grer3;
        !           833:        u_int32_t sd_gfer0, sd_gfer1, sd_gfer2, sd_gfer3;
        !           834:        u_int32_t sd_gafr0_l, sd_gafr1_l, sd_gafr2_l, sd_gafr3_l;
        !           835:        u_int32_t sd_gafr0_u, sd_gafr1_u, sd_gafr2_u, sd_gafr3_u;
        !           836:        u_int32_t sd_gplr0, sd_gplr1, sd_gplr2, sd_gplr3;
        !           837:        /* Interrupt controller registers */
        !           838:        u_int32_t sd_iclr;
        !           839:        u_int32_t sd_icmr;
        !           840:        u_int32_t sd_iccr;
        !           841:        /* Memory controller registers */
        !           842:        u_int32_t sd_mecr;
        !           843:        u_int32_t sd_mcmem0, sd_mcmem1;
        !           844:        u_int32_t sd_mcatt0, sd_mcatt1;
        !           845:        u_int32_t sd_mcio0, sd_mcio1;
        !           846:        /* Clocks manager registers */
        !           847:        u_int32_t sd_cken;
        !           848: };
        !           849:
        !           850: void
        !           851: pxa2x0_apm_sleep(struct pxa2x0_apm_softc *sc)
        !           852: {
        !           853:        struct pxa2x0_sleep_data sd;
        !           854:        bus_space_handle_t ost_ioh;
        !           855:        int save;
        !           856:        u_int32_t rv;
        !           857:
        !           858:        ost_ioh = (bus_space_handle_t)0;
        !           859:        if (bus_space_map(sc->sc_iot, PXA2X0_OST_BASE, PXA2X0_OST_SIZE, 0,
        !           860:            &ost_ioh)) {
        !           861:                printf("pxa2x0_apm_sleep: can't map OST\n");
        !           862:                goto out;
        !           863:        }
        !           864:
        !           865:        save = disable_interrupts(I32_bit|F32_bit);
        !           866:
        !           867:        sd.sd_oscr0 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSCR0);
        !           868:        sd.sd_oscr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSCR4);
        !           869:        sd.sd_omcr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OMCR4);
        !           870:        sd.sd_omcr5 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OMCR5);
        !           871:        sd.sd_osmr0 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR0);
        !           872:        sd.sd_osmr1 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR1);
        !           873:        sd.sd_osmr2 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR2);
        !           874:        sd.sd_osmr3 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR3);
        !           875:        sd.sd_osmr4 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR4);
        !           876:        sd.sd_osmr5 = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OSMR5);
        !           877:        sd.sd_oier = bus_space_read_4(sc->sc_iot, ost_ioh, OST_OIER);
        !           878:
        !           879:        /* Bring the PXA27x into 416MHz turbo mode. */
        !           880:         if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X &&
        !           881:            bus_space_read_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CCCR) !=
        !           882:            (CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16)) {
        !           883: #if 0
        !           884:                pxa27x_cpu_speed_high();
        !           885: #else
        !           886: #define CLKCFG_T               (1<<0)  /* turbo */
        !           887: #define CLKCFG_F               (1<<1)  /* frequency change */
        !           888: #define CLKCFG_B               (1<<3)  /* fast-bus */
        !           889:                pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
        !           890:                    CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T,
        !           891:                    &pxa2x0_memcfg);
        !           892: #endif
        !           893:                delay(500000); /* XXX */
        !           894:        }
        !           895:
        !           896: suspend_again:
        !           897:        /* Clear wake-up status. */
        !           898:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR,
        !           899:            0xffffffff);
        !           900:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PKSR,
        !           901:            0xffffffff);
        !           902:
        !           903:        /* XXX control battery charging in sleep mode. */
        !           904:
        !           905:        /* XXX schedule RTC alarm to check the battery, or schedule
        !           906:           XXX wake-up shortly before an already programmed alarm? */
        !           907:
        !           908:        pxa27x_run_mode();
        !           909: #define MDREFR_LOW             (MDREFR_C3000 | 0x00b)
        !           910:        pxa27x_fastbus_run_mode(0, MDREFR_LOW);
        !           911:        delay(1);
        !           912: #if 1
        !           913:        pxa27x_cpu_speed_91();
        !           914: #else
        !           915:        pxa27x_frequency_change(CCCR_TURBO_X1 | CCCR_RUN_X7, CLKCFG_F,
        !           916:            &pxa2x0_memcfg);
        !           917: #endif
        !           918:        pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh, PI2C_VOLTAGE_LOW);
        !           919:
        !           920:        sd.sd_gpdr0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0);
        !           921:        sd.sd_gpdr1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1);
        !           922:        sd.sd_gpdr2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2);
        !           923:        sd.sd_gpdr3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3);
        !           924:
        !           925:        sd.sd_grer0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER0);
        !           926:        sd.sd_grer1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER1);
        !           927:        sd.sd_grer2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER2);
        !           928:        sd.sd_grer3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER3);
        !           929:
        !           930:        sd.sd_gfer0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER0);
        !           931:        sd.sd_gfer1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER1);
        !           932:        sd.sd_gfer2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER2);
        !           933:        sd.sd_gfer3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER3);
        !           934:
        !           935:        sd.sd_gafr0_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_L);
        !           936:        sd.sd_gafr1_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_L);
        !           937:        sd.sd_gafr2_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_L);
        !           938:        sd.sd_gafr3_l = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_L);
        !           939:
        !           940:        sd.sd_gafr0_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_U);
        !           941:        sd.sd_gafr1_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_U);
        !           942:        sd.sd_gafr2_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_U);
        !           943:        sd.sd_gafr3_u = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_U);
        !           944:
        !           945:        sd.sd_gplr0 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR0);
        !           946:        sd.sd_gplr1 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR1);
        !           947:        sd.sd_gplr2 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR2);
        !           948:        sd.sd_gplr3 = bus_space_read_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPLR3);
        !           949:
        !           950:        sd.sd_iclr = read_icu(INTCTL_ICLR);
        !           951:        sd.sd_icmr = read_icu(INTCTL_ICMR);
        !           952:        sd.sd_iccr = read_icu(INTCTL_ICCR);
        !           953:        write_icu(INTCTL_ICMR, 0);
        !           954:
        !           955:        sd.sd_mecr = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
        !           956:            MEMCTL_MECR);
        !           957:        sd.sd_mcmem0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
        !           958:            MEMCTL_MCMEM(0));
        !           959:        sd.sd_mcmem1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
        !           960:            MEMCTL_MCMEM(1));
        !           961:        sd.sd_mcatt0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
        !           962:            MEMCTL_MCATT(0));
        !           963:        sd.sd_mcatt1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
        !           964:            MEMCTL_MCATT(1));
        !           965:        sd.sd_mcio0 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
        !           966:            MEMCTL_MCIO(0));
        !           967:        sd.sd_mcio1 = bus_space_read_4(sc->sc_iot, pxa2x0_memctl_ioh,
        !           968:            MEMCTL_MCIO(1));
        !           969:
        !           970:        sd.sd_cken = bus_space_read_4(sc->sc_iot, pxa2x0_clkman_ioh,
        !           971:            CLKMAN_CKEN);
        !           972:
        !           973:        /*
        !           974:         * Stop clocks to all units except to the memory controller, and
        !           975:         * to the keypad controller if it is enabled as a wake-up source.
        !           976:         */
        !           977:        rv = CKEN_MEM;
        !           978:        if ((sc->sc_wakeon & PXA2X0_WAKEUP_KEYNS_ALL) != 0)
        !           979:                rv |= CKEN_KEY;
        !           980:        bus_space_write_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CKEN, rv);
        !           981:
        !           982:        /* Disable nRESET_OUT. */
        !           983:        rv = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSLR);
        !           984: #define  PSLR_SL_ROD   (1<<20)
        !           985:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSLR,
        !           986:            rv | PSLR_SL_ROD);
        !           987:
        !           988:        /* Clear all reset status flags. */
        !           989:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_RCSR,
        !           990:            RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR);
        !           991:
        !           992:        /* Stop 3/13MHz oscillator; do not float PCMCIA and chip-selects. */
        !           993:        rv = PCFR_OPDE;
        !           994:         if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X)
        !           995:                /* Enable nRESET_GPIO as a GPIO reset input. */
        !           996:                rv |= PCFR_GPR_EN;
        !           997:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PCFR, rv);
        !           998:
        !           999:        /* XXX C3000 */
        !          1000: #define        GPIO_G0_STROBE_BIT              0x0f800000
        !          1001: #define        GPIO_G1_STROBE_BIT              0x00100000
        !          1002: #define        GPIO_G2_STROBE_BIT              0x01000000
        !          1003: #define        GPIO_G3_STROBE_BIT              0x00041880
        !          1004: #define        GPIO_KEY_STROBE0                88
        !          1005:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR0,
        !          1006:            0x00144018);
        !          1007:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR1,
        !          1008:            0x00ef0000);
        !          1009:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2,
        !          1010:            0x0121c000);
        !          1011:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR3,
        !          1012:            0x00600000);
        !          1013:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR0,
        !          1014:            0x00144018 & ~GPIO_G0_STROBE_BIT);
        !          1015:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR1,
        !          1016:            0x00ef0000 & ~GPIO_G1_STROBE_BIT);
        !          1017:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2,
        !          1018:            0x0121c000 & ~GPIO_G2_STROBE_BIT);
        !          1019:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR3,
        !          1020:            0x00600000 & ~GPIO_G3_STROBE_BIT);
        !          1021:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PGSR2,
        !          1022:            (0x0121c000 & ~GPIO_G2_STROBE_BIT) |
        !          1023:            GPIO_BIT(GPIO_KEY_STROBE0));
        !          1024:
        !          1025:        /* C3000 */
        !          1026: #define GPIO_EXT_BUS_READY     18
        !          1027:        pxa2x0_gpio_set_function(GPIO_EXT_BUS_READY, GPIO_SET | GPIO_OUT);
        !          1028:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0, 0xd01c4418);
        !          1029:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1, 0xfcefbd21);
        !          1030:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2, 0x13a5ffff);
        !          1031:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3, 0x01e3e10c);
        !          1032:
        !          1033:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSPR,
        !          1034:            (u_int32_t)&pxa2x0_cpu_resume - 0xc0200000 + 0xa0200000);
        !          1035:
        !          1036:        pxa2x0_cpu_suspend();
        !          1037:
        !          1038:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PSPR, 0);
        !          1039:
        !          1040:        pxa2x0_clkman_config(CKEN_SSP|CKEN_PWM0|CKEN_PWM1, 1);
        !          1041:        pxa2x0_clkman_config(CKEN_KEY, 0);
        !          1042:
        !          1043: #if 1
        !          1044:        /* Clear all GPIO interrupt sources. */
        !          1045:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR0, 0xffffffff);
        !          1046:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR1, 0xffffffff);
        !          1047:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR2, 0xffffffff);
        !          1048: #endif
        !          1049:
        !          1050:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR0, sd.sd_gpdr0);
        !          1051:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR1, sd.sd_gpdr1);
        !          1052:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR2, sd.sd_gpdr2);
        !          1053:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER0, sd.sd_grer0);
        !          1054:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER1, sd.sd_grer1);
        !          1055:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER2, sd.sd_grer2);
        !          1056:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER0, sd.sd_gfer0);
        !          1057:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER1, sd.sd_gfer1);
        !          1058:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER2, sd.sd_gfer2);
        !          1059:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_L, sd.sd_gafr0_l);
        !          1060:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_L, sd.sd_gafr1_l);
        !          1061:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_L, sd.sd_gafr2_l);
        !          1062:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR0_U, sd.sd_gafr0_u);
        !          1063:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR1_U, sd.sd_gafr1_u);
        !          1064:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR2_U, sd.sd_gafr2_u);
        !          1065:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR0, sd.sd_gplr0 &
        !          1066:            sd.sd_gpdr0);
        !          1067:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR1, sd.sd_gplr1 &
        !          1068:            sd.sd_gpdr1);
        !          1069:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR2, sd.sd_gplr2 &
        !          1070:            sd.sd_gpdr2);
        !          1071:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR0, ~sd.sd_gplr0 &
        !          1072:            sd.sd_gpdr0);
        !          1073:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR1, ~sd.sd_gplr1 &
        !          1074:            sd.sd_gpdr1);
        !          1075:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR2, ~sd.sd_gplr2 &
        !          1076:            sd.sd_gpdr2);
        !          1077:
        !          1078:        /* PXA27x */
        !          1079: #if 0
        !          1080:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GEDR3, 0xffffffff);
        !          1081: #endif
        !          1082:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPDR3, sd.sd_gpdr3);
        !          1083:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GRER3, sd.sd_grer3);
        !          1084:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GFER3, sd.sd_gfer3);
        !          1085:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_L, sd.sd_gafr3_l);
        !          1086:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GAFR3_U, sd.sd_gafr3_u);
        !          1087:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPSR3, sd.sd_gplr3 &
        !          1088:            sd.sd_gpdr3);
        !          1089:        bus_space_write_4(sc->sc_iot, pxa2x0_gpio_ioh, GPIO_GPCR3, ~sd.sd_gplr3 &
        !          1090:            sd.sd_gpdr3);
        !          1091:
        !          1092:        bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MECR,
        !          1093:            sd.sd_mecr);
        !          1094:        bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCMEM(0),
        !          1095:            sd.sd_mcmem0);
        !          1096:        bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCMEM(1),
        !          1097:            sd.sd_mcmem1);
        !          1098:        bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCATT(0),
        !          1099:            sd.sd_mcatt0);
        !          1100:        bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCATT(1),
        !          1101:            sd.sd_mcatt1);
        !          1102:        bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCIO(0),
        !          1103:            sd.sd_mcio0);
        !          1104:        bus_space_write_4(sc->sc_iot, pxa2x0_memctl_ioh, MEMCTL_MCIO(1),
        !          1105:            sd.sd_mcio1);
        !          1106:
        !          1107:        bus_space_write_4(sc->sc_iot, pxa2x0_clkman_ioh, CLKMAN_CKEN,
        !          1108:            sd.sd_cken);
        !          1109:
        !          1110:        write_icu(INTCTL_ICLR, sd.sd_iclr);
        !          1111:        write_icu(INTCTL_ICCR, sd.sd_iccr);
        !          1112:        write_icu(INTCTL_ICMR, sd.sd_icmr);
        !          1113:
        !          1114:        if ((read_icu(INTCTL_ICIP) & 0x1) != 0)
        !          1115:                bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PEDR, 0x1);
        !          1116:
        !          1117:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR0, sd.sd_osmr0);
        !          1118:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR1, sd.sd_osmr1);
        !          1119:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR2, sd.sd_osmr2);
        !          1120:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR3, sd.sd_osmr3);
        !          1121:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR4, sd.sd_osmr4);
        !          1122:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSMR5, sd.sd_osmr5);
        !          1123:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OMCR4, sd.sd_omcr4);
        !          1124:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OMCR5, sd.sd_omcr5);
        !          1125:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSCR0, sd.sd_oscr0);
        !          1126:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OSCR4, sd.sd_oscr4);
        !          1127:        bus_space_write_4(sc->sc_iot, ost_ioh, OST_OIER, sd.sd_oier);
        !          1128:
        !          1129:        pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh, PI2C_VOLTAGE_HIGH);
        !          1130:
        !          1131:        /* Change to 208MHz run mode with fast-bus still disabled. */
        !          1132:        pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16,
        !          1133:            CLKCFG_F, &pxa2x0_memcfg);
        !          1134:        delay(1); /* XXX is the delay long enough, and necessary at all? */
        !          1135:        pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
        !          1136:
        !          1137:        /* Change to 416MHz turbo mode with fast-bus enabled. */
        !          1138:        pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16,
        !          1139:            CLKCFG_B | CLKCFG_F | CLKCFG_T, &pxa2x0_memcfg);
        !          1140:
        !          1141:        if (sc->sc_resume != NULL) {
        !          1142:                if (!sc->sc_resume(sc))
        !          1143:                        goto suspend_again;
        !          1144:        }
        !          1145:
        !          1146:        /*
        !          1147:         * Allow immediate entry into deep-sleep mode if power fails.
        !          1148:         * Resume from immediate deep-sleep is not implemented yet.
        !          1149:         */
        !          1150:        bus_space_write_4(sc->sc_iot, sc->sc_pm_ioh, POWMAN_PMCR, 0);
        !          1151:
        !          1152:
        !          1153:        restore_interrupts(save);
        !          1154:
        !          1155:        pxa2x0_setperf(perflevel);
        !          1156:
        !          1157:  out:
        !          1158:        if (ost_ioh != (bus_space_handle_t)0)
        !          1159:                bus_space_unmap(sc->sc_iot, ost_ioh, PXA2X0_OST_SIZE);
        !          1160: }
        !          1161:
        !          1162: void
        !          1163: pxa2x0_pi2c_open(bus_space_tag_t iot, bus_space_handle_t ioh)
        !          1164: {
        !          1165:        u_int32_t rv;
        !          1166:
        !          1167:        /* Enable the I2C unit, and disable automatic voltage change. */
        !          1168:        rv = bus_space_read_4(iot, ioh, POWMAN_PCFR);
        !          1169:        bus_space_write_4(iot, ioh, POWMAN_PCFR, rv | PCFR_PI2C_EN);
        !          1170:        rv = bus_space_read_4(iot, ioh, POWMAN_PCFR);
        !          1171:        bus_space_write_4(iot, ioh, POWMAN_PCFR, rv & ~PCFR_FVC);
        !          1172:        delay(1);
        !          1173:
        !          1174:        /* Enable the clock to the power manager I2C unit. */
        !          1175:        pxa2x0_clkman_config(CKEN_PI2C, 1);
        !          1176:        delay(1);
        !          1177: }
        !          1178:
        !          1179: void
        !          1180: pxa2x0_pi2c_close(bus_space_tag_t iot, bus_space_handle_t ioh)
        !          1181: {
        !          1182:        u_int32_t rv;
        !          1183:
        !          1184:        bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
        !          1185:        bus_space_write_4(iot, ioh, POWMAN_PISAR, 0);
        !          1186:        delay(1);
        !          1187:
        !          1188:        /* Disable the clock to the power manager I2C unit. */
        !          1189:        pxa2x0_clkman_config(CKEN_PI2C, 0);
        !          1190:        delay(1);
        !          1191:
        !          1192:        /* Disable the I2C unit, and disable automatic voltage change. */
        !          1193:        rv = bus_space_read_4(iot, ioh, POWMAN_PCFR);
        !          1194:        bus_space_write_4(iot, ioh, POWMAN_PCFR,
        !          1195:            rv & ~(PCFR_PI2C_EN | PCFR_FVC));
        !          1196:        delay(1);
        !          1197: }
        !          1198:
        !          1199: int
        !          1200: pxa2x0_pi2c_read(bus_space_tag_t iot, bus_space_handle_t ioh,
        !          1201:     u_char slave, u_char *valuep)
        !          1202: {
        !          1203:        u_int32_t rv;
        !          1204:        int timeout;
        !          1205:        int tries = PI2C_RETRY_COUNT;
        !          1206:
        !          1207: retry:
        !          1208:
        !          1209:        bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
        !          1210:        bus_space_write_4(iot, ioh, POWMAN_PISAR, 0x00);
        !          1211:        delay(1);
        !          1212:        bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_IUE | PICR_SCLE);
        !          1213:
        !          1214:        /* Write slave device address. */
        !          1215:        bus_space_write_4(iot, ioh, POWMAN_PIDBR, (slave<<1) | 0x1);
        !          1216:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1217:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_START);
        !          1218:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1219:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_STOP);
        !          1220:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1221:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_TB);
        !          1222:
        !          1223:        timeout = 10000;
        !          1224:        while ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ITE) == 0) {
        !          1225:                if (timeout-- == 0) {
        !          1226:                        bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
        !          1227:                        goto err;
        !          1228:                }
        !          1229:                delay(1);
        !          1230:        }
        !          1231:
        !          1232:        bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
        !          1233:
        !          1234:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1235:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_START);
        !          1236:
        !          1237:        /* Read data value. */
        !          1238:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1239:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv |
        !          1240:            (PICR_STOP | PICR_ACKNAK));
        !          1241:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1242:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_TB);
        !          1243:
        !          1244:        timeout = 10000;
        !          1245:        while ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_IRF) == 0) {
        !          1246:                if (timeout-- == 0) {
        !          1247:                        bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_IRF);
        !          1248:                        goto err;
        !          1249:                }
        !          1250:                delay(1);
        !          1251:        }
        !          1252:
        !          1253:        bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_IRF);
        !          1254:        rv = bus_space_read_4(iot, ioh, POWMAN_PIDBR);
        !          1255:        *valuep = (u_char)rv;
        !          1256:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1257:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv &
        !          1258:            ~(PICR_STOP | PICR_ACKNAK));
        !          1259:
        !          1260:        return (0);
        !          1261: err:
        !          1262:        if (tries-- >= 0)
        !          1263:                goto retry;
        !          1264:
        !          1265:        bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
        !          1266:        bus_space_write_4(iot, ioh, POWMAN_PISAR, 0x00);
        !          1267:        bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_IUE | PICR_SCLE);
        !          1268:
        !          1269:        return (-EIO);
        !          1270: }
        !          1271:
        !          1272: int
        !          1273: pxa2x0_pi2c_write(bus_space_tag_t iot, bus_space_handle_t ioh,
        !          1274:     u_char slave, u_char value)
        !          1275: {
        !          1276:        u_int32_t rv;
        !          1277:        int timeout;
        !          1278:        int tries = PI2C_RETRY_COUNT;
        !          1279:
        !          1280: retry:
        !          1281:
        !          1282:        bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
        !          1283:        bus_space_write_4(iot, ioh, POWMAN_PISAR, 0x00);
        !          1284:        delay(1);
        !          1285:        bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_IUE | PICR_SCLE);
        !          1286:
        !          1287:        /* Write slave device address. */
        !          1288:        bus_space_write_4(iot, ioh, POWMAN_PIDBR, (slave<<1));
        !          1289:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1290:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_START);
        !          1291:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1292:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_STOP);
        !          1293:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1294:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_TB);
        !          1295:
        !          1296:        timeout = 10000;
        !          1297:        while ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ITE) == 0) {
        !          1298:                if (timeout-- == 0) {
        !          1299:                        bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
        !          1300:                        goto err;
        !          1301:                }
        !          1302:                delay(1);
        !          1303:        }
        !          1304:        if ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ACKNAK) != 0)
        !          1305:                goto err;
        !          1306:        bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
        !          1307:
        !          1308:        /* Write data. */
        !          1309:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1310:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_START);
        !          1311:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1312:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_STOP);
        !          1313:        bus_space_write_4(iot, ioh, POWMAN_PIDBR, value);
        !          1314:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1315:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv | PICR_TB);
        !          1316:
        !          1317:        timeout = 10000;
        !          1318:        while ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ITE) == 0) {
        !          1319:                if (timeout-- == 0) {
        !          1320: #if 0
        !          1321:                        bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
        !          1322: #endif
        !          1323:                        goto err;
        !          1324:                }
        !          1325:                delay(1);
        !          1326:        }
        !          1327:        if ((bus_space_read_4(iot, ioh, POWMAN_PISR) & PISR_ACKNAK) != 0)
        !          1328:                goto err;
        !          1329:        bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
        !          1330:
        !          1331:        rv = bus_space_read_4(iot, ioh, POWMAN_PICR);
        !          1332:        bus_space_write_4(iot, ioh, POWMAN_PICR, rv & ~PICR_STOP);
        !          1333:
        !          1334:        return (0);
        !          1335: err:
        !          1336:        bus_space_write_4(iot, ioh, POWMAN_PISR, PISR_ITE);
        !          1337:        if (tries-- >= 0)
        !          1338:                goto retry;
        !          1339:
        !          1340:        bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_UR);
        !          1341:        bus_space_write_4(iot, ioh, POWMAN_PISAR, 0x00);
        !          1342:        bus_space_write_4(iot, ioh, POWMAN_PICR, PICR_IUE | PICR_SCLE);
        !          1343:
        !          1344:        return (-EIO);
        !          1345: }
        !          1346:
        !          1347: int
        !          1348: pxa2x0_pi2c_getvoltage(bus_space_tag_t iot, bus_space_handle_t ioh,
        !          1349:     u_char *valuep)
        !          1350: {
        !          1351:        int res;
        !          1352:
        !          1353:        pxa2x0_pi2c_open(iot, ioh);
        !          1354:        res = pxa2x0_pi2c_read(iot, ioh, 0x0c, valuep);
        !          1355:        pxa2x0_pi2c_close(iot, ioh);
        !          1356:        return (res);
        !          1357: }
        !          1358:
        !          1359: int
        !          1360: pxa2x0_pi2c_setvoltage(bus_space_tag_t iot, bus_space_handle_t ioh,
        !          1361:     u_char value)
        !          1362: {
        !          1363:        int res;
        !          1364:
        !          1365:        pxa2x0_pi2c_open(iot, ioh);
        !          1366:        res = pxa2x0_pi2c_write(iot, ioh, 0x0c, value);
        !          1367:        pxa2x0_pi2c_close(iot, ioh);
        !          1368:        return (res);
        !          1369: }
        !          1370:
        !          1371: #if 0
        !          1372: void
        !          1373: pxa2x0_pi2c_print(struct pxa2x0_apm_softc *sc)
        !          1374: {
        !          1375:        u_char value = 0;
        !          1376:
        !          1377:        (void)pxa2x0_pi2c_getvoltage(sc->sc_iot, sc->sc_pm_ioh, &value);
        !          1378:        printf("xscale core voltage: %s\n", value == PI2C_VOLTAGE_HIGH ?
        !          1379:            "high" : (value == PI2C_VOLTAGE_LOW ? "low" : "unknown"));
        !          1380: }
        !          1381: #endif
        !          1382:
        !          1383: struct {
        !          1384:        int maxspeed;
        !          1385:        int numspeeds;
        !          1386:        int hz [6];
        !          1387:        int rate [6]; /* could this be simplfied by not having 100% in table? */
        !          1388: }
        !          1389: speedtables[] = {
        !          1390:        { 91, 1, { 91 }, { 100 }},
        !          1391:        { 208, 2, { 91, 208}, {50, 100}},
        !          1392:        { 416, 3, { 91, 208, 416}, {25, 50, 100}},
        !          1393:        { 520, 4, { 91, 208, 416, 520}, {18, 40 ,80, 100}},
        !          1394:        { 624, 5, { 91, 208, 416, 520, 624}, {15, 34, 67, 82, 100}},
        !          1395:        { 0 }
        !          1396: };
        !          1397: int xscale_maxspeed = 416; /* XXX */
        !          1398:
        !          1399: int speed_to_freq(int speed);
        !          1400:
        !          1401: int
        !          1402: speed_to_freq(int speed)
        !          1403: {
        !          1404:        int i, j;
        !          1405:        int newspeed = 0;
        !          1406:        int numspeeds;
        !          1407:        for (i = 0; speedtables[i].maxspeed != 0; i++) {
        !          1408:                if (speedtables[i].maxspeed != xscale_maxspeed)
        !          1409:                        continue;
        !          1410:
        !          1411:                if (speed <= speedtables[i].rate[0]) {
        !          1412:                        return speedtables[i].hz[0];
        !          1413:
        !          1414:                }
        !          1415:                numspeeds = speedtables[i].numspeeds;
        !          1416:                if (speed == speedtables[i].rate[numspeeds-1]) {
        !          1417:                        return speedtables[i].hz[numspeeds-1];
        !          1418:                }
        !          1419:                for (j = 1; j < numspeeds; j++) {
        !          1420:                        if (speed < speedtables[i].rate[j]) {
        !          1421:                                return speedtables[i].hz[j-1];
        !          1422:                        }
        !          1423:                }
        !          1424:        }
        !          1425:        return newspeed;
        !          1426: }
        !          1427:
        !          1428:
        !          1429: void
        !          1430: pxa2x0_setperf(int speed)
        !          1431: {
        !          1432:        struct pxa2x0_apm_softc *sc;
        !          1433:        int s;
        !          1434:        int newfreq;
        !          1435:
        !          1436:        sc = apm_cd.cd_devs[0];
        !          1437:
        !          1438:        newfreq = speed_to_freq(speed);
        !          1439:
        !          1440:        if (newfreq == 0) {
        !          1441:                printf("bogus new frequency 0 for rate %d maxclock %d\n",
        !          1442:                    speed, xscale_maxspeed);
        !          1443:        }
        !          1444:
        !          1445:        DPRINTF(("setperf speed %d newfreq %d, maxfreq %d\n",
        !          1446:            speed, newfreq, xscale_maxspeed));
        !          1447:
        !          1448:        s = disable_interrupts(I32_bit|F32_bit);
        !          1449:
        !          1450:        if (newfreq == 91) {
        !          1451:                if (freq > 91) {
        !          1452:                        pxa27x_run_mode();
        !          1453:                        pxa27x_fastbus_run_mode(0, MDREFR_LOW);
        !          1454:                        pxa27x_cpu_speed_91();
        !          1455:                        pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
        !          1456:                            PI2C_VOLTAGE_LOW);
        !          1457:                        freq = 91;
        !          1458:                }
        !          1459:        } else if (newfreq == 208) {
        !          1460:                if (freq < 208)
        !          1461:                        pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
        !          1462:                            PI2C_VOLTAGE_HIGH);
        !          1463:                if (freq != 208) {
        !          1464:                        pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
        !          1465:                            CCCR_RUN_X16, CLKCFG_F, &pxa2x0_memcfg);
        !          1466:                        pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
        !          1467:                        freq = 208;
        !          1468:                }
        !          1469:        } else if (newfreq == 416) {
        !          1470:                if (freq < 208) {
        !          1471:                        pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
        !          1472:                            PI2C_VOLTAGE_HIGH);
        !          1473:                        pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
        !          1474:                            CCCR_RUN_X16, CLKCFG_F, &pxa2x0_memcfg);
        !          1475:                        pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
        !          1476:                }
        !          1477:                if (freq != 416) {
        !          1478:                        pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
        !          1479:                            CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T,
        !          1480:                            &pxa2x0_memcfg);
        !          1481:                        freq = 416;
        !          1482:                }
        !          1483:        } else if (newfreq == 520) {
        !          1484:                if (freq < 208) {
        !          1485:                        pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
        !          1486:                            PI2C_VOLTAGE_HIGH);
        !          1487:                        pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
        !          1488:                            CCCR_RUN_X16, CLKCFG_F, &pxa2x0_memcfg);
        !          1489:                        pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
        !          1490:                }
        !          1491:                if (freq != 520) {
        !          1492:                        pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X25 |
        !          1493:                            CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T,
        !          1494:                            &pxa2x0_memcfg);
        !          1495:                        freq = 520;
        !          1496:                }
        !          1497:        } else if (newfreq == 624) {
        !          1498:                if (freq < 208) {
        !          1499:                        pxa2x0_pi2c_setvoltage(sc->sc_iot, sc->sc_pm_ioh,
        !          1500:                            PI2C_VOLTAGE_HIGH);
        !          1501:                        pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X2 |
        !          1502:                            CCCR_RUN_X16, CLKCFG_F, &pxa2x0_memcfg);
        !          1503:                        pxa27x_fastbus_run_mode(1, pxa2x0_memcfg.mdrefr_high);
        !          1504:                }
        !          1505:                if (freq != 624) {
        !          1506:                        pxa27x_frequency_change(CCCR_A | CCCR_TURBO_X3 |
        !          1507:                            CCCR_RUN_X16, CLKCFG_B | CLKCFG_F | CLKCFG_T,
        !          1508:                            &pxa2x0_memcfg);
        !          1509:                        freq = 624;
        !          1510:                }
        !          1511:        }
        !          1512:
        !          1513:        restore_interrupts(s);
        !          1514: }
        !          1515:
        !          1516: int
        !          1517: pxa2x0_cpuspeed(int *freqp)
        !          1518: {
        !          1519:        *freqp = freq;
        !          1520:        return 0;
        !          1521: }
        !          1522:
        !          1523: void pxa2x0_maxspeed(int *speedp);
        !          1524:
        !          1525: void
        !          1526: pxa2x0_maxspeed(int *speedp)
        !          1527: {
        !          1528:        /* XXX assumes a pxa270 */
        !          1529:
        !          1530:        if (*speedp < 207) {
        !          1531:                *speedp = 91;
        !          1532:        } else if (*speedp < 415) {
        !          1533:                *speedp = 208;
        !          1534:        } else if (*speedp < 519) {
        !          1535:                *speedp = 416;
        !          1536:        } else if (*speedp < 624) {
        !          1537:                *speedp = 520;
        !          1538: #if 0
        !          1539:        } else if (*speedp < 651) {
        !          1540:                *speedp = 624;
        !          1541: #endif
        !          1542:        } else {
        !          1543:                *speedp = 520; /* hope this is safe. */
        !          1544:        }
        !          1545:        xscale_maxspeed = *speedp;
        !          1546:        pxa2x0_setperf(perflevel);
        !          1547: }

CVSweb