ARC: [plat-arcfpga]: Enabling DeviceTree for Angel4 board

* arc-uart platform device now populated dynamically, using
  of_platform_populate() - applies to any other device whatsoever.

* uart in turn requires incore arc-intc to be also present in DT

* A irq-domain needs to be instantiated for IRQ requests by DT probed
  device (e.g. arc-uart)

TODO: switch over to linear irq domain once all devs have been
      transitioned to DT

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Vineet Gupta 2013-01-18 15:12:21 +05:30
parent 450dd430bf
commit abe11ddea1
6 changed files with 170 additions and 58 deletions

View File

@ -0,0 +1,24 @@
* ARC700 incore Interrupt Controller
The core interrupt controller provides 32 prioritised interrupts (2 levels)
to ARC700 core.
Properties:
- compatible: "snps,arc700-intc"
- interrupt-controller: This is an interrupt controller.
- #interrupt-cells: Must be <1>.
Single Cell "interrupts" property of a device specifies the IRQ number
between 0 to 31
intc accessed via the special ARC AUX register interface, hence "reg" property
is not specified.
Example:
intc: interrupt-controller {
compatible = "snps,arc700-intc";
interrupt-controller;
#interrupt-cells = <1>;
};

View File

@ -1,5 +1,5 @@
# Built-in dtb
builtindtb-y := skeleton
builtindtb-y := angel4
ifneq ($(CONFIG_ARC_BUILTIN_DTB_NAME),"")
builtindtb-y := $(patsubst "%",%,$(CONFIG_ARC_BUILTIN_DTB_NAME))

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
*
* 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.
*/
/dts-v1/;
/include/ "skeleton.dtsi"
/ {
compatible = "snps,arc-angel4";
clock-frequency = <80000000>; /* 80 MHZ */
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
chosen {
bootargs = "console=ttyARC0,115200n8";
};
aliases {
serial0 = &arcuart0;
};
memory {
device_type = "memory";
reg = <0x00000000 0x10000000>; /* 256M */
};
fpga {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
/* child and parent address space 1:1 mapped */
ranges;
intc: interrupt-controller {
compatible = "snps,arc700-intc";
interrupt-controller;
#interrupt-cells = <1>;
};
arcuart0: serial@c0fc1000 {
compatible = "snps,arc-uart";
reg = <0xc0fc1000 0x100>;
interrupts = <5>;
clock-frequency = <80000000>;
baud = <115200>;
status = "okay";
};
};
};

View File

