diff options
Diffstat (limited to 'arch/arm/kernel/tcm.c')
-rw-r--r-- | arch/arm/kernel/tcm.c | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index f5cf660eefcc..30e302d33e0a 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include "tcm.h" | 19 | #include "tcm.h" |
20 | 20 | ||
21 | static struct gen_pool *tcm_pool; | 21 | static struct gen_pool *tcm_pool; |
22 | static bool dtcm_present; | ||
23 | static bool itcm_present; | ||
22 | 24 | ||
23 | /* TCM section definitions from the linker */ | 25 | /* TCM section definitions from the linker */ |
24 | extern char __itcm_start, __sitcm_text, __eitcm_text; | 26 | extern char __itcm_start, __sitcm_text, __eitcm_text; |
@@ -90,6 +92,18 @@ void tcm_free(void *addr, size_t len) | |||
90 | } | 92 | } |
91 | EXPORT_SYMBOL(tcm_free); | 93 | EXPORT_SYMBOL(tcm_free); |
92 | 94 | ||
95 | bool tcm_dtcm_present(void) | ||
96 | { | ||
97 | return dtcm_present; | ||
98 | } | ||
99 | EXPORT_SYMBOL(tcm_dtcm_present); | ||
100 | |||
101 | bool tcm_itcm_present(void) | ||
102 | { | ||
103 | return itcm_present; | ||
104 | } | ||
105 | EXPORT_SYMBOL(tcm_itcm_present); | ||
106 | |||
93 | static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks, | 107 | static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks, |
94 | u32 *offset) | 108 | u32 *offset) |
95 | { | 109 | { |
@@ -134,6 +148,10 @@ static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks, | |||
134 | (tcm_region & 1) ? "" : "not "); | 148 | (tcm_region & 1) ? "" : "not "); |
135 | } | 149 | } |
136 | 150 | ||
151 | /* Not much fun you can do with a size 0 bank */ | ||
152 | if (tcm_size == 0) | ||
153 | return 0; | ||
154 | |||
137 | /* Force move the TCM bank to where we want it, enable */ | 155 | /* Force move the TCM bank to where we want it, enable */ |
138 | tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1; | 156 | tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1; |
139 | 157 | ||
@@ -165,12 +183,20 @@ void __init tcm_init(void) | |||
165 | u32 tcm_status = read_cpuid_tcmstatus(); | 183 | u32 tcm_status = read_cpuid_tcmstatus(); |
166 | u8 dtcm_banks = (tcm_status >> 16) & 0x03; | 184 | u8 dtcm_banks = (tcm_status >> 16) & 0x03; |
167 | u8 itcm_banks = (tcm_status & 0x03); | 185 | u8 itcm_banks = (tcm_status & 0x03); |
186 | size_t dtcm_code_sz = &__edtcm_data - &__sdtcm_data; | ||
187 | size_t itcm_code_sz = &__eitcm_text - &__sitcm_text; | ||
168 | char *start; | 188 | char *start; |
169 | char *end; | 189 | char *end; |
170 | char *ram; | 190 | char *ram; |
171 | int ret; | 191 | int ret; |
172 | int i; | 192 | int i; |
173 | 193 | ||
194 | /* Values greater than 2 for D/ITCM banks are "reserved" */ | ||
195 | if (dtcm_banks > 2) | ||
196 | dtcm_banks = 0; | ||
197 | if (itcm_banks > 2) | ||
198 | itcm_banks = 0; | ||
199 | |||
174 | /* Setup DTCM if present */ | 200 | /* Setup DTCM if present */ |
175 | if (dtcm_banks > 0) { | 201 | if (dtcm_banks > 0) { |
176 | for (i = 0; i < dtcm_banks; i++) { | 202 | for (i = 0; i < dtcm_banks; i++) { |
@@ -178,6 +204,13 @@ void __init tcm_init(void) | |||
178 | if (ret) | 204 | if (ret) |
179 | return; | 205 | return; |
180 | } | 206 | } |
207 | /* This means you compiled more code than fits into DTCM */ | ||
208 | if (dtcm_code_sz > (dtcm_end - DTCM_OFFSET)) { | ||
209 | pr_info("CPU DTCM: %u bytes of code compiled to " | ||
210 | "DTCM but only %lu bytes of DTCM present\n", | ||
211 | dtcm_code_sz, (dtcm_end - DTCM_OFFSET)); | ||
212 | goto no_dtcm; | ||
213 | } | ||
181 | dtcm_res.end = dtcm_end - 1; | 214 | dtcm_res.end = dtcm_end - 1; |
182 | request_resource(&iomem_resource, &dtcm_res); | 215 | request_resource(&iomem_resource, &dtcm_res); |
183 | dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET; | 216 | dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET; |
@@ -186,12 +219,16 @@ void __init tcm_init(void) | |||
186 | start = &__sdtcm_data; | 219 | start = &__sdtcm_data; |
187 | end = &__edtcm_data; | 220 | end = &__edtcm_data; |
188 | ram = &__dtcm_start; | 221 | ram = &__dtcm_start; |
189 | /* This means you compiled more code than fits into DTCM */ | 222 | memcpy(start, ram, dtcm_code_sz); |
190 | BUG_ON((end - start) > (dtcm_end - DTCM_OFFSET)); | 223 | pr_debug("CPU DTCM: copied data from %p - %p\n", |
191 | memcpy(start, ram, (end-start)); | 224 | start, end); |
192 | pr_debug("CPU DTCM: copied data from %p - %p\n", start, end); | 225 | dtcm_present = true; |
226 | } else if (dtcm_code_sz) { | ||
227 | pr_info("CPU DTCM: %u bytes of code compiled to DTCM but no " | ||
228 | "DTCM banks present in CPU\n", dtcm_code_sz); | ||
193 | } | 229 | } |
194 | 230 | ||
231 | no_dtcm: | ||
195 | /* Setup ITCM if present */ | 232 | /* Setup ITCM if present */ |
196 | if (itcm_banks > 0) { | 233 | if (itcm_banks > 0) { |
197 | for (i = 0; i < itcm_banks; i++) { | 234 | for (i = 0; i < itcm_banks; i++) { |
@@ -199,6 +236,13 @@ void __init tcm_init(void) | |||
199 | if (ret) | 236 | if (ret) |
200 | return; | 237 | return; |
201 | } | 238 | } |
239 | /* This means you compiled more code than fits into ITCM */ | ||
240 | if (itcm_code_sz > (itcm_end - ITCM_OFFSET)) { | ||
241 | pr_info("CPU ITCM: %u bytes of code compiled to " | ||
242 | "ITCM but only %lu bytes of ITCM present\n", | ||
243 | itcm_code_sz, (itcm_end - ITCM_OFFSET)); | ||
244 | return; | ||
245 | } | ||
202 | itcm_res.end = itcm_end - 1; | 246 | itcm_res.end = itcm_end - 1; |
203 | request_resource(&iomem_resource, &itcm_res); | 247 | request_resource(&iomem_resource, &itcm_res); |
204 | itcm_iomap[0].length = itcm_end - ITCM_OFFSET; | 248 | itcm_iomap[0].length = itcm_end - ITCM_OFFSET; |
@@ -207,10 +251,13 @@ void __init tcm_init(void) | |||
207 | start = &__sitcm_text; | 251 | start = &__sitcm_text; |
208 | end = &__eitcm_text; | 252 | end = &__eitcm_text; |
209 | ram = &__itcm_start; | 253 | ram = &__itcm_start; |
210 | /* This means you compiled more code than fits into ITCM */ | 254 | memcpy(start, ram, itcm_code_sz); |
211 | BUG_ON((end - start) > (itcm_end - ITCM_OFFSET)); | 255 | pr_debug("CPU ITCM: copied code from %p - %p\n", |
212 | memcpy(start, ram, (end-start)); | 256 | start, end); |
213 | pr_debug("CPU ITCM: copied code from %p - %p\n", start, end); | 257 | itcm_present = true; |
258 | } else if (itcm_code_sz) { | ||
259 | pr_info("CPU ITCM: %u bytes of code compiled to ITCM but no " | ||
260 | "ITCM banks present in CPU\n", itcm_code_sz); | ||
214 | } | 261 | } |
215 | } | 262 | } |
216 | 263 | ||
@@ -221,7 +268,6 @@ void __init tcm_init(void) | |||
221 | */ | 268 | */ |
222 | static int __init setup_tcm_pool(void) | 269 | static int __init setup_tcm_pool(void) |
223 | { | 270 | { |
224 | u32 tcm_status = read_cpuid_tcmstatus(); | ||
225 | u32 dtcm_pool_start = (u32) &__edtcm_data; | 271 | u32 dtcm_pool_start = (u32) &__edtcm_data; |
226 | u32 itcm_pool_start = (u32) &__eitcm_text; | 272 | u32 itcm_pool_start = (u32) &__eitcm_text; |
227 | int ret; | 273 | int ret; |
@@ -236,7 +282,7 @@ static int __init setup_tcm_pool(void) | |||
236 | pr_debug("Setting up TCM memory pool\n"); | 282 | pr_debug("Setting up TCM memory pool\n"); |
237 | 283 | ||
238 | /* Add the rest of DTCM to the TCM pool */ | 284 | /* Add the rest of DTCM to the TCM pool */ |
239 | if (tcm_status & (0x03 << 16)) { | 285 | if (dtcm_present) { |
240 | if (dtcm_pool_start < dtcm_end) { | 286 | if (dtcm_pool_start < dtcm_end) { |
241 | ret = gen_pool_add(tcm_pool, dtcm_pool_start, | 287 | ret = gen_pool_add(tcm_pool, dtcm_pool_start, |
242 | dtcm_end - dtcm_pool_start, -1); | 288 | dtcm_end - dtcm_pool_start, -1); |
@@ -253,7 +299,7 @@ static int __init setup_tcm_pool(void) | |||
253 | } | 299 | } |
254 | 300 | ||
255 | /* Add the rest of ITCM to the TCM pool */ | 301 | /* Add the rest of ITCM to the TCM pool */ |
256 | if (tcm_status & 0x03) { | 302 | if (itcm_present) { |
257 | if (itcm_pool_start < itcm_end) { | 303 | if (itcm_pool_start < itcm_end) { |
258 | ret = gen_pool_add(tcm_pool, itcm_pool_start, | 304 | ret = gen_pool_add(tcm_pool, itcm_pool_start, |
259 | itcm_end - itcm_pool_start, -1); | 305 | itcm_end - itcm_pool_start, -1); |