xref: /netbsd/sys/arch/sbmips/sbmips/cpu.c (revision bf9ec67e)
1 /* $NetBSD: cpu.c,v 1.4 2002/03/06 08:02:12 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. Neither the "Broadcom Corporation" name nor any
19  *    trademark or logo of Broadcom Corporation may be used to endorse or
20  *    promote products derived from this software without the prior written
21  *    permission of Broadcom Corporation.
22  *
23  * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
24  *    WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
25  *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
26  *    NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
27  *    FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
28  *    LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32  *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33  *    OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <sys/param.h>
37 #include <sys/device.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
40 
41 #include <mips/locore.h>
42 #include <mips/cache.h>
43 
44 #include <machine/cpu.h>
45 
46 #include <mips/sibyte/include/zbbusvar.h>
47 #include <mips/sibyte/include/sb1250_regs.h>
48 #include <mips/sibyte/include/sb1250_scd.h>
49 #include <mips/sibyte/dev/sbscdvar.h>
50 
51 #define	READ_REG(rp)		(mips3_ld((uint64_t *)(rp)))
52 
53 static int	cpu_match(struct device *, struct cfdata *, void *);
54 static void	cpu_attach(struct device *, struct device *, void *);
55 
56 struct cfattach cpu_ca = {
57 	sizeof(struct device), cpu_match, cpu_attach
58 };
59 
60 static int
61 cpu_match(struct device *parent, struct cfdata *match, void *aux)
62 {
63 	struct zbbus_attach_args *zap = aux;
64 
65 	if (zap->za_locs.za_type != ZBBUS_ENTTYPE_CPU)
66 		return (0);
67 
68 	return 1;
69 }
70 
71 static void
72 cpu_attach(struct device *parent, struct device *self, void *aux)
73 {
74 	int plldiv;
75 	uint32_t config;
76 
77 	/* XXX this code must run on the target cpu */
78 	config = mips3_cp0_config_read();
79 	config &= ~MIPS3_CONFIG_K0_MASK;
80 	config |= 0x05;				/* XXX.  cacheable coherent */
81 	mips3_cp0_config_write(config);
82 
83 	/*
84 	 * Flush all of the caches, so that any lines marked non-coherent will
85 	 * be flushed.  Don't need to worry about L2; it's always
86 	 * coherent (XXX???).
87 	 */
88 	mips_icache_sync_all();
89 	mips_dcache_wbinv_all();
90 
91 	/* Determine CPU frequency */
92 
93 	/* XXX:  We should determine the CPU frequency from a time source
94 	 *       not coupled with the CPU crystal, like the RTC.  Unfortunately
95 	 *       we don't attach that yet...
96 	 */
97 	plldiv = G_SYS_PLL_DIV(READ_REG(MIPS_PHYS_TO_KSEG1(A_SCD_SYSTEM_CFG)));
98 	if (plldiv == 0) {
99 		printf("PLL_DIV of zero found, assuming 6 (300MHz)\n");
100 		plldiv = 6;
101 
102 		printf("%s", self->dv_xname);
103 	}
104 
105 	curcpu()->ci_cpu_freq = 50000000 * plldiv;
106 	/* Compute the delay divisor. */
107 	curcpu()->ci_divisor_delay = curcpu()->ci_cpu_freq / 1000000;
108 	/* Compute clock cycles per hz */
109 	curcpu()->ci_cycles_per_hz = curcpu()->ci_cpu_freq / hz;
110 
111 	/*
112 	 * To implement a more accurate microtime using the CP0 COUNT
113 	 * register we need to divide that register by the number of
114 	 * cycles per MHz.  But...
115 	 *
116 	 * DIV and DIVU are expensive on MIPS (eg 75 clocks on the
117 	 * R4000).  MULT and MULTU are only 12 clocks on the same CPU.
118 	 * On the SB1 these appear to be 40-72 clocks for DIV/DIVU and 3
119 	 * clocks for MUL/MULTU.
120 	 *
121 	 * The strategy we use to to calculate the reciprical of cycles
122 	 * per MHz, scaled by 1<<32.  Then we can simply issue a MULTU
123 	 * and pluck of the HI register and have the results of the
124 	 * division.
125 	 */
126 	curcpu()->ci_divisor_recip =
127 	    0x100000000ULL / curcpu()->ci_divisor_delay;
128 
129 	printf(": %lu.%02luMHz (hz cycles = %lu, delay divisor = %lu)\n",
130 	    curcpu()->ci_cpu_freq / 1000000,
131 	    (curcpu()->ci_cpu_freq % 1000000) / 10000,
132 	    curcpu()->ci_cycles_per_hz, curcpu()->ci_divisor_delay);
133 
134 	printf("%s: ", self->dv_xname);
135 	cpu_identify();
136 
137 	/* make sure processor is available for use */
138 	/* XXXCGD */
139 }
140