@ -18,6 +18,18 @@
#size-cells = <1>;
chosen { };
aliases { };
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "snps,arc770d";
reg = <0>;
};
};
memory {
device_type = "memory";
reg = <0x00000000 0x10000000>; /* 256M */

View File

@ -9,6 +9,8 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/irqdomain.h>
#include <asm/sections.h>
#include <asm/irq.h>
@ -59,16 +61,40 @@ static struct irq_chip onchip_intc = {
.irq_unmask = arc_unmask_irq,
};
static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
if (irq == TIMER0_IRQ)
irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);
else
irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq);
return 0;
}
static const struct irq_domain_ops arc_intc_domain_ops = {
.xlate = irq_domain_xlate_onecell,
.map = arc_intc_domain_map,
};
static struct irq_domain *root_domain;
void __init init_onchip_IRQ(void)
{
int i;
struct device_node *intc = NULL;
for (i = 0; i < NR_IRQS; i++)
irq_set_chip_and_handler(i, &onchip_intc, handle_level_irq);
intc = of_find_compatible_node(NULL, NULL, "snps,arc700-intc");
if(!intc)
panic("DeviceTree Missing incore intc\n");
#ifdef CONFIG_SMP
irq_set_chip_and_handler(TIMER0_IRQ, &onchip_intc, handle_percpu_irq);
#endif
root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0,
&arc_intc_domain_ops, NULL);
if (!root_domain)
panic("root irq domain not avail\n");
/* with this we don't need to export root_domain */
irq_set_default_host(root_domain);
}
/*

View File

@ -13,6 +13,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/console.h>
#include <linux/of_platform.h>
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/clk.h>
@ -20,58 +21,56 @@
/*----------------------- Platform Devices -----------------------------*/
#if defined(CONFIG_SERIAL_ARC) || defined(CONFIG_SERIAL_ARC_MODULE)
static unsigned long arc_uart_info[] = {
CONFIG_ARC_SERIAL_BAUD, /* uart->baud */
-1, /* uart->port.uartclk */
-1, /* uart->is_emulated (runtime @running_on_hw) */
0, /* uart->is_emulated (runtime @running_on_hw) */
0, /* uart->port.uartclk */
0, /* uart->baud */
0
};
#define ARC_UART_DEV(n) \
\
static struct resource arc_uart##n##_res[] = { \
{ \
.start = UART##n##_BASE, \
.end = UART##n##_BASE + 0xFF, \
.flags = IORESOURCE_MEM, \
}, \
{ \
.start = UART##n##_IRQ, \
.end = UART##n##_IRQ, \
.flags = IORESOURCE_IRQ, \
}, \
}; \
\
static struct platform_device arc_uart##n##_dev = { \
.name = "arc-uart", \
.id = n, \
.num_resources = ARRAY_SIZE(arc_uart##n##_res), \
.resource = arc_uart##n##_res, \
.dev = { \
.platform_data = &arc_uart_info, \
}, \
}
#if defined(CONFIG_SERIAL_ARC_CONSOLE)
/*
* static platform data - but only for early serial
* TBD: derive this from a special DT node
*/
static struct resource arc_uart0_res[] = {
{
.start = UART0_BASE,
.end = UART0_BASE + 0xFF,
.flags = IORESOURCE_MEM,
},
{
.start = UART0_IRQ,
.end = UART0_IRQ,
.flags = IORESOURCE_IRQ,
},
};
ARC_UART_DEV(0);
#if CONFIG_SERIAL_ARC_NR_PORTS > 1
ARC_UART_DEV(1);
#endif
static struct platform_device arc_uart0_dev = {
.name = "arc-uart",
.id = 0,
.num_resources = ARRAY_SIZE(arc_uart0_res),
.resource = arc_uart0_res,
.dev = {
.platform_data = &arc_uart_info,
},
};
static struct platform_device *fpga_early_devs[] __initdata = {
#if defined(CONFIG_SERIAL_ARC_CONSOLE)
&arc_uart0_dev,
#endif
};
#endif
static void arc_fpga_serial_init(void)
{
/* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
arc_uart_info[0] = !running_on_hw;
arc_uart_info[1] = arc_get_core_freq();
/* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
arc_uart_info[2] = !running_on_hw;
arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD;
#if defined(CONFIG_SERIAL_ARC_CONSOLE)
early_platform_add_devices(fpga_early_devs,
ARRAY_SIZE(fpga_early_devs));
@ -97,16 +96,9 @@ static void arc_fpga_serial_init(void)
* otherwise the early console never gets a chance to run.
*/
add_preferred_console("ttyARC", 0, "115200");
#endif
}
#else
static void arc_fpga_serial_init(void)
{
}
#endif /* CONFIG_SERIAL_ARC */
/*
* Early Platform Initialization called from setup_arch()
*/
@ -117,20 +109,23 @@ void __init arc_platform_early_init(void)
arc_fpga_serial_init();
}
static struct platform_device *fpga_devs[] __initdata = {
static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = {
#if defined(CONFIG_SERIAL_ARC) || defined(CONFIG_SERIAL_ARC_MODULE)
&arc_uart0_dev,
#if CONFIG_SERIAL_ARC_NR_PORTS > 1
&arc_uart1_dev,
#endif
OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info),
#endif
{}
};
int __init fpga_plat_init(void)
{
pr_info("[plat-arcfpga]: registering device resources\n");
platform_add_devices(fpga_devs, ARRAY_SIZE(fpga_devs));
/*
* Traverses flattened DeviceTree - registering platform devices
* complete with their resources
*/
of_platform_populate(NULL, of_default_bus_match_table,
plat_auxdata_lookup, NULL);
return 0;
}