svn commit: r225272 - in projects/armv6/sys/arm: arm include
Olivier Houchard
cognet at FreeBSD.org
Tue Aug 30 20:54:55 UTC 2011
Author: cognet
Date: Tue Aug 30 20:54:55 2011
New Revision: 225272
URL: http://svn.freebsd.org/changeset/base/225272
Log:
Initial cortex-a[8|9] support.
Some of those bits were submitted by Damjan Marion, and others by Ben Gray.
Modified:
projects/armv6/sys/arm/arm/cpufunc.c
projects/armv6/sys/arm/arm/cpufunc_asm_armv7.S
projects/armv6/sys/arm/arm/elf_trampoline.c
projects/armv6/sys/arm/include/cpufunc.h
projects/armv6/sys/arm/include/intr.h
Modified: projects/armv6/sys/arm/arm/cpufunc.c
==============================================================================
--- projects/armv6/sys/arm/arm/cpufunc.c Tue Aug 30 20:45:14 2011 (r225271)
+++ projects/armv6/sys/arm/arm/cpufunc.c Tue Aug 30 20:54:55 2011 (r225272)
@@ -968,6 +968,70 @@ struct cpu_functions fa526_cpufuncs = {
};
#endif /* CPU_FA526 || CPU_FA626TE */
+#if defined(CPU_CORTEXA)
+struct cpu_functions cortexa_cpufuncs = {
+ /* CPU functions */
+
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
+
+ /* MMU functions */
+
+ cpufunc_control, /* control */
+ cpufunc_domains, /* Domain */
+ armv7_setttb, /* Setttb */
+ cpufunc_faultstatus, /* Faultstatus */
+ cpufunc_faultaddress, /* Faultaddress */
+
+ /* TLB functions */
+
+ arm11_tlb_flushID, /* tlb_flushID */
+ armv7_tlb_flushID_SE, /* tlb_flushID_SE */
+ arm11_tlb_flushI, /* tlb_flushI */
+ arm11_tlb_flushI_SE, /* tlb_flushI_SE */
+ arm11_tlb_flushD, /* tlb_flushD */
+ arm11_tlb_flushD_SE, /* tlb_flushD_SE */
+
+ /* Cache operations */
+
+ armv7_idcache_wbinv_all, /* icache_sync_all */
+ armv7_icache_sync_range, /* icache_sync_range */
+
+ armv7_dcache_wbinv_all, /* dcache_wbinv_all */
+ armv7_dcache_wbinv_range, /* dcache_wbinv_range */
+ armv7_dcache_inv_range, /* dcache_inv_range */
+ armv7_dcache_wb_range, /* dcache_wb_range */
+
+ armv7_idcache_wbinv_all, /* idcache_wbinv_all */
+ armv7_idcache_wbinv_range, /* idcache_wbinv_range */
+
+ /* Note: From OMAP4 the L2 ops are filled in when the
+ * L2 cache controller is actually enabled.
+ */
+ cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
+
+ /* Other functions */
+
+ cpufunc_nullop, /* flush_prefetchbuf */
+ arm11_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ (void *)cpufunc_nullop, /* flush_brnchtgt_E */
+
+ arm11_sleep, /* sleep */
+
+ /* Soft functions */
+
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
+
+ arm11_context_switch, /* context_switch */
+
+ cortexa_setup /* cpu setup */
+};
+#endif /* CPU_CORTEXA */
/*
* Global constants also used by locore.s
@@ -982,7 +1046,8 @@ u_int cpu_reset_needs_v4_MMU_disable; /*
defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
defined(CPU_FA526) || defined(CPU_FA626TE) || defined(CPU_MV_PJ4B) || \
- defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
+ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
+ defined(CPU_CORTEXA)
static void get_cachetype_cp15(void);
@@ -1264,6 +1329,23 @@ set_cpufuncs()
goto out;
}
#endif /* CPU_ARM10 */
+#ifdef CPU_CORTEXA
+ if (cputype == CPU_ID_CORTEXA8R1 ||
+ cputype == CPU_ID_CORTEXA8R2 ||
+ cputype == CPU_ID_CORTEXA8R3 ||
+ cputype == CPU_ID_CORTEXA9R1 ||
+ cputype == CPU_ID_CORTEXA9R2) {
+ cpufuncs = cortexa_cpufuncs;
+ cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */
+ get_cachetype_cp15();
+
+ pmap_pte_init_mmu_v6();
+ /* Use powersave on this CPU. */
+ cpu_do_powersave = 1;
+ goto out;
+ }
+#endif /* CPU_CORTEXA */
+
#if defined(CPU_MV_PJ4B)
if (cputype == CPU_ID_MV88SV581X_V6 ||
cputype == CPU_ID_MV88SV581X_V7 ||
@@ -2226,6 +2308,52 @@ pj4bv7_setup(args)
}
#endif /* CPU_MV_PJ4B */
+#ifdef CPU_CORTEXA
+
+void
+cortexa_setup(char *args)
+{
+ int cpuctrl, cpuctrlmask;
+
+ cpuctrlmask = CPU_CONTROL_MMU_ENABLE | /* MMU enable [0] */
+ CPU_CONTROL_AFLT_ENABLE | /* Alignment fault [1] */
+ CPU_CONTROL_DC_ENABLE | /* DCache enable [2] */
+ CPU_CONTROL_BPRD_ENABLE | /* Branch prediction [11] */
+ CPU_CONTROL_IC_ENABLE | /* ICache enable [12] */
+ CPU_CONTROL_VECRELOC; /* Vector relocation [13] */
+
+ cpuctrl = CPU_CONTROL_MMU_ENABLE |
+ CPU_CONTROL_IC_ENABLE |
+ CPU_CONTROL_DC_ENABLE |
+ CPU_CONTROL_V6_EXTPAGE |
+ CPU_CONTROL_BPRD_ENABLE;
+
+#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
+ cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
+#endif
+
+ /* Switch to big endian */
+#ifdef __ARMEB__
+ cpuctrl |= CPU_CONTROL_BEND_ENABLE;
+#endif
+
+ /* Check if the vector page is at the high address (0xffff0000) */
+ if (vector_page == ARM_VECTORS_HIGH)
+ cpuctrl |= CPU_CONTROL_VECRELOC;
+
+ /* Clear out the cache */
+ cpu_idcache_wbinv_all();
+
+ /* Set the control register */
+ ctrl = cpuctrl;
+ cpu_control(cpuctrlmask, cpuctrl);
+
+ /* And again. */
+ cpu_idcache_wbinv_all();
+}
+#endif /* CPU_CORTEXA */
+
+
#ifdef CPU_SA110
struct cpu_option sa110_options[] = {
#ifdef COMPAT_12
Modified: projects/armv6/sys/arm/arm/cpufunc_asm_armv7.S
==============================================================================
--- projects/armv6/sys/arm/arm/cpufunc_asm_armv7.S Tue Aug 30 20:45:14 2011 (r225271)
+++ projects/armv6/sys/arm/arm/cpufunc_asm_armv7.S Tue Aug 30 20:54:55 2011 (r225272)
@@ -32,8 +32,6 @@
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
-#define isb mcr p15, 0, r0, c7, c5, 4
-#define dsb mcr p15, 0, r0, c7, c10, 4
#define TTB (0x59)
.Lcoherency_level:
@@ -48,16 +46,22 @@ __FBSDID("$FreeBSD$");
.word 0xfff
ENTRY(armv7_setttb)
- bic r0, r0, #0x18
- mcr p15, 0, r0, c2, c0, 0 /* load new TTB */
- mcr p15, 0, r0, c7, c5, 4 /* ISB */
+ stmdb sp!, {r0, lr}
+ bl _C_LABEL(armv7_idcache_wbinv_all) /* clean the D cache */
+ ldmia sp!, {r0, lr}
+ dsb
+ mcr p15, 0, r0, c2, c0, 0 /* Translation Table Base Register 0 (TTBR0) */
+ mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */
+ dsb
+ isb
RET
ENTRY(armv7_tlb_flushID)
- mcr p15, 0, r0, c7, c10, 4 /* DSB */
+ dsb
mcr p15, 0, r0, c8, c7, 0 /* flush I+D tlb */
mcr p15, 0, r0, c7, c5, 6 /* flush BTB */
- mcr p15, 0, r0, c7, c10, 4 /* DSB */
+ dsb
+ isb
mov pc, lr
ENTRY(armv7_tlb_flushID_SE)
@@ -65,7 +69,7 @@ ENTRY(armv7_tlb_flushID_SE)
bic r0, r0, r1
mcr p15, 0, r0, c8, c7, 1 /* flush D tlb single entry */
mcr p15, 0, r0, c7, c5, 6 /* flush BTB */
- mcr p15, 0, r0, c7, c10, 4 /* DSB */
+ dsb
mov pc, lr
/* Based on algorithm from ARM Architecture Reference Manual */
@@ -115,19 +119,19 @@ Skip:
cmp r3, r8
bne Loop1
Finished:
- mcr p15, 0, r0, c7, c5, 4
+ isb
mcr p15, 0, r0, c7, c5, 5
ldmia sp!, {r4, r5, r6, r7, r8, r9}
-RET
+ RET
ENTRY(armv7_idcache_wbinv_all)
stmdb sp!, {lr}
bl armv7_dcache_wbinv_all
- mcr p15, 0, r0, c7, c5, 0 /* Invalidate I cache SE with VA */
- mcr p15, 0, r0, c7, c10, 4
- mcr p15, 0, r0, c7, c5, 4
+ mcr p15, 0, r0, c7, c5, 0 /* Invalidate all I caches to PoU (ICIALLU) */
+ dsb
+ isb
ldmia sp!, {lr}
-RET
+ RET
/* XXX Temporary set it to 32 for MV cores, however this value should be
* get from Cache Type register
@@ -142,8 +146,8 @@ ENTRY(armv7_dcache_wb_range)
add r0, r0, ip
subs r1, r1, ip
bhi .Larmv7_wb_next
- mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
- bx lr
+ dsb /* data synchronization barrier */
+ RET
ENTRY(armv7_dcache_wbinv_range)
ldr ip, .Larmv7_line_size
@@ -152,8 +156,8 @@ ENTRY(armv7_dcache_wbinv_range)
add r0, r0, ip
subs r1, r1, ip
bhi .Larmv7_wbinv_next
- mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
- bx lr
+ dsb /* data synchronization barrier */
+ RET
/*
* Note, we must not invalidate everything. If the range is too big we
@@ -166,8 +170,8 @@ ENTRY(armv7_dcache_inv_range)
add r0, r0, ip
subs r1, r1, ip
bhi .Larmv7_inv_next
- mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
- bx lr
+ dsb /* data synchronization barrier */
+ RET
ENTRY(armv7_idcache_wbinv_range)
ldr ip, .Larmv7_line_size
@@ -177,8 +181,8 @@ ENTRY(armv7_idcache_wbinv_range)
add r0, r0, ip
subs r1, r1, ip
bhi .Larmv7_id_wbinv_next
- mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
- bx lr
+ dsb /* data synchronization barrier */
+ RET
ENTRY_NP(armv7_icache_sync_range)
ldr ip, .Larmv7_line_size
@@ -188,11 +192,22 @@ ENTRY_NP(armv7_icache_sync_range)
add r0, r0, ip
subs r1, r1, ip
bhi .Larmv7_sync_next
- mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
- bx lr
+ dsb /* data synchronization barrier */
+ RET
ENTRY(armv7_cpu_sleep)
- mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
- /* FIXME: replace with WFI instruction when AS will support it */
- .word 0xe320f003 /* wait for interrupt */
- bx lr
+ dsb /* data synchronization barrier */
+ wfi /* wait for interrupt */
+ RET
+
+ENTRY(armv7_context_switch)
+ dsb
+ mcr p15, 0, r0, c2, c0, 0 /* set the new TTB */
+ mcr p15, 0, r0, c8, c7, 0 /* and flush the I+D tlbs */
+ dsb
+ isb
+ RET
+
+ENTRY(armv7_drain_writebuf)
+ dsb
+ RET
Modified: projects/armv6/sys/arm/arm/elf_trampoline.c
==============================================================================
--- projects/armv6/sys/arm/arm/elf_trampoline.c Tue Aug 30 20:45:14 2011 (r225271)
+++ projects/armv6/sys/arm/arm/elf_trampoline.c Tue Aug 30 20:54:55 2011 (r225272)
@@ -83,6 +83,9 @@ void __startC(void);
#define cpu_l2cache_wbinv_all xscalec3_l2cache_purge
#elif defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
#define cpu_l2cache_wbinv_all sheeva_l2cache_wbinv_all
+#elif defined(CPU_CORTEXA)
+#define cpu_idcache_wbinv_all armv7_idcache_wbinv_all
+#define cpu_l2cache_wbinv_all()
#else
#define cpu_l2cache_wbinv_all()
#endif
@@ -103,6 +106,10 @@ int arm_pcache_unified;
int arm_dcache_align;
int arm_dcache_align_mask;
+u_int arm_cache_level;
+u_int arm_cache_type[14];
+u_int arm_cache_loc;
+
/* Additional cache information local to this file. Log2 of some of the
above numbers. */
static int arm_dcache_l2_nsets;
@@ -237,68 +244,102 @@ _startC(void)
static void
get_cachetype_cp15()
{
- u_int ctype, isize, dsize;
+ u_int ctype, isize, dsize, cpuid;
+ u_int clevel, csize, i, sel;
u_int multiplier;
+ u_char type;
__asm __volatile("mrc p15, 0, %0, c0, c0, 1"
- : "=r" (ctype));
-
+ : "=r" (ctype));
+
+ cpuid = cpufunc_id();
/*
* ...and thus spake the ARM ARM:
*
- * If an <opcode2> value corresponding to an unimplemented or
+ * 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())
+ if (ctype == cpuid)
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 */
+ if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
+ __asm __volatile("mrc p15, 1, %0, c0, c0, 1"
+ : "=r" (clevel));
+ arm_cache_level = clevel;
+ arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level) + 1;
+ 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_cache_type[sel] = csize;
+ }
+ 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));
+ arm_cache_type[sel] = csize;
+ }
+ i++;
+ clevel >>= 3;
+ }
+ } else {
+ 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_picache_ways = 1;
+ arm_pdcache_ways = 1;
} else {
- arm_picache_ways = multiplier <<
- (CPU_CT_xSIZE_ASSOC(isize) - 1);
+ arm_pdcache_ways = multiplier <<
+ (CPU_CT_xSIZE_ASSOC(dsize) - 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 = 1;
- } 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;
+
+ arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
+ arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
+ arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
+ CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
+
+ out:
+ arm_dcache_align_mask = arm_dcache_align - 1;
}
- arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
-
- arm_dcache_align = arm_pdcache_line_size;
-
- arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
- arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
- arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
- CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
- out:
- arm_dcache_align_mask = arm_dcache_align - 1;
}
static void
Modified: projects/armv6/sys/arm/include/cpufunc.h
==============================================================================
--- projects/armv6/sys/arm/include/cpufunc.h Tue Aug 30 20:45:14 2011 (r225271)
+++ projects/armv6/sys/arm/include/cpufunc.h Tue Aug 30 20:54:55 2011 (r225272)
@@ -415,8 +415,9 @@ void sheeva_l2cache_wb_range (vm_offset
void sheeva_l2cache_wbinv_all (void);
#endif
-#if defined(CPU_ARM11) || defined(CPU_MV_PJ4B)
+#if defined(CPU_ARM11) || defined(CPU_MV_PJ4B) || defined(CPU_CORTEXA)
void arm11_setttb (u_int);
+void arm11_sleep (int);
void arm11_tlb_flushID_SE (u_int);
void arm11_tlb_flushI_SE (u_int);
@@ -455,6 +456,7 @@ void armv6_icache_sync_all (void);
void armv6_dcache_wbinv_all (void);
void armv6_idcache_wbinv_all (void);
+void armv7_setttb (u_int);
void armv7_tlb_flushID (void);
void armv7_tlb_flushID_SE (u_int);
void armv7_icache_sync_range (vm_offset_t, vm_size_t);
@@ -464,11 +466,17 @@ void armv7_idcache_wbinv_all (void);
void armv7_dcache_wbinv_range (vm_offset_t, vm_size_t);
void armv7_dcache_inv_range (vm_offset_t, vm_size_t);
void armv7_dcache_wb_range (vm_offset_t, vm_size_t);
+void armv7_cpu_sleep (int);
+void armv7_setup (char *string);
+void armv7_context_switch (void);
+void armv7_drain_writebuf (void);
void pj4bv7_setup (char *string);
void pj4bv6_setup (char *string);
void pj4b_config (void);
void armadaxp_idcache_wbinv_all (void);
+
+void cortexa_setup (char *);
#endif
#if defined(CPU_ARM9E) || defined (CPU_ARM10)
Modified: projects/armv6/sys/arm/include/intr.h
==============================================================================
--- projects/armv6/sys/arm/include/intr.h Tue Aug 30 20:45:14 2011 (r225271)
+++ projects/armv6/sys/arm/include/intr.h Tue Aug 30 20:54:55 2011 (r225272)
@@ -50,6 +50,8 @@
#elif defined(CPU_ARM9) || defined(SOC_MV_KIRKWOOD) || \
defined(CPU_XSCALE_IXP435)
#define NIRQ 64
+#elif defined(CPU_CORTEXA)
+#define NIRQ 128
#else
#define NIRQ 32
#endif
More information about the svn-src-projects
mailing list