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> |
12 | #include <linux/of_clk.h> |
13 | #include <linux/clocksource.h> |
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> |
20 | #include <linux/of_fdt.h> |
21 | #include <linux/pgtable.h> |
22 | |
23 | #include <asm/setup.h> |
24 | #include <asm/sections.h> |
25 | #include <asm/page.h> |
26 | #include <linux/io.h> |
27 | #include <linux/bug.h> |
28 | #include <linux/param.h> |
29 | #include <linux/pci.h> |
30 | #include <linux/cache.h> |
31 | #include <linux/of.h> |
32 | #include <linux/dma-mapping.h> |
33 | #include <asm/cacheflush.h> |
34 | #include <asm/entry.h> |
35 | #include <asm/cpuinfo.h> |
36 | |
37 | |
38 | DEFINE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */ |
39 | DEFINE_PER_CPU(unsigned int, KM); /* Kernel/user mode */ |
40 | DEFINE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */ |
41 | DEFINE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */ |
42 | DEFINE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */ |
43 | |
44 | /* |
45 | * Placed cmd_line to .data section because can be initialized from |
46 | * ASM code. Default position is BSS section which is cleared |
47 | * in machine_early_init(). |
48 | */ |
49 | char cmd_line[COMMAND_LINE_SIZE] __section(".data" ); |
50 | |
51 | void __init setup_arch(char **cmdline_p) |
52 | { |
53 | *cmdline_p = boot_command_line; |
54 | |
55 | setup_memory(); |
56 | |
57 | console_verbose(); |
58 | |
59 | unflatten_device_tree(); |
60 | |
61 | setup_cpuinfo(); |
62 | |
63 | microblaze_cache_init(); |
64 | |
65 | xilinx_pci_init(); |
66 | } |
67 | |
68 | #ifdef CONFIG_MTD_UCLINUX |
69 | /* Handle both romfs and cramfs types, without generating unnecessary |
70 | code (ie no point checking for CRAMFS if it's not even enabled) */ |
71 | inline unsigned get_romfs_len(unsigned *addr) |
72 | { |
73 | #ifdef CONFIG_ROMFS_FS |
74 | if (memcmp(&addr[0], "-rom1fs-" , 8) == 0) /* romfs */ |
75 | return be32_to_cpu(addr[2]); |
76 | #endif |
77 | |
78 | #ifdef CONFIG_CRAMFS |
79 | if (addr[0] == le32_to_cpu(0x28cd3d45)) /* cramfs */ |
80 | return le32_to_cpu(addr[1]); |
81 | #endif |
82 | return 0; |
83 | } |
84 | #endif /* CONFIG_MTD_UCLINUX_EBSS */ |
85 | |
86 | unsigned long kernel_tlb; |
87 | |
88 | void __init machine_early_init(const char *cmdline, unsigned int ram, |
89 | unsigned int fdt, unsigned int msr, unsigned int tlb0, |
90 | unsigned int tlb1) |
91 | { |
92 | unsigned long *src, *dst; |
93 | unsigned int offset = 0; |
94 | |
95 | /* If CONFIG_MTD_UCLINUX is defined, assume ROMFS is at the |
96 | * end of kernel. There are two position which we want to check. |
97 | * The first is __init_end and the second __bss_start. |
98 | */ |
99 | #ifdef CONFIG_MTD_UCLINUX |
100 | int romfs_size; |
101 | unsigned int romfs_base; |
102 | char *old_klimit = klimit; |
103 | |
104 | romfs_base = (ram ? ram : (unsigned int)&__init_end); |
105 | romfs_size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base)); |
106 | if (!romfs_size) { |
107 | romfs_base = (unsigned int)&__bss_start; |
108 | romfs_size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base)); |
109 | } |
110 | |
111 | /* Move ROMFS out of BSS before clearing it */ |
112 | if (romfs_size > 0) { |
113 | memmove(&__bss_stop, (int *)romfs_base, romfs_size); |
114 | klimit += romfs_size; |
115 | } |
116 | #endif |
117 | |
118 | /* clearing bss section */ |
119 | memset(__bss_start, 0, __bss_stop-__bss_start); |
120 | memset(_ssbss, 0, _esbss-_ssbss); |
121 | |
122 | /* initialize device tree for usage in early_printk */ |
123 | early_init_devtree(_fdt_start); |
124 | |
125 | /* setup kernel_tlb after BSS cleaning |
126 | * Maybe worth to move to asm code */ |
127 | kernel_tlb = tlb0 + tlb1; |
128 | /* printk("TLB1 0x%08x, TLB0 0x%08x, tlb 0x%x\n", tlb0, |
129 | tlb1, kernel_tlb); */ |
130 | |
131 | pr_info("Ramdisk addr 0x%08x, " , ram); |
132 | if (fdt) |
133 | pr_info("FDT at 0x%08x\n" , fdt); |
134 | else |
135 | pr_info("Compiled-in FDT at %p\n" , _fdt_start); |
136 | |
137 | #ifdef CONFIG_MTD_UCLINUX |
138 | pr_info("Found romfs @ 0x%08x (0x%08x)\n" , |
139 | romfs_base, romfs_size); |
140 | pr_info("#### klimit %p ####\n" , old_klimit); |
141 | BUG_ON(romfs_size < 0); /* What else can we do? */ |
142 | |
143 | pr_info("Moved 0x%08x bytes from 0x%08x to 0x%08x\n" , |
144 | romfs_size, romfs_base, (unsigned)&__bss_stop); |
145 | |
146 | pr_info("New klimit: 0x%08x\n" , (unsigned)klimit); |
147 | #endif |
148 | |
149 | #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR |
150 | if (msr) { |
151 | pr_info("!!!Your kernel has setup MSR instruction but " ); |
152 | pr_cont("CPU don't have it %x\n" , msr); |
153 | } |
154 | #else |
155 | if (!msr) { |
156 | pr_info("!!!Your kernel not setup MSR instruction but " ); |
157 | pr_cont("CPU have it %x\n" , msr); |
158 | } |
159 | #endif |
160 | |
161 | /* Do not copy reset vectors. offset = 0x2 means skip the first |
162 | * two instructions. dst is pointer to MB vectors which are placed |
163 | * in block ram. If you want to copy reset vector setup offset to 0x0 */ |
164 | #if !CONFIG_MANUAL_RESET_VECTOR |
165 | offset = 0x2; |
166 | #endif |
167 | dst = (unsigned long *) (offset * sizeof(u32)); |
168 | for (src = __ivt_start + offset; src < __ivt_end; src++, dst++) |
169 | *dst = *src; |
170 | |
171 | /* Initialize global data */ |
172 | per_cpu(KM, 0) = 0x1; /* We start in kernel mode */ |
173 | per_cpu(CURRENT_SAVE, 0) = (unsigned long)current; |
174 | } |
175 | |
176 | void __init time_init(void) |
177 | { |
178 | of_clk_init(NULL); |
179 | setup_cpuinfo_clk(); |
180 | timer_probe(); |
181 | } |
182 | |
183 | #ifdef CONFIG_DEBUG_FS |
184 | struct dentry *of_debugfs_root; |
185 | |
186 | static int microblaze_debugfs_init(void) |
187 | { |
188 | of_debugfs_root = debugfs_create_dir(name: "microblaze" , NULL); |
189 | return 0; |
190 | } |
191 | arch_initcall(microblaze_debugfs_init); |
192 | |
193 | static int __init debugfs_tlb(void) |
194 | { |
195 | debugfs_create_u32(name: "tlb_skip" , S_IRUGO, parent: of_debugfs_root, value: &tlb_skip); |
196 | return 0; |
197 | } |
198 | device_initcall(debugfs_tlb); |
199 | #endif |
200 | |