aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorRich Felker <dalias@libc.org>2016-01-22 19:45:41 -0500
committerRich Felker <dalias@libc.org>2016-03-17 15:46:11 -0400
commit7480e0aabd5f9e6c3e3b72ed206e89284e90f11f (patch)
treeafcdb346dbec13ea4be79f062e9f849caedceaae /arch/sh
parent45624ac38926c8c2f1a63b4a39e7b1997743e1b3 (diff)
sh: add device tree support and generic board using device tree
Add a new pseudo-board, within the existing SH boards/machine-vectors framework, which does not represent any actual hardware but instead requires all hardware to be described by the device tree blob provided by the boot loader. Changes made are thus non-invasive and do not risk breaking support for legacy boards. New hardware, including the open-hardware J2 and associated SoC devices, will use device free from the outset. Legacy SH boards can transition to device tree once all their hardware has device tree bindings, driver support for device tree, and a dts file for the board. It is intented that, once all boards are supported in the new framework, the existing machine-vectors framework should be removed and the new device tree setup code integrated directly. Signed-off-by: Rich Felker <dalias@libc.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/boards/Kconfig15
-rw-r--r--arch/sh/boards/Makefile2
-rw-r--r--arch/sh/boards/of-generic.c113
-rw-r--r--arch/sh/kernel/head_32.S13
-rw-r--r--arch/sh/kernel/setup.c27
5 files changed, 170 insertions, 0 deletions
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index 89963d13f930..5e52d5362292 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -6,6 +6,21 @@ config SOLUTION_ENGINE
6config SH_ALPHA_BOARD 6config SH_ALPHA_BOARD
7 bool 7 bool
8 8
9config SH_DEVICE_TREE
10 bool "Board Described by Device Tree"
11 select OF
12 select OF_EARLY_FLATTREE
13 select CLKSRC_OF
14 select GENERIC_CALIBRATE_DELAY
15 help
16 Select Board Described by Device Tree to build a kernel that
17 does not hard-code any board-specific knowledge but instead uses
18 a device tree blob provided by the boot-loader. You must enable
19 drivers for any hardware you want to use separately. At this
20 time, only boards based on the open-hardware J-Core processors
21 have sufficient driver coverage to use this option; do not
22 select it if you are using original SuperH hardware.
23
9config SH_SOLUTION_ENGINE 24config SH_SOLUTION_ENGINE
10 bool "SolutionEngine" 25 bool "SolutionEngine"
11 select SOLUTION_ENGINE 26 select SOLUTION_ENGINE
diff --git a/arch/sh/boards/Makefile b/arch/sh/boards/Makefile
index 975a0f64ff20..cea300362035 100644
--- a/arch/sh/boards/Makefile
+++ b/arch/sh/boards/Makefile
@@ -15,3 +15,5 @@ obj-$(CONFIG_SH_TITAN) += board-titan.o
15obj-$(CONFIG_SH_SH7757LCR) += board-sh7757lcr.o 15obj-$(CONFIG_SH_SH7757LCR) += board-sh7757lcr.o
16obj-$(CONFIG_SH_APSH4A3A) += board-apsh4a3a.o 16obj-$(CONFIG_SH_APSH4A3A) += board-apsh4a3a.o
17obj-$(CONFIG_SH_APSH4AD0A) += board-apsh4ad0a.o 17obj-$(CONFIG_SH_APSH4AD0A) += board-apsh4ad0a.o
18
19obj-$(CONFIG_SH_DEVICE_TREE) += of-generic.o
diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c
new file mode 100644
index 000000000000..71d890932151
--- /dev/null
+++ b/arch/sh/boards/of-generic.c
@@ -0,0 +1,113 @@
1/*
2 * SH generic board support, using device tree
3 *
4 * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/of.h>
12#include <linux/of_platform.h>
13#include <linux/of_fdt.h>
14#include <linux/of_iommu.h>
15#include <linux/clocksource.h>
16#include <linux/irqchip.h>
17#include <linux/clk-provider.h>
18#include <asm/machvec.h>
19#include <asm/rtc.h>
20
21static void noop(void)
22{
23}
24
25static int noopi(void)
26{
27 return 0;
28}
29
30static void __init sh_of_mem_reserve(void)
31{
32 early_init_fdt_reserve_self();
33 early_init_fdt_scan_reserved_mem();
34}
35
36static void __init sh_of_time_init(void)
37{
38 pr_info("SH generic board support: scanning for clocksource devices\n");
39 clocksource_probe();
40}
41
42static void __init sh_of_setup(char **cmdline_p)
43{
44 unflatten_device_tree();
45
46 board_time_init = sh_of_time_init;
47
48 sh_mv.mv_name = of_flat_dt_get_machine_name();
49 if (!sh_mv.mv_name)
50 sh_mv.mv_name = "Unknown SH model";
51
52 /* FIXME: register smp ops to use dt to find cpus, use
53 * cpu enable-method, and use irq controller's ipi
54 * functions. */
55}
56
57static int sh_of_irq_demux(int irq)
58{
59 /* FIXME: eventually this should not be used at all;
60 * the interrupt controller should set_handle_irq(). */
61 return irq;
62}
63
64static void __init sh_of_init_irq(void)
65{
66 pr_info("SH generic board support: scanning for interrupt controllers\n");
67 irqchip_init();
68}
69
70static int __init sh_of_clk_init(void)
71{
72#ifdef CONFIG_COMMON_CLK
73 /* Disabled pending move to COMMON_CLK framework. */
74 pr_info("SH generic board support: scanning for clk providers\n");
75 of_clk_init(NULL);
76#endif
77 return 0;
78}
79
80static struct sh_machine_vector __initmv sh_of_generic_mv = {
81 .mv_setup = sh_of_setup,
82 .mv_name = "devicetree", /* replaced by DT root's model */
83 .mv_irq_demux = sh_of_irq_demux,
84 .mv_init_irq = sh_of_init_irq,
85 .mv_clk_init = sh_of_clk_init,
86 .mv_mode_pins = noopi,
87 .mv_mem_init = noop,
88 .mv_mem_reserve = sh_of_mem_reserve,
89};
90
91struct sh_clk_ops;
92
93void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
94{
95}
96
97void __init plat_irq_setup(void)
98{
99}
100
101static int __init sh_of_device_init(void)
102{
103 pr_info("SH generic board support: populating platform devices\n");
104 if (of_have_populated_dt()) {
105 of_iommu_init();
106 of_platform_populate(NULL, of_default_bus_match_table,
107 NULL, NULL);
108 } else {
109 pr_crit("Device tree not populated\n");
110 }
111 return 0;
112}
113arch_initcall_sync(sh_of_device_init);
diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S
index 7db248936b60..974bc152cc84 100644
--- a/arch/sh/kernel/head_32.S
+++ b/arch/sh/kernel/head_32.S
@@ -66,6 +66,10 @@ ENTRY(_stext)
66 mov #0, r0 66 mov #0, r0
67 ldc r0, r6_bank 67 ldc r0, r6_bank
68#endif 68#endif
69
70#ifdef CONFIG_OF
71 mov r4, r12 ! Store device tree blob pointer in r12
72#endif
69 73
70 /* 74 /*
71 * Prefetch if possible to reduce cache miss penalty. 75 * Prefetch if possible to reduce cache miss penalty.
@@ -314,6 +318,12 @@ ENTRY(_stext)
31410: 31810:
315#endif 319#endif
316 320
321#ifdef CONFIG_OF
322 mov.l 8f, r0 ! Make flat device tree available early.
323 jsr @r0
324 mov r12, r4
325#endif
326
317 ! Additional CPU initialization 327 ! Additional CPU initialization
318 mov.l 6f, r0 328 mov.l 6f, r0
319 jsr @r0 329 jsr @r0
@@ -339,6 +349,9 @@ ENTRY(stack_start)
3395: .long start_kernel 3495: .long start_kernel
3406: .long cpu_init 3506: .long cpu_init
3417: .long init_thread_union 3517: .long init_thread_union
352#if defined(CONFIG_OF)
3538: .long sh_fdt_init
354#endif
342 355
343#ifdef CONFIG_PMB 356#ifdef CONFIG_PMB
344.LPMB_ADDR: .long PMB_ADDR 357.LPMB_ADDR: .long PMB_ADDR
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index de19cfa768f2..efb60ce720a7 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -29,6 +29,8 @@
29#include <linux/delay.h> 29#include <linux/delay.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/memblock.h> 31#include <linux/memblock.h>
32#include <linux/of.h>
33#include <linux/of_fdt.h>
32#include <asm/uaccess.h> 34#include <asm/uaccess.h>
33#include <asm/io.h> 35#include <asm/io.h>
34#include <asm/page.h> 36#include <asm/page.h>
@@ -172,6 +174,7 @@ disable:
172#endif 174#endif
173} 175}
174 176
177#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
175void calibrate_delay(void) 178void calibrate_delay(void)
176{ 179{
177 struct clk *clk = clk_get(NULL, "cpu_clk"); 180 struct clk *clk = clk_get(NULL, "cpu_clk");
@@ -187,6 +190,7 @@ void calibrate_delay(void)
187 (loops_per_jiffy/(5000/HZ)) % 100, 190 (loops_per_jiffy/(5000/HZ)) % 100,
188 loops_per_jiffy); 191 loops_per_jiffy);
189} 192}
193#endif
190 194
191void __init __add_active_range(unsigned int nid, unsigned long start_pfn, 195void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
192 unsigned long end_pfn) 196 unsigned long end_pfn)
@@ -238,6 +242,29 @@ void __init __weak plat_early_device_setup(void)
238{ 242{
239} 243}
240 244
245#ifdef CONFIG_OF
246void __ref sh_fdt_init(phys_addr_t dt_phys)
247{
248 static int done = 0;
249 void *dt_virt;
250
251 /* Avoid calling an __init function on secondary cpus. */
252 if (done) return;
253
254 dt_virt = phys_to_virt(dt_phys);
255
256 if (!dt_virt || !early_init_dt_scan(dt_virt)) {
257 pr_crit("Error: invalid device tree blob"
258 " at physical address %p\n", (void *)dt_phys);
259
260 while (true)
261 cpu_relax();
262 }
263
264 done = 1;
265}
266#endif
267
241void __init setup_arch(char **cmdline_p) 268void __init setup_arch(char **cmdline_p)
242{ 269{
243 enable_mmu(); 270 enable_mmu();