aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/tcm.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2011-07-01 03:23:06 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-07-06 15:49:45 -0400
commit9715efb8dc9ffa629bf5a1215b11bf2f2f29908b (patch)
tree7c05fe2aaf27d60174a33da037fea05e1303b9e6 /arch/arm/kernel/tcm.c
parente4b6381009d740bd3a97e6b841d8efe7fc70c1b7 (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.c47
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
216no_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