linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] ARM: Exynos: Enable device tree support for MCT controller
@ 2012-11-03 14:45 Thomas Abraham
  2012-11-03 14:45 ` [PATCH 1/5] ARM: Exynos: add a register base address variable in mct controller driver Thomas Abraham
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Thomas Abraham @ 2012-11-03 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series adds device tree support for Exynos4/5 MCT controller. This
series depends on the device tree and smp support patches for Exynos4x12 posted
by Tomasz Figa. This patch series has been tested on Exynos4210 based Origen
board, Exynos4412 based SMDK board and Exynos5250 based SMDK board.

Thomas Abraham (5):
  ARM: Exynos: add a register base address variable in mct controller driver
  ARM: Exynos: prepare an array of MCT interrupt numbers and use it
  ARM: Exynos: add device tree support for MCT controller driver
  ARM: Exynos: remove static io-remapping of mct registers for Exynos5
  ARM: dts: add mct device tree node for all supported Exynos SoC's

 .../bindings/timer/samsung,exynos4210-mct.txt      |   70 ++++++++
 arch/arm/boot/dts/exynos4210.dtsi                  |    8 +
 arch/arm/boot/dts/exynos4212.dtsi                  |   10 +
 arch/arm/boot/dts/exynos4412.dtsi                  |    8 +
 arch/arm/boot/dts/exynos5250.dtsi                  |   21 +++
 arch/arm/mach-exynos/common.c                      |    5 -
 arch/arm/mach-exynos/include/mach/irqs.h           |    6 -
 arch/arm/mach-exynos/include/mach/map.h            |    1 -
 arch/arm/mach-exynos/include/mach/regs-mct.h       |   53 ------
 arch/arm/mach-exynos/mct.c                         |  176 +++++++++++++-------
 10 files changed, 234 insertions(+), 124 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
 delete mode 100644 arch/arm/mach-exynos/include/mach/regs-mct.h

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

* [PATCH 1/5] ARM: Exynos: add a register base address variable in mct controller driver
  2012-11-03 14:45 [PATCH 0/5] ARM: Exynos: Enable device tree support for MCT controller Thomas Abraham
@ 2012-11-03 14:45 ` Thomas Abraham
  2012-11-03 14:45 ` [PATCH 2/5] ARM: Exynos: prepare an array of MCT interrupt numbers and use it Thomas Abraham
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Thomas Abraham @ 2012-11-03 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

All the MCT register read/writes use a fixed remapped address S5P_VA_SYSTIMER.
With device tree support for MCT controller, it is possible to remove the
static remap of the MCT controller address space and do the remap during the
initialization of the MCT controller with the physical address obtained from
the device tree.

So in preparation of adding device tree support for MCT controller, add a new
register base address variable that will hold the remapped MCT controller base
address and convert all MCT register read/writes to use this new variable as
the base address instead of the fixed S5P_VA_SYSTIMER.

While at it, the MCT register offset and bit mask definitions are moved into
the MCT controller driver file since there are no other consumers of these
definitions.

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/include/mach/regs-mct.h |   53 --------------
 arch/arm/mach-exynos/mct.c                   |   97 ++++++++++++++++---------
 2 files changed, 62 insertions(+), 88 deletions(-)
 delete mode 100644 arch/arm/mach-exynos/include/mach/regs-mct.h

diff --git a/arch/arm/mach-exynos/include/mach/regs-mct.h b/arch/arm/mach-exynos/include/mach/regs-mct.h
deleted file mode 100644
index 80dd02a..0000000
--- a/arch/arm/mach-exynos/include/mach/regs-mct.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* arch/arm/mach-exynos4/include/mach/regs-mct.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 MCT configutation
- *
- * 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.
-*/
-
-#ifndef __ASM_ARCH_REGS_MCT_H
-#define __ASM_ARCH_REGS_MCT_H __FILE__
-
-#include <mach/map.h>
-
-#define EXYNOS4_MCTREG(x)		(S5P_VA_SYSTIMER + (x))
-
-#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
-#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
-#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
-
-#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
-#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
-#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
-
-#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
-
-#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
-#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
-#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
-
-#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
-#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
-#define EXYNOS4_MCT_L_MASK		(0xffffff00)
-
-#define MCT_L_TCNTB_OFFSET		(0x00)
-#define MCT_L_ICNTB_OFFSET		(0x08)
-#define MCT_L_TCON_OFFSET		(0x20)
-#define MCT_L_INT_CSTAT_OFFSET		(0x30)
-#define MCT_L_INT_ENB_OFFSET		(0x34)
-#define MCT_L_WSTAT_OFFSET		(0x40)
-
-#define MCT_G_TCON_START		(1 << 8)
-#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
-#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
-
-#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
-#define MCT_L_TCON_INT_START		(1 << 1)
-#define MCT_L_TCON_TIMER_START		(1 << 0)
-
-#endif /* __ASM_ARCH_REGS_MCT_H */
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index b601fb8..c3c4799 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -27,9 +27,36 @@
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-#include <mach/regs-mct.h>
 #include <asm/mach/time.h>
 
+#define EXYNOS4_MCTREG(x)		(x)
+#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
+#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
+#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
+#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
+#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
+#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
+#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
+#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
+#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
+#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
+#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
+#define EXYNOS4_MCT_L_MASK		(0xffffff00)
+
+#define MCT_L_TCNTB_OFFSET		(0x00)
+#define MCT_L_ICNTB_OFFSET		(0x08)
+#define MCT_L_TCON_OFFSET		(0x20)
+#define MCT_L_INT_CSTAT_OFFSET		(0x30)
+#define MCT_L_INT_ENB_OFFSET		(0x34)
+#define MCT_L_WSTAT_OFFSET		(0x40)
+#define MCT_G_TCON_START		(1 << 8)
+#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
+#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
+#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
+#define MCT_L_TCON_INT_START		(1 << 1)
+#define MCT_L_TCON_TIMER_START		(1 << 0)
+
 #define TICK_BASE_CNT	1
 
 enum {
@@ -37,64 +64,62 @@ enum {
 	MCT_INT_PPI
 };
 
+static void __iomem *reg_base;
 static unsigned long clk_rate;
 static unsigned int mct_int_type;
 
 struct mct_clock_event_device {
 	struct clock_event_device *evt;
-	void __iomem *base;
+	unsigned long base;
 	char name[10];
 };
 
-static void exynos4_mct_write(unsigned int value, void *addr)
+static void exynos4_mct_write(unsigned int value, unsigned long offset)
 {
-	void __iomem *stat_addr;
+	unsigned long stat_addr;
 	u32 mask;
 	u32 i;
 
-	__raw_writel(value, addr);
+	__raw_writel(value, reg_base + offset);
 
-	if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
-		u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
-		switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
-		case (u32) MCT_L_TCON_OFFSET:
-			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+	if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
+		stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
+		switch (offset & EXYNOS4_MCT_L_MASK) {
+		case MCT_L_TCON_OFFSET:
 			mask = 1 << 3;		/* L_TCON write status */
 			break;
-		case (u32) MCT_L_ICNTB_OFFSET:
-			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+		case MCT_L_ICNTB_OFFSET:
 			mask = 1 << 1;		/* L_ICNTB write status */
 			break;
-		case (u32) MCT_L_TCNTB_OFFSET:
-			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+		case MCT_L_TCNTB_OFFSET:
 			mask = 1 << 0;		/* L_TCNTB write status */
 			break;
 		default:
 			return;
 		}
 	} else {
-		switch ((u32) addr) {
-		case (u32) EXYNOS4_MCT_G_TCON:
+		switch (offset) {
+		case EXYNOS4_MCT_G_TCON:
 			stat_addr = EXYNOS4_MCT_G_WSTAT;
 			mask = 1 << 16;		/* G_TCON write status */
 			break;
-		case (u32) EXYNOS4_MCT_G_COMP0_L:
+		case EXYNOS4_MCT_G_COMP0_L:
 			stat_addr = EXYNOS4_MCT_G_WSTAT;
 			mask = 1 << 0;		/* G_COMP0_L write status */
 			break;
-		case (u32) EXYNOS4_MCT_G_COMP0_U:
+		case EXYNOS4_MCT_G_COMP0_U:
 			stat_addr = EXYNOS4_MCT_G_WSTAT;
 			mask = 1 << 1;		/* G_COMP0_U write status */
 			break;
-		case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
+		case EXYNOS4_MCT_G_COMP0_ADD_INCR:
 			stat_addr = EXYNOS4_MCT_G_WSTAT;
 			mask = 1 << 2;		/* G_COMP0_ADD_INCR w status */
 			break;
-		case (u32) EXYNOS4_MCT_G_CNT_L:
+		case EXYNOS4_MCT_G_CNT_L:
 			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 			mask = 1 << 0;		/* G_CNT_L write status */
 			break;
-		case (u32) EXYNOS4_MCT_G_CNT_U:
+		case EXYNOS4_MCT_G_CNT_U:
 			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 			mask = 1 << 1;		/* G_CNT_U write status */
 			break;
@@ -105,12 +130,12 @@ static void exynos4_mct_write(unsigned int value, void *addr)
 
 	/* Wait maximum 1 ms until written values are applied */
 	for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
-		if (__raw_readl(stat_addr) & mask) {
-			__raw_writel(mask, stat_addr);
+		if (__raw_readl(reg_base + stat_addr) & mask) {
+			__raw_writel(mask, reg_base + stat_addr);
 			return;
 		}
 
-	panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
+	panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset);
 }
 
 /* Clocksource handling */
@@ -121,7 +146,7 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
 	exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
 	exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
 
-	reg = __raw_readl(EXYNOS4_MCT_G_TCON);
+	reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 	reg |= MCT_G_TCON_START;
 	exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
 }
@@ -129,12 +154,12 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
 static cycle_t exynos4_frc_read(struct clocksource *cs)
 {
 	unsigned int lo, hi;
-	u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+	u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
 
 	do {
 		hi = hi2;
-		lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
-		hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+		lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L);
+		hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
 	} while (hi != hi2);
 
 	return ((cycle_t)hi << 32) | lo;
@@ -166,7 +191,7 @@ static void exynos4_mct_comp0_stop(void)
 {
 	unsigned int tcon;
 
-	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+	tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 	tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
 
 	exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
@@ -179,7 +204,7 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode,
 	unsigned int tcon;
 	cycle_t comp_cycle;
 
-	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+	tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 
 	if (mode == CLOCK_EVT_MODE_PERIODIC) {
 		tcon |= MCT_G_TCON_COMP0_AUTO_INC;
@@ -276,12 +301,12 @@ static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
 {
 	unsigned long tmp;
 	unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
-	void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
+	unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
 
-	tmp = __raw_readl(addr);
+	tmp = __raw_readl(reg_base + offset);
 	if (tmp & mask) {
 		tmp &= ~mask;
-		exynos4_mct_write(tmp, addr);
+		exynos4_mct_write(tmp, offset);
 	}
 }
 
@@ -300,7 +325,7 @@ static void exynos4_mct_tick_start(unsigned long cycles,
 	/* enable MCT tick interrupt */
 	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
 
-	tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
+	tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET);
 	tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
 	       MCT_L_TCON_INTERVAL_MODE;
 	exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
@@ -352,7 +377,7 @@ static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
 		exynos4_mct_tick_stop(mevt);
 
 	/* Clear the MCT tick interrupt */
-	if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+	if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
 		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
 		return 1;
 	} else {
@@ -461,6 +486,8 @@ static void __init exynos4_timer_resources(void)
 
 	clk_rate = clk_get_rate(mct_clk);
 
+	reg_base = S5P_VA_SYSTIMER;
+
 #ifdef CONFIG_LOCAL_TIMERS
 	if (mct_int_type == MCT_INT_PPI) {
 		int err;
-- 
1.6.6.rc2

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

* [PATCH 2/5] ARM: Exynos: prepare an array of MCT interrupt numbers and use it
  2012-11-03 14:45 [PATCH 0/5] ARM: Exynos: Enable device tree support for MCT controller Thomas Abraham
  2012-11-03 14:45 ` [PATCH 1/5] ARM: Exynos: add a register base address variable in mct controller driver Thomas Abraham
