All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] ARM: Xilinx: Adding Xilinx platform infrastructure support
       [not found] <1296922637-24662-1-git-send-email-john.linn@xilinx.com>
@ 2011-02-05 16:17   ` John Linn
       [not found] ` <1296922637-24662-2-git-send-email-john.linn@xilinx.com>
  1 sibling, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 16:17 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linux, catalin.marinas, glikely; +Cc: John Linn

Minimum infrastructure to add the Xilinx machine and allow it to
be selected in the build.

Signed-off-by: John Linn <john.linn@xilinx.com>
---
 arch/arm/Kconfig    |   13 +++++++++++++
 arch/arm/Makefile   |    1 +
 arch/arm/mm/Kconfig |    4 ++--
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5cff165..3317671 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -875,6 +875,17 @@ config PLAT_SPEAR
 	help
 	  Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
 
+config ARCH_XILINX
+	bool "Xilinx ARM Cortex A9 Based FPGA"
+	select CPU_V7
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select CLKDEV_LOOKUP
+	select ARM_GIC
+	select ARM_AMBA
+	help
+	  Support for Xilinx ARM Cortex A9 Based FPGA
+
 endchoice
 
 #
@@ -1009,6 +1020,8 @@ source "arch/arm/mach-vexpress/Kconfig"
 
 source "arch/arm/mach-w90x900/Kconfig"
 
+source "arch/arm/mach-xilinx/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index c22c1ad..4bad6ef 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -197,6 +197,7 @@ machine-$(CONFIG_MACH_SPEAR300)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR310)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR320)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR600)		:= spear6xx
+machine-$(CONFIG_ARCH_XILINX)		:= xilinx
 
 # Platform directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 9d30c6f..cf0c6f6 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -415,7 +415,7 @@ config CPU_32v6K
 
 # ARMv7
 config CPU_V7
-	bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
+	bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || ARCH_XILINX
 	select CPU_32v6K if !ARCH_OMAP2
 	select CPU_32v7
 	select CPU_ABRT_EV7
@@ -813,7 +813,7 @@ config CACHE_L2X0
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
 		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \
 		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_S5PV310 || ARCH_TEGRA || \
-		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
+		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || ARCH_XILINX
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC
-- 
1.6.2.1



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.



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 1/4] ARM: Xilinx: Adding Xilinx platform infrastructure support
@ 2011-02-05 16:17   ` John Linn
  0 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 16:17 UTC (permalink / raw)
  To: linux-arm-kernel

Minimum infrastructure to add the Xilinx machine and allow it to
be selected in the build.

Signed-off-by: John Linn <john.linn@xilinx.com>
---
 arch/arm/Kconfig    |   13 +++++++++++++
 arch/arm/Makefile   |    1 +
 arch/arm/mm/Kconfig |    4 ++--
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5cff165..3317671 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -875,6 +875,17 @@ config PLAT_SPEAR
 	help
 	  Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
 
+config ARCH_XILINX
+	bool "Xilinx ARM Cortex A9 Based FPGA"
+	select CPU_V7
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select CLKDEV_LOOKUP
+	select ARM_GIC
+	select ARM_AMBA
+	help
+	  Support for Xilinx ARM Cortex A9 Based FPGA
+
 endchoice
 
 #
@@ -1009,6 +1020,8 @@ source "arch/arm/mach-vexpress/Kconfig"
 
 source "arch/arm/mach-w90x900/Kconfig"
 
+source "arch/arm/mach-xilinx/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index c22c1ad..4bad6ef 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -197,6 +197,7 @@ machine-$(CONFIG_MACH_SPEAR300)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR310)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR320)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR600)		:= spear6xx
+machine-$(CONFIG_ARCH_XILINX)		:= xilinx
 
 # Platform directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 9d30c6f..cf0c6f6 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -415,7 +415,7 @@ config CPU_32v6K
 
 # ARMv7
 config CPU_V7
-	bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
+	bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || ARCH_XILINX
 	select CPU_32v6K if !ARCH_OMAP2
 	select CPU_32v7
 	select CPU_ABRT_EV7
@@ -813,7 +813,7 @@ config CACHE_L2X0
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
 		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \
 		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_S5PV310 || ARCH_TEGRA || \
-		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
+		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || ARCH_XILINX
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC
-- 
1.6.2.1



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.

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
       [not found] ` <1296922637-24662-2-git-send-email-john.linn@xilinx.com>
@ 2011-02-05 16:17     ` John Linn
       [not found]   ` <1296922637-24662-3-git-send-email-john.linn@xilinx.com>
  1 sibling, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 16:17 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linux, catalin.marinas, glikely; +Cc: John Linn

The 1st board support is minimal to get a system up and running
on the Xilinx platform.

Signed-off-by: John Linn <john.linn@xilinx.com>
---
 arch/arm/mach-xilinx/Kconfig       |   14 ++++
 arch/arm/mach-xilinx/Makefile      |    6 ++
 arch/arm/mach-xilinx/Makefile.boot |    3 +
 arch/arm/mach-xilinx/board_ep107.c |   81 ++++++++++++++++++++++
 arch/arm/mach-xilinx/common.c      |  132 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-xilinx/common.h      |   32 +++++++++
 6 files changed, 268 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-xilinx/Kconfig
 create mode 100644 arch/arm/mach-xilinx/Makefile
 create mode 100644 arch/arm/mach-xilinx/Makefile.boot
 create mode 100644 arch/arm/mach-xilinx/board_ep107.c
 create mode 100644 arch/arm/mach-xilinx/common.c
 create mode 100644 arch/arm/mach-xilinx/common.h

