diff options
author | Guo Ren <ren_guo@c-sky.com> | 2018-09-05 02:25:07 -0400 |
---|---|---|
committer | Guo Ren <ren_guo@c-sky.com> | 2018-10-25 11:36:19 -0400 |
commit | 9143a9359d051142081b26c3726c928f965c5eb7 (patch) | |
tree | dc479bde8b6fe4faf45f2b53519a019708bfe649 | |
parent | 7c768f845104b7c96954ad536be29797eff6a434 (diff) |
csky: Kernel booting
This patch add boot code. Thx boot params is all in dtb and it's
the only way to let kernel get bootloader param information.
Signed-off-by: Guo Ren <ren_guo@c-sky.com>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | arch/csky/kernel/head.S | 77 | ||||
-rw-r--r-- | arch/csky/kernel/setup.c | 162 | ||||
-rw-r--r-- | arch/csky/kernel/vmlinux.lds.S | 66 |
3 files changed, 305 insertions, 0 deletions
diff --git a/arch/csky/kernel/head.S b/arch/csky/kernel/head.S new file mode 100644 index 000000000000..9c4ec473b76b --- /dev/null +++ b/arch/csky/kernel/head.S | |||
@@ -0,0 +1,77 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | |||
3 | #include <linux/linkage.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <asm/page.h> | ||
6 | #include <abi/entry.h> | ||
7 | |||
8 | __HEAD | ||
9 | ENTRY(_start) | ||
10 | /* set super user mode */ | ||
11 | lrw a3, DEFAULT_PSR_VALUE | ||
12 | mtcr a3, psr | ||
13 | psrset ee | ||
14 | |||
15 | SETUP_MMU a3 | ||
16 | |||
17 | /* set stack point */ | ||
18 | lrw a3, init_thread_union + THREAD_SIZE | ||
19 | mov sp, a3 | ||
20 | |||
21 | jmpi csky_start | ||
22 | END(_start) | ||
23 | |||
24 | #ifdef CONFIG_SMP | ||
25 | .align 10 | ||
26 | ENTRY(_start_smp_secondary) | ||
27 | /* Invalid I/Dcache BTB BHT */ | ||
28 | movi a3, 7 | ||
29 | lsli a3, 16 | ||
30 | addi a3, (1<<4) | 3 | ||
31 | mtcr a3, cr17 | ||
32 | |||
33 | tlbi.alls | ||
34 | |||
35 | /* setup PAGEMASK */ | ||
36 | movi a3, 0 | ||
37 | mtcr a3, cr<6, 15> | ||
38 | |||
39 | /* setup MEL0/MEL1 */ | ||
40 | grs a0, _start_smp_pc | ||
41 | _start_smp_pc: | ||
42 | bmaski a1, 13 | ||
43 | andn a0, a1 | ||
44 | movi a1, 0x00000006 | ||
45 | movi a2, 0x00001006 | ||
46 | or a1, a0 | ||
47 | or a2, a0 | ||
48 | mtcr a1, cr<2, 15> | ||
49 | mtcr a2, cr<3, 15> | ||
50 | |||
51 | /* setup MEH */ | ||
52 | mtcr a0, cr<4, 15> | ||
53 | |||
54 | /* write TLB */ | ||
55 | bgeni a3, 28 | ||
56 | mtcr a3, cr<8, 15> | ||
57 | |||
58 | SETUP_MMU a3 | ||
59 | |||
60 | /* enable MMU */ | ||
61 | movi a3, 1 | ||
62 | mtcr a3, cr18 | ||
63 | |||
64 | jmpi _goto_mmu_on | ||
65 | _goto_mmu_on: | ||
66 | lrw a3, DEFAULT_PSR_VALUE | ||
67 | mtcr a3, psr | ||
68 | psrset ee | ||
69 | |||
70 | /* set stack point */ | ||
71 | lrw a3, secondary_stack | ||
72 | ld.w a3, (a3, 0) | ||
73 | mov sp, a3 | ||
74 | |||
75 | jmpi csky_start_secondary | ||
76 | END(_start_smp_secondary) | ||
77 | #endif | ||
diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c new file mode 100644 index 000000000000..a5e3ab1d5360 --- /dev/null +++ b/arch/csky/kernel/setup.c | |||
@@ -0,0 +1,162 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. | ||
3 | |||
4 | #include <linux/console.h> | ||
5 | #include <linux/memblock.h> | ||
6 | #include <linux/bootmem.h> | ||
7 | #include <linux/initrd.h> | ||
8 | #include <linux/of.h> | ||
9 | #include <linux/of_fdt.h> | ||
10 | #include <linux/start_kernel.h> | ||
11 | #include <linux/dma-contiguous.h> | ||
12 | #include <linux/screen_info.h> | ||
13 | #include <asm/sections.h> | ||
14 | #include <asm/mmu_context.h> | ||
15 | #include <asm/pgalloc.h> | ||
16 | |||
17 | #ifdef CONFIG_DUMMY_CONSOLE | ||
18 | struct screen_info screen_info = { | ||
19 | .orig_video_lines = 30, | ||
20 | .orig_video_cols = 80, | ||
21 | .orig_video_mode = 0, | ||
22 | .orig_video_ega_bx = 0, | ||
23 | .orig_video_isVGA = 1, | ||
24 | .orig_video_points = 8 | ||
25 | }; | ||
26 | #endif | ||
27 | |||
28 | phys_addr_t __init_memblock memblock_end_of_REG0(void) | ||
29 | { | ||
30 | return (memblock.memory.regions[0].base + | ||
31 | memblock.memory.regions[0].size); | ||
32 | } | ||
33 | |||
34 | phys_addr_t __init_memblock memblock_start_of_REG1(void) | ||
35 | { | ||
36 | return memblock.memory.regions[1].base; | ||
37 | } | ||
38 | |||
39 | size_t __init_memblock memblock_size_of_REG1(void) | ||
40 | { | ||
41 | return memblock.memory.regions[1].size; | ||
42 | } | ||
43 | |||
44 | static void __init csky_memblock_init(void) | ||
45 | { | ||
46 | unsigned long zone_size[MAX_NR_ZONES]; | ||
47 | unsigned long zhole_size[MAX_NR_ZONES]; | ||
48 | signed long size; | ||
49 | |||
50 | memblock_reserve(__pa(_stext), _end - _stext); | ||
51 | #ifdef CONFIG_BLK_DEV_INITRD | ||
52 | memblock_reserve(__pa(initrd_start), initrd_end - initrd_start); | ||
53 | #endif | ||
54 | |||
55 | early_init_fdt_reserve_self(); | ||
56 | early_init_fdt_scan_reserved_mem(); | ||
57 | |||
58 | memblock_dump_all(); | ||
59 | |||
60 | memset(zone_size, 0, sizeof(zone_size)); | ||
61 | memset(zhole_size, 0, sizeof(zhole_size)); | ||
62 | |||
63 | min_low_pfn = PFN_UP(memblock_start_of_DRAM()); | ||
64 | max_pfn = PFN_DOWN(memblock_end_of_DRAM()); | ||
65 | |||
66 | max_low_pfn = PFN_UP(memblock_end_of_REG0()); | ||
67 | if (max_low_pfn == 0) | ||
68 | max_low_pfn = max_pfn; | ||
69 | |||
70 | size = max_pfn - min_low_pfn; | ||
71 | |||
72 | if (memblock.memory.cnt > 1) { | ||
73 | zone_size[ZONE_NORMAL] = | ||
74 | PFN_DOWN(memblock_start_of_REG1()) - min_low_pfn; | ||
75 | zhole_size[ZONE_NORMAL] = | ||
76 | PFN_DOWN(memblock_start_of_REG1()) - max_low_pfn; | ||
77 | } else { | ||
78 | if (size <= PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET)) | ||
79 | zone_size[ZONE_NORMAL] = max_pfn - min_low_pfn; | ||
80 | else { | ||
81 | zone_size[ZONE_NORMAL] = | ||
82 | PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET); | ||
83 | max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL]; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | #ifdef CONFIG_HIGHMEM | ||
88 | size = 0; | ||
89 | if (memblock.memory.cnt > 1) { | ||
90 | size = PFN_DOWN(memblock_size_of_REG1()); | ||
91 | highstart_pfn = PFN_DOWN(memblock_start_of_REG1()); | ||
92 | } else { | ||
93 | size = max_pfn - min_low_pfn - | ||
94 | PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET); | ||
95 | highstart_pfn = min_low_pfn + | ||
96 | PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET); | ||
97 | } | ||
98 | |||
99 | if (size > 0) | ||
100 | zone_size[ZONE_HIGHMEM] = size; | ||
101 | |||
102 | highend_pfn = max_pfn; | ||
103 | #endif | ||
104 | memblock_set_current_limit(PFN_PHYS(max_low_pfn)); | ||
105 | |||
106 | dma_contiguous_reserve(0); | ||
107 | |||
108 | free_area_init_node(0, zone_size, min_low_pfn, zhole_size); | ||
109 | } | ||
110 | |||
111 | void __init setup_arch(char **cmdline_p) | ||
112 | { | ||
113 | *cmdline_p = boot_command_line; | ||
114 | |||
115 | console_verbose(); | ||
116 | |||
117 | pr_info("Phys. mem: %ldMB\n", | ||
118 | (unsigned long) memblock_phys_mem_size()/1024/1024); | ||
119 | |||
120 | init_mm.start_code = (unsigned long) _stext; | ||
121 | init_mm.end_code = (unsigned long) _etext; | ||
122 | init_mm.end_data = (unsigned long) _edata; | ||
123 | init_mm.brk = (unsigned long) _end; | ||
124 | |||
125 | parse_early_param(); | ||
126 | |||
127 | csky_memblock_init(); | ||
128 | |||
129 | unflatten_and_copy_device_tree(); | ||
130 | |||
131 | #ifdef CONFIG_SMP | ||
132 | setup_smp(); | ||
133 | #endif | ||
134 | |||
135 | sparse_init(); | ||
136 | |||
137 | #ifdef CONFIG_HIGHMEM | ||
138 | kmap_init(); | ||
139 | #endif | ||
140 | |||
141 | #if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE) | ||
142 | conswitchp = &dummy_con; | ||
143 | #endif | ||
144 | } | ||
145 | |||
146 | asmlinkage __visible void __init csky_start(unsigned int unused, void *param) | ||
147 | { | ||
148 | /* Clean up bss section */ | ||
149 | memset(__bss_start, 0, __bss_stop - __bss_start); | ||
150 | |||
151 | pre_trap_init(); | ||
152 | pre_mmu_init(); | ||
153 | |||
154 | if (param == NULL) | ||
155 | early_init_dt_scan(__dtb_start); | ||
156 | else | ||
157 | early_init_dt_scan(param); | ||
158 | |||
159 | start_kernel(); | ||
160 | |||
161 | asm volatile("br .\n"); | ||
162 | } | ||
diff --git a/arch/csky/kernel/vmlinux.lds.S b/arch/csky/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..ae7961b973f2 --- /dev/null +++ b/arch/csky/kernel/vmlinux.lds.S | |||
@@ -0,0 +1,66 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | |||
3 | #include <asm/vmlinux.lds.h> | ||
4 | #include <asm/page.h> | ||
5 | |||
6 | OUTPUT_ARCH(csky) | ||
7 | ENTRY(_start) | ||
8 | |||
9 | #ifndef __cskyBE__ | ||
10 | jiffies = jiffies_64; | ||
11 | #else | ||
12 | jiffies = jiffies_64 + 4; | ||
13 | #endif | ||
14 | |||
15 | #define VBR_BASE \ | ||
16 | . = ALIGN(1024); \ | ||
17 | vec_base = .; \ | ||
18 | . += 512; | ||
19 | |||
20 | SECTIONS | ||
21 | { | ||
22 | . = PAGE_OFFSET + PHYS_OFFSET_OFFSET; | ||
23 | |||
24 | _stext = .; | ||
25 | __init_begin = .; | ||
26 | HEAD_TEXT_SECTION | ||
27 | INIT_TEXT_SECTION(PAGE_SIZE) | ||
28 | INIT_DATA_SECTION(PAGE_SIZE) | ||
29 | PERCPU_SECTION(L1_CACHE_BYTES) | ||
30 | . = ALIGN(PAGE_SIZE); | ||
31 | __init_end = .; | ||
32 | |||
33 | .text : AT(ADDR(.text) - LOAD_OFFSET) { | ||
34 | _text = .; | ||
35 | IRQENTRY_TEXT | ||
36 | SOFTIRQENTRY_TEXT | ||
37 | TEXT_TEXT | ||
38 | SCHED_TEXT | ||
39 | CPUIDLE_TEXT | ||
40 | LOCK_TEXT | ||
41 | KPROBES_TEXT | ||
42 | *(.fixup) | ||
43 | *(.gnu.warning) | ||
44 | } = 0 | ||
45 | _etext = .; | ||
46 | |||
47 | /* __init_begin __init_end must be page aligned for free_initmem */ | ||
48 | . = ALIGN(PAGE_SIZE); | ||
49 | |||
50 | |||
51 | _sdata = .; | ||
52 | RO_DATA_SECTION(PAGE_SIZE) | ||
53 | RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) | ||
54 | _edata = .; | ||
55 | |||
56 | NOTES | ||
57 | EXCEPTION_TABLE(L1_CACHE_BYTES) | ||
58 | BSS_SECTION(L1_CACHE_BYTES, PAGE_SIZE, L1_CACHE_BYTES) | ||
59 | VBR_BASE | ||
60 | _end = . ; | ||
61 | |||
62 | STABS_DEBUG | ||
63 | DWARF_DEBUG | ||
64 | |||
65 | DISCARDS | ||
66 | } | ||