@ 2012-11-03 14:45 ` Thomas Abraham
  2012-11-03 14:45 ` [PATCH 3/5] ARM: Exynos: add device tree support for MCT controller driver Thomas Abraham
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Thomas Abraham @ 2012-11-03 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

Instead of using soc_is_xxx macro at more than one place in the MCT
controller driver to decide the MCT interrpt number to be setup, populate
a table of known MCT global and local timer interrupts and use the values
in table to setup the MCT interrupts.

This also helps in adding device tree support for MCT controller driver by
allowing the driver to retrieve interrupt numbers from device tree and
populating them into this table, thereby supporting both legacy and dt
functionality to co-exist.

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/mct.c |   57 +++++++++++++++++++++++++++----------------
 1 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index c3c4799..d65d0c7 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -64,9 +64,22 @@ enum {
 	MCT_INT_PPI
 };
 
+enum {
+	MCT_G0_IRQ,
+	MCT_G1_IRQ,
+	MCT_G2_IRQ,
+	MCT_G3_IRQ,
+	MCT_L0_IRQ,
+	MCT_L1_IRQ,
+	MCT_L2_IRQ,
+	MCT_L3_IRQ,
+	MCT_NR_IRQS,
+};
+
 static void __iomem *reg_base;
 static unsigned long clk_rate;
 static unsigned int mct_int_type;
