Fetch cache info from the Cache Type register on ARM7TDMI and "greater"

processors.  Report this when the processor is attached.
This commit is contained in:
thorpej 2001-11-29 02:24:58 +00:00
parent 9058fce64e
commit 959181a8b2
4 changed files with 168 additions and 16 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpufunc.c,v 1.18 2001/11/26 22:26:44 thorpej Exp $ */
/* $NetBSD: cpufunc.c,v 1.19 2001/11/29 02:24:58 thorpej Exp $ */
/*
* arm7tdmi support code Copyright (c) 2001 John Fremlin
@ -58,6 +58,21 @@
#include <arm/cpufunc.h>
/* PRIMARY CACHE VARIABLES */
int arm_picache_size;
int arm_picache_line_size;
int arm_picache_ways;
int arm_pdcache_size; /* and unified */
int arm_pdcache_line_size;
int arm_pdcache_ways;
int arm_pcache_type;
int arm_pcache_unified;
int arm_dcache_align;
int arm_dcache_align_mask;
#ifdef CPU_ARM3
struct cpu_functions arm3_cpufuncs = {
/* CPU functions */
@ -703,6 +718,70 @@ struct cpu_functions cpufuncs;
u_int cputype;
u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */
static void
get_cachetype()
{
u_int ctype, isize, dsize;
u_int multiplier;
__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
: "=r" (ctype));
/*
* ...and thus spake the ARM ARM:
*
* If an <opcode2> value corresponding to an unimplemented or
* reserved ID register is encountered, the System Control
* processor returns the value of the main ID register.
*/
if (ctype == cpufunc_id())
goto out;
if ((ctype & CPU_CT_S) == 0)
arm_pcache_unified = 1;
/*
* If you want to know how this code works, go read the ARM ARM.
*/
arm_pcache_type = CPU_CT_CTYPE(ctype);
if (arm_pcache_unified == 0) {
isize = CPU_CT_ISIZE(ctype);
multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
if (isize & CPU_CT_xSIZE_M)
arm_picache_line_size = 0; /* not present */
else
arm_picache_ways = 1;
} else {
arm_picache_ways = multiplier <<
(CPU_CT_xSIZE_ASSOC(isize) - 1);
}
arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
}
dsize = CPU_CT_DSIZE(ctype);
multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
if (dsize & CPU_CT_xSIZE_M)
arm_pdcache_line_size = 0; /* not present */
else
arm_pdcache_ways = 0;
} else {
arm_pdcache_ways = multiplier <<
(CPU_CT_xSIZE_ASSOC(dsize) - 1);
}
arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
arm_dcache_align = arm_pdcache_line_size;
out:
arm_dcache_align_mask = arm_dcache_align - 1;
}
/*
* Cannot panic here as we may not have a console yet ...
*/
@ -719,6 +798,8 @@ set_cpufuncs()
(cputype & 0x00000f00) == 0x00000300) {
cpufuncs = arm3_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 0;
/* XXX Cache info? */
arm_dcache_align_mask = -1;
return 0;
}
#endif /* CPU_ARM3 */
@ -727,6 +808,8 @@ set_cpufuncs()
(cputype & 0x00000f00) == 0x00000600) {
cpufuncs = arm6_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 0;
/* XXX Cache info? */
arm_dcache_align_mask = -1;
return 0;
}
#endif /* CPU_ARM6 */
@ -736,6 +819,8 @@ set_cpufuncs()
(cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V3) {
cpufuncs = arm7_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 0;
/* XXX Cache info? */
arm_dcache_align_mask = -1;
return 0;
}
#endif /* CPU_ARM7 */
@ -745,6 +830,7 @@ set_cpufuncs()
(cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) {
cpufuncs = arm7tdmi_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 0;
get_cachetype();
return 0;
}
#endif
@ -753,6 +839,7 @@ set_cpufuncs()
(cputype & 0x0000f000) == 0x00008000) {
cpufuncs = arm8_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 0; /* XXX correct? */
get_cachetype();
return 0;
}
#endif /* CPU_ARM8 */
@ -761,6 +848,7 @@ set_cpufuncs()
pte_cache_mode = PT_C; /* Select write-through cacheing. */
cpufuncs = arm9_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
get_cachetype();
return 0;
}
#endif /* CPU_ARM9 */
@ -769,6 +857,7 @@ set_cpufuncs()
cputype == CPU_ID_SA1110) {
cpufuncs = sa110_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */
get_cachetype();
return 0;
}
#endif /* CPU_SA110 */
@ -777,6 +866,7 @@ set_cpufuncs()
pte_cache_mode = PT_C; /* Select write-through cacheing. */
cpufuncs = xscale_writethrough_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */
get_cachetype();
return 0;
}
#endif /* CPU_XSCALE */

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.11 2001/11/24 01:26:24 thorpej Exp $ */
/* $NetBSD: cpu.c,v 1.12 2001/11/29 02:24:58 thorpej Exp $ */
/*
* Copyright (c) 1995 Mark Brinicombe.
@ -311,6 +311,25 @@ const struct cpu_classtab cpu_classes[] = {
* The remaining fields in the cpu structure are filled in appropriately.
*/
static const char *wtnames[] = {
"write-through",
"write-back",
"write-back",
"**unknown 3**",
"**unknown 4**",
"write-back-locking", /* XXX XScale-specific? */
"write-back-locking-A",
"write-back-locking-B",
"**unknown 8**",
"**unknown 9**",
"**unknown 10**",
"**unknown 11**",
"**unknown 12**",
"**unknown 13**",
"**unknown 14**",
"**unknown 15**",
};
void
identify_arm_cpu(dv, cpu_number)
struct device *dv;
@ -377,9 +396,29 @@ identify_arm_cpu(dv, cpu_number)
strcat(cpu->cpu_model, " branch prediction enabled");
/* Print the info */
printf(": %s\n", cpu->cpu_model);
/* Print cache info. */
if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
goto skip_pcache;
if (arm_pcache_unified) {
printf("%s: %dKB/%dB %d-way %s unified cache\n",
dv->dv_xname, arm_pdcache_size / 1024,
arm_pdcache_line_size, arm_pdcache_ways,
wtnames[arm_pcache_type]);
} else {
printf("%s: %dKB/%dB %d-way Instruction cache\n",
dv->dv_xname, arm_picache_size / 1024,
arm_picache_line_size, arm_picache_ways);
printf("%s: %dKB/%dB %d-way %s Data cache\n",
dv->dv_xname, arm_pdcache_size / 1024,
arm_pdcache_line_size, arm_pdcache_ways,
wtnames[arm_pcache_type]);
}
skip_pcache:
switch (cpu->cpu_class) {
#ifdef CPU_ARM2
case CPU_CLASS_ARM2:

View File

@ -1,4 +1,4 @@
/* $NetBSD: armreg.h,v 1.8 2001/07/18 16:31:17 rjs Exp $ */
/* $NetBSD: armreg.h,v 1.9 2001/11/29 02:24:59 thorpej Exp $ */
/*
* Copyright (c) 1998, 2001 Ben Harris
@ -224,17 +224,21 @@
#define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE
/* Cache type register definitions */
#define CPU_CT_IINFO_MASK 0x00000fff
#define CPU_CT_IINFO_SHIFT 0
#define CPU_CT_DINFO_MASK 0x00fff000
#define CPU_CT_DINFO_SHIFT 12
#define CPU_CT_HARVARD 0x01000000
#define CPU_CT_TYPE_MASK 0x1e000000
/* "Info" subfields -- see ARM ARM for meanings. */
#define CPU_CT_LINE_MASK 0x00000003
#define CPU_CT_M_BIT 0x00000004
#define CPU_CT_ASSOC_MASK 0x00000038
#define CPU_CT_SIZE_MASK 0x000001c0
#define CPU_CT_ISIZE(x) ((x) & 0xfff) /* I$ info */
#define CPU_CT_DSIZE(x) (((x) >> 12) & 0xfff) /* D$ info */
#define CPU_CT_S (1U << 24) /* split cache */
#define CPU_CT_CTYPE(x) (((x) >> 25) & 0xf) /* cache type */
#define CPU_CT_CTYPE_WT 0 /* write-through */
#define CPU_CT_CTYPE_WB1 1 /* write-back, clean w/ read */
#define CPU_CT_CTYPE_WB2 2 /* w/b, clean w/ cp15,7 */
#define CPU_CT_CTYPE_WB6 6 /* w/b, cp15,7, lockdown fmt A */
#define CPU_CT_CTYPE_WB7 7 /* w/b, cp15,7, lockdown fmt B */
#define CPU_CT_xSIZE_LEN(x) ((x) & 0x3) /* line size */
#define CPU_CT_xSIZE_M (1U << 2) /* multiplier */
#define CPU_CT_xSIZE_ASSOC(x) (((x) >> 3) & 0x7) /* associativity */
#define CPU_CT_xSIZE_SIZE(x) (((x) >> 6) & 0x7) /* size */
/* Fault status register definitions */

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpufunc.h,v 1.13 2001/11/28 00:18:46 thorpej Exp $ */
/* $NetBSD: cpufunc.h,v 1.14 2001/11/29 02:24:59 thorpej Exp $ */
/*
* Copyright (c) 1997 Mark Brinicombe.
@ -396,6 +396,25 @@ int get_pc_str_offset __P((void));
void cpu_reset __P((void)) __attribute__((__noreturn__));
/*
* Cache info variables.
*/
/* PRIMARY CACHE VARIABLES */
int arm_picache_size;
int arm_picache_line_size;
int arm_picache_ways;
int arm_pdcache_size; /* and unified */
int arm_pdcache_line_size;
int arm_pdcache_ways;
int arm_pcache_type;
int arm_pcache_unified;
int arm_dcache_align;
int arm_dcache_align_mask;
#endif /* _KERNEL */
#endif /* _ARM32_CPUFUNC_H_ */