Home | History | Annotate | Line # | Download | only in nintendo
      1 /* $NetBSD: cpu.c,v 1.1 2026/01/09 22:54:28 jmcneill Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2025 Jared McNeill <jmcneill (at) invisible.ca>
      5  * All rights reserved.
      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  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.1 2026/01/09 22:54:28 jmcneill Exp $");
     31 
     32 #include "opt_multiprocessor.h"
     33 
     34 #include <sys/param.h>
     35 #include <sys/device.h>
     36 #include <sys/systm.h>
     37 #include <sys/bus.h>
     38 #include <sys/cpu.h>
     39 #include <sys/kprintf.h>
     40 #include <machine/wii.h>
     41 #include <machine/wiiu.h>
     42 #include <powerpc/include/spr.h>
     43 #include <powerpc/include/oea/spr.h>
     44 #include <powerpc/include/psl.h>
     45 #include <arch/evbppc/nintendo/dev/mainbus.h>
     46 #include <arch/evbppc/nintendo/pic_pi.h>
     47 
     48 static int	cpu_match(device_t, cfdata_t, void *);
     49 static void	cpu_attach(device_t, device_t, void *);
     50 
     51 CFATTACH_DECL_NEW(cpu, 0, cpu_match, cpu_attach, NULL, NULL);
     52 
     53 extern struct cfdriver cpu_cd;
     54 
     55 #ifdef MULTIPROCESSOR
     56 static uint32_t cpu_start_code[] = {
     57 	0x3c600000,	// lis     r3, 0	/* upper 32-bits of entry pt */
     58 	0x60630000,	// ori     r3, r3, 0	/* lower 32-bits of entry pt */
     59 	0x7c7a03a6,	// mtsrr0  r3
     60 
     61 	0x38600000,	// li      r3, 0
     62 	0x7c7b03a6,	// mtsrr1  r3
     63 
     64 	0x3c600011,	// lis     r3, 0x0011
     65 	0x60630024,	// ori     r3, r3, 0x0024
     66 	0x7c70fba6,	// mtspr   1008, r3	/* HID0 */
     67 
     68 	0x3c60b1b0,	// lis     r3, 0xb1b0
     69 	0x7c73fba6,	// mtspr   1011, r3	/* HID4 */
     70 	0x7c0004ac,	// sync
     71 
     72 	0x3c60e7fd,	// lis     r3, 0xe7fd
     73 	0x6063c000,	// ori     r3, r3, 0xc000
     74 	0x7c70eba6,	// mtspr   944, r3	/* HID5 */
     75 	0x7c0004ac,	// sync
     76 
     77 	0x4c000064,	// rfi
     78 };
     79 #endif
     80 
     81 int
     82 cpu_match(device_t parent, cfdata_t cf, void *aux)
     83 {
     84 	struct mainbus_attach_args *maa = aux;
     85 
     86 	if (strcmp(maa->maa_name, cpu_cd.cd_name) != 0) {
     87 		return 0;
     88 	}
     89 
     90 	return 1;
     91 }
     92 
     93 void
     94 cpu_attach(device_t parent, device_t self, void *aux)
     95 {
     96 	u_int cpu_num = device_unit(self);
     97 	struct cpu_info *ci;
     98 
     99 	ci = cpu_attach_common(self, cpu_num);
    100 	if (ci == NULL) {
    101 		return;
    102 	}
    103 
    104 #ifdef MULTIPROCESSOR
    105 	if (cpu_num > 0) {
    106 		cpu_spinup(self, ci);
    107 	}
    108 
    109 	if (wiiu_native) {
    110 		/*
    111 		 * All cores are the same speed, but cores 1 has a bigger
    112 		 * cache, so let the scheduler know that the other cores
    113 		 * are slower.
    114 		 */
    115 		cpu_topology_setspeed(ci, cpu_index(ci) != 1);
    116 	}
    117 #endif
    118 
    119 	ci->ci_data.cpu_cc_freq = cpu_timebase;
    120 }
    121 
    122 #ifdef MULTIPROCESSOR
    123 
    124 int
    125 md_setup_trampoline(volatile struct cpu_hatch_data *h, struct cpu_info *ci)
    126 {
    127 	extern volatile u_int cpu_spinstart_ack;
    128 	u_int cpu_num = cpu_index(ci);
    129 	u_int i;
    130 
    131 	if (!wiiu_native) {
    132 		return -1;
    133 	}
    134 
    135 	/* construct an absolute branch instruction */
    136 	/* ba cpu_spinup_trampoline */
    137 	cpu_start_code[0] |= ((u_int)cpu_spinup_trampoline >> 16) & 0x7fff;
    138 	cpu_start_code[1] |= (u_int)cpu_spinup_trampoline & 0xffff;
    139 	memcpy((void *)WIIU_BOOT_VECTOR, cpu_start_code, sizeof(cpu_start_code));
    140 	__syncicache((void *)WIIU_BOOT_VECTOR, sizeof(cpu_start_code));
    141 	h->hatch_running = -1;
    142 
    143 	/* Start secondary CPU. */
    144 	mtspr(SPR_SCR, mfspr(SPR_SCR) | SPR_SCR_WAKE(cpu_num));
    145 
    146 	for (i = 0; i < 100000000; i++) {
    147 		if (cpu_spinstart_ack == 0) {
    148 			break;
    149 		}
    150 	}
    151 
    152 	/*
    153 	 * XXX FIXME
    154 	 * Without this printf, CPU startup takes a lot longer. I haven't
    155 	 * worked out why yet, so leave it for now.
    156 	 */
    157 	printf_flags(TOCONS|NOTSTAMP, " \x08");
    158 
    159 	return 1;
    160 }
    161 
    162 void
    163 md_presync_timebase(volatile struct cpu_hatch_data *h)
    164 {
    165 	uint64_t tb;
    166 
    167 	/* Sync timebase. */
    168 	tb = mftb();
    169 	tb += 100000;  /* 3ms @ 33MHz */
    170 
    171 	h->hatch_tbu = tb >> 32;
    172 	h->hatch_tbl = tb & 0xffffffff;
    173 
    174 	while (tb > mftb())
    175 		;
    176 
    177 	__asm volatile ("sync; isync" ::: "memory");
    178 	h->hatch_running = 0;
    179 
    180 	delay(500000);
    181 }
    182 
    183 void
    184 md_start_timebase(volatile struct cpu_hatch_data *h)
    185 {
    186 	u_int i;
    187 
    188 	for (i = 0; i < 1000000; i++) {
    189 		if (h->hatch_running) {
    190 			break;
    191 		}
    192 	}
    193 }
    194 
    195 void
    196 md_sync_timebase(volatile struct cpu_hatch_data *h)
    197 {
    198 	/* Sync timebase. */
    199 	u_int tbu = h->hatch_tbu;
    200 	u_int tbl = h->hatch_tbl;
    201 
    202 	while (h->hatch_running == -1)
    203 		;
    204 
    205 	__asm volatile ("sync; isync" ::: "memory");
    206 	__asm volatile ("mttbl %0" :: "r"(0));
    207 	__asm volatile ("mttbu %0" :: "r"(tbu));
    208 	__asm volatile ("mttbl %0" :: "r"(tbl));
    209 }
    210 
    211 void
    212 md_setup_interrupts(void)
    213 {
    214 	mtmsr(mfmsr() & ~PSL_IP);
    215 }
    216 
    217 #endif /* !MULTIPROCESSOR */
    218