1 /* $NetBSD: cpu.c,v 1.3 2017/08/02 12:23:43 simonb Exp $ */ 2 3 /* 4 * Copyright 2000, 2001 5 * Broadcom Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and copied only 8 * in accordance with the following terms and conditions. Subject to these 9 * conditions, you may download, copy, install, use, modify and distribute 10 * modified or unmodified copies of this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce and 14 * retain this copyright notice and list of conditions as they appear in 15 * the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Broadcom Corporation. The "Broadcom Corporation" name may not be 19 * used to endorse or promote products derived from this software 20 * without the prior written permission of Broadcom Corporation. 21 * 22 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 25 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 26 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 27 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 32 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.3 2017/08/02 12:23:43 simonb Exp $"); 37 38 #include "opt_multiprocessor.h" 39 40 #include <sys/param.h> 41 #include <sys/cpu.h> 42 #include <sys/device.h> 43 #include <sys/kernel.h> 44 #include <sys/systm.h> 45 46 #include <mips/locore.h> 47 #include <mips/cache.h> 48 49 #include <evbmips/sbmips/cpuvar.h> 50 #include <evbmips/sbmips/systemsw.h> 51 52 #include <mips/sibyte/include/zbbusvar.h> 53 #include <mips/sibyte/include/sb1250_regs.h> 54 #include <mips/sibyte/include/sb1250_scd.h> 55 #include <mips/sibyte/dev/sbscdvar.h> 56 #include <mips/cfe/cfe_api.h> 57 58 #define READ_REG(rp) mips3_ld((register_t)(rp)) 59 60 static int cpu_match(device_t, cfdata_t, void *); 61 static void cpu_attach(device_t, device_t, void *); 62 63 CFATTACH_DECL_NEW(cpu, sizeof(struct cpu_softc), 64 cpu_match, cpu_attach, NULL, NULL); 65 66 static u_int found = 0; 67 68 static int 69 cpu_match(device_t parent, cfdata_t match, void *aux) 70 { 71 struct zbbus_attach_args *zap = aux; 72 int part; 73 74 if (zap->za_locs.za_type != ZBBUS_ENTTYPE_CPU) 75 return (0); 76 77 /* 78 * The 3rd hex digit of the part number is the number of CPUs; 79 * ref Table 26, p38 1250-UM101-R. 80 */ 81 part = G_SYS_PART(READ_REG(MIPS_PHYS_TO_KSEG1(A_SCD_SYSTEM_REVISION))); 82 return (found < ((part >> 8) & 0xf)); 83 } 84 85 static void 86 cpu_attach(device_t parent, device_t self, void *aux) 87 { 88 struct cpu_info *ci; 89 struct cpu_softc * const cpu = device_private(self); 90 const char * const xname = device_xname(self); 91 uint32_t config; 92 int plldiv; 93 94 found++; 95 96 /* XXX this code must run on the target CPU */ 97 config = mips3_cp0_config_read(); 98 __USE(config); 99 KASSERT((config & MIPS3_CONFIG_K0_MASK) == 5); 100 101 /* Determine CPU frequency */ 102 103 /* XXX: We should determine the CPU frequency from a time source 104 * not coupled with the CPU crystal, like the RTC. Unfortunately 105 * we don't attach that yet... 106 */ 107 plldiv = G_SYS_PLL_DIV(READ_REG(MIPS_PHYS_TO_KSEG1(A_SCD_SYSTEM_CFG))); 108 if (plldiv == 0) { 109 aprint_normal(": PLL_DIV of zero found, assuming 6 (300MHz)\n"); 110 plldiv = 6; 111 112 aprint_normal("%s", xname); 113 } 114 115 if (found == 1) { 116 ci = curcpu(); 117 ci->ci_cpu_freq = 50000000 * plldiv; 118 /* Compute the delay divisor. */ 119 ci->ci_divisor_delay = (ci->ci_cpu_freq + 500000) / 1000000; 120 /* Compute clock cycles per hz */ 121 ci->ci_cycles_per_hz = (ci->ci_cpu_freq + hz / 2 ) / hz; 122 123 aprint_normal(": %lu.%02luMHz (hz cycles = %lu, delay divisor = %lu)\n", 124 ci->ci_cpu_freq / 1000000, 125 (ci->ci_cpu_freq % 1000000) / 10000, 126 ci->ci_cycles_per_hz, ci->ci_divisor_delay); 127 128 KASSERT(ci->ci_cpuid == 0); 129 130 cpu->sb1cpu_dev = self; 131 cpu->sb1cpu_ci = ci; 132 ci->ci_softc = cpu; 133 134 sb1250_cpu_init(cpu); 135 } else { 136 #if defined(MULTIPROCESSOR) 137 int status; 138 ci = cpu_info_alloc(NULL, found - 1, 0, found - 1, 0); 139 KASSERT(ci); 140 141 cpu->sb1cpu_dev = self; 142 cpu->sb1cpu_ci = ci; 143 ci->ci_softc = cpu; 144 145 sb1250_cpu_init(cpu); 146 147 status = cfe_cpu_start(ci->ci_cpuid, cpu_trampoline, 148 (long) ci->ci_data.cpu_idlelwp->l_md.md_utf, 0, 149 (long) ci); 150 if (status != 0) { 151 aprint_error(": CFE call to start failed: %d\n", 152 status); 153 } 154 const u_long cpu_mask = 1L << cpu_index(ci); 155 for (size_t i = 0; i < 10000; i++) { 156 if (cpus_hatched & cpu_mask) 157 break; 158 DELAY(100); 159 } 160 if ((cpus_hatched & cpu_mask) == 0) { 161 aprint_error(": failed to hatch!\n"); 162 return; 163 } 164 #else 165 aprint_normal("\n"); 166 aprint_normal_dev(self, 167 "processor off-line; " 168 "multiprocessor support not present in kernel\n"); 169 return; 170 #endif 171 } 172 173 /* 174 * Announce ourselves. 175 */ 176 aprint_normal("%s: ", xname); 177 cpu_identify(self); 178 179 cpu_attach_common(self, ci); 180 } 181