aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/kernel/tcm.c68
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}
93EXPORT_SYMBOL(tcm_free); 93EXPORT_SYMBOL(tcm_free);
94 94
95 95static void __init setup_tcm_bank(u8 type, u8 bank, u8 banks,
96static 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 */
152void __init tcm_init(void) 169void __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);