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

Commit 4980f9bc authored by Linus Walleij's avatar Linus Walleij Committed by Russell King
Browse files

ARM: 7517/1: integrator: initial device tree support



This is initial device tree support for the ARM Integrator family,
we create a very basic device tree, #ifdef out the non-DT machines
when compiling for device tree.

Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent dc81df52
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
ARM Integrator/AP (Application Platform) and Integrator/CP (Compact Platform)
-----------------------------------------------------------------------------
ARM's oldest Linux-supported platform with connectors for different core
tiles of ARMv4, ARMv5 and ARMv6 type.

Required properties (in root node):
	compatible = "arm,integrator-ap";  /* Application Platform */
	compatible = "arm,integrator-cp";  /* Compact Platform */

FPGA type interrupt controllers, see the versatile-fpga-irq binding doc.


ARM Versatile Application and Platform Baseboards
-------------------------------------------------
ARM's development hardware platform with connectors for customizable
+33 −0
Original line number Diff line number Diff line
/*
 * SoC core Device Tree for the ARM Integrator platforms
 */

/include/ "skeleton.dtsi"

/ {
	timer@13000000 {
		reg = <0x13000000 0x100>;
		interrupt-parent = <&pic>;
		interrupts = <5>;
	};

	timer@13000100 {
		reg = <0x13000100 0x100>;
		interrupt-parent = <&pic>;
		interrupts = <6>;
	};

	timer@13000200 {
		reg = <0x13000200 0x100>;
		interrupt-parent = <&pic>;
		interrupts = <7>;
	};

	pic@14000000 {
		compatible = "arm,versatile-fpga-irq";
		#interrupt-cells = <1>;
		interrupt-controller;
		reg = <0x14000000 0x100>;
		clear-mask = <0xffffffff>;
	};
};
+36 −0
Original line number Diff line number Diff line
/*
 * Device Tree for the ARM Integrator/AP platform
 */

/dts-v1/;
/include/ "integrator.dtsi"

/ {
	model = "ARM Integrator/AP";
	compatible = "arm,integrator-ap";

	aliases {
		arm,timer-primary = &timer2;
		arm,timer-secondary = &timer1;
	};

	chosen {
		bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk";
	};

	timer0: timer@13000000 {
		compatible = "arm,integrator-timer";
	};

	timer1: timer@13000100 {
		compatible = "arm,integrator-timer";
	};

	timer2: timer@13000200 {
		compatible = "arm,integrator-timer";
	};

	pic: pic@14000000 {
		valid-mask = <0x003fffff>;
	};
};
+54 −0
Original line number Diff line number Diff line
/*
 * Device Tree for the ARM Integrator/CP platform
 */

/dts-v1/;
/include/ "integrator.dtsi"

/ {
	model = "ARM Integrator/CP";
	compatible = "arm,integrator-cp";

	aliases {
		arm,timer-primary = &timer2;
		arm,timer-secondary = &timer1;
	};

	chosen {
		bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
	};

	timer0: timer@13000000 {
		compatible = "arm,sp804", "arm,primecell";
	};

	timer1: timer@13000100 {
		compatible = "arm,sp804", "arm,primecell";
	};

	timer2: timer@13000200 {
		compatible = "arm,sp804", "arm,primecell";
	};

	pic: pic@14000000 {
		valid-mask = <0x1fc003ff>;
	};

	cic: cic@10000040 {
		compatible = "arm,versatile-fpga-irq";
		#interrupt-cells = <1>;
		interrupt-controller;
		reg = <0x10000040 0x100>;
		clear-mask = <0xffffffff>;
		valid-mask = <0x00000007>;
	};

	sic: sic@ca000000 {
		compatible = "arm,versatile-fpga-irq";
		#interrupt-cells = <1>;
		interrupt-controller;
		reg = <0xca000000 0x100>;
		clear-mask = <0x00000fff>;
		valid-mask = <0x00000fff>;
	};
};
+114 −25
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@
#include <linux/mtd/physmap.h>
#include <linux/clk.h>
#include <linux/platform_data/clk-integrator.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <video/vga.h>

#include <mach/hardware.h>
@@ -161,23 +163,6 @@ static void __init ap_map_io(void)
	vga_base = PCI_MEMORY_VADDR;
}

#define INTEGRATOR_SC_VALID_INT	0x003fffff

static void __init ap_init_irq(void)
{
	/* Disable all interrupts initially. */
	/* Do the core module ones */
	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);

	/* do the header card stuff next */
	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);

	fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
		-1, INTEGRATOR_SC_VALID_INT, NULL);
	integrator_clk_init(false);
}

#ifdef CONFIG_PM
static unsigned long ic_irq_enable;

@@ -330,9 +315,9 @@ static u32 notrace integrator_read_sched_clock(void)
	return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
}

