diff options
-rw-r--r-- | arch/arm/kernel/tcm.c | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index 0c62aa2c86e..f2ead32c1aa 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c | |||
@@ -92,14 +92,24 @@ void tcm_free(void *addr, size_t len) | |||
92 | } | 92 | } |
93 | EXPORT_SYMBOL(tcm_free); | 93 | EXPORT_SYMBOL(tcm_free); |
94 | 94 | ||
95 | 95 | static void __init setup_tcm_bank(u8 type, u8 bank, u8 banks, | |
96 | static void __init setup_tcm_bank(u8 type, u32 offset, u32 expected_size) | 96 | u32 offset, u32 expected_size) |
97 | { | 97 | { |
98 | const int tcm_sizes[16] = { 0, -1, -1, 4, 8, 16, 32, 64, 128, | 98 | const int tcm_sizes[16] = { 0, -1, -1, 4, 8, 16, 32, 64, 128, |
99 | 256, 512, 1024, -1, -1, -1, -1 }; | 99 | 256, 512, 1024, -1, -1, -1, -1 }; |
100 | u32 tcm_region; | 100 | u32 tcm_region; |
101 | int tcm_size; | 101 | int tcm_size; |
102 | 102 | ||
103 | /* | ||
104 | * If there are more than one TCM bank of this type, | ||
105 | * select the TCM bank to operate on in the TCM selection | ||
106 | * register. | ||
107 | */ | ||
108 | if (banks > 1) | ||
109 | asm("mcr p15, 0, %0, c9, c2, 0" | ||
110 | : /* No output operands */ | ||
111 | : "r" (bank)); | ||
112 | |||
103 | /* Read the special TCM region register c9, 0 */ | 113 | /* Read the special TCM region register c9, 0 */ |
104 | if (!type) | 114 | if (!type) |
105 | asm("mrc p15, 0, %0, c9, c1, 0" | 115 | asm("mrc p15, 0, %0, c9, c1, 0" |
@@ -110,21 +120,23 @@ static void __init setup_tcm_bank(u8 type, u32 offset, u32 expected_size) | |||
110 | 120 | ||
111 | tcm_size = tcm_sizes[(tcm_region >> 2) & 0x0f]; | 121 | tcm_size = tcm_sizes[(tcm_region >> 2) & 0x0f]; |
112 | if (tcm_size < 0) { | 122 | if (tcm_size < 0) { |
113 | pr_err("CPU: %sTCM of unknown size!\n", | 123 | pr_err("CPU: %sTCM%d of unknown size!\n", |
114 | type ? "I" : "D"); | 124 | type ? "I" : "D", bank); |
115 | } else { | 125 | } else { |
116 | pr_info("CPU: found %sTCM %dk @ %08x, %senabled\n", | 126 | pr_info("CPU: found %sTCM%d %dk @ %08x, %senabled\n", |
117 | type ? "I" : "D", | 127 | type ? "I" : "D", |
128 | bank, | ||
118 | tcm_size, | 129 | tcm_size, |
119 | (tcm_region & 0xfffff000U), | 130 | (tcm_region & 0xfffff000U), |
120 | (tcm_region & 1) ? "" : "not "); | 131 | (tcm_region & 1) ? "" : "not "); |
121 | } | 132 | } |
122 | 133 | ||
123 | if (tcm_size != expected_size) { | 134 | if (tcm_size != (expected_size >> 10)) { |
124 | pr_crit("CPU: %sTCM was detected %dk but expected %dk!\n", | 135 | pr_crit("CPU: %sTCM%d was detected %dk but expected %dk!\n", |
125 | type ? "I" : "D", | 136 | type ? "I" : "D", |
126 | tcm_size, | 137 | bank, |
127 | expected_size); | 138 | tcm_size, |
139 | (expected_size >> 10)); | ||
128 | /* Adjust to the expected size? what can we do... */ | 140 | /* Adjust to the expected size? what can we do... */ |
129 | } | 141 | } |
130 | 142 | ||
@@ -140,26 +152,37 @@ static void __init setup_tcm_bank(u8 type, u32 offset, u32 expected_size) | |||
140 | : /* No output operands */ | 152 | : /* No output operands */ |
141 | : "r" (tcm_region)); | 153 | : "r" (tcm_region)); |
142 | 154 | ||
143 | pr_debug("CPU: moved %sTCM %dk to %08x, enabled\n", | 155 | pr_info("CPU: moved %sTCM%d %dk to %08x, enabled\n", |
144 | type ? "I" : "D", | 156 | type ? "I" : "D", |
145 | tcm_size, | 157 | bank, |
146 | (tcm_region & 0xfffff000U)); | 158 | tcm_size, |
159 | (tcm_region & 0xfffff000U)); | ||
147 | } | 160 | } |
148 | 161 | ||
162 | /* We expect to find what is configured for the platform */ | ||
163 | #define DTCM_EXPECTED (DTCM_END - DTCM_OFFSET + 1) | ||
164 | #define ITCM_EXPECTED (ITCM_END - ITCM_OFFSET + 1) | ||
165 | |||
149 | /* | 166 | /* |
150 | * This initializes the TCM memory | 167 | * This initializes the TCM memory |
151 | */ | 168 | */ |
152 | void __init tcm_init(void) | 169 | void __init tcm_init(void) |
153 | { | 170 | { |
154 | u32 tcm_status = read_cpuid_tcmstatus(); | 171 | u32 tcm_status = read_cpuid_tcmstatus(); |
172 | u8 dtcm_banks = (tcm_status >> 16) & 0x03; | ||
173 | u32 dtcm_banksize = DTCM_EXPECTED / dtcm_banks; | ||
174 | u8 itcm_banks = (tcm_status & 0x03); | ||
175 | u32 itcm_banksize = ITCM_EXPECTED / itcm_banks; | ||
155 | char *start; | 176 | char *start; |
156 | char *end; | 177 | char *end; |
157 | char *ram; | 178 | char *ram; |
179 | int i; | ||
158 | 180 | ||
159 | /* Setup DTCM if present */ | 181 | /* Setup DTCM if present */ |
160 | if (tcm_status & (1 << 16)) { | 182 | for (i = 0; i < dtcm_banks; i++) { |
161 | setup_tcm_bank(0, DTCM_OFFSET, | 183 | setup_tcm_bank(0, i, dtcm_banks, |
162 | (DTCM_END - DTCM_OFFSET + 1) >> 10); | 184 | DTCM_OFFSET + (i * dtcm_banksize), |
185 | dtcm_banksize); | ||
163 | request_resource(&iomem_resource, &dtcm_res); | 186 | request_resource(&iomem_resource, &dtcm_res); |
164 | iotable_init(dtcm_iomap, 1); | 187 | iotable_init(dtcm_iomap, 1); |
165 | /* Copy data from RAM to DTCM */ | 188 | /* Copy data from RAM to DTCM */ |
@@ -171,9 +194,10 @@ void __init tcm_init(void) | |||
171 | } | 194 | } |
172 | 195 | ||
173 | /* Setup ITCM if present */ | 196 | /* Setup ITCM if present */ |
174 | if (tcm_status & 1) { | 197 | for (i = 0; i < itcm_banks; i++) { |
175 | setup_tcm_bank(1, ITCM_OFFSET, | 198 | setup_tcm_bank(1, i, itcm_banks, |
176 | (ITCM_END - ITCM_OFFSET + 1) >> 10); | 199 | ITCM_OFFSET + (i * itcm_banksize), |
200 | itcm_banksize); | ||
177 | request_resource(&iomem_resource, &itcm_res); | 201 | request_resource(&iomem_resource, &itcm_res); |
178 | iotable_init(itcm_iomap, 1); | 202 | iotable_init(itcm_iomap, 1); |
179 | /* Copy code from RAM to ITCM */ | 203 | /* Copy code from RAM to ITCM */ |
@@ -207,7 +231,7 @@ static int __init setup_tcm_pool(void) | |||
207 | pr_debug("Setting up TCM memory pool\n"); | 231 | pr_debug("Setting up TCM memory pool\n"); |
208 | 232 | ||
209 | /* Add the rest of DTCM to the TCM pool */ | 233 | /* Add the rest of DTCM to the TCM pool */ |
210 | if (tcm_status & (1 << 16)) { | 234 | if (tcm_status & (0x03 << 16)) { |
211 | if (dtcm_pool_start < DTCM_END) { | 235 | if (dtcm_pool_start < DTCM_END) { |
212 | ret = gen_pool_add(tcm_pool, dtcm_pool_start, | 236 | ret = gen_pool_add(tcm_pool, dtcm_pool_start, |
213 | DTCM_END - dtcm_pool_start + 1, -1); | 237 | DTCM_END - dtcm_pool_start + 1, -1); |
@@ -224,7 +248,7 @@ static int __init setup_tcm_pool(void) | |||
224 | } | 248 | } |
225 | 249 | ||
226 | /* Add the rest of ITCM to the TCM pool */ | 250 | /* Add the rest of ITCM to the TCM pool */ |
227 | if (tcm_status & 1) { | 251 | if (tcm_status & 0x03) { |
228 | if (itcm_pool_start < ITCM_END) { | 252 | if (itcm_pool_start < ITCM_END) { |
229 | ret = gen_pool_add(tcm_pool, itcm_pool_start, | 253 | ret = gen_pool_add(tcm_pool, itcm_pool_start, |
230 | ITCM_END - itcm_pool_start + 1, -1); | 254 | ITCM_END - itcm_pool_start + 1, -1); |