Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ Table of Contents
    2) Entry point for arch/powerpc
    3) Entry point for arch/x86
    4) Entry point for arch/mips/bmips
    5) Entry point for arch/sh

  II - The DT block format
    1) Header
@@ -316,6 +317,18 @@ it with special cases.
  This convention is defined for 32-bit systems only, as there are not
  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
========================

+1 −0
Original line number Diff line number Diff line
config SUPERH
	def_bool y
	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
	select ARCH_MIGHT_HAVE_PC_PARPORT
	select HAVE_PATA_PLATFORM
	select CLKDEV_LOOKUP
+15 −0
Original line number Diff line number Diff line
@@ -6,6 +6,21 @@ config SOLUTION_ENGINE
config SH_ALPHA_BOARD
	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
	bool "SolutionEngine"
	select SOLUTION_ENGINE
+2 −0
Original line number Diff line number Diff line
@@ -15,3 +15,5 @@ obj-$(CONFIG_SH_TITAN) += board-titan.o
obj-$(CONFIG_SH_SH7757LCR)	+= board-sh7757lcr.o
obj-$(CONFIG_SH_APSH4A3A)	+= board-apsh4a3a.o
obj-$(CONFIG_SH_APSH4AD0A)	+= board-apsh4ad0a.o

obj-$(CONFIG_SH_DEVICE_TREE)	+= of-generic.o
+196 −0
Original line number Diff line number Diff line
/*
 * 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);
Loading