diff options
author | Bill Gatliff <bgat@billgatliff.com> | 2007-05-31 17:02:22 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-07-12 06:13:33 -0400 |
commit | 9d20fdd58e74d4d26dc5216efaaa0f800c23dd3a (patch) | |
tree | bc8520791f304ce297a52f575930c2797067521c /arch/arm | |
parent | 7d09e85448dfa78e3e58186c934449aaf6d49b50 (diff) |
[ARM] 4423/1: add ATAGS support
Examines the ATAGS pointer (r2) at boot, and interprets
a nonzero value as a reference to an ATAGS structure. A
suitable ATAGS structure replaces the kernel's command line.
Signed-off-by: Bill Gatliff <bgat@billgatliff.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/kernel/head-common.S | 40 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 7 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 6 |
3 files changed, 48 insertions, 5 deletions
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index a52da0ddb43d..024a9cf469b4 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S | |||
@@ -20,7 +20,8 @@ __switch_data: | |||
20 | .long _end @ r7 | 20 | .long _end @ r7 |
21 | .long processor_id @ r4 | 21 | .long processor_id @ r4 |
22 | .long __machine_arch_type @ r5 | 22 | .long __machine_arch_type @ r5 |
23 | .long cr_alignment @ r6 | 23 | .long __atags_pointer @ r6 |
24 | .long cr_alignment @ r7 | ||
24 | .long init_thread_union + THREAD_START_SP @ sp | 25 | .long init_thread_union + THREAD_START_SP @ sp |
25 | 26 | ||
26 | /* | 27 | /* |
@@ -29,6 +30,7 @@ __switch_data: | |||
29 | * | 30 | * |
30 | * r0 = cp#15 control register | 31 | * r0 = cp#15 control register |
31 | * r1 = machine ID | 32 | * r1 = machine ID |
33 | * r2 = atags pointer | ||
32 | * r9 = processor ID | 34 | * r9 = processor ID |
33 | */ | 35 | */ |
34 | .type __mmap_switched, %function | 36 | .type __mmap_switched, %function |
@@ -47,11 +49,12 @@ __mmap_switched: | |||
47 | strcc fp, [r6],#4 | 49 | strcc fp, [r6],#4 |
48 | bcc 1b | 50 | bcc 1b |
49 | 51 | ||
50 | ldmia r3, {r4, r5, r6, sp} | 52 | ldmia r3, {r4, r5, r6, r7, sp} |
51 | str r9, [r4] @ Save processor ID | 53 | str r9, [r4] @ Save processor ID |
52 | str r1, [r5] @ Save machine type | 54 | str r1, [r5] @ Save machine type |
55 | str r2, [r6] @ Save atags pointer | ||
53 | bic r4, r0, #CR_A @ Clear 'A' bit | 56 | bic r4, r0, #CR_A @ Clear 'A' bit |
54 | stmia r6, {r0, r4} @ Save control register values | 57 | stmia r7, {r0, r4} @ Save control register values |
55 | b start_kernel | 58 | b start_kernel |
56 | 59 | ||
57 | /* | 60 | /* |
@@ -215,3 +218,34 @@ ENTRY(lookup_machine_type) | |||
215 | bl __lookup_machine_type | 218 | bl __lookup_machine_type |
216 | mov r0, r5 | 219 | mov r0, r5 |
217 | ldmfd sp!, {r4 - r6, pc} | 220 | ldmfd sp!, {r4 - r6, pc} |
221 | |||
222 | /* Determine validity of the r2 atags pointer. The heuristic requires | ||
223 | * that the pointer be aligned, in the first 16k of physical RAM and | ||
224 | * that the ATAG_CORE marker is first and present. Future revisions | ||
225 | * of this function may be more lenient with the physical address and | ||
226 | * may also be able to move the ATAGS block if necessary. | ||
227 | * | ||
228 | * r8 = machinfo | ||
229 | * | ||
230 | * Returns: | ||
231 | * r2 either valid atags pointer, or zero | ||
232 | * r5, r6 corrupted | ||
233 | */ | ||
234 | |||
235 | .type __vet_atags, %function | ||
236 | __vet_atags: | ||
237 | tst r2, #0x3 @ aligned? | ||
238 | bne 1f | ||
239 | |||
240 | ldr r5, [r2, #0] @ is first tag ATAG_CORE? | ||
241 | subs r5, r5, #ATAG_CORE_SIZE | ||
242 | bne 1f | ||
243 | ldr r5, [r2, #4] | ||
244 | ldr r6, =ATAG_CORE | ||
245 | cmp r5, r6 | ||
246 | bne 1f | ||
247 | |||
248 | mov pc, lr @ atag pointer is ok | ||
249 | |||
250 | 1: mov r2, #0 | ||
251 | mov pc, lr | ||
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 41f98b4ba2ee..7898cbc9861a 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -29,6 +29,10 @@ | |||
29 | #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) | 29 | #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) |
30 | #define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) | 30 | #define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) |
31 | 31 | ||
32 | #define ATAG_CORE 0x54410001 | ||
33 | #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) | ||
34 | |||
35 | |||
32 | /* | 36 | /* |
33 | * swapper_pg_dir is the virtual address of the initial page table. | 37 | * swapper_pg_dir is the virtual address of the initial page table. |
34 | * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must | 38 | * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must |
@@ -61,7 +65,7 @@ | |||
61 | * | 65 | * |
62 | * This is normally called from the decompressor code. The requirements | 66 | * This is normally called from the decompressor code. The requirements |
63 | * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, | 67 | * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, |
64 | * r1 = machine nr. | 68 | * r1 = machine nr, r2 = atags pointer. |
65 | * | 69 | * |
66 | * This code is mostly position independent, so if you link the kernel at | 70 | * This code is mostly position independent, so if you link the kernel at |
67 | * 0xc0008000, you call this at __pa(0xc0008000). | 71 | * 0xc0008000, you call this at __pa(0xc0008000). |
@@ -85,6 +89,7 @@ ENTRY(stext) | |||
85 | bl __lookup_machine_type @ r5=machinfo | 89 | bl __lookup_machine_type @ r5=machinfo |
86 | movs r8, r5 @ invalid machine (r5=0)? | 90 | movs r8, r5 @ invalid machine (r5=0)? |
87 | beq __error_a @ yes, error 'a' | 91 | beq __error_a @ yes, error 'a' |
92 | bl __vet_atags | ||
88 | bl __create_page_tables | 93 | bl __create_page_tables |
89 | 94 | ||
90 | /* | 95 | /* |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 650eac1bc0a6..5be2e987b843 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -63,6 +63,8 @@ unsigned int processor_id; | |||
63 | unsigned int __machine_arch_type; | 63 | unsigned int __machine_arch_type; |
64 | EXPORT_SYMBOL(__machine_arch_type); | 64 | EXPORT_SYMBOL(__machine_arch_type); |
65 | 65 | ||
66 | unsigned int __atags_pointer __initdata; | ||
67 | |||
66 | unsigned int system_rev; | 68 | unsigned int system_rev; |
67 | EXPORT_SYMBOL(system_rev); | 69 | EXPORT_SYMBOL(system_rev); |
68 | 70 | ||
@@ -780,7 +782,9 @@ void __init setup_arch(char **cmdline_p) | |||
780 | if (mdesc->soft_reboot) | 782 | if (mdesc->soft_reboot) |
781 | reboot_setup("s"); | 783 | reboot_setup("s"); |
782 | 784 | ||
783 | if (mdesc->boot_params) | 785 | if (__atags_pointer) |
786 | tags = phys_to_virt(__atags_pointer); | ||
787 | else if (mdesc->boot_params) | ||
784 | tags = phys_to_virt(mdesc->boot_params); | 788 | tags = phys_to_virt(mdesc->boot_params); |
785 | 789 | ||
786 | /* | 790 | /* |