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
This commit is contained in:
@@ -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.
|
|||||||
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
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
||||||
|
|||||||
196
arch/sh/boards/of-generic.c
Normal file
196
arch/sh/boards/of-generic.c
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* 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)
|
|||||||
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)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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)
|
|||||||
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
|
|||||||
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)
|
|||||||
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:
|
|||||||
|
|
||||||
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)
|
|||||||
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:
|
|||||||
|
|
||||||
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:
|
|||||||
* 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.
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ ENTRY(_stext)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 @@
|
|||||||
#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>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
@@ -172,6 +174,7 @@ disable:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
|
||||||
void calibrate_delay(void)
|
void calibrate_delay(void)
|
||||||
{
|
{
|
||||||
struct clk *clk = clk_get(NULL, "cpu_clk");
|
struct clk *clk = clk_get(NULL, "cpu_clk");
|
||||||
@@ -187,6 +190,7 @@ void calibrate_delay(void)
|
|||||||
(loops_per_jiffy/(5000/HZ)) % 100,
|
(loops_per_jiffy/(5000/HZ)) % 100,
|
||||||
loops_per_jiffy);
|
loops_per_jiffy);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
|
void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
|
||||||
unsigned long end_pfn)
|
unsigned long end_pfn)
|
||||||
@@ -238,6 +242,29 @@ void __init __weak plat_early_device_setup(void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
void __ref sh_fdt_init(phys_addr_t dt_phys)
|
||||||
|
{
|
||||||
|
static int done = 0;
|
||||||
|
void *dt_virt;
|
||||||
|
|
||||||
|
/* Avoid calling an __init function on secondary cpus. */
|
||||||
|
if (done) return;
|
||||||
|
|
||||||
|
dt_virt = phys_to_virt(dt_phys);
|
||||||
|
|
||||||
|
if (!dt_virt || !early_init_dt_scan(dt_virt)) {
|
||||||
|
pr_crit("Error: invalid device tree blob"
|
||||||
|
" at physical address %p\n", (void *)dt_phys);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
cpu_relax();
|
||||||
|
}
|
||||||
|
|
||||||
|
done = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void __init setup_arch(char **cmdline_p)
|
void __init setup_arch(char **cmdline_p)
|
||||||
{
|
{
|
||||||
enable_mmu();
|
enable_mmu();
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ DECLARE_EXPORT(__sdivsi3);
|
|||||||
DECLARE_EXPORT(__lshrsi3);
|
DECLARE_EXPORT(__lshrsi3);
|
||||||
DECLARE_EXPORT(__ashrsi3);
|
DECLARE_EXPORT(__ashrsi3);
|
||||||
DECLARE_EXPORT(__ashlsi3);
|
DECLARE_EXPORT(__ashlsi3);
|
||||||
|
DECLARE_EXPORT(__lshrsi3_r0);
|
||||||
|
DECLARE_EXPORT(__ashrsi3_r0);
|
||||||
|
DECLARE_EXPORT(__ashlsi3_r0);
|
||||||
DECLARE_EXPORT(__ashiftrt_r4_6);
|
DECLARE_EXPORT(__ashiftrt_r4_6);
|
||||||
DECLARE_EXPORT(__ashiftrt_r4_7);
|
DECLARE_EXPORT(__ashiftrt_r4_7);
|
||||||
DECLARE_EXPORT(__ashiftrt_r4_8);
|
DECLARE_EXPORT(__ashiftrt_r4_8);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
|
#include <linux/clockchips.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
@@ -140,17 +141,14 @@ int __cpu_disable(void)
|
|||||||
*/
|
*/
|
||||||
migrate_irqs();
|
migrate_irqs();
|
||||||
|
|
||||||
/*
|
|
||||||
* Stop the local timer for this CPU.
|
|
||||||
*/
|
|
||||||
local_timer_stop(cpu);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flush user cache and TLB mappings, and then remove this CPU
|
* Flush user cache and TLB mappings, and then remove this CPU
|
||||||
* from the vm mask set of all processes.
|
* from the vm mask set of all processes.
|
||||||
*/
|
*/
|
||||||
flush_cache_all();
|
flush_cache_all();
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
local_flush_tlb_all();
|
local_flush_tlb_all();
|
||||||
|
#endif
|
||||||
|
|
||||||
clear_tasks_mm_cpumask(cpu);
|
clear_tasks_mm_cpumask(cpu);
|
||||||
|
|
||||||
@@ -183,8 +181,10 @@ asmlinkage void start_secondary(void)
|
|||||||
atomic_inc(&mm->mm_count);
|
atomic_inc(&mm->mm_count);
|
||||||
atomic_inc(&mm->mm_users);
|
atomic_inc(&mm->mm_users);
|
||||||
current->active_mm = mm;
|
current->active_mm = mm;
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
enter_lazy_tlb(mm, current);
|
enter_lazy_tlb(mm, current);
|
||||||
local_flush_tlb_all();
|
local_flush_tlb_all();
|
||||||
|
#endif
|
||||||
|
|
||||||
per_cpu_trap_init();
|
per_cpu_trap_init();
|
||||||
|
|
||||||
@@ -194,8 +194,6 @@ asmlinkage void start_secondary(void)
|
|||||||
|
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
/* Enable local timers */
|
|
||||||
local_timer_setup(cpu);
|
|
||||||
calibrate_delay();
|
calibrate_delay();
|
||||||
|
|
||||||
smp_store_cpu_info(cpu);
|
smp_store_cpu_info(cpu);
|
||||||
@@ -285,7 +283,8 @@ void arch_send_call_function_single_ipi(int cpu)
|
|||||||
mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE);
|
mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void smp_timer_broadcast(const struct cpumask *mask)
|
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
|
void tick_broadcast(const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
@@ -296,9 +295,10 @@ void smp_timer_broadcast(const struct cpumask *mask)
|
|||||||
static void ipi_timer(void)
|
static void ipi_timer(void)
|
||||||
{
|
{
|
||||||
irq_enter();
|
irq_enter();
|
||||||
local_timer_interrupt();
|
tick_receive_broadcast();
|
||||||
irq_exit();
|
irq_exit();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void smp_message_recv(unsigned int msg)
|
void smp_message_recv(unsigned int msg)
|
||||||
{
|
{
|
||||||
@@ -312,9 +312,11 @@ void smp_message_recv(unsigned int msg)
|
|||||||
case SMP_MSG_FUNCTION_SINGLE:
|
case SMP_MSG_FUNCTION_SINGLE:
|
||||||
generic_smp_call_function_single_interrupt();
|
generic_smp_call_function_single_interrupt();
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
case SMP_MSG_TIMER:
|
case SMP_MSG_TIMER:
|
||||||
ipi_timer();
|
ipi_timer();
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
printk(KERN_WARNING "SMP %d: %s(): unknown IPI %d\n",
|
printk(KERN_WARNING "SMP %d: %s(): unknown IPI %d\n",
|
||||||
smp_processor_id(), __func__, msg);
|
smp_processor_id(), __func__, msg);
|
||||||
@@ -328,6 +330,8 @@ int setup_profiling_timer(unsigned int multiplier)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
|
|
||||||
static void flush_tlb_all_ipi(void *info)
|
static void flush_tlb_all_ipi(void *info)
|
||||||
{
|
{
|
||||||
local_flush_tlb_all();
|
local_flush_tlb_all();
|
||||||
@@ -467,3 +471,5 @@ void flush_tlb_one(unsigned long asid, unsigned long vaddr)
|
|||||||
smp_call_function(flush_tlb_one_ipi, (void *)&fd, 1);
|
smp_call_function(flush_tlb_one_ipi, (void *)&fd, 1);
|
||||||
local_flush_tlb_one(asid, vaddr);
|
local_flush_tlb_one(asid, vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -54,21 +54,38 @@ Boston, MA 02110-1301, USA. */
|
|||||||
!
|
!
|
||||||
! (none)
|
! (none)
|
||||||
!
|
!
|
||||||
|
! __ashlsi3_r0
|
||||||
|
!
|
||||||
|
! Entry:
|
||||||
|
!
|
||||||
|
! r4: Value to shift
|
||||||
|
! r0: Shifts
|
||||||
|
!
|
||||||
|
! Exit:
|
||||||
|
!
|
||||||
|
! r0: Result
|
||||||
|
!
|
||||||
|
! Destroys:
|
||||||
|
!
|
||||||
|
! (none)
|
||||||
|
|
||||||
|
|
||||||
.global __ashlsi3
|
.global __ashlsi3
|
||||||
|
.global __ashlsi3_r0
|
||||||
|
|
||||||
.align 2
|
.align 2
|
||||||
__ashlsi3:
|
__ashlsi3:
|
||||||
mov #31,r0
|
mov r5,r0
|
||||||
and r0,r5
|
.align 2
|
||||||
|
__ashlsi3_r0:
|
||||||
|
and #31,r0
|
||||||
|
mov.l r4,@-r15
|
||||||
|
mov r0,r4
|
||||||
mova ashlsi3_table,r0
|
mova ashlsi3_table,r0
|
||||||
mov.b @(r0,r5),r5
|
mov.b @(r0,r4),r4
|
||||||
#ifdef __sh1__
|
add r4,r0
|
||||||
add r5,r0
|
|
||||||
jmp @r0
|
jmp @r0
|
||||||
#else
|
mov.l @r15+,r0
|
||||||
braf r5
|
|
||||||
#endif
|
|
||||||
mov r4,r0
|
|
||||||
|
|
||||||
.align 2
|
.align 2
|
||||||
ashlsi3_table:
|
ashlsi3_table:
|
||||||
|
|||||||
@@ -54,22 +54,37 @@ Boston, MA 02110-1301, USA. */
|
|||||||
!
|
!
|
||||||
! (none)
|
! (none)
|
||||||
!
|
!
|
||||||
|
! __ashrsi3_r0
|
||||||
|
!
|
||||||
|
! Entry:
|
||||||
|
!
|
||||||
|
! r4: Value to shift
|
||||||
|
! r0: Shifts
|
||||||
|
!
|
||||||
|
! Exit:
|
||||||
|
!
|
||||||
|
! r0: Result
|
||||||
|
!
|
||||||
|
! Destroys:
|
||||||
|
!
|
||||||
|
! (none)
|
||||||
|
|
||||||
.global __ashrsi3
|
.global __ashrsi3
|
||||||
|
.global __ashrsi3_r0
|
||||||
|
|
||||||
.align 2
|
.align 2
|
||||||
__ashrsi3:
|
__ashrsi3:
|
||||||
mov #31,r0
|
mov r5,r0
|
||||||
and r0,r5
|
.align 2
|
||||||
|
__ashrsi3_r0:
|
||||||
|
and #31,r0
|
||||||
|
mov.l r4,@-r15
|
||||||
|
mov r0,r4
|
||||||
mova ashrsi3_table,r0
|
mova ashrsi3_table,r0
|
||||||
mov.b @(r0,r5),r5
|
mov.b @(r0,r4),r4
|
||||||
#ifdef __sh1__
|
add r4,r0
|
||||||
add r5,r0
|
|
||||||
jmp @r0
|
jmp @r0
|
||||||
#else
|
mov.l @r15+,r0
|
||||||
braf r5
|
|
||||||
#endif
|
|
||||||
mov r4,r0
|
|
||||||
|
|
||||||
.align 2
|
.align 2
|
||||||
ashrsi3_table:
|
ashrsi3_table:
|
||||||
|
|||||||
@@ -53,22 +53,38 @@ Boston, MA 02110-1301, USA. */
|
|||||||
! Destroys:
|
! Destroys:
|
||||||
!
|
!
|
||||||
! (none)
|
! (none)
|
||||||
|
!
|
||||||
|
! __lshrsi3_r0
|
||||||
|
!
|
||||||
|
! Entry:
|
||||||
|
!
|
||||||
|
! r0: Value to shift
|
||||||
|
! r5: Shifts
|
||||||
|
!
|
||||||
|
! Exit:
|
||||||
|
!
|
||||||
|
! r0: Result
|
||||||
|
!
|
||||||
|
! Destroys:
|
||||||
|
!
|
||||||
|
! (none)
|
||||||
!
|
!
|
||||||
.global __lshrsi3
|
.global __lshrsi3
|
||||||
|
.global __lshrsi3_r0
|
||||||
|
|
||||||
.align 2
|
.align 2
|
||||||
__lshrsi3:
|
__lshrsi3:
|
||||||
mov #31,r0
|
mov r5,r0
|
||||||
and r0,r5
|
.align 2
|
||||||
|
__lshrsi3_r0:
|
||||||
|
and #31,r0
|
||||||
|
mov.l r4,@-r15
|
||||||
|
mov r0,r4
|
||||||
mova lshrsi3_table,r0
|
mova lshrsi3_table,r0
|
||||||
mov.b @(r0,r5),r5
|
mov.b @(r0,r4),r4
|
||||||
#ifdef __sh1__
|
add r4,r0
|
||||||
add r5,r0
|
|
||||||
jmp @r0
|
jmp @r0
|
||||||
#else
|
mov.l @r15+,r0
|
||||||
braf r5
|
|
||||||
#endif
|
|
||||||
mov r4,r0
|
|
||||||
|
|
||||||
.align 2
|
.align 2
|
||||||
lshrsi3_table:
|
lshrsi3_table:
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
|
|||||||
|
|
||||||
BUG_ON(!test_bit(PG_dcache_clean, &page->flags));
|
BUG_ON(!test_bit(PG_dcache_clean, &page->flags));
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
idx = FIX_CMAP_END -
|
idx = FIX_CMAP_END -
|
||||||
@@ -64,4 +65,5 @@ void kunmap_coherent(void *kvaddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user