Skip to content

Commit 7480e0a

Browse files
author
Rich Felker
committed
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>
1 parent 45624ac commit 7480e0a

File tree

6 files changed

+183
-0
lines changed

6 files changed

+183
-0
lines changed

Documentation/devicetree/booting-without-of.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Table of Contents
1616
2) Entry point for arch/powerpc
1717
3) Entry point for arch/x86
1818
4) Entry point for arch/mips/bmips
19+
5) Entry point for arch/sh
1920

2021
II - The DT block format
2122
1) Header
@@ -316,6 +317,18 @@ it with special cases.
316317
This convention is defined for 32-bit systems only, as there are not
317318
currently any 64-bit BMIPS implementations.
318319

320+
5) Entry point for arch/sh
321+
--------------------------
322+
323+
Device-tree-compatible SH bootloaders are expected to provide the physical
324+
address of the device tree blob in r4. Since legacy bootloaders did not
325+
guarantee any particular initial register state, kernels built to
326+
inter-operate with old bootloaders must either use a builtin DTB or
327+
select a legacy board option (something other than CONFIG_SH_DEVICE_TREE)
328+
that does not use device tree. Support for the latter is being phased out
329+
in favor of device tree.
330+
331+
319332
II - The DT block format
320333
========================
321334

arch/sh/boards/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ config SOLUTION_ENGINE
66
config SH_ALPHA_BOARD
77
bool
88

9+
config 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+
924
config SH_SOLUTION_ENGINE
1025
bool "SolutionEngine"
1126
select SOLUTION_ENGINE

arch/sh/boards/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ obj-$(CONFIG_SH_TITAN) += board-titan.o
1515
obj-$(CONFIG_SH_SH7757LCR) += board-sh7757lcr.o
1616
obj-$(CONFIG_SH_APSH4A3A) += board-apsh4a3a.o
1717
obj-$(CONFIG_SH_APSH4AD0A) += board-apsh4ad0a.o
18+
19+
obj-$(CONFIG_SH_DEVICE_TREE) += of-generic.o

arch/sh/boards/of-generic.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
21+
static void noop(void)
22+
{
23+
}
24+
25+
static int noopi(void)
26+
{
27+
return 0;
28+
}
29+
30+
static void __init sh_of_mem_reserve(void)
31+
{
32+
early_init_fdt_reserve_self();
33+
early_init_fdt_scan_reserved_mem();
34+
}
35+
36+
static 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+
42+
static 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+
57+
static 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+
64+
static 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+
70+
static 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+
80+
static 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+
91+
struct sh_clk_ops;
92+
93+
void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
94+
{
95+
}
96+
97+
void __init plat_irq_setup(void)
98+
{
99+
}
100+
101+
static 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+
}
113+
arch_initcall_sync(sh_of_device_init);

arch/sh/kernel/head_32.S

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ ENTRY(_stext)
6666
mov #0, r0
6767
ldc r0, r6_bank
6868
#endif
69+
70+
#ifdef CONFIG_OF
71+
mov r4, r12 ! Store device tree blob pointer in r12
72+
#endif
6973
7074
/*
7175
* Prefetch if possible to reduce cache miss penalty.
@@ -314,6 +318,12 @@ ENTRY(_stext)
314318
10:
315319
#endif
316320

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+
317327
! Additional CPU initialization
318328
mov.l 6f, r0
319329
jsr @r0
@@ -339,6 +349,9 @@ ENTRY(stack_start)
339349
5: .long start_kernel
340350
6: .long cpu_init
341351
7: .long init_thread_union
352+
#if defined(CONFIG_OF)
353+
8: .long sh_fdt_init
354+
#endif
342355

343356
#ifdef CONFIG_PMB
344357
.LPMB_ADDR: .long PMB_ADDR

arch/sh/kernel/setup.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include <linux/delay.h>
3030
#include <linux/platform_device.h>
3131
#include <linux/memblock.h>
32+
#include <linux/of.h>
33+
#include <linux/of_fdt.h>
3234
#include <asm/uaccess.h>
3335
#include <asm/io.h>
3436
#include <asm/page.h>
@@ -172,6 +174,7 @@ void __init check_for_initrd(void)
172174
#endif
173175
}
174176

177+
#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
175178
void calibrate_delay(void)
176179
{
177180
struct clk *clk = clk_get(NULL, "cpu_clk");
@@ -187,6 +190,7 @@ void calibrate_delay(void)
187190
(loops_per_jiffy/(5000/HZ)) % 100,
188191
loops_per_jiffy);
189192
}
193+
#endif
190194

191195
void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
192196
unsigned long end_pfn)
@@ -238,6 +242,29 @@ void __init __weak plat_early_device_setup(void)
238242
{
239243
}
240244

245+
#ifdef CONFIG_OF
246+
void __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+
241268
void __init setup_arch(char **cmdline_p)
242269
{
243270
enable_mmu();

0 commit comments

Comments
 (0)