diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-01-18 04:42:25 -0500 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-02-15 12:46:10 -0500 |
commit | 8b5850f8ac8d9b809db4588b80b568faca5aaaaf (patch) | |
tree | 9cb026d610787ba2177e3543d44c7f94fdfd6bfe /arch/arc/kernel | |
parent | 9c57564e26c5392ac7f0e08cc0ad8d29e225a3a3 (diff) |
ARC: Support for single cycle Close Coupled Mem (CCM)
* Includes mapping of CCMs in address space
* Annotations to move arbitrary code/data into CCM
* Moving some of the critical code/data into CCM
* Runtime detection/reporting
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r-- | arch/arc/kernel/entry.S | 4 | ||||
-rw-r--r-- | arch/arc/kernel/setup.c | 53 | ||||
-rw-r--r-- | arch/arc/kernel/vmlinux.lds.S | 21 |
3 files changed, 75 insertions, 3 deletions
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index f8efade15368..3f628ca9b71a 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S | |||
@@ -149,7 +149,7 @@ VECTOR reserved ; Reserved Exceptions | |||
149 | 149 | ||
150 | ;##################### Scratch Mem for IRQ stack switching ############# | 150 | ;##################### Scratch Mem for IRQ stack switching ############# |
151 | 151 | ||
152 | .section .data ; NOT .global | 152 | ARCFP_DATA int1_saved_reg |
153 | .align 32 | 153 | .align 32 |
154 | .type int1_saved_reg, @object | 154 | .type int1_saved_reg, @object |
155 | .size int1_saved_reg, 4 | 155 | .size int1_saved_reg, 4 |
@@ -159,7 +159,7 @@ int1_saved_reg: | |||
159 | /* Each Interrupt level needs it's own scratch */ | 159 | /* Each Interrupt level needs it's own scratch */ |
160 | #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS | 160 | #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS |
161 | 161 | ||
162 | .section .data ; NOT .global | 162 | ARCFP_DATA int2_saved_reg |
163 | .type int2_saved_reg, @object | 163 | .type int2_saved_reg, @object |
164 | .size int2_saved_reg, 4 | 164 | .size int2_saved_reg, 4 |
165 | int2_saved_reg: | 165 | int2_saved_reg: |
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index e25538e29fe7..6cc361c6751a 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c | |||
@@ -64,6 +64,33 @@ void __init read_arc_build_cfg_regs(void) | |||
64 | cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR); | 64 | cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR); |
65 | cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR); | 65 | cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR); |
66 | 66 | ||
67 | /* Note that we read the CCM BCRs independent of kernel config | ||
68 | * This is to catch the cases where user doesn't know that | ||
69 | * CCMs are present in hardware build | ||
70 | */ | ||
71 | { | ||
72 | struct bcr_iccm iccm; | ||
73 | struct bcr_dccm dccm; | ||
74 | struct bcr_dccm_base dccm_base; | ||
75 | unsigned int bcr_32bit_val; | ||
76 | |||
77 | bcr_32bit_val = read_aux_reg(ARC_REG_ICCM_BCR); | ||
78 | if (bcr_32bit_val) { | ||
79 | iccm = *((struct bcr_iccm *)&bcr_32bit_val); | ||
80 | cpu->iccm.base_addr = iccm.base << 16; | ||
81 | cpu->iccm.sz = 0x2000 << (iccm.sz - 1); | ||
82 | } | ||
83 | |||
84 | bcr_32bit_val = read_aux_reg(ARC_REG_DCCM_BCR); | ||
85 | if (bcr_32bit_val) { | ||
86 | dccm = *((struct bcr_dccm *)&bcr_32bit_val); | ||
87 | cpu->dccm.sz = 0x800 << (dccm.sz); | ||
88 | |||
89 | READ_BCR(ARC_REG_DCCMBASE_BCR, dccm_base); | ||
90 | cpu->dccm.base_addr = dccm_base.addr << 8; | ||
91 | } | ||
92 | } | ||
93 | |||
67 | READ_BCR(ARC_REG_XY_MEM_BCR, cpu->extn_xymem); | 94 | READ_BCR(ARC_REG_XY_MEM_BCR, cpu->extn_xymem); |
68 | 95 | ||
69 | read_decode_mmu_bcr(); | 96 | read_decode_mmu_bcr(); |
@@ -211,6 +238,30 @@ char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) | |||
211 | return buf; | 238 | return buf; |
212 | } | 239 | } |
213 | 240 | ||
241 | void __init arc_chk_ccms(void) | ||
242 | { | ||
243 | #if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM) | ||
244 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; | ||
245 | |||
246 | #ifdef CONFIG_ARC_HAS_DCCM | ||
247 | /* | ||
248 | * DCCM can be arbit placed in hardware. | ||
249 | * Make sure it's placement/sz matches what Linux is built with | ||
250 | */ | ||
251 | if ((unsigned int)__arc_dccm_base != cpu->dccm.base_addr) | ||
252 | panic("Linux built with incorrect DCCM Base address\n"); | ||
253 | |||
254 | if (CONFIG_ARC_DCCM_SZ != cpu->dccm.sz) | ||
255 | panic("Linux built with incorrect DCCM Size\n"); | ||
256 | #endif | ||
257 | |||
258 | #ifdef CONFIG_ARC_HAS_ICCM | ||
259 | if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz) | ||
260 | panic("Linux built with incorrect ICCM Size\n"); | ||
261 | #endif | ||
262 | #endif | ||
263 | } | ||
264 | |||
214 | /* | 265 | /* |
215 | * Ensure that FP hardware and kernel config match | 266 | * Ensure that FP hardware and kernel config match |
216 | * -If hardware contains DPFP, kernel needs to save/restore FPU state | 267 | * -If hardware contains DPFP, kernel needs to save/restore FPU state |
@@ -255,7 +306,7 @@ void __init setup_processor(void) | |||
255 | 306 | ||
256 | arc_mmu_init(); | 307 | arc_mmu_init(); |
257 | arc_cache_init(); | 308 | arc_cache_init(); |
258 | 309 | arc_chk_ccms(); | |
259 | 310 | ||
260 | printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str))); | 311 | printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str))); |
261 | 312 | ||
diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S index 303ea01c85c8..8d3b0d447498 100644 --- a/arch/arc/kernel/vmlinux.lds.S +++ b/arch/arc/kernel/vmlinux.lds.S | |||
@@ -23,6 +23,12 @@ jiffies = jiffies_64; | |||
23 | 23 | ||
24 | SECTIONS | 24 | SECTIONS |
25 | { | 25 | { |
26 | /* | ||
27 | * ICCM starts at 0x8000_0000. So if kernel is relocated to some other | ||
28 | * address, make sure peripheral at 0x8z doesn't clash with ICCM | ||
29 | * Essentially vector is also in ICCM. | ||
30 | */ | ||
31 | |||
26 | . = CONFIG_LINUX_LINK_BASE; | 32 | . = CONFIG_LINUX_LINK_BASE; |
27 | 33 | ||
28 | _int_vec_base_lds = .; | 34 | _int_vec_base_lds = .; |
@@ -31,6 +37,13 @@ SECTIONS | |||
31 | . = ALIGN(PAGE_SIZE); | 37 | . = ALIGN(PAGE_SIZE); |
32 | } | 38 | } |
33 | 39 | ||
40 | #ifdef CONFIG_ARC_HAS_ICCM | ||
41 | .text.arcfp : { | ||
42 | *(.text.arcfp) | ||
43 | . = ALIGN(CONFIG_ARC_ICCM_SZ * 1024); | ||
44 | } | ||
45 | #endif | ||
46 | |||
34 | /* | 47 | /* |
35 | * The reason for having a seperate subsection .init.ramfs is to | 48 | * The reason for having a seperate subsection .init.ramfs is to |
36 | * prevent objump from including it in kernel dumps | 49 | * prevent objump from including it in kernel dumps |
@@ -134,4 +147,12 @@ SECTIONS | |||
134 | .debug_loc 0 : { *(.debug_loc) } | 147 | .debug_loc 0 : { *(.debug_loc) } |
135 | .debug_macinfo 0 : { *(.debug_macinfo) } | 148 | .debug_macinfo 0 : { *(.debug_macinfo) } |
136 | 149 | ||
150 | #ifdef CONFIG_ARC_HAS_DCCM | ||
151 | . = CONFIG_ARC_DCCM_BASE; | ||
152 | __arc_dccm_base = .; | ||
153 | .data.arcfp : { | ||
154 | *(.data.arcfp) | ||
155 | } | ||
156 | . = ALIGN(CONFIG_ARC_DCCM_SZ * 1024); | ||
157 | #endif | ||
137 | } | 158 | } |