diff options
Diffstat (limited to 'arch/sh/kernel/setup.c')
-rw-r--r-- | arch/sh/kernel/setup.c | 210 |
1 files changed, 38 insertions, 172 deletions
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index c2772913593..de8e6e2f2c8 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kexec.h> | 23 | #include <linux/kexec.h> |
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/io.h> | 25 | #include <asm/io.h> |
26 | #include <asm/page.h> | ||
26 | #include <asm/sections.h> | 27 | #include <asm/sections.h> |
27 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
28 | #include <asm/setup.h> | 29 | #include <asm/setup.h> |
@@ -41,20 +42,19 @@ extern void * __rd_start, * __rd_end; | |||
41 | * The bigger value means no problem. | 42 | * The bigger value means no problem. |
42 | */ | 43 | */ |
43 | struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, }; | 44 | struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, }; |
45 | |||
46 | /* | ||
47 | * The machine vector. First entry in .machvec.init, or clobbered by | ||
48 | * sh_mv= on the command line, prior to .machvec.init teardown. | ||
49 | */ | ||
50 | struct sh_machine_vector sh_mv = { .mv_name = "generic", }; | ||
51 | |||
44 | #ifdef CONFIG_VT | 52 | #ifdef CONFIG_VT |
45 | struct screen_info screen_info; | 53 | struct screen_info screen_info; |
46 | #endif | 54 | #endif |
47 | 55 | ||
48 | #if defined(CONFIG_SH_UNKNOWN) | ||
49 | struct sh_machine_vector sh_mv; | ||
50 | #endif | ||
51 | |||
52 | extern int root_mountflags; | 56 | extern int root_mountflags; |
53 | 57 | ||
54 | #define MV_NAME_SIZE 32 | ||
55 | |||
56 | static struct sh_machine_vector* __init get_mv_byname(const char* name); | ||
57 | |||
58 | /* | 58 | /* |
59 | * This is set up by the setup-routine at boot-time | 59 | * This is set up by the setup-routine at boot-time |
60 | */ | 60 | */ |
@@ -80,131 +80,17 @@ static struct resource data_resource = { .name = "Kernel data", }; | |||
80 | 80 | ||
81 | unsigned long memory_start, memory_end; | 81 | unsigned long memory_start, memory_end; |
82 | 82 | ||
83 | static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], | 83 | static int __init early_parse_mem(char *p) |
84 | struct sh_machine_vector** mvp, | ||
85 | unsigned long *mv_io_base) | ||
86 | { | 84 | { |
87 | char c = ' ', *to = command_line, *from = COMMAND_LINE; | 85 | unsigned long size; |
88 | int len = 0; | ||
89 | |||
90 | /* Save unparsed command line copy for /proc/cmdline */ | ||
91 | memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); | ||
92 | boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; | ||
93 | 86 | ||
94 | memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; | 87 | memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; |
95 | memory_end = memory_start + __MEMORY_SIZE; | 88 | size = memparse(p, &p); |
96 | 89 | memory_end = memory_start + size; | |
97 | for (;;) { | ||
98 | /* | ||
99 | * "mem=XXX[kKmM]" defines a size of memory. | ||
100 | */ | ||
101 | if (c == ' ' && !memcmp(from, "mem=", 4)) { | ||
102 | if (to != command_line) | ||
103 | to--; | ||
104 | { | ||
105 | unsigned long mem_size; | ||
106 | |||
107 | mem_size = memparse(from+4, &from); | ||
108 | memory_end = memory_start + mem_size; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (c == ' ' && !memcmp(from, "sh_mv=", 6)) { | ||
113 | char* mv_end; | ||
114 | char* mv_comma; | ||
115 | int mv_len; | ||
116 | if (to != command_line) | ||
117 | to--; | ||
118 | from += 6; | ||
119 | mv_end = strchr(from, ' '); | ||
120 | if (mv_end == NULL) | ||
121 | mv_end = from + strlen(from); | ||
122 | |||
123 | mv_comma = strchr(from, ','); | ||
124 | if ((mv_comma != NULL) && (mv_comma < mv_end)) { | ||
125 | int ints[3]; | ||
126 | get_options(mv_comma+1, ARRAY_SIZE(ints), ints); | ||
127 | *mv_io_base = ints[1]; | ||
128 | mv_len = mv_comma - from; | ||
129 | } else { | ||
130 | mv_len = mv_end - from; | ||
131 | } | ||
132 | if (mv_len > (MV_NAME_SIZE-1)) | ||
133 | mv_len = MV_NAME_SIZE-1; | ||
134 | memcpy(mv_name, from, mv_len); | ||
135 | mv_name[mv_len] = '\0'; | ||
136 | from = mv_end; | ||
137 | |||
138 | *mvp = get_mv_byname(mv_name); | ||
139 | } | ||
140 | |||
141 | c = *(from++); | ||
142 | if (!c) | ||
143 | break; | ||
144 | if (COMMAND_LINE_SIZE <= ++len) | ||
145 | break; | ||
146 | *(to++) = c; | ||
147 | } | ||
148 | *to = '\0'; | ||
149 | *cmdline_p = command_line; | ||
150 | } | ||
151 | |||
152 | static int __init sh_mv_setup(char **cmdline_p) | ||
153 | { | ||
154 | #ifdef CONFIG_SH_UNKNOWN | ||
155 | extern struct sh_machine_vector mv_unknown; | ||
156 | #endif | ||
157 | struct sh_machine_vector *mv = NULL; | ||
158 | char mv_name[MV_NAME_SIZE] = ""; | ||
159 | unsigned long mv_io_base = 0; | ||
160 | |||
161 | parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base); | ||
162 | |||
163 | #ifdef CONFIG_SH_UNKNOWN | ||
164 | if (mv == NULL) { | ||
165 | mv = &mv_unknown; | ||
166 | if (*mv_name != '\0') { | ||
167 | printk("Warning: Unsupported machine %s, using unknown\n", | ||
168 | mv_name); | ||
169 | } | ||
170 | } | ||
171 | sh_mv = *mv; | ||
172 | #endif | ||
173 | |||
174 | /* | ||
175 | * Manually walk the vec, fill in anything that the board hasn't yet | ||
176 | * by hand, wrapping to the generic implementation. | ||
177 | */ | ||
178 | #define mv_set(elem) do { \ | ||
179 | if (!sh_mv.mv_##elem) \ | ||
180 | sh_mv.mv_##elem = generic_##elem; \ | ||
181 | } while (0) | ||
182 | |||
183 | mv_set(inb); mv_set(inw); mv_set(inl); | ||
184 | mv_set(outb); mv_set(outw); mv_set(outl); | ||
185 | |||
186 | mv_set(inb_p); mv_set(inw_p); mv_set(inl_p); | ||
187 | mv_set(outb_p); mv_set(outw_p); mv_set(outl_p); | ||
188 | |||
189 | mv_set(insb); mv_set(insw); mv_set(insl); | ||
190 | mv_set(outsb); mv_set(outsw); mv_set(outsl); | ||
191 | |||
192 | mv_set(readb); mv_set(readw); mv_set(readl); | ||
193 | mv_set(writeb); mv_set(writew); mv_set(writel); | ||
194 | |||
195 | mv_set(ioport_map); | ||
196 | mv_set(ioport_unmap); | ||
197 | mv_set(irq_demux); | ||
198 | |||
199 | #ifdef CONFIG_SH_UNKNOWN | ||
200 | __set_io_port_base(mv_io_base); | ||
201 | #endif | ||
202 | |||
203 | if (!sh_mv.mv_nr_irqs) | ||
204 | sh_mv.mv_nr_irqs = NR_IRQS; | ||
205 | 90 | ||
206 | return 0; | 91 | return 0; |
207 | } | 92 | } |
93 | early_param("mem", early_parse_mem); | ||
208 | 94 | ||
209 | /* | 95 | /* |
210 | * Register fully available low RAM pages with the bootmem allocator. | 96 | * Register fully available low RAM pages with the bootmem allocator. |
@@ -230,7 +116,7 @@ static void __init register_bootmem_low_pages(void) | |||
230 | free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); | 116 | free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); |
231 | } | 117 | } |
232 | 118 | ||
233 | void __init setup_bootmem_allocator(unsigned long start_pfn) | 119 | void __init setup_bootmem_allocator(unsigned long free_pfn) |
234 | { | 120 | { |
235 | unsigned long bootmap_size; | 121 | unsigned long bootmap_size; |
236 | 122 | ||
@@ -239,9 +125,10 @@ void __init setup_bootmem_allocator(unsigned long start_pfn) | |||
239 | * bootstrap step all allocations (until the page allocator | 125 | * bootstrap step all allocations (until the page allocator |
240 | * is intact) must be done via bootmem_alloc(). | 126 | * is intact) must be done via bootmem_alloc(). |
241 | */ | 127 | */ |
242 | bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, | 128 | bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn, |
243 | min_low_pfn, max_low_pfn); | 129 | min_low_pfn, max_low_pfn); |
244 | 130 | ||
131 | add_active_range(0, min_low_pfn, max_low_pfn); | ||
245 | register_bootmem_low_pages(); | 132 | register_bootmem_low_pages(); |
246 | 133 | ||
247 | node_set_online(0); | 134 | node_set_online(0); |
@@ -254,7 +141,7 @@ void __init setup_bootmem_allocator(unsigned long start_pfn) | |||
254 | * an invalid RAM area. | 141 | * an invalid RAM area. |
255 | */ | 142 | */ |
256 | reserve_bootmem(__MEMORY_START+PAGE_SIZE, | 143 | reserve_bootmem(__MEMORY_START+PAGE_SIZE, |
257 | (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START); | 144 | (PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START); |
258 | 145 | ||
259 | /* | 146 | /* |
260 | * reserve physical page 0 - it's a special BIOS page on many boxes, | 147 | * reserve physical page 0 - it's a special BIOS page on many boxes, |
@@ -262,6 +149,8 @@ void __init setup_bootmem_allocator(unsigned long start_pfn) | |||
262 | */ | 149 | */ |
263 | reserve_bootmem(__MEMORY_START, PAGE_SIZE); | 150 | reserve_bootmem(__MEMORY_START, PAGE_SIZE); |
264 | 151 | ||
152 | sparse_memory_present_with_active_regions(0); | ||
153 | |||
265 | #ifdef CONFIG_BLK_DEV_INITRD | 154 | #ifdef CONFIG_BLK_DEV_INITRD |
266 | ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); | 155 | ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); |
267 | if (&__rd_start != &__rd_end) { | 156 | if (&__rd_start != &__rd_end) { |
@@ -315,10 +204,6 @@ void __init setup_arch(char **cmdline_p) | |||
315 | { | 204 | { |
316 | enable_mmu(); | 205 | enable_mmu(); |
317 | 206 | ||
318 | #ifdef CONFIG_CMDLINE_BOOL | ||
319 | strcpy(COMMAND_LINE, CONFIG_CMDLINE); | ||
320 | #endif | ||
321 | |||
322 | ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); | 207 | ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); |
323 | 208 | ||
324 | #ifdef CONFIG_BLK_DEV_RAM | 209 | #ifdef CONFIG_BLK_DEV_RAM |
@@ -339,9 +224,22 @@ void __init setup_arch(char **cmdline_p) | |||
339 | data_resource.start = virt_to_phys(_etext); | 224 | data_resource.start = virt_to_phys(_etext); |
340 | data_resource.end = virt_to_phys(_edata)-1; | 225 | data_resource.end = virt_to_phys(_edata)-1; |
341 | 226 | ||
227 | memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; | ||
228 | memory_end = memory_start + __MEMORY_SIZE; | ||
229 | |||
230 | #ifdef CONFIG_CMDLINE_BOOL | ||
231 | strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line)); | ||
232 | #else | ||
233 | strlcpy(command_line, COMMAND_LINE, sizeof(command_line)); | ||
234 | #endif | ||
235 | |||
236 | /* Save unparsed command line copy for /proc/cmdline */ | ||
237 | memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | ||
238 | *cmdline_p = command_line; | ||
239 | |||
342 | parse_early_param(); | 240 | parse_early_param(); |
343 | 241 | ||
344 | sh_mv_setup(cmdline_p); | 242 | sh_mv_setup(); |
345 | 243 | ||
346 | /* | 244 | /* |
347 | * Find the highest page frame number we have available | 245 | * Find the highest page frame number we have available |
@@ -355,8 +253,9 @@ void __init setup_arch(char **cmdline_p) | |||
355 | min_low_pfn = __MEMORY_START >> PAGE_SHIFT; | 253 | min_low_pfn = __MEMORY_START >> PAGE_SHIFT; |
356 | 254 | ||
357 | nodes_clear(node_online_map); | 255 | nodes_clear(node_online_map); |
256 | |||
257 | /* Setup bootmem with available RAM */ | ||
358 | setup_memory(); | 258 | setup_memory(); |
359 | paging_init(); | ||
360 | sparse_init(); | 259 | sparse_init(); |
361 | 260 | ||
362 | #ifdef CONFIG_DUMMY_CONSOLE | 261 | #ifdef CONFIG_DUMMY_CONSOLE |
@@ -366,46 +265,13 @@ void __init setup_arch(char **cmdline_p) | |||
366 | /* Perform the machine specific initialisation */ | 265 | /* Perform the machine specific initialisation */ |
367 | if (likely(sh_mv.mv_setup)) | 266 | if (likely(sh_mv.mv_setup)) |
368 | sh_mv.mv_setup(cmdline_p); | 267 | sh_mv.mv_setup(cmdline_p); |
369 | } | ||
370 | |||
371 | struct sh_machine_vector* __init get_mv_byname(const char* name) | ||
372 | { | ||
373 | extern long __machvec_start, __machvec_end; | ||
374 | struct sh_machine_vector *all_vecs = | ||
375 | (struct sh_machine_vector *)&__machvec_start; | ||
376 | |||
377 | int i, n = ((unsigned long)&__machvec_end | ||
378 | - (unsigned long)&__machvec_start)/ | ||
379 | sizeof(struct sh_machine_vector); | ||
380 | |||
381 | for (i = 0; i < n; ++i) { | ||
382 | struct sh_machine_vector *mv = &all_vecs[i]; | ||
383 | if (mv == NULL) | ||
384 | continue; | ||
385 | if (strcasecmp(name, get_system_type()) == 0) { | ||
386 | return mv; | ||
387 | } | ||
388 | } | ||
389 | return NULL; | ||
390 | } | ||
391 | |||
392 | static struct cpu cpu[NR_CPUS]; | ||
393 | |||
394 | static int __init topology_init(void) | ||
395 | { | ||
396 | int cpu_id; | ||
397 | 268 | ||
398 | for_each_possible_cpu(cpu_id) | 269 | paging_init(); |
399 | register_cpu(&cpu[cpu_id], cpu_id); | ||
400 | |||
401 | return 0; | ||
402 | } | 270 | } |
403 | 271 | ||
404 | subsys_initcall(topology_init); | ||
405 | |||
406 | static const char *cpu_name[] = { | 272 | static const char *cpu_name[] = { |
407 | [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", | 273 | [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", |
408 | [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300", | 274 | [CPU_SH7300] = "SH7300", |
409 | [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", | 275 | [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", |
410 | [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", | 276 | [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", |
411 | [CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710", | 277 | [CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710", |
@@ -419,7 +285,7 @@ static const char *cpu_name[] = { | |||
419 | [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", | 285 | [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", |
420 | [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", | 286 | [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", |
421 | [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", | 287 | [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", |
422 | [CPU_SH_NONE] = "Unknown" | 288 | [CPU_SHX3] = "SH-X3", [CPU_SH_NONE] = "Unknown" |
423 | }; | 289 | }; |
424 | 290 | ||
425 | const char *get_cpu_subtype(struct sh_cpuinfo *c) | 291 | const char *get_cpu_subtype(struct sh_cpuinfo *c) |