diff options
Diffstat (limited to 'arch/mn10300/kernel/setup.c')
-rw-r--r-- | arch/mn10300/kernel/setup.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c new file mode 100644 index 000000000000..6b7ce2636851 --- /dev/null +++ b/arch/mn10300/kernel/setup.c | |||
@@ -0,0 +1,298 @@ | |||
1 | /* MN10300 Arch-specific initialisation | ||
2 | * | ||
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/mm.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/unistd.h> | ||
17 | #include <linux/ptrace.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/user.h> | ||
20 | #include <linux/a.out.h> | ||
21 | #include <linux/tty.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/bootmem.h> | ||
26 | #include <linux/seq_file.h> | ||
27 | #include <asm/processor.h> | ||
28 | #include <linux/console.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/setup.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <asm/smp.h> | ||
34 | #include <asm/proc/proc.h> | ||
35 | #include <asm/busctl-regs.h> | ||
36 | #include <asm/fpu.h> | ||
37 | #include <asm/sections.h> | ||
38 | |||
39 | struct mn10300_cpuinfo boot_cpu_data; | ||
40 | |||
41 | /* For PCI or other memory-mapped resources */ | ||
42 | unsigned long pci_mem_start = 0x18000000; | ||
43 | |||
44 | char redboot_command_line[COMMAND_LINE_SIZE] = | ||
45 | "console=ttyS0,115200 root=/dev/mtdblock3 rw"; | ||
46 | |||
47 | char __initdata redboot_platform_name[COMMAND_LINE_SIZE]; | ||
48 | |||
49 | static struct resource code_resource = { | ||
50 | .start = 0x100000, | ||
51 | .end = 0, | ||
52 | .name = "Kernel code", | ||
53 | }; | ||
54 | |||
55 | static struct resource data_resource = { | ||
56 | .start = 0, | ||
57 | .end = 0, | ||
58 | .name = "Kernel data", | ||
59 | }; | ||
60 | |||
61 | static unsigned long __initdata phys_memory_base; | ||
62 | static unsigned long __initdata phys_memory_end; | ||
63 | static unsigned long __initdata memory_end; | ||
64 | unsigned long memory_size; | ||
65 | |||
66 | struct thread_info *__current_ti = &init_thread_union.thread_info; | ||
67 | struct task_struct *__current = &init_task; | ||
68 | |||
69 | #define mn10300_known_cpus 3 | ||
70 | static const char *const mn10300_cputypes[] = { | ||
71 | "am33v1", | ||
72 | "am33v2", | ||
73 | "am34v1", | ||
74 | "unknown" | ||
75 | }; | ||
76 | |||
77 | /* | ||
78 | * | ||
79 | */ | ||
80 | static void __init parse_mem_cmdline(char **cmdline_p) | ||
81 | { | ||
82 | char *from, *to, c; | ||
83 | |||
84 | /* save unparsed command line copy for /proc/cmdline */ | ||
85 | strcpy(boot_command_line, redboot_command_line); | ||
86 | |||
87 | /* see if there's an explicit memory size option */ | ||
88 | from = redboot_command_line; | ||
89 | to = redboot_command_line; | ||
90 | c = ' '; | ||
91 | |||
92 | for (;;) { | ||
93 | if (c == ' ' && !memcmp(from, "mem=", 4)) { | ||
94 | if (to != redboot_command_line) | ||
95 | to--; | ||
96 | memory_size = memparse(from + 4, &from); | ||
97 | } | ||
98 | |||
99 | c = *(from++); | ||
100 | if (!c) | ||
101 | break; | ||
102 | |||
103 | *(to++) = c; | ||
104 | } | ||
105 | |||
106 | *to = '\0'; | ||
107 | *cmdline_p = redboot_command_line; | ||
108 | |||
109 | if (memory_size == 0) | ||
110 | panic("Memory size not known\n"); | ||
111 | |||
112 | memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS + | ||
113 | memory_size; | ||
114 | if (memory_end > phys_memory_end) | ||
115 | memory_end = phys_memory_end; | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * architecture specific setup | ||
120 | */ | ||
121 | void __init setup_arch(char **cmdline_p) | ||
122 | { | ||
123 | unsigned long bootmap_size; | ||
124 | unsigned long kstart_pfn, start_pfn, free_pfn, end_pfn; | ||
125 | |||
126 | cpu_init(); | ||
127 | unit_setup(); | ||
128 | parse_mem_cmdline(cmdline_p); | ||
129 | |||
130 | init_mm.start_code = (unsigned long)&_text; | ||
131 | init_mm.end_code = (unsigned long) &_etext; | ||
132 | init_mm.end_data = (unsigned long) &_edata; | ||
133 | init_mm.brk = (unsigned long) &_end; | ||
134 | |||
135 | code_resource.start = virt_to_bus(&_text); | ||
136 | code_resource.end = virt_to_bus(&_etext)-1; | ||
137 | data_resource.start = virt_to_bus(&_etext); | ||
138 | data_resource.end = virt_to_bus(&_edata)-1; | ||
139 | |||
140 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
141 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
142 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
143 | |||
144 | start_pfn = (CONFIG_KERNEL_RAM_BASE_ADDRESS >> PAGE_SHIFT); | ||
145 | kstart_pfn = PFN_UP(__pa(&_text)); | ||
146 | free_pfn = PFN_UP(__pa(&_end)); | ||
147 | end_pfn = PFN_DOWN(__pa(memory_end)); | ||
148 | |||
149 | bootmap_size = init_bootmem_node(&contig_page_data, | ||
150 | free_pfn, | ||
151 | start_pfn, | ||
152 | end_pfn); | ||
153 | |||
154 | if (kstart_pfn > start_pfn) | ||
155 | free_bootmem(PFN_PHYS(start_pfn), | ||
156 | PFN_PHYS(kstart_pfn - start_pfn)); | ||
157 | |||
158 | free_bootmem(PFN_PHYS(free_pfn), | ||
159 | PFN_PHYS(end_pfn - free_pfn)); | ||
160 | |||
161 | /* If interrupt vector table is in main ram, then we need to | ||
162 | reserve the page it is occupying. */ | ||
163 | if (CONFIG_INTERRUPT_VECTOR_BASE >= CONFIG_KERNEL_RAM_BASE_ADDRESS && | ||
164 | CONFIG_INTERRUPT_VECTOR_BASE < memory_end) | ||
165 | reserve_bootmem(CONFIG_INTERRUPT_VECTOR_BASE, 1, | ||
166 | BOOTMEM_DEFAULT); | ||
167 | |||
168 | reserve_bootmem(PAGE_ALIGN(PFN_PHYS(free_pfn)), bootmap_size, | ||
169 | BOOTMEM_DEFAULT); | ||
170 | |||
171 | #ifdef CONFIG_VT | ||
172 | #if defined(CONFIG_VGA_CONSOLE) | ||
173 | conswitchp = &vga_con; | ||
174 | #elif defined(CONFIG_DUMMY_CONSOLE) | ||
175 | conswitchp = &dummy_con; | ||
176 | #endif | ||
177 | #endif | ||
178 | |||
179 | paging_init(); | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * perform CPU initialisation | ||
184 | */ | ||
185 | void __init cpu_init(void) | ||
186 | { | ||
187 | unsigned long cpurev = CPUREV, type; | ||
188 | unsigned long base, size; | ||
189 | |||
190 | type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; | ||
191 | if (type > mn10300_known_cpus) | ||
192 | type = mn10300_known_cpus; | ||
193 | |||
194 | printk(KERN_INFO "Matsushita %s, rev %ld\n", | ||
195 | mn10300_cputypes[type], | ||
196 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S); | ||
197 | |||
198 | /* determine the memory size and base from the memory controller regs */ | ||
199 | memory_size = 0; | ||
200 | |||
201 | base = SDBASE(0); | ||
202 | if (base & SDBASE_CE) { | ||
203 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
204 | size = ~size + 1; | ||
205 | base &= SDBASE_CBA; | ||
206 | |||
207 | printk(KERN_INFO "SDRAM[0]: %luMb @%08lx\n", size >> 20, base); | ||
208 | memory_size += size; | ||
209 | phys_memory_base = base; | ||
210 | } | ||
211 | |||
212 | base = SDBASE(1); | ||
213 | if (base & SDBASE_CE) { | ||
214 | size = (base & SDBASE_CBAM) << SDBASE_CBAM_SHIFT; | ||
215 | size = ~size + 1; | ||
216 | base &= SDBASE_CBA; | ||
217 | |||
218 | printk(KERN_INFO "SDRAM[1]: %luMb @%08lx\n", size >> 20, base); | ||
219 | memory_size += size; | ||
220 | if (phys_memory_base == 0) | ||
221 | phys_memory_base = base; | ||
222 | } | ||
223 | |||
224 | phys_memory_end = phys_memory_base + memory_size; | ||
225 | |||
226 | #ifdef CONFIG_FPU | ||
227 | fpu_init_state(); | ||
228 | #endif | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * Get CPU information for use by the procfs. | ||
233 | */ | ||
234 | static int show_cpuinfo(struct seq_file *m, void *v) | ||
235 | { | ||
236 | unsigned long cpurev = CPUREV, type, icachesz, dcachesz; | ||
237 | |||
238 | type = (CPUREV & CPUREV_TYPE) >> CPUREV_TYPE_S; | ||
239 | if (type > mn10300_known_cpus) | ||
240 | type = mn10300_known_cpus; | ||
241 | |||
242 | icachesz = | ||
243 | ((cpurev & CPUREV_ICWAY ) >> CPUREV_ICWAY_S) * | ||
244 | ((cpurev & CPUREV_ICSIZE) >> CPUREV_ICSIZE_S) * | ||
245 | 1024; | ||
246 | |||
247 | dcachesz = | ||
248 | ((cpurev & CPUREV_DCWAY ) >> CPUREV_DCWAY_S) * | ||
249 | ((cpurev & CPUREV_DCSIZE) >> CPUREV_DCSIZE_S) * | ||
250 | 1024; | ||
251 | |||
252 | seq_printf(m, | ||
253 | "processor : 0\n" | ||
254 | "vendor_id : Matsushita\n" | ||
255 | "cpu core : %s\n" | ||
256 | "cpu rev : %lu\n" | ||
257 | "model name : " PROCESSOR_MODEL_NAME "\n" | ||
258 | "icache size: %lu\n" | ||
259 | "dcache size: %lu\n", | ||
260 | mn10300_cputypes[type], | ||
261 | (cpurev & CPUREV_REVISION) >> CPUREV_REVISION_S, | ||
262 | icachesz, | ||
263 | dcachesz | ||
264 | ); | ||
265 | |||
266 | seq_printf(m, | ||
267 | "ioclk speed: %lu.%02luMHz\n" | ||
268 | "bogomips : %lu.%02lu\n\n", | ||
269 | MN10300_IOCLK / 1000000, | ||
270 | (MN10300_IOCLK / 10000) % 100, | ||
271 | loops_per_jiffy / (500000 / HZ), | ||
272 | (loops_per_jiffy / (5000 / HZ)) % 100 | ||
273 | ); | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
279 | { | ||
280 | return *pos < NR_CPUS ? cpu_data + *pos : NULL; | ||
281 | } | ||
282 | |||
283 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
284 | { | ||
285 | ++*pos; | ||
286 | return c_start(m, pos); | ||
287 | } | ||
288 | |||
289 | static void c_stop(struct seq_file *m, void *v) | ||
290 | { | ||
291 | } | ||
292 | |||
293 | struct seq_operations cpuinfo_op = { | ||
294 | .start = c_start, | ||
295 | .next = c_next, | ||
296 | .stop = c_stop, | ||
297 | .show = show_cpuinfo, | ||
298 | }; | ||