aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@stericsson.com>2010-07-12 16:51:41 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-07-18 15:29:48 -0400
commit598509779e5b8037d371df764d7438744a24b61f (patch)
treefc38aed80a8d64d9afe36b806c6c73aa184f6a2e
parentcb9d7707cd9be57830f31616233f6a872ca8416d (diff)
ARM: 6223/1: support multiple TCM banks
CPUs v6 and up support multiple TCM banks, for example an ITCM of 8k is supplied in two 4k banks. This makes the TCM work on the 1176JZF-S devchip. Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-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);