+static int mct_irqs[MCT_NR_IRQS];
 
 struct mct_clock_event_device {
 	struct clock_event_device *evt;
@@ -285,11 +298,7 @@ static void exynos4_clockevent_init(void)
 		clockevent_delta2ns(0xf, &mct_comp_device);
 	mct_comp_device.cpumask = cpumask_of(0);
 	clockevents_register_device(&mct_comp_device);
-
-	if (soc_is_exynos5250())
-		setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq);
-	else
-		setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq);
+	setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq);
 }
 
 #ifdef CONFIG_LOCAL_TIMERS
@@ -413,7 +422,6 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
 {
 	struct mct_clock_event_device *mevt;
 	unsigned int cpu = smp_processor_id();
-	int mct_lx_irq;
 
 	mevt = this_cpu_ptr(&percpu_mct_tick);
 	mevt->evt = evt;
@@ -440,21 +448,17 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
 
 	if (mct_int_type == MCT_INT_SPI) {
 		if (cpu == 0) {
-			mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L0 :
-						EXYNOS5_IRQ_MCT_L0;
 			mct_tick0_event_irq.dev_id = mevt;
-			evt->irq = mct_lx_irq;
-			setup_irq(mct_lx_irq, &mct_tick0_event_irq);
+			evt->irq = mct_irqs[MCT_L0_IRQ];
+			setup_irq(evt->irq, &mct_tick0_event_irq);
 		} else {
-			mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L1 :
-						EXYNOS5_IRQ_MCT_L1;
 			mct_tick1_event_irq.dev_id = mevt;
-			evt->irq = mct_lx_irq;
-			setup_irq(mct_lx_irq, &mct_tick1_event_irq);
-			irq_set_affinity(mct_lx_irq, cpumask_of(1));
+			evt->irq = mct_irqs[MCT_L1_IRQ];
+			setup_irq(evt->irq, &mct_tick1_event_irq);
+			irq_set_affinity(evt->irq, cpumask_of(1));
 		}
 	} else {
-		enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0);
+		enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
 	}
 
 	return 0;
@@ -470,7 +474,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
 		else
 			remove_irq(evt->irq, &mct_tick1_event_irq);
 	else
-		disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER);
+		disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
 }
 
 static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
@@ -492,11 +496,11 @@ static void __init exynos4_timer_resources(void)
 	if (mct_int_type == MCT_INT_PPI) {
 		int err;
 
-		err = request_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER,
+		err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
 					 exynos4_mct_tick_isr, "MCT",
 					 &percpu_mct_tick);
 		WARN(err, "MCT: can't request IRQ %d (%d)\n",
-		     EXYNOS_IRQ_MCT_LOCALTIMER, err);
+		     mct_irqs[MCT_L0_IRQ], err);
 	}
 
 	local_timer_register(&exynos4_mct_tick_ops);
@@ -505,10 +509,21 @@ static void __init exynos4_timer_resources(void)
 
 static void __init exynos4_timer_init(void)
 {
-	if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
+	if (soc_is_exynos4210()) {
+		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
+		mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0;
+		mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1;
 		mct_int_type = MCT_INT_SPI;
-	else
+	} else if (soc_is_exynos5250()) {
+		mct_irqs[MCT_G0_IRQ] = EXYNOS5_IRQ_MCT_G0;
+		mct_irqs[MCT_L0_IRQ] = EXYNOS5_IRQ_MCT_L0;
+		mct_irqs[MCT_L1_IRQ] = EXYNOS5_IRQ_MCT_L1;
+		mct_int_type = MCT_INT_SPI;
+	} else {
+		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
+		mct_irqs[MCT_L0_IRQ] = EXYNOS_IRQ_MCT_LOCALTIMER;
 		mct_int_type = MCT_INT_PPI;
+	}
 
 	exynos4_timer_resources();
 	exynos4_clocksource_init();
-- 
1.6.6.rc2

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

* [PATCH 3/5] ARM: Exynos: add device tree support for MCT controller driver
  2012-11-03 14:45 [PATCH 0/5] ARM: Exynos: Enable device tree support for MCT controller Thomas Abraham
  2012-11-03 14:45 ` [PATCH 1/5] ARM: Exynos: add a register base address variable in mct controller driver Thomas Abraham
  2012-11-03 14:45 ` [PATCH 2/5] ARM: Exynos: prepare an array of MCT interrupt numbers and use it Thomas Abraham
@ 2012-11-03 14:45 ` Thomas Abraham
  2012-11-03 16:50   ` Sylwester Nawrocki
  2012-11-03 14:45 ` [PATCH 4/5] ARM: Exynos: remove static io-remapping of mct registers for Exynos5 Thomas Abraham
  2012-11-03 14:45 ` [PATCH 5/5] ARM: dts: add mct device tree node for all supported Exynos SoC's Thomas Abraham
  4 siblings, 1 reply; 8+ messages in thread
From: Thomas Abraham @ 2012-11-03 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

Allow the MCT controller base address and interrupts to be obtained from
device tree and remove unused static definitions of these. The non-dt support
for Exynos5250 is removed but retained for Exynos4210 based platforms.

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 .../bindings/timer/samsung,exynos4210-mct.txt      |   70 ++++++++++++++++++++
 arch/arm/mach-exynos/include/mach/irqs.h           |    6 --
 arch/arm/mach-exynos/mct.c                         |   42 ++++++++----
 3 files changed, 99 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt

diff --git a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
new file mode 100644
index 0000000..c53fd93
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
@@ -0,0 +1,70 @@
+Samsung's Multi Core Timer (MCT)
+
+The Samsung's Multi Core Timer (MCT) module includes two main blocks, the
+global timer and CPU local timers. The global timer is a 64-bit free running
+up-counter and can generate 4 interrupts when the counter reaches one of the
+four preset counter values. The CPU local timers are 32-bit free running
+down-counters and generates an interrupt when the counter expires. There is
+one CPU local timer instantiated in MCT for every CPU in the system.
+
+Required properties:
+
+- compatible: should be "samsung,exynos4210-mct".
+- reg: base address of the mct controller and length of the address space
+  it occupies.
+- interrupts: the list of interrupts generated by the controller. The following
+  should be the order of the interrupts specified. The local timer interrupts
+  should be specified after the four global timer interrupts have been
+  specified.
+
+	0: Global Timer Interrupt 0
+	1: Global Timer Interrupt 1
+	2: Global Timer Interrupt 2
+	3: Global Timer Interrupt 3
+	4: Local Timer Interrupt 0
+	5: Local Timer Interrupt 1
+	6: ..
+	7: ..
+	i: Local Timer Interrupt n
+
+- samsung,mct-nr-local-irqs: The number of local timer interrupts supported
+  by the MCT controller.
+
+Example 1: In this example, the system uses only the first global timer
+	   interrupt generated by MCT and the remaining three global timer
+	   interrupts are unused. Two local timer interrupts have been
+	   specified.
+
+	mct at 10050000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x10050000 0x800>;
+		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+			     <0 42 0>, <0 48 0>;
+		samsung,mct-nr-local-irqs = <4>;
+	};
+
+Example 2: In this example, the MCT global and local timer interrupts are
+	   connected to two seperate interrupt controllers. Hence, an
+	   interrupt-map is created to map the interrupts to the respective
+	   interrupt controllers.
+
+	mct at 101C0000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x101C0000 0x800>;
+		interrupt-controller;
+		#interrups-cells = <2>;
+		interrupt-parent = <&mct_map>;
+		interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+			     <4 0>, <5 0>;
+		samsung,mct-nr-local-irqs = <2>;
+
+		mct_map: mct-map {
+			compatible = "samsung,mct-map";
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0x0 0 &combiner 23 3>,
+					<0x4 0 &gic 0 120 0>,
+					<0x5 0 &gic 0 121 0>;
+		};
+	};
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 6da3115..03c9f04 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -30,8 +30,6 @@
 
 /* For EXYNOS4 and EXYNOS5 */
 
