#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/disassem.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/uma.h>
#include <machine/cpufunc.h>
unsigned int arm_dcache_align;
unsigned int arm_dcache_align_mask;
#ifdef CPU_MV_PJ4B
static void pj4bv7_setup(void);
#endif
#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
static void cortexa_setup(void);
#endif
#ifdef CPU_MV_PJ4B
struct cpu_functions pj4bv7_cpufuncs = {
.cf_l2cache_wbinv_all = (void *)cpufunc_nullop,
.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
.cf_l2cache_inv_range = (void *)cpufunc_nullop,
.cf_l2cache_wb_range = (void *)cpufunc_nullop,
.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
.cf_sleep = (void *)cpufunc_nullop,
.cf_setup = pj4bv7_setup
};
#endif
#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
struct cpu_functions cortexa_cpufuncs = {
.cf_l2cache_wbinv_all = cpufunc_nullop,
.cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
.cf_l2cache_inv_range = (void *)cpufunc_nullop,
.cf_l2cache_wb_range = (void *)cpufunc_nullop,
.cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
.cf_sleep = armv7_cpu_sleep,
.cf_setup = cortexa_setup
};
#endif
struct cpu_functions cpufuncs;
u_int cputype;
static void get_cachetype_cp15(void);
static void
get_cachetype_cp15(void)
{
u_int ctype, dsize, cpuid;
u_int clevel, csize, i, sel;
u_char type;
ctype = cp15_ctr_get();
cpuid = cp15_midr_get();
if (ctype == cpuid)
goto out;
if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
__asm __volatile("mrc p15, 1, %0, c0, c0, 1"
: "=r" (clevel));
i = 0;
while ((type = (clevel & 0x7)) && i < 7) {
if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
type == CACHE_SEP_CACHE) {
sel = i << 1;
__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
: : "r" (sel));
__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
: "=r" (csize));
arm_dcache_align = 1U <<
(CPUV7_CT_xSIZE_LEN(csize) + 4);
}
if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
sel = (i << 1) | 1;
__asm __volatile("mcr p15, 2, %0, c0, c0, 0"
: : "r" (sel));
__asm __volatile("mrc p15, 1, %0, c0, c0, 0"
: "=r" (csize));
}
i++;
clevel >>= 3;
}
} else {
dsize = CPU_CT_DSIZE(ctype);
arm_dcache_align = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
if (dsize & CPU_CT_xSIZE_M)
arm_dcache_align = 0;
}
}
out:
arm_dcache_align_mask = arm_dcache_align - 1;
}
int
set_cpufuncs(void)
{
cputype = cp15_midr_get();
cputype &= CPU_ID_CPU_MASK;
#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
switch(cputype & CPU_ID_SCHEME_MASK) {
case CPU_ID_CORTEXA5:
case CPU_ID_CORTEXA7:
case CPU_ID_CORTEXA8:
case CPU_ID_CORTEXA9:
case CPU_ID_CORTEXA12:
case CPU_ID_CORTEXA15:
case CPU_ID_CORTEXA53:
case CPU_ID_CORTEXA57:
case CPU_ID_CORTEXA72:
case CPU_ID_KRAIT300:
cpufuncs = cortexa_cpufuncs;
get_cachetype_cp15();
goto out;
default:
break;
}
#endif
#if defined(CPU_MV_PJ4B)
if (cputype == CPU_ID_MV88SV581X_V7 ||
cputype == CPU_ID_MV88SV584X_V7 ||
cputype == CPU_ID_ARM_88SV581X_V7) {
cpufuncs = pj4bv7_cpufuncs;
get_cachetype_cp15();
goto out;
}
#endif
panic("No support for this CPU type (%08x) in kernel", cputype);
return(ARCHITECTURE_NOT_PRESENT);
out:
uma_set_cache_align_mask(arm_dcache_align_mask);
return (0);
}
#if defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
static __inline void
cpu_scc_setup_ccnt(void)
{
#ifdef _PMC_USER_READ_WRITE_
cp15_pmuserenr_set(1);
#endif
cp15_pminten_clr(0xFFFFFFFF);
cp15_pmcr_set(5);
cp15_pmcnten_set(0x80000000);
}
#endif
#ifdef CPU_MV_PJ4B
static void
pj4bv7_setup(void)
{
pj4b_config();
cpu_scc_setup_ccnt();
}
#endif
#if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
static void
cortexa_setup(void)
{
cpu_scc_setup_ccnt();
}
#endif