Home | History | Annotate | Line # | Download | only in arm32
cpu.c revision 1.9
      1  1.9   thorpej /*	$NetBSD: cpu.c,v 1.9 2001/11/06 20:39:13 thorpej Exp $	*/
      2  1.1      matt 
      3  1.1      matt /*
      4  1.1      matt  * Copyright (c) 1995 Mark Brinicombe.
      5  1.1      matt  * Copyright (c) 1995 Brini.
      6  1.1      matt  * All rights reserved.
      7  1.1      matt  *
      8  1.1      matt  * Redistribution and use in source and binary forms, with or without
      9  1.1      matt  * modification, are permitted provided that the following conditions
     10  1.1      matt  * are met:
     11  1.1      matt  * 1. Redistributions of source code must retain the above copyright
     12  1.1      matt  *    notice, this list of conditions and the following disclaimer.
     13  1.1      matt  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1      matt  *    notice, this list of conditions and the following disclaimer in the
     15  1.1      matt  *    documentation and/or other materials provided with the distribution.
     16  1.1      matt  * 3. All advertising materials mentioning features or use of this software
     17  1.1      matt  *    must display the following acknowledgement:
     18  1.1      matt  *	This product includes software developed by Brini.
     19  1.1      matt  * 4. The name of the company nor the name of the author may be used to
     20  1.1      matt  *    endorse or promote products derived from this software without specific
     21  1.1      matt  *    prior written permission.
     22  1.1      matt  *
     23  1.1      matt  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
     24  1.1      matt  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     25  1.1      matt  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  1.1      matt  * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     27  1.1      matt  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     28  1.1      matt  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     29  1.1      matt  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  1.1      matt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  1.1      matt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  1.1      matt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  1.1      matt  * SUCH DAMAGE.
     34  1.1      matt  *
     35  1.1      matt  * RiscBSD kernel project
     36  1.1      matt  *
     37  1.1      matt  * cpu.c
     38  1.1      matt  *
     39  1.1      matt  * Probing and configuration for the master cpu
     40  1.1      matt  *
     41  1.1      matt  * Created      : 10/10/95
     42  1.1      matt  */
     43  1.1      matt 
     44  1.1      matt #include "opt_armfpe.h"
     45  1.1      matt #include "opt_cputypes.h"
     46  1.1      matt 
     47  1.1      matt #include <sys/param.h>
     48  1.1      matt #include <sys/systm.h>
     49  1.1      matt #include <sys/malloc.h>
     50  1.1      matt #include <sys/device.h>
     51  1.1      matt #include <sys/proc.h>
     52  1.1      matt #include <uvm/uvm_extern.h>
     53  1.1      matt #include <machine/conf.h>
     54  1.1      matt #include <machine/cpu.h>
     55  1.1      matt #include <machine/cpus.h>
     56  1.1      matt #include <machine/undefined.h>
     57  1.1      matt 
     58  1.1      matt #ifdef ARMFPE
     59  1.1      matt #include <machine/bootconfig.h> /* For boot args */
     60  1.1      matt #include <arm32/fpe-arm/armfpe.h>
     61  1.1      matt #endif	/* ARMFPE */
     62  1.1      matt 
     63  1.1      matt cpu_t cpus[MAX_CPUS];
     64  1.1      matt 
     65  1.1      matt char cpu_model[64];
     66  1.1      matt volatile int undefined_test;	/* Used for FPA test */
     67  1.1      matt extern int cpuctrl;		/* cpu control register value */
     68  1.1      matt 
     69  1.1      matt /* Prototypes */
     70  1.1      matt void identify_master_cpu __P((struct device *dv, int cpu_number));
     71  1.1      matt void identify_arm_cpu	__P((struct device *dv, int cpu_number));
     72  1.1      matt void identify_arm_fpu	__P((struct device *dv, int cpu_number));
     73  1.5     chris int fpa_test __P((u_int, u_int, trapframe_t *, int));
     74  1.5     chris int fpa_handler __P((u_int, u_int, trapframe_t *, int));
     75  1.1      matt 
     76  1.1      matt /*
     77  1.1      matt  * void cpusattach(struct device *parent, struct device *dev, void *aux)
     78  1.1      matt  *
     79  1.1      matt  * Attach the main cpu
     80  1.1      matt  */
     81  1.1      matt 
     82  1.1      matt void
     83  1.1      matt cpu_attach(dv)
     84  1.1      matt 	struct device *dv;
     85  1.1      matt {
     86  1.1      matt 	identify_master_cpu(dv, CPU_MASTER);
     87  1.1      matt }
     88  1.1      matt 
     89  1.1      matt /*
     90  1.1      matt  * Used to test for an FPA. The following function is installed as a coproc1
     91  1.1      matt  * handler on the undefined instruction vector and then we issue a FPA
     92  1.1      matt  * instruction. If undefined_test is non zero then the FPA did not handle
     93  1.1      matt  * the instruction so must be absent.
     94  1.1      matt  */
     95  1.1      matt 
     96  1.1      matt int
     97  1.5     chris fpa_test(address, instruction, frame, fault_code)
     98  1.1      matt 	u_int address;
     99  1.1      matt 	u_int instruction;
    100  1.1      matt 	trapframe_t *frame;
    101  1.5     chris 	int fault_code;
    102  1.1      matt {
    103  1.1      matt 
    104  1.1      matt 	frame->tf_pc += INSN_SIZE;
    105  1.1      matt 	++undefined_test;
    106  1.1      matt 	return(0);
    107  1.1      matt }
    108  1.1      matt 
    109  1.1      matt /*
    110  1.1      matt  * If an FPA was found then this function is installed as the coproc1 handler
    111  1.1      matt  * on the undefined instruction vector. Currently we don't support FPA's
    112  1.1      matt  * so this just triggers an exception.
    113  1.1      matt  */
    114  1.1      matt 
    115  1.1      matt int
    116  1.1      matt fpa_handler(address, instruction, frame, fault_code)
    117  1.1      matt 	u_int address;
    118  1.1      matt 	u_int instruction;
    119  1.1      matt 	trapframe_t *frame;
    120  1.1      matt 	int fault_code;
    121  1.1      matt {
    122  1.1      matt 	u_int fpsr;
    123  1.1      matt 
    124  1.1      matt 	__asm __volatile("stmfd sp!, {r0}; .word 0xee300110; mov %0, r0; ldmfd sp!, {r0}" : "=r" (fpsr));
    125  1.1      matt 
    126  1.1      matt 	printf("FPA exception: fpsr = %08x\n", fpsr);
    127  1.1      matt 
    128  1.1      matt 	return(1);
    129  1.1      matt }
    130  1.1      matt 
    131  1.1      matt 
    132  1.1      matt /*
    133  1.1      matt  * Identify the master (boot) CPU
    134  1.1      matt  * This also probes for an FPU and will install an FPE if necessary
    135  1.1      matt  */
    136  1.1      matt 
    137  1.1      matt void
    138  1.1      matt identify_master_cpu(dv, cpu_number)
    139  1.1      matt 	struct device *dv;
    140  1.1      matt 	int cpu_number;
    141  1.1      matt {
    142  1.1      matt 	u_int fpsr;
    143  1.1      matt 	void *uh;
    144  1.1      matt 
    145  1.1      matt 	cpus[cpu_number].cpu_ctrl = cpuctrl;
    146  1.1      matt 
    147  1.1      matt 	/* Get the cpu ID from coprocessor 15 */
    148  1.1      matt 
    149  1.1      matt 	cpus[cpu_number].cpu_id = cpu_id();
    150  1.1      matt 
    151  1.1      matt 	identify_arm_cpu(dv, cpu_number);
    152  1.1      matt 	strcpy(cpu_model, cpus[cpu_number].cpu_model);
    153  1.1      matt 
    154  1.1      matt 	if (cpus[CPU_MASTER].cpu_class == CPU_CLASS_SA1
    155  1.1      matt 	    && (cpus[CPU_MASTER].cpu_id & CPU_ID_REVISION_MASK) < 3) {
    156  1.1      matt 		printf("%s: SA-110 with bugged STM^ instruction\n",
    157  1.1      matt 		       dv->dv_xname);
    158  1.1      matt 	}
    159  1.1      matt 
    160  1.1      matt #ifdef CPU_ARM8
    161  1.1      matt 	if ((cpus[CPU_MASTER].cpu_id & CPU_ID_CPU_MASK) == CPU_ID_ARM810) {
    162  1.1      matt 		int clock = arm8_clock_config(0, 0);
    163  1.1      matt 		char *fclk;
    164  1.1      matt 		printf("%s: ARM810 cp15=%02x", dv->dv_xname, clock);
    165  1.1      matt 		printf(" clock:%s", (clock & 1) ? " dynamic" : "");
    166  1.1      matt 		printf("%s", (clock & 2) ? " sync" : "");
    167  1.1      matt 		switch ((clock >> 2) & 3) {
    168  1.1      matt 		case 0 :
    169  1.1      matt 			fclk = "bus clock";
    170  1.1      matt 			break;
    171  1.1      matt 		case 1 :
    172  1.1      matt 			fclk = "ref clock";
    173  1.1      matt 			break;
    174  1.1      matt 		case 3 :
    175  1.1      matt 			fclk = "pll";
    176  1.1      matt 			break;
    177  1.1      matt 		default :
    178  1.1      matt 			fclk = "illegal";
    179  1.1      matt 			break;
    180  1.1      matt 		}
    181  1.1      matt 		printf(" fclk source=%s\n", fclk);
    182  1.1      matt  	}
    183  1.1      matt #endif
    184  1.1      matt 
    185  1.1      matt 	/*
    186  1.1      matt 	 * Ok now we test for an FPA
    187  1.1      matt 	 * At this point no floating point emulator has been installed.
    188  1.1      matt 	 * This means any FP instruction will cause undefined exception.
    189  1.1      matt 	 * We install a temporay coproc 1 handler which will modify
    190  1.1      matt 	 * undefined_test if it is called.
    191  1.1      matt 	 * We then try to read the FP status register. If undefined_test
    192  1.1      matt 	 * has been decremented then the instruction was not handled by
    193  1.1      matt 	 * an FPA so we know the FPA is missing. If undefined_test is
    194  1.1      matt 	 * still 1 then we know the instruction was handled by an FPA.
    195  1.1      matt 	 * We then remove our test handler and look at the
    196  1.1      matt 	 * FP status register for identification.
    197  1.1      matt 	 */
    198  1.1      matt 
    199  1.1      matt 	uh = install_coproc_handler(FP_COPROC, fpa_test);
    200  1.1      matt 
    201  1.1      matt 	undefined_test = 0;
    202  1.1      matt 
    203  1.1      matt 	__asm __volatile("stmfd sp!, {r0}; .word 0xee300110; mov %0, r0; ldmfd sp!, {r0}" : "=r" (fpsr));
    204  1.1      matt 
    205  1.1      matt 	remove_coproc_handler(uh);
    206  1.1      matt 
    207  1.1      matt 	if (undefined_test == 0) {
    208  1.1      matt 		cpus[cpu_number].fpu_type = (fpsr >> 24);
    209  1.1      matt 	        switch (fpsr >> 24) {
    210  1.1      matt 		case 0x81 :
    211  1.1      matt 			cpus[cpu_number].fpu_class = FPU_CLASS_FPA;
    212  1.1      matt 			break;
    213  1.1      matt 
    214  1.1      matt 		default :
    215  1.1      matt 			cpus[cpu_number].fpu_class = FPU_CLASS_FPU;
    216  1.1      matt 			break;
    217  1.1      matt 		}
    218  1.1      matt 		cpus[cpu_number].fpu_flags = 0;
    219  1.1      matt 		install_coproc_handler(FP_COPROC, fpa_handler);
    220  1.1      matt 	} else {
    221  1.1      matt 		cpus[cpu_number].fpu_class = FPU_CLASS_NONE;
    222  1.1      matt 		cpus[cpu_number].fpu_flags = 0;
    223  1.1      matt 
    224  1.1      matt 		/*
    225  1.1      matt 		 * Ok if ARMFPE is defined and the boot options request the
    226  1.1      matt 		 * ARM FPE then it will be installed as the FPE.
    227  1.1      matt 		 * This is just while I work on integrating the new FPE.
    228  1.1      matt 		 * It means the new FPE gets installed if compiled int (ARMFPE
    229  1.1      matt 		 * defined) and also gives me a on/off option when I boot in
    230  1.1      matt 		 * case the new FPE is causing panics.
    231  1.1      matt 		 */
    232  1.1      matt 
    233  1.1      matt #ifdef ARMFPE
    234  1.1      matt 		if (boot_args) {
    235  1.2     bjh21 			int usearmfpe = 1;
    236  1.1      matt 
    237  1.2     bjh21 			get_bootconf_option(boot_args, "armfpe",
    238  1.2     bjh21 			    BOOTOPT_TYPE_BOOLEAN, &usearmfpe);
    239  1.2     bjh21 			if (usearmfpe) {
    240  1.1      matt 				if (initialise_arm_fpe(&cpus[cpu_number]) != 0)
    241  1.1      matt 					identify_arm_fpu(dv, cpu_number);
    242  1.1      matt 			}
    243  1.1      matt 		}
    244  1.1      matt 
    245  1.1      matt #endif
    246  1.1      matt 	}
    247  1.1      matt 
    248  1.1      matt 	identify_arm_fpu(dv, cpu_number);
    249  1.1      matt }
    250  1.1      matt 
    251  1.1      matt struct cpuidtab {
    252  1.1      matt 	u_int32_t	cpuid;
    253  1.1      matt 	enum		cpu_class cpu_class;
    254  1.9   thorpej 	const char	*cpu_name;
    255  1.1      matt };
    256  1.1      matt 
    257  1.1      matt const struct cpuidtab cpuids[] = {
    258  1.1      matt 	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2" },
    259  1.1      matt 	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250" },
    260  1.1      matt 	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3" },
    261  1.1      matt 	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600" },
    262  1.1      matt 	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610" },
    263  1.1      matt 	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620" },
    264  1.1      matt 	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700" },
    265  1.1      matt 	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710" },
    266  1.1      matt 	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500" },
    267  1.1      matt 	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a" },
    268  1.1      matt 	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE" },
    269  1.1      matt 	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T" },
    270  1.1      matt 	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T" },
    271  1.1      matt 	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)" },
    272  1.1      matt 	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)" },
    273  1.1      matt 	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810" },
    274  1.1      matt 	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T" },
    275  1.1      matt 	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T" },
    276  1.1      matt 	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T" },
    277  1.1      matt 	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S" },
    278  1.1      matt 	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S" },
    279  1.6  rearnsha 	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S" },
    280  1.1      matt 	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110" },
    281  1.1      matt 	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100" },
    282  1.1      matt 	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110" },
    283  1.8   thorpej 	{ CPU_ID_I80200,	CPU_CLASS_XSCALE,	"i80200" },
    284  1.1      matt 	{ 0, CPU_CLASS_NONE, NULL }
    285  1.1      matt };
    286  1.1      matt 
    287  1.1      matt struct cpu_classtab {
    288  1.9   thorpej 	const char	*class_name;
    289  1.9   thorpej 	const char	*class_option;
    290  1.1      matt };
    291  1.1      matt 
    292  1.1      matt const struct cpu_classtab cpu_classes[] = {
    293  1.6  rearnsha 	{ "unknown",	NULL },			/* CPU_CLASS_NONE */
    294  1.6  rearnsha 	{ "ARM2",	"CPU_ARM2" },		/* CPU_CLASS_ARM2 */
    295  1.6  rearnsha 	{ "ARM2as",	"CPU_ARM250" },		/* CPU_CLASS_ARM2AS */
    296  1.6  rearnsha 	{ "ARM3",	"CPU_ARM3" },		/* CPU_CLASS_ARM3 */
    297  1.6  rearnsha 	{ "ARM6",	"CPU_ARM6" },		/* CPU_CLASS_ARM6 */
    298  1.6  rearnsha 	{ "ARM7",	"CPU_ARM7" },		/* CPU_CLASS_ARM7 */
    299  1.6  rearnsha 	{ "ARM7TDMI",	"CPU_ARM7TDMI" },	/* CPU_CLASS_ARM7TDMI */
    300  1.6  rearnsha 	{ "ARM8",	"CPU_ARM8" },		/* CPU_CLASS_ARM8 */
    301  1.6  rearnsha 	{ "ARM9TDMI",	NULL },			/* CPU_CLASS_ARM9TDMI */
    302  1.6  rearnsha 	{ "ARM9E-S",	NULL },			/* CPU_CLASS_ARM9ES */
    303  1.6  rearnsha 	{ "SA-1",	"CPU_SA110" },		/* CPU_CLASS_SA1 */
    304  1.7   thorpej 	{ "XScale",	"CPU_XSCALE" },		/* CPU_CLASS_XSCALE */
    305  1.1      matt };
    306  1.1      matt 
    307  1.1      matt /*
    308  1.1      matt  * Report the type of the specifed arm processor. This uses the generic and
    309  1.1      matt  * arm specific information in the cpu structure to identify the processor.
    310  1.1      matt  * The remaining fields in the cpu structure are filled in appropriately.
    311  1.1      matt  */
    312  1.1      matt 
    313  1.1      matt void
    314  1.1      matt identify_arm_cpu(dv, cpu_number)
    315  1.1      matt 	struct device *dv;
    316  1.1      matt 	int cpu_number;
    317  1.1      matt {
    318  1.1      matt 	cpu_t *cpu;
    319  1.1      matt 	u_int cpuid;
    320  1.1      matt 	int i;
    321  1.1      matt 
    322  1.1      matt 	cpu = &cpus[cpu_number];
    323  1.1      matt 	cpuid = cpu->cpu_id;
    324  1.1      matt 
    325  1.1      matt 	if (cpuid == 0) {
    326  1.1      matt 		printf("Processor failed probe - no CPU ID\n");
    327  1.1      matt 		return;
    328  1.1      matt 	}
    329  1.1      matt 
    330  1.1      matt 	for (i = 0; cpuids[i].cpuid != 0; i++)
    331  1.1      matt 		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
    332  1.1      matt 			cpu->cpu_class = cpuids[i].cpu_class;
    333  1.1      matt 			sprintf(cpu->cpu_model, "%s rev %d (%s core)",
    334  1.1      matt 			    cpuids[i].cpu_name, cpuid & CPU_ID_REVISION_MASK,
    335  1.1      matt 			    cpu_classes[cpu->cpu_class].class_name);
    336  1.1      matt 			break;
    337  1.1      matt 		}
    338  1.1      matt 
    339  1.1      matt 	if (cpuids[i].cpuid == 0)
    340  1.1      matt 		sprintf(cpu->cpu_model, "unknown CPU (ID = 0x%x)", cpuid);
    341  1.1      matt 
    342  1.1      matt 	switch (cpu->cpu_class) {
    343  1.1      matt 	case CPU_CLASS_ARM6:
    344  1.1      matt 	case CPU_CLASS_ARM7:
    345  1.3     chris 	case CPU_CLASS_ARM7TDMI:
    346  1.1      matt 	case CPU_CLASS_ARM8:
    347  1.1      matt 		if ((cpu->cpu_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
    348  1.1      matt 			strcat(cpu->cpu_model, " IDC disabled");
    349  1.1      matt 		else
    350  1.1      matt 			strcat(cpu->cpu_model, " IDC enabled");
    351  1.1      matt 		break;
    352  1.6  rearnsha 	case CPU_CLASS_ARM9TDMI:
    353  1.1      matt 	case CPU_CLASS_SA1:
    354  1.4      matt 	case CPU_CLASS_XSCALE:
    355  1.1      matt 		if ((cpu->cpu_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
    356  1.1      matt 			strcat(cpu->cpu_model, " DC disabled");
    357  1.1      matt 		else
    358  1.1      matt 			strcat(cpu->cpu_model, " DC enabled");
    359  1.1      matt 		if ((cpu->cpu_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
    360  1.1      matt 			strcat(cpu->cpu_model, " IC disabled");
    361  1.1      matt 		else
    362  1.1      matt 			strcat(cpu->cpu_model, " IC enabled");
    363  1.1      matt 		break;
    364  1.1      matt 	}
    365  1.1      matt 	if ((cpu->cpu_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
    366  1.1      matt 		strcat(cpu->cpu_model, " WB disabled");
    367  1.1      matt 	else
    368  1.1      matt 		strcat(cpu->cpu_model, " WB enabled");
    369  1.1      matt 
    370  1.1      matt 	if (cpu->cpu_ctrl & CPU_CONTROL_LABT_ENABLE)
    371  1.1      matt 		strcat(cpu->cpu_model, " LABT");
    372  1.1      matt 	else
    373  1.1      matt 		strcat(cpu->cpu_model, " EABT");
    374  1.1      matt 
    375  1.1      matt 	if (cpu->cpu_ctrl & CPU_CONTROL_BPRD_ENABLE)
    376  1.1      matt 		strcat(cpu->cpu_model, " branch prediction enabled");
    377  1.1      matt 
    378  1.1      matt 	/* Print the info */
    379  1.1      matt 
    380  1.1      matt 	printf(": %s\n", cpu->cpu_model);
    381  1.1      matt 
    382  1.1      matt 	switch (cpu->cpu_class) {
    383  1.1      matt #ifdef CPU_ARM2
    384  1.1      matt 	case CPU_CLASS_ARM2:
    385  1.1      matt #endif
    386  1.1      matt #ifdef CPU_ARM250
    387  1.1      matt 	case CPU_CLASS_ARM2AS:
    388  1.1      matt #endif
    389  1.1      matt #ifdef CPU_ARM3
    390  1.1      matt 	case CPU_CLASS_ARM3:
    391  1.1      matt #endif
    392  1.1      matt #ifdef CPU_ARM6
    393  1.1      matt 	case CPU_CLASS_ARM6:
    394  1.1      matt #endif
    395  1.1      matt #ifdef CPU_ARM7
    396  1.1      matt 	case CPU_CLASS_ARM7:
    397  1.1      matt #endif
    398  1.3     chris #ifdef CPU_ARM7TDMI
    399  1.3     chris 	case CPU_CLASS_ARM7TDMI:
    400  1.3     chris #endif
    401  1.1      matt #ifdef CPU_ARM8
    402  1.1      matt 	case CPU_CLASS_ARM8:
    403  1.6  rearnsha #endif
    404  1.6  rearnsha #ifdef CPU_ARM9
    405  1.6  rearnsha 	case CPU_CLASS_ARM9TDMI:
    406  1.1      matt #endif
    407  1.1      matt #ifdef CPU_SA110
    408  1.1      matt 	case CPU_CLASS_SA1:
    409  1.4      matt #endif
    410  1.4      matt #ifdef CPU_XSCALE
    411  1.4      matt 	case CPU_CLASS_XSCALE:
    412  1.1      matt #endif
    413  1.1      matt 		break;
    414  1.1      matt 	default:
    415  1.1      matt 		if (cpu_classes[cpu->cpu_class].class_option != NULL)
    416  1.1      matt 			printf("%s: %s does not fully support this CPU."
    417  1.1      matt 			       "\n", dv->dv_xname, ostype);
    418  1.1      matt 		else {
    419  1.1      matt 			printf("%s: This kernel does not fully support "
    420  1.1      matt 			       "this CPU.\n", dv->dv_xname);
    421  1.1      matt 			printf("%s: Recompile with \"options %s\" to "
    422  1.1      matt 			       "correct this.\n", dv->dv_xname,
    423  1.1      matt 			       cpu_classes[cpu->cpu_class].class_option);
    424  1.1      matt 		}
    425  1.1      matt 		break;
    426  1.1      matt 	}
    427  1.1      matt 
    428  1.1      matt }
    429  1.1      matt 
    430  1.1      matt 
    431  1.1      matt /*
    432  1.1      matt  * Report the type of the specifed arm fpu. This uses the generic and arm
    433  1.1      matt  * specific information in the cpu structure to identify the fpu. The
    434  1.1      matt  * remaining fields in the cpu structure are filled in appropriately.
    435  1.1      matt  */
    436  1.1      matt 
    437  1.1      matt void
    438  1.1      matt identify_arm_fpu(dv, cpu_number)
    439  1.1      matt 	struct device *dv;
    440  1.1      matt 	int cpu_number;
    441  1.1      matt {
    442  1.1      matt 	cpu_t *cpu;
    443  1.1      matt 
    444  1.1      matt 	cpu = &cpus[cpu_number];
    445  1.1      matt 
    446  1.1      matt 	/* Now for the FP info */
    447  1.1      matt 
    448  1.1      matt 	switch (cpu->fpu_class) {
    449  1.1      matt 	case FPU_CLASS_NONE :
    450  1.1      matt 		strcpy(cpu->fpu_model, "None");
    451  1.1      matt 		break;
    452  1.1      matt 	case FPU_CLASS_FPE :
    453  1.1      matt 		printf("%s: FPE: %s\n", dv->dv_xname, cpu->fpu_model);
    454  1.1      matt 		printf("%s: no FP hardware found\n", dv->dv_xname);
    455  1.1      matt 		break;
    456  1.1      matt 	case FPU_CLASS_FPA :
    457  1.1      matt 		printf("%s: FPE: %s\n", dv->dv_xname, cpu->fpu_model);
    458  1.1      matt 		if (cpu->fpu_type == FPU_TYPE_FPA11) {
    459  1.1      matt 			strcpy(cpu->fpu_model, "FPA11");
    460  1.1      matt 			printf("%s: FPA11 found\n", dv->dv_xname);
    461  1.1      matt 		} else {
    462  1.1      matt 			strcpy(cpu->fpu_model, "FPA");
    463  1.1      matt 			printf("%s: FPA10 found\n", dv->dv_xname);
    464  1.1      matt 		}
    465  1.1      matt 		if ((cpu->fpu_flags & 4) == 0)
    466  1.1      matt 			strcat(cpu->fpu_model, "");
    467  1.1      matt 		else
    468  1.1      matt 			strcat(cpu->fpu_model, " clk/2");
    469  1.1      matt 		break;
    470  1.1      matt 	case FPU_CLASS_FPU :
    471  1.1      matt 		sprintf(cpu->fpu_model, "Unknown FPU (ID=%02x)\n",
    472  1.1      matt 		    cpu->fpu_type);
    473  1.1      matt 		printf("%s: %s\n", dv->dv_xname, cpu->fpu_model);
    474  1.1      matt 		break;
    475  1.1      matt 	}
    476  1.1      matt }
    477  1.1      matt 
    478  1.1      matt /* End of cpu.c */
    479