[BACK]Return to cpu.c CVS log [TXT][DIR] Up to [local] / sys / arch / macppc / macppc

Annotation of sys/arch/macppc/macppc/cpu.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cpu.c,v 1.43 2007/05/23 23:40:21 kettenis Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1997 Per Fogelstrom
        !             5:  * Copyright (c) 1997 RTMX Inc
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed under OpenBSD for RTMX Inc
        !            18:  *     North Carolina, USA, by Per Fogelstrom, Opsycon AB, Sweden.
        !            19:  * 4. The name of the author may not be used to endorse or promote products
        !            20:  *    derived from this software without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
        !            23:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            24:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
        !            26:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            32:  * SUCH DAMAGE.
        !            33:  *
        !            34:  */
        !            35:
        !            36: #include <sys/param.h>
        !            37: #include <sys/systm.h>
        !            38: #include <sys/proc.h>
        !            39: #include <sys/user.h>
        !            40: #include <sys/device.h>
        !            41:
        !            42: #include <dev/ofw/openfirm.h>
        !            43:
        !            44: #include <machine/autoconf.h>
        !            45: #include <machine/bat.h>
        !            46: #include <machine/trap.h>
        !            47:
        !            48: /* only valid on 603(e,ev) and G3, G4 */
        !            49: #define HID0_DOZE      (1 << (31-8))
        !            50: #define HID0_NAP       (1 << (31-9))
        !            51: #define HID0_SLEEP     (1 << (31-10))
        !            52: #define HID0_DPM       (1 << (31-11))
        !            53: #define HID0_SGE       (1 << (31-24))
        !            54: #define HID0_BTIC      (1 << (31-26))
        !            55: #define HID0_LRSTK     (1 << (31-27))
        !            56: #define HID0_FOLD      (1 << (31-28))
        !            57: #define HID0_BHT       (1 << (31-29))
        !            58:
        !            59: /* SCOM addresses (24-bit) */
        !            60: #define SCOM_PCR       0x0aa001 /* Power Control Register */
        !            61: #define SCOM_PSR       0x408001 /* Power Tuning Status Register */
        !            62:
        !            63: /* SCOMC format */
        !            64: #define SCOMC_ADDR_SHIFT       8
        !            65: #define SCOMC_ADDR_MASK                0xffff0000
        !            66: #define SCOMC_READ             0x00008000
        !            67:
        !            68: /* Frequency scaling */
        !            69: #define FREQ_FULL      0
        !            70: #define FREQ_HALF      1
        !            71: #define FREQ_QUARTER   2       /* Not supported on IBM 970FX */
        !            72:
        !            73: /* Power (Tuning) Status Register */
        !            74: #define PSR_CMD_RECEIVED       0x2000000000000000LL
        !            75: #define PSR_CMD_COMPLETED      0x1000000000000000LL
        !            76: #define PSR_FREQ_MASK          0x0300000000000000LL
        !            77: #define PSR_FREQ_HALF          0x0100000000000000LL
        !            78:
        !            79: struct cpu_info cpu_info[PPC_MAXPROCS];
        !            80:
        !            81: char cpu_model[80];
        !            82: char machine[] = MACHINE;      /* cpu architecture */
        !            83:
        !            84: /* Definition of the driver for autoconfig. */
        !            85: int    cpumatch(struct device *, void *, void *);
        !            86: void   cpuattach(struct device *, struct device *, void *);
        !            87:
        !            88: struct cfattach cpu_ca = {
        !            89:        sizeof(struct device), cpumatch, cpuattach
        !            90: };
        !            91:
        !            92: struct cfdriver cpu_cd = {
        !            93:        NULL, "cpu", DV_DULL
        !            94: };
        !            95:
        !            96: void ppc64_scale_frequency(u_int);
        !            97: void (*ppc64_slew_voltage)(u_int);
        !            98: void ppc64_setperf(int);
        !            99:
        !           100: void config_l2cr(int);
        !           101:
        !           102: int
        !           103: cpumatch(struct device *parent, void *cfdata, void *aux)
        !           104: {
        !           105:        struct confargs *ca = aux;
        !           106:        int *reg = ca->ca_reg;
        !           107:
        !           108:        /* make sure that we're looking for a CPU. */
        !           109:        if (strcmp(ca->ca_name, cpu_cd.cd_name) != 0)
        !           110:                return (0);
        !           111:
        !           112:        if (reg[0] >= PPC_MAXPROCS)
        !           113:                return (0);
        !           114:
        !           115:        return (1);
        !           116: }
        !           117:
        !           118: static u_int32_t ppc_curfreq;
        !           119: static u_int32_t ppc_maxfreq;
        !           120: int ppc_altivec;
        !           121:
        !           122:
        !           123: int
        !           124: ppc_cpuspeed(int *freq)
        !           125: {
        !           126:        *freq = ppc_curfreq;
        !           127:
        !           128:        return (0);
        !           129: }
        !           130:
        !           131: static u_int32_t ppc_power_mode_data[2];
        !           132:
        !           133: void
        !           134: ppc64_scale_frequency(u_int freq_scale)
        !           135: {
        !           136:        u_int64_t psr;
        !           137:        int s;
        !           138:
        !           139:        s = ppc_intr_disable();
        !           140:
        !           141:        /* Clear PCRH and PCR. */
        !           142:        ppc_mtscomd(0x00000000);
        !           143:        ppc_mtscomc(SCOM_PCR << SCOMC_ADDR_SHIFT);
        !           144:        ppc_mtscomd(0x80000000);
        !           145:        ppc_mtscomc(SCOM_PCR << SCOMC_ADDR_SHIFT);
        !           146:
        !           147:        /* Set PCR. */
        !           148:        ppc_mtscomd(ppc_power_mode_data[freq_scale] | 0x80000000);
        !           149:        ppc_mtscomc(SCOM_PCR << SCOMC_ADDR_SHIFT);
        !           150:
        !           151:        /* Wait until frequency change is completed. */
        !           152:        do {
        !           153:                ppc64_mtscomc((SCOM_PSR << SCOMC_ADDR_SHIFT) | SCOMC_READ);
        !           154:                psr = ppc64_mfscomd();
        !           155:                ppc64_mfscomc();
        !           156:                if (psr & PSR_CMD_COMPLETED)
        !           157:                        break;
        !           158:                DELAY(100);
        !           159:        } while (psr & PSR_CMD_RECEIVED);
        !           160:
        !           161:        if ((psr & PSR_FREQ_MASK) == PSR_FREQ_HALF)
        !           162:                ppc_curfreq = ppc_maxfreq / 2;
        !           163:        else
        !           164:                ppc_curfreq = ppc_maxfreq;
        !           165:
        !           166:        ppc_intr_enable(s);
        !           167: }
        !           168:
        !           169: extern int perflevel;
        !           170:
        !           171: void
        !           172: ppc64_setperf(int speed)
        !           173: {
        !           174:        if (speed <= 50) {
        !           175:                if (ppc_curfreq == ppc_maxfreq / 2)
        !           176:                        return;
        !           177:
        !           178:                ppc64_scale_frequency(FREQ_HALF);
        !           179:                if (ppc64_slew_voltage)
        !           180:                        ppc64_slew_voltage(FREQ_HALF);
        !           181:        } else {
        !           182:                if (ppc_curfreq == ppc_maxfreq)
        !           183:                        return;
        !           184:
        !           185:                if (ppc64_slew_voltage)
        !           186:                        ppc64_slew_voltage(FREQ_FULL);
        !           187:                ppc64_scale_frequency(FREQ_FULL);
        !           188:        }
        !           189: }
        !           190:
        !           191: int ppc_proc_is_64b;
        !           192: extern u_int32_t rfi_inst, rfid_inst, nop_inst;
        !           193: struct patch {
        !           194:        u_int32_t *s;
        !           195:        u_int32_t *e;
        !           196: };
        !           197: extern struct patch rfi_start;
        !           198: extern struct patch nop32_start;
        !           199: extern struct patch nop64_start;
        !           200:
        !           201:
        !           202: void
        !           203: ppc_check_procid()
        !           204: {
        !           205:        u_int32_t cpu, pvr;
        !           206:        u_int32_t *inst;
        !           207:        struct patch *p;
        !           208:
        !           209:        pvr = ppc_mfpvr();
        !           210:        cpu = pvr >> 16;
        !           211:
        !           212:        switch (cpu) {
        !           213:        case PPC_CPU_IBM970FX:
        !           214:        case PPC_CPU_IBM970MP:
        !           215:                ppc_proc_is_64b = 1;
        !           216:                for (p = &rfi_start; p->s; p++) {
        !           217:                        for (inst = p->s; inst < p->e; inst++)
        !           218:                                *inst = rfid_inst;
        !           219:                        syncicache(p->s, (p->e - p->s) * sizeof(*p->e));
        !           220:                }
        !           221:                for (p = &nop64_start; p->s; p++) {
        !           222:                        for (inst = p->s; inst < p->e; inst++)
        !           223:                                *inst = nop_inst;
        !           224:                        syncicache(p->s, (p->e - p->s) * sizeof(*p->e));
        !           225:                }
        !           226:
        !           227:                break;
        !           228:        default:
        !           229:                ppc_proc_is_64b = 0;
        !           230:                for (p = &nop32_start; p->s; p++) {
        !           231:                        for (inst = p->s; inst < p->e; inst++)
        !           232:                                *inst = nop_inst;
        !           233:                        syncicache(p->s, (p->e - p->s) * sizeof(p->e));
        !           234:                }
        !           235:        }
        !           236: }
        !           237:
        !           238: void
        !           239: cpuattach(struct device *parent, struct device *dev, void *aux)
        !           240: {
        !           241:        struct confargs *ca = aux;
        !           242:        int *reg = ca->ca_reg;
        !           243:        u_int32_t cpu, pvr, hid0;
        !           244:        char name[32];
        !           245:        int qhandle, phandle;
        !           246:        u_int32_t clock_freq = 0;
        !           247:        struct cpu_info *ci;
        !           248:
        !           249:        ci = &cpu_info[reg[0]];
        !           250:        ci->ci_cpuid = reg[0];
        !           251:        ci->ci_intrdepth = -1;
        !           252:        ci->ci_dev = dev;
        !           253:
        !           254:        pvr = ppc_mfpvr();
        !           255:        cpu = pvr >> 16;
        !           256:        switch (cpu) {
        !           257:        case PPC_CPU_MPC601:
        !           258:                snprintf(cpu_model, sizeof(cpu_model), "601");
        !           259:                break;
        !           260:        case PPC_CPU_MPC603:
        !           261:                snprintf(cpu_model, sizeof(cpu_model), "603");
        !           262:                break;
        !           263:        case PPC_CPU_MPC604:
        !           264:                snprintf(cpu_model, sizeof(cpu_model), "604");
        !           265:                break;
        !           266:        case PPC_CPU_MPC603e:
        !           267:                snprintf(cpu_model, sizeof(cpu_model), "603e");
        !           268:                break;
        !           269:        case PPC_CPU_MPC603ev:
        !           270:                snprintf(cpu_model, sizeof(cpu_model), "603ev");
        !           271:                break;
        !           272:        case PPC_CPU_MPC750:
        !           273:                snprintf(cpu_model, sizeof(cpu_model), "750");
        !           274:                break;
        !           275:        case PPC_CPU_MPC604ev:
        !           276:                snprintf(cpu_model, sizeof(cpu_model), "604ev");
        !           277:                break;
        !           278:        case PPC_CPU_MPC7400:
        !           279:                ppc_altivec = 1;
        !           280:                snprintf(cpu_model, sizeof(cpu_model), "7400");
        !           281:                break;
        !           282:        case PPC_CPU_MPC7447A:
        !           283:                ppc_altivec = 1;
        !           284:                snprintf(cpu_model, sizeof(cpu_model), "7447A");
        !           285:                break;
        !           286:        case PPC_CPU_IBM970FX:
        !           287:                ppc_altivec = 1;
        !           288:                snprintf(cpu_model, sizeof(cpu_model), "970FX");
        !           289:                break;
        !           290:        case PPC_CPU_IBM750FX:
        !           291:                snprintf(cpu_model, sizeof(cpu_model), "750FX");
        !           292:                break;
        !           293:        case PPC_CPU_MPC7410:
        !           294:                ppc_altivec = 1;
        !           295:                snprintf(cpu_model, sizeof(cpu_model), "7410");
        !           296:                break;
        !           297:        case PPC_CPU_MPC7450:
        !           298:                ppc_altivec = 1;
        !           299:                if ((pvr & 0xf) < 3)
        !           300:                        snprintf(cpu_model, sizeof(cpu_model), "7450");
        !           301:                 else
        !           302:                        snprintf(cpu_model, sizeof(cpu_model), "7451");
        !           303:                break;
        !           304:        case PPC_CPU_MPC7455:
        !           305:                ppc_altivec = 1;
        !           306:                snprintf(cpu_model, sizeof(cpu_model), "7455");
        !           307:                break;
        !           308:        case PPC_CPU_MPC7457:
        !           309:                ppc_altivec = 1;
        !           310:                snprintf(cpu_model, sizeof(cpu_model), "7457");
        !           311:                break;
        !           312:        default:
        !           313:                snprintf(cpu_model, sizeof(cpu_model), "Version %x", cpu);
        !           314:                break;
        !           315:        }
        !           316:        snprintf(cpu_model + strlen(cpu_model),
        !           317:            sizeof(cpu_model) - strlen(cpu_model),
        !           318:            " (Revision 0x%x)", pvr & 0xffff);
        !           319:        printf(": %s", cpu_model);
        !           320:
        !           321:        /* This should only be executed on openfirmware systems... */
        !           322:
        !           323:        for (qhandle = OF_peer(0); qhandle; qhandle = phandle) {
        !           324:                 if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0
        !           325:                     && !strcmp(name, "cpu")
        !           326:                     && OF_getprop(qhandle, "clock-frequency",
        !           327:                         &clock_freq, sizeof clock_freq) >= 0)
        !           328:                {
        !           329:                        break;
        !           330:                }
        !           331:                 if ((phandle = OF_child(qhandle)))
        !           332:                         continue;
        !           333:                 while (qhandle) {
        !           334:                         if ((phandle = OF_peer(qhandle)))
        !           335:                                 break;
        !           336:                         qhandle = OF_parent(qhandle);
        !           337:                 }
        !           338:        }
        !           339:
        !           340:        if (clock_freq != 0) {
        !           341:                /* Openfirmware stores clock in Hz, not MHz */
        !           342:                clock_freq /= 1000000;
        !           343:                printf(": %d MHz", clock_freq);
        !           344:                ppc_curfreq = ppc_maxfreq = clock_freq;
        !           345:                cpu_cpuspeed = ppc_cpuspeed;
        !           346:        }
        !           347:
        !           348:        if (cpu == PPC_CPU_IBM970FX) {
        !           349:                u_int64_t psr;
        !           350:                int s;
        !           351:
        !           352:                s = ppc_intr_disable();
        !           353:                ppc64_mtscomc((SCOM_PSR << SCOMC_ADDR_SHIFT) | SCOMC_READ);
        !           354:                psr = ppc64_mfscomd();
        !           355:                ppc64_mfscomc();
        !           356:                ppc_intr_enable(s);
        !           357:
        !           358:                if ((psr & PSR_FREQ_MASK) == PSR_FREQ_HALF) {
        !           359:                        ppc_curfreq = ppc_maxfreq / 2;
        !           360:                        perflevel = 50;
        !           361:                }
        !           362:
        !           363:                if (OF_getprop(qhandle, "power-mode-data",
        !           364:                    &ppc_power_mode_data, sizeof ppc_power_mode_data) >= 8)
        !           365:                        cpu_setperf = ppc64_setperf;
        !           366:        }
        !           367:
        !           368:        /* power savings mode */
        !           369:        if (ppc_proc_is_64b == 0)
        !           370:                hid0 = ppc_mfhid0();
        !           371:        switch (cpu) {
        !           372:        case PPC_CPU_MPC603:
        !           373:        case PPC_CPU_MPC603e:
        !           374:        case PPC_CPU_MPC750:
        !           375:        case PPC_CPU_MPC7400:
        !           376:        case PPC_CPU_IBM750FX:
        !           377:        case PPC_CPU_MPC7410:
        !           378:                /* select DOZE mode */
        !           379:                hid0 &= ~(HID0_NAP | HID0_SLEEP);
        !           380:                hid0 |= HID0_DOZE | HID0_DPM;
        !           381:                break;
        !           382:        case PPC_CPU_MPC7447A:
        !           383:        case PPC_CPU_MPC7450:
        !           384:        case PPC_CPU_MPC7455:
        !           385:        case PPC_CPU_MPC7457:
        !           386:                /* select NAP mode */
        !           387:                hid0 &= ~(HID0_DOZE | HID0_SLEEP);
        !           388:                hid0 |= HID0_NAP | HID0_DPM;
        !           389:                /* try some other flags */
        !           390:                hid0 |= HID0_SGE | HID0_BTIC;
        !           391:                hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT;
        !           392:                /* Disable BTIC on 7450 Rev 2.0 or earlier */
        !           393:                if (cpu == PPC_CPU_MPC7450 && (pvr & 0xffff) < 0x0200)
        !           394:                        hid0 &= ~HID0_BTIC;
        !           395:                break;
        !           396:        case PPC_CPU_IBM970FX:
        !           397:                /* select NAP mode */
        !           398:                hid0 &= ~(HID0_DOZE | HID0_SLEEP);
        !           399:                hid0 |= HID0_NAP | HID0_DPM;
        !           400:                break;
        !           401:        }
        !           402:        if (ppc_proc_is_64b == 0)
        !           403:                ppc_mthid0(hid0);
        !           404:
        !           405:        /* if processor is G3 or G4, configure l2 cache */
        !           406:        if (cpu == PPC_CPU_MPC750 || cpu == PPC_CPU_MPC7400 ||
        !           407:            cpu == PPC_CPU_IBM750FX || cpu == PPC_CPU_MPC7410 ||
        !           408:            cpu == PPC_CPU_MPC7447A || cpu == PPC_CPU_MPC7450 ||
        !           409:            cpu == PPC_CPU_MPC7455 || cpu == PPC_CPU_MPC7457) {
        !           410:                config_l2cr(cpu);
        !           411:        }
        !           412:        printf("\n");
        !           413: }
        !           414:
        !           415: /* L2CR bit definitions */
        !           416: #define L2CR_L2E        0x80000000 /* 0: L2 enable */
        !           417: #define L2CR_L2PE       0x40000000 /* 1: L2 data parity enable */
        !           418: #define L2CR_L2SIZ      0x30000000 /* 2-3: L2 size */
        !           419: #define  L2SIZ_RESERVED         0x00000000
        !           420: #define  L2SIZ_256K             0x10000000
        !           421: #define  L2SIZ_512K             0x20000000
        !           422: #define  L2SIZ_1M       0x30000000
        !           423: #define L2CR_L2CLK      0x0e000000 /* 4-6: L2 clock ratio */
        !           424: #define  L2CLK_DIS              0x00000000 /* disable L2 clock */
        !           425: #define  L2CLK_10               0x02000000 /* core clock / 1   */
        !           426: #define  L2CLK_15               0x04000000 /*            / 1.5 */
        !           427: #define  L2CLK_20               0x08000000 /*            / 2   */
        !           428: #define  L2CLK_25               0x0a000000 /*            / 2.5 */
        !           429: #define  L2CLK_30               0x0c000000 /*            / 3   */
        !           430: #define L2CR_L2RAM      0x01800000 /* 7-8: L2 RAM type */
        !           431: #define  L2RAM_FLOWTHRU_BURST   0x00000000
        !           432: #define  L2RAM_PIPELINE_BURST   0x01000000
        !           433: #define  L2RAM_PIPELINE_LATE    0x01800000
        !           434: #define L2CR_L2DO       0x00400000 /* 9: L2 data-only.
        !           435:                                       Setting this bit disables instruction
        !           436:                                       caching. */
        !           437: #define L2CR_L2I        0x00200000 /* 10: L2 global invalidate. */
        !           438: #define L2CR_L2CTL      0x00100000 /* 11: L2 RAM control (ZZ enable).
        !           439:                                       Enables automatic operation of the
        !           440:                                       L2ZZ (low-power mode) signal. */
        !           441: #define L2CR_L2WT       0x00080000 /* 12: L2 write-through. */
        !           442: #define L2CR_L2TS       0x00040000 /* 13: L2 test support. */
        !           443: #define L2CR_L2OH       0x00030000 /* 14-15: L2 output hold. */
        !           444: #define L2CR_L2SL       0x00008000 /* 16: L2 DLL slow. */
        !           445: #define L2CR_L2DF       0x00004000 /* 17: L2 differential clock. */
        !           446: #define L2CR_L2BYP      0x00002000 /* 18: L2 DLL bypass. */
        !           447: #define L2CR_L2IP       0x00000001 /* 31: L2 global invalidate in progress
        !           448:                                       (read only). */
        !           449: #ifdef L2CR_CONFIG
        !           450: u_int l2cr_config = L2CR_CONFIG;
        !           451: #else
        !           452: u_int l2cr_config = 0;
        !           453: #endif
        !           454:
        !           455: /* L3CR bit definitions */
        !           456: #define   L3CR_L3E                0x80000000 /*  0: L3 enable */
        !           457: #define   L3CR_L3SIZ              0x10000000 /*  3: L3 size (0=1MB, 1=2MB) */
        !           458:
        !           459: void
        !           460: config_l2cr(int cpu)
        !           461: {
        !           462:        u_int l2cr, x;
        !           463:
        !           464:        l2cr = ppc_mfl2cr();
        !           465:
        !           466:        /*
        !           467:         * Configure L2 cache if not enabled.
        !           468:         */
        !           469:        if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) {
        !           470:                l2cr = l2cr_config;
        !           471:                ppc_mtl2cr(l2cr);
        !           472:
        !           473:                /* Wait for L2 clock to be stable (640 L2 clocks). */
        !           474:                delay(100);
        !           475:
        !           476:                /* Invalidate all L2 contents. */
        !           477:                l2cr |= L2CR_L2I;
        !           478:                ppc_mtl2cr(l2cr);
        !           479:                do {
        !           480:                        x = ppc_mfl2cr();
        !           481:                } while (x & L2CR_L2IP);
        !           482:
        !           483:                /* Enable L2 cache. */
        !           484:                l2cr &= ~L2CR_L2I;
        !           485:                l2cr |= L2CR_L2E;
        !           486:                ppc_mtl2cr(l2cr);
        !           487:        }
        !           488:
        !           489:        if (l2cr & L2CR_L2E) {
        !           490:                if (cpu == PPC_CPU_MPC7450 || cpu == PPC_CPU_MPC7455) {
        !           491:                        u_int l3cr;
        !           492:
        !           493:                        printf(": 256KB L2 cache");
        !           494:
        !           495:                        l3cr = ppc_mfl3cr();
        !           496:                        if (l3cr & L3CR_L3E)
        !           497:                                printf(", %cMB L3 cache",
        !           498:                                    l3cr & L3CR_L3SIZ ? '2' : '1');
        !           499:                } else if (cpu == PPC_CPU_IBM750FX ||
        !           500:                           cpu == PPC_CPU_MPC7447A || cpu == PPC_CPU_MPC7457)
        !           501:                        printf(": 512KB L2 cache");
        !           502:                else {
        !           503:                        switch (l2cr & L2CR_L2SIZ) {
        !           504:                        case L2SIZ_256K:
        !           505:                                printf(": 256KB");
        !           506:                                break;
        !           507:                        case L2SIZ_512K:
        !           508:                                printf(": 512KB");
        !           509:                                break;
        !           510:                        case L2SIZ_1M:
        !           511:                                printf(": 1MB");
        !           512:                                break;
        !           513:                        default:
        !           514:                                printf(": unknown size");
        !           515:                        }
        !           516:                        printf(" backside cache");
        !           517:                }
        !           518: #if 0
        !           519:                switch (l2cr & L2CR_L2RAM) {
        !           520:                case L2RAM_FLOWTHRU_BURST:
        !           521:                        printf(" Flow-through synchronous burst SRAM");
        !           522:                        break;
        !           523:                case L2RAM_PIPELINE_BURST:
        !           524:                        printf(" Pipelined synchronous burst SRAM");
        !           525:                        break;
        !           526:                case L2RAM_PIPELINE_LATE:
        !           527:                        printf(" Pipelined synchronous late-write SRAM");
        !           528:                        break;
        !           529:                default:
        !           530:                        printf(" unknown type");
        !           531:                }
        !           532:
        !           533:                if (l2cr & L2CR_L2PE)
        !           534:                        printf(" with parity");
        !           535: #endif
        !           536:        } else
        !           537:                printf(": L2 cache not enabled");
        !           538: }
        !           539:
        !           540: #ifdef MULTIPROCESSOR
        !           541:
        !           542: #define        INTSTK  (8*1024)                /* 8K interrupt stack */
        !           543:
        !           544: int cpu_spinup(struct device *, struct cpu_info *);
        !           545: void cpu_hatch(void);
        !           546: void cpu_spinup_trampoline(void);
        !           547:
        !           548: struct cpu_hatch_data {
        !           549:        struct cpu_info *ci;
        !           550:        int running;
        !           551:        int hid0;
        !           552:        int sdr1;
        !           553:        int tbu, tbl;
        !           554: };
        !           555:
        !           556: volatile struct cpu_hatch_data *cpu_hatch_data;
        !           557: volatile int cpu_hatch_stack;
        !           558:
        !           559: int
        !           560: cpu_spinup(struct device *self, struct cpu_info *ci)
        !           561: {
        !           562:        volatile struct cpu_hatch_data hatch_data, *h = &hatch_data;
        !           563:        int i;
        !           564:        struct pcb *pcb;
        !           565:        struct pglist mlist;
        !           566:        struct vm_page *m;
        !           567:        int error;
        !           568:        int size = 0;
        !           569:        char *cp;
        !           570:        u_char *reset_cpu;
        !           571:
        !           572:         /*
        !           573:          * Allocate some contiguous pages for the idle PCB and stack
        !           574:          * from the lowest 256MB (because bat0 always maps it va == pa).
        !           575:          */
        !           576:         size += USPACE;
        !           577:         size += INTSTK;
        !           578:         size += 4096;   /* SPILLSTK */
        !           579:
        !           580:        TAILQ_INIT(&mlist);
        !           581:        error = uvm_pglistalloc(size, 0x0, 0x10000000, 0, 0, &mlist, 1, 1);
        !           582:        if (error) {
        !           583:                printf(": unable to allocate idle stack\n");
        !           584:                return -1;
        !           585:        }
        !           586:
        !           587:        m = TAILQ_FIRST(&mlist);
        !           588:        cp = (char *)VM_PAGE_TO_PHYS(m);
        !           589:        bzero(cp, size);
        !           590:
        !           591:         pcb = (struct pcb *)cp;
        !           592:         ci->ci_idle_pcb = pcb;
        !           593:         ci->ci_intstk = cp + USPACE + INTSTK;
        !           594:
        !           595:         /*
        !           596:          * Initialize the idle stack pointer, reserving space for an
        !           597:          * (empty) trapframe (XXX is the trapframe really necessary?)
        !           598:          */
        !           599:         pcb->pcb_sp = (paddr_t)pcb + USPACE - sizeof(struct trapframe);
        !           600:        cpu_hatch_stack = ci->ci_idle_pcb->pcb_sp;
        !           601:
        !           602:        h->ci = ci;
        !           603:        h->running = 0;
        !           604:        h->hid0 = ppc_mfhid0();
        !           605:        h->sdr1 = ppc_mfsdr1();
        !           606:        cpu_hatch_data = h;
        !           607:
        !           608: #ifdef notyet
        !           609:        ci->ci_lasttb = curcpu()->ci_lasttb;
        !           610: #endif
        !           611:
        !           612:        __asm volatile ("sync; isync");
        !           613:
        !           614:        /* XXX OpenPIC */
        !           615:        {
        !           616:                uint64_t tb;
        !           617:
        !           618:                *(u_int *)EXC_RST = 0x48000002 | (u_int)cpu_spinup_trampoline;
        !           619:                syncicache((void *)EXC_RST, 0x100);
        !           620:
        !           621:                h->running = -1;
        !           622:
        !           623:                /* Start secondary CPU. */
        !           624:                reset_cpu = mapiodev(0x80000000 + 0x5c, 1);
        !           625:                *reset_cpu = 0x4;
        !           626:                __asm volatile ("eieio" ::: "memory");
        !           627:                *reset_cpu = 0x5;
        !           628:                __asm volatile ("eieio" ::: "memory");
        !           629:
        !           630:                /* Sync timebase. */
        !           631:                tb = ppc_mftb();
        !           632:                tb += 100000;   /* 3ms @ 33MHz  */
        !           633:
        !           634:                h->tbu = tb >> 32;
        !           635:                h->tbl = tb & 0xffffffff;
        !           636:
        !           637:                while (tb > ppc_mftb())
        !           638:                        ;
        !           639:                 __asm volatile ("sync; isync");
        !           640:                 h->running = 0;
        !           641:
        !           642:                 delay(500000);
        !           643:        }
        !           644:
        !           645:        printf("cpu%d: timebase %llx\n", cpu_number(), ppc_mftb());
        !           646:
        !           647:        for (i = 0; i < 0x3fffffff; i++)
        !           648:                if (h->running) {
        !           649:                        printf("running\n");
        !           650:                        break;
        !           651:                }
        !           652:
        !           653:        return 0;
        !           654: }
        !           655:
        !           656: volatile static int start_secondary_cpu;
        !           657:
        !           658: void
        !           659: cpu_boot_secondary_processors(void)
        !           660: {
        !           661:        struct cpu_info *ci;
        !           662:        int i;
        !           663:
        !           664:        for (i = 0; i < PPC_MAXPROCS; i++) {
        !           665:                ci = &cpu_info[i];
        !           666:                if (ci->ci_cpuid == 0)
        !           667:                        continue;
        !           668:                cpu_spinup(NULL, ci);
        !           669:        }
        !           670:
        !           671:        start_secondary_cpu = 1;
        !           672:        __asm volatile ("sync");
        !           673: }
        !           674:
        !           675: void
        !           676: cpu_hatch(void)
        !           677: {
        !           678:        volatile struct cpu_hatch_data *h = cpu_hatch_data;
        !           679:        int scratch, i;
        !           680:
        !           681:         /* Initialize timebase. */
        !           682:         __asm ("mttbl %0; mttbu %0; mttbl %0" :: "r"(0));
        !           683:
        !           684:        /* Initialize curcpu(). */
        !           685:        ppc_mtsprg0((u_int)h->ci);
        !           686:
        !           687:        /* Set PIR . */
        !           688:        ppc_mtpir(curcpu()->ci_cpuid);
        !           689:
        !           690:        /*
        !           691:         * Initialize BAT registers to unmapped to not generate
        !           692:         * overlapping mappings below.
        !           693:         */
        !           694:        ppc_mtibat0u(0);
        !           695:        ppc_mtibat1u(0);
        !           696:        ppc_mtibat2u(0);
        !           697:        ppc_mtibat3u(0);
        !           698:        ppc_mtdbat0u(0);
        !           699:        ppc_mtdbat1u(0);
        !           700:        ppc_mtdbat2u(0);
        !           701:        ppc_mtdbat3u(0);
        !           702:
        !           703:        /*
        !           704:         * Now setup fixed bat registers
        !           705:         *
        !           706:         * Note that we still run in real mode, and the BAT
        !           707:         * registers were cleared above.
        !           708:         */
        !           709:        /* IBAT0 used for initial 256 MB segment */
        !           710:        ppc_mtibat0l(battable[0].batl);
        !           711:        ppc_mtibat0u(battable[0].batu);
        !           712:
        !           713:        /* DBAT0 used similar */
        !           714:        ppc_mtdbat0l(battable[0].batl);
        !           715:        ppc_mtdbat0u(battable[0].batu);
        !           716:
        !           717:        /*
        !           718:         * Initialize segment registers.
        !           719:         */
        !           720:        for (i = 0; i < 16; i++)
        !           721:                ppc_mtsrin(PPC_KERNEL_SEG0 + i, i << ADDR_SR_SHIFT);
        !           722:
        !           723:        ppc_mthid0(h->hid0);
        !           724:        ppc_mtsdr1(h->sdr1);
        !           725:
        !           726:        /*
        !           727:         * Now enable translation (and machine checks/recoverable interrupts).
        !           728:         */
        !           729:        __asm__ volatile ("eieio; mfmsr %0; ori %0,%0,%1; mtmsr %0; sync;isync"
        !           730:                      : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
        !           731:
        !           732:        /* XXX OpenPIC */
        !           733:        {
        !           734:                /* Sync timebase. */
        !           735:                u_int tbu = h->tbu;
        !           736:                u_int tbl = h->tbl;
        !           737:                while (h->running == -1)
        !           738:                        ;
        !           739:                 __asm volatile ("sync; isync");
        !           740:                 __asm volatile ("mttbl %0" :: "r"(0));
        !           741:                 __asm volatile ("mttbu %0" :: "r"(tbu));
        !           742:                 __asm volatile ("mttbl %0" :: "r"(tbl));
        !           743:        }
        !           744:
        !           745:        ncpus++;
        !           746:        h->running = 1;
        !           747:        __asm volatile ("eieio" ::: "memory");
        !           748:
        !           749:        while (start_secondary_cpu == 0)
        !           750:                ;
        !           751:
        !           752:        __asm volatile ("sync; isync");
        !           753:
        !           754:        printf("cpu%d: running\n", cpu_number());
        !           755:        printf("cpu%d: timebase %llx\n", cpu_number(), ppc_mftb());
        !           756: #ifdef notyet
        !           757:        ppc_mtdec(ticks_per_intr);
        !           758: #endif
        !           759:
        !           760:        curcpu()->ci_ipending = 0;
        !           761:        curcpu()->ci_cpl = 0;
        !           762: }
        !           763: #endif

CVSweb