aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@stericsson.com>2010-07-12 16:53:28 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-07-27 05:42:38 -0400
commit1dbd30e9890fd69e50b17edd70ca583546b0fe4e (patch)
tree5b5ab74c1792a81340478f7bbccd053e60a23a5e
parent07d2a5c721c6aa2bd69812a74c8b3b116abf3e56 (diff)
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 <linus.walleij@stericsson.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--Documentation/arm/memory.txt8
-rw-r--r--Documentation/arm/tcm.txt30
-rw-r--r--arch/arm/include/asm/memory.h9
-rw-r--r--arch/arm/kernel/tcm.c91
-rw-r--r--arch/arm/mach-u300/include/mach/memory.h8
-rw-r--r--arch/arm/mm/init.c17
6 files changed, 90 insertions, 73 deletions
diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt
index eb0fae18ffb..771d48d3b33 100644
--- a/Documentation/arm/memory.txt
+++ b/Documentation/arm/memory.txt
@@ -33,7 +33,13 @@ ffff0000 ffff0fff CPU vector page.
33 33
34fffe0000 fffeffff XScale cache flush area. This is used 34fffe0000 fffeffff XScale cache flush area. This is used
35 in proc-xscale.S to flush the whole data 35 in proc-xscale.S to flush the whole data
36 cache. Free for other usage on non-XScale. 36 cache. (XScale does not have TCM.)
37
38fffe8000 fffeffff DTCM mapping area for platforms with
39 DTCM mounted inside the CPU.
40
41fffe0000 fffe7fff ITCM mapping area for platforms with
42 ITCM mounted inside the CPU.
37 43
38fff00000 fffdffff Fixmap mapping region. Addresses provided 44fff00000 fffdffff Fixmap mapping region. Addresses provided
39 by fix_to_virt() will be located here. 45 by fix_to_virt() will be located here.
diff --git a/Documentation/arm/tcm.txt b/Documentation/arm/tcm.txt
index 77fd9376e6d..7c15871c188 100644
--- a/Documentation/arm/tcm.txt
+++ b/Documentation/arm/tcm.txt
@@ -19,8 +19,8 @@ defines a CPUID_TCM register that you can read out from the
19system control coprocessor. Documentation from ARM can be found 19system control coprocessor. Documentation from ARM can be found
20at http://infocenter.arm.com, search for "TCM Status Register" 20at http://infocenter.arm.com, search for "TCM Status Register"
21to see documents for all CPUs. Reading this register you can 21to see documents for all CPUs. Reading this register you can
22determine if ITCM (bit 0) and/or DTCM (bit 16) is present in the 22determine if ITCM (bits 1-0) and/or DTCM (bit 17-16) is present
23machine. 23in the machine.
24 24
25There is further a TCM region register (search for "TCM Region 25There is further a TCM region register (search for "TCM Region
26Registers" at the ARM site) that can report and modify the location 26Registers" at the ARM site) that can report and modify the location
@@ -35,7 +35,15 @@ The TCM memory can then be remapped to another address again using
35the MMU, but notice that the TCM if often used in situations where 35the MMU, but notice that the TCM if often used in situations where
36the MMU is turned off. To avoid confusion the current Linux 36the MMU is turned off. To avoid confusion the current Linux
37implementation will map the TCM 1 to 1 from physical to virtual 37implementation will map the TCM 1 to 1 from physical to virtual
38memory in the location specified by the machine. 38memory in the location specified by the kernel. Currently Linux
39will map ITCM to 0xfffe0000 and on, and DTCM to 0xfffe8000 and
40on, supporting a maximum of 32KiB of ITCM and 32KiB of DTCM.
41
42Newer versions of the region registers also support dividing these
43TCMs in two separate banks, so for example an 8KiB ITCM is divided
44into two 4KiB banks with its own control registers. The idea is to
45be able to lock and hide one of the banks for use by the secure
46world (TrustZone).
39 47
40TCM is used for a few things: 48TCM is used for a few things:
41 49
@@ -65,18 +73,18 @@ in <asm/tcm.h>. Using this interface it is possible to:
65 memory. Such a heap is great for things like saving 73 memory. Such a heap is great for things like saving
66 device state when shutting off device power domains. 74 device state when shutting off device power domains.
67 75
68A machine that has TCM memory shall select HAVE_TCM in 76A machine that has TCM memory shall select HAVE_TCM from
69arch/arm/Kconfig for itself, and then the 77arch/arm/Kconfig for itself. Code that needs to use TCM shall
70rest of the functionality will depend on the physical 78#include <asm/tcm.h>
71location and size of ITCM and DTCM to be defined in
72mach/memory.h for the machine. Code that needs to use
73TCM shall #include <asm/tcm.h> If the TCM is not located
74at the place given in memory.h it will be moved using
75the TCM Region registers.
76 79
77Functions to go into itcm can be tagged like this: 80Functions to go into itcm can be tagged like this:
78int __tcmfunc foo(int bar); 81int __tcmfunc foo(int bar);
79 82
83Since these are marked to become long_calls and you may want
84to have functions called locally inside the TCM without
85wasting space, there is also the __tcmlocalfunc prefix that
86will make the call relative.
87
80Variables to go into dtcm can be tagged like this: 88Variables to go into dtcm can be tagged like this:
81int __tcmdata foo; 89int __tcmdata foo;
82 90
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 4312ee5e3d0..ab08d977ad4 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -124,6 +124,15 @@
124#endif /* !CONFIG_MMU */ 124#endif /* !CONFIG_MMU */
125 125
126/* 126/*
127 * We fix the TCM memories max 32 KiB ITCM resp DTCM at these
128 * locations
129 */
130#ifdef CONFIG_HAVE_TCM
131#define ITCM_OFFSET UL(0xfffe0000)
132#define DTCM_OFFSET UL(0xfffe8000)
133#endif
134
135/*
127 * Physical vs virtual RAM address space conversion. These are 136 * Physical vs virtual RAM address space conversion. These are
128 * private definitions which should NOT be used outside memory.h 137 * private definitions which should NOT be used outside memory.h
129 * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. 138 * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c
index f2ead32c1aa..26685c2f7a4 100644
--- a/arch/arm/kernel/tcm.c
+++ b/arch/arm/kernel/tcm.c
@@ -18,32 +18,30 @@
18#include <mach/memory.h> 18#include <mach/memory.h>
19#include "tcm.h" 19#include "tcm.h"
20 20
21/* Scream and warn about misuse */
22#if !defined(ITCM_OFFSET) || !defined(ITCM_END) || \
23 !defined(DTCM_OFFSET) || !defined(DTCM_END)
24#error "TCM support selected but offsets not defined!"
25#endif
26
27static struct gen_pool *tcm_pool; 21static struct gen_pool *tcm_pool;
28 22
29/* TCM section definitions from the linker */ 23/* TCM section definitions from the linker */
30extern char __itcm_start, __sitcm_text, __eitcm_text; 24extern char __itcm_start, __sitcm_text, __eitcm_text;
31extern char __dtcm_start, __sdtcm_data, __edtcm_data; 25extern char __dtcm_start, __sdtcm_data, __edtcm_data;
32 26
27/* These will be increased as we run */
28u32 dtcm_end = DTCM_OFFSET;
29u32 itcm_end = ITCM_OFFSET;
30
33/* 31/*
34 * TCM memory resources 32 * TCM memory resources
35 */ 33 */
36static struct resource dtcm_res = { 34static struct resource dtcm_res = {
37 .name = "DTCM RAM", 35 .name = "DTCM RAM",
38 .start = DTCM_OFFSET, 36 .start = DTCM_OFFSET,
39 .end = DTCM_END, 37 .end = DTCM_OFFSET,
40 .flags = IORESOURCE_MEM 38 .flags = IORESOURCE_MEM
41}; 39};
42 40
43static struct resource itcm_res = { 41static struct resource itcm_res = {
44 .name = "ITCM RAM", 42 .name = "ITCM RAM",
45 .start = ITCM_OFFSET, 43 .start = ITCM_OFFSET,
46 .end = ITCM_END, 44 .end = ITCM_OFFSET,
47 .flags = IORESOURCE_MEM 45 .flags = IORESOURCE_MEM
48}; 46};
49 47
@@ -51,7 +49,7 @@ static struct map_desc dtcm_iomap[] __initdata = {
51 { 49 {
52 .virtual = DTCM_OFFSET, 50 .virtual = DTCM_OFFSET,
53 .pfn = __phys_to_pfn(DTCM_OFFSET), 51 .pfn = __phys_to_pfn(DTCM_OFFSET),
54 .length = (DTCM_END - DTCM_OFFSET + 1), 52 .length = 0,
55 .type = MT_MEMORY_DTCM 53 .type = MT_MEMORY_DTCM
56 } 54 }
57}; 55};
@@ -60,7 +58,7 @@ static struct map_desc itcm_iomap[] __initdata = {
60 { 58 {
61 .virtual = ITCM_OFFSET, 59 .virtual = ITCM_OFFSET,
62 .pfn = __phys_to_pfn(ITCM_OFFSET), 60 .pfn = __phys_to_pfn(ITCM_OFFSET),
63 .length = (ITCM_END - ITCM_OFFSET + 1), 61 .length = 0,
64 .type = MT_MEMORY_ITCM 62 .type = MT_MEMORY_ITCM
65 } 63 }
66}; 64};
@@ -92,8 +90,8 @@ void tcm_free(void *addr, size_t len)
92} 90}
93EXPORT_SYMBOL(tcm_free); 91EXPORT_SYMBOL(tcm_free);
94 92
95static void __init setup_tcm_bank(u8 type, u8 bank, u8 banks, 93static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks,
96 u32 offset, u32 expected_size) 94 u32 *offset)
97{ 95{
98 const int tcm_sizes[16] = { 0, -1, -1, 4, 8, 16, 32, 64, 128, 96 const int tcm_sizes[16] = { 0, -1, -1, 4, 8, 16, 32, 64, 128,
99 256, 512, 1024, -1, -1, -1, -1 }; 97 256, 512, 1024, -1, -1, -1, -1 };
@@ -120,8 +118,13 @@ static void __init setup_tcm_bank(u8 type, u8 bank, u8 banks,
120 118
121 tcm_size = tcm_sizes[(tcm_region >> 2) & 0x0f]; 119 tcm_size = tcm_sizes[(tcm_region >> 2) & 0x0f];
122 if (tcm_size < 0) { 120 if (tcm_size < 0) {
123 pr_err("CPU: %sTCM%d of unknown size!\n", 121 pr_err("CPU: %sTCM%d of unknown size\n",
124 type ? "I" : "D", bank); 122 type ? "I" : "D", bank);
123 return -EINVAL;