Skip to contentSkip to conversation

sh: cpuvec prototype for sh7722

PATCH In review Magnus Damm 2 participants 2 messages Apr 2, 2008 – Apr 7, 2008 SuperH

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 sh: cpuvec prototype for sh7722

This patch contains my cpuvec prototype for sh7722. The idea behind cpuvec is that we need something similar to machvec, but cpu specific.

Commonly used data structures such as platform device lists and intc controller data are pointed out directly by the cpuvec struct. This is convenient since it allows us to locate cpu specific platform data early in the boot process. Think serial port data for early printk, tmu information for the timers, pci bridge base addresses and so on.

Matching is done by comparing the detected cpu_type enum with the one present in the cpuvec. Seems to work well.

I'd be happy to convert the rest of the cpu code, just let me know if the currect struct sh_cpu_vector is good enough.

---

 arch/sh/kernel/Makefile_32             |    2 
 arch/sh/kernel/Makefile_64             |    2 
 arch/sh/kernel/cpu/sh4a/setup-sh7722.c |   24 +++++------
 arch/sh/kernel/cpuvec.c                |   65 ++++++++++++++++++++++++++++++++
 arch/sh/kernel/irq.c                   |   14 ++++++
 arch/sh/kernel/setup.c                 |   36 +++++++----------
 arch/sh/kernel/vmlinux_32.lds.S        |    5 ++
 arch/sh/kernel/vmlinux_64.lds.S        |    5 ++
 arch/sh/mm/numa.c                      |    4 +
 include/asm-sh/cpuvec.h                |   37 ++++++++++++++++++
 include/asm-sh/hw_irq.h                |    2 
 include/asm-sh/mmzone.h                |    3 -
 include/asm-sh/sections.h              |    1 
 include/asm-sh/setup.h                 |    1 
 14 files changed, 158 insertions(+), 43 deletions(-)
arch/sh/kernel/Makefile_32 +1 -1
@@ -6,7 +6,7 @@ extra-y	:= head_32.o init_task.o vmlinux
 
 obj-y	:= debugtraps.o io.o io_generic.o irq.o machvec.o process_32.o \
 	   ptrace_32.o semaphore.o setup.o signal_32.o sys_sh.o sys_sh32.o \
-	   syscalls_32.o time_32.o topology.o traps.o traps_32.o
+	   syscalls_32.o time_32.o topology.o traps.o traps_32.o cpuvec.o
 
 obj-y				+= cpu/ timers/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
arch/sh/kernel/Makefile_64 +1 -1
@@ -2,7 +2,7 @@ extra-y	:= head_64.o init_task.o vmlinux
 
 obj-y	:= debugtraps.o io.o io_generic.o irq.o machvec.o process_64.o \
 	   ptrace_64.o semaphore.o setup.o signal_64.o sys_sh.o sys_sh64.o \
-	   syscalls_64.o time_64.o topology.o traps.o traps_64.o
+	   syscalls_64.o time_64.o topology.o traps.o traps_64.o cpuvec.o
 
 obj-y				+= cpu/ timers/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
arch/sh/kernel/cpu/sh4a/setup-sh7722.c +11 -13
@@ -12,6 +12,7 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/mm.h>
+#include <asm/cpuvec.h>
 #include <asm/mmzone.h>
 
 static struct resource usbf_resources[] = {
@@ -97,13 +98,6 @@ static struct platform_device *sh7722_de
 	&sci_device,
 };
 
-static int __init sh7722_devices_setup(void)
-{
-	return platform_add_devices(sh7722_devices,
-				    ARRAY_SIZE(sh7722_devices));
-}
-__initcall(sh7722_devices_setup);
-
 enum {
 	UNUSED=0,
 
@@ -232,13 +226,17 @@ static struct intc_sense_reg sense_regis
 static DECLARE_INTC_DESC(intc_desc, "sh7722", vectors, groups,
 			 mask_registers, prio_registers, sense_registers);
 
-void __init plat_irq_setup(void)
-{
-	register_intc_controller(&intc_desc);
-}
-
-void __init plat_mem_setup(void)
+static void __init sh7722_setup_mem(void)
 {
 	/* Register the URAM space as Node 1 */
 	setup_bootmem_node(1, 0x055f0000, 0x05610000);
 }
+
+static struct sh_cpu_vector cv_sh7722 __initcv = {
+	.type = CPU_SH7722,
+	.name = "SH7722",
+	.devices = sh7722_devices,
+	.nr_devices = ARRAY_SIZE(sh7722_devices),
+	.intc = &intc_desc,
+	.setup_mem = sh7722_setup_mem,
+};
arch/sh/kernel/cpuvec.c new file +65 -0

65 lines not on this page · raw message

arch/sh/kernel/irq.c +13 -1
@@ -12,6 +12,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <asm/processor.h>
+#include <asm/cpuvec.h>
 #include <asm/machvec.h>
 #include <asm/uaccess.h>
 #include <asm/thread_info.h>
@@ -246,9 +247,20 @@ asmlinkage void do_softirq(void)
 }
 #endif
 
