Home | History | Annotate | Line # | Download | only in arm32
cpu.c revision 1.6.2.1
      1  1.6.2.1   thorpej /*	$NetBSD: cpu.c,v 1.6.2.1 2001/11/12 21:16:29 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.6.2.1   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.6.2.1   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.6.2.1   thorpej 	const char	*class_name;
    289  1.6.2.1   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.6.2.1   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