-#define EXYNOS_IRQ_MCT_LOCALTIMER	IRQ_PPI(12)
-
 #define EXYNOS_IRQ_EINT16_31		IRQ_SPI(32)
 
 /* For EXYNOS4 SoCs */
@@ -320,8 +318,6 @@
 #define EXYNOS5_IRQ_CEC			IRQ_SPI(114)
 #define EXYNOS5_IRQ_SATA		IRQ_SPI(115)
 
-#define EXYNOS5_IRQ_MCT_L0		IRQ_SPI(120)
-#define EXYNOS5_IRQ_MCT_L1		IRQ_SPI(121)
 #define EXYNOS5_IRQ_MMC44		IRQ_SPI(123)
 #define EXYNOS5_IRQ_MDMA1		IRQ_SPI(124)
 #define EXYNOS5_IRQ_FIMC_LITE0		IRQ_SPI(125)
@@ -411,8 +407,6 @@
 #define EXYNOS5_IRQ_PMU_CPU1		COMBINER_IRQ(22, 4)
 
 #define EXYNOS5_IRQ_EINT0		COMBINER_IRQ(23, 0)
-#define EXYNOS5_IRQ_MCT_G0		COMBINER_IRQ(23, 3)
-#define EXYNOS5_IRQ_MCT_G1		COMBINER_IRQ(23, 4)
 
 #define EXYNOS5_IRQ_EINT1		COMBINER_IRQ(24, 0)
 #define EXYNOS5_IRQ_SYSMMU_LITE1_0	COMBINER_IRQ(24, 1)
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index d65d0c7..f7792b8 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -19,6 +19,9 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/percpu.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
 
 #include <asm/hardware/gic.h>
 #include <asm/localtimer.h>
@@ -483,14 +486,16 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
 };
 #endif /* CONFIG_LOCAL_TIMERS */
 
