aboutsummaryrefslogtreecommitdiffstats
path: root/arch/nios2
diff options
context:
space:
mode:
authorLey Foon Tan <lftan@altera.com>2014-11-06 02:19:37 -0500
committerLey Foon Tan <lftan@altera.com>2014-12-07 23:55:49 -0500
commit27d22413e60009603bc4eb515392c2639ff31010 (patch)
tree9948df5e5259c938c358337daeed461dbaa32450 /arch/nios2
parent39b505cb7929d272020a2c9c25f6e3cd7c112447 (diff)
nios2: Kernel booting and initialization
This patch adds the kernel booting and the initial setup code. Signed-off-by: Ley Foon Tan <lftan@altera.com>
Diffstat (limited to 'arch/nios2')
-rw-r--r--arch/nios2/include/asm/entry.h120
-rw-r--r--arch/nios2/include/asm/setup.h38
-rw-r--r--arch/nios2/kernel/head.S175
-rw-r--r--arch/nios2/kernel/setup.c218
4 files changed, 551 insertions, 0 deletions
diff --git a/arch/nios2/include/asm/entry.h b/arch/nios2/include/asm/entry.h
new file mode 100644
index 000000000000..cf37f55efbc2
--- /dev/null
+++ b/arch/nios2/include/asm/entry.h
@@ -0,0 +1,120 @@
1/*
2 * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
3 * Copyright (C) 2004 Microtronix Datacom Ltd.
4 *
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file "COPYING" in the main directory of this archive
7 * for more details.
8 */
9
10#ifndef _ASM_NIOS2_ENTRY_H
11#define _ASM_NIOS2_ENTRY_H
12
13#ifdef __ASSEMBLY__
14
15#include <asm/processor.h>
16#include <asm/registers.h>
17#include <asm/asm-offsets.h>
18
19/*
20 * Standard Nios2 interrupt entry and exit macros.
21 * Must be called with interrupts disabled.
22 */
23.macro SAVE_ALL
24 rdctl r24, estatus
25 andi r24, r24, ESTATUS_EU
26 beq r24, r0, 1f /* In supervisor mode, already on kernel stack */
27
28 movia r24, _current_thread /* Switch to current kernel stack */
29 ldw r24, 0(r24) /* using the thread_info */
30 addi r24, r24, THREAD_SIZE-PT_REGS_SIZE
31 stw sp, PT_SP(r24) /* Save user stack before changing */
32 mov sp, r24
33 br 2f
34
351 : mov r24, sp
36 addi sp, sp, -PT_REGS_SIZE /* Backup the kernel stack pointer */
37 stw r24, PT_SP(sp)
382 : stw r1, PT_R1(sp)
39 stw r2, PT_R2(sp)
40 stw r3, PT_R3(sp)
41 stw r4, PT_R4(sp)
42 stw r5, PT_R5(sp)
43 stw r6, PT_R6(sp)
44 stw r7, PT_R7(sp)
45 stw r8, PT_R8(sp)
46 stw r9, PT_R9(sp)
47 stw r10, PT_R10(sp)
48 stw r11, PT_R11(sp)
49 stw r12, PT_R12(sp)
50 stw r13, PT_R13(sp)
51 stw r14, PT_R14(sp)
52 stw r15, PT_R15(sp)
53 stw r2, PT_ORIG_R2(sp)
54 stw r7, PT_ORIG_R7(sp)
55
56 stw ra, PT_RA(sp)
57 stw fp, PT_FP(sp)
58 stw gp, PT_GP(sp)
59 rdctl r24, estatus
60 stw r24, PT_ESTATUS(sp)
61 stw ea, PT_EA(sp)
62.endm
63
64.macro RESTORE_ALL
65 ldw r1, PT_R1(sp) /* Restore registers */
66 ldw r2, PT_R2(sp)
67 ldw r3, PT_R3(sp)
68 ldw r4, PT_R4(sp)
69 ldw r5, PT_R5(sp)
70 ldw r6, PT_R6(sp)
71 ldw r7, PT_R7(sp)
72 ldw r8, PT_R8(sp)
73 ldw r9, PT_R9(sp)
74 ldw r10, PT_R10(sp)
75 ldw r11, PT_R11(sp)
76 ldw r12, PT_R12(sp)
77 ldw r13, PT_R13(sp)
78 ldw r14, PT_R14(sp)
79 ldw r15, PT_R15(sp)
80 ldw ra, PT_RA(sp)
81 ldw fp, PT_FP(sp)
82 ldw gp, PT_GP(sp)
83 ldw r24, PT_ESTATUS(sp)
84 wrctl estatus, r24
85 ldw ea, PT_EA(sp)
86 ldw sp, PT_SP(sp) /* Restore sp last */
87.endm
88
89.macro SAVE_SWITCH_STACK
90 addi sp, sp, -SWITCH_STACK_SIZE
91 stw r16, SW_R16(sp)
92 stw r17, SW_R17(sp)
93 stw r18, SW_R18(sp)
94 stw r19, SW_R19(sp)
95 stw r20, SW_R20(sp)
96 stw r21, SW_R21(sp)
97 stw r22, SW_R22(sp)
98 stw r23, SW_R23(sp)
99 stw fp, SW_FP(sp)
100 stw gp, SW_GP(sp)
101 stw ra, SW_RA(sp)
102.endm
103
104.macro RESTORE_SWITCH_STACK
105 ldw r16, SW_R16(sp)
106 ldw r17, SW_R17(sp)
107 ldw r18, SW_R18(sp)
108 ldw r19, SW_R19(sp)
109 ldw r20, SW_R20(sp)
110 ldw r21, SW_R21(sp)
111 ldw r22, SW_R22(sp)
112 ldw r23, SW_R23(sp)
113 ldw fp, SW_FP(sp)
114 ldw gp, SW_GP(sp)
115 ldw ra, SW_RA(sp)
116 addi sp, sp, SWITCH_STACK_SIZE
117.endm
118
119#endif /* __ASSEMBLY__ */
120#endif /* _ASM_NIOS2_ENTRY_H */
diff --git a/arch/nios2/include/asm/setup.h b/arch/nios2/include/asm/setup.h
new file mode 100644
index 000000000000..dcbf8cf1a344
--- /dev/null
+++ b/arch/nios2/include/asm/setup.h
@@ -0,0 +1,38 @@
1/*
2 * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19#ifndef _ASM_NIOS2_SETUP_H
20#define _ASM_NIOS2_SETUP_H
21
22#include <asm-generic/setup.h>
23
24#ifndef __ASSEMBLY__
25#ifdef __KERNEL__
26
27extern char exception_handler_hook[];
28extern char fast_handler[];
29extern char fast_handler_end[];
30
31extern void pagetable_init(void);
32
33extern void setup_early_printk(void);
34
35#endif/* __KERNEL__ */
36#endif /* __ASSEMBLY__ */
37
38#endif /* _ASM_NIOS2_SETUP_H */
diff --git a/arch/nios2/kernel/head.S b/arch/nios2/kernel/head.S
new file mode 100644
index 000000000000..372ce4a33018
--- /dev/null
+++ b/arch/nios2/kernel/head.S
@@ -0,0 +1,175 @@
1/*
2 * Copyright (C) 2009 Wind River Systems Inc
3 * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
4 * Copyright (C) 2004 Microtronix Datacom Ltd
5 * Copyright (C) 2001 Vic Phillips, Microtronix Datacom Ltd.
6 *
7 * Based on head.S for Altera's Excalibur development board with nios processor
8 *
9 * Based on the following from the Excalibur sdk distribution:
10 * NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.s
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file "COPYING" in the main directory of this archive
14 * for more details.
15 */
16
17#include <linux/init.h>
18#include <linux/linkage.h>
19#include <asm/thread_info.h>
20#include <asm/processor.h>
21#include <asm/cache.h>
22#include <asm/page.h>
23#include <asm/asm-offsets.h>
24#include <asm/asm-macros.h>
25
26/*
27 * ZERO_PAGE is a special page that is used for zero-initialized
28 * data and COW.
29 */
30.data
31.global empty_zero_page
32.align 12
33empty_zero_page:
34 .space PAGE_SIZE
35
36/*
37 * This global variable is used as an extension to the nios'
38 * STATUS register to emulate a user/supervisor mode.
39 */
40 .data
41 .align 2
42 .set noat
43
44 .global _current_thread
45_current_thread:
46 .long 0
47/*
48 * Input(s): passed from u-boot
49 * r4 - Optional pointer to a board information structure.
50 * r5 - Optional pointer to the physical starting address of the init RAM
51 * disk.
52 * r6 - Optional pointer to the physical ending address of the init RAM
53 * disk.
54 * r7 - Optional pointer to the physical starting address of any kernel
55 * command-line parameters.
56 */
57
58/*
59 * First executable code - detected and jumped to by the ROM bootstrap
60 * if the code resides in flash (looks for "Nios" at offset 0x0c from
61 * the potential executable image).
62 */
63 __HEAD
64ENTRY(_start)
65 wrctl status, r0 /* Disable interrupts */
66
67 /* Initialize all cache lines within the instruction cache */
68 movia r1, NIOS2_ICACHE_SIZE
69 movui r2, NIOS2_ICACHE_LINE_SIZE
70
71icache_init:
72 initi r1
73 sub r1, r1, r2
74 bgt r1, r0, icache_init
75 br 1f
76
77 /*
78 * This is the default location for the exception handler. Code in jump
79 * to our handler
80 */
81ENTRY(exception_handler_hook)
82 movia r24, inthandler
83 jmp r24
84
85ENTRY(fast_handler)
86 nextpc et
87helper:
88 stw r3, r3save - helper(et)
89
90 rdctl r3 , pteaddr
91 srli r3, r3, 12
92 slli r3, r3, 2
93 movia et, pgd_current
94
95 ldw et, 0(et)
96 add r3, et, r3
97 ldw et, 0(r3)
98
99 rdctl r3, pteaddr
100 andi r3, r3, 0xfff
101 add et, r3, et
102 ldw et, 0(et)
103 wrctl tlbacc, et
104 nextpc et
105helper2:
106 ldw r3, r3save - helper2(et)
107 subi ea, ea, 4
108 eret
109r3save:
110 .word 0x0
111ENTRY(fast_handler_end)
112
1131:
114 /*
115 * After the instruction cache is initialized, the data cache must
116 * also be initialized.
117 */
118 movia r1, NIOS2_DCACHE_SIZE
119 movui r2, NIOS2_DCACHE_LINE_SIZE
120
121dcache_init:
122 initd 0(r1)
123 sub r1, r1, r2
124 bgt r1, r0, dcache_init
125
126 nextpc r1 /* Find out where we are */
127chkadr:
128 movia r2, chkadr
129 beq r1, r2,finish_move /* We are running in RAM done */
130 addi r1, r1,(_start - chkadr) /* Source */
131 movia r2, _start /* Destination */
132 movia r3, __bss_start /* End of copy */
133
134loop_move: /* r1: src, r2: dest, r3: last dest */
135 ldw r8, 0(r1) /* load a word from [r1] */
136 stw r8, 0(r2) /* store a word to dest [r2] */
137 flushd 0(r2) /* Flush cache for safety */
138 addi r1, r1, 4 /* inc the src addr */
139 addi r2, r2, 4 /* inc the dest addr */
140 blt r2, r3, loop_move
141
142 movia r1, finish_move /* VMA(_start)->l1 */
143 jmp r1 /* jmp to _start */
144
145finish_move:
146
147 /* Mask off all possible interrupts */
148 wrctl ienable, r0
149
150 /* Clear .bss */
151 movia r2, __bss_start
152 movia r1, __bss_stop
1531:
154 stb r0, 0(r2)
155 addi r2, r2, 1
156 bne r1, r2, 1b
157
158 movia r1, init_thread_union /* set stack at top of the task union */
159 addi sp, r1, THREAD_SIZE
160 movia r2, _current_thread /* Remember current thread */
161 stw r1, 0(r2)
162
163 movia r1, nios2_boot_init /* save args r4-r7 passed from u-boot */
164 callr r1
165
166 movia r1, start_kernel /* call start_kernel as a subroutine */
167 callr r1
168
169 /* If we return from start_kernel, break to the oci debugger and
170 * buggered we are.
171 */
172 break
173
174 /* End of startup code */
175.set at
diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c
new file mode 100644
index 000000000000..cb3121f975d4
--- /dev/null
+++ b/arch/nios2/kernel/setup.c
@@ -0,0 +1,218 @@
1/*
2 * Nios2-specific parts of system setup
3 *
4 * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
5 * Copyright (C) 2004 Microtronix Datacom Ltd.
6 * Copyright (C) 2001 Vic Phillips <vic@microtronix.com>
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/export.h>
14#include <linux/kernel.h>
15#include <linux/mm.h>
16#include <linux/sched.h>
17#include <linux/console.h>
18#include <linux/bootmem.h>
19#include <linux/initrd.h>
20#include <linux/of_fdt.h>
21
22#include <asm/mmu_context.h>
23#include <asm/sections.h>
24#include <asm/setup.h>
25#include <asm/cpuinfo.h>
26
27unsigned long memory_start;
28EXPORT_SYMBOL(memory_start);
29
30unsigned long memory_end;
31EXPORT_SYMBOL(memory_end);
32
33unsigned long memory_size;
34
35static struct pt_regs fake_regs = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 0, 0, 0, 0, 0, 0,
37 0};
38
39/* Copy a short hook instruction sequence to the exception address */
40static inline void copy_exception_handler(unsigned int addr)
41{
42 unsigned int start = (unsigned int) exception_handler_hook;
43 volatile unsigned int tmp = 0;
44
45 if (start == addr) {
46 /* The CPU exception address already points to the handler. */
47 return;
48 }
49
50 __asm__ __volatile__ (
51 "ldw %2,0(%0)\n"
52 "stw %2,0(%1)\n"
53 "ldw %2,4(%0)\n"
54 "stw %2,4(%1)\n"
55 "ldw %2,8(%0)\n"
56 "stw %2,8(%1)\n"
57 "flushd 0(%1)\n"
58 "flushd 4(%1)\n"
59 "flushd 8(%1)\n"
60 "flushi %1\n"
61 "addi %1,%1,4\n"
62 "flushi %1\n"
63 "addi %1,%1,4\n"
64 "flushi %1\n"
65 "flushp\n"
66 : /* no output registers */
67 : "r" (start), "r" (addr), "r" (tmp)
68 : "memory"
69 );
70}
71
72/* Copy the fast TLB miss handler */
73static inline void copy_fast_tlb_miss_handler(unsigned int addr)
74{
75 unsigned int start = (unsigned int) fast_handler;
76 unsigned int end = (unsigned int) fast_handler_end;
77 volatile unsigned int tmp = 0;
78
79 __asm__ __volatile__ (
80 "1:\n"
81 " ldw %3,0(%0)\n"
82 " stw %3,0(%1)\n"
83 " flushd 0(%1)\n"
84 " flushi %1\n"
85 " flushp\n"
86 " addi %0,%0,4\n"
87 " addi %1,%1,4\n"
88 " bne %0,%2,1b\n"
89 : /* no output registers */
90 : "r" (start), "r" (addr), "r" (end), "r" (tmp)
91 : "memory"
92 );
93}
94
95/*
96 * save args passed from u-boot, called from head.S
97 *
98 * @r4: NIOS magic
99 * @r5: initrd start
100 * @r6: initrd end or fdt
101 * @r7: kernel command line
102 */
103asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6,
104 unsigned r7)
105{
106 unsigned dtb_passed = 0;
107 char cmdline_passed[COMMAND_LINE_SIZE] = { 0, };
108
109#if defined(CONFIG_NIOS2_PASS_CMDLINE)
110 if (r4 == 0x534f494e) { /* r4 is magic NIOS */
111#if defined(CONFIG_BLK_DEV_INITRD)
112 if (r5) { /* initramfs */
113 initrd_start = r5;
114 initrd_end = r6;
115 }
116#endif /* CONFIG_BLK_DEV_INITRD */
117 dtb_passed = r6;
118
119 if (r7)
120 strncpy(cmdline_passed, (char *)r7, COMMAND_LINE_SIZE);
121 }
122#endif
123
124 early_init_devtree((void *)dtb_passed);
125
126#ifndef CONFIG_CMDLINE_FORCE
127 if (cmdline_passed[0])
128 strncpy(boot_command_line, cmdline_passed, COMMAND_LINE_SIZE);
129#ifdef CONFIG_NIOS2_CMDLINE_IGNORE_DTB
130 else
131 strncpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
132#endif
133#endif
134}
135
136void __init setup_arch(char **cmdline_p)
137{
138 int bootmap_size;
139
140 console_verbose();
141
142 memory_start = PAGE_ALIGN((unsigned long)__pa(_end));
143 memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size;
144
145 init_mm.start_code = (unsigned long) _stext;
146 init_mm.end_code = (unsigned long) _etext;
147 init_mm.end_data = (unsigned long) _edata;
148 init_mm.brk = (unsigned long) _end;
149 init_task.thread.kregs = &fake_regs;
150
151 /* Keep a copy of command line */
152 *cmdline_p = boot_command_line;
153
154 min_low_pfn = PFN_UP(memory_start);
155 max_low_pfn = PFN_DOWN(memory_end);
156 max_mapnr = max_low_pfn;
157
158 /*
159 * give all the memory to the bootmap allocator, tell it to put the
160 * boot mem_map at the start of memory
161 */
162 pr_debug("init_bootmem_node(?,%#lx, %#x, %#lx)\n",
163 min_low_pfn, PFN_DOWN(PHYS_OFFSET), max_low_pfn);
164 bootmap_size = init_bootmem_node(NODE_DATA(0),
165 min_low_pfn, PFN_DOWN(PHYS_OFFSET),
166 max_low_pfn);
167
168 /*
169 * free the usable memory, we have to make sure we do not free
170 * the bootmem bitmap so we then reserve it after freeing it :-)
171 */
172 pr_debug("free_bootmem(%#lx, %#lx)\n",
173 memory_start, memory_end - memory_start);
174 free_bootmem(memory_start, memory_end - memory_start);
175
176 /*
177 * Reserve the bootmem bitmap itself as well. We do this in two
178 * steps (first step was init_bootmem()) because this catches
179 * the (very unlikely) case of us accidentally initializing the
180 * bootmem allocator with an invalid RAM area.
181 *
182 * Arguments are start, size
183 */
184 pr_debug("reserve_bootmem(%#lx, %#x)\n", memory_start, bootmap_size);
185 reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
186
187#ifdef CONFIG_BLK_DEV_INITRD
188 if (initrd_start) {
189 reserve_bootmem(virt_to_phys((void *)initrd_start),
190 initrd_end - initrd_start, BOOTMEM_DEFAULT);
191 }
192#endif /* CONFIG_BLK_DEV_INITRD */
193
194 unflatten_and_copy_device_tree();
195
196 setup_cpuinfo();
197
198 copy_exception_handler(cpuinfo.exception_addr);
199
200 mmu_init();
201
202 copy_fast_tlb_miss_handler(cpuinfo.fast_tlb_miss_exc_addr);
203
204 /*
205 * Initialize MMU context handling here because data from cpuinfo is
206 * needed for this.
207 */
208 mmu_context_init();
209
210 /*
211 * get kmalloc into gear
212 */
213 paging_init();
214
215#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
216 conswitchp = &dummy_con;
217#endif
218}