1 /* $NetBSD: cpu.c,v 1.19 2009/12/14 00:46:12 matt 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.19 2009/12/14 00:46:12 matt Exp $"); 37 38 #include "opt_multiprocessor.h" 39 40 #include <sys/param.h> 41 #include <sys/device.h> 42 #include <sys/kernel.h> 43 #include <sys/systm.h> 44 #include <sys/cpu.h> 45 46 #include <mips/locore.h> 47 #include <mips/cache.h> 48 49 #include <machine/cpu.h> 50 51 #include <mips/sibyte/include/zbbusvar.h> 52 #include <mips/sibyte/include/sb1250_regs.h> 53 #include <mips/sibyte/include/sb1250_scd.h> 54 #include <mips/sibyte/dev/sbscdvar.h> 55 56 #define READ_REG(rp) (mips3_ld((volatile uint64_t *)(rp))) 57 58 static int cpu_match(struct device *, struct cfdata *, void *); 59 static void cpu_attach(struct device *, struct device *, void *); 60 61 CFATTACH_DECL(cpu, sizeof(struct device), 62 cpu_match, cpu_attach, NULL, NULL); 63 64 static int found = 0; 65 66 static int 67 cpu_match(struct device *parent, struct cfdata *match, void *aux) 68 { 69 struct zbbus_attach_args *zap = aux; 70 int part; 71 72 if (zap->za_locs.za_type != ZBBUS_ENTTYPE_CPU) 73 return (0); 74 75 /* 76 * The 3rd hex digit of the part number is the number of CPUs; 77 * ref Table 26, p38 1250-UM101-R. 78 */ 79 part = G_SYS_PART(READ_REG(MIPS_PHYS_TO_KSEG1(A_SCD_SYSTEM_REVISION))); 80 return (found < ((part >> 8) & 0xf)); 81 } 82 83 static void 84 cpu_attach(struct device *parent, struct device *self, void *aux) 85 { 86 int plldiv; 87 uint32_t config; 88 89 /* XXX this code must run on the target CPU */ 90 config = mips3_cp0_config_read(); 91 config &= ~MIPS3_CONFIG_K0_MASK; 92 config |= 0x05; /* XXX. cacheable coherent */ 93 mips3_cp0_config_write(config); 94 95 found++; 96 97 /* 98 * Flush all of the caches, so that any lines marked non-coherent will 99 * be flushed. Don't need to worry about L2; it's always 100 * coherent (XXX???). 101 */ 102 mips_icache_sync_all(); 103 mips_dcache_wbinv_all(); 104 105 /* Determine CPU frequency */ 106 107 /* XXX: We should determine the CPU frequency from a time source 108 * not coupled with the CPU crystal, like the RTC. Unfortunately 109 * we don't attach that yet... 110 */ 111 plldiv = G_SYS_PLL_DIV(READ_REG(MIPS_PHYS_TO_KSEG1(A_SCD_SYSTEM_CFG))); 112 if (plldiv == 0) { 113 printf("PLL_DIV of zero found, assuming 6 (300MHz)\n"); 114 plldiv = 6; 115 116 printf("%s", self->dv_xname); 117 } 118 119 curcpu()->ci_cpu_freq = 50000000 * plldiv; 120 /* Compute the delay divisor. */ 121 curcpu()->ci_divisor_delay = (curcpu()->ci_cpu_freq + 500000) / 1000000; 122 /* Compute clock cycles per hz */ 123 curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2 ) / hz; 124 125 printf(": %lu.%02luMHz (hz cycles = %lu, delay divisor = %lu)\n", 126 curcpu()->ci_cpu_freq / 1000000, 127 (curcpu()->ci_cpu_freq % 1000000) / 10000, 128 curcpu()->ci_cycles_per_hz, curcpu()->ci_divisor_delay); 129 130 /* 131 * If we're the primary CPU, no more work to do; we're already 132 * running! 133 */ 134 if (found == 1) { 135 printf("%s: ", self->dv_xname); 136 cpu_identify(); 137 } else { 138 #if defined(MULTIPROCESSOR) 139 # error! 140 #else 141 printf("%s: processor off-line; multiprocessor support " 142 "not present in kernel\n", /* sc->sc_dev. */self->dv_xname); 143 #endif 144 } 145 } 146