Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Add generic support for multiple machines within a single kernel

This patch adds a generic solution to support multiple machines based on
a given SoC within a single kernel image. It is implemented already for
several other architectures but MIPS has no generic support for that yet.

[Ralf: This competes with DT but DT is a much more complex solution and this
code has been used by OpenWRT for a long time so for now DT is a bad reason
to stop the merge but longer term this should be migrated to DT.]

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: kaloz@openwrt.org
Cc: Luis R. Rodriguez <lrodriguez@atheros.com>
Cc: Cliff Holden <Cliff.Holden@Atheros.com>
Patchwork: https://patchwork.linux-mips.org/patch/1814/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Gabor Juhos and committed by
Ralf Baechle
487d70d0 0bec405e

+157 -1
+3
arch/mips/Kconfig
··· 883 883 config SYNC_R4K 884 884 bool 885 885 886 + config MIPS_MACHINE 887 + def_bool n 888 + 886 889 config NO_IOPORT 887 890 def_bool n 888 891
+54
arch/mips/include/asm/mips_machine.h
··· 1 + /* 2 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published 6 + * by the Free Software Foundation. 7 + * 8 + */ 9 + 10 + #ifndef __ASM_MIPS_MACHINE_H 11 + #define __ASM_MIPS_MACHINE_H 12 + 13 + #include <linux/init.h> 14 + #include <linux/stddef.h> 15 + 16 + #include <asm/bootinfo.h> 17 + 18 + struct mips_machine { 19 + unsigned long mach_type; 20 + const char *mach_id; 21 + const char *mach_name; 22 + void (*mach_setup)(void); 23 + }; 24 + 25 + #define MIPS_MACHINE(_type, _id, _name, _setup) \ 26 + static const char machine_name_##_type[] __initconst \ 27 + __aligned(1) = _name; \ 28 + static const char machine_id_##_type[] __initconst \ 29 + __aligned(1) = _id; \ 30 + static struct mips_machine machine_##_type \ 31 + __used __section(.mips.machines.init) = \ 32 + { \ 33 + .mach_type = _type, \ 34 + .mach_id = machine_id_##_type, \ 35 + .mach_name = machine_name_##_type, \ 36 + .mach_setup = _setup, \ 37 + }; 38 + 39 + extern long __mips_machines_start; 40 + extern long __mips_machines_end; 41 + 42 + #ifdef CONFIG_MIPS_MACHINE 43 + int mips_machtype_setup(char *id) __init; 44 + void mips_machine_setup(void) __init; 45 + void mips_set_machine_name(const char *name) __init; 46 + char *mips_get_machine_name(void); 47 + #else 48 + static inline int mips_machtype_setup(char *id) { return 1; } 49 + static inline void mips_machine_setup(void) { } 50 + static inline void mips_set_machine_name(const char *name) { } 51 + static inline char *mips_get_machine_name(void) { return NULL; } 52 + #endif /* CONFIG_MIPS_MACHINE */ 53 + 54 + #endif /* __ASM_MIPS_MACHINE_H */
+1
arch/mips/kernel/Makefile
··· 95 95 obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 96 96 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 97 97 obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o 98 + obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o 98 99 99 100 obj-$(CONFIG_OF) += prom.o 100 101
+86
arch/mips/kernel/mips_machine.c
··· 1 + /* 2 + * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published 6 + * by the Free Software Foundation. 7 + * 8 + */ 9 + #include <linux/mm.h> 10 + #include <linux/string.h> 11 + #include <linux/slab.h> 12 + 13 + #include <asm/mips_machine.h> 14 + 15 + static struct mips_machine *mips_machine __initdata; 16 + static char *mips_machine_name = "Unknown"; 17 + 18 + #define for_each_machine(mach) \ 19 + for ((mach) = (struct mips_machine *)&__mips_machines_start; \ 20 + (mach) && \ 21 + (unsigned long)(mach) < (unsigned long)&__mips_machines_end; \ 22 + (mach)++) 23 + 24 + __init void mips_set_machine_name(const char *name) 25 + { 26 + char *p; 27 + 28 + if (name == NULL) 29 + return; 30 + 31 + p = kstrdup(name, GFP_KERNEL); 32 + if (!p) 33 + pr_err("MIPS: no memory for machine_name\n"); 34 + 35 + mips_machine_name = p; 36 + } 37 + 38 + char *mips_get_machine_name(void) 39 + { 40 + return mips_machine_name; 41 + } 42 + 43 + __init int mips_machtype_setup(char *id) 44 + { 45 + struct mips_machine *mach; 46 + 47 + for_each_machine(mach) { 48 + if (mach->mach_id == NULL) 49 + continue; 50 + 51 + if (strcmp(mach->mach_id, id) == 0) { 52 + mips_machtype = mach->mach_type; 53 + return 0; 54 + } 55 + } 56 + 57 + pr_err("MIPS: no machine found for id '%s', supported machines:\n", id); 58 + pr_err("%-24s %s\n", "id", "name"); 59 + for_each_machine(mach) 60 + pr_err("%-24s %s\n", mach->mach_id, mach->mach_name); 61 + 62 + return 1; 63 + } 64 + 65 + __setup("machtype=", mips_machtype_setup); 66 + 67 + __init void mips_machine_setup(void) 68 + { 69 + struct mips_machine *mach; 70 + 71 + for_each_machine(mach) { 72 + if (mips_machtype == mach->mach_type) { 73 + mips_machine = mach; 74 + break; 75 + } 76 + } 77 + 78 + if (!mips_machine) 79 + return; 80 + 81 + mips_set_machine_name(mips_machine->mach_name); 82 + pr_info("MIPS: machine is %s\n", mips_machine_name); 83 + 84 + if (mips_machine->mach_setup) 85 + mips_machine->mach_setup(); 86 + }
+6 -1
arch/mips/kernel/proc.c
··· 12 12 #include <asm/cpu-features.h> 13 13 #include <asm/mipsregs.h> 14 14 #include <asm/processor.h> 15 + #include <asm/mips_machine.h> 15 16 16 17 unsigned int vced_count, vcei_count; 17 18 ··· 32 31 /* 33 32 * For the first processor also print the system type 34 33 */ 35 - if (n == 0) 34 + if (n == 0) { 36 35 seq_printf(m, "system type\t\t: %s\n", get_system_type()); 36 + if (mips_get_machine_name()) 37 + seq_printf(m, "machine\t\t\t: %s\n", 38 + mips_get_machine_name()); 39 + } 37 40 38 41 seq_printf(m, "processor\t\t: %ld\n", n); 39 42 sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
+7
arch/mips/kernel/vmlinux.lds.S
··· 98 98 INIT_TEXT_SECTION(PAGE_SIZE) 99 99 INIT_DATA_SECTION(16) 100 100 101 + . = ALIGN(4); 102 + .mips.machines.init : AT(ADDR(.mips.machines.init) - LOAD_OFFSET) { 103 + __mips_machines_start = .; 104 + *(.mips.machines.init) 105 + __mips_machines_end = .; 106 + } 107 + 101 108 /* .exit.text is discarded at runtime, not link time, to deal with 102 109 * references from .rodata 103 110 */