aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/kernel/Makefile2
-rw-r--r--arch/sh/kernel/machvec.c105
-rw-r--r--arch/sh/kernel/setup.c162
-rw-r--r--arch/sh/kernel/vmlinux.lds.S3
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
5extra-y := head.o init_task.o vmlinux.lds 5extra-y := head.o init_task.o vmlinux.lds
6 6
7obj-y := debugtraps.o io.o io_generic.o irq.o process.o ptrace.o \ 7obj-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
27static 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
38static 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}
74early_param("sh_mv", early_parse_mv);
75
76void __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, };
46struct screen_info screen_info; 46struct screen_info screen_info;
47#endif 47#endif
48 48
49#if defined(CONFIG_SH_UNKNOWN)
50struct sh_machine_vector sh_mv;
51#endif
52
53extern int root_mountflags; 49extern int root_mountflags;
54 50
55#define MV_NAME_SIZE 32
56
57static 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
82unsigned long memory_start, memory_end; 74unsigned long memory_start, memory_end;
83 75
84static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], 76static 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
153static 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}
86early_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
372struct 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
393static const char *cpu_name[] = { 259static 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