Date: Tue, 30 Aug 2011 20:54:55 +0000 (UTC) From: Olivier Houchard <cognet@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r225272 - in projects/armv6/sys/arm: arm include Message-ID: <201108302054.p7UKst1A066762@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201108302054.p7UKst1A066762>