From cb9d7707cd9be57830f31616233f6a872ca8416d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Jul 2010 21:50:59 +0100 Subject: ARM: 6222/1: add memory types for the TCMs The earlier TCM memory regions were mapped as MT_MEMORY_UNCACHED which doesn't really work on platforms supporting the new v6 features like the NX bit. Add unique MT_MEMORY_[I|D]TCM types instead. Cc: Nicolas Pitre Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/kernel/tcm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/arm/kernel/tcm.c') diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index e503038..0c62aa2 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c @@ -13,7 +13,6 @@ #include #include #include /* memcpy */ -#include /* PAGE_SHIFT */ #include #include #include @@ -53,7 +52,7 @@ static struct map_desc dtcm_iomap[] __initdata = { .virtual = DTCM_OFFSET, .pfn = __phys_to_pfn(DTCM_OFFSET), .length = (DTCM_END - DTCM_OFFSET + 1), - .type = MT_UNCACHED + .type = MT_MEMORY_DTCM } }; @@ -62,7 +61,7 @@ static struct map_desc itcm_iomap[] __initdata = { .virtual = ITCM_OFFSET, .pfn = __phys_to_pfn(ITCM_OFFSET), .length = (ITCM_END - ITCM_OFFSET + 1), - .type = MT_UNCACHED + .type = MT_MEMORY_ITCM } }; -- cgit v1.1 From 598509779e5b8037d371df764d7438744a24b61f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Jul 2010 21:51:41 +0100 Subject: 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 Signed-off-by: Russell King --- arch/arm/kernel/tcm.c | 68 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 22 deletions(-) (limited to 'arch/arm/kernel/tcm.c') diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index 0c62aa2..f2ead32 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) } EXPORT_SYMBOL(tcm_free); - -static void __init setup_tcm_bank(u8 type, u32 offset, u32 expected_size) +static void __init setup_tcm_bank(u8 type, u8 bank, u8 banks, + u32 offset, u32 expected_size) { const int tcm_sizes[16] = { 0, -1, -1, 4, 8, 16, 32, 64, 128, 256, 512, 1024, -1, -1, -1, -1 }; u32 tcm_region; int tcm_size; + /* + * If there are more than one TCM bank of this type, + * select the TCM bank to operate on in the TCM selection + * register. + */ + if (banks > 1) + asm("mcr p15, 0, %0, c9, c2, 0" + : /* No output operands */ + : "r" (bank)); + /* Read the special TCM region register c9, 0 */ if (!type) 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) tcm_size = tcm_sizes[(tcm_region >> 2) & 0x0f]; if (tcm_size < 0) { - pr_err("CPU: %sTCM of unknown size!\n", - type ? "I" : "D"); + pr_err("CPU: %sTCM%d of unknown size!\n", + type ? "I" : "D", bank); } else { - pr_info("CPU: found %sTCM %dk @ %08x, %senabled\n", + pr_info("CPU: found %sTCM%d %dk @ %08x, %senabled\n", type ? "I" : "D", + bank, tcm_size, (tcm_region & 0xfffff000U), (tcm_region & 1) ? "" : "not "); } - if (tcm_size != expected_size) { - pr_crit("CPU: %sTCM was detected %dk but expected %dk!\n", - type ? "I" : "D", - tcm_size, - expected_size); + if (tcm_size != (expected_size >> 10)) { + pr_crit("CPU: %sTCM%d was detected %dk but expected %dk!\n", + type ? "I" : "D", + bank, + tcm_size, + (expected_size >> 10)); /* Adjust to the expected size? what can we do... */ } @@ -140,26 +152,37 @@ static void __init setup_tcm_bank(u8 type, u32 offset, u32 expected_size) : /* No output operands */ : "r" (tcm_region)); - pr_debug("CPU: moved %sTCM %dk to %08x, enabled\n", - type ? "I" : "D", - tcm_size, - (tcm_region & 0xfffff000U)); + pr_info("CPU: moved %sTCM%d %dk to %08x, enabled\n", + type ? "I" : "D", + bank, + tcm_size, + (tcm_region & 0xfffff000U)); } +/* We expect to find what is configured for the platform */ +#define DTCM_EXPECTED (DTCM_END - DTCM_OFFSET + 1) +#define ITCM_EXPECTED (ITCM_END - ITCM_OFFSET + 1) + /* * This initializes the TCM memory */ void __init tcm_init(void) { u32 tcm_status = read_cpuid_tcmstatus(); + u8 dtcm_banks = (tcm_status >> 16) & 0x03; + u32 dtcm_banksize = DTCM_EXPECTED / dtcm_banks; + u8 itcm_banks = (tcm_status & 0x03); + u32 itcm_banksize = ITCM_EXPECTED / itcm_banks; char *start; char *end; char *ram; + int i; /* Setup DTCM if present */ - if (tcm_status & (1 << 16)) { - setup_tcm_bank(0, DTCM_OFFSET, - (DTCM_END - DTCM_OFFSET + 1) >> 10); + for (i = 0; i < dtcm_banks; i++) { + setup_tcm_bank(0, i, dtcm_banks, + DTCM_OFFSET + (i * dtcm_banksize), + dtcm_banksize); request_resource(&iomem_resource, &dtcm_res); iotable_init(dtcm_iomap, 1); /* Copy data from RAM to DTCM */ @@ -171,9 +194,10 @@ void __init tcm_init(void) } /* Setup ITCM if present */ - if (tcm_status & 1) { - setup_tcm_bank(1, ITCM_OFFSET, - (ITCM_END - ITCM_OFFSET + 1) >> 10); + for (i = 0; i < itcm_banks; i++) { + setup_tcm_bank(1, i, itcm_banks, + ITCM_OFFSET + (i * itcm_banksize), + itcm_banksize); request_resource(&iomem_resource, &itcm_res); iotable_init(itcm_iomap, 1); /* Copy code from RAM to ITCM */ @@ -207,7 +231,7 @@ static int __init setup_tcm_pool(void) pr_debug("Setting up TCM memory pool\n"); /* Add the rest of DTCM to the TCM pool */ - if (tcm_status & (1 << 16)) { + if (tcm_status & (0x03 << 16)) { if (dtcm_pool_start < DTCM_END) { ret = gen_pool_add(tcm_pool, dtcm_pool_start, DTCM_END - dtcm_pool_start + 1, -1); @@ -224,7 +248,7 @@ static int __init setup_tcm_pool(void) } /* Add the rest of ITCM to the TCM pool */ - if (tcm_status & 1) { + if (tcm_status & 0x03) { if (itcm_pool_start < ITCM_END) { ret = gen_pool_add(tcm_pool, itcm_pool_start, ITCM_END - itcm_pool_start + 1, -1); -- cgit v1.1 From 1dbd30e9890fd69e50b17edd70ca583546b0fe4e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Jul 2010 21:53:28 +0100 Subject: ARM: 6225/1: make TCM allocation static and common for all archs This changes the TCM handling so that a fixed area is reserved at 0xfffe0000-0xfffeffff for TCM. This areas is used by XScale but XScale does not have TCM so the mechanisms are mutually exclusive. This change is needed to make TCM detection more dynamic while still being able to compile code into it, and is a must for the unified ARM goals: the current TCM allocation at different places in memory for each machine would be a nightmare if you want to compile a single image for more than one machine with TCM so it has to be nailed down in one place. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/kernel/tcm.c | 91 +++++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 43 deletions(-) (limited to 'arch/arm/kernel/tcm.c') diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c index f2ead32..26685c2 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c @@ -18,32 +18,30 @@ #include #include "tcm.h" -/* Scream and warn about misuse */ -#if !defined(ITCM_OFFSET) || !defined(ITCM_END) || \ - !defined(DTCM_OFFSET) || !defined(DTCM_END) -#error "TCM support selected but offsets not defined!" -#endif - static struct gen_pool *tcm_pool; /* TCM section definitions from the linker */ extern char __itcm_start, __sitcm_text, __eitcm_text; extern char __dtcm_start, __sdtcm_data, __edtcm_data; +/* These will be increased as we run */ +u32 dtcm_end = DTCM_OFFSET; +u32 itcm_end = ITCM_OFFSET; + /* * TCM memory resources */ static struct resource dtcm_res = { .name = "DTCM RAM", .start = DTCM_OFFSET, - .end = DTCM_END, + .end = DTCM_OFFSET, .flags = IORESOURCE_MEM }; static struct resource itcm_res = { .name = "ITCM RAM", .start = ITCM_OFFSET, - .end = ITCM_END, + .end = ITCM_OFFSET, .flags = IORESOURCE_MEM }; @@ -51,7 +49,7 @@ static struct map_desc dtcm_iomap[] __initdata = { { .virtual = DTCM_OFFSET, .pfn = __phys_to_pfn(DTCM_OFFSET), - .length = (DTCM_END - DTCM_OFFSET + 1), + .length = 0, .type = MT_MEMORY_DTCM } }; @@ -60,7 +58,7 @@ static struct map_desc itcm_iomap[] __initdata = { { .virtual = ITCM_OFFSET, .pfn = __phys_to_pfn(ITCM_OFFSET), - .length = (ITCM_END - ITCM_OFFSET + 1), + .length = 0, .type = MT_MEMORY_ITCM } }; @@ -92,8 +90,8 @@ void tcm_free(void *addr, size_t len) } EXPORT_SYMBOL(tcm_free); -static void __init setup_tcm_bank(u8 type, u8 bank, u8 banks, - u32 offset, u32 expected_size) +static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks, + u32 *offset) { const int tcm_sizes[16] = { 0, -1, -1, 4, 8, 16, 32, 64, 128, 256, 512, 1024, -1, -1, -1, -1 }; @@ -120,8 +118,13 @@ static void __init setup_tcm_bank(u8 type, u8 bank, u8 banks, tcm_size = tcm_sizes[(tcm_region >> 2) & 0x0f]; if (tcm_size < 0) { - pr_err("CPU: %sTCM%d of unknown size!\n", + pr_err("CPU: %sTCM%d of unknown size\n", type ? "I" : "D", bank); + return -EINVAL; + } else if (tcm_size > 32) { + pr_err("CPU: %sTCM%d larger than 32k found\n", + type ? "I" : "D", bank); + return -EINVAL; } else { pr_info("CPU: found %sTCM%d %dk @ %08x, %senabled\n", type ? "I" : "D", @@ -131,17 +134,8 @@ static void __init setup_tcm_bank(u8 type, u8 bank, u8 banks, (tcm_region & 1) ? "" : "not "); } - if (tcm_size != (expected_size >> 10)) { - pr_crit("CPU: %sTCM%d was detected %dk but expected %dk!\n", - type ? "I" : "D", - bank, - tcm_size, - (expected_size >> 10)); - /* Adjust to the expected size? what can we do... */ - } - /* Force move the TCM bank to where we want it, enable */ - tcm_region = offset | (tcm_region & 0x00000ffeU) | 1; + tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1; if (!type) asm("mcr p15, 0, %0, c9, c1, 0" @@ -152,17 +146,17 @@ static void __init setup_tcm_bank(u8 type, u8 bank, u8 banks, : /* No output operands */ : "r" (tcm_region)); + /* Increase offset */ + *offset += (tcm_size << 10); + pr_info("CPU: moved %sTCM%d %dk to %08x, enabled\n", type ? "I" : "D", bank, tcm_size, (tcm_region & 0xfffff000U)); + return 0; } -/* We expect to find what is configured for the platform */ -#define DTCM_EXPECTED (DTCM_END - DTCM_OFFSET + 1) -#define ITCM_EXPECTED (ITCM_END - ITCM_OFFSET + 1) - /* * This initializes the TCM memory */ @@ -170,40 +164,51 @@ void __init tcm_init(void) { u32 tcm_status = read_cpuid_tcmstatus(); u8 dtcm_banks = (tcm_status >> 16) & 0x03; - u32 dtcm_banksize = DTCM_EXPECTED / dtcm_banks; u8 itcm_banks = (tcm_status & 0x03); - u32 itcm_banksize = ITCM_EXPECTED / itcm_banks; char *start; char *end; char *ram; + int ret; int i; /* Setup DTCM if present */ - for (i = 0; i < dtcm_banks; i++) { - setup_tcm_bank(0, i, dtcm_banks, - DTCM_OFFSET + (i * dtcm_banksize), - dtcm_banksize); + if (dtcm_banks > 0) { + for (i = 0; i < dtcm_banks; i++) { + ret = setup_tcm_bank(0, i, dtcm_banks, &dtcm_end); + if (ret) + return; + } + dtcm_res.end = dtcm_end - 1; request_resource(&iomem_resource, &dtcm_res); + dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET; iotable_init(dtcm_iomap, 1); /* Copy data from RAM to DTCM */ start = &__sdtcm_data; end = &__edtcm_data; ram = &__dtcm_start; + /* This means you compiled more code than fits into DTCM */ + BUG_ON((end - start) > (dtcm_end - DTCM_OFFSET)); memcpy(start, ram, (end-start)); pr_debug("CPU DTCM: copied data from %p - %p\n", start, end); } /* Setup ITCM if present */ - for (i = 0; i < itcm_banks; i++) { - setup_tcm_bank(1, i, itcm_banks, - ITCM_OFFSET + (i * itcm_banksize), - itcm_banksize); + if (itcm_banks > 0) { + for (i = 0; i < itcm_banks; i++) { + ret = setup_tcm_bank(1, i, itcm_banks, &itcm_end); + if (ret) + return; + } + itcm_res.end = itcm_end - 1; request_resource(&iomem_resource, &itcm_res); + itcm_iomap[0].length = itcm_end - ITCM_OFFSET; iotable_init(itcm_iomap, 1); /* Copy code from RAM to ITCM */ start = &__sitcm_text; end = &__eitcm_text; ram = &__itcm_start; + /* This means you compiled more code than fits into ITCM */ + BUG_ON((end - start) > (itcm_end - ITCM_OFFSET)); memcpy(start, ram, (end-start)); pr_debug("CPU ITCM: copied code from %p - %p\n", start, end); } @@ -232,9 +237,9 @@ static int __init setup_tcm_pool(void) /* Add the rest of DTCM to the TCM pool */ if (tcm_status & (0x03 << 16)) { - if (dtcm_pool_start < DTCM_END) { + if (dtcm_pool_start < dtcm_end) { ret = gen_pool_add(tcm_pool, dtcm_pool_start, - DTCM_END - dtcm_pool_start + 1, -1); + dtcm_end - dtcm_pool_start, -1); if (ret) { pr_err("CPU DTCM: could not add DTCM " \ "remainder to pool!\n"); @@ -242,16 +247,16 @@ static int __init setup_tcm_pool(void) } pr_debug("CPU DTCM: Added %08x bytes @ %08x to " \ "the TCM memory pool\n", - DTCM_END - dtcm_pool_start + 1, + dtcm_end - dtcm_pool_start, dtcm_pool_start); } } /* Add the rest of ITCM to the TCM pool */ if (tcm_status & 0x03) { - if (itcm_pool_start < ITCM_END) { + if (itcm_pool_start < itcm_end) { ret = gen_pool_add(tcm_pool, itcm_pool_start, - ITCM_END - itcm_pool_start + 1, -1); + itcm_end - itcm_pool_start, -1); if (ret) { pr_err("CPU ITCM: could not add ITCM " \ "remainder to pool!\n"); @@ -259,7 +264,7 @@ static int __init setup_tcm_pool(void) } pr_debug("CPU ITCM: Added %08x bytes @ %08x to " \ "the TCM memory pool\n", - ITCM_END - itcm_pool_start + 1, + itcm_end - itcm_pool_start, itcm_pool_start); } } -- cgit v1.1