diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2011-07-01 03:23:06 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-07-06 15:49:45 -0400 |
commit | 9715efb8dc9ffa629bf5a1215b11bf2f2f29908b (patch) | |
tree | 7c05fe2aaf27d60174a33da037fea05e1303b9e6 /arch/arm/kernel/tcm.c | |
parent | e4b6381009d740bd3a97e6b841d8efe7fc70c1b7 (diff) |
ARM: 6984/1: enhance TCM robustness
The PB11MPCore reports "3" DTCM banks, but anything above 2 is an
"undefined" value, so push this to become 0. Further add some checks
if code is compiled to TCM even if there is no D/ITCM present in the
system, and if we can really fit the compiled code. We don't do the
BUG() since it's not helpful, it's better to deal with non-present
TCM dynamically. If there is nothing compiled to the TCM and no TCM
is detected, it will now just shut up even if TCM support is enabled.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel/tcm.c')
-rw-r--r-- | arch/arm/kernel/tcm.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index f5cf660eefcc..d402d4829524 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c | |||
@@ -134,6 +134,10 @@ static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks, | |||
134 | (tcm_region & 1) ? "" : "not "); | 134 | (tcm_region & 1) ? "" : "not "); |
135 | } | 135 | } |
136 | 136 | ||
137 | /* Not much fun you can do with a size 0 bank */ | ||
138 | if (tcm_size == 0) | ||
139 | return 0; | ||
140 | |||
137 | /* Force move the TCM bank to where we want it, enable */ | 141 | /* Force move the TCM bank to where we want it, enable */ |
138 | tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1; | 142 | tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1; |
139 | 143 | ||
@@ -165,12 +169,20 @@ void __init tcm_init(void) | |||
165 | u32 tcm_status = read_cpuid_tcmstatus(); | 169 | u32 tcm_status = read_cpuid_tcmstatus(); |
166 | u8 dtcm_banks = (tcm_status >> 16) & 0x03; | 170 | u8 dtcm_banks = (tcm_status >> 16) & 0x03; |
167 | u8 itcm_banks = (tcm_status & 0x03); | 171 | u8 itcm_banks = (tcm_status & 0x03); |
172 | size_t dtcm_code_sz = &__edtcm_data - &__sdtcm_data; | ||
173 | size_t itcm_code_sz = &__eitcm_text - &__sitcm_text; | ||
168 | char *start; | 174 | char *start; |
169 | char *end; | 175 | char *end; |
170 | char *ram; | 176 | char *ram; |
171 | int ret; | 177 | int ret; |
172 | int i; | 178 | int i; |
173 | 179 | ||
180 | /* Values greater than 2 for D/ITCM banks are "reserved" */ | ||
181 | if (dtcm_banks > 2) | ||
182 | dtcm_banks = 0; | ||
183 | if (itcm_banks > 2) | ||
184 | itcm_banks = 0; | ||
185 | |||
174 | /* Setup DTCM if present */ | 186 | /* Setup DTCM if present */ |
175 | if (dtcm_banks > 0) { | 187 | if (dtcm_banks > 0) { |
176 | for (i = 0; i < dtcm_banks; i++) { | 188 | for (i = 0; i < dtcm_banks; i++) { |
@@ -178,6 +190,13 @@ void __init tcm_init(void) | |||
178 | if (ret) | 190 | if (ret) |
179 | return; | 191 | return; |
180 | } | 192 | } |
193 | /* This means you compiled more code than fits into DTCM */ | ||
194 | if (dtcm_code_sz > (dtcm_end - DTCM_OFFSET)) { | ||
195 | pr_info("CPU DTCM: %u bytes of code compiled to " | ||
196 | "DTCM but only %lu bytes of DTCM present\n", | ||
197 | dtcm_code_sz, (dtcm_end - DTCM_OFFSET)); | ||
198 | goto no_dtcm; | ||
199 | } | ||
181 | dtcm_res.end = dtcm_end - 1; | 200 | dtcm_res.end = dtcm_end - 1; |
182 | request_resource(&iomem_resource, &dtcm_res); | 201 | request_resource(&iomem_resource, &dtcm_res); |
183 | dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET; | 202 | dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET; |
@@ -186,12 +205,15 @@ void __init tcm_init(void) | |||
186 | start = &__sdtcm_data; | 205 | start = &__sdtcm_data; |
187 | end = &__edtcm_data; | 206 | end = &__edtcm_data; |
188 | ram = &__dtcm_start; | 207 | ram = &__dtcm_start; |
189 | /* This means you compiled more code than fits into DTCM */ | 208 | memcpy(start, ram, dtcm_code_sz); |
190 | BUG_ON((end - start) > (dtcm_end - DTCM_OFFSET)); | 209 | pr_debug("CPU DTCM: copied data from %p - %p\n", |
191 | memcpy(start, ram, (end-start)); | 210 | start, end); |
192 | pr_debug("CPU DTCM: copied data from %p - %p\n", start, end); | 211 | } else if (dtcm_code_sz) { |
212 | pr_info("CPU DTCM: %u bytes of code compiled to DTCM but no " | ||
213 | "DTCM banks present in CPU\n", dtcm_code_sz); | ||
193 | } | 214 | } |
194 | 215 | ||
216 | no_dtcm: | ||
195 | /* Setup ITCM if present */ | 217 | /* Setup ITCM if present */ |
196 | if (itcm_banks > 0) { | 218 | if (itcm_banks > 0) { |
197 | for (i = 0; i < itcm_banks; i++) { | 219 | for (i = 0; i < itcm_banks; i++) { |
@@ -199,6 +221,13 @@ void __init tcm_init(void) | |||
199 | if (ret) | 221 | if (ret) |
200 | return; | 222 | return; |
201 | } | 223 | } |
224 | /* This means you compiled more code than fits into ITCM */ | ||
225 | if (itcm_code_sz > (itcm_end - ITCM_OFFSET)) { | ||
226 | pr_info("CPU ITCM: %u bytes of code compiled to " | ||
227 | "ITCM but only %lu bytes of ITCM present\n", | ||
228 | itcm_code_sz, (itcm_end - ITCM_OFFSET)); | ||
229 | return; | ||
230 | } | ||
202 | itcm_res.end = itcm_end - 1; | 231 | itcm_res.end = itcm_end - 1; |
203 | request_resource(&iomem_resource, &itcm_res); | 232 | request_resource(&iomem_resource, &itcm_res); |
204 | itcm_iomap[0].length = itcm_end - ITCM_OFFSET; | 233 | itcm_iomap[0].length = itcm_end - ITCM_OFFSET; |
@@ -207,10 +236,12 @@ void __init tcm_init(void) | |||
207 | start = &__sitcm_text; | 236 | start = &__sitcm_text; |
208 | end = &__eitcm_text; | 237 | end = &__eitcm_text; |
209 | ram = &__itcm_start; | 238 | ram = &__itcm_start; |
210 | /* This means you compiled more code than fits into ITCM */ | 239 | memcpy(start, ram, itcm_code_sz); |
211 | BUG_ON((end - start) > (itcm_end - ITCM_OFFSET)); | 240 | pr_debug("CPU ITCM: copied code from %p - %p\n", |
212 | memcpy(start, ram, (end-start)); | 241 | start, end); |
213 | pr_debug("CPU ITCM: copied code from %p - %p\n", start, end); | 242 | } else if (itcm_code_sz) { |
243 | pr_info("CPU ITCM: %u bytes of code compiled to ITCM but no " | ||
244 | "ITCM banks present in CPU\n", itcm_code_sz); | ||
214 | } | 245 | } |
215 | } | 246 | } |
216 | 247 | ||