diff --git a/arch/arm/mach-xilinx/Kconfig b/arch/arm/mach-xilinx/Kconfig
new file mode 100644
index 0000000..11f9e65
--- /dev/null
+++ b/arch/arm/mach-xilinx/Kconfig
@@ -0,0 +1,14 @@
+if ARCH_XILINX
+
+choice
+        prompt "Board Selection"
+	default XILINX_EP107
+
+config XILINX_EP107
+	bool "Xilinx EP107 Board"
+	help
+	  Select if you are using a Xilinx EP107 board.
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-xilinx/Makefile b/arch/arm/mach-xilinx/Makefile
new file mode 100644
index 0000000..194f9e4
--- /dev/null
+++ b/arch/arm/mach-xilinx/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := common.o board_ep107.o timer.o
diff --git a/arch/arm/mach-xilinx/Makefile.boot b/arch/arm/mach-xilinx/Makefile.boot
new file mode 100644
index 0000000..67039c3
--- /dev/null
+++ b/arch/arm/mach-xilinx/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x00800000
diff --git a/arch/arm/mach-xilinx/board_ep107.c b/arch/arm/mach-xilinx/board_ep107.c
new file mode 100644
index 0000000..233e744
--- /dev/null
+++ b/arch/arm/mach-xilinx/board_ep107.c
@@ -0,0 +1,81 @@
+/* arch/arm/mach-xilinx/board_ep107.c
+ *
+ * This file contains code specific to the Xilinx EP107 board.
+ *
+ *  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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/hardware.h>
+#include <linux/clkdev.h>
+#include "common.h"
+
+/*
+ * Fixed clocks for now
+ */
+
+static struct clk ref50_clk = {
+	.rate	= 50000000,
+};
+
+/* Create all the platform devices for the board */
+
+static struct resource uart0[] = {
+	{
+		.start = UART0_BASE,
+		.end = UART0_BASE + 0xFFF,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_UART0,
+		.end = IRQ_UART0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device uart_device0 = {
+	.name = "xuartpss",
+	.id = 0,
+	.dev = {
+		.platform_data = &ref50_clk.rate,
+	},
+	.resource = uart0,
+	.num_resources = ARRAY_SIZE(uart0),
+};
+
+static struct platform_device *xilinx_pdevices[] __initdata = {
+	&uart_device0,
+};
+
+/**
+ * board_ep107_init - Board specific initialization for the Xilinx EP107 board.
+ *
+ **/
+static void __init board_ep107_init(void)
+{
+	system_init();
+	platform_device_init(xilinx_pdevices, ARRAY_SIZE(xilinx_pdevices));
+}
+
+MACHINE_START(XILINX_EP107, "Xilinx EP107")
+	.boot_params    = PHYS_OFFSET + 0x00000100,
+	.map_io         = map_io,
+	.init_irq       = irq_init,
+	.init_machine   = board_ep107_init,
+	.timer          = &xttcpss_sys_timer,
+MACHINE_END
diff --git a/arch/arm/mach-xilinx/common.c b/arch/arm/mach-xilinx/common.c
new file mode 100644
index 0000000..f7c51a7
--- /dev/null
+++ b/arch/arm/mach-xilinx/common.c
@@ -0,0 +1,132 @@
+/* arch/arm/mach-xilinx/common.c
+ *
+ * This file contains common code that is intended to be used across
+ * boards so that it's not replicated.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm/mach/map.h>
+#include <asm/page.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/hardware.h>
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+}
+
+/**
+ * system_init - System specific initialization, intended to be called from
+ *			board specific initialization.
+ *
+ **/
+void __init system_init(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+	void *l2cache_base = (void *)PL310_L2CC_BASE;
+
+	/*
+	 * 64KB way size, 8-way associativity, parity disabled
+	 */
+	l2x0_init(l2cache_base, 0x02060000, 0xF0F0FFFF);
+#endif
+}
+
+/**
+ * irq_init - Interrupt controller initialization for the GIC.
+ *
+ **/
+void __init irq_init(void)
+{
+	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
+	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE, gic_cpu_base_addr);
+}
+
+/* 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_BASE,
+		.pfn		= __phys_to_pfn(TTC0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= SCU_PERIPH_BASE,
+		.pfn		= __phys_to_pfn(SCU_PERIPH_BASE),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= PL310_L2CC_BASE,
+		.pfn		= __phys_to_pfn(PL310_L2CC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+
+#ifdef CONFIG_DEBUG_LL
+	{
+		.virtual	= UART0_BASE,
+		.pfn		= __phys_to_pfn(UART0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+#endif
+
+};
+
+/**
+ * map_io - Create memory mappings needed for early I/O.
+ *
+ **/
+void __init map_io(void)
+{
+	iotable_init(io_desc, ARRAY_SIZE(io_desc));
+}
+
+/**
+ * platform_device_init - Initialize all the platform devices.
+ *
+ **/
+void __init platform_device_init(struct platform_device *xilinx_pdevices[],
+					int count)
+{
+	int ret, i;
+
+	/* Initialize all the platform devices */
+
+	for (i = 0; i < count; i++) {
+
+		pr_info("registering platform device '%s' id %d\n",
+			xilinx_pdevices[i]->name,
+			xilinx_pdevices[i]->id);
+
+		ret = platform_device_register(xilinx_pdevices[i]);
+		if (ret)
+			pr_info("Unable to register platform device '%s': %d\n",
+				xilinx_pdevices[i]->name, ret);
+	}
+}
+
diff --git a/arch/arm/mach-xilinx/common.h b/arch/arm/mach-xilinx/common.h
new file mode 100644
index 0000000..49de295
--- /dev/null
+++ b/arch/arm/mach-xilinx/common.h
@@ -0,0 +1,32 @@
+/* arch/arm/mach-xilinx/common.h
+ *
+ * This file contains common function prototypes to avoid externs
+ * in the c files.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_XILINX_COMMON_H__
+#define __MACH_XILINX_COMMON_H__
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+void __init system_init(void);
+void __init irq_init(void);
+void __init map_io(void);
+void __init platform_device_init(struct platform_device *pdevices[],
+					int count);
+
+extern struct sys_timer xttcpss_sys_timer;
+
+#endif
-- 
1.6.2.1



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.



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
@ 2011-02-05 16:17     ` John Linn
  0 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 16:17 UTC (permalink / raw)
  To: linux-arm-kernel

The 1st board support is minimal to get a system up and running
on the Xilinx platform.

Signed-off-by: John Linn <john.linn@xilinx.com>
---
 arch/arm/mach-xilinx/Kconfig       |   14 ++++
 arch/arm/mach-xilinx/Makefile      |    6 ++
 arch/arm/mach-xilinx/Makefile.boot |    3 +
 arch/arm/mach-xilinx/board_ep107.c |   81 ++++++++++++++++++++++
 arch/arm/mach-xilinx/common.c      |  132 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-xilinx/common.h      |   32 +++++++++
 6 files changed, 268 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-xilinx/Kconfig
 create mode 100644 arch/arm/mach-xilinx/Makefile
 create mode 100644 arch/arm/mach-xilinx/Makefile.boot
 create mode 100644 arch/arm/mach-xilinx/board_ep107.c
 create mode 100644 arch/arm/mach-xilinx/common.c
 create mode 100644 arch/arm/mach-xilinx/common.h

diff --git a/arch/arm/mach-xilinx/Kconfig b/arch/arm/mach-xilinx/Kconfig
new file mode 100644
index 0000000..11f9e65
--- /dev/null
+++ b/arch/arm/mach-xilinx/Kconfig
@@ -0,0 +1,14 @@
+if ARCH_XILINX
+
+choice
+        prompt "Board Selection"
+	default XILINX_EP107
+
+config XILINX_EP107
+	bool "Xilinx EP107 Board"
+	help
+	  Select if you are using a Xilinx EP107 board.
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-xilinx/Makefile b/arch/arm/mach-xilinx/Makefile
new file mode 100644
index 0000000..194f9e4
--- /dev/null
+++ b/arch/arm/mach-xilinx/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := common.o board_ep107.o timer.o
diff --git a/arch/arm/mach-xilinx/Makefile.boot b/arch/arm/mach-xilinx/Makefile.boot
new file mode 100644
index 0000000..67039c3
--- /dev/null
+++ b/arch/arm/mach-xilinx/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x00800000
diff --git a/arch/arm/mach-xilinx/board_ep107.c b/arch/arm/mach-xilinx/board_ep107.c
new file mode 100644
index 0000000..233e744
--- /dev/null
+++ b/arch/arm/mach-xilinx/board_ep107.c
@@ -0,0 +1,81 @@
+/* arch/arm/mach-xilinx/board_ep107.c
+ *
+ * This file contains code specific to the Xilinx EP107 board.
+ *
+ *  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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/hardware.h>
+#include <linux/clkdev.h>
+#include "common.h"
+
+/*
+ * Fixed clocks for now
+ */
+
+static struct clk ref50_clk = {
+	.rate	= 50000000,
+};
+
+/* Create all the platform devices for the board */
+
+static struct resource uart0[] = {
+	{
+		.start = UART0_BASE,
+		.end = UART0_BASE + 0xFFF,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_UART0,
+		.end = IRQ_UART0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device uart_device0 = {
+	.name = "xuartpss",
+	.id = 0,
+	.dev = {
+		.platform_data = &ref50_clk.rate,
+	},
+	.resource = uart0,
+	.num_resources = ARRAY_SIZE(uart0),
+};
+
+static struct platform_device *xilinx_pdevices[] __initdata = {
+	&uart_device0,
+};
+
+/**
+ * board_ep107_init - Board specific initialization for the Xilinx EP107 board.
+ *
+ **/
+static void __init board_ep107_init(void)
+{
+	system_init();
+	platform_device_init(xilinx_pdevices, ARRAY_SIZE(xilinx_pdevices));
+}
+
+MACHINE_START(XILINX_EP107, "Xilinx EP107")
+	.boot_params    = PHYS_OFFSET + 0x00000100,
+	.map_io         = map_io,
+	.init_irq       = irq_init,
+	.init_machine   = board_ep107_init,
+	.timer          = &xttcpss_sys_timer,
+MACHINE_END
diff --git a/arch/arm/mach-xilinx/common.c b/arch/arm/mach-xilinx/common.c
new file mode 100644
index 0000000..f7c51a7
--- /dev/null
+++ b/arch/arm/mach-xilinx/common.c
@@ -0,0 +1,132 @@
+/* arch/arm/mach-xilinx/common.c
+ *
+ * This file contains common code that is intended to be used across
+ * boards so that it's not replicated.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm/mach/map.h>
+#include <asm/page.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/hardware.h>
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+}
+
+/**
+ * system_init - System specific initialization, intended to be called from
+ *			board specific initialization.
+ *
+ **/
+void __init system_init(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+	void *l2cache_base = (void *)PL310_L2CC_BASE;
+
+	/*
+	 * 64KB way size, 8-way associativity, parity disabled
+	 */
+	l2x0_init(l2cache_base, 0x02060000, 0xF0F0FFFF);
+#endif
+}
+
+/**
+ * irq_init - Interrupt controller initialization for the GIC.
+ *
+ **/
+void __init irq_init(void)
+{
+	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
+	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE, gic_cpu_base_addr);
+}
+
+/* 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_BASE,
+		.pfn		= __phys_to_pfn(TTC0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= SCU_PERIPH_BASE,
+		.pfn		= __phys_to_pfn(SCU_PERIPH_BASE),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= PL310_L2CC_BASE,
+		.pfn		= __phys_to_pfn(PL310_L2CC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+
+#ifdef CONFIG_DEBUG_LL
+	{
+		.virtual	= UART0_BASE,
+		.pfn		= __phys_to_pfn(UART0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+#endif
+
+};
+
+/**
+ * map_io - Create memory mappings needed for early I/O.
+ *
+ **/
+void __init map_io(void)
+{
+	iotable_init(io_desc, ARRAY_SIZE(io_desc));
+}
+
+/**
+ * platform_device_init - Initialize all the platform devices.
+ *
+ **/
+void __init platform_device_init(struct platform_device *xilinx_pdevices[],
+					int count)
+{
+	int ret, i;
+
+	/* Initialize all the platform devices */
+
+	for (i = 0; i < count; i++) {
+
+		pr_info("registering platform device '%s' id %d\n",
+			xilinx_pdevices[i]->name,
+			xilinx_pdevices[i]->id);
+
+		ret = platform_device_register(xilinx_pdevices[i]);
+		if (ret)
+			pr_info("Unable to register platform device '%s': %d\n",
+				xilinx_pdevices[i]->name, ret);
+	}
+}
+
diff --git a/arch/arm/mach-xilinx/common.h b/arch/arm/mach-xilinx/common.h
new file mode 100644
index 0000000..49de295
--- /dev/null
+++ b/arch/arm/mach-xilinx/common.h
@@ -0,0 +1,32 @@
+/* arch/arm/mach-xilinx/common.h
+ *
+ * This file contains common function prototypes to avoid externs
+ * in the c files.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_XILINX_COMMON_H__
+#define __MACH_XILINX_COMMON_H__
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+void __init system_init(void);
+void __init irq_init(void);
+void __init map_io(void);
+void __init platform_device_init(struct platform_device *pdevices[],
+					int count);
+
+extern struct sys_timer xttcpss_sys_timer;
+
+#endif
-- 
1.6.2.1



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.

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
       [not found]   ` <1296922637-24662-3-git-send-email-john.linn@xilinx.com>
@ 2011-02-05 16:17       ` John Linn
       [not found]     ` <1296922637-24662-4-git-send-email-john.linn@xilinx.com>
  1 sibling, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 16:17 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linux, catalin.marinas, glikely
  Cc: John Linn, Kiran Sutariya

The timer driver supports the Xilinx PS Timer Counter IP.

Signed-off-by: Kiran Sutariya <kiran.sutariya@einfochips.com>
Signed-off-by: John Linn <john.linn@xilinx.com>
---
 arch/arm/mach-xilinx/timer.c |  452 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 452 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-xilinx/timer.c

diff --git a/arch/arm/mach-xilinx/timer.c b/arch/arm/mach-xilinx/timer.c
new file mode 100644
index 0000000..c713e3c
--- /dev/null
+++ b/arch/arm/mach-xilinx/timer.c
@@ -0,0 +1,452 @@
+/* arch/arm/mach-xilinx/timer.c
+ *
+ * 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 program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#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/hardware.h>
+
+/*
+ * 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 is 200MHz which is common to all the
+ * timer channel (T1, T2, and T3)
+ * Clocksource timer resolution is 160ns
+ * Clockevent timer resolution is 160ns
+ */
+#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
+
+/*
+ * 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 */
+
+/*
+ * Bit mask to enable/disable the timer
+ */
+#define XTTCPSS_CNT_CNTRL_ENABLE_MASK	0xFFFFFFFE
+
+/*
+ * Definitions of the timer read/write macro
+ */
+#define xttcpss_read(addr)	__raw_readl((void __iomem *)addr)
+#define xttcpss_write(addr, val) __raw_writel(val, (void __iomem *)(addr))
+
+
+/**
+ * struct xttcpss_timer - This definition defines local timer structure
+ *
+ * @name:	Name of Timer
+ * @base_addr:	Base address of timer
+ * @timer_irq:	irqaction structure for the timer device
+ * @mode:       only valid for an clock event, periodic or one-shot
+ **/
+struct xttcpss_timer {
+	char *name;
+	unsigned long base_addr;
+	struct irqaction timer_irq;
+	enum clock_event_mode mode;
+};
+
+
+static struct xttcpss_timer timers[];
+static struct clock_event_device xttcpss_clockevent;
+
+/*
+ * xttcpss_timer_irqs - Timers IRQ number
+ */
+static int xttcpss_timer_irqs[2] = {
+	IRQ_TIMERCOUNTER0,	/* Timer 1 IRQ number */
+	IRQ_TIMERCOUNTER0 + 1,	/* Timer 2 IRQ number */
+};
+
+/**
+ * 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 = xttcpss_read(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET, ctrl_reg);
+
+	pr_debug("set_interval, name = %s, period = %08X\n",
+			timer->name, (unsigned int)cycles);
+
+	xttcpss_write(timer->base_addr + XTTCPSS_INTR_VAL_OFFSET, cycles);
+
+	/* Reset the counter (0x10) so that it starts from 0, one-shot
+	   mode makes this needed for timing to be right. */
+	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
+	ctrl_reg |= 0x10;
+	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET, ctrl_reg);
+}
+
+/**
+ * xttcpss_clock_source_interrupt - Clock source timer interrupt handler
+ *
+ * @irq:	IRQ number of the Timer
+ * @dev_id:	void pointer to the xttcpss_timer instance
+ *
+ * This will be called when 16-bit clock source counter wraps
+ *
+ * returns: Always IRQ_HANDLED - success
+ **/
+static irqreturn_t xttcpss_clock_source_interrupt(int irq, void *dev_id)
+{
+	struct xttcpss_timer *timer = dev_id;
+
+	/* Acknowledge the interrupt */
+	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
+		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * 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;
+	u32 ctrl_reg;
+
+	/* Acknowledge the interrupt and call event handler */
+	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
+		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
+
+	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
+
+		/* Disable the counter as it would keep running. */
+		ctrl_reg = xttcpss_read(timer->base_addr +
+					XTTCPSS_CNT_CNTRL_OFFSET);
+		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+	}
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * struct xttcpss_timer timers - This definition defines local timers
+ */
+static struct xttcpss_timer timers[] = {
+	[XTTCPSS_CLOCKSOURCE] = {
+		.name = "xttcpss clocksource",
+		.timer_irq = {
+			.flags = IRQF_DISABLED | IRQF_TIMER,
+			.handler = xttcpss_clock_source_interrupt,
+		}
+	},
+	[XTTCPSS_CLOCKEVENT] = {
+		.name = "xttcpss clockevent",
+		.timer_irq = {
+			.flags = IRQF_DISABLED | IRQF_TIMER,
+			.handler = xttcpss_clock_event_interrupt,
+		}
+	},
+};
+
+
+/**
+ * xttcpss_timer_hardware_init - Initialize the timer hardware
+ *
+ * Initialize the hardware, registers the timer interrupts, set the clock source
+ * timer interval and enable the clock source timer
+ **/
+static void __init xttcpss_timer_hardware_init(void)
+{
+	int timer_id;
+	struct xttcpss_timer *timer;
+
+	for (timer_id = 0; timer_id < ARRAY_SIZE(timers); timer_id++) {
+		timer = &timers[timer_id];
+
+		if (!(timer->name))
+			continue;
+
+		timer->base_addr = XTTCPSS_TIMER_BASE + (4*timer_id);
+
+		/* Disable counter, Enable Interval mode, Count up timer,
+		 * Disable Match mode, Internal Clock source select, set
+		 * prescalar to 32, and Enable the Interval interrupt */
+		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				0x23);
+		xttcpss_write(timer->base_addr + XTTCPSS_CLK_CNTRL_OFFSET, 0x9);
+		xttcpss_write(timer->base_addr + XTTCPSS_IER_OFFSET, 0x1);
+
+		/* Setup IRQ */
+		timer->timer_irq.name = timer->name;
+		timer->timer_irq.dev_id = (void *)timer;
+		if (timer->timer_irq.handler != NULL) {
+			setup_irq(xttcpss_timer_irqs[timer_id],
+				&timer->timer_irq);
+		}
+		if (timer_id == XTTCPSS_CLOCKSOURCE)
+			xttcpss_set_interval(timer, ~0);
+	}
+}
+
+/**
+ * xttcpss_read_cycles - Reads the timer counter register
+ *
+ * returns: Current timer counter register value
+ **/
+static cycle_t xttcpss_read_cycles(struct clocksource *cs)
+{
+	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+
+	return (cycle_t)xttcpss_read(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		= xttcpss_read_cycles,
+	.mask		= CLOCKSOURCE_MASK(16),
+	.shift		= 0,			/* Initialized to zero */
+	.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;
+
+	timer->mode = mode;
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		xttcpss_set_interval(timer, CLOCK_TICK_RATE / HZ);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		ctrl_reg = xttcpss_read(timer->base_addr +
+					XTTCPSS_CNT_CNTRL_OFFSET);
+		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		ctrl_reg = xttcpss_read(timer->base_addr +
+					XTTCPSS_CNT_CNTRL_OFFSET);
+		ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
+		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+		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,
+	.shift		= 0,		/* Initialized to zero */
+	.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 registers the clock source and clock event
+ * timers with Linux kernal timer framework
+ **/
+static void __init xttcpss_timer_init(void)
+{
+	u32 shift;
+	u64 temp;
+
+	xttcpss_timer_hardware_init();
+
+	/* Calculate the nanoseconds to cycles divisor value for clock source
+	 * timer */
+	for (shift = 16; shift > 0; shift--) {
+		temp = (u64) NSEC_PER_SEC << shift;
+		do_div(temp, CLOCK_TICK_RATE);
+		if ((temp >> 32) == 0)
+			break;
+	}
+
+	/* Setup clocksource */
+	clocksource_xttcpss.shift = shift;
+	clocksource_xttcpss.mult =
+		clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_xttcpss.shift);
+
+	if (clocksource_register(&clocksource_xttcpss))
+		printk(KERN_ERR "xttcpss_timer_init: can't register clocksource"
+				" for %s\n", clocksource_xttcpss.name);
+	/* Calculate the nanoseconds to cycles divisor value for clock event
+	 * timer */
+	for (shift = 16; shift > 0; shift--) {
+		temp = (u64) CLOCK_TICK_RATE << shift;
+		do_div(temp, NSEC_PER_SEC);
+		if ((temp >> 32) == 0)
+			break;
+	}
+
+	/* Setup clockevent */
+	xttcpss_clockevent.shift = shift;
+	xttcpss_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
+						 xttcpss_clockevent.shift);
+
+	xttcpss_clockevent.max_delta_ns =
+		clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
+	xttcpss_clockevent.min_delta_ns =
+		clockevent_delta2ns(1, &xttcpss_clockevent);
+
+	xttcpss_clockevent.cpumask = cpumask_of(0);
+	clockevents_register_device(&xttcpss_clockevent);
+}
+
+#ifdef CONFIG_PM
+/**
+ * xttcpss_timer_suspend - Suspend the timer
+ *
+ * Disables all (clock source and clock event) the timers
+ **/
+static void xttcpss_timer_suspend(void)
+{
+	struct xttcpss_timer *source_timer = &timers[XTTCPSS_CLOCKSOURCE];
+	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
+	u32 ctrl_reg;
+
+	/* Disable clocksource timer */
+	ctrl_reg = xttcpss_read(source_timer->base_addr +
+				XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+	xttcpss_write(source_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+
+	/* Disable clockevent timer */
+	ctrl_reg = xttcpss_read(event_timer->base_addr +
+				XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+}
+
+/**
+ * xttcpss_timer_resume - Resume the timer
+ *
+ * Enables  all (clock source and clock event) the timers
+ **/
+static void xttcpss_timer_resume(void)
+{
+	struct xttcpss_timer *source_timer = &timers[XTTCPSS_CLOCKSOURCE];
+	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
+	u32 ctrl_reg;
+
+	/* Enable clocksource timer */
+	ctrl_reg = xttcpss_read(source_timer->base_addr +
+				XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
+	xttcpss_write(source_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+
+	/* Enable clockevent timer */
+	ctrl_reg = xttcpss_read(event_timer->base_addr +
+				XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
+	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+}
+#else
+#define xttcpss_timer_suspend NULL
+#define xttcpss_timer_resume NULL
+#endif
+
+/*
+ * Instantiate and initialize the system timer structure
+ */
+struct sys_timer xttcpss_sys_timer = {
+	.init		= xttcpss_timer_init,
+	.suspend	= xttcpss_timer_suspend,
+	.resume		= xttcpss_timer_resume,
+};
-- 
1.6.2.1



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.



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
@ 2011-02-05 16:17       ` John Linn
  0 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 16:17 UTC (permalink / raw)
  To: linux-arm-kernel

The timer driver supports the Xilinx PS Timer Counter IP.

Signed-off-by: Kiran Sutariya <kiran.sutariya@einfochips.com>
Signed-off-by: John Linn <john.linn@xilinx.com>
---
 arch/arm/mach-xilinx/timer.c |  452 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 452 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-xilinx/timer.c

diff --git a/arch/arm/mach-xilinx/timer.c b/arch/arm/mach-xilinx/timer.c
new file mode 100644
index 0000000..c713e3c
--- /dev/null
+++ b/arch/arm/mach-xilinx/timer.c
@@ -0,0 +1,452 @@
+/* arch/arm/mach-xilinx/timer.c
+ *
+ * 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 program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#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/hardware.h>
+
+/*
+ * 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 is 200MHz which is common to all the
+ * timer channel (T1, T2, and T3)
+ * Clocksource timer resolution is 160ns
+ * Clockevent timer resolution is 160ns
+ */
+#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
+
+/*
+ * 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 */
+
+/*
+ * Bit mask to enable/disable the timer
+ */
+#define XTTCPSS_CNT_CNTRL_ENABLE_MASK	0xFFFFFFFE
+
+/*
+ * Definitions of the timer read/write macro
+ */
+#define xttcpss_read(addr)	__raw_readl((void __iomem *)addr)
+#define xttcpss_write(addr, val) __raw_writel(val, (void __iomem *)(addr))
+
+
+/**
+ * struct xttcpss_timer - This definition defines local timer structure
+ *
+ * @name:	Name of Timer
+ * @base_addr:	Base address of timer
+ * @timer_irq:	irqaction structure for the timer device
+ * @mode:       only valid for an clock event, periodic or one-shot
+ **/
+struct xttcpss_timer {
+	char *name;
+	unsigned long base_addr;
+	struct irqaction timer_irq;
+	enum clock_event_mode mode;
+};
+
+
+static struct xttcpss_timer timers[];
+static struct clock_event_device xttcpss_clockevent;
+
+/*
+ * xttcpss_timer_irqs - Timers IRQ number
+ */
+static int xttcpss_timer_irqs[2] = {
+	IRQ_TIMERCOUNTER0,	/* Timer 1 IRQ number */
+	IRQ_TIMERCOUNTER0 + 1,	/* Timer 2 IRQ number */
+};
+
+/**
+ * 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 = xttcpss_read(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET, ctrl_reg);
+
+	pr_debug("set_interval, name = %s, period = %08X\n",
+			timer->name, (unsigned int)cycles);
+
+	xttcpss_write(timer->base_addr + XTTCPSS_INTR_VAL_OFFSET, cycles);
+
+	/* Reset the counter (0x10) so that it starts from 0, one-shot
+	   mode makes this needed for timing to be right. */
+	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
+	ctrl_reg |= 0x10;
+	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET, ctrl_reg);
+}
+
+/**
+ * xttcpss_clock_source_interrupt - Clock source timer interrupt handler
+ *
+ * @irq:	IRQ number of the Timer
+ * @dev_id:	void pointer to the xttcpss_timer instance
+ *
+ * This will be called when 16-bit clock source counter wraps
+ *
+ * returns: Always IRQ_HANDLED - success
+ **/
+static irqreturn_t xttcpss_clock_source_interrupt(int irq, void *dev_id)
+{
+	struct xttcpss_timer *timer = dev_id;
+
+	/* Acknowledge the interrupt */
+	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
+		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * 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;
+	u32 ctrl_reg;
+
+	/* Acknowledge the interrupt and call event handler */
+	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
+		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
+
+	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
+
+		/* Disable the counter as it would keep running. */
+		ctrl_reg = xttcpss_read(timer->base_addr +
+					XTTCPSS_CNT_CNTRL_OFFSET);
+		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+	}
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * struct xttcpss_timer timers - This definition defines local timers
+ */
+static struct xttcpss_timer timers[] = {
+	[XTTCPSS_CLOCKSOURCE] = {
+		.name = "xttcpss clocksource",
+		.timer_irq = {
+			.flags = IRQF_DISABLED | IRQF_TIMER,
+			.handler = xttcpss_clock_source_interrupt,
+		}
+	},
+	[XTTCPSS_CLOCKEVENT] = {
+		.name = "xttcpss clockevent",
+		.timer_irq = {
+			.flags = IRQF_DISABLED | IRQF_TIMER,
+			.handler = xttcpss_clock_event_interrupt,
+		}
+	},
+};
+
+
+/**
+ * xttcpss_timer_hardware_init - Initialize the timer hardware
+ *
+ * Initialize the hardware, registers the timer interrupts, set the clock source
+ * timer interval and enable the clock source timer
+ **/
+static void __init xttcpss_timer_hardware_init(void)
+{
+	int timer_id;
+	struct xttcpss_timer *timer;
+
+	for (timer_id = 0; timer_id < ARRAY_SIZE(timers); timer_id++) {
+		timer = &timers[timer_id];
+
+		if (!(timer->name))
+			continue;
+
+		timer->base_addr = XTTCPSS_TIMER_BASE + (4*timer_id);
+
+		/* Disable counter, Enable Interval mode, Count up timer,
+		 * Disable Match mode, Internal Clock source select, set
+		 * prescalar to 32, and Enable the Interval interrupt */
+		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				0x23);
+		xttcpss_write(timer->base_addr + XTTCPSS_CLK_CNTRL_OFFSET, 0x9);
+		xttcpss_write(timer->base_addr + XTTCPSS_IER_OFFSET, 0x1);
+
+		/* Setup IRQ */
+		timer->timer_irq.name = timer->name;
+		timer->timer_irq.dev_id = (void *)timer;
+		if (timer->timer_irq.handler != NULL) {
+			setup_irq(xttcpss_timer_irqs[timer_id],
+				&timer->timer_irq);
+		}
+		if (timer_id == XTTCPSS_CLOCKSOURCE)
+			xttcpss_set_interval(timer, ~0);
+	}
+}
+
+/**
+ * xttcpss_read_cycles - Reads the timer counter register
+ *
+ * returns: Current timer counter register value
+ **/
+static cycle_t xttcpss_read_cycles(struct clocksource *cs)
+{
+	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
+
+	return (cycle_t)xttcpss_read(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		= xttcpss_read_cycles,
+	.mask		= CLOCKSOURCE_MASK(16),
+	.shift		= 0,			/* Initialized to zero */
+	.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;
+
+	timer->mode = mode;
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		xttcpss_set_interval(timer, CLOCK_TICK_RATE / HZ);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		ctrl_reg = xttcpss_read(timer->base_addr +
+					XTTCPSS_CNT_CNTRL_OFFSET);
+		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		ctrl_reg = xttcpss_read(timer->base_addr +
+					XTTCPSS_CNT_CNTRL_OFFSET);
+		ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
+		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+		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,
+	.shift		= 0,		/* Initialized to zero */
+	.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 registers the clock source and clock event
+ * timers with Linux kernal timer framework
+ **/
+static void __init xttcpss_timer_init(void)
+{
+	u32 shift;
+	u64 temp;
+
+	xttcpss_timer_hardware_init();
+
+	/* Calculate the nanoseconds to cycles divisor value for clock source
+	 * timer */
+	for (shift = 16; shift > 0; shift--) {
+		temp = (u64) NSEC_PER_SEC << shift;
+		do_div(temp, CLOCK_TICK_RATE);
+		if ((temp >> 32) == 0)
+			break;
+	}
+
+	/* Setup clocksource */
+	clocksource_xttcpss.shift = shift;
+	clocksource_xttcpss.mult =
+		clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_xttcpss.shift);
+
+	if (clocksource_register(&clocksource_xttcpss))
+		printk(KERN_ERR "xttcpss_timer_init: can't register clocksource"
+				" for %s\n", clocksource_xttcpss.name);
+	/* Calculate the nanoseconds to cycles divisor value for clock event
+	 * timer */
+	for (shift = 16; shift > 0; shift--) {
+		temp = (u64) CLOCK_TICK_RATE << shift;
+		do_div(temp, NSEC_PER_SEC);
+		if ((temp >> 32) == 0)
+			break;
+	}
+
+	/* Setup clockevent */
+	xttcpss_clockevent.shift = shift;
+	xttcpss_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
+						 xttcpss_clockevent.shift);
+
+	xttcpss_clockevent.max_delta_ns =
+		clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
+	xttcpss_clockevent.min_delta_ns =
+		clockevent_delta2ns(1, &xttcpss_clockevent);
+
+	xttcpss_clockevent.cpumask = cpumask_of(0);
+	clockevents_register_device(&xttcpss_clockevent);
+}
+
+#ifdef CONFIG_PM
+/**
+ * xttcpss_timer_suspend - Suspend the timer
+ *
+ * Disables all (clock source and clock event) the timers
+ **/
+static void xttcpss_timer_suspend(void)
+{
+	struct xttcpss_timer *source_timer = &timers[XTTCPSS_CLOCKSOURCE];
+	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
+	u32 ctrl_reg;
+
+	/* Disable clocksource timer */
+	ctrl_reg = xttcpss_read(source_timer->base_addr +
+				XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+	xttcpss_write(source_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+
+	/* Disable clockevent timer */
+	ctrl_reg = xttcpss_read(event_timer->base_addr +
+				XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
+	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+}
+
+/**
+ * xttcpss_timer_resume - Resume the timer
+ *
+ * Enables  all (clock source and clock event) the timers
+ **/
+static void xttcpss_timer_resume(void)
+{
+	struct xttcpss_timer *source_timer = &timers[XTTCPSS_CLOCKSOURCE];
+	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
+	u32 ctrl_reg;
+
+	/* Enable clocksource timer */
+	ctrl_reg = xttcpss_read(source_timer->base_addr +
+				XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
+	xttcpss_write(source_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+
+	/* Enable clockevent timer */
+	ctrl_reg = xttcpss_read(event_timer->base_addr +
+				XTTCPSS_CNT_CNTRL_OFFSET);
+	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
+	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
+				ctrl_reg);
+}
+#else
+#define xttcpss_timer_suspend NULL
+#define xttcpss_timer_resume NULL
+#endif
+
+/*
+ * Instantiate and initialize the system timer structure
+ */
+struct sys_timer xttcpss_sys_timer = {
+	.init		= xttcpss_timer_init,
+	.suspend	= xttcpss_timer_suspend,
+	.resume		= xttcpss_timer_resume,
+};
-- 
1.6.2.1



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.

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 4/4] ARM: Xilinx: base header files and assembly macros
       [not found]     ` <1296922637-24662-4-git-send-email-john.linn@xilinx.com>
@ 2011-02-05 16:17         ` John Linn
  0 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 16:17 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel, linux, catalin.marinas, glikely; +Cc: John Linn

These are the minimum needed to build the kernel for the new platform.

Signed-off-by: John Linn <john.linn@xilinx.com>
---
 arch/arm/mach-xilinx/include/mach/clkdev.h      |   33 +++++++++
 arch/arm/mach-xilinx/include/mach/debug-macro.S |   36 +++++++++
 arch/arm/mach-xilinx/include/mach/entry-macro.S |   87 +++++++++++++++++++++++
 arch/arm/mach-xilinx/include/mach/hardware.h    |   44 ++++++++++++
 arch/arm/mach-xilinx/include/mach/io.h          |   27 +++++++
 arch/arm/mach-xilinx/include/mach/irqs.h        |   28 +++++++
 arch/arm/mach-xilinx/include/mach/memory.h      |   23 ++++++
 arch/arm/mach-xilinx/include/mach/system.h      |   28 +++++++
 arch/arm/mach-xilinx/include/mach/timex.h       |   22 ++++++
 arch/arm/mach-xilinx/include/mach/uart.h        |   30 ++++++++
 arch/arm/mach-xilinx/include/mach/uncompress.h  |   46 ++++++++++++
 arch/arm/mach-xilinx/include/mach/vmalloc.h     |   20 +++++
 12 files changed, 424 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-xilinx/include/mach/clkdev.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/debug-macro.S
 create mode 100644 arch/arm/mach-xilinx/include/mach/entry-macro.S
 create mode 100644 arch/arm/mach-xilinx/include/mach/hardware.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/io.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/irqs.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/memory.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/system.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/timex.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/uart.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/uncompress.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/vmalloc.h

diff --git a/arch/arm/mach-xilinx/include/mach/clkdev.h b/arch/arm/mach-xilinx/include/mach/clkdev.h
new file mode 100644
index 0000000..5dd1453
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/clkdev.h
@@ -0,0 +1,33 @@
+/*
+ * arch/arm/mach-xilinx/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__
+
+struct clk {
+	unsigned long rate;
+};
+
+static inline int __clk_get(struct clk *clk)
+{
+	return 1;
+}
+
+static inline void __clk_put(struct clk *clk)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/debug-macro.S b/arch/arm/mach-xilinx/include/mach/debug-macro.S
new file mode 100644
index 0000000..db16b13
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
+/* arch/arm/mach-xilinx/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <mach/hardware.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-xilinx/include/mach/entry-macro.S b/arch/arm/mach-xilinx/include/mach/entry-macro.S
new file mode 100644
index 0000000..becb4cd
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/entry-macro.S
@@ -0,0 +1,87 @@
+/*
+ * arch/arm/mach-xilinx/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 <buytenh@wantstofly.org>
+ *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <mach/hardware.h>
+#include <asm/hardware/gic.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro  get_irqnr_preamble, base, tmp
+		ldr	\base, =gic_cpu_base_addr
+		ldr	\base, [\base]
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
+		/*
+		 * The interrupt numbering scheme is defined in the
+		 * interrupt controller spec.
+		 *
+		 * Interrupts 0-15 are SFI and are filtered
+		 * Interrupts 31-1019 are normal and should be processed
+		 * 1020-1021 are reserved and are filtered
+		 * 1022 is not needed and filtered
+		 * 1023 is "spurious" (no interrupt) and is filtered
+		 *
+		 * A simple read from the controller will tell us the number
+		 * of the highest priority enabled interrupt.  We then just
+		 * need to check whether it is in the valid range for an IRQ
+		 * (16-1019 inclusive). If a valid interrupt, Z = 0 on return.
+		 */
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+		/* bits 12-10 = src CPU, 9-0 = int # */
+
+		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
+		ldr	\tmp, =1020
+
+		bic     \irqnr, \irqstat, #0x1c00
+
+		cmp     \irqnr, #31
+		cmpcc	\irqnr, \irqnr
+		cmpne	\irqnr, \tmp
+		cmpcs	\irqnr, \irqnr
+
+		.endm
+
+		.macro test_for_ipi, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		cmp	\irqnr, #16
+		it	cc
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		it	cs
+		cmpcs	\irqnr, \irqnr
+		.endm
+
+		/* As above, this assumes irqstat and base are preserved */
+
+		.macro test_for_ltirq, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		mov 	\tmp, #0
+		cmp	\irqnr, #29
+		itt	eq
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
+		.endm
diff --git a/arch/arm/mach-xilinx/include/mach/hardware.h b/arch/arm/mach-xilinx/include/mach/hardware.h
new file mode 100644
index 0000000..a635322
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/hardware.h
@@ -0,0 +1,44 @@
+/* arch/arm/mach-xilinx/include/mach/hardware.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#include <mach/memory.h>
+#include <mach/irqs.h>
+
+#define PERIPHERAL_CLOCK_RATE	2500000
+
+#define IO_BASE			0xE0000000
+#define UART0_BASE		(IO_BASE)
+
+#define PERIPH_BASE		0xF8000000
+#define TTC0_BASE		(PERIPH_BASE + 0x1000)
+
+#define SCU_PERIPH_BASE		0xF8F00000
+#define SCU_GIC_CPU_BASE	(SCU_PERIPH_BASE + 0x100)
+#define SCU_GLOBAL_TIMER_BASE	(SCU_PERIPH_BASE + 0x200)
+#define SCU_CPU_TIMER_BASE	(SCU_PERIPH_BASE + 0x600)
+#define SCU_WDT_BASE		(SCU_PERIPH_BASE + 0x620)
+#define SCU_GIC_DIST_BASE	(SCU_PERIPH_BASE + 0x1000)
+
+#define PL310_L2CC_BASE		0xF8F02000
+
+/*
+ * Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
+ */
+#define LL_UART_PADDR	UART0_BASE
+#define LL_UART_VADDR	UART0_BASE
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/io.h b/arch/arm/mach-xilinx/include/mach/io.h
new file mode 100644
index 0000000..2e69db7
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/io.h
@@ -0,0 +1,27 @@
+/* arch/arm/mach-xilinx/include/mach/io.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_IO_H__
+#define __MACH_IO_H__
+
+/* Allow IO space to be anywhere in the memory */
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/* IO address mapping macros, nothing special at this time but required */
+
+#define __io(a)			((void __iomem *)(a))
+#define __mem_pci(a)		(a)
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/irqs.h b/arch/arm/mach-xilinx/include/mach/irqs.h
new file mode 100644
index 0000000..da2fadc
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/irqs.h
@@ -0,0 +1,28 @@
+/* arch/arm/mach-xilinx/include/mach/irqs.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_GPIOS	118
+#define NR_IRQS		(128 + ARCH_NR_GPIOS)
+
+/*
+ * GIC Interrupts
+ */
+
+#define IRQ_GIC_SPI_START	32
+#define IRQ_TIMERCOUNTER0	42
+#define IRQ_UART0		59
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/memory.h b/arch/arm/mach-xilinx/include/mach/memory.h
new file mode 100644
index 0000000..2b6d1eb
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/memory.h
@@ -0,0 +1,23 @@
+/* arch/arm/mach-xilinx/include/mach/memory.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_MEMORY_H__
+#define __MACH_MEMORY_H__
+
+#include <mach/hardware.h>
+
+#define PHYS_OFFSET             0x0
+#define MEM_SIZE		SZ_256M
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/system.h b/arch/arm/mach-xilinx/include/mach/system.h
new file mode 100644
index 0000000..a5f1f0f
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/system.h
@@ -0,0 +1,28 @@
+/* arch/arm/mach-xilinx/include/mach/system.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#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-xilinx/include/mach/timex.h b/arch/arm/mach-xilinx/include/mach/timex.h
new file mode 100644
index 0000000..0c1d292
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/timex.h
@@ -0,0 +1,22 @@
+/* arch/arm/mach-xilinx/include/mach/timex.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+#include <mach/hardware.h>
+
+#define CLOCK_TICK_RATE	(PERIPHERAL_CLOCK_RATE / 32)
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/uart.h b/arch/arm/mach-xilinx/include/mach/uart.h
new file mode 100644
index 0000000..2601143
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/uart.h
@@ -0,0 +1,30 @@
+/* arch/arm/mach-xilinx/include/mach/uart.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#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 */
+
+#define UART_FIFO_WRITE(base, value) \
+	(*(volatile unsigned int *)((base) + UART_FIFO_OFFSET) = (value))
+
+#define UART_STATUS(base) \
+	(*(volatile unsigned int *)((base) + UART_SR_OFFSET))
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/uncompress.h b/arch/arm/mach-xilinx/include/mach/uncompress.h
new file mode 100644
index 0000000..3a4aef7
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/uncompress.h
@@ -0,0 +1,46 @@
+/* arch/arm/mach-xilinx/include/mach/uncompress.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __MACH_UNCOMPRESS_H__
+#define __MACH_UNCOMPRESS_H__
+
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+static inline void flush(void)
+{
+	/*
+	 * Wait while the FIFO is not empty
+	 */
+	while (!(UART_STATUS(LL_UART_PADDR) & UART_SR_TXEMPTY))
+		;
+}
+
+#define arch_decomp_wdog()
+
+static void putc(char ch)
+{
+	/*
+	 * Wait for room in the FIFO, then write the char into the FIFO
+	 */
+	while (UART_STATUS(LL_UART_PADDR) & UART_SR_TXFULL)
+		;
+
+	UART_FIFO_WRITE(LL_UART_PADDR, ch);
+}
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/vmalloc.h b/arch/arm/mach-xilinx/include/mach/vmalloc.h
new file mode 100644
index 0000000..b70ff29
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/* arch/arm/mach-xilinx/include/mach/vmalloc.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_VMALLOC_H__
+#define __MACH_VMALLOC_H__
+
+#define VMALLOC_END       IO_BASE
+
+#endif
-- 
1.6.2.1



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.



^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 4/4] ARM: Xilinx: base header files and assembly macros
@ 2011-02-05 16:17         ` John Linn
  0 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 16:17 UTC (permalink / raw)
  To: linux-arm-kernel

These are the minimum needed to build the kernel for the new platform.

Signed-off-by: John Linn <john.linn@xilinx.com>
---
 arch/arm/mach-xilinx/include/mach/clkdev.h      |   33 +++++++++
 arch/arm/mach-xilinx/include/mach/debug-macro.S |   36 +++++++++
 arch/arm/mach-xilinx/include/mach/entry-macro.S |   87 +++++++++++++++++++++++
 arch/arm/mach-xilinx/include/mach/hardware.h    |   44 ++++++++++++
 arch/arm/mach-xilinx/include/mach/io.h          |   27 +++++++
 arch/arm/mach-xilinx/include/mach/irqs.h        |   28 +++++++
 arch/arm/mach-xilinx/include/mach/memory.h      |   23 ++++++
 arch/arm/mach-xilinx/include/mach/system.h      |   28 +++++++
 arch/arm/mach-xilinx/include/mach/timex.h       |   22 ++++++
 arch/arm/mach-xilinx/include/mach/uart.h        |   30 ++++++++
 arch/arm/mach-xilinx/include/mach/uncompress.h  |   46 ++++++++++++
 arch/arm/mach-xilinx/include/mach/vmalloc.h     |   20 +++++
 12 files changed, 424 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-xilinx/include/mach/clkdev.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/debug-macro.S
 create mode 100644 arch/arm/mach-xilinx/include/mach/entry-macro.S
 create mode 100644 arch/arm/mach-xilinx/include/mach/hardware.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/io.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/irqs.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/memory.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/system.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/timex.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/uart.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/uncompress.h
 create mode 100644 arch/arm/mach-xilinx/include/mach/vmalloc.h

diff --git a/arch/arm/mach-xilinx/include/mach/clkdev.h b/arch/arm/mach-xilinx/include/mach/clkdev.h
new file mode 100644
index 0000000..5dd1453
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/clkdev.h
@@ -0,0 +1,33 @@
+/*
+ * arch/arm/mach-xilinx/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__
+
+struct clk {
+	unsigned long rate;
+};
+
+static inline int __clk_get(struct clk *clk)
+{
+	return 1;
+}
+
+static inline void __clk_put(struct clk *clk)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/debug-macro.S b/arch/arm/mach-xilinx/include/mach/debug-macro.S
new file mode 100644
index 0000000..db16b13
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
+/* arch/arm/mach-xilinx/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <mach/hardware.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-xilinx/include/mach/entry-macro.S b/arch/arm/mach-xilinx/include/mach/entry-macro.S
new file mode 100644
index 0000000..becb4cd
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/entry-macro.S
@@ -0,0 +1,87 @@
+/*
+ * arch/arm/mach-xilinx/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 <buytenh@wantstofly.org>
+ *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <mach/hardware.h>
+#include <asm/hardware/gic.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro  get_irqnr_preamble, base, tmp
+		ldr	\base, =gic_cpu_base_addr
+		ldr	\base, [\base]
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
+		/*
+		 * The interrupt numbering scheme is defined in the
+		 * interrupt controller spec.
+		 *
+		 * Interrupts 0-15 are SFI and are filtered
+		 * Interrupts 31-1019 are normal and should be processed
+		 * 1020-1021 are reserved and are filtered
+		 * 1022 is not needed and filtered
+		 * 1023 is "spurious" (no interrupt) and is filtered
+		 *
+		 * A simple read from the controller will tell us the number
+		 * of the highest priority enabled interrupt.  We then just
+		 * need to check whether it is in the valid range for an IRQ
+		 * (16-1019 inclusive). If a valid interrupt, Z = 0 on return.
+		 */
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+		/* bits 12-10 = src CPU, 9-0 = int # */
+
+		ldr     \irqstat, [\base, #GIC_CPU_INTACK]
+		ldr	\tmp, =1020
+
+		bic     \irqnr, \irqstat, #0x1c00
+
+		cmp     \irqnr, #31
+		cmpcc	\irqnr, \irqnr
+		cmpne	\irqnr, \tmp
+		cmpcs	\irqnr, \irqnr
+
+		.endm
+
+		.macro test_for_ipi, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		cmp	\irqnr, #16
+		it	cc
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		it	cs
+		cmpcs	\irqnr, \irqnr
+		.endm
+
+		/* As above, this assumes irqstat and base are preserved */
+
+		.macro test_for_ltirq, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		mov 	\tmp, #0
+		cmp	\irqnr, #29
+		itt	eq
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
+		.endm
diff --git a/arch/arm/mach-xilinx/include/mach/hardware.h b/arch/arm/mach-xilinx/include/mach/hardware.h
new file mode 100644
index 0000000..a635322
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/hardware.h
@@ -0,0 +1,44 @@
+/* arch/arm/mach-xilinx/include/mach/hardware.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_HARDWARE_H__
+#define __MACH_HARDWARE_H__
+
+#include <mach/memory.h>
+#include <mach/irqs.h>
+
+#define PERIPHERAL_CLOCK_RATE	2500000
+
+#define IO_BASE			0xE0000000
+#define UART0_BASE		(IO_BASE)
+
+#define PERIPH_BASE		0xF8000000
+#define TTC0_BASE		(PERIPH_BASE + 0x1000)
+
+#define SCU_PERIPH_BASE		0xF8F00000
+#define SCU_GIC_CPU_BASE	(SCU_PERIPH_BASE + 0x100)
+#define SCU_GLOBAL_TIMER_BASE	(SCU_PERIPH_BASE + 0x200)
+#define SCU_CPU_TIMER_BASE	(SCU_PERIPH_BASE + 0x600)
+#define SCU_WDT_BASE		(SCU_PERIPH_BASE + 0x620)
+#define SCU_GIC_DIST_BASE	(SCU_PERIPH_BASE + 0x1000)
+
+#define PL310_L2CC_BASE		0xF8F02000
+
+/*
+ * Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
+ */
+#define LL_UART_PADDR	UART0_BASE
+#define LL_UART_VADDR	UART0_BASE
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/io.h b/arch/arm/mach-xilinx/include/mach/io.h
new file mode 100644
index 0000000..2e69db7
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/io.h
@@ -0,0 +1,27 @@
+/* arch/arm/mach-xilinx/include/mach/io.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_IO_H__
+#define __MACH_IO_H__
+
+/* Allow IO space to be anywhere in the memory */
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/* IO address mapping macros, nothing special at this time but required */
+
+#define __io(a)			((void __iomem *)(a))
+#define __mem_pci(a)		(a)
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/irqs.h b/arch/arm/mach-xilinx/include/mach/irqs.h
new file mode 100644
index 0000000..da2fadc
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/irqs.h
@@ -0,0 +1,28 @@
+/* arch/arm/mach-xilinx/include/mach/irqs.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __MACH_IRQS_H
+#define __MACH_IRQS_H
+
+#define ARCH_NR_GPIOS	118
+#define NR_IRQS		(128 + ARCH_NR_GPIOS)
+
+/*
+ * GIC Interrupts
+ */
+
+#define IRQ_GIC_SPI_START	32
+#define IRQ_TIMERCOUNTER0	42
+#define IRQ_UART0		59
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/memory.h b/arch/arm/mach-xilinx/include/mach/memory.h
new file mode 100644
index 0000000..2b6d1eb
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/memory.h
@@ -0,0 +1,23 @@
+/* arch/arm/mach-xilinx/include/mach/memory.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_MEMORY_H__
+#define __MACH_MEMORY_H__
+
+#include <mach/hardware.h>
+
+#define PHYS_OFFSET             0x0
+#define MEM_SIZE		SZ_256M
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/system.h b/arch/arm/mach-xilinx/include/mach/system.h
new file mode 100644
index 0000000..a5f1f0f
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/system.h
@@ -0,0 +1,28 @@
+/* arch/arm/mach-xilinx/include/mach/system.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#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-xilinx/include/mach/timex.h b/arch/arm/mach-xilinx/include/mach/timex.h
new file mode 100644
index 0000000..0c1d292
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/timex.h
@@ -0,0 +1,22 @@
+/* arch/arm/mach-xilinx/include/mach/timex.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_TIMEX_H__
+#define __MACH_TIMEX_H__
+
+#include <mach/hardware.h>
+
+#define CLOCK_TICK_RATE	(PERIPHERAL_CLOCK_RATE / 32)
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/uart.h b/arch/arm/mach-xilinx/include/mach/uart.h
new file mode 100644
index 0000000..2601143
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/uart.h
@@ -0,0 +1,30 @@
+/* arch/arm/mach-xilinx/include/mach/uart.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#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 */
+
+#define UART_FIFO_WRITE(base, value) \
+	(*(volatile unsigned int *)((base) + UART_FIFO_OFFSET) = (value))
+
+#define UART_STATUS(base) \
+	(*(volatile unsigned int *)((base) + UART_SR_OFFSET))
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/uncompress.h b/arch/arm/mach-xilinx/include/mach/uncompress.h
new file mode 100644
index 0000000..3a4aef7
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/uncompress.h
@@ -0,0 +1,46 @@
+/* arch/arm/mach-xilinx/include/mach/uncompress.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __MACH_UNCOMPRESS_H__
+#define __MACH_UNCOMPRESS_H__
+
+#include <mach/hardware.h>
+#include <mach/uart.h>
+
+void arch_decomp_setup(void)
+{
+}
+
+static inline void flush(void)
+{
+	/*
+	 * Wait while the FIFO is not empty
+	 */
+	while (!(UART_STATUS(LL_UART_PADDR) & UART_SR_TXEMPTY))
+		;
+}
+
+#define arch_decomp_wdog()
+
+static void putc(char ch)
+{
+	/*
+	 * Wait for room in the FIFO, then write the char into the FIFO
+	 */
+	while (UART_STATUS(LL_UART_PADDR) & UART_SR_TXFULL)
+		;
+
+	UART_FIFO_WRITE(LL_UART_PADDR, ch);
+}
+
+#endif
diff --git a/arch/arm/mach-xilinx/include/mach/vmalloc.h b/arch/arm/mach-xilinx/include/mach/vmalloc.h
new file mode 100644
index 0000000..b70ff29
--- /dev/null
+++ b/arch/arm/mach-xilinx/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/* arch/arm/mach-xilinx/include/mach/vmalloc.h
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_VMALLOC_H__
+#define __MACH_VMALLOC_H__
+
+#define VMALLOC_END       IO_BASE
+
+#endif
-- 
1.6.2.1



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.

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
  2011-02-05 16:17     ` John Linn
@ 2011-02-06  0:45       ` Jamie Iles
  -1 siblings, 0 replies; 27+ messages in thread
From: Jamie Iles @ 2011-02-06  0:45 UTC (permalink / raw)
  To: John Linn; +Cc: linux-arm-kernel, linux-kernel, linux, catalin.marinas, glikely

Hi John,

A couple of nitpicks inline, otherwise looks nice.

Jamie

On Sat, Feb 05, 2011 at 09:17:15AM -0700, John Linn wrote:
> The 1st board support is minimal to get a system up and running
> on the Xilinx platform.
> 
> Signed-off-by: John Linn <john.linn@xilinx.com>
> ---
>  arch/arm/mach-xilinx/Kconfig       |   14 ++++
>  arch/arm/mach-xilinx/Makefile      |    6 ++
>  arch/arm/mach-xilinx/Makefile.boot |    3 +
>  arch/arm/mach-xilinx/board_ep107.c |   81 ++++++++++++++++++++++
>  arch/arm/mach-xilinx/common.c      |  132 ++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-xilinx/common.h      |   32 +++++++++
>  6 files changed, 268 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-xilinx/Kconfig
>  create mode 100644 arch/arm/mach-xilinx/Makefile
>  create mode 100644 arch/arm/mach-xilinx/Makefile.boot
>  create mode 100644 arch/arm/mach-xilinx/board_ep107.c
>  create mode 100644 arch/arm/mach-xilinx/common.c
>  create mode 100644 arch/arm/mach-xilinx/common.h
> 
> diff --git a/arch/arm/mach-xilinx/Kconfig b/arch/arm/mach-xilinx/Kconfig
> new file mode 100644
> index 0000000..11f9e65
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/Kconfig
> @@ -0,0 +1,14 @@
> +if ARCH_XILINX
> +
> +choice
> +        prompt "Board Selection"
> +	default XILINX_EP107
> +
> +config XILINX_EP107
> +	bool "Xilinx EP107 Board"
> +	help
> +	  Select if you are using a Xilinx EP107 board.
> +
> +endchoice
> +
> +endif
> diff --git a/arch/arm/mach-xilinx/Makefile b/arch/arm/mach-xilinx/Makefile
> new file mode 100644
> index 0000000..194f9e4
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Makefile for the linux kernel.
> +#
> +
> +# Common support
> +obj-y := common.o board_ep107.o timer.o
> diff --git a/arch/arm/mach-xilinx/Makefile.boot b/arch/arm/mach-xilinx/Makefile.boot
> new file mode 100644
> index 0000000..67039c3
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/Makefile.boot
> @@ -0,0 +1,3 @@
> +   zreladdr-y	:= 0x00008000
> +params_phys-y	:= 0x00000100
> +initrd_phys-y	:= 0x00800000
> diff --git a/arch/arm/mach-xilinx/board_ep107.c b/arch/arm/mach-xilinx/board_ep107.c
> new file mode 100644
> index 0000000..233e744
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/board_ep107.c
> @@ -0,0 +1,81 @@
> +/* arch/arm/mach-xilinx/board_ep107.c
> + *
> + * This file contains code specific to the Xilinx EP107 board.
> + *
> + *  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 program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#include <linux/platform_device.h>
> +#include <asm/mach-types.h>
> +#include <asm/mach/arch.h>
> +#include <mach/hardware.h>
> +#include <linux/clkdev.h>
> +#include "common.h"
> +
> +/*
> + * Fixed clocks for now
> + */
> +
> +static struct clk ref50_clk = {
> +	.rate	= 50000000,
> +};
> +
> +/* Create all the platform devices for the board */
> +
> +static struct resource uart0[] = {
> +	{
> +		.start = UART0_BASE,
> +		.end = UART0_BASE + 0xFFF,
> +		.flags = IORESOURCE_MEM,
> +	}, {
> +		.start = IRQ_UART0,
> +		.end = IRQ_UART0,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct platform_device uart_device0 = {
> +	.name = "xuartpss",
> +	.id = 0,
> +	.dev = {
> +		.platform_data = &ref50_clk.rate,
> +	},
> +	.resource = uart0,
> +	.num_resources = ARRAY_SIZE(uart0),
> +};
> +
> +static struct platform_device *xilinx_pdevices[] __initdata = {
> +	&uart_device0,
> +};
> +
> +/**
> + * board_ep107_init - Board specific initialization for the Xilinx EP107 board.
> + *
> + **/
> +static void __init board_ep107_init(void)
> +{
> +	system_init();
> +	platform_device_init(xilinx_pdevices, ARRAY_SIZE(xilinx_pdevices));
> +}
> +
> +MACHINE_START(XILINX_EP107, "Xilinx EP107")
> +	.boot_params    = PHYS_OFFSET + 0x00000100,
> +	.map_io         = map_io,
> +	.init_irq       = irq_init,
> +	.init_machine   = board_ep107_init,
> +	.timer          = &xttcpss_sys_timer,
> +MACHINE_END
> diff --git a/arch/arm/mach-xilinx/common.c b/arch/arm/mach-xilinx/common.c
> new file mode 100644
> index 0000000..f7c51a7
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/common.c
> @@ -0,0 +1,132 @@
> +/* arch/arm/mach-xilinx/common.c
> + *
> + * This file contains common code that is intended to be used across
> + * boards so that it's not replicated.
> + *
> + *  Copyright (C) 2011 Xilinx
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/cpumask.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +
> +#include <asm/mach/map.h>
> +#include <asm/page.h>
> +#include <asm/hardware/gic.h>
> +#include <asm/hardware/cache-l2x0.h>
> +
> +#include <mach/hardware.h>
> +
> +int clk_enable(struct clk *clk)
> +{
> +	return 0;
> +}
> +
> +void clk_disable(struct clk *clk)
> +{
> +}

According to include/linux/clk.h you should also implement 
clk_get_rate() here too.

> +
> +/**
> + * system_init - System specific initialization, intended to be called from
> + *			board specific initialization.
> + *
> + **/
> +void __init system_init(void)
> +{
> +#ifdef CONFIG_CACHE_L2X0
> +	void *l2cache_base = (void *)PL310_L2CC_BASE;
> +
> +	/*
> +	 * 64KB way size, 8-way associativity, parity disabled
> +	 */
> +	l2x0_init(l2cache_base, 0x02060000, 0xF0F0FFFF);
> +#endif
> +}
> +
> +/**
> + * irq_init - Interrupt controller initialization for the GIC.
> + *
> + **/
> +void __init irq_init(void)
> +{
> +	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
> +	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE, gic_cpu_base_addr);
> +}
> +
> +/* 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_BASE,
> +		.pfn		= __phys_to_pfn(TTC0_BASE),
> +		.length		= SZ_4K,
> +		.type		= MT_DEVICE,
> +	}, {
> +		.virtual	= SCU_PERIPH_BASE,
> +		.pfn		= __phys_to_pfn(SCU_PERIPH_BASE),
> +		.length		= SZ_8K,
> +		.type		= MT_DEVICE,
> +	}, {
> +		.virtual	= PL310_L2CC_BASE,
> +		.pfn		= __phys_to_pfn(PL310_L2CC_BASE),
> +		.length		= SZ_4K,
> +		.type		= MT_DEVICE,
> +	},
> +
> +#ifdef CONFIG_DEBUG_LL
> +	{
> +		.virtual	= UART0_BASE,
> +		.pfn		= __phys_to_pfn(UART0_BASE),
> +		.length		= SZ_4K,
> +		.type		= MT_DEVICE,
> +	},
> +#endif
> +
> +};
> +
> +/**
> + * map_io - Create memory mappings needed for early I/O.
> + *
> + **/
> +void __init map_io(void)
> +{
> +	iotable_init(io_desc, ARRAY_SIZE(io_desc));
> +}
> +
> +/**
> + * platform_device_init - Initialize all the platform devices.
> + *
> + **/
> +void __init platform_device_init(struct platform_device *xilinx_pdevices[],
> +					int count)
> +{
> +	int ret, i;
> +
> +	/* Initialize all the platform devices */
> +
> +	for (i = 0; i < count; i++) {
> +
> +		pr_info("registering platform device '%s' id %d\n",
> +			xilinx_pdevices[i]->name,
> +			xilinx_pdevices[i]->id);
> +
> +		ret = platform_device_register(xilinx_pdevices[i]);
> +		if (ret)
> +			pr_info("Unable to register platform device '%s': %d\n",
> +				xilinx_pdevices[i]->name, ret);
> +	}
> +}

Would platform_add_devices() do here?  It does the same thing minus the 
pr_info() and will cleanup if any of the registration fails.

> +
> diff --git a/arch/arm/mach-xilinx/common.h b/arch/arm/mach-xilinx/common.h
> new file mode 100644
> index 0000000..49de295
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/common.h
> @@ -0,0 +1,32 @@
> +/* arch/arm/mach-xilinx/common.h
> + *
> + * This file contains common function prototypes to avoid externs
> + * in the c files.
> + *
> + *  Copyright (C) 2011 Xilinx
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#ifndef __MACH_XILINX_COMMON_H__
> +#define __MACH_XILINX_COMMON_H__
> +
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +
> +void __init system_init(void);
> +void __init irq_init(void);
> +void __init map_io(void);
> +void __init platform_device_init(struct platform_device *pdevices[],
> +					int count);
> +
> +extern struct sys_timer xttcpss_sys_timer;
> +
> +#endif
> -- 
> 1.6.2.1
> 
> 
> 
> 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.
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
@ 2011-02-06  0:45       ` Jamie Iles
  0 siblings, 0 replies; 27+ messages in thread
From: Jamie Iles @ 2011-02-06  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi John,

A couple of nitpicks inline, otherwise looks nice.

Jamie

On Sat, Feb 05, 2011 at 09:17:15AM -0700, John Linn wrote:
> The 1st board support is minimal to get a system up and running
> on the Xilinx platform.
> 
> Signed-off-by: John Linn <john.linn@xilinx.com>
> ---
>  arch/arm/mach-xilinx/Kconfig       |   14 ++++
>  arch/arm/mach-xilinx/Makefile      |    6 ++
>  arch/arm/mach-xilinx/Makefile.boot |    3 +
>  arch/arm/mach-xilinx/board_ep107.c |   81 ++++++++++++++++++++++
>  arch/arm/mach-xilinx/common.c      |  132 ++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-xilinx/common.h      |   32 +++++++++
>  6 files changed, 268 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-xilinx/Kconfig
>  create mode 100644 arch/arm/mach-xilinx/Makefile
>  create mode 100644 arch/arm/mach-xilinx/Makefile.boot
>  create mode 100644 arch/arm/mach-xilinx/board_ep107.c
>  create mode 100644 arch/arm/mach-xilinx/common.c
>  create mode 100644 arch/arm/mach-xilinx/common.h
> 
> diff --git a/arch/arm/mach-xilinx/Kconfig b/arch/arm/mach-xilinx/Kconfig
> new file mode 100644
> index 0000000..11f9e65
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/Kconfig
> @@ -0,0 +1,14 @@
> +if ARCH_XILINX
> +
> +choice
> +        prompt "Board Selection"
> +	default XILINX_EP107
> +
> +config XILINX_EP107
> +	bool "Xilinx EP107 Board"
> +	help
> +	  Select if you are using a Xilinx EP107 board.
> +
> +endchoice
> +
> +endif
> diff --git a/arch/arm/mach-xilinx/Makefile b/arch/arm/mach-xilinx/Makefile
> new file mode 100644
> index 0000000..194f9e4
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Makefile for the linux kernel.
> +#
> +
> +# Common support
> +obj-y := common.o board_ep107.o timer.o
> diff --git a/arch/arm/mach-xilinx/Makefile.boot b/arch/arm/mach-xilinx/Makefile.boot
> new file mode 100644
> index 0000000..67039c3
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/Makefile.boot
> @@ -0,0 +1,3 @@
> +   zreladdr-y	:= 0x00008000
> +params_phys-y	:= 0x00000100
> +initrd_phys-y	:= 0x00800000
> diff --git a/arch/arm/mach-xilinx/board_ep107.c b/arch/arm/mach-xilinx/board_ep107.c
> new file mode 100644
> index 0000000..233e744
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/board_ep107.c
> @@ -0,0 +1,81 @@
> +/* arch/arm/mach-xilinx/board_ep107.c
> + *
> + * This file contains code specific to the Xilinx EP107 board.
> + *
> + *  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 program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#include <linux/platform_device.h>
> +#include <asm/mach-types.h>
> +#include <asm/mach/arch.h>
> +#include <mach/hardware.h>
> +#include <linux/clkdev.h>
> +#include "common.h"
> +
> +/*
> + * Fixed clocks for now
> + */
> +
> +static struct clk ref50_clk = {
> +	.rate	= 50000000,
> +};
> +
> +/* Create all the platform devices for the board */
> +
> +static struct resource uart0[] = {
> +	{
> +		.start = UART0_BASE,
> +		.end = UART0_BASE + 0xFFF,
> +		.flags = IORESOURCE_MEM,
> +	}, {
> +		.start = IRQ_UART0,
> +		.end = IRQ_UART0,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct platform_device uart_device0 = {
> +	.name = "xuartpss",
> +	.id = 0,
> +	.dev = {
> +		.platform_data = &ref50_clk.rate,
> +	},
> +	.resource = uart0,
> +	.num_resources = ARRAY_SIZE(uart0),
> +};
> +
> +static struct platform_device *xilinx_pdevices[] __initdata = {
> +	&uart_device0,
> +};
> +
> +/**
> + * board_ep107_init - Board specific initialization for the Xilinx EP107 board.
> + *
> + **/
> +static void __init board_ep107_init(void)
> +{
> +	system_init();
> +	platform_device_init(xilinx_pdevices, ARRAY_SIZE(xilinx_pdevices));
> +}
> +
> +MACHINE_START(XILINX_EP107, "Xilinx EP107")
> +	.boot_params    = PHYS_OFFSET + 0x00000100,
> +	.map_io         = map_io,
> +	.init_irq       = irq_init,
> +	.init_machine   = board_ep107_init,
> +	.timer          = &xttcpss_sys_timer,
> +MACHINE_END
> diff --git a/arch/arm/mach-xilinx/common.c b/arch/arm/mach-xilinx/common.c
> new file mode 100644
> index 0000000..f7c51a7
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/common.c
> @@ -0,0 +1,132 @@
> +/* arch/arm/mach-xilinx/common.c
> + *
> + * This file contains common code that is intended to be used across
> + * boards so that it's not replicated.
> + *
> + *  Copyright (C) 2011 Xilinx
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/cpumask.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +
> +#include <asm/mach/map.h>
> +#include <asm/page.h>
> +#include <asm/hardware/gic.h>
> +#include <asm/hardware/cache-l2x0.h>
> +
> +#include <mach/hardware.h>
> +
> +int clk_enable(struct clk *clk)
> +{
> +	return 0;
> +}
> +
> +void clk_disable(struct clk *clk)
> +{
> +}

According to include/linux/clk.h you should also implement 
clk_get_rate() here too.

> +
> +/**
> + * system_init - System specific initialization, intended to be called from
> + *			board specific initialization.
> + *
> + **/
> +void __init system_init(void)
> +{
> +#ifdef CONFIG_CACHE_L2X0
> +	void *l2cache_base = (void *)PL310_L2CC_BASE;
> +
> +	/*
> +	 * 64KB way size, 8-way associativity, parity disabled
> +	 */
> +	l2x0_init(l2cache_base, 0x02060000, 0xF0F0FFFF);
> +#endif
> +}
> +
> +/**
> + * irq_init - Interrupt controller initialization for the GIC.
> + *
> + **/
> +void __init irq_init(void)
> +{
> +	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
> +	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE, gic_cpu_base_addr);
> +}
> +
> +/* 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_BASE,
> +		.pfn		= __phys_to_pfn(TTC0_BASE),
> +		.length		= SZ_4K,
> +		.type		= MT_DEVICE,
> +	}, {
> +		.virtual	= SCU_PERIPH_BASE,
> +		.pfn		= __phys_to_pfn(SCU_PERIPH_BASE),
> +		.length		= SZ_8K,
> +		.type		= MT_DEVICE,
> +	}, {
> +		.virtual	= PL310_L2CC_BASE,
> +		.pfn		= __phys_to_pfn(PL310_L2CC_BASE),
> +		.length		= SZ_4K,
> +		.type		= MT_DEVICE,
> +	},
> +
> +#ifdef CONFIG_DEBUG_LL
> +	{
> +		.virtual	= UART0_BASE,
> +		.pfn		= __phys_to_pfn(UART0_BASE),
> +		.length		= SZ_4K,
> +		.type		= MT_DEVICE,
> +	},
> +#endif
> +
> +};
> +
> +/**
> + * map_io - Create memory mappings needed for early I/O.
> + *
> + **/
> +void __init map_io(void)
> +{
> +	iotable_init(io_desc, ARRAY_SIZE(io_desc));
> +}
> +
> +/**
> + * platform_device_init - Initialize all the platform devices.
> + *
> + **/
> +void __init platform_device_init(struct platform_device *xilinx_pdevices[],
> +					int count)
> +{
> +	int ret, i;
> +
> +	/* Initialize all the platform devices */
> +
> +	for (i = 0; i < count; i++) {
> +
> +		pr_info("registering platform device '%s' id %d\n",
> +			xilinx_pdevices[i]->name,
> +			xilinx_pdevices[i]->id);
> +
> +		ret = platform_device_register(xilinx_pdevices[i]);
> +		if (ret)
> +			pr_info("Unable to register platform device '%s': %d\n",
> +				xilinx_pdevices[i]->name, ret);
> +	}
> +}

Would platform_add_devices() do here?  It does the same thing minus the 
pr_info() and will cleanup if any of the registration fails.

> +
> diff --git a/arch/arm/mach-xilinx/common.h b/arch/arm/mach-xilinx/common.h
> new file mode 100644
> index 0000000..49de295
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/common.h
> @@ -0,0 +1,32 @@
> +/* arch/arm/mach-xilinx/common.h
> + *
> + * This file contains common function prototypes to avoid externs
> + * in the c files.
> + *
> + *  Copyright (C) 2011 Xilinx
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#ifndef __MACH_XILINX_COMMON_H__
> +#define __MACH_XILINX_COMMON_H__
> +
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +
> +void __init system_init(void);
> +void __init irq_init(void);
> +void __init map_io(void);
> +void __init platform_device_init(struct platform_device *pdevices[],
> +					int count);
> +
> +extern struct sys_timer xttcpss_sys_timer;
> +
> +#endif
> -- 
> 1.6.2.1
> 
> 
> 
> 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.
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
  2011-02-05 16:17       ` John Linn
@ 2011-02-06  1:03         ` Jamie Iles
  -1 siblings, 0 replies; 27+ messages in thread
From: Jamie Iles @ 2011-02-06  1:03 UTC (permalink / raw)
  To: John Linn
  Cc: linux-arm-kernel, linux-kernel, linux, catalin.marinas, glikely,
	Kiran Sutariya

Hi John,

A couple more nitpicks.

Jamie

On Sat, Feb 05, 2011 at 09:17:16AM -0700, John Linn wrote:
> The timer driver supports the Xilinx PS Timer Counter IP.
> 
> Signed-off-by: Kiran Sutariya <kiran.sutariya@einfochips.com>
> Signed-off-by: John Linn <john.linn@xilinx.com>
> ---
>  arch/arm/mach-xilinx/timer.c |  452 ++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 452 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-xilinx/timer.c
> 
> diff --git a/arch/arm/mach-xilinx/timer.c b/arch/arm/mach-xilinx/timer.c
> new file mode 100644
> index 0000000..c713e3c
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/timer.c
> @@ -0,0 +1,452 @@
> +/* arch/arm/mach-xilinx/timer.c
> + *
> + * 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 program is free software; you can redistribute it and/or modify it under
> + * the terms of the GNU General Public License version 2 as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
> + * Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#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/hardware.h>
> +
> +/*
> + * 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 is 200MHz which is common to all the
> + * timer channel (T1, T2, and T3)
> + * Clocksource timer resolution is 160ns
> + * Clockevent timer resolution is 160ns
> + */
> +#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
> +
> +/*
> + * 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 */
> +
> +/*
> + * Bit mask to enable/disable the timer
> + */
> +#define XTTCPSS_CNT_CNTRL_ENABLE_MASK	0xFFFFFFFE

I found this really confusing reading through the code, but that's 
probably just me!  Perhaps if this was called 
XTTCPSS_CNT_CNTRL_DISABLE_MASK and defined to 1 then that might be a 
little easier to follow.

> +
> +/*
> + * Definitions of the timer read/write macro
> + */
> +#define xttcpss_read(addr)	__raw_readl((void __iomem *)addr)
> +#define xttcpss_write(addr, val) __raw_writel(val, (void __iomem *)(addr))
> +
> +
> +/**
> + * struct xttcpss_timer - This definition defines local timer structure
> + *
> + * @name:	Name of Timer
> + * @base_addr:	Base address of timer
> + * @timer_irq:	irqaction structure for the timer device
> + * @mode:       only valid for an clock event, periodic or one-shot
> + **/
> +struct xttcpss_timer {
> +	char *name;
> +	unsigned long base_addr;

Shouldn't this really be a void __iomem pointer?  This could eliminate 
the need for xttcpss_write and xttcpss_read.

> +	struct irqaction timer_irq;
> +	enum clock_event_mode mode;
> +};
> +
> +
> +static struct xttcpss_timer timers[];
> +static struct clock_event_device xttcpss_clockevent;
> +
> +/*
> + * xttcpss_timer_irqs - Timers IRQ number
> + */
> +static int xttcpss_timer_irqs[2] = {
> +	IRQ_TIMERCOUNTER0,	/* Timer 1 IRQ number */
> +	IRQ_TIMERCOUNTER0 + 1,	/* Timer 2 IRQ number */
> +};
> +
> +/**
> + * 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 = xttcpss_read(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> +	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET, 
> ctrl_reg);
> +
> +	pr_debug("set_interval, name = %s, period = %08X\n",
> +			timer->name, (unsigned int)cycles);
> +
> +	xttcpss_write(timer->base_addr + XTTCPSS_INTR_VAL_OFFSET, cycles);
> +
> +	/* Reset the counter (0x10) so that it starts from 0, one-shot
> +	   mode makes this needed for timing to be right. */
> +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> +	ctrl_reg |= 0x10;
> +	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET, 
> ctrl_reg);
> +}
> +
> +/**
> + * xttcpss_clock_source_interrupt - Clock source timer interrupt handler
> + *
> + * @irq:	IRQ number of the Timer
> + * @dev_id:	void pointer to the xttcpss_timer instance
> + *
> + * This will be called when 16-bit clock source counter wraps
> + *
> + * returns: Always IRQ_HANDLED - success
> + **/
> +static irqreturn_t xttcpss_clock_source_interrupt(int irq, void *dev_id)
> +{
> +	struct xttcpss_timer *timer = dev_id;
> +
> +	/* Acknowledge the interrupt */
> +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * 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;
> +	u32 ctrl_reg;
> +
> +	/* Acknowledge the interrupt and call event handler */
> +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> +
> +	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
> +
> +		/* Disable the counter as it would keep running. */
> +		ctrl_reg = xttcpss_read(timer->base_addr +
> +					XTTCPSS_CNT_CNTRL_OFFSET);
> +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);

The clock events framework should reprogram the next event so you don't 
actually need to disable the timer here.  Once the event handler has 
been called the timer will be reenabled with a new period, and as we're 
running with interrupts disabled here we don't need to stop the timer.

> +		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +	}
> +
> +	evt->event_handler(evt);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/*
> + * struct xttcpss_timer timers - This definition defines local timers
> + */
> +static struct xttcpss_timer timers[] = {
> +	[XTTCPSS_CLOCKSOURCE] = {
> +		.name = "xttcpss clocksource",
> +		.timer_irq = {
> +			.flags = IRQF_DISABLED | IRQF_TIMER,
> +			.handler = xttcpss_clock_source_interrupt,
> +		}
> +	},
> +	[XTTCPSS_CLOCKEVENT] = {
> +		.name = "xttcpss clockevent",
> +		.timer_irq = {
> +			.flags = IRQF_DISABLED | IRQF_TIMER,
> +			.handler = xttcpss_clock_event_interrupt,
> +		}
> +	},
> +};
> +
> +
> +/**
> + * xttcpss_timer_hardware_init - Initialize the timer hardware
> + *
> + * Initialize the hardware, registers the timer interrupts, set the clock source
> + * timer interval and enable the clock source timer
> + **/
> +static void __init xttcpss_timer_hardware_init(void)
> +{
> +	int timer_id;
> +	struct xttcpss_timer *timer;
> +
> +	for (timer_id = 0; timer_id < ARRAY_SIZE(timers); timer_id++) {
> +		timer = &timers[timer_id];
> +
> +		if (!(timer->name))
> +			continue;
> +
> +		timer->base_addr = XTTCPSS_TIMER_BASE + (4*timer_id);
> +
> +		/* Disable counter, Enable Interval mode, Count up timer,
> +		 * Disable Match mode, Internal Clock source select, set
> +		 * prescalar to 32, and Enable the Interval interrupt */
> +		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				0x23);
> +		xttcpss_write(timer->base_addr + XTTCPSS_CLK_CNTRL_OFFSET, 0x9);
> +		xttcpss_write(timer->base_addr + XTTCPSS_IER_OFFSET, 0x1);
> +
> +		/* Setup IRQ */
> +		timer->timer_irq.name = timer->name;
> +		timer->timer_irq.dev_id = (void *)timer;
> +		if (timer->timer_irq.handler != NULL) {
> +			setup_irq(xttcpss_timer_irqs[timer_id],
> +				&timer->timer_irq);
> +		}
> +		if (timer_id == XTTCPSS_CLOCKSOURCE)
> +			xttcpss_set_interval(timer, ~0);
> +	}
> +}
> +
> +/**
> + * xttcpss_read_cycles - Reads the timer counter register
> + *
> + * returns: Current timer counter register value
> + **/
> +static cycle_t xttcpss_read_cycles(struct clocksource *cs)
> +{
> +	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
> +
> +	return (cycle_t)xttcpss_read(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		= xttcpss_read_cycles,
> +	.mask		= CLOCKSOURCE_MASK(16),
> +	.shift		= 0,			/* Initialized to zero */
> +	.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;
> +
> +	timer->mode = mode;
> +
> +	switch (mode) {
> +	case CLOCK_EVT_MODE_PERIODIC:
> +		xttcpss_set_interval(timer, CLOCK_TICK_RATE / HZ);
> +		break;
> +	case CLOCK_EVT_MODE_ONESHOT:
> +	case CLOCK_EVT_MODE_UNUSED:
> +	case CLOCK_EVT_MODE_SHUTDOWN:
> +		ctrl_reg = xttcpss_read(timer->base_addr +
> +					XTTCPSS_CNT_CNTRL_OFFSET);
> +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> +		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +		break;
> +	case CLOCK_EVT_MODE_RESUME:
> +		ctrl_reg = xttcpss_read(timer->base_addr +
> +					XTTCPSS_CNT_CNTRL_OFFSET);
> +		ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> +		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +		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,
> +	.shift		= 0,		/* Initialized to zero */
> +	.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 registers the clock source and clock event
> + * timers with Linux kernal timer framework
> + **/
> +static void __init xttcpss_timer_init(void)
> +{
> +	u32 shift;
> +	u64 temp;
> +
> +	xttcpss_timer_hardware_init();
> +
> +	/* Calculate the nanoseconds to cycles divisor value for clock source
> +	 * timer */
> +	for (shift = 16; shift > 0; shift--) {
> +		temp = (u64) NSEC_PER_SEC << shift;
> +		do_div(temp, CLOCK_TICK_RATE);
> +		if ((temp >> 32) == 0)
> +			break;
> +	}
> +
> +	/* Setup clocksource */
> +	clocksource_xttcpss.shift = shift;
> +	clocksource_xttcpss.mult =
> +		clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_xttcpss.shift);
> +
> +	if (clocksource_register(&clocksource_xttcpss))
> +		printk(KERN_ERR "xttcpss_timer_init: can't register clocksource"
> +				" for %s\n", clocksource_xttcpss.name);

If you use clocksource_register_hz() then you don't need to worry about 
calculating shift and mult, the generic framework will do that for you.

> +	/* Calculate the nanoseconds to cycles divisor value for clock event
> +	 * timer */
> +	for (shift = 16; shift > 0; shift--) {
> +		temp = (u64) CLOCK_TICK_RATE << shift;
> +		do_div(temp, NSEC_PER_SEC);
> +		if ((temp >> 32) == 0)
> +			break;
> +	}
> +
> +	/* Setup clockevent */
> +	xttcpss_clockevent.shift = shift;
> +	xttcpss_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
> +						 xttcpss_clockevent.shift);

clockevents_calc_mult_shift()?

> +
> +	xttcpss_clockevent.max_delta_ns =
> +		clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
> +	xttcpss_clockevent.min_delta_ns =
> +		clockevent_delta2ns(1, &xttcpss_clockevent);
> +
> +	xttcpss_clockevent.cpumask = cpumask_of(0);
> +	clockevents_register_device(&xttcpss_clockevent);
> +}
> +
> +#ifdef CONFIG_PM
> +/**
> + * xttcpss_timer_suspend - Suspend the timer
> + *
> + * Disables all (clock source and clock event) the timers
> + **/
> +static void xttcpss_timer_suspend(void)
> +{
> +	struct xttcpss_timer *source_timer = &timers[XTTCPSS_CLOCKSOURCE];
> +	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
> +	u32 ctrl_reg;
> +
> +	/* Disable clocksource timer */
> +	ctrl_reg = xttcpss_read(source_timer->base_addr +
> +				XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> +	xttcpss_write(source_timer->base_addr + 
> XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +
> +	/* Disable clockevent timer */
> +	ctrl_reg = xttcpss_read(event_timer->base_addr +
> +				XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> +	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +}
> +
> +/**
> + * xttcpss_timer_resume - Resume the timer
> + *
> + * Enables  all (clock source and clock event) the timers
> + **/
> +static void xttcpss_timer_resume(void)
> +{
> +	struct xttcpss_timer *source_timer = &timers[XTTCPSS_CLOCKSOURCE];
> +	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
> +	u32 ctrl_reg;
> +
> +	/* Enable clocksource timer */
> +	ctrl_reg = xttcpss_read(source_timer->base_addr +
> +				XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> +	xttcpss_write(source_timer->base_addr + 
> XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +
> +	/* Enable clockevent timer */
> +	ctrl_reg = xttcpss_read(event_timer->base_addr +
> +				XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> +	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +}
> +#else
> +#define xttcpss_timer_suspend NULL
> +#define xttcpss_timer_resume NULL
> +#endif
> +
> +/*
> + * Instantiate and initialize the system timer structure
> + */
> +struct sys_timer xttcpss_sys_timer = {
> +	.init		= xttcpss_timer_init,
> +	.suspend	= xttcpss_timer_suspend,
> +	.resume		= xttcpss_timer_resume,
> +};
> -- 
> 1.6.2.1
> 
> 
> 
> 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.
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
@ 2011-02-06  1:03         ` Jamie Iles
  0 siblings, 0 replies; 27+ messages in thread
From: Jamie Iles @ 2011-02-06  1:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hi John,

A couple more nitpicks.

Jamie

On Sat, Feb 05, 2011 at 09:17:16AM -0700, John Linn wrote:
> The timer driver supports the Xilinx PS Timer Counter IP.
> 
> Signed-off-by: Kiran Sutariya <kiran.sutariya@einfochips.com>
> Signed-off-by: John Linn <john.linn@xilinx.com>
> ---
>  arch/arm/mach-xilinx/timer.c |  452 ++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 452 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-xilinx/timer.c
> 
> diff --git a/arch/arm/mach-xilinx/timer.c b/arch/arm/mach-xilinx/timer.c
> new file mode 100644
> index 0000000..c713e3c
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/timer.c
> @@ -0,0 +1,452 @@
> +/* arch/arm/mach-xilinx/timer.c
> + *
> + * 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 program is free software; you can redistribute it and/or modify it under
> + * the terms of the GNU General Public License version 2 as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
> + * Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#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/hardware.h>
> +
> +/*
> + * 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 is 200MHz which is common to all the
> + * timer channel (T1, T2, and T3)
> + * Clocksource timer resolution is 160ns
> + * Clockevent timer resolution is 160ns
> + */
> +#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
> +
> +/*
> + * 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 */
> +
> +/*
> + * Bit mask to enable/disable the timer
> + */
> +#define XTTCPSS_CNT_CNTRL_ENABLE_MASK	0xFFFFFFFE

I found this really confusing reading through the code, but that's 
probably just me!  Perhaps if this was called 
XTTCPSS_CNT_CNTRL_DISABLE_MASK and defined to 1 then that might be a 
little easier to follow.

> +
> +/*
> + * Definitions of the timer read/write macro
> + */
> +#define xttcpss_read(addr)	__raw_readl((void __iomem *)addr)
> +#define xttcpss_write(addr, val) __raw_writel(val, (void __iomem *)(addr))
> +
> +
> +/**
> + * struct xttcpss_timer - This definition defines local timer structure
> + *
> + * @name:	Name of Timer
> + * @base_addr:	Base address of timer
> + * @timer_irq:	irqaction structure for the timer device
> + * @mode:       only valid for an clock event, periodic or one-shot
> + **/
> +struct xttcpss_timer {
> +	char *name;
> +	unsigned long base_addr;

Shouldn't this really be a void __iomem pointer?  This could eliminate 
the need for xttcpss_write and xttcpss_read.

> +	struct irqaction timer_irq;
> +	enum clock_event_mode mode;
> +};
> +
> +
> +static struct xttcpss_timer timers[];
> +static struct clock_event_device xttcpss_clockevent;
> +
> +/*
> + * xttcpss_timer_irqs - Timers IRQ number
> + */
> +static int xttcpss_timer_irqs[2] = {
> +	IRQ_TIMERCOUNTER0,	/* Timer 1 IRQ number */
> +	IRQ_TIMERCOUNTER0 + 1,	/* Timer 2 IRQ number */
> +};
> +
> +/**
> + * 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 = xttcpss_read(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> +	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET, 
> ctrl_reg);
> +
> +	pr_debug("set_interval, name = %s, period = %08X\n",
> +			timer->name, (unsigned int)cycles);
> +
> +	xttcpss_write(timer->base_addr + XTTCPSS_INTR_VAL_OFFSET, cycles);
> +
> +	/* Reset the counter (0x10) so that it starts from 0, one-shot
> +	   mode makes this needed for timing to be right. */
> +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> +	ctrl_reg |= 0x10;
> +	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET, 
> ctrl_reg);
> +}
> +
> +/**
> + * xttcpss_clock_source_interrupt - Clock source timer interrupt handler
> + *
> + * @irq:	IRQ number of the Timer
> + * @dev_id:	void pointer to the xttcpss_timer instance
> + *
> + * This will be called when 16-bit clock source counter wraps
> + *
> + * returns: Always IRQ_HANDLED - success
> + **/
> +static irqreturn_t xttcpss_clock_source_interrupt(int irq, void *dev_id)
> +{
> +	struct xttcpss_timer *timer = dev_id;
> +
> +	/* Acknowledge the interrupt */
> +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * 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;
> +	u32 ctrl_reg;
> +
> +	/* Acknowledge the interrupt and call event handler */
> +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> +
> +	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
> +
> +		/* Disable the counter as it would keep running. */
> +		ctrl_reg = xttcpss_read(timer->base_addr +
> +					XTTCPSS_CNT_CNTRL_OFFSET);
> +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);

The clock events framework should reprogram the next event so you don't 
actually need to disable the timer here.  Once the event handler has 
been called the timer will be reenabled with a new period, and as we're 
running with interrupts disabled here we don't need to stop the timer.

> +		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +	}
> +
> +	evt->event_handler(evt);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/*
> + * struct xttcpss_timer timers - This definition defines local timers
> + */
> +static struct xttcpss_timer timers[] = {
> +	[XTTCPSS_CLOCKSOURCE] = {
> +		.name = "xttcpss clocksource",
> +		.timer_irq = {
> +			.flags = IRQF_DISABLED | IRQF_TIMER,
> +			.handler = xttcpss_clock_source_interrupt,
> +		}
> +	},
> +	[XTTCPSS_CLOCKEVENT] = {
> +		.name = "xttcpss clockevent",
> +		.timer_irq = {
> +			.flags = IRQF_DISABLED | IRQF_TIMER,
> +			.handler = xttcpss_clock_event_interrupt,
> +		}
> +	},
> +};
> +
> +
> +/**
> + * xttcpss_timer_hardware_init - Initialize the timer hardware
> + *
> + * Initialize the hardware, registers the timer interrupts, set the clock source
> + * timer interval and enable the clock source timer
> + **/
> +static void __init xttcpss_timer_hardware_init(void)
> +{
> +	int timer_id;
> +	struct xttcpss_timer *timer;
> +
> +	for (timer_id = 0; timer_id < ARRAY_SIZE(timers); timer_id++) {
> +		timer = &timers[timer_id];
> +
> +		if (!(timer->name))
> +			continue;
> +
> +		timer->base_addr = XTTCPSS_TIMER_BASE + (4*timer_id);
> +
> +		/* Disable counter, Enable Interval mode, Count up timer,
> +		 * Disable Match mode, Internal Clock source select, set
> +		 * prescalar to 32, and Enable the Interval interrupt */
> +		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				0x23);
> +		xttcpss_write(timer->base_addr + XTTCPSS_CLK_CNTRL_OFFSET, 0x9);
> +		xttcpss_write(timer->base_addr + XTTCPSS_IER_OFFSET, 0x1);
> +
> +		/* Setup IRQ */
> +		timer->timer_irq.name = timer->name;
> +		timer->timer_irq.dev_id = (void *)timer;
> +		if (timer->timer_irq.handler != NULL) {
> +			setup_irq(xttcpss_timer_irqs[timer_id],
> +				&timer->timer_irq);
> +		}
> +		if (timer_id == XTTCPSS_CLOCKSOURCE)
> +			xttcpss_set_interval(timer, ~0);
> +	}
> +}
> +
> +/**
> + * xttcpss_read_cycles - Reads the timer counter register
> + *
> + * returns: Current timer counter register value
> + **/
> +static cycle_t xttcpss_read_cycles(struct clocksource *cs)
> +{
> +	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
> +
> +	return (cycle_t)xttcpss_read(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		= xttcpss_read_cycles,
> +	.mask		= CLOCKSOURCE_MASK(16),
> +	.shift		= 0,			/* Initialized to zero */
> +	.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;
> +
> +	timer->mode = mode;
> +
> +	switch (mode) {
> +	case CLOCK_EVT_MODE_PERIODIC:
> +		xttcpss_set_interval(timer, CLOCK_TICK_RATE / HZ);
> +		break;
> +	case CLOCK_EVT_MODE_ONESHOT:
> +	case CLOCK_EVT_MODE_UNUSED:
> +	case CLOCK_EVT_MODE_SHUTDOWN:
> +		ctrl_reg = xttcpss_read(timer->base_addr +
> +					XTTCPSS_CNT_CNTRL_OFFSET);
> +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> +		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +		break;
> +	case CLOCK_EVT_MODE_RESUME:
> +		ctrl_reg = xttcpss_read(timer->base_addr +
> +					XTTCPSS_CNT_CNTRL_OFFSET);
> +		ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> +		xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +		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,
> +	.shift		= 0,		/* Initialized to zero */
> +	.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 registers the clock source and clock event
> + * timers with Linux kernal timer framework
> + **/
> +static void __init xttcpss_timer_init(void)
> +{
> +	u32 shift;
> +	u64 temp;
> +
> +	xttcpss_timer_hardware_init();
> +
> +	/* Calculate the nanoseconds to cycles divisor value for clock source
> +	 * timer */
> +	for (shift = 16; shift > 0; shift--) {
> +		temp = (u64) NSEC_PER_SEC << shift;
> +		do_div(temp, CLOCK_TICK_RATE);
> +		if ((temp >> 32) == 0)
> +			break;
> +	}
> +
> +	/* Setup clocksource */
> +	clocksource_xttcpss.shift = shift;
> +	clocksource_xttcpss.mult =
> +		clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_xttcpss.shift);
> +
> +	if (clocksource_register(&clocksource_xttcpss))
> +		printk(KERN_ERR "xttcpss_timer_init: can't register clocksource"
> +				" for %s\n", clocksource_xttcpss.name);

If you use clocksource_register_hz() then you don't need to worry about 
calculating shift and mult, the generic framework will do that for you.

> +	/* Calculate the nanoseconds to cycles divisor value for clock event
> +	 * timer */
> +	for (shift = 16; shift > 0; shift--) {
> +		temp = (u64) CLOCK_TICK_RATE << shift;
> +		do_div(temp, NSEC_PER_SEC);
> +		if ((temp >> 32) == 0)
> +			break;
> +	}
> +
> +	/* Setup clockevent */
> +	xttcpss_clockevent.shift = shift;
> +	xttcpss_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
> +						 xttcpss_clockevent.shift);

clockevents_calc_mult_shift()?

> +
> +	xttcpss_clockevent.max_delta_ns =
> +		clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
> +	xttcpss_clockevent.min_delta_ns =
> +		clockevent_delta2ns(1, &xttcpss_clockevent);
> +
> +	xttcpss_clockevent.cpumask = cpumask_of(0);
> +	clockevents_register_device(&xttcpss_clockevent);
> +}
> +
> +#ifdef CONFIG_PM
> +/**
> + * xttcpss_timer_suspend - Suspend the timer
> + *
> + * Disables all (clock source and clock event) the timers
> + **/
> +static void xttcpss_timer_suspend(void)
> +{
> +	struct xttcpss_timer *source_timer = &timers[XTTCPSS_CLOCKSOURCE];
> +	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
> +	u32 ctrl_reg;
> +
> +	/* Disable clocksource timer */
> +	ctrl_reg = xttcpss_read(source_timer->base_addr +
> +				XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> +	xttcpss_write(source_timer->base_addr + 
> XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +
> +	/* Disable clockevent timer */
> +	ctrl_reg = xttcpss_read(event_timer->base_addr +
> +				XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> +	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +}
> +
> +/**
> + * xttcpss_timer_resume - Resume the timer
> + *
> + * Enables  all (clock source and clock event) the timers
> + **/
> +static void xttcpss_timer_resume(void)
> +{
> +	struct xttcpss_timer *source_timer = &timers[XTTCPSS_CLOCKSOURCE];
> +	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
> +	u32 ctrl_reg;
> +
> +	/* Enable clocksource timer */
> +	ctrl_reg = xttcpss_read(source_timer->base_addr +
> +				XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> +	xttcpss_write(source_timer->base_addr + 
> XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +
> +	/* Enable clockevent timer */
> +	ctrl_reg = xttcpss_read(event_timer->base_addr +
> +				XTTCPSS_CNT_CNTRL_OFFSET);
> +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> +	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> +				ctrl_reg);
> +}
> +#else
> +#define xttcpss_timer_suspend NULL
> +#define xttcpss_timer_resume NULL
> +#endif
> +
> +/*
> + * Instantiate and initialize the system timer structure
> + */
> +struct sys_timer xttcpss_sys_timer = {
> +	.init		= xttcpss_timer_init,
> +	.suspend	= xttcpss_timer_suspend,
> +	.resume		= xttcpss_timer_resume,
> +};
> -- 
> 1.6.2.1
> 
> 
> 
> 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.
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
  2011-02-06  0:45       ` Jamie Iles
@ 2011-02-07 14:05         ` John Linn
  -1 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-07 14:05 UTC (permalink / raw)
  To: Jamie Iles
  Cc: linux-arm-kernel, linux-kernel, linux, catalin.marinas, glikely

> -----Original Message-----
> From: Jamie Iles [mailto:jamie@jamieiles.com]
> Sent: Saturday, February 05, 2011 5:46 PM
> To: John Linn
> Cc: linux-arm-kernel@lists.infradead.org;
linux-kernel@vger.kernel.org; linux@arm.linux.org.uk;
> catalin.marinas@arm.com; glikely@secretlab.ca
> Subject: Re: [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
> 
> Hi John,
> 
> A couple of nitpicks inline, otherwise looks nice.
> 
> Jamie
> 
> On Sat, Feb 05, 2011 at 09:17:15AM -0700, John Linn wrote:
> > The 1st board support is minimal to get a system up and running
> > on the Xilinx platform.
> >
> > Signed-off-by: John Linn <john.linn@xilinx.com>
> > ---
> >  arch/arm/mach-xilinx/Kconfig       |   14 ++++
> >  arch/arm/mach-xilinx/Makefile      |    6 ++
> >  arch/arm/mach-xilinx/Makefile.boot |    3 +
> >  arch/arm/mach-xilinx/board_ep107.c |   81 ++++++++++++++++++++++
> >  arch/arm/mach-xilinx/common.c      |  132
++++++++++++++++++++++++++++++++++++
> >  arch/arm/mach-xilinx/common.h      |   32 +++++++++
> >  6 files changed, 268 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/arm/mach-xilinx/Kconfig
> >  create mode 100644 arch/arm/mach-xilinx/Makefile
> >  create mode 100644 arch/arm/mach-xilinx/Makefile.boot
> >  create mode 100644 arch/arm/mach-xilinx/board_ep107.c
> >  create mode 100644 arch/arm/mach-xilinx/common.c
> >  create mode 100644 arch/arm/mach-xilinx/common.h
> >
> > diff --git a/arch/arm/mach-xilinx/Kconfig
b/arch/arm/mach-xilinx/Kconfig
> > new file mode 100644
> > index 0000000..11f9e65
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/Kconfig
> > @@ -0,0 +1,14 @@
> > +if ARCH_XILINX
> > +
> > +choice
> > +        prompt "Board Selection"
> > +	default XILINX_EP107
> > +
> > +config XILINX_EP107
> > +	bool "Xilinx EP107 Board"
> > +	help
> > +	  Select if you are using a Xilinx EP107 board.
> > +
> > +endchoice
> > +
> > +endif
> > diff --git a/arch/arm/mach-xilinx/Makefile
b/arch/arm/mach-xilinx/Makefile
> > new file mode 100644
> > index 0000000..194f9e4
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/Makefile
> > @@ -0,0 +1,6 @@
> > +#
> > +# Makefile for the linux kernel.
> > +#
> > +
> > +# Common support
> > +obj-y := common.o board_ep107.o timer.o
> > diff --git a/arch/arm/mach-xilinx/Makefile.boot
b/arch/arm/mach-xilinx/Makefile.boot
> > new file mode 100644
> > index 0000000..67039c3
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/Makefile.boot
> > @@ -0,0 +1,3 @@
> > +   zreladdr-y	:= 0x00008000
> > +params_phys-y	:= 0x00000100
> > +initrd_phys-y	:= 0x00800000
> > diff --git a/arch/arm/mach-xilinx/board_ep107.c
b/arch/arm/mach-xilinx/board_ep107.c
> > new file mode 100644
> > index 0000000..233e744
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/board_ep107.c
> > @@ -0,0 +1,81 @@
> > +/* arch/arm/mach-xilinx/board_ep107.c
> > + *
> > + * This file contains code specific to the Xilinx EP107 board.
> > + *
> > + *  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 program is free software; you can redistribute it and/or
modify
> > + * it under the terms of the GNU General Public License as
published by
> > + * the Free Software Foundation; either version 2 of the License,
or
> > + * (at your option) any later version.
> > + *
> > + * You should have received a copy of the GNU General Public
License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307  USA
> > + */
> > +
> > +#include <linux/platform_device.h>
> > +#include <asm/mach-types.h>
> > +#include <asm/mach/arch.h>
> > +#include <mach/hardware.h>
> > +#include <linux/clkdev.h>
> > +#include "common.h"
> > +
> > +/*
> > + * Fixed clocks for now
> > + */
> > +
> > +static struct clk ref50_clk = {
> > +	.rate	= 50000000,
> > +};
> > +
> > +/* Create all the platform devices for the board */
> > +
> > +static struct resource uart0[] = {
> > +	{
> > +		.start = UART0_BASE,
> > +		.end = UART0_BASE + 0xFFF,
> > +		.flags = IORESOURCE_MEM,
> > +	}, {
> > +		.start = IRQ_UART0,
> > +		.end = IRQ_UART0,
> > +		.flags = IORESOURCE_IRQ,
> > +	},
> > +};
> > +
> > +static struct platform_device uart_device0 = {
> > +	.name = "xuartpss",
> > +	.id = 0,
> > +	.dev = {
> > +		.platform_data = &ref50_clk.rate,
> > +	},
> > +	.resource = uart0,
> > +	.num_resources = ARRAY_SIZE(uart0),
> > +};
> > +
> > +static struct platform_device *xilinx_pdevices[] __initdata = {
> > +	&uart_device0,
> > +};
> > +
> > +/**
> > + * board_ep107_init - Board specific initialization for the Xilinx
EP107 board.
> > + *
> > + **/
> > +static void __init board_ep107_init(void)
> > +{
> > +	system_init();
> > +	platform_device_init(xilinx_pdevices,
ARRAY_SIZE(xilinx_pdevices));
> > +}
> > +
> > +MACHINE_START(XILINX_EP107, "Xilinx EP107")
> > +	.boot_params    = PHYS_OFFSET + 0x00000100,
> > +	.map_io         = map_io,
> > +	.init_irq       = irq_init,
> > +	.init_machine   = board_ep107_init,
> > +	.timer          = &xttcpss_sys_timer,
> > +MACHINE_END
> > diff --git a/arch/arm/mach-xilinx/common.c
b/arch/arm/mach-xilinx/common.c
> > new file mode 100644
> > index 0000000..f7c51a7
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/common.c
> > @@ -0,0 +1,132 @@
> > +/* arch/arm/mach-xilinx/common.c
> > + *
> > + * This file contains common code that is intended to be used
across
> > + * boards so that it's not replicated.
> > + *
> > + *  Copyright (C) 2011 Xilinx
> > + *
> > + * This program is free software; you can redistribute it and/or
modify
> > + * it under the terms of the GNU General Public License as
published by
> > + * the Free Software Foundation; either version 2 of the License,
or
> > + * (at your option) any later version.
> > + *
> > + * You should have received a copy of the GNU General Public
License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307  USA
> > + */
> > +
> > +#include <linux/init.h>
> > +#include <linux/kernel.h>
> > +#include <linux/cpumask.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/clk.h>
> > +
> > +#include <asm/mach/map.h>
> > +#include <asm/page.h>
> > +#include <asm/hardware/gic.h>
> > +#include <asm/hardware/cache-l2x0.h>
> > +
> > +#include <mach/hardware.h>
> > +
> > +int clk_enable(struct clk *clk)
> > +{
> > +	return 0;
> > +}
> > +
> > +void clk_disable(struct clk *clk)
> > +{
> > +}
> 
> According to include/linux/clk.h you should also implement
> clk_get_rate() here too.

Ok, will take a look at that.

> 
> > +
> > +/**
> > + * system_init - System specific initialization, intended to be
called from
> > + *			board specific initialization.
> > + *
> > + **/
> > +void __init system_init(void)
> > +{
> > +#ifdef CONFIG_CACHE_L2X0
> > +	void *l2cache_base = (void *)PL310_L2CC_BASE;
> > +
> > +	/*
> > +	 * 64KB way size, 8-way associativity, parity disabled
> > +	 */
> > +	l2x0_init(l2cache_base, 0x02060000, 0xF0F0FFFF);
> > +#endif
> > +}
> > +
> > +/**
> > + * irq_init - Interrupt controller initialization for the GIC.
> > + *
> > + **/
> > +void __init irq_init(void)
> > +{
> > +	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
> > +	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE,
gic_cpu_base_addr);
> > +}
> > +
> > +/* 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_BASE,
> > +		.pfn		= __phys_to_pfn(TTC0_BASE),
> > +		.length		= SZ_4K,
> > +		.type		= MT_DEVICE,
> > +	}, {
> > +		.virtual	= SCU_PERIPH_BASE,
> > +		.pfn		= __phys_to_pfn(SCU_PERIPH_BASE),
> > +		.length		= SZ_8K,
> > +		.type		= MT_DEVICE,
> > +	}, {
> > +		.virtual	= PL310_L2CC_BASE,
> > +		.pfn		= __phys_to_pfn(PL310_L2CC_BASE),
> > +		.length		= SZ_4K,
> > +		.type		= MT_DEVICE,
> > +	},
> > +
> > +#ifdef CONFIG_DEBUG_LL
> > +	{
> > +		.virtual	= UART0_BASE,
> > +		.pfn		= __phys_to_pfn(UART0_BASE),
> > +		.length		= SZ_4K,
> > +		.type		= MT_DEVICE,
> > +	},
> > +#endif
> > +
> > +};
> > +
> > +/**
> > + * map_io - Create memory mappings needed for early I/O.
> > + *
> > + **/
> > +void __init map_io(void)
> > +{
> > +	iotable_init(io_desc, ARRAY_SIZE(io_desc));
> > +}
> > +
> > +/**
> > + * platform_device_init - Initialize all the platform devices.
> > + *
> > + **/
> > +void __init platform_device_init(struct platform_device
*xilinx_pdevices[],
> > +					int count)
> > +{
> > +	int ret, i;
> > +
> > +	/* Initialize all the platform devices */
> > +
> > +	for (i = 0; i < count; i++) {
> > +
> > +		pr_info("registering platform device '%s' id %d\n",
> > +			xilinx_pdevices[i]->name,
> > +			xilinx_pdevices[i]->id);
> > +
> > +		ret = platform_device_register(xilinx_pdevices[i]);
> > +		if (ret)
> > +			pr_info("Unable to register platform device
'%s': %d\n",
> > +				xilinx_pdevices[i]->name, ret);
> > +	}
> > +}
> 
> Would platform_add_devices() do here?  It does the same thing minus
the
> pr_info() and will cleanup if any of the registration fails.

Maybe, if so it's cleaner.  Will look at that.

Good suggestions, thanks.

-- John

> 
> > +
> > diff --git a/arch/arm/mach-xilinx/common.h
b/arch/arm/mach-xilinx/common.h
> > new file mode 100644
> > index 0000000..49de295
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/common.h
> > @@ -0,0 +1,32 @@
> > +/* arch/arm/mach-xilinx/common.h
> > + *
> > + * This file contains common function prototypes to avoid externs
> > + * in the c files.
> > + *
> > + *  Copyright (C) 2011 Xilinx
> > + *
> > + * This program is free software; you can redistribute it and/or
modify
> > + * it under the terms of the GNU General Public License as
published by
> > + * the Free Software Foundation; either version 2 of the License,
or
> > + * (at your option) any later version.
> > + *
> > + * You should have received a copy of the GNU General Public
License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307  USA
> > + */
> > +
> > +#ifndef __MACH_XILINX_COMMON_H__
> > +#define __MACH_XILINX_COMMON_H__
> > +
> > +#include <linux/init.h>
> > +#include <linux/platform_device.h>
> > +
> > +void __init system_init(void);
> > +void __init irq_init(void);
> > +void __init map_io(void);
> > +void __init platform_device_init(struct platform_device
*pdevices[],
> > +					int count);
> > +
> > +extern struct sys_timer xttcpss_sys_timer;
> > +
> > +#endif
> > --
> > 1.6.2.1
> >
> >
> >
> > 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.
> >
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


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.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
@ 2011-02-07 14:05         ` John Linn
  0 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-07 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Jamie Iles [mailto:jamie at jamieiles.com]
> Sent: Saturday, February 05, 2011 5:46 PM
> To: John Linn
> Cc: linux-arm-kernel at lists.infradead.org;
linux-kernel at vger.kernel.org; linux at arm.linux.org.uk;
> catalin.marinas at arm.com; glikely at secretlab.ca
> Subject: Re: [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
> 
> Hi John,
> 
> A couple of nitpicks inline, otherwise looks nice.
> 
> Jamie
> 
> On Sat, Feb 05, 2011 at 09:17:15AM -0700, John Linn wrote:
> > The 1st board support is minimal to get a system up and running
> > on the Xilinx platform.
> >
> > Signed-off-by: John Linn <john.linn@xilinx.com>
> > ---
> >  arch/arm/mach-xilinx/Kconfig       |   14 ++++
> >  arch/arm/mach-xilinx/Makefile      |    6 ++
> >  arch/arm/mach-xilinx/Makefile.boot |    3 +
> >  arch/arm/mach-xilinx/board_ep107.c |   81 ++++++++++++++++++++++
> >  arch/arm/mach-xilinx/common.c      |  132
++++++++++++++++++++++++++++++++++++
> >  arch/arm/mach-xilinx/common.h      |   32 +++++++++
> >  6 files changed, 268 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/arm/mach-xilinx/Kconfig
> >  create mode 100644 arch/arm/mach-xilinx/Makefile
> >  create mode 100644 arch/arm/mach-xilinx/Makefile.boot
> >  create mode 100644 arch/arm/mach-xilinx/board_ep107.c
> >  create mode 100644 arch/arm/mach-xilinx/common.c
> >  create mode 100644 arch/arm/mach-xilinx/common.h
> >
> > diff --git a/arch/arm/mach-xilinx/Kconfig
b/arch/arm/mach-xilinx/Kconfig
> > new file mode 100644
> > index 0000000..11f9e65
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/Kconfig
> > @@ -0,0 +1,14 @@
> > +if ARCH_XILINX
> > +
> > +choice
> > +        prompt "Board Selection"
> > +	default XILINX_EP107
> > +
> > +config XILINX_EP107
> > +	bool "Xilinx EP107 Board"
> > +	help
> > +	  Select if you are using a Xilinx EP107 board.
> > +
> > +endchoice
> > +
> > +endif
> > diff --git a/arch/arm/mach-xilinx/Makefile
b/arch/arm/mach-xilinx/Makefile
> > new file mode 100644
> > index 0000000..194f9e4
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/Makefile
> > @@ -0,0 +1,6 @@
> > +#
> > +# Makefile for the linux kernel.
> > +#
> > +
> > +# Common support
> > +obj-y := common.o board_ep107.o timer.o
> > diff --git a/arch/arm/mach-xilinx/Makefile.boot
b/arch/arm/mach-xilinx/Makefile.boot
> > new file mode 100644
> > index 0000000..67039c3
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/Makefile.boot
> > @@ -0,0 +1,3 @@
> > +   zreladdr-y	:= 0x00008000
> > +params_phys-y	:= 0x00000100
> > +initrd_phys-y	:= 0x00800000
> > diff --git a/arch/arm/mach-xilinx/board_ep107.c
b/arch/arm/mach-xilinx/board_ep107.c
> > new file mode 100644
> > index 0000000..233e744
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/board_ep107.c
> > @@ -0,0 +1,81 @@
> > +/* arch/arm/mach-xilinx/board_ep107.c
> > + *
> > + * This file contains code specific to the Xilinx EP107 board.
> > + *
> > + *  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 program is free software; you can redistribute it and/or
modify
> > + * it under the terms of the GNU General Public License as
published by
> > + * the Free Software Foundation; either version 2 of the License,
or
> > + * (at your option) any later version.
> > + *
> > + * You should have received a copy of the GNU General Public
License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307  USA
> > + */
> > +
> > +#include <linux/platform_device.h>
> > +#include <asm/mach-types.h>
> > +#include <asm/mach/arch.h>
> > +#include <mach/hardware.h>
> > +#include <linux/clkdev.h>
> > +#include "common.h"
> > +
> > +/*
> > + * Fixed clocks for now
> > + */
> > +
> > +static struct clk ref50_clk = {
> > +	.rate	= 50000000,
> > +};
> > +
> > +/* Create all the platform devices for the board */
> > +
> > +static struct resource uart0[] = {
> > +	{
> > +		.start = UART0_BASE,
> > +		.end = UART0_BASE + 0xFFF,
> > +		.flags = IORESOURCE_MEM,
> > +	}, {
> > +		.start = IRQ_UART0,
> > +		.end = IRQ_UART0,
> > +		.flags = IORESOURCE_IRQ,
> > +	},
> > +};
> > +
> > +static struct platform_device uart_device0 = {
> > +	.name = "xuartpss",
> > +	.id = 0,
> > +	.dev = {
> > +		.platform_data = &ref50_clk.rate,
> > +	},
> > +	.resource = uart0,
> > +	.num_resources = ARRAY_SIZE(uart0),
> > +};
> > +
> > +static struct platform_device *xilinx_pdevices[] __initdata = {
> > +	&uart_device0,
> > +};
> > +
> > +/**
> > + * board_ep107_init - Board specific initialization for the Xilinx
EP107 board.
> > + *
> > + **/
> > +static void __init board_ep107_init(void)
> > +{
> > +	system_init();
> > +	platform_device_init(xilinx_pdevices,
ARRAY_SIZE(xilinx_pdevices));
> > +}
> > +
> > +MACHINE_START(XILINX_EP107, "Xilinx EP107")
> > +	.boot_params    = PHYS_OFFSET + 0x00000100,
> > +	.map_io         = map_io,
> > +	.init_irq       = irq_init,
> > +	.init_machine   = board_ep107_init,
> > +	.timer          = &xttcpss_sys_timer,
> > +MACHINE_END
> > diff --git a/arch/arm/mach-xilinx/common.c
b/arch/arm/mach-xilinx/common.c
> > new file mode 100644
> > index 0000000..f7c51a7
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/common.c
> > @@ -0,0 +1,132 @@
> > +/* arch/arm/mach-xilinx/common.c
> > + *
> > + * This file contains common code that is intended to be used
across
> > + * boards so that it's not replicated.
> > + *
> > + *  Copyright (C) 2011 Xilinx
> > + *
> > + * This program is free software; you can redistribute it and/or
modify
> > + * it under the terms of the GNU General Public License as
published by
> > + * the Free Software Foundation; either version 2 of the License,
or
> > + * (at your option) any later version.
> > + *
> > + * You should have received a copy of the GNU General Public
License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307  USA
> > + */
> > +
> > +#include <linux/init.h>
> > +#include <linux/kernel.h>
> > +#include <linux/cpumask.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/clk.h>
> > +
> > +#include <asm/mach/map.h>
> > +#include <asm/page.h>
> > +#include <asm/hardware/gic.h>
> > +#include <asm/hardware/cache-l2x0.h>
> > +
> > +#include <mach/hardware.h>
> > +
> > +int clk_enable(struct clk *clk)
> > +{
> > +	return 0;
> > +}
> > +
> > +void clk_disable(struct clk *clk)
> > +{
> > +}
> 
> According to include/linux/clk.h you should also implement
> clk_get_rate() here too.

Ok, will take a look at that.

> 
> > +
> > +/**
> > + * system_init - System specific initialization, intended to be
called from
> > + *			board specific initialization.
> > + *
> > + **/
> > +void __init system_init(void)
> > +{
> > +#ifdef CONFIG_CACHE_L2X0
> > +	void *l2cache_base = (void *)PL310_L2CC_BASE;
> > +
> > +	/*
> > +	 * 64KB way size, 8-way associativity, parity disabled
> > +	 */
> > +	l2x0_init(l2cache_base, 0x02060000, 0xF0F0FFFF);
> > +#endif
> > +}
> > +
> > +/**
> > + * irq_init - Interrupt controller initialization for the GIC.
> > + *
> > + **/
> > +void __init irq_init(void)
> > +{
> > +	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
> > +	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE,
gic_cpu_base_addr);
> > +}
> > +
> > +/* 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_BASE,
> > +		.pfn		= __phys_to_pfn(TTC0_BASE),
> > +		.length		= SZ_4K,
> > +		.type		= MT_DEVICE,
> > +	}, {
> > +		.virtual	= SCU_PERIPH_BASE,
> > +		.pfn		= __phys_to_pfn(SCU_PERIPH_BASE),
> > +		.length		= SZ_8K,
> > +		.type		= MT_DEVICE,
> > +	}, {
> > +		.virtual	= PL310_L2CC_BASE,
> > +		.pfn		= __phys_to_pfn(PL310_L2CC_BASE),
> > +		.length		= SZ_4K,
> > +		.type		= MT_DEVICE,
> > +	},
> > +
> > +#ifdef CONFIG_DEBUG_LL
> > +	{
> > +		.virtual	= UART0_BASE,
> > +		.pfn		= __phys_to_pfn(UART0_BASE),
> > +		.length		= SZ_4K,
> > +		.type		= MT_DEVICE,
> > +	},
> > +#endif
> > +
> > +};
> > +
> > +/**
> > + * map_io - Create memory mappings needed for early I/O.
> > + *
> > + **/
> > +void __init map_io(void)
> > +{
> > +	iotable_init(io_desc, ARRAY_SIZE(io_desc));
> > +}
> > +
> > +/**
> > + * platform_device_init - Initialize all the platform devices.
> > + *
> > + **/
> > +void __init platform_device_init(struct platform_device
*xilinx_pdevices[],
> > +					int count)
> > +{
> > +	int ret, i;
> > +
> > +	/* Initialize all the platform devices */
> > +
> > +	for (i = 0; i < count; i++) {
> > +
> > +		pr_info("registering platform device '%s' id %d\n",
> > +			xilinx_pdevices[i]->name,
> > +			xilinx_pdevices[i]->id);
> > +
> > +		ret = platform_device_register(xilinx_pdevices[i]);
> > +		if (ret)
> > +			pr_info("Unable to register platform device
'%s': %d\n",
> > +				xilinx_pdevices[i]->name, ret);
> > +	}
> > +}
> 
> Would platform_add_devices() do here?  It does the same thing minus
the
> pr_info() and will cleanup if any of the registration fails.

Maybe, if so it's cleaner.  Will look at that.

Good suggestions, thanks.

-- John

> 
> > +
> > diff --git a/arch/arm/mach-xilinx/common.h
b/arch/arm/mach-xilinx/common.h
> > new file mode 100644
> > index 0000000..49de295
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/common.h
> > @@ -0,0 +1,32 @@
> > +/* arch/arm/mach-xilinx/common.h
> > + *
> > + * This file contains common function prototypes to avoid externs
> > + * in the c files.
> > + *
> > + *  Copyright (C) 2011 Xilinx
> > + *
> > + * This program is free software; you can redistribute it and/or
modify
> > + * it under the terms of the GNU General Public License as
published by
> > + * the Free Software Foundation; either version 2 of the License,
or
> > + * (at your option) any later version.
> > + *
> > + * You should have received a copy of the GNU General Public
License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307  USA
> > + */
> > +
> > +#ifndef __MACH_XILINX_COMMON_H__
> > +#define __MACH_XILINX_COMMON_H__
> > +
> > +#include <linux/init.h>
> > +#include <linux/platform_device.h>
> > +
> > +void __init system_init(void);
> > +void __init irq_init(void);
> > +void __init map_io(void);
> > +void __init platform_device_init(struct platform_device
*pdevices[],
> > +					int count);
> > +
> > +extern struct sys_timer xttcpss_sys_timer;
> > +
> > +#endif
> > --
> > 1.6.2.1
> >
> >
> >
> > 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.
> >
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
  2011-02-06  1:03         ` Jamie Iles
@ 2011-02-07 14:16           ` John Linn
  -1 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-07 14:16 UTC (permalink / raw)
  To: Jamie Iles
  Cc: linux-arm-kernel, linux-kernel, linux, catalin.marinas, glikely,
	Kiran Sutariya

> -----Original Message-----
> From: Jamie Iles [mailto:jamie@jamieiles.com]
> Sent: Saturday, February 05, 2011 6:04 PM
> To: John Linn
> Cc: linux-arm-kernel@lists.infradead.org;
linux-kernel@vger.kernel.org; linux@arm.linux.org.uk;
> catalin.marinas@arm.com; glikely@secretlab.ca; Kiran Sutariya
> Subject: Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the
platform
> 
> Hi John,
> 
> A couple more nitpicks.
> 
> Jamie
> 
> On Sat, Feb 05, 2011 at 09:17:16AM -0700, John Linn wrote:
> > The timer driver supports the Xilinx PS Timer Counter IP.
> >
> > Signed-off-by: Kiran Sutariya <kiran.sutariya@einfochips.com>
> > Signed-off-by: John Linn <john.linn@xilinx.com>
> > ---
> >  arch/arm/mach-xilinx/timer.c |  452
++++++++++++++++++++++++++++++++++++++++++
> >  1 files changed, 452 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/arm/mach-xilinx/timer.c
> >
> > diff --git a/arch/arm/mach-xilinx/timer.c
b/arch/arm/mach-xilinx/timer.c
> > new file mode 100644
> > index 0000000..c713e3c
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/timer.c
> > @@ -0,0 +1,452 @@
> > +/* arch/arm/mach-xilinx/timer.c
> > + *
> > + * 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 program is free software; you can redistribute it and/or
modify it under
> > + * the terms of the GNU General Public License version 2 as
published by the
> > + * Free Software Foundation; either version 2 of the License, or
(at your
> > + * option) any later version.
> > + *
> > + * You should have received a copy of the GNU General Public
License along with
> > + * this program; if not, write to the Free Software Foundation,
Inc., 59 Temple
> > + * Place, Suite 330, Boston, MA  02111-1307  USA
> > + */
> > +
> > +#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/hardware.h>
> > +
> > +/*
> > + * 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 is 200MHz which is
common to all the
> > + * timer channel (T1, T2, and T3)
> > + * Clocksource timer resolution is 160ns
> > + * Clockevent timer resolution is 160ns
> > + */
> > +#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
> > +
> > +/*
> > + * 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
*/
> > +
> > +/*
> > + * Bit mask to enable/disable the timer
> > + */
> > +#define XTTCPSS_CNT_CNTRL_ENABLE_MASK	0xFFFFFFFE
> 
> I found this really confusing reading through the code, but that's
> probably just me!  Perhaps if this was called
> XTTCPSS_CNT_CNTRL_DISABLE_MASK and defined to 1 then that might be a
> little easier to follow.
> 

I'll take a look, maybe the name change would be clearer.

> > +
> > +/*
> > + * Definitions of the timer read/write macro
> > + */
> > +#define xttcpss_read(addr)	__raw_readl((void __iomem *)addr)
> > +#define xttcpss_write(addr, val) __raw_writel(val, (void __iomem
*)(addr))
> > +
> > +
> > +/**
> > + * struct xttcpss_timer - This definition defines local timer
structure
> > + *
> > + * @name:	Name of Timer
> > + * @base_addr:	Base address of timer
> > + * @timer_irq:	irqaction structure for the timer device
> > + * @mode:       only valid for an clock event, periodic or one-shot
> > + **/
> > +struct xttcpss_timer {
> > +	char *name;
> > +	unsigned long base_addr;
> 
> Shouldn't this really be a void __iomem pointer?  This could eliminate
> the need for xttcpss_write and xttcpss_read.

That would work too. I kind of like having the I/O accessors as I've
found them handy 
sometimes for debugging.  I'll check it out and consider it as maybe
it's simpler 
and clearer.

> 
> > +	struct irqaction timer_irq;
> > +	enum clock_event_mode mode;
> > +};
> > +
> > +
> > +static struct xttcpss_timer timers[];
> > +static struct clock_event_device xttcpss_clockevent;
> > +
> > +/*
> > + * xttcpss_timer_irqs - Timers IRQ number
> > + */
> > +static int xttcpss_timer_irqs[2] = {
> > +	IRQ_TIMERCOUNTER0,	/* Timer 1 IRQ number */
> > +	IRQ_TIMERCOUNTER0 + 1,	/* Timer 2 IRQ number */
> > +};
> > +
> > +/**
> > + * 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 = xttcpss_read(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > +	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> > ctrl_reg);
> > +
> > +	pr_debug("set_interval, name = %s, period = %08X\n",
> > +			timer->name, (unsigned int)cycles);
> > +
> > +	xttcpss_write(timer->base_addr + XTTCPSS_INTR_VAL_OFFSET,
cycles);
> > +
> > +	/* Reset the counter (0x10) so that it starts from 0, one-shot
> > +	   mode makes this needed for timing to be right. */
> > +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> > +	ctrl_reg |= 0x10;
> > +	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> > ctrl_reg);
> > +}
> > +
> > +/**
> > + * xttcpss_clock_source_interrupt - Clock source timer interrupt
handler
> > + *
> > + * @irq:	IRQ number of the Timer
> > + * @dev_id:	void pointer to the xttcpss_timer instance
> > + *
> > + * This will be called when 16-bit clock source counter wraps
> > + *
> > + * returns: Always IRQ_HANDLED - success
> > + **/
> > +static irqreturn_t xttcpss_clock_source_interrupt(int irq, void
*dev_id)
> > +{
> > +	struct xttcpss_timer *timer = dev_id;
> > +
> > +	/* Acknowledge the interrupt */
> > +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> > +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +/**
> > + * 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;
> > +	u32 ctrl_reg;
> > +
> > +	/* Acknowledge the interrupt and call event handler */
> > +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> > +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> > +
> > +	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
> > +
> > +		/* Disable the counter as it would keep running. */
> > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > +					XTTCPSS_CNT_CNTRL_OFFSET);
> > +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> 
> The clock events framework should reprogram the next event so you
don't
> actually need to disable the timer here.  Once the event handler has
> been called the timer will be reenabled with a new period, and as
we're
> running with interrupts disabled here we don't need to stop the timer.
> 

What about if there's not another event to be started?

> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +	}
> > +
> > +	evt->event_handler(evt);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +/*
> > + * struct xttcpss_timer timers - This definition defines local
timers
> > + */
> > +static struct xttcpss_timer timers[] = {
> > +	[XTTCPSS_CLOCKSOURCE] = {
> > +		.name = "xttcpss clocksource",
> > +		.timer_irq = {
> > +			.flags = IRQF_DISABLED | IRQF_TIMER,
> > +			.handler = xttcpss_clock_source_interrupt,
> > +		}
> > +	},
> > +	[XTTCPSS_CLOCKEVENT] = {
> > +		.name = "xttcpss clockevent",
> > +		.timer_irq = {
> > +			.flags = IRQF_DISABLED | IRQF_TIMER,
> > +			.handler = xttcpss_clock_event_interrupt,
> > +		}
> > +	},
> > +};
> > +
> > +
> > +/**
> > + * xttcpss_timer_hardware_init - Initialize the timer hardware
> > + *
> > + * Initialize the hardware, registers the timer interrupts, set the
clock source
> > + * timer interval and enable the clock source timer
> > + **/
> > +static void __init xttcpss_timer_hardware_init(void)
> > +{
> > +	int timer_id;
> > +	struct xttcpss_timer *timer;
> > +
> > +	for (timer_id = 0; timer_id < ARRAY_SIZE(timers); timer_id++) {
> > +		timer = &timers[timer_id];
> > +
> > +		if (!(timer->name))
> > +			continue;
> > +
> > +		timer->base_addr = XTTCPSS_TIMER_BASE + (4*timer_id);
> > +
> > +		/* Disable counter, Enable Interval mode, Count up
timer,
> > +		 * Disable Match mode, Internal Clock source select, set
> > +		 * prescalar to 32, and Enable the Interval interrupt */
> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET,
> > +				0x23);
> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CLK_CNTRL_OFFSET, 0x9);
> > +		xttcpss_write(timer->base_addr + XTTCPSS_IER_OFFSET,
0x1);
> > +
> > +		/* Setup IRQ */
> > +		timer->timer_irq.name = timer->name;
> > +		timer->timer_irq.dev_id = (void *)timer;
> > +		if (timer->timer_irq.handler != NULL) {
> > +			setup_irq(xttcpss_timer_irqs[timer_id],
> > +				&timer->timer_irq);
> > +		}
> > +		if (timer_id == XTTCPSS_CLOCKSOURCE)
> > +			xttcpss_set_interval(timer, ~0);
> > +	}
> > +}
> > +
> > +/**
> > + * xttcpss_read_cycles - Reads the timer counter register
> > + *
> > + * returns: Current timer counter register value
> > + **/
> > +static cycle_t xttcpss_read_cycles(struct clocksource *cs)
> > +{
> > +	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
> > +
> > +	return (cycle_t)xttcpss_read(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		= xttcpss_read_cycles,
> > +	.mask		= CLOCKSOURCE_MASK(16),
> > +	.shift		= 0,			/* Initialized to zero
*/
> > +	.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;
> > +
> > +	timer->mode = mode;
> > +
> > +	switch (mode) {
> > +	case CLOCK_EVT_MODE_PERIODIC:
> > +		xttcpss_set_interval(timer, CLOCK_TICK_RATE / HZ);
> > +		break;
> > +	case CLOCK_EVT_MODE_ONESHOT:
> > +	case CLOCK_EVT_MODE_UNUSED:
> > +	case CLOCK_EVT_MODE_SHUTDOWN:
> > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > +					XTTCPSS_CNT_CNTRL_OFFSET);
> > +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +		break;
> > +	case CLOCK_EVT_MODE_RESUME:
> > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > +					XTTCPSS_CNT_CNTRL_OFFSET);
> > +		ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +		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,
> > +	.shift		= 0,		/* Initialized to zero */
> > +	.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 registers the clock source
and clock event
> > + * timers with Linux kernal timer framework
> > + **/
> > +static void __init xttcpss_timer_init(void)
> > +{
> > +	u32 shift;
> > +	u64 temp;
> > +
> > +	xttcpss_timer_hardware_init();
> > +
> > +	/* Calculate the nanoseconds to cycles divisor value for clock
source
> > +	 * timer */
> > +	for (shift = 16; shift > 0; shift--) {
> > +		temp = (u64) NSEC_PER_SEC << shift;
> > +		do_div(temp, CLOCK_TICK_RATE);
> > +		if ((temp >> 32) == 0)
> > +			break;
> > +	}
> > +
> > +	/* Setup clocksource */
> > +	clocksource_xttcpss.shift = shift;
> > +	clocksource_xttcpss.mult =
> > +		clocksource_hz2mult(CLOCK_TICK_RATE,
clocksource_xttcpss.shift);
> > +
> > +	if (clocksource_register(&clocksource_xttcpss))
> > +		printk(KERN_ERR "xttcpss_timer_init: can't register
clocksource"
> > +				" for %s\n", clocksource_xttcpss.name);
> 
> If you use clocksource_register_hz() then you don't need to worry
about
> calculating shift and mult, the generic framework will do that for
you.
> 

Yes, sounds easier.

> > +	/* Calculate the nanoseconds to cycles divisor value for clock
event
> > +	 * timer */
> > +	for (shift = 16; shift > 0; shift--) {
> > +		temp = (u64) CLOCK_TICK_RATE << shift;
> > +		do_div(temp, NSEC_PER_SEC);
> > +		if ((temp >> 32) == 0)
> > +			break;
> > +	}
> > +
> > +	/* Setup clockevent */
> > +	xttcpss_clockevent.shift = shift;
> > +	xttcpss_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
> > +
xttcpss_clockevent.shift);
> 
> clockevents_calc_mult_shift()?
> 

Yep, Russell mentioned these type of changes also. Thanks a lot for the
review Jamie. 

I Will try to get changes incorporated into a V2 of the patches.

-- John

> > +
> > +	xttcpss_clockevent.max_delta_ns =
> > +		clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
> > +	xttcpss_clockevent.min_delta_ns =
> > +		clockevent_delta2ns(1, &xttcpss_clockevent);
> > +
> > +	xttcpss_clockevent.cpumask = cpumask_of(0);
> > +	clockevents_register_device(&xttcpss_clockevent);
> > +}
> > +
> > +#ifdef CONFIG_PM
> > +/**
> > + * xttcpss_timer_suspend - Suspend the timer
> > + *
> > + * Disables all (clock source and clock event) the timers
> > + **/
> > +static void xttcpss_timer_suspend(void)
> > +{
> > +	struct xttcpss_timer *source_timer =
&timers[XTTCPSS_CLOCKSOURCE];
> > +	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
> > +	u32 ctrl_reg;
> > +
> > +	/* Disable clocksource timer */
> > +	ctrl_reg = xttcpss_read(source_timer->base_addr +
> > +				XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > +	xttcpss_write(source_timer->base_addr +
> > XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +
> > +	/* Disable clockevent timer */
> > +	ctrl_reg = xttcpss_read(event_timer->base_addr +
> > +				XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > +	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +}
> > +
> > +/**
> > + * xttcpss_timer_resume - Resume the timer
> > + *
> > + * Enables  all (clock source and clock event) the timers
> > + **/
> > +static void xttcpss_timer_resume(void)
> > +{
> > +	struct xttcpss_timer *source_timer =
&timers[XTTCPSS_CLOCKSOURCE];
> > +	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
> > +	u32 ctrl_reg;
> > +
> > +	/* Enable clocksource timer */
> > +	ctrl_reg = xttcpss_read(source_timer->base_addr +
> > +				XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> > +	xttcpss_write(source_timer->base_addr +
> > XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +
> > +	/* Enable clockevent timer */
> > +	ctrl_reg = xttcpss_read(event_timer->base_addr +
> > +				XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> > +	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +}
> > +#else
> > +#define xttcpss_timer_suspend NULL
> > +#define xttcpss_timer_resume NULL
> > +#endif
> > +
> > +/*
> > + * Instantiate and initialize the system timer structure
> > + */
> > +struct sys_timer xttcpss_sys_timer = {
> > +	.init		= xttcpss_timer_init,
> > +	.suspend	= xttcpss_timer_suspend,
> > +	.resume		= xttcpss_timer_resume,
> > +};
> > --
> > 1.6.2.1
> >
> >
> >
> > 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.
> >
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


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.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
@ 2011-02-07 14:16           ` John Linn
  0 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-07 14:16 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Jamie Iles [mailto:jamie at jamieiles.com]
> Sent: Saturday, February 05, 2011 6:04 PM
> To: John Linn
> Cc: linux-arm-kernel at lists.infradead.org;
linux-kernel at vger.kernel.org; linux at arm.linux.org.uk;
> catalin.marinas at arm.com; glikely at secretlab.ca; Kiran Sutariya
> Subject: Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the
platform
> 
> Hi John,
> 
> A couple more nitpicks.
> 
> Jamie
> 
> On Sat, Feb 05, 2011 at 09:17:16AM -0700, John Linn wrote:
> > The timer driver supports the Xilinx PS Timer Counter IP.
> >
> > Signed-off-by: Kiran Sutariya <kiran.sutariya@einfochips.com>
> > Signed-off-by: John Linn <john.linn@xilinx.com>
> > ---
> >  arch/arm/mach-xilinx/timer.c |  452
++++++++++++++++++++++++++++++++++++++++++
> >  1 files changed, 452 insertions(+), 0 deletions(-)
> >  create mode 100644 arch/arm/mach-xilinx/timer.c
> >
> > diff --git a/arch/arm/mach-xilinx/timer.c
b/arch/arm/mach-xilinx/timer.c
> > new file mode 100644
> > index 0000000..c713e3c
> > --- /dev/null
> > +++ b/arch/arm/mach-xilinx/timer.c
> > @@ -0,0 +1,452 @@
> > +/* arch/arm/mach-xilinx/timer.c
> > + *
> > + * 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 program is free software; you can redistribute it and/or
modify it under
> > + * the terms of the GNU General Public License version 2 as
published by the
> > + * Free Software Foundation; either version 2 of the License, or
(at your
> > + * option) any later version.
> > + *
> > + * You should have received a copy of the GNU General Public
License along with
> > + * this program; if not, write to the Free Software Foundation,
Inc., 59 Temple
> > + * Place, Suite 330, Boston, MA  02111-1307  USA
> > + */
> > +
> > +#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/hardware.h>
> > +
> > +/*
> > + * 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 is 200MHz which is
common to all the
> > + * timer channel (T1, T2, and T3)
> > + * Clocksource timer resolution is 160ns
> > + * Clockevent timer resolution is 160ns
> > + */
> > +#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
> > +
> > +/*
> > + * 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
*/
> > +
> > +/*
> > + * Bit mask to enable/disable the timer
> > + */
> > +#define XTTCPSS_CNT_CNTRL_ENABLE_MASK	0xFFFFFFFE
> 
> I found this really confusing reading through the code, but that's
> probably just me!  Perhaps if this was called
> XTTCPSS_CNT_CNTRL_DISABLE_MASK and defined to 1 then that might be a
> little easier to follow.
> 

I'll take a look, maybe the name change would be clearer.

> > +
> > +/*
> > + * Definitions of the timer read/write macro
> > + */
> > +#define xttcpss_read(addr)	__raw_readl((void __iomem *)addr)
> > +#define xttcpss_write(addr, val) __raw_writel(val, (void __iomem
*)(addr))
> > +
> > +
> > +/**
> > + * struct xttcpss_timer - This definition defines local timer
structure
> > + *
> > + * @name:	Name of Timer
> > + * @base_addr:	Base address of timer
> > + * @timer_irq:	irqaction structure for the timer device
> > + * @mode:       only valid for an clock event, periodic or one-shot
> > + **/
> > +struct xttcpss_timer {
> > +	char *name;
> > +	unsigned long base_addr;
> 
> Shouldn't this really be a void __iomem pointer?  This could eliminate
> the need for xttcpss_write and xttcpss_read.

That would work too. I kind of like having the I/O accessors as I've
found them handy 
sometimes for debugging.  I'll check it out and consider it as maybe
it's simpler 
and clearer.

> 
> > +	struct irqaction timer_irq;
> > +	enum clock_event_mode mode;
> > +};
> > +
> > +
> > +static struct xttcpss_timer timers[];
> > +static struct clock_event_device xttcpss_clockevent;
> > +
> > +/*
> > + * xttcpss_timer_irqs - Timers IRQ number
> > + */
> > +static int xttcpss_timer_irqs[2] = {
> > +	IRQ_TIMERCOUNTER0,	/* Timer 1 IRQ number */
> > +	IRQ_TIMERCOUNTER0 + 1,	/* Timer 2 IRQ number */
> > +};
> > +
> > +/**
> > + * 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 = xttcpss_read(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > +	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> > ctrl_reg);
> > +
> > +	pr_debug("set_interval, name = %s, period = %08X\n",
> > +			timer->name, (unsigned int)cycles);
> > +
> > +	xttcpss_write(timer->base_addr + XTTCPSS_INTR_VAL_OFFSET,
cycles);
> > +
> > +	/* Reset the counter (0x10) so that it starts from 0, one-shot
> > +	   mode makes this needed for timing to be right. */
> > +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> > +	ctrl_reg |= 0x10;
> > +	xttcpss_write(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> > ctrl_reg);
> > +}
> > +
> > +/**
> > + * xttcpss_clock_source_interrupt - Clock source timer interrupt
handler
> > + *
> > + * @irq:	IRQ number of the Timer
> > + * @dev_id:	void pointer to the xttcpss_timer instance
> > + *
> > + * This will be called when 16-bit clock source counter wraps
> > + *
> > + * returns: Always IRQ_HANDLED - success
> > + **/
> > +static irqreturn_t xttcpss_clock_source_interrupt(int irq, void
*dev_id)
> > +{
> > +	struct xttcpss_timer *timer = dev_id;
> > +
> > +	/* Acknowledge the interrupt */
> > +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> > +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +/**
> > + * 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;
> > +	u32 ctrl_reg;
> > +
> > +	/* Acknowledge the interrupt and call event handler */
> > +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> > +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> > +
> > +	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
> > +
> > +		/* Disable the counter as it would keep running. */
> > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > +					XTTCPSS_CNT_CNTRL_OFFSET);
> > +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> 
> The clock events framework should reprogram the next event so you
don't
> actually need to disable the timer here.  Once the event handler has
> been called the timer will be reenabled with a new period, and as
we're
> running with interrupts disabled here we don't need to stop the timer.
> 

What about if there's not another event to be started?

> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +	}
> > +
> > +	evt->event_handler(evt);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +/*
> > + * struct xttcpss_timer timers - This definition defines local
timers
> > + */
> > +static struct xttcpss_timer timers[] = {
> > +	[XTTCPSS_CLOCKSOURCE] = {
> > +		.name = "xttcpss clocksource",
> > +		.timer_irq = {
> > +			.flags = IRQF_DISABLED | IRQF_TIMER,
> > +			.handler = xttcpss_clock_source_interrupt,
> > +		}
> > +	},
> > +	[XTTCPSS_CLOCKEVENT] = {
> > +		.name = "xttcpss clockevent",
> > +		.timer_irq = {
> > +			.flags = IRQF_DISABLED | IRQF_TIMER,
> > +			.handler = xttcpss_clock_event_interrupt,
> > +		}
> > +	},
> > +};
> > +
> > +
> > +/**
> > + * xttcpss_timer_hardware_init - Initialize the timer hardware
> > + *
> > + * Initialize the hardware, registers the timer interrupts, set the
clock source
> > + * timer interval and enable the clock source timer
> > + **/
> > +static void __init xttcpss_timer_hardware_init(void)
> > +{
> > +	int timer_id;
> > +	struct xttcpss_timer *timer;
> > +
> > +	for (timer_id = 0; timer_id < ARRAY_SIZE(timers); timer_id++) {
> > +		timer = &timers[timer_id];
> > +
> > +		if (!(timer->name))
> > +			continue;
> > +
> > +		timer->base_addr = XTTCPSS_TIMER_BASE + (4*timer_id);
> > +
> > +		/* Disable counter, Enable Interval mode, Count up
timer,
> > +		 * Disable Match mode, Internal Clock source select, set
> > +		 * prescalar to 32, and Enable the Interval interrupt */
> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET,
> > +				0x23);
> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CLK_CNTRL_OFFSET, 0x9);
> > +		xttcpss_write(timer->base_addr + XTTCPSS_IER_OFFSET,
0x1);
> > +
> > +		/* Setup IRQ */
> > +		timer->timer_irq.name = timer->name;
> > +		timer->timer_irq.dev_id = (void *)timer;
> > +		if (timer->timer_irq.handler != NULL) {
> > +			setup_irq(xttcpss_timer_irqs[timer_id],
> > +				&timer->timer_irq);
> > +		}
> > +		if (timer_id == XTTCPSS_CLOCKSOURCE)
> > +			xttcpss_set_interval(timer, ~0);
> > +	}
> > +}
> > +
> > +/**
> > + * xttcpss_read_cycles - Reads the timer counter register
> > + *
> > + * returns: Current timer counter register value
> > + **/
> > +static cycle_t xttcpss_read_cycles(struct clocksource *cs)
> > +{
> > +	struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
> > +
> > +	return (cycle_t)xttcpss_read(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		= xttcpss_read_cycles,
> > +	.mask		= CLOCKSOURCE_MASK(16),
> > +	.shift		= 0,			/* Initialized to zero
*/
> > +	.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;
> > +
> > +	timer->mode = mode;
> > +
> > +	switch (mode) {
> > +	case CLOCK_EVT_MODE_PERIODIC:
> > +		xttcpss_set_interval(timer, CLOCK_TICK_RATE / HZ);
> > +		break;
> > +	case CLOCK_EVT_MODE_ONESHOT:
> > +	case CLOCK_EVT_MODE_UNUSED:
> > +	case CLOCK_EVT_MODE_SHUTDOWN:
> > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > +					XTTCPSS_CNT_CNTRL_OFFSET);
> > +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +		break;
> > +	case CLOCK_EVT_MODE_RESUME:
> > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > +					XTTCPSS_CNT_CNTRL_OFFSET);
> > +		ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> > +		xttcpss_write(timer->base_addr +
XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +		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,
> > +	.shift		= 0,		/* Initialized to zero */
> > +	.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 registers the clock source
and clock event
> > + * timers with Linux kernal timer framework
> > + **/
> > +static void __init xttcpss_timer_init(void)
> > +{
> > +	u32 shift;
> > +	u64 temp;
> > +
> > +	xttcpss_timer_hardware_init();
> > +
> > +	/* Calculate the nanoseconds to cycles divisor value for clock
source
> > +	 * timer */
> > +	for (shift = 16; shift > 0; shift--) {
> > +		temp = (u64) NSEC_PER_SEC << shift;
> > +		do_div(temp, CLOCK_TICK_RATE);
> > +		if ((temp >> 32) == 0)
> > +			break;
> > +	}
> > +
> > +	/* Setup clocksource */
> > +	clocksource_xttcpss.shift = shift;
> > +	clocksource_xttcpss.mult =
> > +		clocksource_hz2mult(CLOCK_TICK_RATE,
clocksource_xttcpss.shift);
> > +
> > +	if (clocksource_register(&clocksource_xttcpss))
> > +		printk(KERN_ERR "xttcpss_timer_init: can't register
clocksource"
> > +				" for %s\n", clocksource_xttcpss.name);
> 
> If you use clocksource_register_hz() then you don't need to worry
about
> calculating shift and mult, the generic framework will do that for
you.
> 

Yes, sounds easier.

> > +	/* Calculate the nanoseconds to cycles divisor value for clock
event
> > +	 * timer */
> > +	for (shift = 16; shift > 0; shift--) {
> > +		temp = (u64) CLOCK_TICK_RATE << shift;
> > +		do_div(temp, NSEC_PER_SEC);
> > +		if ((temp >> 32) == 0)
> > +			break;
> > +	}
> > +
> > +	/* Setup clockevent */
> > +	xttcpss_clockevent.shift = shift;
> > +	xttcpss_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
> > +
xttcpss_clockevent.shift);
> 
> clockevents_calc_mult_shift()?
> 

Yep, Russell mentioned these type of changes also. Thanks a lot for the
review Jamie. 

I Will try to get changes incorporated into a V2 of the patches.

-- John

> > +
> > +	xttcpss_clockevent.max_delta_ns =
> > +		clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
> > +	xttcpss_clockevent.min_delta_ns =
> > +		clockevent_delta2ns(1, &xttcpss_clockevent);
> > +
> > +	xttcpss_clockevent.cpumask = cpumask_of(0);
> > +	clockevents_register_device(&xttcpss_clockevent);
> > +}
> > +
> > +#ifdef CONFIG_PM
> > +/**
> > + * xttcpss_timer_suspend - Suspend the timer
> > + *
> > + * Disables all (clock source and clock event) the timers
> > + **/
> > +static void xttcpss_timer_suspend(void)
> > +{
> > +	struct xttcpss_timer *source_timer =
&timers[XTTCPSS_CLOCKSOURCE];
> > +	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
> > +	u32 ctrl_reg;
> > +
> > +	/* Disable clocksource timer */
> > +	ctrl_reg = xttcpss_read(source_timer->base_addr +
> > +				XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > +	xttcpss_write(source_timer->base_addr +
> > XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +
> > +	/* Disable clockevent timer */
> > +	ctrl_reg = xttcpss_read(event_timer->base_addr +
> > +				XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > +	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +}
> > +
> > +/**
> > + * xttcpss_timer_resume - Resume the timer
> > + *
> > + * Enables  all (clock source and clock event) the timers
> > + **/
> > +static void xttcpss_timer_resume(void)
> > +{
> > +	struct xttcpss_timer *source_timer =
&timers[XTTCPSS_CLOCKSOURCE];
> > +	struct xttcpss_timer *event_timer = &timers[XTTCPSS_CLOCKEVENT];
> > +	u32 ctrl_reg;
> > +
> > +	/* Enable clocksource timer */
> > +	ctrl_reg = xttcpss_read(source_timer->base_addr +
> > +				XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> > +	xttcpss_write(source_timer->base_addr +
> > XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +
> > +	/* Enable clockevent timer */
> > +	ctrl_reg = xttcpss_read(event_timer->base_addr +
> > +				XTTCPSS_CNT_CNTRL_OFFSET);
> > +	ctrl_reg &= XTTCPSS_CNT_CNTRL_ENABLE_MASK;
> > +	xttcpss_write(event_timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET,
> > +				ctrl_reg);
> > +}
> > +#else
> > +#define xttcpss_timer_suspend NULL
> > +#define xttcpss_timer_resume NULL
> > +#endif
> > +
> > +/*
> > + * Instantiate and initialize the system timer structure
> > + */
> > +struct sys_timer xttcpss_sys_timer = {
> > +	.init		= xttcpss_timer_init,
> > +	.suspend	= xttcpss_timer_suspend,
> > +	.resume		= xttcpss_timer_resume,
> > +};
> > --
> > 1.6.2.1
> >
> >
> >
> > 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.
> >
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
  2011-02-07 14:16           ` John Linn
@ 2011-02-07 14:58             ` Jamie Iles
  -1 siblings, 0 replies; 27+ messages in thread
From: Jamie Iles @ 2011-02-07 14:58 UTC (permalink / raw)
  To: John Linn
  Cc: Jamie Iles, linux-arm-kernel, linux-kernel, linux,
	catalin.marinas, glikely, Kiran Sutariya

On Mon, Feb 07, 2011 at 07:16:01AM -0700, John Linn wrote:
> > -----Original Message-----
> > From: Jamie Iles [mailto:jamie@jamieiles.com]
> > Sent: Saturday, February 05, 2011 6:04 PM
> > To: John Linn
> > Cc: linux-arm-kernel@lists.infradead.org;
> linux-kernel@vger.kernel.org; linux@arm.linux.org.uk;
> > catalin.marinas@arm.com; glikely@secretlab.ca; Kiran Sutariya
> > Subject: Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the
> platform
> > 
> > Hi John,
> > 
> > A couple more nitpicks.
> > 
> > Jamie
> > 
> > On Sat, Feb 05, 2011 at 09:17:16AM -0700, John Linn wrote:
> > > +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;
> > > +	u32 ctrl_reg;
> > > +
> > > +	/* Acknowledge the interrupt and call event handler */
> > > +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> > > +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> > > +
> > > +	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
> > > +
> > > +		/* Disable the counter as it would keep running. */
> > > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > > +					XTTCPSS_CNT_CNTRL_OFFSET);
> > > +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > 
> > The clock events framework should reprogram the next event so you
> don't
> > actually need to disable the timer here.  Once the event handler has
> > been called the timer will be reenabled with a new period, and as
> we're
> > running with interrupts disabled here we don't need to stop the timer.
> > 
> 
> What about if there's not another event to be started?

Then the clockevents code can set the mode to CLOCK_EVT_MODE_SHUTDOWN 
and this should disable the timer.  For NOHZ, AFAICT the 
clockevents/tick code will make sure that the next tick always falls 
within your max_delta_ns.

Jamie

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
@ 2011-02-07 14:58             ` Jamie Iles
  0 siblings, 0 replies; 27+ messages in thread
From: Jamie Iles @ 2011-02-07 14:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 07:16:01AM -0700, John Linn wrote:
> > -----Original Message-----
> > From: Jamie Iles [mailto:jamie at jamieiles.com]
> > Sent: Saturday, February 05, 2011 6:04 PM
> > To: John Linn
> > Cc: linux-arm-kernel at lists.infradead.org;
> linux-kernel at vger.kernel.org; linux at arm.linux.org.uk;
> > catalin.marinas at arm.com; glikely at secretlab.ca; Kiran Sutariya
> > Subject: Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the
> platform
> > 
> > Hi John,
> > 
> > A couple more nitpicks.
> > 
> > Jamie
> > 
> > On Sat, Feb 05, 2011 at 09:17:16AM -0700, John Linn wrote:
> > > +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;
> > > +	u32 ctrl_reg;
> > > +
> > > +	/* Acknowledge the interrupt and call event handler */
> > > +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> > > +		xttcpss_read(timer->base_addr + XTTCPSS_ISR_OFFSET));
> > > +
> > > +	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
> > > +
> > > +		/* Disable the counter as it would keep running. */
> > > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > > +					XTTCPSS_CNT_CNTRL_OFFSET);
> > > +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > 
> > The clock events framework should reprogram the next event so you
> don't
> > actually need to disable the timer here.  Once the event handler has
> > been called the timer will be reenabled with a new period, and as
> we're
> > running with interrupts disabled here we don't need to stop the timer.
> > 
> 
> What about if there's not another event to be started?

Then the clockevents code can set the mode to CLOCK_EVT_MODE_SHUTDOWN 
and this should disable the timer.  For NOHZ, AFAICT the 
clockevents/tick code will make sure that the next tick always falls 
within your max_delta_ns.

Jamie

^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
  2011-02-07 14:58             ` Jamie Iles
@ 2011-02-07 15:01               ` John Linn
  -1 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-07 15:01 UTC (permalink / raw)
  To: Jamie Iles
  Cc: linux-arm-kernel, linux-kernel, linux, catalin.marinas, glikely,
	Kiran Sutariya

> -----Original Message-----
> From: Jamie Iles [mailto:jamie@jamieiles.com]
> Sent: Monday, February 07, 2011 7:59 AM
> To: John Linn
> Cc: Jamie Iles; linux-arm-kernel@lists.infradead.org;
linux-kernel@vger.kernel.org;
> linux@arm.linux.org.uk; catalin.marinas@arm.com; glikely@secretlab.ca;
Kiran Sutariya
> Subject: Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the
platform
> 
> On Mon, Feb 07, 2011 at 07:16:01AM -0700, John Linn wrote:
> > > -----Original Message-----
> > > From: Jamie Iles [mailto:jamie@jamieiles.com]
> > > Sent: Saturday, February 05, 2011 6:04 PM
> > > To: John Linn
> > > Cc: linux-arm-kernel@lists.infradead.org;
> > linux-kernel@vger.kernel.org; linux@arm.linux.org.uk;
> > > catalin.marinas@arm.com; glikely@secretlab.ca; Kiran Sutariya
> > > Subject: Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the
> > platform
> > >
> > > Hi John,
> > >
> > > A couple more nitpicks.
> > >
> > > Jamie
> > >
> > > On Sat, Feb 05, 2011 at 09:17:16AM -0700, John Linn wrote:
> > > > +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;
> > > > +	u32 ctrl_reg;
> > > > +
> > > > +	/* Acknowledge the interrupt and call event handler */
> > > > +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> > > > +		xttcpss_read(timer->base_addr +
XTTCPSS_ISR_OFFSET));
> > > > +
> > > > +	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
> > > > +
> > > > +		/* Disable the counter as it would keep running.
*/
> > > > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > > > +
XTTCPSS_CNT_CNTRL_OFFSET);
> > > > +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > >
> > > The clock events framework should reprogram the next event so you
> > don't
> > > actually need to disable the timer here.  Once the event handler
has
> > > been called the timer will be reenabled with a new period, and as
> > we're
> > > running with interrupts disabled here we don't need to stop the
timer.
> > >
> >
> > What about if there's not another event to be started?
> 
> Then the clockevents code can set the mode to CLOCK_EVT_MODE_SHUTDOWN
> and this should disable the timer.  For NOHZ, AFAICT the
> clockevents/tick code will make sure that the next tick always falls
> within your max_delta_ns.
> 
> Jamie

Thanks, appreciate that help as I'm still learning more on the clock
mgmt.

Sounds good, I can stop it and test that.

-- John

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.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform
@ 2011-02-07 15:01               ` John Linn
  0 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-07 15:01 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Jamie Iles [mailto:jamie at jamieiles.com]
> Sent: Monday, February 07, 2011 7:59 AM
> To: John Linn
> Cc: Jamie Iles; linux-arm-kernel at lists.infradead.org;
linux-kernel at vger.kernel.org;
> linux at arm.linux.org.uk; catalin.marinas at arm.com; glikely at secretlab.ca;
Kiran Sutariya
> Subject: Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the
platform
> 
> On Mon, Feb 07, 2011 at 07:16:01AM -0700, John Linn wrote:
> > > -----Original Message-----
> > > From: Jamie Iles [mailto:jamie at jamieiles.com]
> > > Sent: Saturday, February 05, 2011 6:04 PM
> > > To: John Linn
> > > Cc: linux-arm-kernel at lists.infradead.org;
> > linux-kernel at vger.kernel.org; linux at arm.linux.org.uk;
> > > catalin.marinas at arm.com; glikely at secretlab.ca; Kiran Sutariya
> > > Subject: Re: [PATCH 3/4] ARM: Xilinx: Adding timer support to the
> > platform
> > >
> > > Hi John,
> > >
> > > A couple more nitpicks.
> > >
> > > Jamie
> > >
> > > On Sat, Feb 05, 2011 at 09:17:16AM -0700, John Linn wrote:
> > > > +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;
> > > > +	u32 ctrl_reg;
> > > > +
> > > > +	/* Acknowledge the interrupt and call event handler */
> > > > +	xttcpss_write(timer->base_addr + XTTCPSS_ISR_OFFSET,
> > > > +		xttcpss_read(timer->base_addr +
XTTCPSS_ISR_OFFSET));
> > > > +
> > > > +	if (timer->mode == CLOCK_EVT_MODE_ONESHOT) {
> > > > +
> > > > +		/* Disable the counter as it would keep running.
*/
> > > > +		ctrl_reg = xttcpss_read(timer->base_addr +
> > > > +
XTTCPSS_CNT_CNTRL_OFFSET);
> > > > +		ctrl_reg |= ~(XTTCPSS_CNT_CNTRL_ENABLE_MASK);
> > >
> > > The clock events framework should reprogram the next event so you
> > don't
> > > actually need to disable the timer here.  Once the event handler
has
> > > been called the timer will be reenabled with a new period, and as
> > we're
> > > running with interrupts disabled here we don't need to stop the
timer.
> > >
> >
> > What about if there's not another event to be started?
> 
> Then the clockevents code can set the mode to CLOCK_EVT_MODE_SHUTDOWN
> and this should disable the timer.  For NOHZ, AFAICT the
> clockevents/tick code will make sure that the next tick always falls
> within your max_delta_ns.
> 
> Jamie

Thanks, appreciate that help as I'm still learning more on the clock
mgmt.

Sounds good, I can stop it and test that.

-- John

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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
  2011-02-07 20:54         ` Russell King - ARM Linux
@ 2011-02-07 20:55           ` John Linn
  0 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-07 20:55 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
> Sent: Monday, February 07, 2011 1:54 PM
> To: John Linn
> Cc: linux-arm-kernel at lists.infradead.org; kernel at vger.kernel.org;
catalin.marinas at arm.com;
> glikely at secretlab.ca
> Subject: Re: [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
> 
> On Mon, Feb 07, 2011 at 08:44:11AM -0700, John Linn wrote:
> > It's interesting as I'm looking at this further.  Sure enough it
looks
> > to me like any early mappings in the MMU get destroyed.  Paging_init
calls
> > devicemaps_init which says
> > it destroys the early debug mappings.  Maybe I'm misinterpreting
that?
> 
> I don't think so.  Normally, platforms end up mapping it as part of a
> larger mappign.  If you don't have that then it'll be necessary.

Thanks, appreciate the feedback. Makes sense.

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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
  2011-02-07 15:44       ` John Linn
@ 2011-02-07 20:54         ` Russell King - ARM Linux
  2011-02-07 20:55           ` John Linn
  0 siblings, 1 reply; 27+ messages in thread
From: Russell King - ARM Linux @ 2011-02-07 20:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 08:44:11AM -0700, John Linn wrote:
> It's interesting as I'm looking at this further.  Sure enough it looks
> to me like any early mappings in the MMU get destroyed.  Paging_init calls
> devicemaps_init which says 
> it destroys the early debug mappings.  Maybe I'm misinterpreting that?

I don't think so.  Normally, platforms end up mapping it as part of a
larger mappign.  If you don't have that then it'll be necessary.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
  2011-02-05 16:18     ` Russell King - ARM Linux
  2011-02-05 16:21       ` John Linn
  2011-02-05 17:25       ` John Linn
@ 2011-02-07 15:44       ` John Linn
  2011-02-07 20:54         ` Russell King - ARM Linux
  2 siblings, 1 reply; 27+ messages in thread
From: John Linn @ 2011-02-07 15:44 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
> Sent: Saturday, February 05, 2011 9:19 AM
> To: John Linn
> Cc: linux-arm-kernel at lists.infradead.org; kernel at vger.kernel.org;
catalin.marinas at arm.com;
> glikely at secretlab.ca
> Subject: Re: [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
> 
> On Sat, Feb 05, 2011 at 09:08:42AM -0700, John Linn wrote:
> > +void __init irq_init(void)
> > +{
> > +	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
> 
> Just pass this address into gic_init - there's no need to initialize
> this variable yourself anymore.
> 
> > +	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE,
gic_cpu_base_addr);
> ...
> > +static struct map_desc io_desc[] __initdata = {
> ...
> > +#ifdef CONFIG_DEBUG_LL
> > +	{
> > +		.virtual	= UART0_BASE,
> > +		.pfn		= __phys_to_pfn(UART0_BASE),
> > +		.length		= SZ_4K,
> > +		.type		= MT_DEVICE,
> > +	},
> > +#endif
> 
> You shouldn't need to do this if your addruart macro in
mach/debug-macros.S
> is correctly returning the virtual and physical addresses in rp and
rv.

Hi Russell,

It's interesting as I'm looking at this further.  Sure enough it looks
to me like any 
early mappings in the MMU get destroyed.  Paging_init calls
devicemaps_init which says 
it destroys the early debug mappings.  Maybe I'm misinterpreting that?

I notice that the mach-tegra platform does have a mapping in the table
for iotable_init
but it's not conditional on the DEBUG_LL and it covers the APB which
includes the UART 
for early debug.

Sorry for my slowness, but it still seems like the early MMU mappings go
away. What am I 
not seeing that I should be?

Thanks, appreciate your patience and help
John




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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
  2011-02-05 16:18     ` Russell King - ARM Linux
  2011-02-05 16:21       ` John Linn
@ 2011-02-05 17:25       ` John Linn
  2011-02-07 15:44       ` John Linn
  2 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 17:25 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
> Sent: Saturday, February 05, 2011 9:19 AM
> To: John Linn
> Cc: linux-arm-kernel at lists.infradead.org; kernel at vger.kernel.org;
catalin.marinas at arm.com;
> glikely at secretlab.ca
> Subject: Re: [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
> 
> On Sat, Feb 05, 2011 at 09:08:42AM -0700, John Linn wrote:
> > +void __init irq_init(void)
> > +{
> > +	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
> 
> Just pass this address into gic_init - there's no need to initialize
> this variable yourself anymore.
> 
> > +	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE,
gic_cpu_base_addr);
> ...
> > +static struct map_desc io_desc[] __initdata = {
> ...
> > +#ifdef CONFIG_DEBUG_LL
> > +	{
> > +		.virtual	= UART0_BASE,
> > +		.pfn		= __phys_to_pfn(UART0_BASE),
> > +		.length		= SZ_4K,
> > +		.type		= MT_DEVICE,
> > +	},
> > +#endif
> 
> You shouldn't need to do this if your addruart macro in
mach/debug-macros.S
> is correctly returning the virtual and physical addresses in rp and
rv.

I'm sure there's something I'm overlooking here.

I'm seeing that when I remove that I get I/O just for a bit, then it
stops. I think
that means my addruart macro is working correctly.
 
I know the UART gets an early mapping in the MMU in head.S.  But does
that mapping
stay when the map_io function is ran?  

Thanks,
John

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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
  2011-02-05 16:18     ` Russell King - ARM Linux
@ 2011-02-05 16:21       ` John Linn
  2011-02-05 17:25       ` John Linn
  2011-02-07 15:44       ` John Linn
  2 siblings, 0 replies; 27+ messages in thread
From: John Linn @ 2011-02-05 16:21 UTC (permalink / raw)
  To: linux-arm-kernel

> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
> Sent: Saturday, February 05, 2011 9:19 AM
> To: John Linn
> Cc: linux-arm-kernel at lists.infradead.org; kernel at vger.kernel.org;
catalin.marinas at arm.com;
> glikely at secretlab.ca
> Subject: Re: [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
> 
> On Sat, Feb 05, 2011 at 09:08:42AM -0700, John Linn wrote:
> > +void __init irq_init(void)
> > +{
> > +	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
> 
> Just pass this address into gic_init - there's no need to initialize
> this variable yourself anymore.

Ok, easy fix.

> 
> > +	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE,
gic_cpu_base_addr);
> ...
> > +static struct map_desc io_desc[] __initdata = {
> ...
> > +#ifdef CONFIG_DEBUG_LL
> > +	{
> > +		.virtual	= UART0_BASE,
> > +		.pfn		= __phys_to_pfn(UART0_BASE),
> > +		.length		= SZ_4K,
> > +		.type		= MT_DEVICE,
> > +	},
> > +#endif
> 
> You shouldn't need to do this if your addruart macro in
mach/debug-macros.S
> is correctly returning the virtual and physical addresses in rp and
rv.

Ok, will check that and make sure.

Thanks,
John

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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
  2011-02-05 16:08   ` [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support John Linn
@ 2011-02-05 16:18     ` Russell King - ARM Linux
  2011-02-05 16:21       ` John Linn
                         ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Russell King - ARM Linux @ 2011-02-05 16:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Feb 05, 2011 at 09:08:42AM -0700, John Linn wrote:
> +void __init irq_init(void)
> +{
> +	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;

Just pass this address into gic_init - there's no need to initialize
this variable yourself anymore.

> +	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE, gic_cpu_base_addr);
...
> +static struct map_desc io_desc[] __initdata = {
...
> +#ifdef CONFIG_DEBUG_LL
> +	{
> +		.virtual	= UART0_BASE,
> +		.pfn		= __phys_to_pfn(UART0_BASE),
> +		.length		= SZ_4K,
> +		.type		= MT_DEVICE,
> +	},
> +#endif

You shouldn't need to do this if your addruart macro in mach/debug-macros.S
is correctly returning the virtual and physical addresses in rp and rv.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support
       [not found] ` <1296922124-23379-2-git-send-email-john.linn@xilinx.com>
@ 2011-02-05 16:08   ` John Linn
  2011-02-05 16:18     ` Russell King - ARM Linux
  0 siblings, 1 reply; 27+ messages in thread
From: John Linn @ 2011-02-05 16:08 UTC (permalink / raw)
  To: linux-arm-kernel

The 1st board support is minimal to get a system up and running
on the Xilinx platform.

Signed-off-by: John Linn <john.linn@xilinx.com>
---
 arch/arm/mach-xilinx/Kconfig       |   14 ++++
 arch/arm/mach-xilinx/Makefile      |    6 ++
 arch/arm/mach-xilinx/Makefile.boot |    3 +
 arch/arm/mach-xilinx/board_ep107.c |   81 ++++++++++++++++++++++
 arch/arm/mach-xilinx/common.c      |  132 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-xilinx/common.h      |   32 +++++++++
 6 files changed, 268 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-xilinx/Kconfig
 create mode 100644 arch/arm/mach-xilinx/Makefile
 create mode 100644 arch/arm/mach-xilinx/Makefile.boot
 create mode 100644 arch/arm/mach-xilinx/board_ep107.c
 create mode 100644 arch/arm/mach-xilinx/common.c
 create mode 100644 arch/arm/mach-xilinx/common.h

diff --git a/arch/arm/mach-xilinx/Kconfig b/arch/arm/mach-xilinx/Kconfig
new file mode 100644
index 0000000..11f9e65
--- /dev/null
+++ b/arch/arm/mach-xilinx/Kconfig
@@ -0,0 +1,14 @@
+if ARCH_XILINX
+
+choice
+        prompt "Board Selection"
+	default XILINX_EP107
+
+config XILINX_EP107
+	bool "Xilinx EP107 Board"
+	help
+	  Select if you are using a Xilinx EP107 board.
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-xilinx/Makefile b/arch/arm/mach-xilinx/Makefile
new file mode 100644
index 0000000..194f9e4
--- /dev/null
+++ b/arch/arm/mach-xilinx/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := common.o board_ep107.o timer.o
diff --git a/arch/arm/mach-xilinx/Makefile.boot b/arch/arm/mach-xilinx/Makefile.boot
new file mode 100644
index 0000000..67039c3
--- /dev/null
+++ b/arch/arm/mach-xilinx/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x00800000
diff --git a/arch/arm/mach-xilinx/board_ep107.c b/arch/arm/mach-xilinx/board_ep107.c
new file mode 100644
index 0000000..233e744
--- /dev/null
+++ b/arch/arm/mach-xilinx/board_ep107.c
@@ -0,0 +1,81 @@
+/* arch/arm/mach-xilinx/board_ep107.c
+ *
+ * This file contains code specific to the Xilinx EP107 board.
+ *
+ *  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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/hardware.h>
+#include <linux/clkdev.h>
+#include "common.h"
+
+/*
+ * Fixed clocks for now
+ */
+
+static struct clk ref50_clk = {
+	.rate	= 50000000,
+};
+
+/* Create all the platform devices for the board */
+
+static struct resource uart0[] = {
+	{
+		.start = UART0_BASE,
+		.end = UART0_BASE + 0xFFF,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_UART0,
+		.end = IRQ_UART0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device uart_device0 = {
+	.name = "xuartpss",
+	.id = 0,
+	.dev = {
+		.platform_data = &ref50_clk.rate,
+	},
+	.resource = uart0,
+	.num_resources = ARRAY_SIZE(uart0),
+};
+
+static struct platform_device *xilinx_pdevices[] __initdata = {
+	&uart_device0,
+};
+
+/**
+ * board_ep107_init - Board specific initialization for the Xilinx EP107 board.
+ *
+ **/
+static void __init board_ep107_init(void)
+{
+	system_init();
+	platform_device_init(xilinx_pdevices, ARRAY_SIZE(xilinx_pdevices));
+}
+
+MACHINE_START(XILINX_EP107, "Xilinx EP107")
+	.boot_params    = PHYS_OFFSET + 0x00000100,
+	.map_io         = map_io,
+	.init_irq       = irq_init,
+	.init_machine   = board_ep107_init,
+	.timer          = &xttcpss_sys_timer,
+MACHINE_END
diff --git a/arch/arm/mach-xilinx/common.c b/arch/arm/mach-xilinx/common.c
new file mode 100644
index 0000000..f7c51a7
--- /dev/null
+++ b/arch/arm/mach-xilinx/common.c
@@ -0,0 +1,132 @@
+/* arch/arm/mach-xilinx/common.c
+ *
+ * This file contains common code that is intended to be used across
+ * boards so that it's not replicated.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm/mach/map.h>
+#include <asm/page.h>
+#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/hardware.h>
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+}
+
+/**
+ * system_init - System specific initialization, intended to be called from
+ *			board specific initialization.
+ *
+ **/
+void __init system_init(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+	void *l2cache_base = (void *)PL310_L2CC_BASE;
+
+	/*
+	 * 64KB way size, 8-way associativity, parity disabled
+	 */
+	l2x0_init(l2cache_base, 0x02060000, 0xF0F0FFFF);
+#endif
+}
+
+/**
+ * irq_init - Interrupt controller initialization for the GIC.
+ *
+ **/
+void __init irq_init(void)
+{
+	gic_cpu_base_addr = (void __iomem *)SCU_GIC_CPU_BASE;
+	gic_init(0, 29, (void __iomem *)SCU_GIC_DIST_BASE, gic_cpu_base_addr);
+}
+
+/* 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_BASE,
+		.pfn		= __phys_to_pfn(TTC0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= SCU_PERIPH_BASE,
+		.pfn		= __phys_to_pfn(SCU_PERIPH_BASE),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= PL310_L2CC_BASE,
+		.pfn		= __phys_to_pfn(PL310_L2CC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+
+#ifdef CONFIG_DEBUG_LL
+	{
+		.virtual	= UART0_BASE,
+		.pfn		= __phys_to_pfn(UART0_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+#endif
+
+};
+
+/**
+ * map_io - Create memory mappings needed for early I/O.
+ *
+ **/
+void __init map_io(void)
+{
+	iotable_init(io_desc, ARRAY_SIZE(io_desc));
+}
+
+/**
+ * platform_device_init - Initialize all the platform devices.
+ *
+ **/
+void __init platform_device_init(struct platform_device *xilinx_pdevices[],
+					int count)
+{
+	int ret, i;
+
+	/* Initialize all the platform devices */
+
+	for (i = 0; i < count; i++) {
+
+		pr_info("registering platform device '%s' id %d\n",
+			xilinx_pdevices[i]->name,
+			xilinx_pdevices[i]->id);
+
+		ret = platform_device_register(xilinx_pdevices[i]);
+		if (ret)
+			pr_info("Unable to register platform device '%s': %d\n",
+				xilinx_pdevices[i]->name, ret);
+	}
+}
+
diff --git a/arch/arm/mach-xilinx/common.h b/arch/arm/mach-xilinx/common.h
new file mode 100644
index 0000000..49de295
--- /dev/null
+++ b/arch/arm/mach-xilinx/common.h
@@ -0,0 +1,32 @@
+/* arch/arm/mach-xilinx/common.h
+ *
+ * This file contains common function prototypes to avoid externs
+ * in the c files.
+ *
+ *  Copyright (C) 2011 Xilinx
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __MACH_XILINX_COMMON_H__
+#define __MACH_XILINX_COMMON_H__
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+void __init system_init(void);
+void __init irq_init(void);
+void __init map_io(void);
+void __init platform_device_init(struct platform_device *pdevices[],
+					int count);
+
+extern struct sys_timer xttcpss_sys_timer;
+
+#endif
-- 
1.6.2.1



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.

^ permalink raw reply related	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2011-02-07 20:55 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1296922637-24662-1-git-send-email-john.linn@xilinx.com>
2011-02-05 16:17 ` [PATCH 1/4] ARM: Xilinx: Adding Xilinx platform infrastructure support John Linn
2011-02-05 16:17   ` John Linn
     [not found] ` <1296922637-24662-2-git-send-email-john.linn@xilinx.com>
2011-02-05 16:17   ` [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support John Linn
2011-02-05 16:17     ` John Linn
2011-02-06  0:45     ` Jamie Iles
2011-02-06  0:45       ` Jamie Iles
2011-02-07 14:05       ` John Linn
2011-02-07 14:05         ` John Linn
     [not found]   ` <1296922637-24662-3-git-send-email-john.linn@xilinx.com>
2011-02-05 16:17     ` [PATCH 3/4] ARM: Xilinx: Adding timer support to the platform John Linn
2011-02-05 16:17       ` John Linn
2011-02-06  1:03       ` Jamie Iles
2011-02-06  1:03         ` Jamie Iles
2011-02-07 14:16         ` John Linn
2011-02-07 14:16           ` John Linn
2011-02-07 14:58           ` Jamie Iles
2011-02-07 14:58             ` Jamie Iles
2011-02-07 15:01             ` John Linn
2011-02-07 15:01               ` John Linn
     [not found]     ` <1296922637-24662-4-git-send-email-john.linn@xilinx.com>
2011-02-05 16:17       ` [PATCH 4/4] ARM: Xilinx: base header files and assembly macros John Linn
2011-02-05 16:17         ` John Linn
     [not found] <1296922124-23379-1-git-send-email-john.linn@xilinx.com>
     [not found] ` <1296922124-23379-2-git-send-email-john.linn@xilinx.com>
2011-02-05 16:08   ` [PATCH 2/4] ARM: Xilinx: Adding Xilinx board support John Linn
2011-02-05 16:18     ` Russell King - ARM Linux
2011-02-05 16:21       ` John Linn
2011-02-05 17:25       ` John Linn
2011-02-07 15:44       ` John Linn
2011-02-07 20:54         ` Russell King - ARM Linux
2011-02-07 20:55           ` John Linn

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.