diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2009-06-23 18:16:03 +0100 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2009-09-08 13:19:43 +0100 |
commit | 053d9d0f117f5b3112eb17f2224b36447abbdc5c (patch) | |
tree | b54b0a8f33e2b506bf14a8b35c6d56829b722876 /arch/arm/include | |
parent | 7860173c5e251e9be14d33873ad769d314180df7 (diff) |
Cortex-M3: Add base support for Cortex-M3
This patch adds the base support for the Cortex-M3 processor (ARMv7-M
architecture). It consists of the corresponding arch/arm/mm/ files and
various #ifdef's around the kernel. Exception handling is implemented by
a subsequent patch.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm/include')
-rw-r--r-- | arch/arm/include/asm/assembler.h | 13 | ||||
-rw-r--r-- | arch/arm/include/asm/cacheflush.h | 24 | ||||
-rw-r--r-- | arch/arm/include/asm/cputype.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/glue.h | 8 | ||||
-rw-r--r-- | arch/arm/include/asm/irqflags.h | 41 | ||||
-rw-r--r-- | arch/arm/include/asm/proc-fns.h | 8 | ||||
-rw-r--r-- | arch/arm/include/asm/processor.h | 10 | ||||
-rw-r--r-- | arch/arm/include/asm/ptrace.h | 38 | ||||
-rw-r--r-- | arch/arm/include/asm/system.h | 3 |
9 files changed, 144 insertions, 3 deletions
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 550cdcfb1f1c..2539d254caa7 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -96,7 +96,11 @@ * assumes FIQs are enabled, and that the processor is in SVC mode. */ .macro save_and_disable_irqs, oldcpsr +#ifdef CONFIG_CPU_V7M + mrs \oldcpsr, primask +#else mrs \oldcpsr, cpsr +#endif disable_irq .endm @@ -105,7 +109,11 @@ * guarantee that this will preserve the flags. */ .macro restore_irqs, oldcpsr +#ifdef CONFIG_CPU_V7M + msr primask, \oldcpsr +#else msr cpsr_c, \oldcpsr +#endif .endm #define USER(x...) \ @@ -115,7 +123,10 @@ .long 9999b,9001f; \ .previous -#ifdef CONFIG_THUMB2_KERNEL +#if defined(CONFIG_CPU_V7M) + .macro setmode, mode, reg + .endm +#elif defined(CONFIG_THUMB2_KERNEL) .macro setmode, mode, reg mov \reg, #\mode msr cpsr_c, \reg diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index a8076bfdead4..91aec141aa15 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -115,6 +115,14 @@ //# endif #endif +#if defined(CONFIG_CPU_V7M) +# ifdef _CACHE +# error "Multi-cache not supported on ARMv7-M" +# else +# define _CACHE v7m +# endif +#endif + #if !defined(_CACHE) && !defined(MULTI_CACHE) #error Unknown cache maintainence model #endif @@ -235,6 +243,22 @@ extern struct cpu_cache_fns cpu_cache; #else +#ifdef CONFIG_CPU_V7M + +static inline void v7m_flush_kern_all(void) { } +static inline void v7m_flush_user_all(void) { } +static inline void v7m_flush_user_range(unsigned long a, unsigned long b, unsigned int c) { } + +static inline void v7m_coherent_kern_range(unsigned long a, unsigned long b) { } +static inline void v7m_coherent_user_range(unsigned long a, unsigned long b) { } +static inline void v7m_flush_kern_dcache_page(void *a) { } + +static inline void v7m_dma_inv_range(const void *a, const void *b) { } +static inline void v7m_dma_clean_range(const void *a, const void *b) { } +static inline void v7m_dma_flush_range(const void *a, const void *b) { } + +#endif + #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) #define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) #define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index b3e656c6fb78..c2fe374fcb7f 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -42,6 +42,8 @@ : "cc"); \ __val; \ }) +#elif defined(CONFIG_CPU_V7M) +#define read_cpuid(reg) (*(unsigned int *)0xe000ed00) #else extern unsigned int processor_id; #define read_cpuid(reg) (processor_id) diff --git a/arch/arm/include/asm/glue.h b/arch/arm/include/asm/glue.h index a0e39d5d00c9..0a3bb3d8fab6 100644 --- a/arch/arm/include/asm/glue.h +++ b/arch/arm/include/asm/glue.h @@ -115,6 +115,14 @@ # endif #endif +#ifdef CONFIG_CPU_ABRT_EV7M +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER v7m_early_abort +# endif +#endif + #ifndef CPU_DABORT_HANDLER #error Unknown data abort handler type #endif diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h index 6d09974e6646..5dbb6de221ce 100644 --- a/arch/arm/include/asm/irqflags.h +++ b/arch/arm/include/asm/irqflags.h @@ -10,6 +10,15 @@ */ #if __LINUX_ARM_ARCH__ >= 6 +#ifdef CONFIG_CPU_V7M +#define raw_local_irq_save(x) \ + ({ \ + __asm__ __volatile__( \ + "mrs %0, primask @ local_irq_save\n" \ + "cpsid i" \ + : "=r" (x) : : "memory", "cc"); \ + }) +#else #define raw_local_irq_save(x) \ ({ \ __asm__ __volatile__( \ @@ -17,6 +26,7 @@ "cpsid i" \ : "=r" (x) : : "memory", "cc"); \ }) +#endif #define raw_local_irq_enable() __asm__("cpsie i @ __sti" : : : "memory", "cc") #define raw_local_irq_disable() __asm__("cpsid i @ __cli" : : : "memory", "cc") @@ -103,6 +113,35 @@ #endif +#ifdef CONFIG_CPU_V7M + +/* + * Save the current interrupt enable state. + */ +#define raw_local_save_flags(x) \ + ({ \ + __asm__ __volatile__( \ + "mrs %0, primask @ local_save_flags" \ + : "=r" (x) : : "memory", "cc"); \ + }) + +/* + * restore saved IRQ & FIQ state + */ +#define raw_local_irq_restore(x) \ + __asm__ __volatile__( \ + "msr primask, %0 @ local_irq_restore\n" \ + : \ + : "r" (x) \ + : "memory", "cc") + +#define raw_irqs_disabled_flags(flags) \ +({ \ + (int)((flags) & 1); \ +}) + +#else + /* * Save the current interrupt enable state. */ @@ -128,5 +167,7 @@ (int)((flags) & PSR_I_BIT); \ }) +#endif /* CONFIG_CPU_V7M */ + #endif #endif diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index db80203b68e0..d9faa2b32dfb 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -209,6 +209,14 @@ # define CPU_NAME cpu_v7 # endif # endif +# ifdef CONFIG_CPU_V7M +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_v7m +# endif +# endif #endif #ifndef __ASSEMBLY__ diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index 0b3478c3010d..64409f343381 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h @@ -57,7 +57,15 @@ struct thread_struct { #ifdef CONFIG_MMU #define nommu_start_thread(regs) do { } while (0) #else +#ifndef CONFIG_CPU_V7M #define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data +#else +#define nommu_start_thread(regs) do { \ + regs->ARM_r10 = current->mm->start_data; \ + regs->ARM_sp -= 32; /* exception return state */ \ + regs->ARM_EXC_lr = 0xfffffffdL; /* exception lr */ \ +} while (0) +#endif #endif #define start_thread(regs,pc,sp) \ @@ -72,7 +80,7 @@ struct thread_struct { if (elf_hwcap & HWCAP_THUMB && pc & 1) \ regs->ARM_cpsr |= PSR_T_BIT; \ regs->ARM_cpsr |= PSR_ENDSTATE; \ - regs->ARM_pc = pc & ~1; /* pc */ \ + regs->ARM_pc = pc /*& ~1*/; /* pc */ \ regs->ARM_sp = sp; /* sp */ \ regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index bbecccda76d0..1f7419c9fcc0 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -37,16 +37,25 @@ #define FIQ26_MODE 0x00000001 #define IRQ26_MODE 0x00000002 #define SVC26_MODE 0x00000003 +#ifndef CONFIG_CPU_V7M #define USR_MODE 0x00000010 +#define SVC_MODE 0x00000013 +#else +#define USR_MODE 0x00000000 +#define SVC_MODE 0x00000000 +#endif #define FIQ_MODE 0x00000011 #define IRQ_MODE 0x00000012 -#define SVC_MODE 0x00000013 #define ABT_MODE 0x00000017 #define UND_MODE 0x0000001b #define SYSTEM_MODE 0x0000001f #define MODE32_BIT 0x00000010 #define MODE_MASK 0x0000001f +#ifndef CONFIG_CPU_V7M #define PSR_T_BIT 0x00000020 +#else +#define PSR_T_BIT 0x01000000 +#endif #define PSR_F_BIT 0x00000040 #define PSR_I_BIT 0x00000080 #define PSR_A_BIT 0x00000100 @@ -101,6 +110,28 @@ struct pt_regs { long uregs[18]; }; +#ifdef CONFIG_CPU_V7M +/* Automatically saved registers */ +#define ARM_cpsr uregs[17] +#define ARM_pc uregs[16] +#define ARM_lr uregs[15] +#define ARM_ip uregs[14] +#define ARM_r3 uregs[13] +#define ARM_r2 uregs[12] +#define ARM_r1 uregs[11] +#define ARM_r0 uregs[10] +/* saved by the exception entry code */ +#define ARM_EXC_lr uregs[9] +#define ARM_sp uregs[8] +#define ARM_fp uregs[7] +#define ARM_r10 uregs[6] +#define ARM_r9 uregs[5] +#define ARM_r8 uregs[4] +#define ARM_r7 uregs[3] +#define ARM_r6 uregs[2] +#define ARM_r5 uregs[1] +#define ARM_r4 uregs[0] +#else #define ARM_cpsr uregs[16] #define ARM_pc uregs[15] #define ARM_lr uregs[14] @@ -119,6 +150,7 @@ struct pt_regs { #define ARM_r1 uregs[1] #define ARM_r0 uregs[0] #define ARM_ORIG_r0 uregs[17] +#endif #ifdef __KERNEL__ @@ -150,6 +182,7 @@ struct pt_regs { */ static inline int valid_user_regs(struct pt_regs *regs) { +#ifndef CONFIG_CPU_V7M if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) { regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT); return 1; @@ -163,6 +196,9 @@ static inline int valid_user_regs(struct pt_regs *regs) regs->ARM_cpsr |= USR_MODE; return 0; +#else + return 1; +#endif } #define instruction_pointer(regs) (regs)->ARM_pc diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index a6367611cd70..4851e9d0eba5 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -15,6 +15,7 @@ #define CPU_ARCH_ARMv5TEJ 7 #define CPU_ARCH_ARMv6 8 #define CPU_ARCH_ARMv7 9 +#define CPU_ARCH_ARMv7M 10 /* * CR1 bits (CP#15 CR1) @@ -200,7 +201,9 @@ static inline void set_copro_access(unsigned int val) * so enable interrupts over the context switch to avoid high * latency. */ +#ifndef CONFIG_CPU_V7M #define __ARCH_WANT_INTERRUPTS_ON_CTXSW +#endif /* * switch_to(prev, next) should switch from task `prev' to `next' |