Commit b31a3bc3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'tag-sh-for-4.6' of git://git.libc.org/linux-sh

Pull arch/sh updates from Rich Felker:
 "This includes minor cleanups, a fix for a crash that likely affects
  all sh models with MMU, and introduction of a framework for boards
  described by device tree, which sets the stage for future J2 support"

* tag 'tag-sh-for-4.6' of git://git.libc.org/linux-sh:
  sched/preempt, sh: kmap_coherent relies on disabled preemption
  sh: add SMP method selection to device tree pseudo-board
  sh: add device tree support and generic board using device tree
  sh: remove arch-specific localtimer and use generic one
  sh: make MMU-specific SMP code conditional on CONFIG_MMU
  sh: provide unified syscall trap compatible with all SH models
  sh: New gcc support
  sh: Disable trace for kernel uncompressing.
  sh: Use generic clkdev.h header
parents d5e2d008 b15d53d0
...@@ -16,6 +16,7 @@ Table of Contents ...@@ -16,6 +16,7 @@ Table of Contents
2) Entry point for arch/powerpc 2) Entry point for arch/powerpc
3) Entry point for arch/x86 3) Entry point for arch/x86
4) Entry point for arch/mips/bmips 4) Entry point for arch/mips/bmips
5) Entry point for arch/sh
II - The DT block format II - The DT block format
1) Header 1) Header
...@@ -316,6 +317,18 @@ it with special cases. ...@@ -316,6 +317,18 @@ it with special cases.
This convention is defined for 32-bit systems only, as there are not This convention is defined for 32-bit systems only, as there are not
currently any 64-bit BMIPS implementations. currently any 64-bit BMIPS implementations.
5) Entry point for arch/sh
--------------------------
Device-tree-compatible SH bootloaders are expected to provide the physical
address of the device tree blob in r4. Since legacy bootloaders did not
guarantee any particular initial register state, kernels built to
inter-operate with old bootloaders must either use a builtin DTB or
select a legacy board option (something other than CONFIG_SH_DEVICE_TREE)
that does not use device tree. Support for the latter is being phased out
in favor of device tree.
II - The DT block format II - The DT block format
======================== ========================
......
config SUPERH config SUPERH
def_bool y def_bool y
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_PARPORT
select HAVE_PATA_PLATFORM select HAVE_PATA_PLATFORM
select CLKDEV_LOOKUP select CLKDEV_LOOKUP
......
...@@ -6,6 +6,21 @@ config SOLUTION_ENGINE ...@@ -6,6 +6,21 @@ config SOLUTION_ENGINE
config SH_ALPHA_BOARD config SH_ALPHA_BOARD
bool bool
config SH_DEVICE_TREE
bool "Board Described by Device Tree"
select OF
select OF_EARLY_FLATTREE
select CLKSRC_OF
select GENERIC_CALIBRATE_DELAY
help
Select Board Described by Device Tree to build a kernel that
does not hard-code any board-specific knowledge but instead uses
a device tree blob provided by the boot-loader. You must enable
drivers for any hardware you want to use separately. At this
time, only boards based on the open-hardware J-Core processors
have sufficient driver coverage to use this option; do not
select it if you are using original SuperH hardware.
config SH_SOLUTION_ENGINE config SH_SOLUTION_ENGINE
bool "SolutionEngine" bool "SolutionEngine"
select SOLUTION_ENGINE select SOLUTION_ENGINE
......
...@@ -15,3 +15,5 @@ obj-$(CONFIG_SH_TITAN) += board-titan.o ...@@ -15,3 +15,5 @@ obj-$(CONFIG_SH_TITAN) += board-titan.o
obj-$(CONFIG_SH_SH7757LCR) += board-sh7757lcr.o obj-$(CONFIG_SH_SH7757LCR) += board-sh7757lcr.o
obj-$(CONFIG_SH_APSH4A3A) += board-apsh4a3a.o obj-$(CONFIG_SH_APSH4A3A) += board-apsh4a3a.o
obj-$(CONFIG_SH_APSH4AD0A) += board-apsh4ad0a.o obj-$(CONFIG_SH_APSH4AD0A) += board-apsh4ad0a.o
obj-$(CONFIG_SH_DEVICE_TREE) += of-generic.o
/*
* SH generic board support, using device tree
*
* Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
*
* 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/of.h>
#include <linux/of_platform.h>
#include <linux/of_fdt.h>
#include <linux/of_iommu.h>
#include <linux/clocksource.h>
#include <linux/irqchip.h>
#include <linux/clk-provider.h>
#include <asm/machvec.h>
#include <asm/rtc.h>
#ifdef CONFIG_SMP
static void dummy_smp_setup(void)
{
}
static void dummy_prepare_cpus(unsigned int max_cpus)
{
}
static void dummy_start_cpu(unsigned int cpu, unsigned long entry_point)
{
}
static unsigned int dummy_smp_processor_id(void)
{
return 0;
}
static void dummy_send_ipi(unsigned int cpu, unsigned int message)
{
}
static struct plat_smp_ops dummy_smp_ops = {
.smp_setup = dummy_smp_setup,
.prepare_cpus = dummy_prepare_cpus,
.start_cpu = dummy_start_cpu,
.smp_processor_id = dummy_smp_processor_id,
.send_ipi = dummy_send_ipi,
.cpu_die = native_cpu_die,
.cpu_disable = native_cpu_disable,
.play_dead = native_play_dead,
};
extern const struct of_cpu_method __cpu_method_of_table[];
const struct of_cpu_method __cpu_method_of_table_sentinel
__section(__cpu_method_of_table_end);
static void sh_of_smp_probe(void)
{
struct device_node *np = 0;
const char *method = 0;
const struct of_cpu_method *m = __cpu_method_of_table;
pr_info("SH generic board support: scanning for cpus\n");
init_cpu_possible(cpumask_of(0));
while ((np = of_find_node_by_type(np, "cpu"))) {
const __be32 *cell = of_get_property(np, "reg", NULL);
u64 id = -1;
if (cell) id = of_read_number(cell, of_n_addr_cells(np));
if (id < NR_CPUS) {
if (!method)
of_property_read_string(np, "enable-method", &method);
set_cpu_possible(id, true);
set_cpu_present(id, true);
__cpu_number_map[id] = id;
__cpu_logical_map[id] = id;
}
}
if (!method) {
np = of_find_node_by_name(NULL, "cpus");
of_property_read_string(np, "enable-method", &method);
}
pr_info("CPU enable method: %s\n", method);
if (method)
for (; m->method; m++)
if (!strcmp(m->method, method)) {
register_smp_ops(m->ops);
return;
}
register_smp_ops(&dummy_smp_ops);
}
#else
static void sh_of_smp_probe(void)
{
}
#endif
static void noop(void)
{
}
static int noopi(void)
{
return 0;
}
static void __init sh_of_mem_reserve(void)
{
early_init_fdt_reserve_self();
early_init_fdt_scan_reserved_mem();
}
static void __init sh_of_time_init(void)
{
pr_info("SH generic board support: scanning for clocksource devices\n");
clocksource_probe();
}
static void __init sh_of_setup(char **cmdline_p)
{
unflatten_device_tree();
board_time_init = sh_of_time_init;
sh_mv.mv_name = of_flat_dt_get_machine_name();
if (!sh_mv.mv_name)
sh_mv.mv_name = "Unknown SH model";
sh_of_smp_probe();
}
static int sh_of_irq_demux(int irq)
{
/* FIXME: eventually this should not be used at all;
* the interrupt controller should set_handle_irq(). */
return irq;
}
static void __init sh_of_init_irq(void)
{
pr_info("SH generic board support: scanning for interrupt controllers\n");
irqchip_init();
}
static int __init sh_of_clk_init(void)
{
#ifdef CONFIG_COMMON_CLK
/* Disabled pending move to COMMON_CLK framework. */
pr_info("SH generic board support: scanning for clk providers\n");
of_clk_init(NULL);
#endif
return 0;
}
static struct sh_machine_vector __initmv sh_of_generic_mv = {
.mv_setup = sh_of_setup,
.mv_name = "devicetree", /* replaced by DT root's model */
.mv_irq_demux = sh_of_irq_demux,
.mv_init_irq = sh_of_init_irq,
.mv_clk_init = sh_of_clk_init,
.mv_mode_pins = noopi,
.mv_mem_init = noop,
.mv_mem_reserve = sh_of_mem_reserve,
};
struct sh_clk_ops;
void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
}
void __init plat_irq_setup(void)
{
}
static int __init sh_of_device_init(void)
{
pr_info("SH generic board support: populating platform devices\n");
if (of_have_populated_dt()) {
of_iommu_init();
of_platform_populate(NULL, of_default_bus_match_table,
NULL, NULL);
} else {
pr_crit("Device tree not populated\n");
}
return 0;
}
arch_initcall_sync(sh_of_device_init);
...@@ -48,7 +48,7 @@ ifeq ($(BITS),64) ...@@ -48,7 +48,7 @@ ifeq ($(BITS),64)
lib1funcs-dir := $(addsuffix $(BITS), $(lib1funcs-dir)) lib1funcs-dir := $(addsuffix $(BITS), $(lib1funcs-dir))
endif endif
KBUILD_CFLAGS += -I$(lib1funcs-dir) KBUILD_CFLAGS += -I$(lib1funcs-dir) -DDISABLE_BRANCH_PROFILING
$(addprefix $(obj)/,$(lib1funcs-y)): $(obj)/%: $(lib1funcs-dir)/% FORCE $(addprefix $(obj)/,$(lib1funcs-y)): $(obj)/%: $(lib1funcs-dir)/% FORCE
$(call cmd,shipped) $(call cmd,shipped)
......
generic-y += bitsperlong.h generic-y += bitsperlong.h
generic-y += clkdev.h
generic-y += cputime.h generic-y += cputime.h
generic-y += current.h generic-y += current.h
generic-y += delay.h generic-y += delay.h
......
/*
* Copyright (C) 2010 Paul Mundt <lethal@linux-sh.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Helper for the clk API to assist looking up a struct clk.
*/
#ifndef __CLKDEV__H_
#define __CLKDEV__H_
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/clock.h>
static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
{
if (!slab_is_available())
return alloc_bootmem_low_pages(size);
else
return kzalloc(size, GFP_KERNEL);
}
#ifndef CONFIG_COMMON_CLK
#define __clk_put(clk)
#define __clk_get(clk) ({ 1; })
#endif
#endif /* __CLKDEV_H__ */
...@@ -69,6 +69,16 @@ static inline int hard_smp_processor_id(void) ...@@ -69,6 +69,16 @@ static inline int hard_smp_processor_id(void)
return mp_ops->smp_processor_id(); return mp_ops->smp_processor_id();
} }
struct of_cpu_method {
const char *method;
struct plat_smp_ops *ops;
};
#define CPU_METHOD_OF_DECLARE(name, _method, _ops) \
static const struct of_cpu_method __cpu_method_of_table_##name \
__used __section(__cpu_method_of_table) \
= { .method = _method, .ops = _ops }
#else #else
#define hard_smp_processor_id() (0) #define hard_smp_processor_id() (0)
......
...@@ -46,6 +46,5 @@ obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o ...@@ -46,6 +46,5 @@ obj-$(CONFIG_DWARF_UNWINDER) += dwarf.o
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_callchain.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += localtimer.o
ccflags-y := -Werror ccflags-y := -Werror
...@@ -144,9 +144,9 @@ ENTRY(exception_handler) ...@@ -144,9 +144,9 @@ ENTRY(exception_handler)
mov #64,r8 mov #64,r8
cmp/hs r8,r9 cmp/hs r8,r9
bt interrupt_entry ! vec >= 64 is interrupt bt interrupt_entry ! vec >= 64 is interrupt
mov #32,r8 mov #31,r8
cmp/hs r8,r9 cmp/hs r8,r9
bt trap_entry ! 64 > vec >= 32 is trap bt trap_entry ! 64 > vec >= 31 is trap
mov.l 4f,r8 mov.l 4f,r8
mov r9,r4 mov r9,r4
...@@ -178,9 +178,9 @@ interrupt_entry: ...@@ -178,9 +178,9 @@ interrupt_entry:
trap_entry: trap_entry:
mov #0x30,r8 mov #0x30,r8
cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall cmp/ge r8,r9 ! vector 0x1f-0x2f is systemcall
bt 1f bt 1f
add #-0x10,r9 ! convert SH2 to SH3/4 ABI mov #0x1f,r9 ! convert to unified SH2/3/4 trap number
1: 1:
shll2 r9 ! TRA shll2 r9 ! TRA
bra system_call ! jump common systemcall entry bra system_call ! jump common systemcall entry
......
...@@ -109,9 +109,9 @@ ENTRY(exception_handler) ...@@ -109,9 +109,9 @@ ENTRY(exception_handler)
mov #64,r8 mov #64,r8
cmp/hs r8,r9 cmp/hs r8,r9
bt interrupt_entry ! vec >= 64 is interrupt bt interrupt_entry ! vec >= 64 is interrupt
mov #32,r8 mov #31,r8
cmp/hs r8,r9 cmp/hs r8,r9
bt trap_entry ! 64 > vec >= 32 is trap bt trap_entry ! 64 > vec >= 31 is trap
mov.l 4f,r8 mov.l 4f,r8
mov r9,r4 mov r9,r4
...@@ -143,9 +143,9 @@ interrupt_entry: ...@@ -143,9 +143,9 @@ interrupt_entry:
trap_entry: trap_entry:
mov #0x30,r8 mov #0x30,r8
cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall cmp/ge r8,r9 ! vector 0x1f-0x2f is systemcall
bt 1f bt 1f
add #-0x10,r9 ! convert SH2 to SH3/4 ABI mov #0x1f,r9 ! convert to unified SH2/3/4 trap number
1: 1:
shll2 r9 ! TRA shll2 r9 ! TRA
bra system_call ! jump common systemcall entry bra system_call ! jump common systemcall entry
......
...@@ -268,20 +268,29 @@ debug_trap: ...@@ -268,20 +268,29 @@ debug_trap:
* Syscall #: R3 * Syscall #: R3
* Arguments #0 to #3: R4--R7 * Arguments #0 to #3: R4--R7
* Arguments #4 to #6: R0, R1, R2 * Arguments #4 to #6: R0, R1, R2
* TRA: (number of arguments + ABI revision) x 4 * TRA: See following table.
* *
* This code also handles delegating other traps to the BIOS/gdb stub
* according to:
*
* Trap number
* (TRA>>2) Purpose * (TRA>>2) Purpose
* -------- ------- * -------- -------
* 0x00-0x0f original SH-3/4 syscall ABI (not in general use). * 0x00-0x0f original SH-3/4 syscall ABI (not in general use).
* 0x10-0x1f general SH-3/4 syscall ABI. * 0x10-0x1f general SH-3/4 syscall ABI.
* 0x20-0x2f syscall ABI for SH-2 parts. * 0x1f unified SH-2/3/4 syscall ABI (preferred).
* 0x20-0x2f original SH-2 syscall ABI.
* 0x30-0x3f debug traps used by the kernel. * 0x30-0x3f debug traps used by the kernel.
* 0x40-0xff Not supported by all parts, so left unhandled. * 0x40-0xff Not supported by all parts, so left unhandled.
* *
* For making system calls, any trap number in the range for the
* given cpu model may be used, but the unified trap number 0x1f is
* preferred for compatibility with all models.
*
* The low bits of the trap number were once documented as matching
* the number of arguments, but they were never actually used as such
* by the kernel. SH-2 originally used its own separate trap range
* because several hardware exceptions fell in the range used for the
* SH-3/4 syscall ABI.
*
* This code also handles delegating other traps to the BIOS/gdb stub.
*
* Note: When we're first called, the TRA value must be shifted * Note: When we're first called, the TRA value must be shifted
* right 2 bits in order to get the value that was used as the "trapa" * right 2 bits in order to get the value that was used as the "trapa"
* argument. * argument.
......
...@@ -66,6 +66,10 @@ ENTRY(_stext) ...@@ -66,6 +66,10 @@ ENTRY(_stext)
mov #0, r0 mov #0, r0
ldc r0, r6_bank ldc r0, r6_bank
#endif #endif
#ifdef CONFIG_OF
mov r4, r12 ! Store device tree blob pointer in r12
#endif
/* /*
* Prefetch if possible to reduce cache miss penalty. * Prefetch if possible to reduce cache miss penalty.
...@@ -314,6 +318,12 @@ ENTRY(_stext) ...@@ -314,6 +318,12 @@ ENTRY(_stext)
10: 10:
#endif #endif
#ifdef CONFIG_OF
mov.l 8f, r0 ! Make flat device tree available early.
jsr @r0
mov r12, r4
#endif
! Additional CPU initialization ! Additional CPU initialization
mov.l 6f, r0 mov.l 6f, r0
jsr @r0 jsr @r0
...@@ -339,6 +349,9 @@ ENTRY(stack_start) ...@@ -339,6 +349,9 @@ ENTRY(stack_start)
5: .long start_kernel 5: .long start_kernel
6: .long cpu_init 6: .long cpu_init
7: .long init_thread_union 7: .long init_thread_union
#if defined(CONFIG_OF)
8: .long sh_fdt_init
#endif
#ifdef CONFIG_PMB #ifdef CONFIG_PMB
.LPMB_ADDR: .long PMB_ADDR .LPMB_ADDR: .long PMB_ADDR
......
/*
* Dummy local timer
*
* Copyright (C) 2008 Paul Mundt
*
* cloned from:
*
* linux/arch/arm/mach-realview/localtimer.c
*
* Copyright (C) 2002 ARM Ltd.
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/smp.h>
#include <linux/jiffies.h>
#include <linux/percpu.h>
#include <linux/clockchips.h>
#include <linux/hardirq.h>
#include <linux/irq.h>
static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
/*
* Used on SMP for either the local timer or SMP_MSG_TIMER
*/
void local_timer_interrupt(void)
{
struct clock_event_device *clk = this_cpu_ptr(&local_clockevent);
irq_enter();
clk->event_handler(clk);
irq_exit();
}
void local_timer_setup(unsigned int cpu)
{
struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
clk->name = "dummy_timer";
clk->features = CLOCK_EVT_FEAT_ONESHOT |
CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_DUMMY;
clk->rating = 400;
clk->mult = 1;
clk->broadcast = smp_timer_broadcast;
clk->cpumask = cpumask_of(cpu);
clockevents_register_device(clk);
}
void local_timer_stop(unsigned int cpu)
{
}
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>