Commit 8deed178 authored by Pawel Moll's avatar Pawel Moll

ARM: vexpress: Add Device Tree support

This patch adds generic Versatile Express DT machine description,
Device Tree description for the motherboard and documentation for
the bindings.
Signed-off-by: default avatarPawel Moll <pawel.moll@arm.com>
parent 95d59741
ARM Versatile Express boards family
-----------------------------------
ARM's Versatile Express platform consists of a motherboard and one
or more daughterboards (tiles). The motherboard provides a set of
peripherals. Processor and RAM "live" on the tiles.
The motherboard and each core tile should be described by a separate
Device Tree source file, with the tile's description including
the motherboard file using a /include/ directive. As the motherboard
can be initialized in one of two different configurations ("memory
maps"), care must be taken to include the correct one.
Required properties in the root node:
- compatible value:
compatible = "arm,vexpress,<model>", "arm,vexpress";
where <model> is the full tile model name (as used in the tile's
Technical Reference Manual), eg.:
- for Coretile Express A5x2 (V2P-CA5s):
compatible = "arm,vexpress,v2p-ca5s", "arm,vexpress";
- for Coretile Express A9x4 (V2P-CA9):
compatible = "arm,vexpress,v2p-ca9", "arm,vexpress";
If a tile comes in several variants or can be used in more then one
configuration, the compatible value should be:
compatible = "arm,vexpress,<model>,<variant>", \
"arm,vexpress,<model>", "arm,vexpress";
eg:
- Coretile Express A15x2 (V2P-CA15) with Tech Chip 1:
compatible = "arm,vexpress,v2p-ca15,tc1", \
"arm,vexpress,v2p-ca15", "arm,vexpress";
- LogicTile Express 13MG (V2F-2XV6) running Cortex-A7 (3 cores) SMM:
compatible = "arm,vexpress,v2f-2xv6,ca7x3", \
"arm,vexpress,v2f-2xv6", "arm,vexpress";
Optional properties in the root node:
- tile model name (use name from the tile's Technical Reference
Manual, eg. "V2P-CA5s")
model = "<model>";
- tile's HBI number (unique ARM's board model ID, visible on the
PCB's silkscreen) in hexadecimal transcription:
arm,hbi = <0xhbi>
eg:
- for Coretile Express A5x2 (V2P-CA5s) HBI-0191:
arm,hbi = <0x191>;
- Coretile Express A9x4 (V2P-CA9) HBI-0225:
arm,hbi = <0x225>;
Top-level standard "cpus" node is required. It must contain a node
with device_type = "cpu" property for every available core, eg.:
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a5";
reg = <0>;
};
};
The motherboard description file provides a single "motherboard" node
using 2 address cells corresponding to the Static Memory Bus used
between the motherboard and the tile. The first cell defines the Chip
Select (CS) line number, the second cell address offset within the CS.
All interrupt lines between the motherboard and the tile are active
high and are described using single cell.
Optional properties of the "motherboard" node:
- motherboard's memory map variant:
arm,v2m-memory-map = "<name>";
where name is one of:
- "rs1" - for RS1 map (i.a. peripherals on CS3); this map is also
referred to as "ARM Cortex-A Series memory map":
arm,v2m-memory-map = "rs1";
When this property is missing, the motherboard is using the original
memory map (also known as the "Legacy memory map", primarily used
with the original CoreTile Express A9x4) with peripherals on CS7.
Motherboard .dtsi files provide a set of labelled peripherals that
can be used to obtain required phandle in the tile's "aliases" node:
- UARTs, note that the numbers correspond to the physical connectors
on the motherboard's back panel:
v2m_serial0, v2m_serial1, v2m_serial2 and v2m_serial3
- I2C controllers:
v2m_i2c_dvi and v2m_i2c_pcie
- SP804 timers:
v2m_timer01 and v2m_timer23
Current Linux implementation requires a "arm,v2m_timer" alias
pointing at one of the motherboard's SP804 timers, if it is to be
used as the system timer. This alias should be defined in the
motherboard files.
The tile description must define "ranges", "interrupt-map-mask" and
"interrupt-map" properties to translate the motherboard's address
and interrupt space into one used by the tile's processor.
Abbreviated example:
/dts-v1/;
/ {
model = "V2P-CA5s";
arm,hbi = <0x225>;
compatible = "arm,vexpress-v2p-ca5s", "arm,vexpress";
interrupt-parent = <&gic>;
#address-cells = <1>;
#size-cells = <1>;
chosen { };
aliases {
serial0 = &v2m_serial0;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a5";
reg = <0>;
};
};
gic: interrupt-controller@2c001000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
#address-cells = <0>;
interrupt-controller;
reg = <0x2c001000 0x1000>,
<0x2c000100 0x100>;
};
motherboard {
/* CS0 is visible at 0x08000000 */
ranges = <0 0 0x08000000 0x04000000>;
interrupt-map-mask = <0 0 63>;
/* Active high IRQ 0 is connected to GIC's SPI0 */
interrupt-map = <0 0 0 &gic 0 0 4>;
};
};
/include/ "vexpress-v2m-rs1.dtsi"
/*
* ARM Ltd. Versatile Express
*
* Motherboard Express uATX
* V2M-P1
*
* HBI-0190D
*
* Original memory map ("Legacy memory map" in the board's
* Technical Reference Manual)
*
* WARNING! The hardware described in this file is independent from the
* RS1 variant (vexpress-v2m-rs1.dtsi), but there is a strong
* correspondence between the two configurations.
*
* TAKE CARE WHEN MAINTAINING THIS FILE TO PROPAGATE ANY RELEVANT
* CHANGES TO vexpress-v2m-rs1.dtsi!
*/
/ {
aliases {
arm,v2m_timer = &v2m_timer01;
};
motherboard {
compatible = "simple-bus";
#address-cells = <2>; /* SMB chipselect number and offset */
#size-cells = <1>;
#interrupt-cells = <1>;
flash@0,00000000 {
compatible = "arm,vexpress-flash", "cfi-flash";
reg = <0 0x00000000 0x04000000>,
<1 0x00000000 0x04000000>;
bank-width = <4>;
};
psram@2,00000000 {
compatible = "arm,vexpress-psram", "mtd-ram";
reg = <2 0x00000000 0x02000000>;
bank-width = <4>;
};
vram@3,00000000 {
compatible = "arm,vexpress-vram";
reg = <3 0x00000000 0x00800000>;
};
ethernet@3,02000000 {
compatible = "smsc,lan9118", "smsc,lan9115";
reg = <3 0x02000000 0x10000>;
interrupts = <15>;
phy-mode = "mii";
reg-io-width = <4>;
smsc,irq-active-high;
smsc,irq-push-pull;
};
usb@3,03000000 {
compatible = "nxp,usb-isp1761";
reg = <3 0x03000000 0x20000>;
interrupts = <16>;
port1-otg;
};
iofpga@7,00000000 {
compatible = "arm,amba-bus", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 7 0 0x20000>;
sysreg@00000 {
compatible = "arm,vexpress-sysreg";
reg = <0x00000 0x1000>;
};
sysctl@01000 {
compatible = "arm,sp810", "arm,primecell";
reg = <0x01000 0x1000>;
};
/* PCI-E I2C bus */
v2m_i2c_pcie: i2c@02000 {
compatible = "arm,versatile-i2c";
reg = <0x02000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
pcie-switch@60 {
compatible = "idt,89hpes32h8";
reg = <0x60>;
};
};
aaci@04000 {
compatible = "arm,pl041", "arm,primecell";
reg = <0x04000 0x1000>;
interrupts = <11>;
};
mmci@05000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x05000 0x1000>;
interrupts = <9 10>;
};
kmi@06000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x06000 0x1000>;
interrupts = <12>;
};
kmi@07000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x07000 0x1000>;
interrupts = <13>;
};
v2m_serial0: uart@09000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x09000 0x1000>;
interrupts = <5>;
};
v2m_serial1: uart@0a000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0a000 0x1000>;
interrupts = <6>;
};
v2m_serial2: uart@0b000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0b000 0x1000>;
interrupts = <7>;
};
v2m_serial3: uart@0c000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0c000 0x1000>;
interrupts = <8>;
};
wdt@0f000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0f000 0x1000>;
interrupts = <0>;
};
v2m_timer01: timer@11000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x11000 0x1000>;
interrupts = <2>;
};
v2m_timer23: timer@12000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x12000 0x1000>;
};
/* DVI I2C bus */
v2m_i2c_dvi: i2c@16000 {
compatible = "arm,versatile-i2c";
reg = <0x16000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
dvi-transmitter@39 {
compatible = "sil,sii9022-tpi", "sil,sii9022";
reg = <0x39>;
};
dvi-transmitter@60 {
compatible = "sil,sii9022-cpi", "sil,sii9022";
reg = <0x60>;
};
};
rtc@17000 {
compatible = "arm,pl031", "arm,primecell";
reg = <0x17000 0x1000>;
interrupts = <4>;
};
compact-flash@1a000 {
compatible = "arm,vexpress-cf", "ata-generic";
reg = <0x1a000 0x100
0x1a100 0xf00>;
reg-shift = <2>;
};
clcd@1f000 {
compatible = "arm,pl111", "arm,primecell";
reg = <0x1f000 0x1000>;
interrupts = <14>;
};
};
};
};
menu "Versatile Express platform type"
depends on ARCH_VEXPRESS
config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
bool
select ARM_ERRATA_720789
select ARM_ERRATA_751472
select PL310_ERRATA_753970 if CACHE_PL310
help
Provides common dependencies for Versatile Express platforms
based on Cortex-A5 and Cortex-A9 processors. In order to
build a working kernel, you must also enable relevant core
tile support or Flattened Device Tree based support options.
config ARCH_VEXPRESS_CA9X4
bool "Versatile Express Cortex-A9x4 tile"
select ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
select ARM_GIC
select CPU_V7
select HAVE_SMP
select MIGHT_HAVE_CACHE_L2X0
config ARCH_VEXPRESS_DT
bool "Device Tree support for Versatile Express platforms"
select ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
select ARM_GIC
select ARM_ERRATA_720789
select ARM_ERRATA_751472
select ARM_ERRATA_753970
select ARM_PATCH_PHYS_VIRT
select AUTO_ZRELADDR
select CPU_V7
select HAVE_SMP
select MIGHT_HAVE_CACHE_L2X0
select USE_OF
help
New Versatile Express platforms require Flattened Device Tree to
be passed to the kernel.
This option enables support for systems using Cortex processor based
ARM core and logic (FPGA) tiles on the Versatile Express motherboard,
for example:
- CoreTile Express A5x2 (V2P-CA5s)
- CoreTile Express A9x4 (V2P-CA9)
- CoreTile Express A15x2 (V2P-CA15)
- LogicTile Express 13MG (V2F-2XV6) with A5, A7, A9 or A15 SMMs
(Soft Macrocell Models)
- Versatile Express RTSMs (Models)
You must boot using a Flattened Device Tree in order to use these
platforms. The traditional (ATAGs) boot method is not usable on
these boards with this option.
If your bootloader supports Flattened Device Tree based booting,
say Y here.
endmenu
# Those numbers are used only by the non-DT V2P-CA9 platform
# The DT-enabled ones require CONFIG_AUTO_ZRELADDR=y
zreladdr-y += 0x60008000
params_phys-y := 0x60000100
initrd_phys-y := 0x60800000
......@@ -116,6 +116,12 @@ int v2m_cfg_write(u32 devfn, u32 data);
int v2m_cfg_read(u32 devfn, u32 *data);
void v2m_flags_set(u32 data);
/*
* Miscellaneous
*/
#define SYS_MISC_MASTERSITE (1 << 14)
#define SYS_PROCIDx_HBI_MASK 0xfff
/*
* Core tile IDs
*/
......
......@@ -6,6 +6,10 @@
#include <linux/amba/mmci.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/ata_platform.h>
#include <linux/smsc911x.h>
......@@ -21,6 +25,8 @@
#include <asm/mach/map.h>
#include <asm/mach/time.h>
#include <asm/hardware/arm_timer.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/gic.h>
#include <asm/hardware/timer-sp.h>
#include <asm/hardware/sp810.h>
#include <asm/hardware/gic.h>
......@@ -430,8 +436,9 @@ static void __init v2m_populate_ct_desc(void)
ct_desc = ct_descs[i];
if (!ct_desc)
panic("vexpress: failed to populate core tile description "
"for tile ID 0x%8x\n", current_tile_id);
panic("vexpress: this kernel does not support core tile ID 0x%08x when booting via ATAGs.\n"
"You may need a device tree blob or a different kernel to boot on this board.\n",
current_tile_id);
}
static void __init v2m_map_io(void)
......@@ -476,3 +483,145 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express")
.init_machine = v2m_init,
.restart = v2m_restart,
MACHINE_END
#if defined(CONFIG_ARCH_VEXPRESS_DT)
void __init v2m_dt_map_io(void)
{
iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
#if defined(CONFIG_SMP)
vexpress_dt_smp_map_io();
#endif
}
static struct clk_lookup v2m_dt_lookups[] = {
{ /* AMBA bus clock */
.con_id = "apb_pclk",
.clk = &dummy_apb_pclk,
}, { /* SP804 timers */
.dev_id = "sp804",
.con_id = "v2m-timer0",
.clk = &v2m_sp804_clk,
}, { /* SP804 timers */
.dev_id = "sp804",
.con_id = "v2m-timer1",
.clk = &v2m_sp804_clk,
}, { /* PL180 MMCI */
.dev_id = "mb:mmci", /* 10005000.mmci */
.clk = &osc2_clk,
}, { /* PL050 KMI0 */
.dev_id = "10006000.kmi",
.clk = &osc2_clk,
}, { /* PL050 KMI1 */
.dev_id = "10007000.kmi",
.clk = &osc2_clk,
}, { /* PL011 UART0 */
.dev_id = "10009000.uart",
.clk = &osc2_clk,
}, { /* PL011 UART1 */
.dev_id = "1000a000.uart",
.clk = &osc2_clk,
}, { /* PL011 UART2 */
.dev_id = "1000b000.uart",
.clk = &osc2_clk,
}, { /* PL011 UART3 */
.dev_id = "1000c000.uart",
.clk = &osc2_clk,
}, { /* SP805 WDT */
.dev_id = "1000f000.wdt",
.clk = &v2m_ref_clk,
}, { /* PL111 CLCD */
.dev_id = "1001f000.clcd",
.clk = &osc1_clk,
},
};
void __init v2m_dt_init_early(void)
{
struct device_node *node;
u32 dt_hbi;
node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
v2m_sysreg_base = of_iomap(node, 0);
if (WARN_ON(!v2m_sysreg_base))
return;
/* Confirm board type against DT property, if available */
if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
u32 id = readl(v2m_sysreg_base + (misc & SYS_MISC_MASTERSITE ?
V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
u32 hbi = id & SYS_PROCIDx_HBI_MASK;
if (WARN_ON(dt_hbi != hbi))
pr_warning("vexpress: DT HBI (%x) is not matching "
"hardware (%x)!\n", dt_hbi, hbi);
}
clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups));
versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
}
static struct of_device_id vexpress_irq_match[] __initdata = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
{}
};
static void __init v2m_dt_init_irq(void)
{
of_irq_init(vexpress_irq_match);
}
static void __init v2m_dt_timer_init(void)
{
struct device_node *node;
const char *path;
int err;
node = of_find_compatible_node(NULL, NULL, "arm,sp810");
v2m_sysctl_init(of_iomap(node, 0));
err = of_property_read_string(of_aliases, "arm,v2m_timer", &path);
if (WARN_ON(err))
return;
node = of_find_node_by_path(path);
v2m_sp804_init(of_iomap(node, 0), irq_of_parse_and_map(node, 0));
}
static struct sys_timer v2m_dt_timer = {
.init = v2m_dt_timer_init,
};
static struct of_dev_auxdata v2m_dt_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("arm,vexpress-flash", V2M_NOR0, "physmap-flash",
&v2m_flash_data),
OF_DEV_AUXDATA("arm,primecell", V2M_MMCI, "mb:mmci", &v2m_mmci_data),
{}
};
static void __init v2m_dt_init(void)
{
l2x0_of_init(0x00400000, 0xfe0fffff);
of_platform_populate(NULL, of_default_bus_match_table,
v2m_dt_auxdata_lookup, NULL);
pm_power_off = v2m_power_off;
}
const static char *v2m_dt_match[] __initconst = {
"arm,vexpress",
NULL,
};
DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
.dt_compat = v2m_dt_match,
.map_io = v2m_dt_map_io,
.init_early = v2m_dt_init_early,
.init_irq = v2m_dt_init_irq,
.timer = &v2m_dt_timer,
.init_machine = v2m_dt_init,
.handle_irq = gic_handle_irq,
.restart = v2m_restart,
MACHINE_END
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment