[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

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