Commit | Line | Data |
---|---|---|
ec9f9101 MS |
1 | /* |
2 | * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> | |
3 | * Copyright (C) 2007-2009 PetaLogix | |
4 | * Copyright (C) 2006 Atmark Techno, Inc. | |
5 | * | |
6 | * This file is subject to the terms and conditions of the GNU General Public | |
7 | * License. See the file "COPYING" in the main directory of this archive | |
8 | * for more details. | |
9 | */ | |
10 | ||
11 | #include <linux/init.h> | |
c1120542 | 12 | #include <linux/clk-provider.h> |
4bcd943e | 13 | #include <linux/clocksource.h> |
ec9f9101 MS |
14 | #include <linux/string.h> |
15 | #include <linux/seq_file.h> | |
16 | #include <linux/cpu.h> | |
17 | #include <linux/initrd.h> | |
18 | #include <linux/console.h> | |
19 | #include <linux/debugfs.h> | |
5c9f303e | 20 | #include <linux/of_fdt.h> |
ec9f9101 MS |
21 | |
22 | #include <asm/setup.h> | |
23 | #include <asm/sections.h> | |
24 | #include <asm/page.h> | |
25 | #include <linux/io.h> | |
26 | #include <linux/bug.h> | |
27 | #include <linux/param.h> | |
733cc218 | 28 | #include <linux/pci.h> |
ec9f9101 | 29 | #include <linux/cache.h> |
ccfe27d7 MS |
30 | #include <linux/of_platform.h> |
31 | #include <linux/dma-mapping.h> | |
ec9f9101 MS |
32 | #include <asm/cacheflush.h> |
33 | #include <asm/entry.h> | |
34 | #include <asm/cpuinfo.h> | |
35 | ||
ec9f9101 MS |
36 | #include <asm/prom.h> |
37 | #include <asm/pgtable.h> | |
38 | ||
39 | DEFINE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */ | |
40 | DEFINE_PER_CPU(unsigned int, KM); /* Kernel/user mode */ | |
41 | DEFINE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */ | |
42 | DEFINE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */ | |
43 | DEFINE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */ | |
44 | ||
45 | unsigned int boot_cpuid; | |
fcc1c0ff MS |
46 | /* |
47 | * Placed cmd_line to .data section because can be initialized from | |
48 | * ASM code. Default position is BSS section which is cleared | |
49 | * in machine_early_init(). | |
50 | */ | |
51 | char cmd_line[COMMAND_LINE_SIZE] __attribute__ ((section(".data"))); | |
ec9f9101 MS |
52 | |
53 | void __init setup_arch(char **cmdline_p) | |
54 | { | |
dc0b4335 | 55 | *cmdline_p = boot_command_line; |
ec9f9101 MS |
56 | |
57 | console_verbose(); | |
58 | ||
59 | unflatten_device_tree(); | |
60 | ||
ec9f9101 MS |
61 | setup_cpuinfo(); |
62 | ||
2ee2ff87 | 63 | microblaze_cache_init(); |
ec9f9101 | 64 | |
ec9f9101 MS |
65 | setup_memory(); |
66 | ||
e721a45f MS |
67 | #ifdef CONFIG_EARLY_PRINTK |
68 | /* remap early console to virtual address */ | |
69 | remap_early_printk(); | |
70 | #endif | |
71 | ||
733cc218 MS |
72 | xilinx_pci_init(); |
73 | ||
8c770db9 | 74 | #if defined(CONFIG_DUMMY_CONSOLE) |
ec9f9101 MS |
75 | conswitchp = &dummy_con; |
76 | #endif | |
ec9f9101 MS |
77 | } |
78 | ||
79 | #ifdef CONFIG_MTD_UCLINUX | |
80 | /* Handle both romfs and cramfs types, without generating unnecessary | |
81 | code (ie no point checking for CRAMFS if it's not even enabled) */ | |
82 | inline unsigned get_romfs_len(unsigned *addr) | |
83 | { | |
84 | #ifdef CONFIG_ROMFS_FS | |
85 | if (memcmp(&addr[0], "-rom1fs-", 8) == 0) /* romfs */ | |
86 | return be32_to_cpu(addr[2]); | |
87 | #endif | |
88 | ||
89 | #ifdef CONFIG_CRAMFS | |
90 | if (addr[0] == le32_to_cpu(0x28cd3d45)) /* cramfs */ | |
91 | return le32_to_cpu(addr[1]); | |
92 | #endif | |
93 | return 0; | |
94 | } | |
95 | #endif /* CONFIG_MTD_UCLINUX_EBSS */ | |
96 | ||
95b0f9ea MS |
97 | unsigned long kernel_tlb; |
98 | ||
ec9f9101 | 99 | void __init machine_early_init(const char *cmdline, unsigned int ram, |
95b0f9ea MS |
100 | unsigned int fdt, unsigned int msr, unsigned int tlb0, |
101 | unsigned int tlb1) | |
ec9f9101 | 102 | { |
0b9b0200 MS |
103 | unsigned long *src, *dst; |
104 | unsigned int offset = 0; | |
ec9f9101 | 105 | |
cda1fd5a MS |
106 | /* If CONFIG_MTD_UCLINUX is defined, assume ROMFS is at the |
107 | * end of kernel. There are two position which we want to check. | |
108 | * The first is __init_end and the second __bss_start. | |
109 | */ | |
110 | #ifdef CONFIG_MTD_UCLINUX | |
111 | int romfs_size; | |
112 | unsigned int romfs_base; | |
113 | char *old_klimit = klimit; | |
114 | ||
115 | romfs_base = (ram ? ram : (unsigned int)&__init_end); | |
116 | romfs_size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base)); | |
117 | if (!romfs_size) { | |
118 | romfs_base = (unsigned int)&__bss_start; | |
119 | romfs_size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base)); | |
120 | } | |
121 | ||
122 | /* Move ROMFS out of BSS before clearing it */ | |
123 | if (romfs_size > 0) { | |
363737d6 | 124 | memmove(&__bss_stop, (int *)romfs_base, romfs_size); |
cda1fd5a MS |
125 | klimit += romfs_size; |
126 | } | |
127 | #endif | |
128 | ||
ec9f9101 MS |
129 | /* clearing bss section */ |
130 | memset(__bss_start, 0, __bss_stop-__bss_start); | |
131 | memset(_ssbss, 0, _esbss-_ssbss); | |
132 | ||
ec9f9101 | 133 | /* initialize device tree for usage in early_printk */ |
7746c99f | 134 | early_init_devtree(_fdt_start); |
ec9f9101 MS |
135 | |
136 | #ifdef CONFIG_EARLY_PRINTK | |
137 | setup_early_printk(NULL); | |
138 | #endif | |
139 | ||
95b0f9ea MS |
140 | /* setup kernel_tlb after BSS cleaning |
141 | * Maybe worth to move to asm code */ | |
142 | kernel_tlb = tlb0 + tlb1; | |
143 | /* printk("TLB1 0x%08x, TLB0 0x%08x, tlb 0x%x\n", tlb0, | |
144 | tlb1, kernel_tlb); */ | |
145 | ||
6bd55f0b | 146 | pr_info("Ramdisk addr 0x%08x, ", ram); |
74510f2a | 147 | if (fdt) |
6bd55f0b | 148 | pr_info("FDT at 0x%08x\n", fdt); |
74510f2a | 149 | else |
7746c99f | 150 | pr_info("Compiled-in FDT at %p\n", _fdt_start); |
ec9f9101 MS |
151 | |
152 | #ifdef CONFIG_MTD_UCLINUX | |
6bd55f0b | 153 | pr_info("Found romfs @ 0x%08x (0x%08x)\n", |
cda1fd5a | 154 | romfs_base, romfs_size); |
6bd55f0b | 155 | pr_info("#### klimit %p ####\n", old_klimit); |
cda1fd5a MS |
156 | BUG_ON(romfs_size < 0); /* What else can we do? */ |
157 | ||
6bd55f0b | 158 | pr_info("Moved 0x%08x bytes from 0x%08x to 0x%08x\n", |
363737d6 | 159 | romfs_size, romfs_base, (unsigned)&__bss_stop); |
cda1fd5a | 160 | |
6bd55f0b | 161 | pr_info("New klimit: 0x%08x\n", (unsigned)klimit); |
ec9f9101 MS |
162 | #endif |
163 | ||
2622434e | 164 | #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR |
6bd55f0b MS |
165 | if (msr) { |
166 | pr_info("!!!Your kernel has setup MSR instruction but "); | |
167 | pr_cont("CPU don't have it %x\n", msr); | |
168 | } | |
2622434e | 169 | #else |
6bd55f0b MS |
170 | if (!msr) { |
171 | pr_info("!!!Your kernel not setup MSR instruction but "); | |
eae38104 | 172 | pr_cont("CPU have it %x\n", msr); |
6bd55f0b | 173 | } |
2622434e MS |
174 | #endif |
175 | ||
0b9b0200 MS |
176 | /* Do not copy reset vectors. offset = 0x2 means skip the first |
177 | * two instructions. dst is pointer to MB vectors which are placed | |
178 | * in block ram. If you want to copy reset vector setup offset to 0x0 */ | |
179 | #if !CONFIG_MANUAL_RESET_VECTOR | |
180 | offset = 0x2; | |
181 | #endif | |
182 | dst = (unsigned long *) (offset * sizeof(u32)); | |
183 | for (src = __ivt_start + offset; src < __ivt_end; src++, dst++) | |
ec9f9101 MS |
184 | *dst = *src; |
185 | ||
186 | /* Initialize global data */ | |
187 | per_cpu(KM, 0) = 0x1; /* We start in kernel mode */ | |
188 | per_cpu(CURRENT_SAVE, 0) = (unsigned long)current; | |
189 | } | |
190 | ||
4bcd943e MS |
191 | void __init time_init(void) |
192 | { | |
c1120542 MS |
193 | of_clk_init(NULL); |
194 | setup_cpuinfo_clk(); | |
3722ed23 | 195 | clocksource_probe(); |
4bcd943e MS |
196 | } |
197 | ||
ec9f9101 MS |
198 | #ifdef CONFIG_DEBUG_FS |
199 | struct dentry *of_debugfs_root; | |
200 | ||
201 | static int microblaze_debugfs_init(void) | |
202 | { | |
203 | of_debugfs_root = debugfs_create_dir("microblaze", NULL); | |
204 | ||
205 | return of_debugfs_root == NULL; | |
206 | } | |
207 | arch_initcall(microblaze_debugfs_init); | |
e02db0aa | 208 | |
a28d73ca | 209 | # ifdef CONFIG_MMU |
e02db0aa MS |
210 | static int __init debugfs_tlb(void) |
211 | { | |
212 | struct dentry *d; | |
213 | ||
214 | if (!of_debugfs_root) | |
215 | return -ENODEV; | |
216 | ||
217 | d = debugfs_create_u32("tlb_skip", S_IRUGO, of_debugfs_root, &tlb_skip); | |
218 | if (!d) | |
219 | return -ENOMEM; | |
5b3084b5 MS |
220 | |
221 | return 0; | |
e02db0aa MS |
222 | } |
223 | device_initcall(debugfs_tlb); | |
a28d73ca | 224 | # endif |
ec9f9101 | 225 | #endif |