Hi Russell,
Just for giggles, here is the Xilinx board support series reworked a
bit to depend entirely on CONFIG_OF and not use any static device
registrations other than what is needed to bootstrap the system, and
adds as little code as possible in terms of new infrastructure. All
told, the 4th patch adds less than 950 lines of code to the kernel,
which is pretty darn good for a whole new subarch.
The zynq platform is a pretty ideal test case for this since the goal
has been from day one to depend on CONFIG_OF. The previous series
only used static device registrations because device tree on arm isn't
yet in mainline. Plus, xilinx is already quite comfortable with how
to use the device tree since their other two architectures (powerpc and
microblaze) have depended on device tree for years now.
I'd like to get your thoughts on the reuse of plat-versatile for the
struct clk implementation. I'm certainly not excited about creating
yet another implementation, and versatile seems to be ideal to reuse.
The previous version of this board support has already been in
linux-next for quite a while now. If you do decide to pick up
device tree support for 2.6.40, then it would pretty low risk thing to
queue up this board support also.
The 2nd and 3rd patches aren't actually part of the board support, but
I included them here because they're needed to get the patch to apply.
The whole series is based on top of both the irq_domain series I
posted last week and the latest arm device tree support series.
g.
---
Grant Likely (4):
arm/dt: Add dt machine definition
of/address: Add of_find_matching_node_by_address helper
dt/irq: add of_irq_domain_add_simple() helper
ARM: Xilinx: Adding Xilinx board support
Documentation/devicetree/bindings/arm/xilinx.txt | 7 +
arch/arm/Kconfig | 14 +
arch/arm/Makefile | 2
arch/arm/boot/dts/zynq-ep107.dts | 52 ++++
arch/arm/include/asm/mach/arch.h | 9 +
arch/arm/mach-zynq/Makefile | 6
arch/arm/mach-zynq/Makefile.boot | 3
arch/arm/mach-zynq/board_dt.c | 36 +++
arch/arm/mach-zynq/common.c | 112 ++++++++
arch/arm/mach-zynq/common.h | 29 ++
arch/arm/mach-zynq/include/mach/clkdev.h | 32 ++
arch/arm/mach-zynq/include/mach/debug-macro.S | 36 +++
arch/arm/mach-zynq/include/mach/entry-macro.S | 30 ++
arch/arm/mach-zynq/include/mach/hardware.h | 18 +
arch/arm/mach-zynq/include/mach/io.h | 33 ++
arch/arm/mach-zynq/include/mach/irqs.h | 21 ++
arch/arm/mach-zynq/include/mach/memory.h | 22 ++
arch/arm/mach-zynq/include/mach/system.h | 28 ++
arch/arm/mach-zynq/include/mach/timex.h | 23 ++
arch/arm/mach-zynq/include/mach/uart.h | 25 ++
arch/arm/mach-zynq/include/mach/uncompress.h | 51 ++++
arch/arm/mach-zynq/include/mach/vmalloc.h | 20 +
arch/arm/mach-zynq/include/mach/zynq_soc.h | 48 ++++
arch/arm/mach-zynq/timer.c | 298 ++++++++++++++++++++++
arch/arm/mm/Kconfig | 2
drivers/of/address.c | 18 +
drivers/of/irq.c | 44 +++
include/linux/of_address.h | 4
include/linux/of_irq.h | 2
29 files changed, 1024 insertions(+), 1 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/xilinx.txt
create mode 100644 arch/arm/boot/dts/zynq-ep107.dts
create mode 100644 arch/arm/mach-zynq/Makefile
create mode 100644 arch/arm/mach-zynq/Makefile.boot
create mode 100644 arch/arm/mach-zynq/board_dt.c
create mode 100644 arch/arm/mach-zynq/common.c
create mode 100644 arch/arm/mach-zynq/common.h
create mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h
create mode 100644 arch/arm/mach-zynq/include/mach/debug-macro.S
create mode 100644 arch/arm/mach-zynq/include/mach/entry-macro.S
create mode 100644 arch/arm/mach-zynq/include/mach/hardware.h
create mode 100644 arch/arm/mach-zynq/include/mach/io.h
create mode 100644 arch/arm/mach-zynq/include/mach/irqs.h
create mode 100644 arch/arm/mach-zynq/include/mach/memory.h
create mode 100644 arch/arm/mach-zynq/include/mach/system.h
create mode 100644 arch/arm/mach-zynq/include/mach/timex.h
create mode 100644 arch/arm/mach-zynq/include/mach/uart.h
create mode 100644 arch/arm/mach-zynq/include/mach/uncompress.h
create mode 100644 arch/arm/mach-zynq/include/mach/vmalloc.h
create mode 100644 arch/arm/mach-zynq/include/mach/zynq_soc.h
create mode 100644 arch/arm/mach-zynq/timer.c
--
Signature
This patch adds a DT_MACHINE_START macro to use instead of
MACHINE_START when creating a machine_desc that supports using the
device tree.
Signed-off-by: Grant Likely <[email protected]>
---
arch/arm/include/asm/mach/arch.h | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 946f4d7..858d269 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -70,4 +70,13 @@ static const struct machine_desc __mach_desc_##_type \
#define MACHINE_END \
};
+#define MACH_TYPE_DT 0xffffffff
+
+#define DT_MACHINE_START(_name, _namestr) \
+static const struct machine_desc __mach_desc_##_name \
+ __used \
+ __attribute__((__section__(".arch.info.init"))) = { \
+ .nr = MACH_TYPE_DT, \
+ .name = _namestr,
+
#endif
of_find_matching_node_by_address() can be used to find a device tree
node for a device at a specific address.
Signed-off-by: Grant Likely <[email protected]>
---
drivers/of/address.c | 18 ++++++++++++++++++
include/linux/of_address.h | 4 ++++
2 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/drivers/of/address.c b/drivers/of/address.c
index b43ff66..deefc0c 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -591,6 +591,24 @@ int of_address_to_resource(struct device_node *dev, int index,
}
EXPORT_SYMBOL_GPL(of_address_to_resource);
+struct device_node *of_find_matching_node_by_address(struct device_node *from,
+ const struct of_device_id *matches,
+ u64 base_address)
+{
+ struct device_node *dn = of_find_matching_node(from, matches);
+ struct resource res;
+
+ while (dn) {
+ if (of_address_to_resource(dn, 0, &res))
+ continue;
+ if (res.start == base_address)
+ return dn;
+ dn = of_find_matching_node(dn, matches);
+ }
+
+ return NULL;
+}
+
/**
* of_iomap - Maps the memory mapped IO for a given device_node
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 6711d5f..4fbea28 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -7,6 +7,10 @@ extern int of_address_count(struct device_node *np);
extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
extern int of_address_to_resource(struct device_node *dev, int index,
struct resource *r);
+extern struct device_node *of_find_matching_node_by_address(
+ struct device_node *from,
+ const struct of_device_id *matches,
+ u64 base_address);
extern void __iomem *of_iomap(struct device_node *device, int index);
/* Extract an address from a device, returns the region size and
of_irq_domain_add_simple() is an easy way to generate an irq translation
domain for simple irq controllers. It assumes a flat 1:1 mapping from
hardware irq number to an offset of the first linux irq number assigned
to the controller
Signed-off-by: Grant Likely <[email protected]>
---
drivers/of/irq.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/of_irq.h | 2 ++
2 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 6da0964..641590c 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -24,6 +24,7 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/string.h>
+#include <linux/slab.h>
/* For archs that don't support NO_IRQ (such as x86), provide a dummy value */
#ifndef NO_IRQ
@@ -147,6 +148,49 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
}
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+/*
+ * A simple irq domain implementation that 1:1 translates hwirqs to an offset
+ * from the irq_start value
+ */
+struct of_irq_domain_simple {
+ struct of_irq_domain domain;
+ int irq_start;
+ int irq_size;
+};
+
+static unsigned int of_irq_domain_simple_map(struct of_irq_domain *domain,
+ struct device_node *controller,
+ const u32 *intspec, u32 intsize)
+{
+ struct of_irq_domain_simple *ds;
+
+ ds = container_of(domain, struct of_irq_domain_simple, domain);
+ if (intspec[0] >= ds->irq_size)
+ return NO_IRQ;
+ return ds->irq_start + intspec[0];
+}
+
+/**
+ * of_irq_domain_create_simple() - Set up a 'simple' translation range
+ */
+void of_irq_domain_add_simple(struct device_node *controller,
+ int irq_start, int irq_size)
+{
+ struct of_irq_domain_simple *sd;
+
+ sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+ if (!sd) {
+ WARN_ON(1);
+ return;
+ }
+
+ sd->irq_start = irq_start;
+ sd->irq_size = irq_size;
+ sd->domain.controller = of_node_get(controller);
+ sd->domain.map = of_irq_domain_simple_map;
+ of_irq_domain_add(&sd->domain);
+}
+
/**
* irq_of_parse_and_map - Parse and map an interrupt into linux virq space
* @device: Device node of the device whose interrupt is to be mapped
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 511dbc3..8e49a0e 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -63,6 +63,8 @@ struct of_irq_domain {
extern void of_irq_domain_add(struct of_irq_domain *domain);
extern void of_irq_set_default_domain(struct of_irq_domain *host);
extern struct of_irq_domain *of_irq_domain_find(struct device_node *controller);
+extern void of_irq_domain_add_simple(struct device_node *controller,
+ int irq_start, int irq_size);
/*
* Workarounds only applied to 32bit powermac machines
The 1st board support is minimal to get a system up and running
on the Xilinx platform.
This platform reuses the clock implementation from plat-versatile, and
it depends entirely on CONFIG_OF support. There is only one board
support file which obtains all device information from a device tree
dtb file which is passed to the kernel at boot time.
Signed-off-by: John Linn <[email protected]>
Signed-off-by: Grant Likely <[email protected]>
---
Documentation/devicetree/bindings/arm/xilinx.txt | 7 +
arch/arm/Kconfig | 14 +
arch/arm/Makefile | 2
arch/arm/boot/dts/zynq-ep107.dts | 52 ++++
arch/arm/mach-zynq/Makefile | 6
arch/arm/mach-zynq/Makefile.boot | 3
arch/arm/mach-zynq/board_dt.c | 36 +++
arch/arm/mach-zynq/common.c | 112 ++++++++
arch/arm/mach-zynq/common.h | 29 ++
arch/arm/mach-zynq/include/mach/clkdev.h | 32 ++
arch/arm/mach-zynq/include/mach/debug-macro.S | 36 +++
arch/arm/mach-zynq/include/mach/entry-macro.S | 30 ++
arch/arm/mach-zynq/include/mach/hardware.h | 18 +
arch/arm/mach-zynq/include/mach/io.h | 33 ++
arch/arm/mach-zynq/include/mach/irqs.h | 21 ++
arch/arm/mach-zynq/include/mach/memory.h | 22 ++
arch/arm/mach-zynq/include/mach/system.h | 28 ++
arch/arm/mach-zynq/include/mach/timex.h | 23 ++
arch/arm/mach-zynq/include/mach/uart.h | 25 ++
arch/arm/mach-zynq/include/mach/uncompress.h | 51 ++++
arch/arm/mach-zynq/include/mach/vmalloc.h | 20 +
arch/arm/mach-zynq/include/mach/zynq_soc.h | 48 ++++
arch/arm/mach-zynq/timer.c | 298 ++++++++++++++++++++++
arch/arm/mm/Kconfig | 2
24 files changed, 947 insertions(+), 1 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/xilinx.txt
create mode 100644 arch/arm/boot/dts/zynq-ep107.dts
create mode 100644 arch/arm/mach-zynq/Makefile
create mode 100644 arch/arm/mach-zynq/Makefile.boot
create mode 100644 arch/arm/mach-zynq/board_dt.c
create mode 100644 arch/arm/mach-zynq/common.c
create mode 100644 arch/arm/mach-zynq/common.h
create mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h
create mode 100644 arch/arm/mach-zynq/include/mach/debug-macro.S
create mode 100644 arch/arm/mach-zynq/include/mach/entry-macro.S
create mode 100644 arch/arm/mach-zynq/include/mach/hardware.h
create mode 100644 arch/arm/mach-zynq/include/mach/io.h
create mode 100644 arch/arm/mach-zynq/include/mach/irqs.h
create mode 100644 arch/arm/mach-zynq/include/mach/memory.h
create mode 100644 arch/arm/mach-zynq/include/mach/system.h
create mode 100644 arch/arm/mach-zynq/include/mach/timex.h
create mode 100644 arch/arm/mach-zynq/include/mach/uart.h
create mode 100644 arch/arm/mach-zynq/include/mach/uncompress.h
create mode 100644 arch/arm/mach-zynq/include/mach/vmalloc.h
create mode 100644 arch/arm/mach-zynq/include/mach/zynq_soc.h
create mode 100644 arch/arm/mach-zynq/timer.c
diff --git a/Documentation/devicetree/bindings/arm/xilinx.txt b/Documentation/devicetree/bindings/arm/xilinx.txt
new file mode 100644
index 0000000..6f1ed830
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/xilinx.txt
@@ -0,0 +1,7 @@
+Xilinx Zynq EP107 Emulation Platform board
+
+This board is an emulation platform for the Zynq product which is
+based on an ARM Cortex A9 processor.
+
+Required root node properties:
+ - compatible = "xlnx,zynq-ep107";
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index efc7f3c..3b22878 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -889,6 +889,20 @@ config ARCH_VT8500
select HAVE_PWM
help
Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
+
+config ARCH_ZYNQ
+ bool "Xilinx Zynq ARM Cortex A9 Platform"
+ select CPU_V7
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+ select CLKDEV_LOOKUP
+ select ARM_GIC
+ select ARM_AMBA
+ select ICST
+ select USE_OF
+ help
+ Support for Xilinx Zynq ARM Cortex A9 Platform
+
endchoice
#
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index c7d321a..06234de 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -201,6 +201,7 @@ machine-$(CONFIG_MACH_SPEAR300) := spear3xx
machine-$(CONFIG_MACH_SPEAR310) := spear3xx
machine-$(CONFIG_MACH_SPEAR320) := spear3xx
machine-$(CONFIG_MACH_SPEAR600) := spear6xx
+machine-$(CONFIG_ARCH_ZYNQ) := zynq
# Platform directory name. This list is sorted alphanumerically
# by CONFIG_* macro name.
@@ -209,6 +210,7 @@ plat-$(CONFIG_ARCH_OMAP) := omap
plat-$(CONFIG_ARCH_S3C64XX) := samsung
plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx
plat-$(CONFIG_ARCH_TCC_926) := tcc
+plat-$(CONFIG_ARCH_ZYNQ) := versatile
plat-$(CONFIG_PLAT_IOP) := iop
plat-$(CONFIG_PLAT_NOMADIK) := nomadik
plat-$(CONFIG_PLAT_ORION) := orion
diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts
new file mode 100644
index 0000000..37ca192
--- /dev/null
+++ b/arch/arm/boot/dts/zynq-ep107.dts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/ {
+ model = "Xilinx Zynq EP107";
+ compatible = "xlnx,zynq-ep107";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x10000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
+ linux,stdout-path = &uart0;
+ };
+
+ amba {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ intc: interrupt-controller@f8f01000 {
+ interrupt-controller;
+ compatible = "arm,gic";
+ reg = <0xF8F01000 0x1000>;
+ #interrupt-cells = <2>;
+ };
+
+ uart0: uart@e0000000 {
+ compatible = "xlnx,xuartps";
+ reg = <0xE0000000 0x1000>;
+ interrupts = <59 0>;
+ clock = <50000000>;
+ };
+ };
+};
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
new file mode 100644
index 0000000..c550c67
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := common.o timer.o board_dt.o
diff --git a/arch/arm/mach-zynq/Makefile.boot b/arch/arm/mach-zynq/Makefile.boot
new file mode 100644
index 0000000..67039c3
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile.boot
@@ -0,0 +1,3 @@
+ zreladdr-y := 0x00008000
+params_phys-y := 0x00000100
+initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-zynq/board_dt.c b/arch/arm/mach-zynq/board_dt.c
new file mode 100644
index 0000000..668f465
--- /dev/null
+++ b/arch/arm/mach-zynq/board_dt.c
@@ -0,0 +1,36 @@
+/*
+ * This file contains code for boards with device tree support.
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * based on arch/arm/mach-realview/core.c
+ *
+ * Copyright (C) 1999 - 2003 ARM Limited
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <asm/mach/arch.h>
+#include "common.h"
+
+static const char *xilinx_dt_match[] = {
+ "xlnx,zynq-ep107",
+ NULL
+};
+
+DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
+ .map_io = xilinx_map_io,
+ .init_irq = xilinx_irq_init,
+ .init_machine = xilinx_init_machine,
+ .timer = &xttcpss_sys_timer,
+ .dt_compat = xilinx_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
new file mode 100644
index 0000000..3b31376
--- /dev/null
+++ b/arch/arm/mach-zynq/common.c
@@ -0,0 +1,112 @@
+/*
+ * This file contains common code that is intended to be used across
+ * boards so that it's not replicated.
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/map.h>
+#include <asm/page.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/zynq_soc.h>
+#include <mach/clkdev.h>
+#include "common.h"
+
+static struct of_device_id zynq_of_bus_ids[] __initdata = {
+ { .compatible = "simple-bus", },
+ {}
+};
+
+static struct of_device_id gic_match[] = {
+ { .compatible = "arm,gic", },
+ {}
+};
+
+/**
+ * xilinx_init_machine() - System specific initialization, intended to be
+ * called from board specific initialization.
+ */
+void __init xilinx_init_machine(void)
+{
+ struct device_node *node = of_find_matching_node(NULL, gic_match);
+
+ if (node)
+ of_irq_domain_add_simple(node, 0, NR_IRQS);
+
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * 64KB way size, 8-way associativity, parity disabled
+ */
+ l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
+#endif
+
+ of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
+}
+
+/**
+ * xilinx_irq_init() - Interrupt controller initialization for the GIC.
+ */
+void __init xilinx_irq_init(void)
+{
+ gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
+}
+
+/* The minimum devices needed to be mapped before the VM system is up and
+ * running include the GIC, UART and Timer Counter.
+ */
+
+static struct map_desc io_desc[] __initdata = {
+ {
+ .virtual = TTC0_VIRT,
+ .pfn = __phys_to_pfn(TTC0_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = SCU_PERIPH_VIRT,
+ .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
+ .length = SZ_8K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = PL310_L2CC_VIRT,
+ .pfn = __phys_to_pfn(PL310_L2CC_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+
+#ifdef CONFIG_DEBUG_LL
+ {
+ .virtual = UART0_VIRT,
+ .pfn = __phys_to_pfn(UART0_PHYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+#endif
+
+};
+
+/**
+ * xilinx_map_io() - Create memory mappings needed for early I/O.
+ */
+void __init xilinx_map_io(void)
+{
+ iotable_init(io_desc, ARRAY_SIZE(io_desc));
+}
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
new file mode 100644
index 0000000..bca2196
--- /dev/null
+++ b/arch/arm/mach-zynq/common.h
@@ -0,0 +1,29 @@
+/*
+ * This file contains common function prototypes to avoid externs
+ * in the c files.
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_ZYNQ_COMMON_H__
+#define __MACH_ZYNQ_COMMON_H__
+
+#include <linux/init.h>
+#include <asm/mach/time.h>
+
+extern void xilinx_init_machine(void);
+extern void xilinx_irq_init(void);
+extern void xilinx_map_io(void);
+
+extern struct sys_timer xttcpss_sys_timer;
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h
new file mode 100644
index 0000000..c6e73d8
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/clkdev.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-zynq/include/mach/clkdev.h
+ *
+ * Copyright (C) 2011 Xilinx, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_CLKDEV_H__
+#define __MACH_CLKDEV_H__
+
+#include <plat/clock.h>
+
+struct clk {
+ unsigned long rate;
+ const struct clk_ops *ops;
+ const struct icst_params *params;
+ void __iomem *vcoreg;
+};
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/mach-zynq/include/mach/debug-macro.S
new file mode 100644
index 0000000..9f664d5
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
+/* arch/arm/mach-zynq/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+ .macro addruart, rp, rv
+ ldr \rp, =LL_UART_PADDR @ physical
+ ldr \rv, =LL_UART_VADDR @ virtual
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA
+ .endm
+
+ .macro waituart,rd,rx
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldr \rd, [\rx, #UART_SR_OFFSET] @ get status register
+ tst \rd, #UART_SR_TXFULL @
+ bne 1002b @ wait if FIFO is full
+ .endm
diff --git a/arch/arm/mach-zynq/include/mach/entry-macro.S b/arch/arm/mach-zynq/include/mach/entry-macro.S
new file mode 100644
index 0000000..3cfc01b
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/entry-macro.S
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/mach-zynq/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * based on arch/plat-mxc/include/mach/entry-macro.S
+ *
+ * Copyright (C) 2007 Lennert Buytenhek <[email protected]>
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/hardware.h>
+#include <asm/hardware/entry-macro-gic.S>
+
+ .macro disable_fiq
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
new file mode 100644
index 0000000..d558d8a
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/hardware.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-zynq/include/mach/hardware.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/io.h b/arch/arm/mach-zynq/include/mach/io.h
new file mode 100644
index 0000000..39d9885
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/io.h
@@ -0,0 +1,33 @@
+/* arch/arm/mach-zynq/include/mach/io.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_IO_H__
+#define __MACH_IO_H__
+
+/* Allow IO space to be anywhere in the memory */
+
+#define IO_SPACE_LIMIT 0xffff
+
+/* IO address mapping macros, nothing special at this time but required */
+
+#ifdef __ASSEMBLER__
+#define IOMEM(x) (x)
+#else
+#define IOMEM(x) ((void __force __iomem *)(x))
+#endif
+
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h
new file mode 100644
index 0000000..5fb04fd
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/irqs.h
@@ -0,0 +1,21 @@
+/* arch/arm/mach-zynq/include/mach/irqs.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_GPIOS 118
+#define NR_IRQS (128 + ARCH_NR_GPIOS)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/memory.h b/arch/arm/mach-zynq/include/mach/memory.h
new file mode 100644
index 0000000..35a9263
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/memory.h
@@ -0,0 +1,22 @@
+/* arch/arm/mach-zynq/include/mach/memory.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_MEMORY_H__
+#define __MACH_MEMORY_H__
+
+#include <asm/sizes.h>
+
+#define PLAT_PHYS_OFFSET UL(0x0)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/system.h b/arch/arm/mach-zynq/include/mach/system.h
new file mode 100644
index 0000000..1b84d70
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/system.h
@@ -0,0 +1,28 @@
+/* arch/arm/mach-zynq/include/mach/system.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_SYSTEM_H__
+#define __MACH_SYSTEM_H__
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ /* Add architecture specific reset processing here */
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h
new file mode 100644
index 0000000..6c0245e
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/timex.h
@@ -0,0 +1,23 @@
+/* arch/arm/mach-zynq/include/mach/timex.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+/* the following is needed for the system to build but will be removed
+ in the future, the value is not important but won't hurt
+*/
+#define CLOCK_TICK_RATE (100 * HZ)
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h
new file mode 100644
index 0000000..5c47c97
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uart.h
@@ -0,0 +1,25 @@
+/* arch/arm/mach-zynq/include/mach/uart.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_UART_H__
+#define __MACH_UART_H__
+
+#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */
+#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */
+#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */
+
+#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */
+#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h
new file mode 100644
index 0000000..af4e844
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/uncompress.h
@@ -0,0 +1,51 @@
+/* arch/arm/mach-zynq/include/mach/uncompress.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_UNCOMPRESS_H__
+#define __MACH_UNCOMPRESS_H__
+
+#include <linux/io.h>
+#include <asm/processor.h>
+#include <mach/zynq_soc.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+static inline void flush(void)
+{
+ /*
+ * Wait while the FIFO is not empty
+ */
+ while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+ UART_SR_TXEMPTY))
+ cpu_relax();
+}
+
+#define arch_decomp_wdog()
+
+static void putc(char ch)
+{
+ /*
+ * Wait for room in the FIFO, then write the char into the FIFO
+ */
+ while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
+ UART_SR_TXFULL)
+ cpu_relax();
+
+ __raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/vmalloc.h b/arch/arm/mach-zynq/include/mach/vmalloc.h
new file mode 100644
index 0000000..2398eff
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/* arch/arm/mach-zynq/include/mach/vmalloc.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_VMALLOC_H__
+#define __MACH_VMALLOC_H__
+
+#define VMALLOC_END 0xE0000000UL
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h
new file mode 100644
index 0000000..d0d3f8f
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/zynq_soc.h
@@ -0,0 +1,48 @@
+/* arch/arm/mach-zynq/include/mach/zynq_soc.h
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_XILINX_SOC_H__
+#define __MACH_XILINX_SOC_H__
+
+#define PERIPHERAL_CLOCK_RATE 2500000
+
+/* For now, all mappings are flat (physical = virtual)
+ */
+#define UART0_PHYS 0xE0000000
+#define UART0_VIRT UART0_PHYS
+
+#define TTC0_PHYS 0xF8001000
+#define TTC0_VIRT TTC0_PHYS
+
+#define PL310_L2CC_PHYS 0xF8F02000
+#define PL310_L2CC_VIRT PL310_L2CC_PHYS
+
+#define SCU_PERIPH_PHYS 0xF8F00000
+#define SCU_PERIPH_VIRT SCU_PERIPH_PHYS
+
+/* The following are intended for the devices that are mapped early */
+
+#define TTC0_BASE IOMEM(TTC0_VIRT)
+#define SCU_PERIPH_BASE IOMEM(SCU_PERIPH_VIRT)
+#define SCU_GIC_CPU_BASE (SCU_PERIPH_BASE + 0x100)
+#define SCU_GIC_DIST_BASE (SCU_PERIPH_BASE + 0x1000)
+#define PL310_L2CC_BASE IOMEM(PL310_L2CC_VIRT)
+
+/*
+ * Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
+ */
+#define LL_UART_PADDR UART0_PHYS
+#define LL_UART_VADDR UART0_VIRT
+
+#endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
new file mode 100644
index 0000000..c2c96cc
--- /dev/null
+++ b/arch/arm/mach-zynq/timer.c
@@ -0,0 +1,298 @@
+/*
+ * This file contains driver for the Xilinx PS Timer Counter IP.
+ *
+ * Copyright (C) 2011 Xilinx
+ *
+ * based on arch/mips/kernel/time.c timer driver
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+
+#include <asm/mach/time.h>
+#include <mach/zynq_soc.h>
+#include "common.h"
+
+#define IRQ_TIMERCOUNTER0 42
+
+/*
+ * This driver configures the 2 16-bit count-up timers as follows:
+ *
+ * T1: Timer 1, clocksource for generic timekeeping
+ * T2: Timer 2, clockevent source for hrtimers
+ * T3: Timer 3, <unused>
+ *
+ * The input frequency to the timer module for emulation is 2.5MHz which is
+ * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
+ * the timers are clocked at 78.125KHz (12.8 us resolution).
+ *
+ * The input frequency to the timer module in silicon will be 200MHz. With the
+ * pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
+ */
+#define XTTCPSS_CLOCKSOURCE 0 /* Timer 1 as a generic timekeeping */
+#define XTTCPSS_CLOCKEVENT 1 /* Timer 2 as a clock event */
+
+#define XTTCPSS_TIMER_BASE TTC0_BASE
+#define XTTCPCC_EVENT_TIMER_IRQ (IRQ_TIMERCOUNTER0 + 1)
+/*
+ * Timer Register Offset Definitions of Timer 1, Increment base address by 4
+ * and use same offsets for Timer 2
+ */
+#define XTTCPSS_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */
+#define XTTCPSS_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */
+#define XTTCPSS_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */
+#define XTTCPSS_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */
+#define XTTCPSS_MATCH_1_OFFSET 0x30 /* Match 1 Value Reg, RW */
+#define XTTCPSS_MATCH_2_OFFSET 0x3C /* Match 2 Value Reg, RW */
+#define XTTCPSS_MATCH_3_OFFSET 0x48 /* Match 3 Value Reg, RW */
+#define XTTCPSS_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */
+#define XTTCPSS_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */
+
+#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1
+
+/* Setup the timers to use pre-scaling */
+
+#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
+
+/**
+ * struct xttcpss_timer - This definition defines local timer structure
+ *
+ * @base_addr: Base address of timer
+ **/
+struct xttcpss_timer {
+ void __iomem *base_addr;
+};
+
+static struct xttcpss_timer timers[2];
+static struct clock_event_device xttcpss_clockevent;
+
+/**
+ * xttcpss_set_interval - Set the timer interval value
+ *
+ * @timer: Pointer to the timer instance
+ * @cycles: Timer interval ticks
+ **/
+static void xttcpss_set_interval(struct xttcpss_timer *timer,
+ unsigned long cycles)
+{
+ u32 ctrl_reg;
+
+ /* Disable the counter, set the counter value and re-enable counter */
+ ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+
+ __raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET);
+
+ /* Reset the counter (0x10) so that it starts from 0, one-shot
+ mode makes this needed for timing to be right. */
+ ctrl_reg |= 0x10;
+ ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+}
+
+/**
+ * xttcpss_clock_event_interrupt - Clock event timer interrupt handler
+ *
+ * @irq: IRQ number of the Timer
+ * @dev_id: void pointer to the xttcpss_timer instance
+ *
+ * returns: Always IRQ_HANDLED - success
+ **/
+static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &xttcpss_clockevent;
+ struct xttcpss_timer *timer = dev_id;
+
+ /* Acknowledge the interrupt and call event handler */
+ __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
+ timer->base_addr + XTTCPSS_ISR_OFFSET);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction event_timer_irq = {
+ .name = "xttcpss clockevent",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = xttcpss_clock_event_interrupt,
+};
+
+/**
+ * xttcpss_timer_hardware_init - Initialize the timer hardware
+ *
+ * Initialize the hardware to start the clock source, get the clock
+ * event timer ready to use, and hook up the interrupt.
+ **/
+static void __init xttcpss_timer_hardware_init(void)
+{
+ /* Setup the clock source counter to be an incrementing counter
+ * with no interrupt and it rolls over at 0xFFFF. Pre-scale
+ it by 32 also. Let it start running now.
+ */
+ timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
+
+ __raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+ XTTCPSS_IER_OFFSET);
+ __raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+ XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+
+ /* Setup the clock event timer to be an interval timer which
+ * is prescaled by 32 using the interval interrupt. Leave it
+ * disabled for now.
+ */
+
+ timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
+
+ __raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+ __raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
+ XTTCPSS_CLK_CNTRL_OFFSET);
+ __raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
+ XTTCPSS_IER_OFFSET);
+
+ /* Setup IRQ the clock event timer */
+ event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
+ setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
+}
+
+/**
+ * __raw_readl_cycles - Reads the timer counter register
+ *
+ * returns: Current timer counter register value
+ **/
+static cycle_t __raw_readl_cycles(struct clocksource *cs)
+{
+ struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+
+ return (cycle_t)__raw_readl(timer->base_addr +
+ XTTCPSS_COUNT_VAL_OFFSET);
+}
+
+
+/*
+ * Instantiate and initialize the clock source structure
+ */
+static struct clocksource clocksource_xttcpss = {
+ .name = "xttcpss_timer1",
+ .rating = 200, /* Reasonable clock source */
+ .read = __raw_readl_cycles,
+ .mask = CLOCKSOURCE_MASK(16),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+
+/**
+ * xttcpss_set_next_event - Sets the time interval for next event
+ *
+ * @cycles: Timer interval ticks
+ * @evt: Address of clock event instance
+ *
+ * returns: Always 0 - success
+ **/
+static int xttcpss_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+
+ xttcpss_set_interval(timer, cycles);
+ return 0;
+}
+
+/**
+ * xttcpss_set_mode - Sets the mode of timer
+ *
+ * @mode: Mode to be set
+ * @evt: Address of clock event instance
+ **/
+static void xttcpss_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
+ u32 ctrl_reg;
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ xttcpss_set_interval(timer, TIMER_RATE / HZ);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ ctrl_reg = __raw_readl(timer->base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+ ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg,
+ timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ ctrl_reg = __raw_readl(timer->base_addr +
+ XTTCPSS_CNT_CNTRL_OFFSET);
+ ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
+ __raw_writel(ctrl_reg,
+ timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+ break;
+ }
+}
+
+/*
+ * Instantiate and initialize the clock event structure
+ */
+static struct clock_event_device xttcpss_clockevent = {
+ .name = "xttcpss_timer2",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_next_event = xttcpss_set_next_event,
+ .set_mode = xttcpss_set_mode,
+ .rating = 200,
+};
+
+/**
+ * xttcpss_timer_init - Initialize the timer
+ *
+ * Initializes the timer hardware and register the clock source and clock event
+ * timers with Linux kernal timer framework
+ **/
+static void __init xttcpss_timer_init(void)
+{
+ xttcpss_timer_hardware_init();
+ clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
+
+ /* Calculate the parameters to allow the clockevent to operate using
+ integer math
+ */
+ clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
+
+ xttcpss_clockevent.max_delta_ns =
+ clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
+ xttcpss_clockevent.min_delta_ns =
+ clockevent_delta2ns(1, &xttcpss_clockevent);
+
+ /* Indicate that clock event is on 1st CPU as SMP boot needs it */
+
+ xttcpss_clockevent.cpumask = cpumask_of(0);
+ clockevents_register_device(&xttcpss_clockevent);
+}
+
+/*
+ * Instantiate and initialize the system timer structure
+ */
+struct sys_timer xttcpss_sys_timer = {
+ .init = xttcpss_timer_init,
+};
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 0074b8d..f046982 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -821,7 +821,7 @@ config CACHE_L2X0
depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
- ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
+ ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || ARCH_ZYNQ
default y
select OUTER_CACHE
select OUTER_CACHE_SYNC
Grant Likely wrote:
> The 1st board support is minimal to get a system up and running
> on the Xilinx platform.
>
> This platform reuses the clock implementation from plat-versatile, and
> it depends entirely on CONFIG_OF support. There is only one board
> support file which obtains all device information from a device tree
> dtb file which is passed to the kernel at boot time.
>
> Signed-off-by: John Linn <[email protected]>
> Signed-off-by: Grant Likely <[email protected]>
> ---
> Documentation/devicetree/bindings/arm/xilinx.txt | 7 +
> arch/arm/Kconfig | 14 +
> arch/arm/Makefile | 2
> arch/arm/boot/dts/zynq-ep107.dts | 52 ++++
> arch/arm/mach-zynq/Makefile | 6
> arch/arm/mach-zynq/Makefile.boot | 3
> arch/arm/mach-zynq/board_dt.c | 36 +++
> arch/arm/mach-zynq/common.c | 112 ++++++++
> arch/arm/mach-zynq/common.h | 29 ++
> arch/arm/mach-zynq/include/mach/clkdev.h | 32 ++
> arch/arm/mach-zynq/include/mach/debug-macro.S | 36 +++
> arch/arm/mach-zynq/include/mach/entry-macro.S | 30 ++
> arch/arm/mach-zynq/include/mach/hardware.h | 18 +
> arch/arm/mach-zynq/include/mach/io.h | 33 ++
> arch/arm/mach-zynq/include/mach/irqs.h | 21 ++
> arch/arm/mach-zynq/include/mach/memory.h | 22 ++
> arch/arm/mach-zynq/include/mach/system.h | 28 ++
> arch/arm/mach-zynq/include/mach/timex.h | 23 ++
> arch/arm/mach-zynq/include/mach/uart.h | 25 ++
> arch/arm/mach-zynq/include/mach/uncompress.h | 51 ++++
> arch/arm/mach-zynq/include/mach/vmalloc.h | 20 +
> arch/arm/mach-zynq/include/mach/zynq_soc.h | 48 ++++
> arch/arm/mach-zynq/timer.c | 298 ++++++++++++++++++++++
> arch/arm/mm/Kconfig | 2
> 24 files changed, 947 insertions(+), 1 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/xilinx.txt
> create mode 100644 arch/arm/boot/dts/zynq-ep107.dts
> create mode 100644 arch/arm/mach-zynq/Makefile
> create mode 100644 arch/arm/mach-zynq/Makefile.boot
> create mode 100644 arch/arm/mach-zynq/board_dt.c
> create mode 100644 arch/arm/mach-zynq/common.c
> create mode 100644 arch/arm/mach-zynq/common.h
> create mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h
> create mode 100644 arch/arm/mach-zynq/include/mach/debug-macro.S
> create mode 100644 arch/arm/mach-zynq/include/mach/entry-macro.S
> create mode 100644 arch/arm/mach-zynq/include/mach/hardware.h
> create mode 100644 arch/arm/mach-zynq/include/mach/io.h
> create mode 100644 arch/arm/mach-zynq/include/mach/irqs.h
> create mode 100644 arch/arm/mach-zynq/include/mach/memory.h
> create mode 100644 arch/arm/mach-zynq/include/mach/system.h
> create mode 100644 arch/arm/mach-zynq/include/mach/timex.h
> create mode 100644 arch/arm/mach-zynq/include/mach/uart.h
> create mode 100644 arch/arm/mach-zynq/include/mach/uncompress.h
> create mode 100644 arch/arm/mach-zynq/include/mach/vmalloc.h
> create mode 100644 arch/arm/mach-zynq/include/mach/zynq_soc.h
> create mode 100644 arch/arm/mach-zynq/timer.c
>
> diff --git a/Documentation/devicetree/bindings/arm/xilinx.txt b/Documentation/devicetree/bindings/arm/xilinx.txt
> new file mode 100644
> index 0000000..6f1ed830
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/xilinx.txt
> @@ -0,0 +1,7 @@
> +Xilinx Zynq EP107 Emulation Platform board
> +
> +This board is an emulation platform for the Zynq product which is
> +based on an ARM Cortex A9 processor.
> +
> +Required root node properties:
> + - compatible = "xlnx,zynq-ep107";
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index efc7f3c..3b22878 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -889,6 +889,20 @@ config ARCH_VT8500
> select HAVE_PWM
> help
> Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
> +
> +config ARCH_ZYNQ
> + bool "Xilinx Zynq ARM Cortex A9 Platform"
> + select CPU_V7
> + select GENERIC_TIME
> + select GENERIC_CLOCKEVENTS
> + select CLKDEV_LOOKUP
> + select ARM_GIC
> + select ARM_AMBA
> + select ICST
> + select USE_OF
> + help
> + Support for Xilinx Zynq ARM Cortex A9 Platform
> +
> endchoice
>
> #
> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
> index c7d321a..06234de 100644
> --- a/arch/arm/Makefile
> +++ b/arch/arm/Makefile
> @@ -201,6 +201,7 @@ machine-$(CONFIG_MACH_SPEAR300) := spear3xx
> machine-$(CONFIG_MACH_SPEAR310) := spear3xx
> machine-$(CONFIG_MACH_SPEAR320) := spear3xx
> machine-$(CONFIG_MACH_SPEAR600) := spear6xx
> +machine-$(CONFIG_ARCH_ZYNQ) := zynq
>
> # Platform directory name. This list is sorted alphanumerically
> # by CONFIG_* macro name.
> @@ -209,6 +210,7 @@ plat-$(CONFIG_ARCH_OMAP) := omap
> plat-$(CONFIG_ARCH_S3C64XX) := samsung
> plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx
> plat-$(CONFIG_ARCH_TCC_926) := tcc
> +plat-$(CONFIG_ARCH_ZYNQ) := versatile
> plat-$(CONFIG_PLAT_IOP) := iop
> plat-$(CONFIG_PLAT_NOMADIK) := nomadik
> plat-$(CONFIG_PLAT_ORION) := orion
> diff --git a/arch/arm/boot/dts/zynq-ep107.dts b/arch/arm/boot/dts/zynq-ep107.dts
> new file mode 100644
> index 0000000..37ca192
> --- /dev/null
> +++ b/arch/arm/boot/dts/zynq-ep107.dts
> @@ -0,0 +1,52 @@
> +/*
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +/dts-v1/;
> +/ {
> + model = "Xilinx Zynq EP107";
> + compatible = "xlnx,zynq-ep107";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + interrupt-parent = <&intc>;
> +
> + memory {
> + device_type = "memory";
> + reg = <0x0 0x10000000>;
> + };
> +
> + chosen {
> + bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
> + linux,stdout-path = &uart0;
> + };
> +
> + amba {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges;
> +
> + intc: interrupt-controller@f8f01000 {
> + interrupt-controller;
> + compatible = "arm,gic";
> + reg = <0xF8F01000 0x1000>;
> + #interrupt-cells = <2>;
> + };
> +
> + uart0: uart@e0000000 {
> + compatible = "xlnx,xuartps";
> + reg = <0xE0000000 0x1000>;
> + interrupts = <59 0>;
> + clock = <50000000>;
> + };
> + };
> +};
> diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
> new file mode 100644
> index 0000000..c550c67
> --- /dev/null
> +++ b/arch/arm/mach-zynq/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Makefile for the linux kernel.
> +#
> +
> +# Common support
> +obj-y := common.o timer.o board_dt.o
> diff --git a/arch/arm/mach-zynq/Makefile.boot b/arch/arm/mach-zynq/Makefile.boot
> new file mode 100644
> index 0000000..67039c3
> --- /dev/null
> +++ b/arch/arm/mach-zynq/Makefile.boot
> @@ -0,0 +1,3 @@
> + zreladdr-y := 0x00008000
> +params_phys-y := 0x00000100
> +initrd_phys-y := 0x00800000
> diff --git a/arch/arm/mach-zynq/board_dt.c b/arch/arm/mach-zynq/board_dt.c
> new file mode 100644
> index 0000000..668f465
> --- /dev/null
> +++ b/arch/arm/mach-zynq/board_dt.c
> @@ -0,0 +1,36 @@
> +/*
> + * This file contains code for boards with device tree support.
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * based on arch/arm/mach-realview/core.c
> + *
> + * Copyright (C) 1999 - 2003 ARM Limited
> + * Copyright (C) 2000 Deep Blue Solutions Ltd
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/of.h>
> +#include <asm/mach/arch.h>
> +#include "common.h"
> +
> +static const char *xilinx_dt_match[] = {
> + "xlnx,zynq-ep107",
> + NULL
> +};
> +
> +DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
> + .map_io = xilinx_map_io,
> + .init_irq = xilinx_irq_init,
> + .init_machine = xilinx_init_machine,
> + .timer = &xttcpss_sys_timer,
> + .dt_compat = xilinx_dt_match,
> +MACHINE_END
> diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
> new file mode 100644
> index 0000000..3b31376
> --- /dev/null
> +++ b/arch/arm/mach-zynq/common.c
> @@ -0,0 +1,112 @@
> +/*
> + * This file contains common code that is intended to be used across
> + * boards so that it's not replicated.
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/cpumask.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +
> +#include <asm/mach/map.h>
> +#include <asm/page.h>
> +#include <asm/hardware/gic.h>
> +#include <asm/hardware/cache-l2x0.h>
> +
> +#include <mach/zynq_soc.h>
> +#include <mach/clkdev.h>
> +#include "common.h"
> +
> +static struct of_device_id zynq_of_bus_ids[] __initdata = {
> + { .compatible = "simple-bus", },
> + {}
> +};
> +
> +static struct of_device_id gic_match[] = {
> + { .compatible = "arm,gic", },
> + {}
> +};
> +
> +/**
> + * xilinx_init_machine() - System specific initialization, intended to be
> + * called from board specific initialization.
> + */
> +void __init xilinx_init_machine(void)
> +{
> + struct device_node *node = of_find_matching_node(NULL, gic_match);
> +
> + if (node)
> + of_irq_domain_add_simple(node, 0, NR_IRQS);
> +
> +#ifdef CONFIG_CACHE_L2X0
> + /*
> + * 64KB way size, 8-way associativity, parity disabled
> + */
> + l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
> +#endif
> +
> + of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
> +}
> +
> +/**
> + * xilinx_irq_init() - Interrupt controller initialization for the GIC.
> + */
> +void __init xilinx_irq_init(void)
> +{
> + gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
> +}
> +
> +/* The minimum devices needed to be mapped before the VM system is up and
> + * running include the GIC, UART and Timer Counter.
> + */
> +
> +static struct map_desc io_desc[] __initdata = {
> + {
> + .virtual = TTC0_VIRT,
> + .pfn = __phys_to_pfn(TTC0_PHYS),
> + .length = SZ_4K,
> + .type = MT_DEVICE,
> + }, {
> + .virtual = SCU_PERIPH_VIRT,
> + .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
> + .length = SZ_8K,
> + .type = MT_DEVICE,
> + }, {
> + .virtual = PL310_L2CC_VIRT,
> + .pfn = __phys_to_pfn(PL310_L2CC_PHYS),
> + .length = SZ_4K,
> + .type = MT_DEVICE,
> + },
> +
> +#ifdef CONFIG_DEBUG_LL
> + {
> + .virtual = UART0_VIRT,
> + .pfn = __phys_to_pfn(UART0_PHYS),
> + .length = SZ_4K,
> + .type = MT_DEVICE,
> + },
> +#endif
> +
> +};
look below
> +
> +/**
> + * xilinx_map_io() - Create memory mappings needed for early I/O.
> + */
> +void __init xilinx_map_io(void)
> +{
> + iotable_init(io_desc, ARRAY_SIZE(io_desc));
> +}
> diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
> new file mode 100644
> index 0000000..bca2196
> --- /dev/null
> +++ b/arch/arm/mach-zynq/common.h
> @@ -0,0 +1,29 @@
> +/*
> + * This file contains common function prototypes to avoid externs
> + * in the c files.
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_ZYNQ_COMMON_H__
> +#define __MACH_ZYNQ_COMMON_H__
> +
> +#include <linux/init.h>
> +#include <asm/mach/time.h>
> +
> +extern void xilinx_init_machine(void);
> +extern void xilinx_irq_init(void);
> +extern void xilinx_map_io(void);
> +
> +extern struct sys_timer xttcpss_sys_timer;
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h
> new file mode 100644
> index 0000000..c6e73d8
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/clkdev.h
> @@ -0,0 +1,32 @@
> +/*
> + * arch/arm/mach-zynq/include/mach/clkdev.h
> + *
> + * Copyright (C) 2011 Xilinx, Inc.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#ifndef __MACH_CLKDEV_H__
> +#define __MACH_CLKDEV_H__
> +
> +#include <plat/clock.h>
> +
> +struct clk {
> + unsigned long rate;
> + const struct clk_ops *ops;
> + const struct icst_params *params;
> + void __iomem *vcoreg;
> +};
> +
> +#define __clk_get(clk) ({ 1; })
> +#define __clk_put(clk) do { } while (0)
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/debug-macro.S b/arch/arm/mach-zynq/include/mach/debug-macro.S
> new file mode 100644
> index 0000000..9f664d5
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/debug-macro.S
> @@ -0,0 +1,36 @@
> +/* arch/arm/mach-zynq/include/mach/debug-macro.S
> + *
> + * Debugging macro include header
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <mach/zynq_soc.h>
> +#include <mach/uart.h>
> +
> + .macro addruart, rp, rv
> + ldr \rp, =LL_UART_PADDR @ physical
> + ldr \rv, =LL_UART_VADDR @ virtual
> + .endm
> +
> + .macro senduart,rd,rx
> + str \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA
> + .endm
> +
> + .macro waituart,rd,rx
> + .endm
> +
> + .macro busyuart,rd,rx
> +1002: ldr \rd, [\rx, #UART_SR_OFFSET] @ get status register
> + tst \rd, #UART_SR_TXFULL @
> + bne 1002b @ wait if FIFO is full
> + .endm
> diff --git a/arch/arm/mach-zynq/include/mach/entry-macro.S b/arch/arm/mach-zynq/include/mach/entry-macro.S
> new file mode 100644
> index 0000000..3cfc01b
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/entry-macro.S
> @@ -0,0 +1,30 @@
> +/*
> + * arch/arm/mach-zynq/include/mach/entry-macro.S
> + *
> + * Low-level IRQ helper macros
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * based on arch/plat-mxc/include/mach/entry-macro.S
> + *
> + * Copyright (C) 2007 Lennert Buytenhek <[email protected]>
> + * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <mach/hardware.h>
> +#include <asm/hardware/entry-macro-gic.S>
> +
> + .macro disable_fiq
> + .endm
> +
> + .macro arch_ret_to_user, tmp1, tmp2
> + .endm
> diff --git a/arch/arm/mach-zynq/include/mach/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h
> new file mode 100644
> index 0000000..d558d8a
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/hardware.h
> @@ -0,0 +1,18 @@
> +/* arch/arm/mach-zynq/include/mach/hardware.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_HARDWARE_H__
> +#define __MACH_HARDWARE_H__
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/io.h b/arch/arm/mach-zynq/include/mach/io.h
> new file mode 100644
> index 0000000..39d9885
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/io.h
> @@ -0,0 +1,33 @@
> +/* arch/arm/mach-zynq/include/mach/io.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_IO_H__
> +#define __MACH_IO_H__
> +
> +/* Allow IO space to be anywhere in the memory */
> +
> +#define IO_SPACE_LIMIT 0xffff
> +
> +/* IO address mapping macros, nothing special at this time but required */
> +
> +#ifdef __ASSEMBLER__
> +#define IOMEM(x) (x)
> +#else
> +#define IOMEM(x) ((void __force __iomem *)(x))
> +#endif
> +
> +#define __io(a) __typesafe_io(a)
> +#define __mem_pci(a) (a)
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/irqs.h b/arch/arm/mach-zynq/include/mach/irqs.h
> new file mode 100644
> index 0000000..5fb04fd
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/irqs.h
> @@ -0,0 +1,21 @@
> +/* arch/arm/mach-zynq/include/mach/irqs.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_IRQS_H
> +#define __MACH_IRQS_H
> +
> +#define ARCH_NR_GPIOS 118
> +#define NR_IRQS (128 + ARCH_NR_GPIOS)
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/memory.h b/arch/arm/mach-zynq/include/mach/memory.h
> new file mode 100644
> index 0000000..35a9263
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/memory.h
> @@ -0,0 +1,22 @@
> +/* arch/arm/mach-zynq/include/mach/memory.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_MEMORY_H__
> +#define __MACH_MEMORY_H__
> +
> +#include <asm/sizes.h>
> +
> +#define PLAT_PHYS_OFFSET UL(0x0)
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/system.h b/arch/arm/mach-zynq/include/mach/system.h
> new file mode 100644
> index 0000000..1b84d70
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/system.h
> @@ -0,0 +1,28 @@
> +/* arch/arm/mach-zynq/include/mach/system.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_SYSTEM_H__
> +#define __MACH_SYSTEM_H__
> +
> +static inline void arch_idle(void)
> +{
> + cpu_do_idle();
> +}
> +
> +static inline void arch_reset(char mode, const char *cmd)
> +{
> + /* Add architecture specific reset processing here */
> +}
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/timex.h b/arch/arm/mach-zynq/include/mach/timex.h
> new file mode 100644
> index 0000000..6c0245e
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/timex.h
> @@ -0,0 +1,23 @@
> +/* arch/arm/mach-zynq/include/mach/timex.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_TIMEX_H__
> +#define __MACH_TIMEX_H__
> +
> +/* the following is needed for the system to build but will be removed
> + in the future, the value is not important but won't hurt
> +*/
> +#define CLOCK_TICK_RATE (100 * HZ)
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/uart.h b/arch/arm/mach-zynq/include/mach/uart.h
> new file mode 100644
> index 0000000..5c47c97
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/uart.h
> @@ -0,0 +1,25 @@
> +/* arch/arm/mach-zynq/include/mach/uart.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_UART_H__
> +#define __MACH_UART_H__
> +
> +#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */
> +#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */
> +#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */
> +
> +#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */
> +#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/uncompress.h b/arch/arm/mach-zynq/include/mach/uncompress.h
> new file mode 100644
> index 0000000..af4e844
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/uncompress.h
> @@ -0,0 +1,51 @@
> +/* arch/arm/mach-zynq/include/mach/uncompress.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_UNCOMPRESS_H__
> +#define __MACH_UNCOMPRESS_H__
> +
> +#include <linux/io.h>
> +#include <asm/processor.h>
> +#include <mach/zynq_soc.h>
> +#include <mach/uart.h>
> +
> +void arch_decomp_setup(void)
> +{
> +}
> +
> +static inline void flush(void)
> +{
> + /*
> + * Wait while the FIFO is not empty
> + */
> + while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
> + UART_SR_TXEMPTY))
> + cpu_relax();
> +}
> +
> +#define arch_decomp_wdog()
> +
> +static void putc(char ch)
> +{
> + /*
> + * Wait for room in the FIFO, then write the char into the FIFO
> + */
> + while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
> + UART_SR_TXFULL)
> + cpu_relax();
> +
> + __raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
> +}
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/vmalloc.h b/arch/arm/mach-zynq/include/mach/vmalloc.h
> new file mode 100644
> index 0000000..2398eff
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/vmalloc.h
> @@ -0,0 +1,20 @@
> +/* arch/arm/mach-zynq/include/mach/vmalloc.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_VMALLOC_H__
> +#define __MACH_VMALLOC_H__
> +
> +#define VMALLOC_END 0xE0000000UL
> +
> +#endif
> diff --git a/arch/arm/mach-zynq/include/mach/zynq_soc.h b/arch/arm/mach-zynq/include/mach/zynq_soc.h
> new file mode 100644
> index 0000000..d0d3f8f
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/zynq_soc.h
> @@ -0,0 +1,48 @@
> +/* arch/arm/mach-zynq/include/mach/zynq_soc.h
> + *
> + * Copyright (C) 2011 Xilinx
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MACH_XILINX_SOC_H__
> +#define __MACH_XILINX_SOC_H__
> +
> +#define PERIPHERAL_CLOCK_RATE 2500000
I think this should be moved to DTS too.
> +
> +/* For now, all mappings are flat (physical = virtual)
> + */
> +#define UART0_PHYS 0xE0000000
> +#define UART0_VIRT UART0_PHYS
I am not quite sure if is depend entirely on DTS. Why is here physical uart
address? I don't know how you handle DT in arm but seems to me that the whole
io_desc structure should go away too.
Michal
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian
On Monday 02 May 2011 07:08:00 Grant Likely wrote:
> The 1st board support is minimal to get a system up and running
> on the Xilinx platform.
>
> This platform reuses the clock implementation from plat-versatile, and
> it depends entirely on CONFIG_OF support. There is only one board
> support file which obtains all device information from a device tree
> dtb file which is passed to the kernel at boot time.
Very cool stuff!
> +
> + amba {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges;
Shouldn't we have a way to identify amba buses by the compatible property
as well, rather than only declaring it simple-bus?
We might be able to do some more automatic probing in the amba
code in cases where the architected registers are actually filled
with meaningful data there.
Is the empty ranges property technically correct? Excuse my poor
knowledge of amba, but I would have assumed that only a range
of addresses is actually put on the bus, while others (e.g. RAM)
are not visible on AMBA.
> +static struct of_device_id zynq_of_bus_ids[] __initdata = {
> + { .compatible = "simple-bus", },
> + {}
> +};
> +
> +static struct of_device_id gic_match[] = {
> + { .compatible = "arm,gic", },
> + {}
> +};
> +
> +/**
> + * xilinx_init_machine() - System specific initialization, intended to be
> + * called from board specific initialization.
> + */
> +void __init xilinx_init_machine(void)
> +{
> + struct device_node *node = of_find_matching_node(NULL, gic_match);
> +
> + if (node)
> + of_irq_domain_add_simple(node, 0, NR_IRQS);
> +
> +#ifdef CONFIG_CACHE_L2X0
> + /*
> + * 64KB way size, 8-way associativity, parity disabled
> + */
> + l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
> +#endif
> +
> +/**
> + * xilinx_irq_init() - Interrupt controller initialization for the GIC.
> + */
> +void __init xilinx_irq_init(void)
> +{
> + gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
> +}
I think we can do better than this, there is still more hardcoded stuff
in here than I think should be. I understand that you tried to minimize
the size of the patch set for obvious reasons, but none of this
seems too board specific to put into common code in one way or another.
Of course we can not fix all of this at once, but maybe we can have
an explanation for each hardcoded setting on why it is still needed
and what would have to be done to make it go away.
> +/* The minimum devices needed to be mapped before the VM system is up and
> + * running include the GIC, UART and Timer Counter.
> + */
> +
> +static struct map_desc io_desc[] __initdata = {
> + {
> + .virtual = TTC0_VIRT,
> + .pfn = __phys_to_pfn(TTC0_PHYS),
> + .length = SZ_4K,
> + .type = MT_DEVICE,
> + }, {
> + .virtual = SCU_PERIPH_VIRT,
> + .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
> + .length = SZ_8K,
> + .type = MT_DEVICE,
> + }, {
> + .virtual = PL310_L2CC_VIRT,
> + .pfn = __phys_to_pfn(PL310_L2CC_PHYS),
> + .length = SZ_4K,
> + .type = MT_DEVICE,
> + },
I especially dislike the idea of having to set up iotables, these
seem completely counterintuitive when we probe the devices from the
device tree.
AFAICT, all of init_irq, time_init and init_machine are called way after
mm_init, so you should have ioremap available by the time you need to
access these virtual memory ranges.
I can understand why you'd want to special-case PCI I/O space windows
and early serial port access, but I think we should handle them differently
and give them fixed machine independent virtual addresses.
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/io.h
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/irqs.h
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/memory.h
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/system.h
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/timex.h
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/vmalloc.h
These are all either completely generic versions that could be reused
on a number of other machines, or they could be turned into such files.
For the global inlude/asm-generic files, we have just added a mechanism
to share that kind of file across multiple architectures using some
Makefile magic. Should we perhaps do something similar here to avoid
having to create more of the same files?
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/uart.h
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/uncompress.h
For these, it obviously won't work.
> diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
> new file mode 100644
> index 0000000..c2c96cc
> --- /dev/null
> +++ b/arch/arm/mach-zynq/timer.c
In the light of the recent discussions of drivers moving out of
platforms into common Linux code, do we expect this to also
happen to timers any time soon?
Arnd
On 05/02/2011 03:39 AM, Arnd Bergmann wrote:
> On Monday 02 May 2011 07:08:00 Grant Likely wrote:
>> The 1st board support is minimal to get a system up and running
>> on the Xilinx platform.
>>
>> This platform reuses the clock implementation from plat-versatile, and
>> it depends entirely on CONFIG_OF support. There is only one board
>> support file which obtains all device information from a device tree
>> dtb file which is passed to the kernel at boot time.
>
> Very cool stuff!
>
>> +
>> + amba {
>> + compatible = "simple-bus";
>> + #address-cells =<1>;
>> + #size-cells =<1>;
>> + ranges;
>
> Shouldn't we have a way to identify amba buses by the compatible property
> as well, rather than only declaring it simple-bus?
>
> We might be able to do some more automatic probing in the amba
> code in cases where the architected registers are actually filled
> with meaningful data there.
>
Typically, I don't think anything but ARM's Primecell peripherals have
registers for probing. The GIC and PL310 don't have them.
However, this is what was used for an early version of the versatile dts:
compatible = "arm,amba-bus";
> Is the empty ranges property technically correct? Excuse my poor
> knowledge of amba, but I would have assumed that only a range
> of addresses is actually put on the bus, while others (e.g. RAM)
> are not visible on AMBA.
>
>> +static struct of_device_id zynq_of_bus_ids[] __initdata = {
>> + { .compatible = "simple-bus", },
>> + {}
>> +};
>> +
>> +static struct of_device_id gic_match[] = {
>> + { .compatible = "arm,gic", },
>> + {}
>> +};
>> +
>> +/**
>> + * xilinx_init_machine() - System specific initialization, intended to be
>> + * called from board specific initialization.
>> + */
>> +void __init xilinx_init_machine(void)
>> +{
>> + struct device_node *node = of_find_matching_node(NULL, gic_match);
>> +
>> + if (node)
>> + of_irq_domain_add_simple(node, 0, NR_IRQS);
>> +
>> +#ifdef CONFIG_CACHE_L2X0
>> + /*
>> + * 64KB way size, 8-way associativity, parity disabled
>> + */
>> + l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
>> +#endif
>> +
>> +/**
>> + * xilinx_irq_init() - Interrupt controller initialization for the GIC.
>> + */
>> +void __init xilinx_irq_init(void)
>> +{
>> + gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
>> +}
>
> I think we can do better than this, there is still more hardcoded stuff
> in here than I think should be. I understand that you tried to minimize
> the size of the patch set for obvious reasons, but none of this
> seems too board specific to put into common code in one way or another.
>
> Of course we can not fix all of this at once, but maybe we can have
> an explanation for each hardcoded setting on why it is still needed
> and what would have to be done to make it go away.
The SCU base address is probe-able:
/* Get SCU base */
asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
However, this is specific to the A9 and not an SCU feature.
>
>> +/* The minimum devices needed to be mapped before the VM system is up and
>> + * running include the GIC, UART and Timer Counter.
>> + */
>> +
>> +static struct map_desc io_desc[] __initdata = {
>> + {
>> + .virtual = TTC0_VIRT,
>> + .pfn = __phys_to_pfn(TTC0_PHYS),
>> + .length = SZ_4K,
>> + .type = MT_DEVICE,
>> + }, {
>> + .virtual = SCU_PERIPH_VIRT,
>> + .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
>> + .length = SZ_8K,
>> + .type = MT_DEVICE,
>> + }, {
>> + .virtual = PL310_L2CC_VIRT,
>> + .pfn = __phys_to_pfn(PL310_L2CC_PHYS),
>> + .length = SZ_4K,
>> + .type = MT_DEVICE,
>> + },
>
> I especially dislike the idea of having to set up iotables, these
> seem completely counterintuitive when we probe the devices from the
> device tree.
>
> AFAICT, all of init_irq, time_init and init_machine are called way after
> mm_init, so you should have ioremap available by the time you need to
> access these virtual memory ranges.
>
The SCU is accessed before ioremap is up. The only reason it is accessed
early is to determine the number of cores present.
The L2 can certainly be ioremapped and probed via DT. How about
something like this:
l2cc {
compatible = "arm,pl310-l2";
reg = <0xfff12000 0x1000>;
aux-value = <0>;
aux-mask = <0xffffffff>;
};
Rob
On Monday 02 May 2011, Rob Herring wrote:
> The SCU is accessed before ioremap is up. The only reason it is accessed
> early is to determine the number of cores present.
The number of cores should definitely be available in the device tree,
normally by looking at the root interrupt controller.
> The L2 can certainly be ioremapped and probed via DT. How about
> something like this:
>
> l2cc {
> compatible = "arm,pl310-l2";
> reg = <0xfff12000 0x1000>;
> aux-value = <0>;
> aux-mask = <0xffffffff>;
> };
sounds good to me.
Arnd
> -----Original Message-----
> From: Arnd Bergmann [mailto:[email protected]]
> Sent: Monday, May 02, 2011 2:40 AM
> To: [email protected]
> Cc: [email protected]; Nicolas Pitre; Russell King;
> [email protected]; [email protected];
> John
> Linn
> Subject: Re: [RFC PATCH 4/4] ARM: Xilinx: Adding Xilinx board support
>
> On Monday 02 May 2011 07:08:00 Grant Likely wrote:
> > The 1st board support is minimal to get a system up and running
> > on the Xilinx platform.
> >
> > This platform reuses the clock implementation from plat-versatile,
> and
> > it depends entirely on CONFIG_OF support. There is only one board
> > support file which obtains all device information from a device
> tree
> > dtb file which is passed to the kernel at boot time.
>
> Very cool stuff!
>
> > +
> > + amba {
> > + compatible = "simple-bus";
> > + #address-cells = <1>;
> > + #size-cells = <1>;
> > + ranges;
>
> Shouldn't we have a way to identify amba buses by the compatible
> property
> as well, rather than only declaring it simple-bus?
>
> We might be able to do some more automatic probing in the amba
> code in cases where the architected registers are actually filled
> with meaningful data there.
>
> Is the empty ranges property technically correct? Excuse my poor
> knowledge of amba, but I would have assumed that only a range
> of addresses is actually put on the bus, while others (e.g. RAM)
> are not visible on AMBA.
>
Grant can comment on the ranges technical correctness, I see it other
places but that's doesn't mean it's right.
AFAIK, everything is visible from this bus including RAM.
> > +static struct of_device_id zynq_of_bus_ids[] __initdata = {
> > + { .compatible = "simple-bus", },
> > + {}
> > +};
> > +
> > +static struct of_device_id gic_match[] = {
> > + { .compatible = "arm,gic", },
> > + {}
> > +};
> > +
> > +/**
> > + * xilinx_init_machine() - System specific initialization,
> intended
> to be
> > + * called from board specific initialization.
> > + */
> > +void __init xilinx_init_machine(void)
> > +{
> > + struct device_node *node = of_find_matching_node(NULL,
> gic_match);
> > +
> > + if (node)
> > + of_irq_domain_add_simple(node, 0, NR_IRQS);
> > +
> > +#ifdef CONFIG_CACHE_L2X0
> > + /*
> > + * 64KB way size, 8-way associativity, parity disabled
> > + */
> > + l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
> > +#endif
> > +
> > +/**
> > + * xilinx_irq_init() - Interrupt controller initialization for the
> GIC.
> > + */
> > +void __init xilinx_irq_init(void)
> > +{
> > + gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
> > +}
>
> I think we can do better than this, there is still more hardcoded
> stuff
> in here than I think should be. I understand that you tried to
> minimize
> the size of the patch set for obvious reasons, but none of this
> seems too board specific to put into common code in one way or
> another.
>
> Of course we can not fix all of this at once, but maybe we can have
> an explanation for each hardcoded setting on why it is still needed
> and what would have to be done to make it go away.
>
Yes we could explain hard coded numbers. Ideally GIC driver would support
device tree it seems like to me.
> > +/* The minimum devices needed to be mapped before the VM system is
> up
> and
> > + * running include the GIC, UART and Timer Counter.
> > + */
> > +
> > +static struct map_desc io_desc[] __initdata = {
> > + {
> > + .virtual = TTC0_VIRT,
> > + .pfn = __phys_to_pfn(TTC0_PHYS),
> > + .length = SZ_4K,
> > + .type = MT_DEVICE,
> > + }, {
> > + .virtual = SCU_PERIPH_VIRT,
> > + .pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
> > + .length = SZ_8K,
> > + .type = MT_DEVICE,
> > + }, {
> > + .virtual = PL310_L2CC_VIRT,
> > + .pfn = __phys_to_pfn(PL310_L2CC_PHYS),
> > + .length = SZ_4K,
> > + .type = MT_DEVICE,
> > + },
>
> I especially dislike the idea of having to set up iotables, these
> seem completely counterintuitive when we probe the devices from the
> device tree.
>
> AFAICT, all of init_irq, time_init and init_machine are called way
> after
> mm_init, so you should have ioremap available by the time you need to
> access these virtual memory ranges.
>
Seems like the GIC driver could remap it's own memory but maybe that won't
work across all platforms and then the platform would need to do it.
Yes the timer driver could remap it's own memory.
> I can understand why you'd want to special-case PCI I/O space windows
> and early serial port access, but I think we should handle them
> differently
> and give them fixed machine independent virtual addresses.
>
> > --- /dev/null
> > +++ b/arch/arm/mach-zynq/include/mach/io.h
> > --- /dev/null
> > +++ b/arch/arm/mach-zynq/include/mach/irqs.h
> > --- /dev/null
> > +++ b/arch/arm/mach-zynq/include/mach/memory.h
> > --- /dev/null
> > +++ b/arch/arm/mach-zynq/include/mach/system.h
> > --- /dev/null
> > +++ b/arch/arm/mach-zynq/include/mach/timex.h
> > --- /dev/null
> > +++ b/arch/arm/mach-zynq/include/mach/vmalloc.h
>
> These are all either completely generic versions that could be reused
> on a number of other machines, or they could be turned into such
> files.
>
> For the global inlude/asm-generic files, we have just added a
> mechanism
> to share that kind of file across multiple architectures using some
> Makefile magic. Should we perhaps do something similar here to avoid
> having to create more of the same files?
>
> > --- /dev/null
> > +++ b/arch/arm/mach-zynq/include/mach/uart.h
> > --- /dev/null
> > +++ b/arch/arm/mach-zynq/include/mach/uncompress.h
>
> For these, it obviously won't work.
>
> > diff --git a/arch/arm/mach-zynq/timer.c
> b/arch/arm/mach-zynq/timer.c
> > new file mode 100644
> > index 0000000..c2c96cc
> > --- /dev/null
> > +++ b/arch/arm/mach-zynq/timer.c
>
> In the light of the recent discussions of drivers moving out of
> platforms into common Linux code, do we expect this to also
> happen to timers any time soon?
I'm not sure on the rest. Thanks Arnd, appreciate the help.
-- John
>
> Arnd
>
>
> This email and any attachments are intended for the sole use of the
> named recipient(s) and contain(s) confidential information that may be
> proprietary, privileged or copyrighted under applicable law. If you
> are not the intended recipient, do not read, copy, or forward this
> email message or any attachments. Delete this email message and any
> attachments immediately.
On Monday 02 May 2011 23:27:04 [email protected] wrote:
> Yes we could explain hard coded numbers. Ideally GIC driver would support
> device tree it seems like to me.
>
> Seems like the GIC driver could remap it's own memory but maybe that won't
> work across all platforms and then the platform would need to do it.
Why not just add a stub in the xilinx platform for now that remaps the
memory using ioremap and calls the regular GIC initialization?
That function can then easily be moved to common code when another
platform uses it.
Arnd
> On Monday 02 May 2011 23:27:04 [email protected] wrote:
> > Yes we could explain hard coded numbers. Ideally GIC driver would
> support
> > device tree it seems like to me.
>
> >
> > Seems like the GIC driver could remap it's own memory but maybe that
> won't
> > work across all platforms and then the platform would need to do
> it.
>
> Why not just add a stub in the xilinx platform for now that remaps
> the
> memory using ioremap and calls the regular GIC initialization?
Seems easy enough assuming we don't need the SCU early for the core count
and can get that from the device tree.
Since the SCU and part of the GIC end up in the same 4K page they need to be
together (unless I'm thinking about that wrong).
SCU 0xF8000000
GIC_CPU 0xF8000100
GIC_DIS 0xF8001000
-- John
>
> That function can then easily be moved to common code when another
> platform uses it.
>
> Arnd
On Mon, May 02, 2011 at 09:50:11PM +0000, [email protected] wrote:
> Seems easy enough assuming we don't need the SCU early for the core count
> and can get that from the device tree.
Beware. Things may not be that trivial when you start considering some
of the weirdnesses that some vendors start coming out with.
> Since the SCU and part of the GIC end up in the same 4K page they need to be
> together (unless I'm thinking about that wrong).
>
> SCU 0xF8000000
> GIC_CPU 0xF8000100
> GIC_DIS 0xF8001000
It is preferable to use the same mapping, as it ensures that you're not
going to create incompatible aliases.
But, before we get too bogged down with this, please realise that it is
possible to setup early mappings from the device tree for things like the
SCU. Maybe not using ioremap(), but I'm sure we can find some way to use
the iotable_init() stuff to setup some early mappings from DT for this
stuff.
On Mon, May 2, 2011 at 5:01 PM, Russell King - ARM Linux
<[email protected]> wrote:
> On Mon, May 02, 2011 at 09:50:11PM +0000, [email protected] wrote:
>> Seems easy enough assuming we don't need the SCU early for the core count
>> and can get that from the device tree.
>
> Beware. ?Things may not be that trivial when you start considering some
> of the weirdnesses that some vendors start coming out with.
>
>> Since the SCU and part of the GIC end up in the same 4K page they need to be
>> together (unless I'm thinking about that wrong).
>>
>> SCU 0xF8000000
>> GIC_CPU 0xF8000100
>> GIC_DIS 0xF8001000
>
> It is preferable to use the same mapping, as it ensures that you're not
> going to create incompatible aliases.
>
> But, before we get too bogged down with this, please realise that it is
> possible to setup early mappings from the device tree for things like the
> SCU. ?Maybe not using ioremap(), but I'm sure we can find some way to use
> the iotable_init() stuff to setup some early mappings from DT for this
> stuff.
absolutely.
g.
On Tuesday 03 May 2011 01:01:18 Russell King - ARM Linux wrote:
> It is preferable to use the same mapping, as it ensures that you're not
> going to create incompatible aliases.
Is aliasing a problem for MMIO mappings? I would think that you can
ioremap registers anywhere and as often as you want because they are
never cacheable.
> But, before we get too bogged down with this, please realise that it is
> possible to setup early mappings from the device tree for things like the
> SCU. Maybe not using ioremap(), but I'm sure we can find some way to use
> the iotable_init() stuff to setup some early mappings from DT for this
> stuff.
Good point. It doesn't really matter how the entries get into the page
table, whether you call it ioremap, iotable_init, create_mapping or
ioremap_early. What matters is that we don't hardcode the physical
address in the board code, because that limits the possible reuse
on other device tree enabled targets.
Arnd
On Tue, May 03, 2011 at 09:58:14AM +0200, Arnd Bergmann wrote:
> On Tuesday 03 May 2011 01:01:18 Russell King - ARM Linux wrote:
> > It is preferable to use the same mapping, as it ensures that you're not
> > going to create incompatible aliases.
>
> Is aliasing a problem for MMIO mappings? I would think that you can
> ioremap registers anywhere and as often as you want because they are
> never cacheable.
Provided the type and sharability is identical then there is no problem.
I wasn't referring to multiple ioremap()s of the same region - that
should be fine as the same attributes will be used. If you mix ioremap()
and iotable_init() then you _could_ have problems if you don't use
MT_DEVICE in the iotable.
What I'm basically saying is that mixing the methods of creating these
mappings makes it much easier to get tripped up over these issues.
On Tuesday 03 May 2011, Russell King - ARM Linux wrote:
> On Tue, May 03, 2011 at 09:58:14AM +0200, Arnd Bergmann wrote:
> > On Tuesday 03 May 2011 01:01:18 Russell King - ARM Linux wrote:
> > > It is preferable to use the same mapping, as it ensures that you're not
> > > going to create incompatible aliases.
> >
> > Is aliasing a problem for MMIO mappings? I would think that you can
> > ioremap registers anywhere and as often as you want because they are
> > never cacheable.
>
> Provided the type and sharability is identical then there is no problem.
> I wasn't referring to multiple ioremap()s of the same region - that
> should be fine as the same attributes will be used. If you mix ioremap()
> and iotable_init() then you _could_ have problems if you don't use
> MT_DEVICE in the iotable.
>
> What I'm basically saying is that mixing the methods of creating these
> mappings makes it much easier to get tripped up over these issues.
Ok, makes sense.
Thanks,
Arnd