static void integrator_clocksource_init(unsigned long inrate)
static void integrator_clocksource_init(unsigned long inrate,
					void __iomem *base)
{
	void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
	u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
	unsigned long rate = inrate;

@@ -349,7 +334,7 @@ static void integrator_clocksource_init(unsigned long inrate)
	setup_sched_clock(integrator_read_sched_clock, 16, rate);
}

static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
static void __iomem * clkevt_base;

/*
 * IRQ handler for the timer
@@ -421,11 +406,13 @@ static struct irqaction integrator_timer_irq = {
	.dev_id		= &integrator_clockevent,
};

static void integrator_clockevent_init(unsigned long inrate)
static void integrator_clockevent_init(unsigned long inrate,
				void __iomem *base, int irq)
{
	unsigned long rate = inrate;
	unsigned int ctrl = 0;

	clkevt_base = base;
	/* Calculate and program a divisor */
	if (rate > 0x100000 * HZ) {
		rate /= 256;
@@ -437,7 +424,7 @@ static void integrator_clockevent_init(unsigned long inrate)
	timer_reload = rate / HZ;
	writel(ctrl, clkevt_base + TIMER_CTRL);

	setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
	setup_irq(irq, &integrator_timer_irq);
	clockevents_config_and_register(&integrator_clockevent,
					rate,
					1,
@@ -448,9 +435,91 @@ void __init ap_init_early(void)
{
}

#ifdef CONFIG_OF

static void __init ap_init_timer_of(void)
{
	struct device_node *node;
	const char *path;
	void __iomem *base;
	int err;
	int irq;
	struct clk *clk;
	unsigned long rate;

	clk = clk_get_sys("ap_timer", NULL);
	BUG_ON(IS_ERR(clk));
	clk_prepare_enable(clk);
	rate = clk_get_rate(clk);

	err = of_property_read_string(of_aliases,
				"arm,timer-primary", &path);
	if (WARN_ON(err))
		return;
	node = of_find_node_by_path(path);
	base = of_iomap(node, 0);
	if (WARN_ON(!base))
		return;
	writel(0, base + TIMER_CTRL);
	integrator_clocksource_init(rate, base);

	err = of_property_read_string(of_aliases,
				"arm,timer-secondary", &path);
	if (WARN_ON(err))
		return;
	node = of_find_node_by_path(path);
	base = of_iomap(node, 0);
	if (WARN_ON(!base))
		return;
	irq = irq_of_parse_and_map(node, 0);
	writel(0, base + TIMER_CTRL);
	integrator_clockevent_init(rate, base, irq);
}

static struct sys_timer ap_of_timer = {
	.init		= ap_init_timer_of,
};

static const struct of_device_id fpga_irq_of_match[] __initconst = {
	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
	{ /* Sentinel */ }
};

static void __init ap_init_irq_of(void)
{
	/* disable core module IRQs */
	writel(0xffffffffU, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
	of_irq_init(fpga_irq_of_match);
	integrator_clk_init(false);
}

static const char * ap_dt_board_compat[] = {
	"arm,integrator-ap",
	NULL,
};

DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
	.reserve	= integrator_reserve,
	.map_io		= ap_map_io,
	.nr_irqs	= NR_IRQS_INTEGRATOR_AP,
	.init_early	= ap_init_early,
	.init_irq	= ap_init_irq_of,
	.handle_irq	= fpga_handle_irq,
	.timer		= &ap_of_timer,
	.init_machine	= ap_init,
	.restart	= integrator_restart,
	.dt_compat      = ap_dt_board_compat,
MACHINE_END

#endif

#ifdef CONFIG_ATAGS

/*
 * Set up timer(s).
 * This is where non-devicetree initialization code is collected and stashed
 * for eventual deletion.
 */

static void __init ap_init_timer(void)
{
	struct clk *clk;
@@ -465,14 +534,32 @@ static void __init ap_init_timer(void)
	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
	writel(0, TIMER2_VA_BASE + TIMER_CTRL);

	integrator_clocksource_init(rate);
	integrator_clockevent_init(rate);
	integrator_clocksource_init(rate, (void __iomem *)TIMER2_VA_BASE);
	integrator_clockevent_init(rate, (void __iomem *)TIMER1_VA_BASE,
				IRQ_TIMERINT1);
}

static struct sys_timer ap_timer = {
	.init		= ap_init_timer,
};

#define INTEGRATOR_SC_VALID_INT	0x003fffff

static void __init ap_init_irq(void)
{
	/* Disable all interrupts initially. */
	/* Do the core module ones */
	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);

	/* do the header card stuff next */
	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);

	fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
		-1, INTEGRATOR_SC_VALID_INT, NULL);
	integrator_clk_init(false);
}

MACHINE_START(INTEGRATOR, "ARM-Integrator")
	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
	.atag_offset	= 0x100,
@@ -486,3 +573,5 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
	.init_machine	= ap_init,
	.restart	= integrator_restart,
MACHINE_END

#endif
Loading