--- /dev/null
+/*
+ * arch/sh/kernel/machvec.c
+ *
+ * The SuperH machine vector setup handlers, yanked from setup.c
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2002 - 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/machvec.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define MV_NAME_SIZE 32
+
+#define for_each_mv(mv) \
+ for ((mv) = (struct sh_machine_vector *)&__machvec_start; \
+ (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \
+ (mv)++)
+
+static struct sh_machine_vector * __init get_mv_byname(const char *name)
+{
+ struct sh_machine_vector *mv;
+
+ for_each_mv(mv)
+ if (strcasecmp(name, get_system_type()) == 0)
+ return mv;
+
+ return NULL;
+}
+
+static int __init early_parse_mv(char *from)
+{
+ char mv_name[MV_NAME_SIZE] = "";
+ char *mv_end;
+ char *mv_comma;
+ int mv_len;
+ struct sh_machine_vector *mvp;
+
+ mv_end = strchr(from, ' ');
+ if (mv_end == NULL)
+ mv_end = from + strlen(from);
+
+ mv_comma = strchr(from, ',');
+ mv_len = mv_end - from;
+ if (mv_len > (MV_NAME_SIZE-1))
+ mv_len = MV_NAME_SIZE-1;
+ memcpy(mv_name, from, mv_len);
+ mv_name[mv_len] = '\0';
+ from = mv_end;
+
+ if (strcmp(sh_mv.mv_name, mv_name) != 0) {
+ mvp = get_mv_byname(mv_name);
+ if (unlikely(!mvp)) {
+ printk("Available vectors:\n\n\t");
+ for_each_mv(mvp)
+ printk("'%s', ", mvp->mv_name);
+ printk("\n\n");
+ panic("Failed to select machvec '%s' -- halting.\n",
+ mv_name);
+ } else
+ sh_mv = *mvp;
+ }
+
+ printk(KERN_NOTICE "Booting machvec: %s\n", sh_mv.mv_name);
+ return 0;
+}
+early_param("sh_mv", early_parse_mv);
+
+void __init sh_mv_setup(void)
+{
+ /*
+ * Manually walk the vec, fill in anything that the board hasn't yet
+ * by hand, wrapping to the generic implementation.
+ */
+#define mv_set(elem) do { \
+ if (!sh_mv.mv_##elem) \
+ sh_mv.mv_##elem = generic_##elem; \
+} while (0)
+
+ mv_set(inb); mv_set(inw); mv_set(inl);
+ mv_set(outb); mv_set(outw); mv_set(outl);
+
+ mv_set(inb_p); mv_set(inw_p); mv_set(inl_p);
+ mv_set(outb_p); mv_set(outw_p); mv_set(outl_p);
+
+ mv_set(insb); mv_set(insw); mv_set(insl);
+ mv_set(outsb); mv_set(outsw); mv_set(outsl);
+
+ mv_set(readb); mv_set(readw); mv_set(readl);
+ mv_set(writeb); mv_set(writew); mv_set(writel);
+
+ mv_set(ioport_map);
+ mv_set(ioport_unmap);
+ mv_set(irq_demux);
+
+ if (!sh_mv.mv_nr_irqs)
+ sh_mv.mv_nr_irqs = NR_IRQS;
+}
struct screen_info screen_info;
#endif
-#if defined(CONFIG_SH_UNKNOWN)
-struct sh_machine_vector sh_mv;
-#endif
-
extern int root_mountflags;
-#define MV_NAME_SIZE 32
-
-static struct sh_machine_vector* __init get_mv_byname(const char* name);
-
/*
* This is set up by the setup-routine at boot-time
*/
unsigned long memory_start, memory_end;
-static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
- struct sh_machine_vector** mvp,
- unsigned long *mv_io_base)
+static int __init early_parse_mem(char *p)
{
- char c = ' ', *to = command_line, *from = COMMAND_LINE;
- int len = 0;
-
- /* Save unparsed command line copy for /proc/cmdline */
- memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
- boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
+ unsigned long size;
memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
- memory_end = memory_start + __MEMORY_SIZE;
-
- for (;;) {
- /*
- * "mem=XXX[kKmM]" defines a size of memory.
- */
- if (c == ' ' && !memcmp(from, "mem=", 4)) {
- if (to != command_line)
- to--;
- {
- unsigned long mem_size;
-
- mem_size = memparse(from+4, &from);
- memory_end = memory_start + mem_size;
- }
- }
-
- if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
- char* mv_end;
- char* mv_comma;
- int mv_len;
- if (to != command_line)
- to--;
- from += 6;
- mv_end = strchr(from, ' ');
- if (mv_end == NULL)
- mv_end = from + strlen(from);
-
- mv_comma = strchr(from, ',');
- if ((mv_comma != NULL) && (mv_comma < mv_end)) {
- int ints[3];
- get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
- *mv_io_base = ints[1];
- mv_len = mv_comma - from;
- } else {
- mv_len = mv_end - from;
- }
- if (mv_len > (MV_NAME_SIZE-1))
- mv_len = MV_NAME_SIZE-1;
- memcpy(mv_name, from, mv_len);
- mv_name[mv_len] = '\0';
- from = mv_end;
-
- *mvp = get_mv_byname(mv_name);
- }
-
- c = *(from++);
- if (!c)
- break;
- if (COMMAND_LINE_SIZE <= ++len)
- break;
- *(to++) = c;
- }
- *to = '\0';
- *cmdline_p = command_line;
-}
-
-static int __init sh_mv_setup(char **cmdline_p)
-{
-#ifdef CONFIG_SH_UNKNOWN
- extern struct sh_machine_vector mv_unknown;
-#endif
- struct sh_machine_vector *mv = NULL;
- char mv_name[MV_NAME_SIZE] = "";
- unsigned long mv_io_base = 0;
-
- parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base);
-
-#ifdef CONFIG_SH_UNKNOWN
- if (mv == NULL) {
- mv = &mv_unknown;
- if (*mv_name != '\0') {
- printk("Warning: Unsupported machine %s, using unknown\n",
- mv_name);
- }
- }
- sh_mv = *mv;
-#endif
-
- /*
- * Manually walk the vec, fill in anything that the board hasn't yet
- * by hand, wrapping to the generic implementation.
- */
-#define mv_set(elem) do { \
- if (!sh_mv.mv_##elem) \
- sh_mv.mv_##elem = generic_##elem; \
-} while (0)
-
- mv_set(inb); mv_set(inw); mv_set(inl);
- mv_set(outb); mv_set(outw); mv_set(outl);
-
- mv_set(inb_p); mv_set(inw_p); mv_set(inl_p);
- mv_set(outb_p); mv_set(outw_p); mv_set(outl_p);
-
- mv_set(insb); mv_set(insw); mv_set(insl);
- mv_set(outsb); mv_set(outsw); mv_set(outsl);
-
- mv_set(readb); mv_set(readw); mv_set(readl);
- mv_set(writeb); mv_set(writew); mv_set(writel);
-
- mv_set(ioport_map);
- mv_set(ioport_unmap);
- mv_set(irq_demux);
-
-#ifdef CONFIG_SH_UNKNOWN
- __set_io_port_base(mv_io_base);
-#endif
-
- if (!sh_mv.mv_nr_irqs)
- sh_mv.mv_nr_irqs = NR_IRQS;
+ size = memparse(p, &p);
+ memory_end = memory_start + size;
return 0;
}
+early_param("mem", early_parse_mem);
/*
* Register fully available low RAM pages with the bootmem allocator.
data_resource.start = virt_to_phys(_etext);
data_resource.end = virt_to_phys(_edata)-1;
+ memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
+ memory_end = memory_start + __MEMORY_SIZE;
+
+ /* Save unparsed command line copy for /proc/cmdline */
+ strlcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+
+ *cmdline_p = command_line;
+
parse_early_param();
- sh_mv_setup(cmdline_p);
+ sh_mv_setup();
/*
* Find the highest page frame number we have available
sh_mv.mv_setup(cmdline_p);
}
-struct sh_machine_vector* __init get_mv_byname(const char* name)
-{
- extern long __machvec_start, __machvec_end;
- struct sh_machine_vector *all_vecs =
- (struct sh_machine_vector *)&__machvec_start;
-
- int i, n = ((unsigned long)&__machvec_end
- - (unsigned long)&__machvec_start)/
- sizeof(struct sh_machine_vector);
-
- for (i = 0; i < n; ++i) {
- struct sh_machine_vector *mv = &all_vecs[i];
- if (mv == NULL)
- continue;
- if (strcasecmp(name, get_system_type()) == 0) {
- return mv;
- }
- }
- return NULL;
-}
static const char *cpu_name[] = {
[CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619",
#ifndef __SH_MACHVEC_INIT_H
#define __SH_MACHVEC_INIT_H
-
-/*
- * In a GENERIC kernel, we have lots of these vectors floating about,
- * all but one of which we want to go away. In a non-GENERIC kernel,
- * we want only one, ever.
- *
- * Accomplish this in the GENERIC kernel by puting all of the vectors
- * in the .init.data section where they'll go away. We'll copy the
- * one we want to the real alpha_mv vector in setup_arch.
- *
- * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
- * one of the vectors, which will not reside in .init.data. We then
- * alias this one vector to alpha_mv, so no copy is needed.
- *
- * Upshot: set __initdata to nothing for non-GENERIC kernels.
- *
- * Note we do the same thing for the UNKNOWN kernel, as we need to write
- * to the machine vector while setting it up.
- */
-
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN)
#define __initmv __attribute__((unused,__section__ (".machvec.init")))
-#define ALIAS_MV(x)
-#else
-#define __initmv
-
-/* GCC actually has a syntax for defining aliases, but is under some
- delusion that you shouldn't be able to declare it extern somewhere
- else beforehand. Fine. We'll do it ourselves. */
-#if 0
-#define ALIAS_MV(system) \
- struct sh_machine_vector sh_mv __attribute__((alias("mv_"#system)));
-#else
#define ALIAS_MV(system) \
asm(".global sh_mv\nsh_mv = mv_"#system );
-#endif
-#endif /* GENERIC */
#endif /* __SH_MACHVEC_INIT_H */