1 /*-
2  * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * NETLOGIC_BSD */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD: stable/10/sys/mips/nlm/xlp_machdep.c 261455 2014-02-04 03:36:42Z eadler $");
32 
33 #include "opt_ddb.h"
34 #include "opt_platform.h"
35 
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/conf.h>
39 #include <sys/rtprio.h>
40 #include <sys/systm.h>
41 #include <sys/interrupt.h>
42 #include <sys/limits.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/mutex.h>
46 #include <sys/random.h>
47 
48 #include <sys/cons.h>		/* cinit() */
49 #include <sys/kdb.h>
50 #include <sys/reboot.h>
51 #include <sys/queue.h>
52 #include <sys/smp.h>
53 #include <sys/timetc.h>
54 
55 #include <vm/vm.h>
56 #include <vm/vm_page.h>
57 
58 #include <machine/cpu.h>
59 #include <machine/cpufunc.h>
60 #include <machine/cpuinfo.h>
61 #include <machine/tlb.h>
62 #include <machine/cpuregs.h>
63 #include <machine/frame.h>
64 #include <machine/hwfunc.h>
65 #include <machine/md_var.h>
66 #include <machine/asm.h>
67 #include <machine/pmap.h>
68 #include <machine/trap.h>
69 #include <machine/clock.h>
70 #include <machine/fls64.h>
71 #include <machine/intr_machdep.h>
72 #include <machine/smp.h>
73 
74 #include <mips/nlm/hal/mips-extns.h>
75 #include <mips/nlm/hal/haldefs.h>
76 #include <mips/nlm/hal/iomap.h>
77 #include <mips/nlm/hal/sys.h>
78 #include <mips/nlm/hal/pic.h>
79 #include <mips/nlm/hal/uart.h>
80 #include <mips/nlm/hal/mmu.h>
81 #include <mips/nlm/hal/bridge.h>
82 #include <mips/nlm/hal/cpucontrol.h>
83 #include <mips/nlm/hal/cop2.h>
84 
85 #include <mips/nlm/clock.h>
86 #include <mips/nlm/interrupt.h>
87 #include <mips/nlm/board.h>
88 #include <mips/nlm/xlp.h>
89 #include <mips/nlm/msgring.h>
90 
91 #ifdef FDT
92 #include <dev/fdt/fdt_common.h>
93 #include <dev/ofw/openfirm.h>
94 #endif
95 
96 /* 4KB static data aread to keep a copy of the bootload env until
97    the dynamic kenv is setup */
98 char boot1_env[4096];
99 
100 uint64_t xlp_cpu_frequency;
101 uint64_t xlp_io_base = MIPS_PHYS_TO_DIRECT_UNCACHED(XLP_DEFAULT_IO_BASE);
102 
103 int xlp_ncores;
104 int xlp_threads_per_core;
105 uint32_t xlp_hw_thread_mask;
106 int xlp_cpuid_to_hwtid[MAXCPU];
107 int xlp_hwtid_to_cpuid[MAXCPU];
108 uint64_t xlp_pic_base;
109 
110 static int xlp_mmuval;
111 
112 extern uint32_t _end;
113 extern char XLPResetEntry[], XLPResetEntryEnd[];
114 
115 static void
xlp_setup_core(void)116 xlp_setup_core(void)
117 {
118 	uint64_t reg;
119 
120 	reg = nlm_mfcr(LSU_DEFEATURE);
121 	/* Enable Unaligned and L2HPE */
122 	reg |= (1 << 30) | (1 << 23);
123 	/*
124 	 * Experimental : Enable SUE
125 	 * Speculative Unmap Enable. Enable speculative L2 cache request for
126 	 * unmapped access.
127 	 */
128 	reg |= (1ull << 31);
129 	/* Clear S1RCM  - A0 errata */
130 	reg &= ~0xeull;
131 	nlm_mtcr(LSU_DEFEATURE, reg);
132 
133 	reg = nlm_mfcr(SCHED_DEFEATURE);
134 	/* Experimental: Disable BRU accepting ALU ops - A0 errata */
135 	reg |= (1 << 24);
136 	nlm_mtcr(SCHED_DEFEATURE, reg);
137 }
138 
139 static void
xlp_setup_mmu(void)140 xlp_setup_mmu(void)
141 {
142 	uint32_t pagegrain;
143 
144 	if (nlm_threadid() == 0) {
145 		nlm_setup_extended_pagemask(0);
146 		nlm_large_variable_tlb_en(1);
147 		nlm_extended_tlb_en(1);
148 		nlm_mmu_setup(0, 0, 0);
149 	}
150 
151 	/* Enable no-read, no-exec, large-physical-address */
152 	pagegrain = mips_rd_pagegrain();
153 	pagegrain |= (1U << 31)	|	/* RIE */
154 	    (1 << 30)		|	/* XIE */
155 	    (1 << 29);			/* ELPA */
156 	mips_wr_pagegrain(pagegrain);
157 }
158 
159 static void
xlp_enable_blocks(void)160 xlp_enable_blocks(void)
161 {
162 	uint64_t sysbase;
163 	int i;
164 
165 	for (i = 0; i < XLP_MAX_NODES; i++) {
166 		if (!nlm_dev_exists(XLP_IO_SYS_OFFSET(i)))
167 			continue;
168 		sysbase = nlm_get_sys_regbase(i);
169 		nlm_sys_enable_block(sysbase, DFS_DEVICE_RSA);
170 	}
171 }
172 
173 static void
xlp_parse_mmu_options(void)174 xlp_parse_mmu_options(void)
175 {
176 	uint64_t sysbase;
177 	uint32_t cpu_map = xlp_hw_thread_mask;
178 	uint32_t core0_thr_mask, core_thr_mask, cpu_rst_mask;
179 	int i, j, k;
180 
181 #ifdef SMP
182 	if (cpu_map == 0)
183 		cpu_map = 0xffffffff;
184 #else /* Uniprocessor! */
185 	if (cpu_map == 0)
186 		cpu_map = 0x1;
187 	else if (cpu_map != 0x1) {
188 		printf("WARNING: Starting uniprocessor kernel on cpumask [0x%lx]!\n"
189 		    "WARNING: Other CPUs will be unused.\n", (u_long)cpu_map);
190 		cpu_map = 0x1;
191 	}
192 #endif
193 
194 	xlp_ncores = 1;
195 	core0_thr_mask = cpu_map & 0xf;
196 	switch (core0_thr_mask) {
197 	case 1:
198 		xlp_threads_per_core = 1;
199 		xlp_mmuval = 0;
200 	       	break;
201 	case 3:
202 		xlp_threads_per_core = 2;
203 		xlp_mmuval = 2;
204 	       	break;
205 	case 0xf:
206 		xlp_threads_per_core = 4;
207 		xlp_mmuval = 3;
208 	       	break;
209 	default:
210 		goto unsupp;
211 	}
212 
213 	/* Try to find the enabled cores from SYS block */
214 	sysbase = nlm_get_sys_regbase(0);
215 	cpu_rst_mask = nlm_read_sys_reg(sysbase, SYS_CPU_RESET) & 0xff;
216 
217 	/* XLP 416 does not report this correctly, fix */
218 	if (nlm_processor_id() == CHIP_PROCESSOR_ID_XLP_416)
219 		cpu_rst_mask = 0xe;
220 
221 	/* Take out cores which do not exist on chip */
222 	for (i = 1; i < XLP_MAX_CORES; i++) {
223 		if ((cpu_rst_mask & (1 << i)) == 0)
224 			cpu_map &= ~(0xfu << (4 * i));
225 	}
226 
227  	/* Verify other cores' CPU masks */
228 	for (i = 1; i < XLP_MAX_CORES; i++) {
229 		core_thr_mask = (cpu_map >> (4 * i)) & 0xf;
230 		if (core_thr_mask == 0)
231 	       		continue;
232 		if (core_thr_mask != core0_thr_mask)
233 			goto unsupp;
234 		xlp_ncores++;
235 	}
236 
237 	xlp_hw_thread_mask = cpu_map;
238 	/* setup hardware processor id to cpu id mapping */
239 	for (i = 0; i< MAXCPU; i++)
240 		xlp_cpuid_to_hwtid[i] =
241 		    xlp_hwtid_to_cpuid[i] = -1;
242 	for (i = 0, k = 0; i < XLP_MAX_CORES; i++) {
243 		if (((cpu_map >> (i * 4)) & 0xf) == 0)
244 			continue;
245 		for (j = 0; j < xlp_threads_per_core; j++) {
246 			xlp_cpuid_to_hwtid[k] = i * 4 + j;
247 			xlp_hwtid_to_cpuid[i * 4 + j] = k;
248 			k++;
249 		}
250 	}
251 
252 	return;
253 
254 unsupp:
255 	printf("ERROR : Unsupported CPU mask [use 1,2 or 4 threads per core].\n"
256 	    "\tcore0 thread mask [%lx], boot cpu mask [%lx].\n",
257 	    (u_long)core0_thr_mask, (u_long)cpu_map);
258 	panic("Invalid CPU mask - halting.\n");
259 	return;
260 }
261 
262 /* Parse cmd line args as env - copied from ar71xx */
263 static void
xlp_parse_bootargs(char * cmdline)264 xlp_parse_bootargs(char *cmdline)
265 {
266 	char *n, *v;
267 
268 	while ((v = strsep(&cmdline, " \n")) != NULL) {
269 		if (*v == '\0')
270 			continue;
271 		if (*v == '-') {
272 			while (*v != '\0') {
273 				v++;
274 				switch (*v) {
275 				case 'a': boothowto |= RB_ASKNAME; break;
276 				case 'd': boothowto |= RB_KDB; break;
277 				case 'g': boothowto |= RB_GDB; break;
278 				case 's': boothowto |= RB_SINGLE; break;
279 				case 'v': boothowto |= RB_VERBOSE; break;
280 				}
281 			}
282 		} else {
283 			n = strsep(&v, "=");
284 			if (v == NULL)
285 				setenv(n, "1");
286 			else
287 				setenv(n, v);
288 		}
289 	}
290 }
291 
292 #ifdef FDT
293 static void
xlp_bootargs_init(__register_t arg)294 xlp_bootargs_init(__register_t arg)
295 {
296 	char	buf[2048]; /* early stack is big enough */
297 	void	*dtbp;
298 	phandle_t chosen;
299 	ihandle_t mask;
300 
301 	dtbp = (void *)(intptr_t)arg;
302 #if defined(FDT_DTB_STATIC)
303 	/*
304 	 * In case the device tree blob was not passed as argument try
305 	 * to use the statically embedded one.
306 	 */
307 	if (dtbp == NULL)
308 		dtbp = &fdt_static_dtb;
309 #endif
310 	if (OF_install(OFW_FDT, 0) == FALSE)
311 		while (1);
312 	if (OF_init((void *)dtbp) != 0)
313 		while (1);
314 	if (fdt_immr_addr(xlp_io_base) != 0)
315 		while (1);
316 	OF_interpret("perform-fixup", 0);
317 
318 	chosen = OF_finddevice("/chosen");
319 	if (OF_getprop(chosen, "cpumask", &mask, sizeof(mask)) != -1) {
320 		xlp_hw_thread_mask = mask;
321 	}
322 
323 	if (OF_getprop(chosen, "bootargs", buf, sizeof(buf)) != -1)
324 		xlp_parse_bootargs(buf);
325 }
326 #else
327 /*
328  * arg is a pointer to the environment block, the format of the block is
329  * a=xyz\0b=pqr\0\0
330  */
331 static void
xlp_bootargs_init(__register_t arg)332 xlp_bootargs_init(__register_t arg)
333 {
334 	char	buf[2048]; /* early stack is big enough */
335 	char	*p, *v, *n;
336 	uint32_t mask;
337 
338 	/*
339 	 * provide backward compat for passing cpu mask as arg
340 	 */
341 	if (arg & 1) {
342 		xlp_hw_thread_mask = arg;
343 		return;
344 	}
345 
346 	p = (void *)(intptr_t)arg;
347 	while (*p != '\0') {
348 		strlcpy(buf, p, sizeof(buf));
349 		v = buf;
350 		n = strsep(&v, "=");
351 		if (v == NULL)
352 			setenv(n, "1");
353 		else
354 			setenv(n, v);
355 		p += strlen(p) + 1;
356 	}
357 
358 	/* CPU mask can be passed thru env */
359 	if (getenv_uint("cpumask", &mask) != 0)
360 		xlp_hw_thread_mask = mask;
361 
362 	/* command line argument */
363 	v = getenv("bootargs");
364 	if (v != NULL) {
365 		strlcpy(buf, v, sizeof(buf));
366 		xlp_parse_bootargs(buf);
367 		freeenv(v);
368 	}
369 }
370 #endif
371 
372 static void
mips_init(void)373 mips_init(void)
374 {
375 	init_param1();
376 	init_param2(physmem);
377 
378 	mips_cpu_init();
379 	cpuinfo.cache_coherent_dma = TRUE;
380 	pmap_bootstrap();
381 	mips_proc0_init();
382 	mutex_init();
383 #ifdef DDB
384 	kdb_init();
385 	if (boothowto & RB_KDB) {
386 		kdb_enter("Boot flags requested debugger", NULL);
387 	}
388 #endif
389 }
390 
391 unsigned int
platform_get_timecount(struct timecounter * tc __unused)392 platform_get_timecount(struct timecounter *tc __unused)
393 {
394 	uint64_t count = nlm_pic_read_timer(xlp_pic_base, PIC_CLOCK_TIMER);
395 
396 	return (unsigned int)~count;
397 }
398 
399 static void
xlp_pic_init(void)400 xlp_pic_init(void)
401 {
402 	struct timecounter pic_timecounter = {
403 		platform_get_timecount, /* get_timecount */
404 		0,                      /* no poll_pps */
405 		~0U,                    /* counter_mask */
406 		XLP_IO_CLK,            /* frequency */
407 		"XLRPIC",               /* name */
408 		2000,                   /* quality (adjusted in code) */
409 	};
410         int i;
411 	int maxirt;
412 
413 	xlp_pic_base = nlm_get_pic_regbase(0);  /* TOOD: Add other nodes */
414 	maxirt = nlm_read_reg(nlm_get_pic_pcibase(nlm_nodeid()),
415 	    XLP_PCI_DEVINFO_REG0);
416         printf("Initializing PIC...@%jx %d IRTs\n", (uintmax_t)xlp_pic_base,
417 	    maxirt);
418 	/* Bind all PIC irqs to cpu 0 */
419         for (i = 0; i < maxirt; i++)
420 	    nlm_pic_write_irt(xlp_pic_base, i, 0, 0, 1, 0,
421 	    1, 0, 0x1);
422 
423 	nlm_pic_set_timer(xlp_pic_base, PIC_CLOCK_TIMER, ~0ULL, 0, 0);
424 	platform_timecounter = &pic_timecounter;
425 }
426 
427 #if defined(__mips_n32) || defined(__mips_n64) /* PHYSADDR_64_BIT */
428 #ifdef XLP_SIM
429 #define	XLP_MEM_LIM	0x200000000ULL
430 #else
431 #define	XLP_MEM_LIM	0x10000000000ULL
432 #endif
433 #else
434 #define	XLP_MEM_LIM	0xfffff000UL
435 #endif
436 static vm_paddr_t xlp_mem_excl[] = {
437 	0,          0,		/* for kernel image region, see xlp_mem_init */
438 	0x0c000000, 0x14000000,	/* uboot area, cms queue and other stuff */
439 	0x1fc00000, 0x1fd00000,	/* reset vec */
440 	0x1e000000, 0x1e200000,	/* poe buffers */
441 };
442 
443 static int
mem_exclude_add(vm_paddr_t * avail,vm_paddr_t mstart,vm_paddr_t mend)444 mem_exclude_add(vm_paddr_t *avail, vm_paddr_t mstart, vm_paddr_t mend)
445 {
446 	int nreg = sizeof(xlp_mem_excl)/sizeof(xlp_mem_excl[0]);
447 	int i, pos;
448 
449 	pos = 0;
450 	for (i = 0; i < nreg; i += 2) {
451 		if (mstart > xlp_mem_excl[i + 1])
452 			continue;
453 		if (mstart < xlp_mem_excl[i]) {
454 			avail[pos++] = mstart;
455 			if (mend < xlp_mem_excl[i])
456 				avail[pos++] = mend;
457 			else
458 				avail[pos++] = xlp_mem_excl[i];
459 		}
460 		mstart = xlp_mem_excl[i + 1];
461 		if (mend <= mstart)
462 			break;
463 	}
464 	if (mstart < mend) {
465 		avail[pos++] = mstart;
466 		avail[pos++] = mend;
467 	}
468 	return (pos);
469 }
470 
471 static void
xlp_mem_init(void)472 xlp_mem_init(void)
473 {
474 	vm_paddr_t physsz, tmp;
475 	uint64_t bridgebase, base, lim, val;
476 	int i, j, k, n;
477 
478 	/* update kernel image area in exclude regions */
479 	tmp = (vm_paddr_t)MIPS_KSEG0_TO_PHYS(&_end);
480 	tmp = round_page(tmp) + 0x20000; /* round up */
481 	xlp_mem_excl[1] = tmp;
482 
483 	printf("Memory (from DRAM BARs):\n");
484 	bridgebase = nlm_get_bridge_regbase(0); /* TODO: Add other nodes */
485 	physsz = 0;
486         for (i = 0, j = 0; i < 8; i++) {
487 		val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_BAR(i));
488                 val = (val >>  12) & 0xfffff;
489 		base = val << 20;
490 		val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_LIMIT(i));
491                 val = (val >>  12) & 0xfffff;
492 		if (val == 0)	/* BAR not enabled */
493 			continue;
494                 lim = (val + 1) << 20;
495 		printf("  BAR %d: %#jx - %#jx : ", i, (intmax_t)base,
496 		    (intmax_t)lim);
497 
498 		if (lim <= base) {
499 			printf("\tskipped - malformed %#jx -> %#jx\n",
500 			    (intmax_t)base, (intmax_t)lim);
501 			continue;
502 		} else if (base >= XLP_MEM_LIM) {
503 			printf(" skipped - outside usable limit %#jx.\n",
504 			    (intmax_t)XLP_MEM_LIM);
505 			continue;
506 		} else if (lim >= XLP_MEM_LIM) {
507 			lim = XLP_MEM_LIM;
508 			printf(" truncated to %#jx.\n", (intmax_t)XLP_MEM_LIM);
509 		} else
510 			printf(" usable\n");
511 
512 		/* exclude unusable regions from BAR and add rest */
513 		n = mem_exclude_add(&phys_avail[j], base, lim);
514 		for (k = j; k < j + n; k += 2) {
515 			physsz += phys_avail[k + 1] - phys_avail[k];
516 			printf("\tMem[%d]: %#jx - %#jx\n", k/2,
517 			    (intmax_t)phys_avail[k], (intmax_t)phys_avail[k+1]);
518 		}
519 		j = k;
520         }
521 
522 	/* setup final entry with 0 */
523 	phys_avail[j] = phys_avail[j + 1] = 0;
524 
525 	/* copy phys_avail to dump_avail */
526 	for (i = 0; i <= j + 1; i++)
527 		dump_avail[i] = phys_avail[i];
528 
529 	realmem = physmem = btoc(physsz);
530 }
531 
532 void
platform_start(__register_t a0 __unused,__register_t a1 __unused,__register_t a2 __unused,__register_t a3 __unused)533 platform_start(__register_t a0 __unused,
534     __register_t a1 __unused,
535     __register_t a2 __unused,
536     __register_t a3 __unused)
537 {
538 
539 	/* Initialize pcpu stuff */
540 	mips_pcpu0_init();
541 
542 	/* initialize console so that we have printf */
543 	boothowto |= (RB_SERIAL | RB_MULTIPLE);	/* Use multiple consoles */
544 
545 	init_static_kenv(boot1_env, sizeof(boot1_env));
546 	xlp_bootargs_init(a0);
547 
548 	/* clockrate used by delay, so initialize it here */
549 	xlp_cpu_frequency = xlp_get_cpu_frequency(0, 0);
550 	cpu_clock = xlp_cpu_frequency / 1000000;
551 	mips_timer_early_init(xlp_cpu_frequency);
552 
553 	/* Init console please */
554 	cninit();
555 
556 	/* Early core init and fixes for errata */
557 	xlp_setup_core();
558 
559 	xlp_parse_mmu_options();
560 	xlp_mem_init();
561 
562 	bcopy(XLPResetEntry, (void *)MIPS_RESET_EXC_VEC,
563               XLPResetEntryEnd - XLPResetEntry);
564 #ifdef SMP
565 	/*
566 	 * We will enable the other threads in core 0 here
567 	 * so that the TLB and cache info is correct when
568 	 * mips_init runs
569 	 */
570 	xlp_enable_threads(xlp_mmuval);
571 #endif
572 	/* setup for the startup core */
573 	xlp_setup_mmu();
574 
575 	xlp_enable_blocks();
576 
577 	/* Read/Guess/setup board information */
578 	nlm_board_info_setup();
579 
580 	/* MIPS generic init */
581 	mips_init();
582 
583 	/*
584 	 * XLP specific post initialization
585  	 * initialize other on chip stuff
586 	 */
587 	xlp_pic_init();
588 
589 	mips_timer_init_params(xlp_cpu_frequency, 0);
590 }
591 
592 void
platform_cpu_init()593 platform_cpu_init()
594 {
595 }
596 
597 void
platform_reset(void)598 platform_reset(void)
599 {
600 	uint64_t sysbase = nlm_get_sys_regbase(0);
601 
602 	nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
603 	for( ; ; )
604 		__asm __volatile("wait");
605 }
606 
607 #ifdef SMP
608 /*
609  * XLP threads are started simultaneously when we enable threads, this will
610  * ensure that the threads are blocked in platform_init_ap, until they are
611  * ready to proceed to smp_init_secondary()
612  */
613 static volatile int thr_unblock[4];
614 
615 int
platform_start_ap(int cpuid)616 platform_start_ap(int cpuid)
617 {
618 	uint32_t coremask, val;
619 	uint64_t sysbase = nlm_get_sys_regbase(0);
620 	int hwtid = xlp_cpuid_to_hwtid[cpuid];
621 	int core, thr;
622 
623 	core = hwtid / 4;
624 	thr = hwtid % 4;
625 	if (thr == 0) {
626 		/* First thread in core, do core wake up */
627 		coremask = 1u << core;
628 
629 		/* Enable core clock */
630 		val = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
631 		val &= ~coremask;
632 		nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, val);
633 
634 		/* Remove CPU Reset */
635 		val = nlm_read_sys_reg(sysbase, SYS_CPU_RESET);
636 		val &=  ~coremask & 0xff;
637 		nlm_write_sys_reg(sysbase, SYS_CPU_RESET, val);
638 
639 		if (bootverbose)
640 			printf("Waking up core %d ...", core);
641 
642 		/* Poll for CPU to mark itself coherent */
643 		do {
644 			val = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
645        		} while ((val & coremask) != 0);
646 		if (bootverbose)
647 			printf("Done\n");
648         } else {
649 		/* otherwise release the threads stuck in platform_init_ap */
650 		thr_unblock[thr] = 1;
651 	}
652 
653 	return (0);
654 }
655 
656 void
platform_init_ap(int cpuid)657 platform_init_ap(int cpuid)
658 {
659 	uint32_t stat;
660 	int thr;
661 
662 	/* The first thread has to setup the MMU and enable other threads */
663 	thr = nlm_threadid();
664 	if (thr == 0) {
665 		xlp_setup_core();
666 		xlp_enable_threads(xlp_mmuval);
667 	} else {
668 		/*
669 		 * FIXME busy wait here eats too many cycles, especially
670 		 * in the core 0 while bootup
671 		 */
672 		while (thr_unblock[thr] == 0)
673 			__asm__ __volatile__ ("nop;nop;nop;nop");
674 		thr_unblock[thr] = 0;
675 	}
676 
677 	xlp_setup_mmu();
678 	stat = mips_rd_status();
679 	KASSERT((stat & MIPS_SR_INT_IE) == 0,
680 	    ("Interrupts enabled in %s!", __func__));
681 	stat |= MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT;
682 	mips_wr_status(stat);
683 
684 	nlm_write_c0_eimr(0ull);
685 	xlp_enable_irq(IRQ_IPI);
686 	xlp_enable_irq(IRQ_TIMER);
687 	xlp_enable_irq(IRQ_MSGRING);
688 
689 	return;
690 }
691 
692 int
platform_ipi_intrnum(void)693 platform_ipi_intrnum(void)
694 {
695 
696 	return (IRQ_IPI);
697 }
698 
699 void
platform_ipi_send(int cpuid)700 platform_ipi_send(int cpuid)
701 {
702 
703 	nlm_pic_send_ipi(xlp_pic_base, xlp_cpuid_to_hwtid[cpuid],
704 	    platform_ipi_intrnum(), 0);
705 }
706 
707 void
platform_ipi_clear(void)708 platform_ipi_clear(void)
709 {
710 }
711 
712 int
platform_processor_id(void)713 platform_processor_id(void)
714 {
715 
716 	return (xlp_hwtid_to_cpuid[nlm_cpuid()]);
717 }
718 
719 void
platform_cpu_mask(cpuset_t * mask)720 platform_cpu_mask(cpuset_t *mask)
721 {
722 	int i, s;
723 
724 	CPU_ZERO(mask);
725 	s = xlp_ncores * xlp_threads_per_core;
726 	for (i = 0; i < s; i++)
727 		CPU_SET(i, mask);
728 }
729 
730 struct cpu_group *
platform_smp_topo()731 platform_smp_topo()
732 {
733 
734 	return (smp_topo_2level(CG_SHARE_L2, xlp_ncores, CG_SHARE_L1,
735 		xlp_threads_per_core, CG_FLAG_THREAD));
736 }
737 #endif
738