+void __init plat_irq_setup_pins(int mode)
+{
+	if (sh_cv.setup_irq_pins)
+		sh_cv.setup_irq_pins(mode);
+}
+
 void __init init_IRQ(void)
 {
-	plat_irq_setup();
+	/* Cpu-specific setup first */
+	if (sh_cv.intc)
+		register_intc_controller(sh_cv.intc);
+
+	if (sh_cv.setup_irq)
+		sh_cv.setup_irq();
 
 	/* Perform the machine specific initialisation */
 	if (sh_mv.mv_init_irq)
arch/sh/kernel/setup.c +15 -21
@@ -34,6 +34,7 @@
 #include <asm/setup.h>
 #include <asm/clock.h>
 #include <asm/mmu_context.h>
+#include <asm/cpuvec.h>
 
 /*
  * Initialize loops_per_jiffy as 10000000 (1000MIPS).
@@ -284,6 +285,7 @@ void __init setup_arch(char **cmdline_p)
 
 	parse_early_param();
 
+	sh_cv_setup();
 	sh_mv_setup();
 
 	/*
@@ -318,30 +320,22 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
-static const char *cpu_name[] = {
-	[CPU_SH7203]	= "SH7203",	[CPU_SH7263]	= "SH7263",
-	[CPU_SH7206]	= "SH7206",	[CPU_SH7619]	= "SH7619",
-	[CPU_SH7705]	= "SH7705",	[CPU_SH7706]	= "SH7706",
-	[CPU_SH7707]	= "SH7707",	[CPU_SH7708]	= "SH7708",
-	[CPU_SH7709]	= "SH7709",	[CPU_SH7710]	= "SH7710",
-	[CPU_SH7712]	= "SH7712",	[CPU_SH7720]	= "SH7720",
-	[CPU_SH7721]	= "SH7721",	[CPU_SH7729]	= "SH7729",
-	[CPU_SH7750]	= "SH7750",	[CPU_SH7750S]	= "SH7750S",
-	[CPU_SH7750R]	= "SH7750R",	[CPU_SH7751]	= "SH7751",
-	[CPU_SH7751R]	= "SH7751R",	[CPU_SH7760]	= "SH7760",
-	[CPU_SH4_202]	= "SH4-202",	[CPU_SH4_501]	= "SH4-501",
-	[CPU_SH7763]	= "SH7763",	[CPU_SH7770]	= "SH7770",
-	[CPU_SH7780]	= "SH7780",	[CPU_SH7781]	= "SH7781",
-	[CPU_SH7343]	= "SH7343",	[CPU_SH7785]	= "SH7785",
-	[CPU_SH7722]	= "SH7722",	[CPU_SHX3]	= "SH-X3",
-	[CPU_SH5_101]	= "SH5-101",	[CPU_SH5_103]	= "SH5-103",
-	[CPU_MXG]	= "MX-G",
-	[CPU_SH7366]	= "SH7366",	[CPU_SH_NONE]	= "Unknown"
-};
+static int __init devices_setup(void)
+{
+	int ret = 0;
+
+	if (sh_cv.devices)
+		ret = platform_add_devices(sh_cv.devices, sh_cv.nr_devices);
+	if (!ret && sh_cv.setup_devices)
+		ret = sh_cv.setup_devices();
+
+	return ret;
+}
+__initcall(devices_setup);
 
 const char *get_cpu_subtype(struct sh_cpuinfo *c)
 {
-	return cpu_name[c->type];
+	return sh_cv.name;
 }
 
 #ifdef CONFIG_PROC_FS
arch/sh/kernel/vmlinux_32.lds.S +5 -0
@@ -112,6 +112,11 @@ SECTIONS
 #endif
 
 	. = ALIGN(4);
+	__cpuvec_start = .;
+	.cpuvec.init : { *(.cpuvec.init) }
+	__cpuvec_end = .;
+
+	. = ALIGN(4);
 	__machvec_start = .;
 	.machvec.init : { *(.machvec.init) }
 	__machvec_end = .;
arch/sh/kernel/vmlinux_64.lds.S +5 -0
@@ -124,6 +124,11 @@ SECTIONS
 #endif
 
 	. = ALIGN(8);
+	__cpuvec_start = .;
+	.cpuvec.init : C_PHYS(.cpuvec.init) { *(.cpuvec.init) }
+	__cpuvec_end = .;
+
+	. = ALIGN(8);
 	__machvec_start = .;
 	.machvec.init : C_PHYS(.machvec.init) { *(.machvec.init) }
 	__machvec_end = .;
arch/sh/mm/numa.c +3 -1
@@ -13,6 +13,7 @@
 #include <linux/numa.h>
 #include <linux/pfn.h>
 #include <asm/sections.h>
+#include <asm/cpuvec.h>
 
 static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
@@ -41,7 +42,8 @@ void __init setup_memory(void)
 	setup_bootmem_allocator(free_pfn);
 
 	/* Give the platforms a chance to hook up their nodes */
-	plat_mem_setup();
+	if (sh_cv.setup_mem)
+		sh_cv.setup_mem();
 }
 
 void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
