2 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
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
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.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
38 #include <sys/rtprio.h>
39 #include <sys/systm.h>
40 #include <sys/interrupt.h>
41 #include <sys/limits.h>
43 #include <sys/malloc.h>
44 #include <sys/mutex.h>
45 #include <sys/random.h>
47 #include <sys/cons.h> /* cinit() */
49 #include <sys/reboot.h>
50 #include <sys/queue.h>
52 #include <sys/timetc.h>
55 #include <vm/vm_page.h>
57 #include <machine/cpu.h>
58 #include <machine/cpufunc.h>
59 #include <machine/cpuinfo.h>
60 #include <machine/tlb.h>
61 #include <machine/cpuregs.h>
62 #include <machine/frame.h>
63 #include <machine/hwfunc.h>
64 #include <machine/md_var.h>
65 #include <machine/asm.h>
66 #include <machine/pmap.h>
67 #include <machine/trap.h>
68 #include <machine/clock.h>
69 #include <machine/fls64.h>
70 #include <machine/intr_machdep.h>
71 #include <machine/smp.h>
73 #include <mips/nlm/hal/mips-extns.h>
74 #include <mips/nlm/hal/haldefs.h>
75 #include <mips/nlm/hal/iomap.h>
76 #include <mips/nlm/hal/sys.h>
77 #include <mips/nlm/hal/pic.h>
78 #include <mips/nlm/hal/uart.h>
79 #include <mips/nlm/hal/mmu.h>
80 #include <mips/nlm/hal/bridge.h>
81 #include <mips/nlm/hal/cpucontrol.h>
83 #include <mips/nlm/clock.h>
84 #include <mips/nlm/interrupt.h>
85 #include <mips/nlm/board.h>
86 #include <mips/nlm/xlp.h>
88 /* 4KB static data aread to keep a copy of the bootload env until
89 the dynamic kenv is setup */
92 char **xlp_argv, **xlp_envp;
94 uint64_t xlp_cpu_frequency;
95 uint64_t xlp_io_base = MIPS_PHYS_TO_KSEG1(XLP_DEFAULT_IO_BASE);
98 int xlp_threads_per_core;
99 uint32_t xlp_hw_thread_mask;
100 int xlp_cpuid_to_hwtid[MAXCPU];
101 int xlp_hwtid_to_cpuid[MAXCPU];
102 uint64_t xlp_pic_base;
104 static int xlp_mmuval;
106 extern uint32_t _end;
107 extern char XLPResetEntry[], XLPResetEntryEnd[];
114 reg = nlm_mfcr(LSU_DEFEATURE);
115 /* Enable Unaligned and L2HPE */
116 reg |= (1 << 30) | (1 << 23);
118 * Experimental : Enable SUE
119 * Speculative Unmap Enable. Enable speculative L2 cache request for
123 /* Clear S1RCM - A0 errata */
125 nlm_mtcr(LSU_DEFEATURE, reg);
127 reg = nlm_mfcr(SCHED_DEFEATURE);
128 /* Experimental: Disable BRU accepting ALU ops - A0 errata */
130 nlm_mtcr(SCHED_DEFEATURE, reg);
137 nlm_setup_extended_pagemask(0); /* pagemask = 0 for 4K pages */
138 nlm_large_variable_tlb_en(0);
139 nlm_extended_tlb_en(1);
140 nlm_mmu_setup(0, 0, 0);
144 xlp_parse_mmu_options(void)
147 uint32_t cpu_map = xlp_hw_thread_mask;
148 uint32_t core0_thr_mask, core_thr_mask;
150 #ifndef SMP /* Uniprocessor! */
151 if (cpu_map != 0x1) {
152 printf("WARNING: Starting uniprocessor kernel on cpumask [0x%lx]!\n"
153 "WARNING: Other CPUs will be unused.\n", (u_long)cpu_map);
159 core0_thr_mask = cpu_map & 0xf;
160 switch (core0_thr_mask) {
162 xlp_threads_per_core = 1;
166 xlp_threads_per_core = 2;
170 xlp_threads_per_core = 4;
177 /* Verify other cores CPU masks */
178 for (i = 1; i < XLP_MAX_CORES; i++) {
179 core_thr_mask = (cpu_map >> (i*4)) & 0xf;
181 if (core_thr_mask != core0_thr_mask)
187 xlp_hw_thread_mask = cpu_map;
188 /* setup hardware processor id to cpu id mapping */
189 for (i = 0; i< MAXCPU; i++)
190 xlp_cpuid_to_hwtid[i] =
191 xlp_hwtid_to_cpuid [i] = -1;
192 for (i = 0, k = 0; i < XLP_MAX_CORES; i++) {
193 if (((cpu_map >> (i*4)) & 0xf) == 0)
195 for (j = 0; j < xlp_threads_per_core; j++) {
196 xlp_cpuid_to_hwtid[k] = i*4 + j;
197 xlp_hwtid_to_cpuid[i*4 + j] = k;
204 * We will enable the other threads in core 0 here
205 * so that the TLB and cache info is correct when
208 xlp_enable_threads(xlp_mmuval);
210 /* setup for the startup core */
215 printf("ERROR : Unsupported CPU mask [use 1,2 or 4 threads per core].\n"
216 "\tcore0 thread mask [%lx], boot cpu mask [%lx].\n",
217 (u_long)core0_thr_mask, (u_long)cpu_map);
218 panic("Invalid CPU mask - halting.\n");
223 xlp_set_boot_flags(void)
227 p = getenv("bootflags");
231 for (; p && *p != '\0'; p++) {
243 boothowto |= RB_VERBOSE;
246 case 's': /* single-user (default, supported for sanity) */
248 boothowto |= RB_SINGLE;
252 printf("Unrecognized boot flag '%c'.\n", *p);
265 init_param2(physmem);
268 cpuinfo.cache_coherent_dma = TRUE;
272 if (boothowto & RB_KDB) {
273 kdb_enter("Boot flags requested debugger", NULL);
281 platform_get_timecount(struct timecounter *tc __unused)
283 uint64_t count = nlm_pic_read_timer(xlp_pic_base, PIC_CLOCK_TIMER);
285 return (unsigned int)~count;
291 struct timecounter pic_timecounter = {
292 platform_get_timecount, /* get_timecount */
294 ~0U, /* counter_mask */
295 XLP_IO_CLK, /* frequency */
297 2000, /* quality (adjusted in code) */
301 xlp_pic_base = nlm_get_pic_regbase(0); /* TOOD: Add other nodes */
302 printf("Initializing PIC...@%jx\n", (uintmax_t)xlp_pic_base);
303 /* Bind all PIC irqs to cpu 0 */
304 for(i = 0; i < PIC_NUM_IRTS; i++) {
305 nlm_pic_write_irt(xlp_pic_base, i, 0, 0, 1, 0,
309 nlm_pic_set_timer(xlp_pic_base, PIC_CLOCK_TIMER, ~0ULL, 0, 0);
310 platform_timecounter = &pic_timecounter;
313 #if defined(__mips_n32) || defined(__mips_n64) /* PHYSADDR_64_BIT */
315 #define XLP_MEM_LIM 0x200000000ULL
317 #define XLP_MEM_LIM 0x10000000000ULL
320 #define XLP_MEM_LIM 0xfffff000UL
325 uint64_t bridgebase = nlm_get_bridge_regbase(0); /* TOOD: Add other nodes */
326 vm_size_t physsz = 0;
327 uint64_t base, lim, val;
330 for (i = 0, j = 0; i < 8; i++) {
331 val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_BAR(i));
332 base = ((val >> 12) & 0xfffff) << 20;
333 val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_LIMIT(i));
334 lim = ((val >> 12) & 0xfffff) << 20;
336 /* BAR not enabled */
340 /* first bar, start a bit after end */
342 base = (vm_paddr_t)MIPS_KSEG0_TO_PHYS(&_end) + 0x20000;
343 lim = 0x0c000000; /* TODO : hack to avoid uboot packet mem */
345 if (base >= XLP_MEM_LIM) {
346 printf("Mem [%d]: Ignore %#jx - %#jx\n", i,
347 (intmax_t)base, (intmax_t)lim);
350 if (lim > XLP_MEM_LIM) {
351 printf("Mem [%d]: Restrict %#jx -> %#jx\n", i,
352 (intmax_t)lim, (intmax_t)XLP_MEM_LIM);
356 printf("Mem[%d]: Malformed %#jx -> %#jx\n", i,
357 (intmax_t)base, (intmax_t)lim);
362 * Exclude reset entry memory range 0x1fc00000 - 0x20000000
365 if (base <= 0x1fc00000 && (base + lim) > 0x1fc00000) {
366 uint64_t base0, lim0, base1, lim1;
374 phys_avail[j++] = (vm_paddr_t)base0;
375 phys_avail[j++] = (vm_paddr_t)lim0;
376 physsz += lim0 - base0;
377 printf("Mem[%d]: %#jx - %#jx (excl reset)\n", i,
378 (intmax_t)base0, (intmax_t)lim0);
381 phys_avail[j++] = (vm_paddr_t)base1;
382 phys_avail[j++] = (vm_paddr_t)lim1;
383 physsz += lim1 - base1;
384 printf("Mem[%d]: %#jx - %#jx (excl reset)\n", i,
385 (intmax_t)base1, (intmax_t)lim1);
388 phys_avail[j++] = (vm_paddr_t)base;
389 phys_avail[j++] = (vm_paddr_t)lim;
390 physsz += lim - base;
391 printf("Mem[%d]: %#jx - %#jx\n", i,
392 (intmax_t)base, (intmax_t)lim);
397 /* setup final entry with 0 */
398 phys_avail[j] = phys_avail[j + 1] = 0;
400 /* copy phys_avail to dump_avail */
401 for(i = 0; i <= j + 1; i++)
402 dump_avail[i] = phys_avail[i];
404 realmem = physmem = btoc(physsz);
408 xlp_get_cpu_frequency(void)
410 uint64_t sysbase = nlm_get_sys_regbase(0);
411 unsigned int pll_divf, pll_divr, dfs_div, num, denom;
414 val = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
415 pll_divf = (val >> 10) & 0x7f;
416 pll_divr = (val >> 8) & 0x3;
417 dfs_div = (val >> 17) & 0x3;
420 denom = 3 * (pll_divr + 1) * (1<< (dfs_div + 1));
421 val = 800000000ULL * num / denom;
426 platform_start(__register_t a0 __unused,
427 __register_t a1 __unused,
428 __register_t a2 __unused,
429 __register_t a3 __unused)
435 * argv and envp are passed in array of 32bit pointers
440 /* Initialize pcpu stuff */
443 /* initialize console so that we have printf */
444 boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */
447 boothowto |= RB_VERBOSE;
448 boothowto |= RB_SINGLE;
451 /* clockrate used by delay, so initialize it here */
452 xlp_cpu_frequency = xlp_get_cpu_frequency();
453 cpu_clock = xlp_cpu_frequency / 1000000;
454 mips_timer_early_init(xlp_cpu_frequency);
456 /* Init console please */
460 printf("Args %#jx %#jx %#jx %#jx:\n", (intmax_t)a0,
461 (intmax_t)a1, (intmax_t)a2, (intmax_t)a3);
462 xlp_hw_thread_mask = a0;
463 init_static_kenv(boot1_env, sizeof(boot1_env));
464 printf("Environment (from %d args):\n", xlp_argc - 1);
467 for (i = 1; i < xlp_argc; i++) {
470 arg = (char *)(intptr_t)xlp_argv[i];
471 printf("\t%s\n", arg);
472 n = strsep(&arg, "=");
479 /* Early core init and fixes for errata */
482 xlp_set_boot_flags();
483 xlp_parse_mmu_options();
487 bcopy(XLPResetEntry, (void *)MIPS_RESET_EXC_VEC,
488 XLPResetEntryEnd - XLPResetEntry);
495 * XLP specific post initialization
496 * initialize other on chip stuff
498 nlm_board_info_setup();
501 mips_timer_init_params(xlp_cpu_frequency, 0);
510 platform_identify(void)
513 printf("XLP Eval Board\n");
517 * XXX Maybe return the state of the watchdog in enter, and pass it to
521 platform_trap_enter(void)
528 uint64_t sysbase = nlm_get_sys_regbase(0);
530 nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
532 __asm __volatile("wait");
536 platform_trap_exit(void)
542 * XLP threads are started simultaneously when we enable threads, this will
543 * ensure that the threads are blocked in platform_init_ap, until they are
544 * ready to proceed to smp_init_secondary()
546 static volatile int thr_unblock[4];
549 platform_start_ap(int cpuid)
551 uint32_t coremask, val;
552 uint64_t sysbase = nlm_get_sys_regbase(0);
553 int hwtid = xlp_cpuid_to_hwtid[cpuid];
559 /* First thread in core, do core wake up */
560 coremask = 1u << core;
562 /* Enable core clock */
563 val = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
565 nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, val);
567 /* Remove CPU Reset */
568 val = nlm_read_sys_reg(sysbase, SYS_CPU_RESET);
569 val &= ~coremask & 0xff;
570 nlm_write_sys_reg(sysbase, SYS_CPU_RESET, val);
573 printf("Waking up core %d ...", core);
575 /* Poll for CPU to mark itself coherent */
577 val = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
578 } while ((val & coremask) != 0);
582 /* otherwise release the threads stuck in platform_init_ap */
583 thr_unblock[thr] = 1;
590 platform_init_ap(int cpuid)
595 /* The first thread has to setup the MMU and enable other threads */
596 thr = nlm_threadid();
599 xlp_enable_threads(xlp_mmuval);
603 * FIXME busy wait here eats too many cycles, especially
604 * in the core 0 while bootup
606 while (thr_unblock[thr] == 0)
607 __asm__ __volatile__ ("nop;nop;nop;nop");
608 thr_unblock[thr] = 0;
611 stat = mips_rd_status();
612 KASSERT((stat & MIPS_SR_INT_IE) == 0,
613 ("Interrupts enabled in %s!", __func__));
614 stat |= MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT;
615 mips_wr_status(stat);
617 nlm_write_c0_eimr(0ull);
618 xlp_enable_irq(IRQ_IPI);
619 xlp_enable_irq(IRQ_TIMER);
620 xlp_enable_irq(IRQ_MSGRING);
626 platform_ipi_intrnum(void)
633 platform_ipi_send(int cpuid)
636 nlm_pic_send_ipi(xlp_pic_base, xlp_cpuid_to_hwtid[cpuid],
637 platform_ipi_intrnum(), 0);
641 platform_ipi_clear(void)
646 platform_processor_id(void)
649 return (xlp_hwtid_to_cpuid[nlm_cpuid()]);
653 platform_cpu_mask(cpuset_t *mask)
658 s = xlp_ncores * xlp_threads_per_core;
659 for (i = 0; i < s; i++)
667 return (smp_topo_2level(CG_SHARE_L2, xlp_ncores, CG_SHARE_L1,
668 xlp_threads_per_core, CG_FLAG_THREAD));