summaryrefslogtreecommitdiff
path: root/arch/arm/include
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2009-06-23 18:16:03 +0100
committerCatalin Marinas <catalin.marinas@arm.com>2009-09-08 13:19:43 +0100
commit053d9d0f117f5b3112eb17f2224b36447abbdc5c (patch)
treeb54b0a8f33e2b506bf14a8b35c6d56829b722876 /arch/arm/include
parent7860173c5e251e9be14d33873ad769d314180df7 (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.h13
-rw-r--r--arch/arm/include/asm/cacheflush.h24
-rw-r--r--arch/arm/include/asm/cputype.h2
-rw-r--r--arch/arm/include/asm/glue.h8
-rw-r--r--arch/arm/include/asm/irqflags.h41
-rw-r--r--arch/arm/include/asm/proc-fns.h8
-rw-r--r--arch/arm/include/asm/processor.h10
-rw-r--r--arch/arm/include/asm/ptrace.h38
-rw-r--r--arch/arm/include/asm/system.h3
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'