include/asm-sh/cpuvec.h new file +37 -0
@@ -0,0 +1,37 @@
+/*
+ * include/asm-sh/cpuhvec.h
+ *
+ * Copyright 2008 Magnus Damm
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+
+#ifndef _ASM_SH_CPUVEC_H
+#define _ASM_SH_CPUVEC_H
+
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <asm/processor.h>
+
+struct sh_cpu_vector {
+	enum cpu_type type;
+	char name[8];
+
+	struct platform_device **devices;
+	unsigned int nr_devices;
+	struct intc_desc *intc;
+
+	int (*setup_devices)(void);
+	int (*setup_irq)(void);
+	void (*setup_irq_pins)(int mode);
+	void (*setup_mem)(void);
+};
+
+extern struct sh_cpu_vector sh_cv;
+
+#define __initcv \
+	__used __section(.cpuvec.init)
+
+#endif /* _ASM_SH_CPUVEC_H */
include/asm-sh/hw_irq.h +0 -2
@@ -94,8 +94,6 @@ struct intc_desc symbol __initdata = {		
 void __init register_intc_controller(struct intc_desc *desc);
 int intc_set_priority(unsigned int irq, unsigned int prio);
 
-void __init plat_irq_setup(void);
-
 enum { IRQ_MODE_IRQ, IRQ_MODE_IRQ7654, IRQ_MODE_IRQ3210,
        IRQ_MODE_IRL7654_MASK, IRQ_MODE_IRL3210_MASK,
        IRQ_MODE_IRL7654, IRQ_MODE_IRL3210 };
include/asm-sh/mmzone.h +0 -3
@@ -36,9 +36,6 @@ setup_bootmem_node(int nid, unsigned lon
 }
 #endif /* CONFIG_NEED_MULTIPLE_NODES */
 
-/* Platform specific mem init */
-void __init plat_mem_setup(void);
-
 /* arch/sh/kernel/setup.c */
 void __init setup_bootmem_allocator(unsigned long start_pfn);
 
include/asm-sh/sections.h +1 -0
@@ -3,6 +3,7 @@
 
 #include <asm-generic/sections.h>
 
+extern long __cpuvec_start, __cpuvec_end;
 extern long __machvec_start, __machvec_end;
 extern char __uncached_start, __uncached_end;
 extern char _ebss[];
include/asm-sh/setup.h +1 -0
@@ -20,6 +20,7 @@
 #define COMMAND_LINE ((char *) (PARAM+0x100))
 
 int setup_early_printk(char *);
+void sh_cv_setup(void);
 void sh_mv_setup(void);
 
 #endif /* __KERNEL__ */
#1 lore raw
Quoted 9 lines · Magnus Damm

This patch contains my cpuvec prototype for sh7722. The idea behind cpuvec is that we need something similar to machvec, but cpu specific.

Commonly used data structures such as platform device lists and intc controller data are pointed out directly by the cpuvec struct. This is convenient since it allows us to locate cpu specific platform data early in the boot process. Think serial port data for early printk, tmu information for the timers, pci bridge base addresses and so on.

Quoted 6 lines

Matching is done by comparing the detected cpu_type enum with the one present in the cpuvec. Seems to work well.

I'd be happy to convert the rest of the cpu code, just let me know if the currect struct sh_cpu_vector is good enough.

The general idea seems fine, but I don't think it's appropriate to have platform device data as part of the vector itself. Having a device setup callback where the CPU setup code can register all of its devices is fine, but that should be the end of the abstraction.

We already have cases today (ie, SH4-202) where on-chip devices are mapped under a differing bus abstraction. There's no reason to drag this sort of information around, as we're never going to tear these devices down anyways.

Quoted 11 lines
arch/sh/kernel/cpuvec.c new file +8 -0
@@ -0,0 +1,65 @@
+/*
+ * arch/sh/kernel/cpuvec.c
+ *
+ * SuperH cpu vector setup code, yanked from machvec.c
+ *
+ *  Copyright (C) 1999 Niibe Yutaka
+ *  Copyright (C) 2002 - 2007 Paul Mundt
+ *  Copyright (C) 2008 Magnus Damm

arch/sh/kernel/cpuvec.c line 18

Quoted 10 lines
arch/sh/kernel/cpuvec.c new file +10 -0
+ *
+ * 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 <asm/processor.h>
+#include <asm/cpuvec.h>
+#include <asm/sections.h>
+

This has almost 100% overlap with the machvec.c, lets just macroify that and have it handle both the mach and cpu vec cases instead.

Quoted 22 lines
arch/sh/kernel/irq.c +7 -0
@@ -12,6 +12,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <asm/processor.h>
+#include <asm/cpuvec.h>
 #include <asm/machvec.h>
 #include <asm/uaccess.h>
 #include <asm/thread_info.h>
@@ -246,9 +247,20 @@ asmlinkage void do_softirq(void)
 }
 #endif
 
+void __init plat_irq_setup_pins(int mode)
+{
+	if (sh_cv.setup_irq_pins)
+		sh_cv.setup_irq_pins(mode);
+}
+
 void __init init_IRQ(void)
 {

arch/sh/kernel/irq.c asmlinkage void do_softirq(void) · line 266

Quoted 10 lines
arch/sh/kernel/irq.c +6 -1
-	plat_irq_setup();
+	/* Cpu-specific setup first */
+	if (sh_cv.intc)
+		register_intc_controller(sh_cv.intc);
+
+	if (sh_cv.setup_irq)
+		sh_cv.setup_irq();
 
 	/* Perform the machine specific initialisation */
 	if (sh_mv.mv_init_irq)

What exactly does this buy us? If we already have a CPU-specific IRQ setup, we can do the registration there. Some CPUs may also have multiple controllers, so the intc abstraction here isn't really useful.

Quoted 27 lines
arch/sh/kernel/irq.c +3 -20
@@ -318,30 +320,22 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
-static const char *cpu_name[] = {
-	[CPU_SH7203]	= "SH7203",	[CPU_SH7263]	= "SH7263",
-	[CPU_SH7206]	= "SH7206",	[CPU_SH7619]	= "SH7619",
-	[CPU_SH7705]	= "SH7705",	[CPU_SH7706]	= "SH7706",
-	[CPU_SH7707]	= "SH7707",	[CPU_SH7708]	= "SH7708",
-	[CPU_SH7709]	= "SH7709",	[CPU_SH7710]	= "SH7710",
-	[CPU_SH7712]	= "SH7712",	[CPU_SH7720]	= "SH7720",
-	[CPU_SH7721]	= "SH7721",	[CPU_SH7729]	= "SH7729",
-	[CPU_SH7750]	= "SH7750",	[CPU_SH7750S]	= "SH7750S",
-	[CPU_SH7750R]	= "SH7750R",	[CPU_SH7751]	= "SH7751",
-	[CPU_SH7751R]	= "SH7751R",	[CPU_SH7760]	= "SH7760",
-	[CPU_SH4_202]	= "SH4-202",	[CPU_SH4_501]	= "SH4-501",
-	[CPU_SH7763]	= "SH7763",	[CPU_SH7770]	= "SH7770",
-	[CPU_SH7780]	= "SH7780",	[CPU_SH7781]	= "SH7781",
-	[CPU_SH7343]	= "SH7343",	[CPU_SH7785]	= "SH7785",
-	[CPU_SH7722]	= "SH7722",	[CPU_SHX3]	= "SH-X3",
-	[CPU_SH5_101]	= "SH5-101",	[CPU_SH5_103]	= "SH5-103",
-	[CPU_MXG]	= "MX-G",
-	[CPU_SH7366]	= "SH7366",	[CPU_SH_NONE]	= "Unknown"
-};
+static int __init devices_setup(void)
+{
+	int ret = 0;

arch/sh/kernel/irq.c void __init setup_arch(char **cmdline_p) · line 335

Quoted 10 lines
arch/sh/kernel/irq.c +9 -0
+
+	if (sh_cv.devices)
+		ret = platform_add_devices(sh_cv.devices, sh_cv.nr_devices);
+	if (!ret && sh_cv.setup_devices)
+		ret = sh_cv.setup_devices();
+
+	return ret;
+}
+__initcall(devices_setup);
 

This conversion also needs to be incremental, we are not going to break bisect on every possible CPU except the one you happen to be converting.