diff options
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/sh/kernel/machvec.c | 105 | ||||
-rw-r--r-- | arch/sh/kernel/setup.c | 162 | ||||
-rw-r--r-- | arch/sh/kernel/vmlinux.lds.S | 3 |
4 files changed, 122 insertions, 150 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index fb623e5d1857..1f141a8ba17c 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | extra-y := head.o init_task.o vmlinux.lds | 5 | extra-y := head.o init_task.o vmlinux.lds |
6 | 6 | ||
7 | obj-y := debugtraps.o io.o io_generic.o irq.o process.o ptrace.o \ | 7 | obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process.o ptrace.o \ |
8 | semaphore.o setup.o signal.o sys_sh.o syscalls.o \ | 8 | semaphore.o setup.o signal.o sys_sh.o syscalls.o \ |
9 | time.o topology.o traps.o | 9 | time.o topology.o traps.o |
10 | 10 | ||
diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c new file mode 100644 index 000000000000..1e78191154e3 --- /dev/null +++ b/arch/sh/kernel/machvec.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/machvec.c | ||
3 | * | ||
4 | * The SuperH machine vector setup handlers, yanked from setup.c | ||
5 | * | ||
6 | * Copyright (C) 1999 Niibe Yutaka | ||
7 | * Copyright (C) 2002 - 2007 Paul Mundt | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <asm/machvec.h> | ||
16 | #include <asm/sections.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/irq.h> | ||
19 | |||
20 | #define MV_NAME_SIZE 32 | ||
21 | |||
22 | #define for_each_mv(mv) \ | ||
23 | for ((mv) = (struct sh_machine_vector *)&__machvec_start; \ | ||
24 | (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \ | ||
25 | (mv)++) | ||
26 | |||
27 | static struct sh_machine_vector * __init get_mv_byname(const char *name) | ||
28 | { | ||
29 | struct sh_machine_vector *mv; | ||
30 | |||
31 | for_each_mv(mv) | ||
32 | if (strcasecmp(name, get_system_type()) == 0) | ||
33 | return mv; | ||
34 | |||
35 | return NULL; | ||
36 | } | ||
37 | |||
38 | static int __init early_parse_mv(char *from) | ||
39 | { | ||
40 | char mv_name[MV_NAME_SIZE] = ""; | ||
41 | char *mv_end; | ||
42 | char *mv_comma; | ||
43 | int mv_len; | ||
44 | struct sh_machine_vector *mvp; | ||
45 | |||
46 | mv_end = strchr(from, ' '); | ||
47 | if (mv_end == NULL) | ||
48 | mv_end = from + strlen(from); | ||
49 | |||
50 | mv_comma = strchr(from, ','); | ||
51 | mv_len = mv_end - from; | ||
52 | if (mv_len > (MV_NAME_SIZE-1)) | ||
53 | mv_len = MV_NAME_SIZE-1; | ||
54 | memcpy(mv_name, from, mv_len); | ||
55 | mv_name[mv_len] = '\0'; | ||
56 | from = mv_end; | ||
57 | |||
58 | if (strcmp(sh_mv.mv_name, mv_name) != 0) { | ||
59 | mvp = get_mv_byname(mv_name); | ||
60 | if (unlikely(!mvp)) { | ||
61 | printk("Available vectors:\n\n\t"); | ||
62 | for_each_mv(mvp) | ||
63 | printk("'%s', ", mvp->mv_name); | ||
64 | printk("\n\n"); | ||
65 | panic("Failed to select machvec '%s' -- halting.\n", | ||
66 | mv_name); | ||
67 | } else | ||
68 | sh_mv = *mvp; | ||
69 | } | ||
70 | |||
71 | printk(KERN_NOTICE "Booting machvec: %s\n", sh_mv.mv_name); | ||
72 | return 0; | ||
73 | } | ||
74 | early_param("sh_mv", early_parse_mv); | ||
75 | |||
76 | void __init sh_mv_setup(void) | ||
77 | { | ||
78 | /* | ||
79 | * Manually walk the vec, fill in anything that the board hasn't yet | ||
80 | * by hand, wrapping to the generic implementation. | ||
81 | */ | ||
82 | #define mv_set(elem) do { \ | ||
83 | if (!sh_mv.mv_##elem) \ | ||
84 | sh_mv.mv_##elem = generic_##elem; \ | ||
85 | } while (0) | ||
86 | |||
87 | mv_set(inb); mv_set(inw); mv_set(inl); | ||
88 | mv_set(outb); mv_set(outw); mv_set(outl); | ||
89 | |||
90 | mv_set(inb_p); mv_set(inw_p); mv_set(inl_p); | ||
91 | mv_set(outb_p); mv_set(outw_p); mv_set(outl_p); | ||
92 | |||
93 | mv_set(insb); mv_set(insw); mv_set(insl); | ||
94 | mv_set(outsb); mv_set(outsw); mv_set(outsl); | ||
95 | |||
96 | mv_set(readb); mv_set(readw); mv_set(readl); | ||
97 | mv_set(writeb); mv_set(writew); mv_set(writel); | ||
98 | |||
99 | mv_set(ioport_map); | ||
100 | mv_set(ioport_unmap); | ||
101 | mv_set(irq_demux); | ||
102 | |||
103 | if (!sh_mv.mv_nr_irqs) | ||
104 | sh_mv.mv_nr_irqs = NR_IRQS; | ||
105 | } | ||
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 61152b438325..0ad715833990 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -46,16 +46,8 @@ struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, }; | |||
46 | struct screen_info screen_info; | 46 | struct screen_info screen_info; |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #if defined(CONFIG_SH_UNKNOWN) | ||
50 | struct sh_machine_vector sh_mv; | ||
51 | #endif | ||
52 | |||
53 | extern int root_mountflags; | 49 | extern int root_mountflags; |
54 | 50 | ||
55 | #define MV_NAME_SIZE 32 | ||
56 | |||
57 | static struct sh_machine_vector* __init get_mv_byname(const char* name); | ||
58 | |||
59 | /* | 51 | /* |
60 | * This is set up by the setup-routine at boot-time | 52 | * This is set up by the setup-routine at boot-time |
61 | */ | 53 | */ |
@@ -81,131 +73,17 @@ static struct resource data_resource = { .name = "Kernel data", }; | |||
81 | 73 | ||
82 | unsigned long memory_start, memory_end; | 74 | unsigned long memory_start, memory_end; |
83 | 75 | ||
84 | static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], | 76 | static int __init early_parse_mem(char *p) |
85 | struct sh_machine_vector** mvp, | ||
86 | unsigned long *mv_io_base) | ||
87 | { | 77 | { |
88 | char c = ' ', *to = command_line, *from = COMMAND_LINE; | 78 | unsigned long size; |
89 | int len = 0; | ||
90 | |||
91 | /* Save unparsed command line copy for /proc/cmdline */ | ||
92 | memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); | ||
93 | boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; | ||
94 | 79 | ||
95 | memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; | 80 | memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; |
96 | memory_end = memory_start + __MEMORY_SIZE; | 81 | size = memparse(p, &p); |
97 | 82 | memory_end = memory_start + size; | |
98 | for (;;) { | ||
99 | /* | ||
100 | * "mem=XXX[kKmM]" defines a size of memory. | ||
101 | */ | ||
102 | if (c == ' ' && !memcmp(from, "mem=", 4)) { | ||
103 | if (to != command_line) | ||
104 | to--; | ||
105 | { | ||
106 | unsigned long mem_size; | ||
107 | |||
108 | mem_size = memparse(from+4, &from); | ||
109 | memory_end = memory_start + mem_size; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | if (c == ' ' && !memcmp(from, "sh_mv=", 6)) { | ||
114 | char* mv_end; | ||
115 | char* mv_comma; | ||
116 | int mv_len; | ||
117 | if (to != command_line) | ||
118 | to--; | ||
119 | from += 6; | ||
120 | mv_end = strchr(from, ' '); | ||
121 | if (mv_end == NULL) | ||
122 | mv_end = from + strlen(from); | ||
123 | |||
124 | mv_comma = strchr(from, ','); | ||
125 | if ((mv_comma != NULL) && (mv_comma < mv_end)) { | ||
126 | int ints[3]; | ||
127 | get_options(mv_comma+1, ARRAY_SIZE(ints), ints); | ||
128 | *mv_io_base = ints[1]; | ||
129 | mv_len = mv_comma - from; | ||
130 | } else { | ||
131 | mv_len = mv_end - from; | ||
132 | } | ||
133 | if (mv_len > (MV_NAME_SIZE-1)) | ||
134 | mv_len = MV_NAME_SIZE-1; | ||
135 | memcpy(mv_name, from, mv_len); | ||
136 | mv_name[mv_len] = '\0'; | ||
137 | from = mv_end; | ||
138 | |||
139 | *mvp = get_mv_byname(mv_name); | ||
140 | } | ||
141 | |||
142 | c = *(from++); | ||
143 | if (!c) | ||
144 | break; | ||
145 | if (COMMAND_LINE_SIZE <= ++len) | ||
146 | break; | ||
147 | *(to++) = c; | ||
148 | } | ||
149 | *to = '\0'; | ||
150 | *cmdline_p = command_line; | ||
151 | } | ||
152 | |||
153 | static int __init sh_mv_setup(char **cmdline_p) | ||
154 | { | ||
155 | #ifdef CONFIG_SH_UNKNOWN | ||
156 | extern struct sh_machine_vector mv_unknown; | ||
157 | #endif | ||
158 | struct sh_machine_vector *mv = NULL; | ||
159 | char mv_name[MV_NAME_SIZE] = ""; | ||
160 | unsigned long mv_io_base = 0; | ||
161 | |||
162 | parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base); | ||
163 | |||
164 | #ifdef CONFIG_SH_UNKNOWN | ||
165 | if (mv == NULL) { | ||
166 | mv = &mv_unknown; | ||
167 | if (*mv_name != '\0') { | ||
168 | printk("Warning: Unsupported machine %s, using unknown\n", | ||
169 | mv_name); | ||
170 | } | ||
171 | } | ||
172 | sh_mv = *mv; | ||
173 | #endif | ||
174 | |||
175 | /* | ||
176 | * Manually walk the vec, fill in anything that the board hasn't yet | ||
177 | * by hand, wrapping to the generic implementation. | ||
178 | */ | ||
179 | #define mv_set(elem) do { \ | ||
180 | if (!sh_mv.mv_##elem) \ | ||
181 | sh_mv.mv_##elem = generic_##elem; \ | ||
182 | } while (0) | ||
183 | |||
184 | mv_set(inb); mv_set(inw); mv_set(inl); | ||
185 | mv_set(outb); mv_set(outw); mv_set(outl); | ||
186 | |||
187 | mv_set(inb_p); mv_set(inw_p); mv_set(inl_p); | ||
188 | mv_set(outb_p); mv_set(outw_p); mv_set(outl_p); | ||
189 | |||
190 | mv_set(insb); mv_set(insw); mv_set(insl); | ||
191 | mv_set(outsb); mv_set(outsw); mv_set(outsl); | ||
192 | |||
193 | mv_set(readb); mv_set(readw); mv_set(readl); | ||
194 | mv_set(writeb); mv_set(writew); mv_set(writel); | ||
195 | |||
196 | mv_set(ioport_map); | ||
197 | mv_set(ioport_unmap); | ||
198 | mv_set(irq_demux); | ||
199 | |||
200 | #ifdef CONFIG_SH_UNKNOWN | ||
201 | __set_io_port_base(mv_io_base); | ||
202 | #endif | ||
203 | |||
204 | if (!sh_mv.mv_nr_irqs) | ||
205 | sh_mv.mv_nr_irqs = NR_IRQS; | ||
206 | 83 | ||
207 | return 0; | 84 | return 0; |
208 | } | 85 | } |
86 | early_param("mem", early_parse_mem); | ||
209 | 87 | ||
210 | /* | 88 | /* |
211 | * Register fully available low RAM pages with the bootmem allocator. | 89 | * Register fully available low RAM pages with the bootmem allocator. |
@@ -340,9 +218,17 @@ void __init setup_arch(char **cmdline_p) | |||
340 | data_resource.start = virt_to_phys(_etext); | 218 | data_resource.start = virt_to_phys(_etext); |
341 | data_resource.end = virt_to_phys(_edata)-1; | 219 | data_resource.end = virt_to_phys(_edata)-1; |
342 | 220 | ||
221 | memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; | ||
222 | memory_end = memory_start + __MEMORY_SIZE; | ||
223 | |||
224 | /* Save unparsed command line copy for /proc/cmdline */ | ||
225 | strlcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); | ||
226 | |||
227 | *cmdline_p = command_line; | ||
228 | |||
343 | parse_early_param(); | 229 | parse_early_param(); |
344 | 230 | ||
345 | sh_mv_setup(cmdline_p); | 231 | sh_mv_setup(); |
346 | 232 | ||
347 | /* | 233 | /* |
348 | * Find the highest page frame number we have available | 234 | * Find the highest page frame number we have available |
@@ -369,26 +255,6 @@ void __init setup_arch(char **cmdline_p) | |||
369 | sh_mv.mv_setup(cmdline_p); | 255 | sh_mv.mv_setup(cmdline_p); |
370 | } | 256 | } |
371 | 257 | ||
372 | struct sh_machine_vector* __init get_mv_byname(const char* name) | ||
373 | { | ||
374 | extern long __machvec_start, __machvec_end; | ||
375 | struct sh_machine_vector *all_vecs = | ||
376 | (struct sh_machine_vector *)&__machvec_start; | ||
377 | |||
378 | int i, n = ((unsigned long)&__machvec_end | ||
379 | - (unsigned long)&__machvec_start)/ | ||
380 | sizeof(struct sh_machine_vector); | ||
381 | |||
382 | for (i = 0; i < n; ++i) { | ||
383 | struct sh_machine_vector *mv = &all_vecs[i]; | ||
384 | if (mv == NULL) | ||
385 | continue; | ||
386 | if (strcasecmp(name, get_system_type()) == 0) { | ||
387 | return mv; | ||
388 | } | ||
389 | } | ||
390 | return NULL; | ||
391 | } | ||
392 | 258 | ||
393 | static const char *cpu_name[] = { | 259 | static const char *cpu_name[] = { |
394 | [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", | 260 | [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", |
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 4c5b57e9c3c1..f437a4f06da4 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S | |||
@@ -98,8 +98,9 @@ SECTIONS | |||
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | __machvec_start = .; | 100 | __machvec_start = .; |
101 | .init.machvec : { *(.init.machvec) } | 101 | .machvec.init : { *(.machvec.init) } |
102 | __machvec_end = .; | 102 | __machvec_end = .; |
103 | |||
103 | . = ALIGN(PAGE_SIZE); | 104 | . = ALIGN(PAGE_SIZE); |
104 | __init_end = .; | 105 | __init_end = .; |
105 | 106 | ||