-static void __init exynos4_timer_resources(void)
+static void __init exynos4_timer_resources(struct device_node *np)
 {
 	struct clk *mct_clk;
 	mct_clk = clk_get(NULL, "xtal");
 
 	clk_rate = clk_get_rate(mct_clk);
 
-	reg_base = S5P_VA_SYSTIMER;
+	reg_base = (np) ? of_iomap(np, 0) : S5P_VA_SYSTIMER;
+	if (!reg_base)
+		panic("%s: unable to ioremap mct address space\n", __func__);
 
 #ifdef CONFIG_LOCAL_TIMERS
 	if (mct_int_type == MCT_INT_PPI) {
@@ -509,23 +514,34 @@ static void __init exynos4_timer_resources(void)
 
 static void __init exynos4_timer_init(void)
 {
-	if (soc_is_exynos4210()) {
+	struct device_node *np;
+	u32 nr_irqs, i;
+
+	np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-mct");
+	if (np) {
+		if (of_machine_is_compatible("samsung,exynos4210") ||
+			of_machine_is_compatible("samsung,exynos5250"))
+			mct_int_type = MCT_INT_SPI;
+		else
+			mct_int_type = MCT_INT_PPI;
+
+		if (of_property_read_u32(np, "samsung,mct-nr-local-irqs",
+						&nr_irqs))
+			panic("%s: number of local irqs not specified\n",
+						__func__);
+
+		mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
+		for (i = 0; i < nr_irqs; i++)
+			mct_irqs[MCT_L0_IRQ + i] =
+				irq_of_parse_and_map(np, MCT_L0_IRQ + i);
+	} else if (soc_is_exynos4210()) {
 		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
 		mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0;
 		mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1;
 		mct_int_type = MCT_INT_SPI;
-	} else if (soc_is_exynos5250()) {
-		mct_irqs[MCT_G0_IRQ] = EXYNOS5_IRQ_MCT_G0;
-		mct_irqs[MCT_L0_IRQ] = EXYNOS5_IRQ_MCT_L0;
-		mct_irqs[MCT_L1_IRQ] = EXYNOS5_IRQ_MCT_L1;
-		mct_int_type = MCT_INT_SPI;
-	} else {
-		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
-		mct_irqs[MCT_L0_IRQ] = EXYNOS_IRQ_MCT_LOCALTIMER;
-		mct_int_type = MCT_INT_PPI;
 	}
 
-	exynos4_timer_resources();
+	exynos4_timer_resources(np);
 	exynos4_clocksource_init();
 	exynos4_clockevent_init();
 }
-- 
1.6.6.rc2

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

* [PATCH 4/5] ARM: Exynos: remove static io-remapping of mct registers for Exynos5
  2012-11-03 14:45 [PATCH 0/5] ARM: Exynos: Enable device tree support for MCT controller Thomas Abraham
                   ` (2 preceding siblings ...)
  2012-11-03 14:45 ` [PATCH 3/5] ARM: Exynos: add device tree support for MCT controller driver Thomas Abraham
@ 2012-11-03 14:45 ` Thomas Abraham
  2012-11-03 14:45 ` [PATCH 5/5] ARM: dts: add mct device tree node for all supported Exynos SoC's Thomas Abraham
  4 siblings, 0 replies; 8+ messages in thread
From: Thomas Abraham @ 2012-11-03 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

With device tree support enabled for MCT controller, the static io-remapping
of the MCT controller address space is removed for Exynos5 platforms (which
supports only device tree based boot).

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/common.c           |    5 -----
 arch/arm/mach-exynos/include/mach/map.h |    1 -
 2 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 56844d1..44be55d 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -234,11 +234,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
-		.pfn		= __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
 		.virtual	= (unsigned long)S5P_VA_SYSRAM,
 		.pfn		= __phys_to_pfn(EXYNOS5_PA_SYSRAM),
 		.length		= SZ_4K,
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index e737331..9355552 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -64,7 +64,6 @@
 #define EXYNOS5_PA_CMU			0x10010000
 
 #define EXYNOS4_PA_SYSTIMER		0x10050000
-#define EXYNOS5_PA_SYSTIMER		0x101C0000
 
 #define EXYNOS4_PA_WATCHDOG		0x10060000
 #define EXYNOS5_PA_WATCHDOG		0x101D0000
-- 
1.6.6.rc2

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

* [PATCH 5/5] ARM: dts: add mct device tree node for all supported Exynos SoC's
  2012-11-03 14:45 [PATCH 0/5] ARM: Exynos: Enable device tree support for MCT controller Thomas Abraham
                   ` (3 preceding siblings ...)
  2012-11-03 14:45 ` [PATCH 4/5] ARM: Exynos: remove static io-remapping of mct registers for Exynos5 Thomas Abraham
@ 2012-11-03 14:45 ` Thomas Abraham
  4 siblings, 0 replies; 8+ messages in thread
From: Thomas Abraham @ 2012-11-03 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add MCT device tree node for Exynos4210, Exynos4212, Exynos4412 and Exynos5250.

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/boot/dts/exynos4210.dtsi |    8 ++++++++
 arch/arm/boot/dts/exynos4212.dtsi |   10 ++++++++++
 arch/arm/boot/dts/exynos4412.dtsi |    8 ++++++++
 arch/arm/boot/dts/exynos5250.dtsi |   21 +++++++++++++++++++++
 4 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 214c557..129762c 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -42,6 +42,14 @@
 			     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
 	};
 
+	mct at 10050000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x10050000 0x800>;
+		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+			     <0 42 0>, <0 48 0>;
+		samsung,mct-nr-local-irqs = <4>;
+	};
+
 	pinctrl_0: pinctrl at 11400000 {
 		compatible = "samsung,pinctrl-exynos4210";
 		reg = <0x11400000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
index c6ae200..87c6da4 100644
--- a/arch/arm/boot/dts/exynos4212.dtsi
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -25,4 +25,14 @@
 	gic:interrupt-controller at 10490000 {
 		cpu-offset = <0x8000>;
 	};
+
+	mct at 10050000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x10050000 0x800>;
+		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+			     <1 12 0>, <1 12 0>;
+		samsung,mct-nr-local-irqs = <2>;
+	};
+
+
 };
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index d7dfe31..ccf020a 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -25,4 +25,12 @@
 	gic:interrupt-controller at 10490000 {
 		cpu-offset = <0x4000>;
 	};
+
+	mct at 10050000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x10050000 0x800>;
+		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+			     <1 12 0>, <1 12 0>, <1 12 0>, <1 12 0>;
+		samsung,mct-nr-local-irqs = <4>;
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 49546bc..688acf2 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -56,6 +56,27 @@
 			     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
 	};
 
+	mct at 101C0000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x101C0000 0x800>;
+		interrupt-controller;
+		#interrups-cells = <2>;
+		interrupt-parent = <&mct_map>;
+		interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+			     <4 0>, <5 0>;
+		samsung,mct-nr-local-irqs = <2>;
+
+		mct_map: mct-map {
+			compatible = "samsung,mct-map";
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0x0 0 &combiner 23 3>,
+					<0x4 0 &gic 0 120 0>,
+					<0x5 0 &gic 0 121 0>;
+		};
+	};
+
 	watchdog {
 		compatible = "samsung,s3c2410-wdt";
 		reg = <0x101D0000 0x100>;
-- 
1.6.6.rc2

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

* [PATCH 3/5] ARM: Exynos: add device tree support for MCT controller driver
  2012-11-03 14:45 ` [PATCH 3/5] ARM: Exynos: add device tree support for MCT controller driver Thomas Abraham
@ 2012-11-03 16:50   ` Sylwester Nawrocki
  2012-11-05  7:46     ` Thomas Abraham
  0 siblings, 1 reply; 8+ messages in thread
From: Sylwester Nawrocki @ 2012-11-03 16:50 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Thomas,

On 11/03/2012 03:45 PM, Thomas Abraham wrote:
> Allow the MCT controller base address and interrupts to be obtained from
> device tree and remove unused static definitions of these. The non-dt support
> for Exynos5250 is removed but retained for Exynos4210 based platforms.
>
> Cc: Changhwan Youn<chaos.youn@samsung.com>
> Signed-off-by: Thomas Abraham<thomas.abraham@linaro.org>
> ---
>   .../bindings/timer/samsung,exynos4210-mct.txt      |   70 ++++++++++++++++++++
>   arch/arm/mach-exynos/include/mach/irqs.h           |    6 --
>   arch/arm/mach-exynos/mct.c                         |   42 ++++++++----
>   3 files changed, 99 insertions(+), 19 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
>
> diff --git a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
> new file mode 100644
> index 0000000..c53fd93
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
> @@ -0,0 +1,70 @@
> +Samsung's Multi Core Timer (MCT)
> +
> +The Samsung's Multi Core Timer (MCT) module includes two main blocks, the
> +global timer and CPU local timers. The global timer is a 64-bit free running
> +up-counter and can generate 4 interrupts when the counter reaches one of the
> +four preset counter values. The CPU local timers are 32-bit free running
> +down-counters and generates an interrupt when the counter expires. There is

s/generates/generate ?

> +one CPU local timer instantiated in MCT for every CPU in the system.
> +
> +Required properties:
> +
> +- compatible: should be "samsung,exynos4210-mct".
> +- reg: base address of the mct controller and length of the address space
> +  it occupies.
> +- interrupts: the list of interrupts generated by the controller. The following
> +  should be the order of the interrupts specified. The local timer interrupts
> +  should be specified after the four global timer interrupts have been
> +  specified.
> +
> +	0: Global Timer Interrupt 0
> +	1: Global Timer Interrupt 1
> +	2: Global Timer Interrupt 2
> +	3: Global Timer Interrupt 3
> +	4: Local Timer Interrupt 0
> +	5: Local Timer Interrupt 1
> +	6: ..
> +	7: ..
> +	i: Local Timer Interrupt n
> +
> +- samsung,mct-nr-local-irqs: The number of local timer interrupts supported
> +  by the MCT controller.
> +
> +Example 1: In this example, the system uses only the first global timer
> +	   interrupt generated by MCT and the remaining three global timer
> +	   interrupts are unused. Two local timer interrupts have been
> +	   specified.
> +
> +	mct at 10050000 {
> +		compatible = "samsung,exynos4210-mct";
> +		reg =<0x10050000 0x800>;
> +		interrupts =<0 57 0>,<0 0 0>,<0 0 0>,<0 0 0>,
> +			<0 42 0>,<0 48 0>;
> +		samsung,mct-nr-local-irqs =<4>;

Then this means the MCT supports 4 local interrupts but only 2 are
specified here ? Doesn't the code below expect

	samsung,mct-nr-local-irqs = <2>;

in this case ? Or should interrupts really be

	interrupts =<0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
		<0 42 0>, <0 48 0>, <0 0 0>, <0 0 0>;
?
> +	};
> +
> +Example 2: In this example, the MCT global and local timer interrupts are
> +	   connected to two seperate interrupt controllers. Hence, an
> +	   interrupt-map is created to map the interrupts to the respective
> +	   interrupt controllers.
> +
> +	mct at 101C0000 {
> +		compatible = "samsung,exynos4210-mct";
> +		reg =<0x101C0000 0x800>;
> +		interrupt-controller;
> +		#interrups-cells =<2>;
> +		interrupt-parent =<&mct_map>;
> +		interrupts =<0 0>,<1 0>,<2 0>,<3 0>,
> +			<4 0>,<5 0>;
> +		samsung,mct-nr-local-irqs =<2>;

Here the samsung,mct-nr-local-irqs' value matches what's specified in 
the interrupts property.

> +
> +		mct_map: mct-map {
> +			compatible = "samsung,mct-map";

Do we need a compatible property in sub-nodes like this one ?
Wouldn't it be sufficient to reference this node, for example by name ?

> +			#interrupt-cells =<2>;
> +			#address-cells =<0>;
> +			#size-cells =<0>;
> +			interrupt-map =<0x0 0&combiner 23 3>,
> +					<0x4 0&gic 0 120 0>,
> +					<0x5 0&gic 0 121 0>;
> +		};
> +	};
> diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
> index 6da3115..03c9f04 100644
> --- a/arch/arm/mach-exynos/include/mach/irqs.h
> +++ b/arch/arm/mach-exynos/include/mach/irqs.h
> @@ -30,8 +30,6 @@
>
>   /* For EXYNOS4 and EXYNOS5 */
>
> -#define EXYNOS_IRQ_MCT_LOCALTIMER	IRQ_PPI(12)
> -
>   #define EXYNOS_IRQ_EINT16_31		IRQ_SPI(32)
>
>   /* For EXYNOS4 SoCs */
> @@ -320,8 +318,6 @@
>   #define EXYNOS5_IRQ_CEC			IRQ_SPI(114)
>   #define EXYNOS5_IRQ_SATA		IRQ_SPI(115)
>
> -#define EXYNOS5_IRQ_MCT_L0		IRQ_SPI(120)
> -#define EXYNOS5_IRQ_MCT_L1		IRQ_SPI(121)
>   #define EXYNOS5_IRQ_MMC44		IRQ_SPI(123)
>   #define EXYNOS5_IRQ_MDMA1		IRQ_SPI(124)
>   #define EXYNOS5_IRQ_FIMC_LITE0		IRQ_SPI(125)
> @@ -411,8 +407,6 @@
>   #define EXYNOS5_IRQ_PMU_CPU1		COMBINER_IRQ(22, 4)
>
>   #define EXYNOS5_IRQ_EINT0		COMBINER_IRQ(23, 0)
> -#define EXYNOS5_IRQ_MCT_G0		COMBINER_IRQ(23, 3)
> -#define EXYNOS5_IRQ_MCT_G1		COMBINER_IRQ(23, 4)
>
>   #define EXYNOS5_IRQ_EINT1		COMBINER_IRQ(24, 0)
>   #define EXYNOS5_IRQ_SYSMMU_LITE1_0	COMBINER_IRQ(24, 1)
> diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
> index d65d0c7..f7792b8 100644
> --- a/arch/arm/mach-exynos/mct.c
> +++ b/arch/arm/mach-exynos/mct.c
> @@ -19,6 +19,9 @@
>   #include<linux/platform_device.h>
>   #include<linux/delay.h>
>   #include<linux/percpu.h>
> +#include<linux/of.h>
> +#include<linux/of_irq.h>
> +#include<linux/of_address.h>
>
>   #include<asm/hardware/gic.h>
>   #include<asm/localtimer.h>
> @@ -483,14 +486,16 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
>   };
>   #endif /* CONFIG_LOCAL_TIMERS */
>
> -static void __init exynos4_timer_resources(void)
> +static void __init exynos4_timer_resources(struct device_node *np)
>   {
>   	struct clk *mct_clk;
>   	mct_clk = clk_get(NULL, "xtal");
>
>   	clk_rate = clk_get_rate(mct_clk);
>
> -	reg_base = S5P_VA_SYSTIMER;
> +	reg_base = (np) ? of_iomap(np, 0) : S5P_VA_SYSTIMER;

nit: Parentheses around np look redundant.

> +	if (!reg_base)
> +		panic("%s: unable to ioremap mct address space\n", __func__);

How about adding a line like:

#define pr_fmt(fmt) "%s: " fmt, __func__

on top of this file and dropping "%s: " and __func__ in those panic() 
calls ? It would make the logs more consistent across whole file.

>   #ifdef CONFIG_LOCAL_TIMERS
>   	if (mct_int_type == MCT_INT_PPI) {
> @@ -509,23 +514,34 @@ static void __init exynos4_timer_resources(void)
>
>   static void __init exynos4_timer_init(void)
>   {
> -	if (soc_is_exynos4210()) {
> +	struct device_node *np;
> +	u32 nr_irqs, i;
> +
> +	np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-mct");
> +	if (np) {
> +		if (of_machine_is_compatible("samsung,exynos4210") ||
> +			of_machine_is_compatible("samsung,exynos5250"))
> +			mct_int_type = MCT_INT_SPI;
> +		else
> +			mct_int_type = MCT_INT_PPI;

Does it make sense to specify this mct_int_type as a property of
the mct node ?

> +
> +		if (of_property_read_u32(np, "samsung,mct-nr-local-irqs",
> +						&nr_irqs))
> +			panic("%s: number of local irqs not specified\n",
> +						__func__);
> +
> +		mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
> +		for (i = 0; i<  nr_irqs; i++)
> +			mct_irqs[MCT_L0_IRQ + i] =
> +				irq_of_parse_and_map(np, MCT_L0_IRQ + i);
> +	} else if (soc_is_exynos4210()) {
>   		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
>   		mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0;
>   		mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1;
>   		mct_int_type = MCT_INT_SPI;
> -	} else if (soc_is_exynos5250()) {
> -		mct_irqs[MCT_G0_IRQ] = EXYNOS5_IRQ_MCT_G0;
> -		mct_irqs[MCT_L0_IRQ] = EXYNOS5_IRQ_MCT_L0;
> -		mct_irqs[MCT_L1_IRQ] = EXYNOS5_IRQ_MCT_L1;
> -		mct_int_type = MCT_INT_SPI;
> -	} else {
> -		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
> -		mct_irqs[MCT_L0_IRQ] = EXYNOS_IRQ_MCT_LOCALTIMER;
> -		mct_int_type = MCT_INT_PPI;
>   	}
>
> -	exynos4_timer_resources();
> +	exynos4_timer_resources(np);
>   	exynos4_clocksource_init();
>   	exynos4_clockevent_init();
>   }

--

Regards,
Sylwester

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

* [PATCH 3/5] ARM: Exynos: add device tree support for MCT controller driver
  2012-11-03 16:50   ` Sylwester Nawrocki
@ 2012-11-05  7:46     ` Thomas Abraham
  0 siblings, 0 replies; 8+ messages in thread
From: Thomas Abraham @ 2012-11-05  7:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sylwester,

Thanks for your comments.

On 3 November 2012 22:20, Sylwester Nawrocki
<sylvester.nawrocki@gmail.com> wrote:
> Hi Thomas,
>
>
> On 11/03/2012 03:45 PM, Thomas Abraham wrote:
>>
>> Allow the MCT controller base address and interrupts to be obtained from
>> device tree and remove unused static definitions of these. The non-dt
>> support
>> for Exynos5250 is removed but retained for Exynos4210 based platforms.
>>
>> Cc: Changhwan Youn<chaos.youn@samsung.com>
>> Signed-off-by: Thomas Abraham<thomas.abraham@linaro.org>
>> ---
>>   .../bindings/timer/samsung,exynos4210-mct.txt      |   70
>> ++++++++++++++++++++
>>   arch/arm/mach-exynos/include/mach/irqs.h           |    6 --
>>   arch/arm/mach-exynos/mct.c                         |   42 ++++++++----
>>   3 files changed, 99 insertions(+), 19 deletions(-)
>>   create mode 100644
>> Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
>>
>> diff --git
>> a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
>> b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
>> new file mode 100644
>> index 0000000..c53fd93
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
>> @@ -0,0 +1,70 @@
>> +Samsung's Multi Core Timer (MCT)
>> +
>> +The Samsung's Multi Core Timer (MCT) module includes two main blocks, the
>> +global timer and CPU local timers. The global timer is a 64-bit free
>> running
>> +up-counter and can generate 4 interrupts when the counter reaches one of
>> the
>> +four preset counter values. The CPU local timers are 32-bit free running
>> +down-counters and generates an interrupt when the counter expires. There
>> is
>
>
> s/generates/generate ?

Ok.

>
>
>> +one CPU local timer instantiated in MCT for every CPU in the system.
>> +
>> +Required properties:
>> +
>> +- compatible: should be "samsung,exynos4210-mct".
>> +- reg: base address of the mct controller and length of the address space
>> +  it occupies.
>> +- interrupts: the list of interrupts generated by the controller. The
>> following
>> +  should be the order of the interrupts specified. The local timer
>> interrupts
>> +  should be specified after the four global timer interrupts have been
>> +  specified.
>> +
>> +       0: Global Timer Interrupt 0
>> +       1: Global Timer Interrupt 1
>> +       2: Global Timer Interrupt 2
>> +       3: Global Timer Interrupt 3
>> +       4: Local Timer Interrupt 0
>> +       5: Local Timer Interrupt 1
>> +       6: ..
>> +       7: ..
>> +       i: Local Timer Interrupt n
>> +
>> +- samsung,mct-nr-local-irqs: The number of local timer interrupts
>> supported
>> +  by the MCT controller.
>> +
>> +Example 1: In this example, the system uses only the first global timer
>> +          interrupt generated by MCT and the remaining three global timer
>> +          interrupts are unused. Two local timer interrupts have been
>> +          specified.
>> +
>> +       mct at 10050000 {
>> +               compatible = "samsung,exynos4210-mct";
>> +               reg =<0x10050000 0x800>;
>> +               interrupts =<0 57 0>,<0 0 0>,<0 0 0>,<0 0 0>,
>> +                       <0 42 0>,<0 48 0>;
>> +               samsung,mct-nr-local-irqs =<4>;
>
>
> Then this means the MCT supports 4 local interrupts but only 2 are
> specified here ? Doesn't the code below expect
>
>         samsung,mct-nr-local-irqs = <2>;
>
> in this case ? Or should interrupts really be
>
>
>         interrupts =<0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
>                 <0 42 0>, <0 48 0>, <0 0 0>, <0 0 0>;
>
> ?

No, that was a typo. It should be samsung,mct-nr-local-irqs = <2>.
Thanks for spotting this.

>>
>> +       };
>> +
>> +Example 2: In this example, the MCT global and local timer interrupts are
>> +          connected to two seperate interrupt controllers. Hence, an
>> +          interrupt-map is created to map the interrupts to the
>> respective
>> +          interrupt controllers.
>> +
>> +       mct at 101C0000 {
>> +               compatible = "samsung,exynos4210-mct";
>> +               reg =<0x101C0000 0x800>;
>> +               interrupt-controller;
>> +               #interrups-cells =<2>;
>> +               interrupt-parent =<&mct_map>;
>> +               interrupts =<0 0>,<1 0>,<2 0>,<3 0>,
>> +                       <4 0>,<5 0>;
>> +               samsung,mct-nr-local-irqs =<2>;
>
>
> Here the samsung,mct-nr-local-irqs' value matches what's specified in the
> interrupts property.
>
>
>> +
>> +               mct_map: mct-map {
>> +                       compatible = "samsung,mct-map";
>
>
> Do we need a compatible property in sub-nodes like this one ?
> Wouldn't it be sufficient to reference this node, for example by name ?

Yes, it is not really required. I will remove it.

>
>> +                       #interrupt-cells =<2>;
>> +                       #address-cells =<0>;
>> +                       #size-cells =<0>;
>> +                       interrupt-map =<0x0 0&combiner 23 3>,
>> +                                       <0x4 0&gic 0 120 0>,
>> +                                       <0x5 0&gic 0 121 0>;
>>
>> +               };
>> +       };
>> diff --git a/arch/arm/mach-exynos/include/mach/irqs.h
>> b/arch/arm/mach-exynos/include/mach/irqs.h
>> index 6da3115..03c9f04 100644
>> --- a/arch/arm/mach-exynos/include/mach/irqs.h
>> +++ b/arch/arm/mach-exynos/include/mach/irqs.h
>> @@ -30,8 +30,6 @@
>>
>>   /* For EXYNOS4 and EXYNOS5 */
>>
>> -#define EXYNOS_IRQ_MCT_LOCALTIMER      IRQ_PPI(12)
>> -
>>   #define EXYNOS_IRQ_EINT16_31          IRQ_SPI(32)
>>
>>   /* For EXYNOS4 SoCs */
>> @@ -320,8 +318,6 @@
>>   #define EXYNOS5_IRQ_CEC                       IRQ_SPI(114)
>>   #define EXYNOS5_IRQ_SATA              IRQ_SPI(115)
>>
>> -#define EXYNOS5_IRQ_MCT_L0             IRQ_SPI(120)
>> -#define EXYNOS5_IRQ_MCT_L1             IRQ_SPI(121)
>>   #define EXYNOS5_IRQ_MMC44             IRQ_SPI(123)
>>   #define EXYNOS5_IRQ_MDMA1             IRQ_SPI(124)
>>   #define EXYNOS5_IRQ_FIMC_LITE0                IRQ_SPI(125)
>> @@ -411,8 +407,6 @@
>>   #define EXYNOS5_IRQ_PMU_CPU1          COMBINER_IRQ(22, 4)
>>
>>   #define EXYNOS5_IRQ_EINT0             COMBINER_IRQ(23, 0)
>> -#define EXYNOS5_IRQ_MCT_G0             COMBINER_IRQ(23, 3)
>> -#define EXYNOS5_IRQ_MCT_G1             COMBINER_IRQ(23, 4)
>>
>>   #define EXYNOS5_IRQ_EINT1             COMBINER_IRQ(24, 0)
>>   #define EXYNOS5_IRQ_SYSMMU_LITE1_0    COMBINER_IRQ(24, 1)
>> diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
>> index d65d0c7..f7792b8 100644
>> --- a/arch/arm/mach-exynos/mct.c
>> +++ b/arch/arm/mach-exynos/mct.c
>> @@ -19,6 +19,9 @@
>>   #include<linux/platform_device.h>
>>   #include<linux/delay.h>
>>   #include<linux/percpu.h>
>> +#include<linux/of.h>
>> +#include<linux/of_irq.h>
>> +#include<linux/of_address.h>
>>
>>   #include<asm/hardware/gic.h>
>>   #include<asm/localtimer.h>
>> @@ -483,14 +486,16 @@ static struct local_timer_ops exynos4_mct_tick_ops
>> __cpuinitdata = {
>>   };
>>   #endif /* CONFIG_LOCAL_TIMERS */
>>
>> -static void __init exynos4_timer_resources(void)
>> +static void __init exynos4_timer_resources(struct device_node *np)
>>   {
>>         struct clk *mct_clk;
>>         mct_clk = clk_get(NULL, "xtal");
>>
>>         clk_rate = clk_get_rate(mct_clk);
>>
>> -       reg_base = S5P_VA_SYSTIMER;
>> +       reg_base = (np) ? of_iomap(np, 0) : S5P_VA_SYSTIMER;
>
>
> nit: Parentheses around np look redundant.

Ok.

>
>
>> +       if (!reg_base)
>> +               panic("%s: unable to ioremap mct address space\n",
>> __func__);
>
>
> How about adding a line like:
>
> #define pr_fmt(fmt) "%s: " fmt, __func__
>
> on top of this file and dropping "%s: " and __func__ in those panic() calls
> ? It would make the logs more consistent across whole file.

Ok.

>
>
>>   #ifdef CONFIG_LOCAL_TIMERS
>>         if (mct_int_type == MCT_INT_PPI) {
>> @@ -509,23 +514,34 @@ static void __init exynos4_timer_resources(void)
>>
>>   static void __init exynos4_timer_init(void)
>>   {
>> -       if (soc_is_exynos4210()) {
>> +       struct device_node *np;
>> +       u32 nr_irqs, i;
>> +
>> +       np = of_find_compatible_node(NULL, NULL,
>> "samsung,exynos4210-mct");
>> +       if (np) {
>> +               if (of_machine_is_compatible("samsung,exynos4210") ||
>> +                       of_machine_is_compatible("samsung,exynos5250"))
>> +                       mct_int_type = MCT_INT_SPI;
>> +               else
>> +                       mct_int_type = MCT_INT_PPI;
>
>
> Does it make sense to specify this mct_int_type as a property of
> the mct node ?

The MCT bindings are independent of the system integration details.
There could be a system that uses MCT controller but not GIC
controller.

Thanks,
Thomas.

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

end of thread, other threads:[~2012-11-05  7:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-03 14:45 [PATCH 0/5] ARM: Exynos: Enable device tree support for MCT controller Thomas Abraham
2012-11-03 14:45 ` [PATCH 1/5] ARM: Exynos: add a register base address variable in mct controller driver Thomas Abraham
2012-11-03 14:45 ` [PATCH 2/5] ARM: Exynos: prepare an array of MCT interrupt numbers and use it Thomas Abraham
2012-11-03 14:45 ` [PATCH 3/5] ARM: Exynos: add device tree support for MCT controller driver Thomas Abraham
2012-11-03 16:50   ` Sylwester Nawrocki
2012-11-05  7:46     ` Thomas Abraham
2012-11-03 14:45 ` [PATCH 4/5] ARM: Exynos: remove static io-remapping of mct registers for Exynos5 Thomas Abraham
2012-11-03 14:45 ` [PATCH 5/5] ARM: dts: add mct device tree node for all supported Exynos SoC's Thomas Abraham

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).