cpu.c revision 1.14
1/*	$OpenBSD: cpu.c,v 1.14 2002/03/19 01:30:46 mickey Exp $	*/
2
3/*
4 * Copyright (c) 1998-2002 Michael Shalayeff
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 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by Michael Shalayeff.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF MIND,
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/device.h>
36#include <sys/reboot.h>
37
38#include <machine/cpufunc.h>
39#include <machine/pdc.h>
40#include <machine/reg.h>
41#include <machine/iomod.h>
42#include <machine/autoconf.h>
43
44#include <hppa/dev/cpudevs.h>
45
46struct cpu_softc {
47	struct  device sc_dev;
48
49	hppa_hpa_t sc_hpa;
50	void *sc_ih;
51};
52
53int	cpumatch(struct device *, void *, void *);
54void	cpuattach(struct device *, struct device *, void *);
55
56struct cfattach cpu_ca = {
57	sizeof(struct cpu_softc), cpumatch, cpuattach
58};
59
60struct cfdriver cpu_cd = {
61	NULL, "cpu", DV_DULL
62};
63
64int
65cpumatch(parent, cfdata, aux)
66	struct device *parent;
67	void *cfdata;
68	void *aux;
69{
70	struct confargs *ca = aux;
71	struct cfdata *cf = cfdata;
72
73	/* there will be only one for now XXX */
74	/* probe any 1.0, 1.1 or 2.0 */
75	if (cf->cf_unit > 0 ||
76	    ca->ca_type.iodc_type != HPPA_TYPE_NPROC ||
77	    ca->ca_type.iodc_sv_model != HPPA_NPROC_HPPA)
78		return 0;
79
80	return 1;
81}
82
83void
84cpuattach(parent, self, aux)
85	struct device *parent;
86	struct device *self;
87	void *aux;
88{
89	/* machdep.c */
90	extern struct pdc_cache pdc_cache;
91	extern struct pdc_btlb pdc_btlb;
92	extern u_int cpu_ticksnum, cpu_ticksdenom;
93	extern u_int fpu_enable;
94
95	struct pdc_model pdc_model PDC_ALIGNMENT;
96	struct pdc_cpuid pdc_cpuid PDC_ALIGNMENT;
97	u_int pdc_cversion[32] PDC_ALIGNMENT;
98	register struct cpu_softc *sc = (struct cpu_softc *)self;
99	register struct confargs *ca = aux;
100	const char *p = NULL;
101	u_int mhz = 100 * cpu_ticksnum / cpu_ticksdenom;
102	int err;
103
104	bzero (&pdc_cpuid, sizeof(pdc_cpuid));
105	if (pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID,
106		     &pdc_cpuid, sc->sc_dev.dv_unit, 0, 0, 0) >= 0) {
107
108		/* patch for old 8200 */
109		if (pdc_cpuid.version == HPPA_CPU_PCXUP &&
110		    pdc_cpuid.revision > 0x0d)
111			pdc_cpuid.version = HPPA_CPU_PCXUP1;
112
113		p = hppa_mod_info(HPPA_TYPE_CPU, pdc_cpuid.version);
114	}
115	/* otherwise try to guess on component version numbers */
116	else if (pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_COMP,
117		     &pdc_cversion, sc->sc_dev.dv_unit) >= 0) {
118		/* XXX p = hppa_mod_info(HPPA_TYPE_CPU,pdc_cversion[0]); */
119	}
120
121	printf (": %s rev %d ", p? p : cpu_typename, (*cpu_desidhash)());
122
123	if ((err = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO,
124			    &pdc_model)) < 0) {
125#ifdef DEBUG
126		printf("PDC_MODEL(%d) ", err);
127#endif
128	} else {
129		static const char lvls[4][4] = { "0", "1", "1.5", "2" };
130
131		printf("L%s-%c ", lvls[pdc_model.pa_lvl], "AB"[pdc_model.mc]);
132	}
133
134	printf ("%d", mhz / 100);
135	if (mhz % 100 > 9)
136		printf(".%02d", mhz % 100);
137	printf("MHz, ");
138
139	if (fpu_enable) {
140		const char *name;
141		u_int ver;
142
143		mtctl(fpu_enable, CR_CCR);
144		__asm volatile(
145		    "copr,0,0\n\t"
146		    "fstws   %%fr0,0(%0)"
147		    :: "r" (&ver) : "memory");
148		mtctl(0, CR_CCR);
149		ver = HPPA_FPUVER(ver);
150		name = hppa_mod_info(HPPA_TYPE_FPU, ver >> 5);
151		if (name)
152			printf("FPU %s rev %d", name, ver);
153		else
154			printf("FPU v%d.%02d", ver >> 5, ver & 0x1f);
155	}
156
157	/* if (pdc_model.sh)
158		printf("shadows, "); */
159
160	printf("\n%s: ", self->dv_xname);
161	p = "";
162	if (!pdc_cache.dc_conf.cc_sh) {
163		printf("%uK(%db/l) Icache, ",
164		    pdc_cache.ic_size / 1024, pdc_cache.ic_conf.cc_line * 16);
165		p = "D";
166	}
167	/* TODO decode associativity */
168	printf("%uK(%db/l) %s %scoherent %scache, ",
169	    pdc_cache.dc_size / 1024, pdc_cache.dc_conf.cc_line * 16,
170	    pdc_cache.dc_conf.cc_wt? "w-thru" : "w-back",
171	    pdc_cache.dc_conf.cc_cst? "" : "in", p);
172
173	p = "";
174	if (!pdc_cache.dt_conf.tc_sh) {
175		printf("%u ITLB, ", pdc_cache.it_size);
176		p = "D";
177	}
178	printf("%u %scoherent %sTLB",
179	    pdc_cache.dt_size, pdc_cache.dt_conf.tc_cst? "" : "in", p);
180
181	if (pdc_btlb.finfo.num_c)
182		printf(", %u BTLB\n", pdc_btlb.finfo.num_c);
183	else
184		printf(", %u/%u D/I BTLBs\n",
185		    pdc_btlb.finfo.num_i, pdc_btlb.finfo.num_d);
186
187	/* sanity against lusers amongst config editors */
188	if (ca->ca_irq == 31)
189		sc->sc_ih = cpu_intr_establish(IPL_CLOCK, ca->ca_irq,
190		    clock_intr, NULL /*trapframe*/, &sc->sc_dev);
191	else
192		printf ("%s: bad irq %d\n", sc->sc_dev.dv_xname, ca->ca_irq);
193}
194