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