Skip to contentSkip to conversation

ARM: imx: move timer driver into drivers/clocksource

PATCH Superseded Shawn Guo 5 participants 28 messages May 22, 2015 – Jun 4, 2015

Subsystems (6)
lore
Share & tools
lore

Shawn Guo

author
#0 lore raw

v2 cover ARM: imx: move timer driver into drivers/clocksource

Changes since v1:
- Use relaxed IO accessor to replace __raw_xxx version
- Create imx_gpt_data structure to accommodate gpt device specific data
- Move clock event related variables into imx_timer structure

Daniel,

If the patch series looks good to you, can you please give your ACK on the last patch, so that I can send the whole series through IMX tree? Thanks.

Shawn

Shawn Guo (12):
ARM: imx: use relaxed IO accessor in timer driver
ARM: imx: move timer resources into a structure
ARM: imx: define an enum for gpt timer device type
ARM: imx: initialize gpt device type for DT boot
ARM: imx: setup tctl register in device specific function
ARM: imx: set up .set_next_event hook via imx_gpt_data
ARM: imx: move clock event variables into imx_timer
ARM: imx: define gpt register offset per device type
ARM: imx: get rid of variable timer_base
ARM: imx: provide gpt device specific irq functions
ARM: imx: remove platform headers from timer driver
ARM: imx: move timer driver into drivers/clocksource

 arch/arm/mach-imx/Makefile      |   2 +-
 arch/arm/mach-imx/time.c        | 388 -----------------------------
 drivers/clk/imx/clk-imx1.c      |   3 +-
 drivers/clk/imx/clk-imx21.c     |   3 +-
 drivers/clk/imx/clk-imx27.c     |   3 +-
 drivers/clk/imx/clk-imx31.c     |   3 +-
 drivers/clk/imx/clk-imx35.c     |   3 +-
 drivers/clk/imx/clk.h           |   7 -
 drivers/clocksource/Makefile    |   1 +
 drivers/clocksource/timer-imx.c | 531 ++++++++++++++++++++++++++++++++++++++++
 include/soc/imx/timer.h         |  26 ++
 11 files changed, 569 insertions(+), 401 deletions(-)
 delete mode 100644 arch/arm/mach-imx/time.c
 create mode 100644 drivers/clocksource/timer-imx.c
 create mode 100644 include/soc/imx/timer.h
Signature · 1 line
1.9.1
author
#1 lore raw

PATCH v2 1/12 ARM: imx: use relaxed IO accessor in timer driver

Replace the __raw_readl/__raw_writel with readl_relaxed/writel_relaxed which is endian-safe, as a step of moving the driver code into folder drivers/clocksource.

---
 arch/arm/mach-imx/time.c | 48 ++++++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 24 deletions(-)
arch/arm/mach-imx/time.c +24 -24
index ab5ee1c445f3..376d5d8ccfb8 100644
@@ -91,19 +91,19 @@ static inline void gpt_irq_disable(void)
 	unsigned int tmp;
 
 	if (timer_is_v2())
-		__raw_writel(0, timer_base + V2_IR);
+		writel_relaxed(0, timer_base + V2_IR);
 	else {
-		tmp = __raw_readl(timer_base + MXC_TCTL);
-		__raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
+		tmp = readl_relaxed(timer_base + MXC_TCTL);
+		writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
 	}
 }
 
 static inline void gpt_irq_enable(void)
 {
 	if (timer_is_v2())
-		__raw_writel(1<<0, timer_base + V2_IR);
+		writel_relaxed(1<<0, timer_base + V2_IR);
 	else {
-		__raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
+		writel_relaxed(readl_relaxed(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
 			timer_base + MXC_TCTL);
 	}
 }
@@ -112,26 +112,26 @@ static void gpt_irq_acknowledge(void)
 {
 	if (timer_is_v1()) {
 		if (cpu_is_mx1())
-			__raw_writel(0, timer_base + MX1_2_TSTAT);
+			writel_relaxed(0, timer_base + MX1_2_TSTAT);
 		else
-			__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
+			writel_relaxed(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
 				timer_base + MX1_2_TSTAT);
 	} else if (timer_is_v2())
-		__raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
+		writel_relaxed(V2_TSTAT_OF1, timer_base + V2_TSTAT);
 }
 
 static void __iomem *sched_clock_reg;
 
 static u64 notrace mxc_read_sched_clock(void)
 {
-	return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
+	return sched_clock_reg ? readl_relaxed(sched_clock_reg) : 0;
 }
 
 static struct delay_timer imx_delay_timer;
 
 static unsigned long imx_read_current_timer(void)
 {
-	return __raw_readl(sched_clock_reg);
+	return readl_relaxed(sched_clock_reg);
 }
 
 static int __init mxc_clocksource_init(struct clk *timer_clk)
@@ -157,11 +157,11 @@ static int mx1_2_set_next_event(unsigned long evt,
 {
 	unsigned long tcmp;
 
-	tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
+	tcmp = readl_relaxed(timer_base + MX1_2_TCN) + evt;
 
-	__raw_writel(tcmp, timer_base + MX1_2_TCMP);
+	writel_relaxed(tcmp, timer_base + MX1_2_TCMP);
 
-	return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
+	return (int)(tcmp - readl_relaxed(timer_base + MX1_2_TCN)) < 0 ?
 				-ETIME : 0;
 }
 
@@ -170,12 +170,12 @@ static int v2_set_next_event(unsigned long evt,
 {
 	unsigned long tcmp;
 
-	tcmp = __raw_readl(timer_base + V2_TCN) + evt;
+	tcmp = readl_relaxed(timer_base + V2_TCN) + evt;
 
-	__raw_writel(tcmp, timer_base + V2_TCMP);
+	writel_relaxed(tcmp, timer_base + V2_TCMP);
 
 	return evt < 0x7fffffff &&
-		(int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
+		(int)(tcmp - readl_relaxed(timer_base + V2_TCN)) < 0 ?
 				-ETIME : 0;
 }
 
@@ -206,10 +206,10 @@ static void mxc_set_mode(enum clock_event_mode mode,
 	if (mode != clockevent_mode) {
 		/* Set event time into far-far future */
 		if (timer_is_v2())
-			__raw_writel(__raw_readl(timer_base + V2_TCN) - 3,
+			writel_relaxed(readl_relaxed(timer_base + V2_TCN) - 3,
 					timer_base + V2_TCMP);
 		else
-			__raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
+			writel_relaxed(readl_relaxed(timer_base + MX1_2_TCN) - 3,
 					timer_base + MX1_2_TCMP);
 
 		/* Clear pending interrupt */
@@ -259,9 +259,9 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 	uint32_t tstat;
 
 	if (timer_is_v2())
-		tstat = __raw_readl(timer_base + V2_TSTAT);
+		tstat = readl_relaxed(timer_base + V2_TSTAT);
 	else
-		tstat = __raw_readl(timer_base + MX1_2_TSTAT);
+		tstat = readl_relaxed(timer_base + MX1_2_TSTAT);
 
 	gpt_irq_acknowledge();
 
@@ -316,8 +316,8 @@ static void __init _mxc_timer_init(int irq,
 	 * Initialise to a known state (all timers off, and timing reset)
 	 */
 
-	__raw_writel(0, timer_base + MXC_TCTL);
-	__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
+	writel_relaxed(0, timer_base + MXC_TCTL);
+	writel_relaxed(0, timer_base + MXC_TPRER); /* see datasheet note */
 
 	if (timer_is_v2()) {
 		tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
@@ -325,7 +325,7 @@ static void __init _mxc_timer_init(int irq,
 			tctl_val |= V2_TCTL_CLK_OSC_DIV8;
 			if (cpu_is_imx6dl() || cpu_is_imx6sx()) {
 				/* 24 / 8 = 3 MHz */
-				__raw_writel(7 << V2_TPRER_PRE24M,
+				writel_relaxed(7 << V2_TPRER_PRE24M,
 					timer_base + MXC_TPRER);
 				tctl_val |= V2_TCTL_24MEN;
 			}
@@ -336,7 +336,7 @@ static void __init _mxc_timer_init(int irq,
 		tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
 	}
 
-	__raw_writel(tctl_val, timer_base + MXC_TCTL);
+	writel_relaxed(tctl_val, timer_base + MXC_TCTL);
 
 	/* init and register the timer to the framework */
 	mxc_clocksource_init(clk_per);
Signature · 1 line
1.9.1
author
#2 lore raw

PATCH v2 2/12 ARM: imx: move timer resources into a structure

In reply to Shawn Guo

Instead of passing around as individual argument, let's move timer resources like irq and clocks together with base address into a data structure, and pass pointer of the structure as argument to simplify the function call interface.

---
 arch/arm/mach-imx/time.c | 91 +++++++++++++++++++++++++++++-------------------
 1 file changed, 56 insertions(+), 35 deletions(-)
arch/arm/mach-imx/time.c +56 -35
index 376d5d8ccfb8..7c131e1b2637 100644
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/sched_clock.h>
+#include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -84,6 +85,13 @@
 static struct clock_event_device clockevent_mxc;
 static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
+struct imx_timer {
+	void __iomem *base;
+	int irq;
+	struct clk *clk_per;
+	struct clk *clk_ipg;
+};
+
 static void __iomem *timer_base;
 
 static inline void gpt_irq_disable(void)
@@ -134,10 +142,10 @@ static unsigned long imx_read_current_timer(void)
 	return readl_relaxed(sched_clock_reg);
 }
 
-static int __init mxc_clocksource_init(struct clk *timer_clk)
+static int __init mxc_clocksource_init(struct imx_timer *imxtm)
 {
-	unsigned int c = clk_get_rate(timer_clk);
-	void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN);
+	unsigned int c = clk_get_rate(imxtm->clk_per);
+	void __iomem *reg = imxtm->base + (timer_is_v2() ? V2_TCN : MX1_2_TCN);
 
 	imx_delay_timer.read_current_timer = &imx_read_current_timer;
 	imx_delay_timer.freq = c;
@@ -284,49 +292,51 @@ static struct clock_event_device clockevent_mxc = {
 	.rating		= 200,
 };
 
-static int __init mxc_clockevent_init(struct clk *timer_clk)
+static int __init mxc_clockevent_init(struct imx_timer *imxtm)
 {
 	if (timer_is_v2())
 		clockevent_mxc.set_next_event = v2_set_next_event;
 
 	clockevent_mxc.cpumask = cpumask_of(0);
 	clockevents_config_and_register(&clockevent_mxc,
-					clk_get_rate(timer_clk),
+					clk_get_rate(imxtm->clk_per),
 					0xff, 0xfffffffe);
 
 	return 0;
 }
 
-static void __init _mxc_timer_init(int irq,
-				   struct clk *clk_per, struct clk *clk_ipg)
+static void __init _mxc_timer_init(struct imx_timer *imxtm)
 {
 	uint32_t tctl_val;
 
-	if (IS_ERR(clk_per)) {
+	/* Temporary */
+	timer_base = imxtm->base;
+
+	if (IS_ERR(imxtm->clk_per)) {
 		pr_err("i.MX timer: unable to get clk\n");
 		return;
 	}
 
-	if (!IS_ERR(clk_ipg))
-		clk_prepare_enable(clk_ipg);
+	if (!IS_ERR(imxtm->clk_ipg))
+		clk_prepare_enable(imxtm->clk_ipg);
 
-	clk_prepare_enable(clk_per);
+	clk_prepare_enable(imxtm->clk_per);
 
 	/*
 	 * Initialise to a known state (all timers off, and timing reset)
 	 */
 
-	writel_relaxed(0, timer_base + MXC_TCTL);
-	writel_relaxed(0, timer_base + MXC_TPRER); /* see datasheet note */
+	writel_relaxed(0, imxtm->base + MXC_TCTL);
+	writel_relaxed(0, imxtm->base + MXC_TPRER); /* see datasheet note */
 
 	if (timer_is_v2()) {
 		tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
-		if (clk_get_rate(clk_per) == V2_TIMER_RATE_OSC_DIV8) {
+		if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8) {
 			tctl_val |= V2_TCTL_CLK_OSC_DIV8;
 			if (cpu_is_imx6dl() || cpu_is_imx6sx()) {
 				/* 24 / 8 = 3 MHz */
 				writel_relaxed(7 << V2_TPRER_PRE24M,
-					timer_base + MXC_TPRER);
+					imxtm->base + MXC_TPRER);
 				tctl_val |= V2_TCTL_24MEN;
 			}
 		} else {
@@ -336,47 +346,58 @@ static void __init _mxc_timer_init(int irq,
 		tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
 	}
 
-	writel_relaxed(tctl_val, timer_base + MXC_TCTL);
+	writel_relaxed(tctl_val, imxtm->base + MXC_TCTL);
 
 	/* init and register the timer to the framework */
-	mxc_clocksource_init(clk_per);
-	mxc_clockevent_init(clk_per);
+	mxc_clocksource_init(imxtm);
+	mxc_clockevent_init(imxtm);
 
 	/* Make irqs happen */
-	setup_irq(irq, &mxc_timer_irq);
+	setup_irq(imxtm->irq, &mxc_timer_irq);
 }
 
 void __init mxc_timer_init(unsigned long pbase, int irq)
 {
-	struct clk *clk_per = clk_get_sys("imx-gpt.0", "per");
-	struct clk *clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
+	struct imx_timer *imxtm;
+
+	imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL);
+	BUG_ON(!imxtm);
 
-	timer_base = ioremap(pbase, SZ_4K);
-	BUG_ON(!timer_base);
+	imxtm->clk_per = clk_get_sys("imx-gpt.0", "per");
+	imxtm->clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
 
-	_mxc_timer_init(irq, clk_per, clk_ipg);
+	imxtm->base = ioremap(pbase, SZ_4K);
+	BUG_ON(!imxtm->base);
+
+	_mxc_timer_init(imxtm);
 }
 
 static void __init mxc_timer_init_dt(struct device_node *np)
 {
-	struct clk *clk_per, *clk_ipg;
-	int irq;
+	struct imx_timer *imxtm;
+	static int initialized;
 
-	if (timer_base)
+	/* Support one instance only */
+	if (initialized)
 		return;
 
-	timer_base = of_iomap(np, 0);
-	WARN_ON(!timer_base);
-	irq = irq_of_parse_and_map(np, 0);
+	imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL);
+	BUG_ON(!imxtm);
 
-	clk_ipg = of_clk_get_by_name(np, "ipg");
+	imxtm->base = of_iomap(np, 0);
+	WARN_ON(!imxtm->base);
+	imxtm->irq = irq_of_parse_and_map(np, 0);
+
+	imxtm->clk_ipg = of_clk_get_by_name(np, "ipg");
 
 	/* Try osc_per first, and fall back to per otherwise */
-	clk_per = of_clk_get_by_name(np, "osc_per");
-	if (IS_ERR(clk_per))
-		clk_per = of_clk_get_by_name(np, "per");
+	imxtm->clk_per = of_clk_get_by_name(np, "osc_per");
+	if (IS_ERR(imxtm->clk_per))
+		imxtm->clk_per = of_clk_get_by_name(np, "per");
+
+	_mxc_timer_init(imxtm);
 
-	_mxc_timer_init(irq, clk_per, clk_ipg);
+	initialized = 1;
 }
 CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);
 CLOCKSOURCE_OF_DECLARE(mx25_timer, "fsl,imx25-gpt", mxc_timer_init_dt);
Signature · 1 line
1.9.1
author
#3 lore raw

PATCH v2 3/12 ARM: imx: define an enum for gpt timer device type

In reply to Shawn Guo

Define an enum for gpt timer device type in include/soc/imx/timer.h to tell the gpt block differences among SoCs. Update non-DT users (clock drivers) to pass the device type.

As we now have include/soc/imx/timer.h, the declaration of mxc_timer_init() is moved into there as the best fit.

---
 arch/arm/mach-imx/time.c    |  6 +++++-
 drivers/clk/imx/clk-imx1.c  |  3 ++-
 drivers/clk/imx/clk-imx21.c |  3 ++-
 drivers/clk/imx/clk-imx27.c |  3 ++-
 drivers/clk/imx/clk-imx31.c |  3 ++-
 drivers/clk/imx/clk-imx35.c |  3 ++-
 drivers/clk/imx/clk.h       |  7 -------
 include/soc/imx/timer.h     | 26 ++++++++++++++++++++++++++
 8 files changed, 41 insertions(+), 13 deletions(-)
 create mode 100644 include/soc/imx/timer.h
arch/arm/mach-imx/time.c +5 -1
index 7c131e1b2637..307cbc7abc8e 100644
@@ -32,6 +32,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <soc/imx/timer.h>
 
 #include <asm/mach/time.h>
 
@@ -86,6 +87,7 @@ static struct clock_event_device clockevent_mxc;
 static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
 struct imx_timer {
+	enum imx_gpt_type type;
 	void __iomem *base;
 	int irq;
 	struct clk *clk_per;
@@ -356,7 +358,7 @@ static void __init _mxc_timer_init(struct imx_timer *imxtm)
 	setup_irq(imxtm->irq, &mxc_timer_irq);
 }
 
-void __init mxc_timer_init(unsigned long pbase, int irq)
+void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type)
 {
 	struct imx_timer *imxtm;
 
@@ -369,6 +371,8 @@ void __init mxc_timer_init(unsigned long pbase, int irq)
 	imxtm->base = ioremap(pbase, SZ_4K);
 	BUG_ON(!imxtm->base);
 
+	imxtm->type = type;
+
 	_mxc_timer_init(imxtm);
 }
 
drivers/clk/imx/clk-imx1.c +2 -1
index c9812dbacac2..c2647fa19f28 100644
@@ -23,6 +23,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <dt-bindings/clock/imx1-clock.h>
+#include <soc/imx/timer.h>
 #include <asm/irq.h>
 
 #include "clk.h"
@@ -102,7 +103,7 @@ int __init mx1_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-fb.0");
 	clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ahb", "imx1-fb.0");
 
-	mxc_timer_init(MX1_TIM1_BASE_ADDR, MX1_TIM1_INT);
+	mxc_timer_init(MX1_TIM1_BASE_ADDR, MX1_TIM1_INT, GPT_TYPE_IMX1);
 
 	return 0;
 }
drivers/clk/imx/clk-imx21.c +2 -1
index 0ca842cf4ca7..dba987e3b89f 100644
@@ -15,6 +15,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <dt-bindings/clock/imx21-clock.h>
+#include <soc/imx/timer.h>
 #include <asm/irq.h>
 
 #include "clk.h"
@@ -156,7 +157,7 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href)
 	clk_register_clkdev(clk[IMX21_CLK_I2C_GATE], NULL, "imx21-i2c.0");
 	clk_register_clkdev(clk[IMX21_CLK_OWIRE_GATE], NULL, "mxc_w1.0");
 
-	mxc_timer_init(MX21_GPT1_BASE_ADDR, MX21_INT_GPT1);
+	mxc_timer_init(MX21_GPT1_BASE_ADDR, MX21_INT_GPT1, GPT_TYPE_IMX21);
 
 	return 0;
 }
drivers/clk/imx/clk-imx27.c +2 -1
index df2dfc081c71..d9d50d54ef2a 100644
@@ -6,6 +6,7 @@
 #include <linux/of_address.h>
 #include <dt-bindings/clock/imx27-clock.h>
 #include <soc/imx/revision.h>
+#include <soc/imx/timer.h>
 #include <asm/irq.h>
 
 #include "clk.h"
@@ -233,7 +234,7 @@ int __init mx27_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[IMX27_CLK_EMMA_AHB_GATE], "ahb", "m2m-emmaprp.0");
 	clk_register_clkdev(clk[IMX27_CLK_EMMA_IPG_GATE], "ipg", "m2m-emmaprp.0");
 
-	mxc_timer_init(MX27_GPT1_BASE_ADDR, MX27_INT_GPT1);
+	mxc_timer_init(MX27_GPT1_BASE_ADDR, MX27_INT_GPT1, GPT_TYPE_IMX21);
 
 	return 0;
 }
drivers/clk/imx/clk-imx31.c +2 -1
index a55290c1c264..fe66c40b7be2 100644
@@ -22,6 +22,7 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <soc/imx/revision.h>
+#include <soc/imx/timer.h>
 #include <asm/irq.h>
 
 #include "clk.h"
@@ -198,7 +199,7 @@ int __init mx31_clocks_init(unsigned long fref)
 	mx31_revision();
 	clk_disable_unprepare(clk[iim_gate]);
 
-	mxc_timer_init(MX31_GPT1_BASE_ADDR, MX31_INT_GPT);
+	mxc_timer_init(MX31_GPT1_BASE_ADDR, MX31_INT_GPT, GPT_TYPE_IMX31);
 
 	return 0;
 }
drivers/clk/imx/clk-imx35.c +2 -1
index f2f3b8164f7b..69138ba3dec7 100644
@@ -14,6 +14,7 @@
 #include <linux/of.h>
 #include <linux/err.h>
 #include <soc/imx/revision.h>
+#include <soc/imx/timer.h>
 #include <asm/irq.h>
 
 #include "clk.h"
@@ -293,7 +294,7 @@ int __init mx35_clocks_init(void)
 
 	imx_print_silicon_rev("i.MX35", mx35_revision());
 
-	mxc_timer_init(MX35_GPT1_BASE_ADDR, MX35_INT_GPT);
+	mxc_timer_init(MX35_GPT1_BASE_ADDR, MX35_INT_GPT, GPT_TYPE_IMX31);
 
 	return 0;
 }
drivers/clk/imx/clk.h +0 -7
index 8b112182a83b..1049b0c7d818 100644
@@ -6,13 +6,6 @@
 
 extern spinlock_t imx_ccm_lock;
 
-/*
- * This is a stop-gap solution for clock drivers like imx1/imx21 which call
- * mxc_timer_init() to initialize timer for non-DT boot.  It can be removed
- * when these legacy non-DT support is converted or dropped.
- */
-void mxc_timer_init(unsigned long pbase, int irq);
-
 void imx_check_clocks(struct clk *clks[], unsigned int count);
 
 extern void imx_cscmr1_fixup(u32 *val);
include/soc/imx/timer.h new file +26 -0
new file mode 100644
index 000000000000..bbbafd65f464
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Linaro Ltd.
+ *
+ * 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 __SOC_IMX_TIMER_H__
+#define __SOC_IMX_TIMER_H__
+
+enum imx_gpt_type {
+	GPT_TYPE_IMX1,		/* i.MX1 */
+	GPT_TYPE_IMX21,		/* i.MX21/27 */
+	GPT_TYPE_IMX31,		/* i.MX31/35/25/37/51/6Q */
+	GPT_TYPE_IMX6DL,	/* i.MX6DL/SX/SL */
+};
+
+/*
+ * This is a stop-gap solution for clock drivers like imx1/imx21 which call
+ * mxc_timer_init() to initialize timer for non-DT boot.  It can be removed
+ * when these legacy non-DT support is converted or dropped.
+ */
+void mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type);
+
+#endif  /* __SOC_IMX_TIMER_H__ */
Signature · 1 line
1.9.1
author
#4 lore raw

PATCH v2 4/12 ARM: imx: initialize gpt device type for DT boot

In reply to Shawn Guo

Use different initialization function in CLOCKSOURCE_OF_DECLARE() to initialize gpt device type for DT boot.

---
 arch/arm/mach-imx/time.c | 44 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 9 deletions(-)
arch/arm/mach-imx/time.c +35 -9
index 307cbc7abc8e..cf88355654dd 100644
@@ -376,7 +376,7 @@ void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type)
 	_mxc_timer_init(imxtm);
 }
 
-static void __init mxc_timer_init_dt(struct device_node *np)
+static void __init mxc_timer_init_dt(struct device_node *np,  enum imx_gpt_type type)
 {
 	struct imx_timer *imxtm;
 	static int initialized;
@@ -399,15 +399,41 @@ static void __init mxc_timer_init_dt(struct device_node *np)
 	if (IS_ERR(imxtm->clk_per))
 		imxtm->clk_per = of_clk_get_by_name(np, "per");
 
+	imxtm->type = type;
+
 	_mxc_timer_init(imxtm);
 
 	initialized = 1;
 }
-CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(mx25_timer, "fsl,imx25-gpt", mxc_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(mx50_timer, "fsl,imx50-gpt", mxc_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(mx51_timer, "fsl,imx51-gpt", mxc_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(mx53_timer, "fsl,imx53-gpt", mxc_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(mx6q_timer, "fsl,imx6q-gpt", mxc_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(mx6sl_timer, "fsl,imx6sl-gpt", mxc_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(mx6sx_timer, "fsl,imx6sx-gpt", mxc_timer_init_dt);
+
+static void __init imx1_timer_init_dt(struct device_node *np)
+{
+	mxc_timer_init_dt(np, GPT_TYPE_IMX1);
+}
+
+static void __init imx21_timer_init_dt(struct device_node *np)
+{
+	mxc_timer_init_dt(np, GPT_TYPE_IMX21);
+}
+
+static void __init imx31_timer_init_dt(struct device_node *np)
+{
+	mxc_timer_init_dt(np, GPT_TYPE_IMX31);
+}
+
+static void __init imx6dl_timer_init_dt(struct device_node *np)
+{
+	mxc_timer_init_dt(np, GPT_TYPE_IMX6DL);
+}
+
+CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
+CLOCKSOURCE_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);
Signature · 1 line
1.9.1
author
#5 lore raw

PATCH v2 5/12 ARM: imx: setup tctl register in device specific function

In reply to Shawn Guo

It creates a gpt device speicific data structure and adds function hook gpt_setup_tctl in there to set up gpt TCTL register.

---
 arch/arm/mach-imx/time.c | 98 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 78 insertions(+), 20 deletions(-)
arch/arm/mach-imx/time.c +78 -20
index cf88355654dd..2fbc3022ce3f 100644
@@ -92,6 +92,11 @@ struct imx_timer {
 	int irq;
 	struct clk *clk_per;
 	struct clk *clk_ipg;
+	const struct imx_gpt_data *gpt;
+};
+
+struct imx_gpt_data {
+	void (*gpt_setup_tctl)(struct imx_timer *imxtm);
 };
 
 static void __iomem *timer_base;
@@ -307,13 +312,83 @@ static int __init mxc_clockevent_init(struct imx_timer *imxtm)
 	return 0;
 }
 
-static void __init _mxc_timer_init(struct imx_timer *imxtm)
+static void imx1_gpt_setup_tctl(struct imx_timer *imxtm)
+{
+	u32 tctl_val;
+
+	tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
+	writel_relaxed(tctl_val, imxtm->base + MXC_TCTL);
+}
+#define imx21_gpt_setup_tctl imx1_gpt_setup_tctl
+
+static void imx31_gpt_setup_tctl(struct imx_timer *imxtm)
+{
+	u32 tctl_val;
+
+	tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
+	if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8)
+		tctl_val |= V2_TCTL_CLK_OSC_DIV8;
+	else
+		tctl_val |= V2_TCTL_CLK_PER;
+
+	writel_relaxed(tctl_val, imxtm->base + MXC_TCTL);
+}
+
+static void imx6dl_gpt_setup_tctl(struct imx_timer *imxtm)
 {
-	uint32_t tctl_val;
+	u32 tctl_val;
+
+	tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
+	if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8) {
+		tctl_val |= V2_TCTL_CLK_OSC_DIV8;
+		/* 24 / 8 = 3 MHz */
+		writel_relaxed(7 << V2_TPRER_PRE24M, imxtm->base + MXC_TPRER);
+		tctl_val |= V2_TCTL_24MEN;
+	} else {
+		tctl_val |= V2_TCTL_CLK_PER;
+	}
+
+	writel_relaxed(tctl_val, imxtm->base + MXC_TCTL);
+}
 
+static const struct imx_gpt_data imx1_gpt_data = {
+	.gpt_setup_tctl = imx1_gpt_setup_tctl,
+};
+
+static const struct imx_gpt_data imx21_gpt_data = {
+	.gpt_setup_tctl = imx21_gpt_setup_tctl,
+};
+
+static const struct imx_gpt_data imx31_gpt_data = {
+	.gpt_setup_tctl = imx31_gpt_setup_tctl,
+};
+
+static const struct imx_gpt_data imx6dl_gpt_data = {
+	.gpt_setup_tctl = imx6dl_gpt_setup_tctl,
+};
+
+static void __init _mxc_timer_init(struct imx_timer *imxtm)
+{
 	/* Temporary */
 	timer_base = imxtm->base;
 
+	switch (imxtm->type) {
+	case GPT_TYPE_IMX1:
+		imxtm->gpt = &imx1_gpt_data;
+		break;
+	case GPT_TYPE_IMX21:
+		imxtm->gpt = &imx21_gpt_data;
+		break;
+	case GPT_TYPE_IMX31:
+		imxtm->gpt = &imx31_gpt_data;
+		break;
+	case GPT_TYPE_IMX6DL:
+		imxtm->gpt = &imx6dl_gpt_data;
+		break;
+	default:
+		BUG();
+	}
+
 	if (IS_ERR(imxtm->clk_per)) {
 		pr_err("i.MX timer: unable to get clk\n");
 		return;
@@ -331,24 +406,7 @@ static void __init _mxc_timer_init(struct imx_timer *imxtm)
 	writel_relaxed(0, imxtm->base + MXC_TCTL);
 	writel_relaxed(0, imxtm->base + MXC_TPRER); /* see datasheet note */
 
-	if (timer_is_v2()) {
-		tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
-		if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8) {
-			tctl_val |= V2_TCTL_CLK_OSC_DIV8;
-			if (cpu_is_imx6dl() || cpu_is_imx6sx()) {
-				/* 24 / 8 = 3 MHz */
-				writel_relaxed(7 << V2_TPRER_PRE24M,
-					imxtm->base + MXC_TPRER);
-				tctl_val |= V2_TCTL_24MEN;
-			}
-		} else {
-			tctl_val |= V2_TCTL_CLK_PER;
-		}
-	} else {
-		tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
-	}
-
-	writel_relaxed(tctl_val, imxtm->base + MXC_TCTL);
+	imxtm->gpt->gpt_setup_tctl(imxtm);
 
 	/* init and register the timer to the framework */
 	mxc_clocksource_init(imxtm);
Signature · 1 line
1.9.1
#6 lore raw

PATCH v2 5/12 ARM: imx: setup tctl register in device specific function

Hi Shawn,

Quoted 4 lines · Shawn Guo

It creates a gpt device speicific data structure and adds function hook gpt_setup_tctl in there to set up gpt TCTL register.

Starting with next-20150529, imx6dl-wandboard (both dual and solo) started having boot failures[1]. Today I bisected it down to this commit. It didn't revert cleanly, so I didn't verify that this patch alone is the root cause, but reproducing the boot failure should be pretty easy on wandboard with recent linux-next.

Kevin

[1] http://kernelci.org/boot/all/job/next/kernel/next-20150529/

author
#7 lore raw

PATCH v2 5/12 ARM: imx: setup tctl register in device specific function

Hi Kevin,

Quoted 6 lines · Kevin Hilman

Hi Shawn,

Quoted 3 lines · Shawn Guo

It creates a gpt device speicific data structure and adds function hook gpt_setup_tctl in there to set up gpt TCTL register.

Quoted 7 lines
Quoted 1 line

Starting with next-20150529, imx6dl-wandboard (both dual and solo) started having boot failures[1]. Today I bisected it down to this commit. It didn't revert cleanly, so I didn't verify that this patch alone is the root cause, but reproducing the boot failure should be pretty easy on wandboard with recent linux-next.

The imx clocksource driver was marked as BROKEN on linux-next, because it causes a build error on powerpc allyesconfig build [1]. I'm working on a fix for it.

Can you please try to remove the BROKEN mark in your test to see if it fixes your problem?

Sorry for the breakage.

Shawn

[1] http://www.mail-archive.com/linux-kernel at vger.kernel.org/msg901156.html

#8 lore raw

PATCH v2 5/12 ARM: imx: setup tctl register in device specific function

Quoted 17 lines · Shawn Guo

Hi Kevin,

Quoted 6 lines · Kevin Hilman

Hi Shawn,

Quoted 3 lines · Shawn Guo

It creates a gpt device speicific data structure and adds function hook gpt_setup_tctl in there to set up gpt TCTL register.

Quoted 7 lines
Quoted 1 line

Starting with next-20150529, imx6dl-wandboard (both dual and solo) started having boot failures[1]. Today I bisected it down to this commit. It didn't revert cleanly, so I didn't verify that this patch alone is the root cause, but reproducing the boot failure should be pretty easy on wandboard with recent linux-next.

Quoted 6 lines

The imx clocksource driver was marked as BROKEN on linux-next, because it causes a build error on powerpc allyesconfig build [1]. I'm working on a fix for it.

Can you please try to remove the BROKEN mark in your test to see if it fixes your problem?

I'm just using multi_v7_defconfig, and BROKEN is not set, but that driver is still built because it's explicitly selected by ARCH_MXC:

$ git describe
next-20150601
$ rm build/.config
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build multi_v7_defconfig
make[1]: Entering directory `/work/kernel/next/build'
  GEN     ./Makefile
arch/arm/configs/multi_v7_defconfig:603:warning: override: reassigning
to symbol COMMON_CLK_QCOM
warning: (ARCH_MXC) selects CLKSRC_IMX_GPT which has unmet direct
dependencies (OF && BROKEN)
warning: (ARCH_MXC) selects CLKSRC_IMX_GPT which has unmet direct
dependencies (OF && BROKEN)
#
# configuration written to .config
#
make[1]: Leaving directory `/work/kernel/next/build'
$ grep CLKSRC_IMX_GPT build/.config
CONFIG_CLKSRC_IMX_GPT=y
$

Kevin

#9 lore raw

PATCH v2 5/12 ARM: imx: setup tctl register in device specific function

Quoted 14 lines · Kevin Hilman

I'm just using multi_v7_defconfig, and BROKEN is not set, but that driver is still built because it's explicitly selected by ARCH_MXC:

$ git describe
next-20150601
$ rm build/.config
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build multi_v7_defconfig
make[1]: Entering directory `/work/kernel/next/build'
  GEN     ./Makefile
arch/arm/configs/multi_v7_defconfig:603:warning: override: reassigning
to symbol COMMON_CLK_QCOM
warning: (ARCH_MXC) selects CLKSRC_IMX_GPT which has unmet direct
dependencies (OF && BROKEN)
warning: (ARCH_MXC) selects CLKSRC_IMX_GPT which has unmet direct
Quoted 8 lines
dependencies (OF && BROKEN)
#
# configuration written to .config
#
make[1]: Leaving directory `/work/kernel/next/build'
$ grep CLKSRC_IMX_GPT build/.config
CONFIG_CLKSRC_IMX_GPT=y
$

Yes, you're right. It's broken on i.MX6DL/S indeed. The cause is that i.MX6DL/S DTBs are using the same GPT compatible string as i.MX6Q. It effectively makes kernel select an incorrect GPT device type on i.MX6DL/S. We will need to update i.MX6DL/S device tree to use a correct compatible string. But to keep the existing DTBs continue working, we need the following change. As I'm asked by Arnd to rebase my branch, I would like fold the changes into the original patch to save the git bisect issue.

Thanks for the bug report, and sorry for the breakage.

Shawn

-----8<------------------

drivers/clocksource/timer-imx-gpt.c +12 -1
index a98d1104b3fd..e41b021b9d62 100644
@@ -508,7 +508,18 @@ static void __init imx21_timer_init_dt(struct device_node *np)
 
 static void __init imx31_timer_init_dt(struct device_node *np)
 {
-       mxc_timer_init_dt(np, GPT_TYPE_IMX31);
+       enum imx_gpt_type type = GPT_TYPE_IMX31;
+
+       /*
+        * We were using the same compatible string for i.MX6Q/D and i.MX6DL/S
+        * GPT device, while they actually have different programming model.
+        * This is a workaround to keep the existing i.MX6DL/S DTBs continue
+        * working with the new kernel.
+        */
+       if (of_machine_is_compatible("fsl,imx6dl"))
+               type = GPT_TYPE_IMX6DL;
+
+       mxc_timer_init_dt(np, type);
 }
 
 static void __init imx6dl_timer_init_dt(struct device_node *np)
#10 lore raw

PATCH v2 5/12 ARM: imx: setup tctl register in device specific function

Quoted 24 lines · Shawn Guo
Quoted 14 lines · Kevin Hilman

I'm just using multi_v7_defconfig, and BROKEN is not set, but that driver is still built because it's explicitly selected by ARCH_MXC:

$ git describe
next-20150601
$ rm build/.config
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=build multi_v7_defconfig
make[1]: Entering directory `/work/kernel/next/build'
  GEN     ./Makefile
arch/arm/configs/multi_v7_defconfig:603:warning: override: reassigning
to symbol COMMON_CLK_QCOM
warning: (ARCH_MXC) selects CLKSRC_IMX_GPT which has unmet direct
dependencies (OF && BROKEN)
warning: (ARCH_MXC) selects CLKSRC_IMX_GPT which has unmet direct
Quoted 8 lines
dependencies (OF && BROKEN)
#
# configuration written to .config
#
make[1]: Leaving directory `/work/kernel/next/build'
$ grep CLKSRC_IMX_GPT build/.config
CONFIG_CLKSRC_IMX_GPT=y
$
Quoted 8 lines

Yes, you're right. It's broken on i.MX6DL/S indeed. The cause is that i.MX6DL/S DTBs are using the same GPT compatible string as i.MX6Q. It effectively makes kernel select an incorrect GPT device type on i.MX6DL/S. We will need to update i.MX6DL/S device tree to use a correct compatible string. But to keep the existing DTBs continue working, we need the following change. As I'm asked by Arnd to rebase my branch, I would like fold the changes into the original patch to save the git bisect issue.

I tried your patch on top of next-20150529 (where I originally found the issue) and it gets my wandboard dual and solo booting again.

Kevin

#11 lore raw

PATCH v2 5/12 ARM: imx: setup tctl register in device specific function

Quoted 4 lines · Kevin Hilman

I tried your patch on top of next-20150529 (where I originally found the issue) and it gets my wandboard dual and solo booting again.

Thanks for confirming, Kevin.

Shawn

author
#12 lore raw

PATCH v2 6/12 ARM: imx: set up .set_next_event hook via imx_gpt_data

In reply to Shawn Guo

Set up .set_next_event hook via imx_gpt_data, so that we can save the use of timer_is_v2().

---
 arch/arm/mach-imx/time.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
arch/arm/mach-imx/time.c +7 -3
index 2fbc3022ce3f..ceba782a1f1d 100644
@@ -97,6 +97,8 @@ struct imx_timer {
 
 struct imx_gpt_data {
 	void (*gpt_setup_tctl)(struct imx_timer *imxtm);
+	int (*set_next_event)(unsigned long evt,
+			      struct clock_event_device *ced);
 };
 
 static void __iomem *timer_base;
@@ -301,9 +303,7 @@ static struct clock_event_device clockevent_mxc = {
 
 static int __init mxc_clockevent_init(struct imx_timer *imxtm)
 {
-	if (timer_is_v2())
-		clockevent_mxc.set_next_event = v2_set_next_event;
-
+	clockevent_mxc.set_next_event = imxtm->gpt->set_next_event;
 	clockevent_mxc.cpumask = cpumask_of(0);
 	clockevents_config_and_register(&clockevent_mxc,
 					clk_get_rate(imxtm->clk_per),
@@ -353,18 +353,22 @@ static void imx6dl_gpt_setup_tctl(struct imx_timer *imxtm)
 
 static const struct imx_gpt_data imx1_gpt_data = {
 	.gpt_setup_tctl = imx1_gpt_setup_tctl,
+	.set_next_event = mx1_2_set_next_event,
 };
 
 static const struct imx_gpt_data imx21_gpt_data = {
 	.gpt_setup_tctl = imx21_gpt_setup_tctl,
+	.set_next_event = mx1_2_set_next_event,
 };
 
 static const struct imx_gpt_data imx31_gpt_data = {
 	.gpt_setup_tctl = imx31_gpt_setup_tctl,
+	.set_next_event = v2_set_next_event,
 };
 
 static const struct imx_gpt_data imx6dl_gpt_data = {
 	.gpt_setup_tctl = imx6dl_gpt_setup_tctl,
+	.set_next_event = v2_set_next_event,
 };
 
 static void __init _mxc_timer_init(struct imx_timer *imxtm)
Signature · 1 line
1.9.1
author
#13 lore raw

PATCH v2 7/12 ARM: imx: move clock event variables into imx_timer

In reply to Shawn Guo

Since we now have imx_timer structure, it makes more sense to move those clock event related variables into the structure, so that we can save some global variables.

---
 arch/arm/mach-imx/time.c | 64 +++++++++++++++++++++++++-----------------------
 1 file changed, 33 insertions(+), 31 deletions(-)
arch/arm/mach-imx/time.c +33 -31
index ceba782a1f1d..c4692e0a944f 100644
@@ -83,9 +83,6 @@
 #define timer_is_v1()	(cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
 #define timer_is_v2()	(!timer_is_v1())
 
-static struct clock_event_device clockevent_mxc;
-static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
-
 struct imx_timer {
 	enum imx_gpt_type type;
 	void __iomem *base;
@@ -93,6 +90,9 @@ struct imx_timer {
 	struct clk *clk_per;
 	struct clk *clk_ipg;
 	const struct imx_gpt_data *gpt;
+	struct clock_event_device ced;
+	enum clock_event_mode cem;
+	struct irqaction act;
 };
 
 struct imx_gpt_data {
@@ -103,6 +103,11 @@ struct imx_gpt_data {
 
 static void __iomem *timer_base;
 
+static inline struct imx_timer *to_imx_timer(struct clock_event_device *ced)
+{
+	return container_of(ced, struct imx_timer, ced);
+}
+
 static inline void gpt_irq_disable(void)
 {
 	unsigned int tmp;
@@ -207,8 +212,9 @@ static const char *clock_event_mode_label[] = {
 #endif /* DEBUG */
 
 static void mxc_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
+				struct clock_event_device *ced)
 {
+	struct imx_timer *imxtm = to_imx_timer(ced);
 	unsigned long flags;
 
 	/*
@@ -220,7 +226,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
 	/* Disable interrupt in GPT module */
 	gpt_irq_disable();
 
-	if (mode != clockevent_mode) {
+	if (mode != imxtm->cem) {
 		/* Set event time into far-far future */
 		if (timer_is_v2())
 			writel_relaxed(readl_relaxed(timer_base + V2_TCN) - 3,
@@ -235,12 +241,12 @@ static void mxc_set_mode(enum clock_event_mode mode,
 
 #ifdef DEBUG
 	printk(KERN_INFO "mxc_set_mode: changing mode from %s to %s\n",
-		clock_event_mode_label[clockevent_mode],
+		clock_event_mode_label[imxtm->cem],
 		clock_event_mode_label[mode]);
 #endif /* DEBUG */
 
 	/* Remember timer mode */
-	clockevent_mode = mode;
+	imxtm->cem = mode;
 	local_irq_restore(flags);
 
 	switch (mode) {
@@ -272,7 +278,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
  */
 static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = &clockevent_mxc;
+	struct clock_event_device *ced = dev_id;
 	uint32_t tstat;
 
 	if (timer_is_v2())
@@ -282,34 +288,33 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 
 	gpt_irq_acknowledge();
 
-	evt->event_handler(evt);
+	ced->event_handler(ced);
 
 	return IRQ_HANDLED;
 }
 
-static struct irqaction mxc_timer_irq = {
-	.name		= "i.MX Timer Tick",
-	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= mxc_timer_interrupt,
-};
-
-static struct clock_event_device clockevent_mxc = {
-	.name		= "mxc_timer1",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode	= mxc_set_mode,
-	.set_next_event	= mx1_2_set_next_event,
-	.rating		= 200,
-};
-
 static int __init mxc_clockevent_init(struct imx_timer *imxtm)
 {
-	clockevent_mxc.set_next_event = imxtm->gpt->set_next_event;
-	clockevent_mxc.cpumask = cpumask_of(0);
-	clockevents_config_and_register(&clockevent_mxc,
-					clk_get_rate(imxtm->clk_per),
+	struct clock_event_device *ced = &imxtm->ced;
+	struct irqaction *act = &imxtm->act;
+
+	imxtm->cem = CLOCK_EVT_MODE_UNUSED;
+
+	ced->name = "mxc_timer1";
+	ced->features = CLOCK_EVT_FEAT_ONESHOT;
+	ced->set_mode = mxc_set_mode;
+	ced->set_next_event = imxtm->gpt->set_next_event;
+	ced->rating = 200;
+	ced->cpumask = cpumask_of(0);
+	clockevents_config_and_register(ced, clk_get_rate(imxtm->clk_per),
 					0xff, 0xfffffffe);
 
-	return 0;
+	act->name = "i.MX Timer Tick";
+	act->flags = IRQF_TIMER | IRQF_IRQPOLL;
+	act->handler = mxc_timer_interrupt;
+	act->dev_id = ced;
+
+	return setup_irq(imxtm->irq, act);
 }
 
 static void imx1_gpt_setup_tctl(struct imx_timer *imxtm)
@@ -415,9 +420,6 @@ static void __init _mxc_timer_init(struct imx_timer *imxtm)
 	/* init and register the timer to the framework */
 	mxc_clocksource_init(imxtm);
 	mxc_clockevent_init(imxtm);
-
-	/* Make irqs happen */
-	setup_irq(imxtm->irq, &mxc_timer_irq);
 }
 
 void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type)
Signature · 1 line
1.9.1
author
#14 lore raw

PATCH v2 8/12 ARM: imx: define gpt register offset per device type

In reply to Shawn Guo

It defines offset of gpt registers TSTAT, TCN and TCMP per device type in imx_gpt_data, so that these registers can be accessed in an way without timer_is_v2() checking.

---
 arch/arm/mach-imx/time.c | 31 ++++++++++++++++++++-----------
 1 file changed, 20 insertions(+), 11 deletions(-)
arch/arm/mach-imx/time.c +20 -11
index c4692e0a944f..da1ad20d2c1d 100644
@@ -96,6 +96,9 @@ struct imx_timer {
 };
 
 struct imx_gpt_data {
+	int reg_tstat;
+	int reg_tcn;
+	int reg_tcmp;
 	void (*gpt_setup_tctl)(struct imx_timer *imxtm);
 	int (*set_next_event)(unsigned long evt,
 			      struct clock_event_device *ced);
@@ -159,7 +162,7 @@ static unsigned long imx_read_current_timer(void)
 static int __init mxc_clocksource_init(struct imx_timer *imxtm)
 {
 	unsigned int c = clk_get_rate(imxtm->clk_per);
-	void __iomem *reg = imxtm->base + (timer_is_v2() ? V2_TCN : MX1_2_TCN);
+	void __iomem *reg = imxtm->base + imxtm->gpt->reg_tcn;
 
 	imx_delay_timer.read_current_timer = &imx_read_current_timer;
 	imx_delay_timer.freq = c;
@@ -227,13 +230,9 @@ static void mxc_set_mode(enum clock_event_mode mode,
 	gpt_irq_disable();
 
 	if (mode != imxtm->cem) {
+		u32 tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn);
 		/* Set event time into far-far future */
-		if (timer_is_v2())
-			writel_relaxed(readl_relaxed(timer_base + V2_TCN) - 3,
-					timer_base + V2_TCMP);
-		else
-			writel_relaxed(readl_relaxed(timer_base + MX1_2_TCN) - 3,
-					timer_base + MX1_2_TCMP);
+		writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp);
 
 		/* Clear pending interrupt */
 		gpt_irq_acknowledge();
@@ -279,12 +278,10 @@ static void mxc_set_mode(enum clock_event_mode mode,
 static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *ced = dev_id;
+	struct imx_timer *imxtm = to_imx_timer(ced);
 	uint32_t tstat;
 
-	if (timer_is_v2())
-		tstat = readl_relaxed(timer_base + V2_TSTAT);
-	else
-		tstat = readl_relaxed(timer_base + MX1_2_TSTAT);
+	tstat = readl_relaxed(imxtm->base + imxtm->gpt->reg_tstat);
 
 	gpt_irq_acknowledge();
 
@@ -357,21 +354,33 @@ static void imx6dl_gpt_setup_tctl(struct imx_timer *imxtm)
 }
 
 static const struct imx_gpt_data imx1_gpt_data = {
+	.reg_tstat = MX1_2_TSTAT,
+	.reg_tcn = MX1_2_TCN,
+	.reg_tcmp = MX1_2_TCMP,
 	.gpt_setup_tctl = imx1_gpt_setup_tctl,
 	.set_next_event = mx1_2_set_next_event,
 };
 
 static const struct imx_gpt_data imx21_gpt_data = {
+	.reg_tstat = MX1_2_TSTAT,
+	.reg_tcn = MX1_2_TCN,
+	.reg_tcmp = MX1_2_TCMP,
 	.gpt_setup_tctl = imx21_gpt_setup_tctl,
 	.set_next_event = mx1_2_set_next_event,
 };
 
 static const struct imx_gpt_data imx31_gpt_data = {
+	.reg_tstat = V2_TSTAT,
+	.reg_tcn = V2_TCN,
+	.reg_tcmp = V2_TCMP,
 	.gpt_setup_tctl = imx31_gpt_setup_tctl,
 	.set_next_event = v2_set_next_event,
 };
 
 static const struct imx_gpt_data imx6dl_gpt_data = {
+	.reg_tstat = V2_TSTAT,
+	.reg_tcn = V2_TCN,
+	.reg_tcmp = V2_TCMP,
 	.gpt_setup_tctl = imx6dl_gpt_setup_tctl,
 	.set_next_event = v2_set_next_event,
 };
Signature · 1 line
1.9.1
author
#15 lore raw

PATCH v2 9/12 ARM: imx: get rid of variable timer_base

In reply to Shawn Guo

We now have pointer to imx_timer structure available where timer base address is needed, so we can just kill global timer_base by using imxtm->base instead.

---
 arch/arm/mach-imx/time.c | 55 +++++++++++++++++++++++-------------------------
 1 file changed, 26 insertions(+), 29 deletions(-)
arch/arm/mach-imx/time.c +26 -29
index da1ad20d2c1d..a4f12c75050f 100644
@@ -104,45 +104,43 @@ struct imx_gpt_data {
 			      struct clock_event_device *ced);
 };
 
-static void __iomem *timer_base;
-
 static inline struct imx_timer *to_imx_timer(struct clock_event_device *ced)
 {
 	return container_of(ced, struct imx_timer, ced);
 }
 
-static inline void gpt_irq_disable(void)
+static inline void gpt_irq_disable(struct imx_timer *imxtm)
 {
 	unsigned int tmp;
 
 	if (timer_is_v2())
-		writel_relaxed(0, timer_base + V2_IR);
+		writel_relaxed(0, imxtm->base + V2_IR);
 	else {
-		tmp = readl_relaxed(timer_base + MXC_TCTL);
-		writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
+		tmp = readl_relaxed(imxtm->base + MXC_TCTL);
+		writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL);
 	}
 }
 
-static inline void gpt_irq_enable(void)
+static inline void gpt_irq_enable(struct imx_timer *imxtm)
 {
 	if (timer_is_v2())
-		writel_relaxed(1<<0, timer_base + V2_IR);
+		writel_relaxed(1<<0, imxtm->base + V2_IR);
 	else {
-		writel_relaxed(readl_relaxed(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
-			timer_base + MXC_TCTL);
+		writel_relaxed(readl_relaxed(imxtm->base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
+			imxtm->base + MXC_TCTL);
 	}
 }
 
-static void gpt_irq_acknowledge(void)
+static void gpt_irq_acknowledge(struct imx_timer *imxtm)
 {
 	if (timer_is_v1()) {
 		if (cpu_is_mx1())
-			writel_relaxed(0, timer_base + MX1_2_TSTAT);
+			writel_relaxed(0, imxtm->base + MX1_2_TSTAT);
 		else
 			writel_relaxed(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
-				timer_base + MX1_2_TSTAT);
+				imxtm->base + MX1_2_TSTAT);
 	} else if (timer_is_v2())
-		writel_relaxed(V2_TSTAT_OF1, timer_base + V2_TSTAT);
+		writel_relaxed(V2_TSTAT_OF1, imxtm->base + V2_TSTAT);
 }
 
 static void __iomem *sched_clock_reg;
@@ -178,29 +176,31 @@ static int __init mxc_clocksource_init(struct imx_timer *imxtm)
 /* clock event */
 
 static int mx1_2_set_next_event(unsigned long evt,
-			      struct clock_event_device *unused)
+			      struct clock_event_device *ced)
 {
+	struct imx_timer *imxtm = to_imx_timer(ced);
 	unsigned long tcmp;
 
-	tcmp = readl_relaxed(timer_base + MX1_2_TCN) + evt;
+	tcmp = readl_relaxed(imxtm->base + MX1_2_TCN) + evt;
 
-	writel_relaxed(tcmp, timer_base + MX1_2_TCMP);
+	writel_relaxed(tcmp, imxtm->base + MX1_2_TCMP);
 
-	return (int)(tcmp - readl_relaxed(timer_base + MX1_2_TCN)) < 0 ?
+	return (int)(tcmp - readl_relaxed(imxtm->base + MX1_2_TCN)) < 0 ?
 				-ETIME : 0;
 }
 
 static int v2_set_next_event(unsigned long evt,
-			      struct clock_event_device *unused)
+			      struct clock_event_device *ced)
 {
+	struct imx_timer *imxtm = to_imx_timer(ced);
 	unsigned long tcmp;
 
-	tcmp = readl_relaxed(timer_base + V2_TCN) + evt;
+	tcmp = readl_relaxed(imxtm->base + V2_TCN) + evt;
 
-	writel_relaxed(tcmp, timer_base + V2_TCMP);
+	writel_relaxed(tcmp, imxtm->base + V2_TCMP);
 
 	return evt < 0x7fffffff &&
-		(int)(tcmp - readl_relaxed(timer_base + V2_TCN)) < 0 ?
+		(int)(tcmp - readl_relaxed(imxtm->base + V2_TCN)) < 0 ?
 				-ETIME : 0;
 }
 
@@ -227,7 +227,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
 	local_irq_save(flags);
 
 	/* Disable interrupt in GPT module */
-	gpt_irq_disable();
+	gpt_irq_disable(imxtm);
 
 	if (mode != imxtm->cem) {
 		u32 tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn);
@@ -235,7 +235,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
 		writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp);
 
 		/* Clear pending interrupt */
-		gpt_irq_acknowledge();
+		gpt_irq_acknowledge(imxtm);
 	}
 
 #ifdef DEBUG
@@ -261,7 +261,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
 	 * mode switching
 	 */
 		local_irq_save(flags);
-		gpt_irq_enable();
+		gpt_irq_enable(imxtm);
 		local_irq_restore(flags);
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
@@ -283,7 +283,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 
 	tstat = readl_relaxed(imxtm->base + imxtm->gpt->reg_tstat);
 
-	gpt_irq_acknowledge();
+	gpt_irq_acknowledge(imxtm);
 
 	ced->event_handler(ced);
 
@@ -387,9 +387,6 @@ static const struct imx_gpt_data imx6dl_gpt_data = {
 
 static void __init _mxc_timer_init(struct imx_timer *imxtm)
 {
-	/* Temporary */
-	timer_base = imxtm->base;
-
 	switch (imxtm->type) {
 	case GPT_TYPE_IMX1:
 		imxtm->gpt = &imx1_gpt_data;
Signature · 1 line
1.9.1
author
#16 lore raw

PATCH v2 10/12 ARM: imx: provide gpt device specific irq functions

In reply to Shawn Guo

It splits irq enable/disable/acknowledge operations into device specific functions as the hooks in imx_gpt_data, so that we can save the use of timer_is_xxx() and cpu_is_xxx() checking in these irq functions.

---
 arch/arm/mach-imx/time.c | 80 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 54 insertions(+), 26 deletions(-)
arch/arm/mach-imx/time.c +54 -26
index a4f12c75050f..5fb8397d8fe2 100644
@@ -100,6 +100,9 @@ struct imx_gpt_data {
 	int reg_tcn;
 	int reg_tcmp;
 	void (*gpt_setup_tctl)(struct imx_timer *imxtm);
+	void (*gpt_irq_enable)(struct imx_timer *imxtm);
+	void (*gpt_irq_disable)(struct imx_timer *imxtm);
+	void (*gpt_irq_acknowledge)(struct imx_timer *imxtm);
 	int (*set_next_event)(unsigned long evt,
 			      struct clock_event_device *ced);
 };
@@ -109,40 +112,53 @@ static inline struct imx_timer *to_imx_timer(struct clock_event_device *ced)
 	return container_of(ced, struct imx_timer, ced);
 }
 
-static inline void gpt_irq_disable(struct imx_timer *imxtm)
+static void imx1_gpt_irq_disable(struct imx_timer *imxtm)
 {
 	unsigned int tmp;
 
-	if (timer_is_v2())
-		writel_relaxed(0, imxtm->base + V2_IR);
-	else {
-		tmp = readl_relaxed(imxtm->base + MXC_TCTL);
-		writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL);
-	}
+	tmp = readl_relaxed(imxtm->base + MXC_TCTL);
+	writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL);
 }
+#define imx21_gpt_irq_disable imx1_gpt_irq_disable
 
-static inline void gpt_irq_enable(struct imx_timer *imxtm)
+static void imx31_gpt_irq_disable(struct imx_timer *imxtm)
 {
-	if (timer_is_v2())
-		writel_relaxed(1<<0, imxtm->base + V2_IR);
-	else {
-		writel_relaxed(readl_relaxed(imxtm->base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
-			imxtm->base + MXC_TCTL);
-	}
+	writel_relaxed(0, imxtm->base + V2_IR);
+}
+#define imx6dl_gpt_irq_disable imx31_gpt_irq_disable
+
+static void imx1_gpt_irq_enable(struct imx_timer *imxtm)
+{
+	unsigned int tmp;
+
+	tmp = readl_relaxed(imxtm->base + MXC_TCTL);
+	writel_relaxed(tmp | MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL);
+}
+#define imx21_gpt_irq_enable imx1_gpt_irq_enable
+
+static void imx31_gpt_irq_enable(struct imx_timer *imxtm)
+{
+	writel_relaxed(1<<0, imxtm->base + V2_IR);
+}
+#define imx6dl_gpt_irq_enable imx31_gpt_irq_enable
+
+static void imx1_gpt_irq_acknowledge(struct imx_timer *imxtm)
+{
+	writel_relaxed(0, imxtm->base + MX1_2_TSTAT);
 }
 
-static void gpt_irq_acknowledge(struct imx_timer *imxtm)
+static void imx21_gpt_irq_acknowledge(struct imx_timer *imxtm)
 {
-	if (timer_is_v1()) {
-		if (cpu_is_mx1())
-			writel_relaxed(0, imxtm->base + MX1_2_TSTAT);
-		else
-			writel_relaxed(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
+	writel_relaxed(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
 				imxtm->base + MX1_2_TSTAT);
-	} else if (timer_is_v2())
-		writel_relaxed(V2_TSTAT_OF1, imxtm->base + V2_TSTAT);
 }
 
+static void imx31_gpt_irq_acknowledge(struct imx_timer *imxtm)
+{
+	writel_relaxed(V2_TSTAT_OF1, imxtm->base + V2_TSTAT);
+}
+#define imx6dl_gpt_irq_acknowledge imx31_gpt_irq_acknowledge
+
 static void __iomem *sched_clock_reg;
 
 static u64 notrace mxc_read_sched_clock(void)
@@ -227,7 +243,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
 	local_irq_save(flags);
 
 	/* Disable interrupt in GPT module */
-	gpt_irq_disable(imxtm);
+	imxtm->gpt->gpt_irq_disable(imxtm);
 
 	if (mode != imxtm->cem) {
 		u32 tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn);
@@ -235,7 +251,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
 		writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp);
 
 		/* Clear pending interrupt */
-		gpt_irq_acknowledge(imxtm);
+		imxtm->gpt->gpt_irq_acknowledge(imxtm);
 	}
 
 #ifdef DEBUG
@@ -261,7 +277,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
 	 * mode switching
 	 */
 		local_irq_save(flags);
-		gpt_irq_enable(imxtm);
+		imxtm->gpt->gpt_irq_enable(imxtm);
 		local_irq_restore(flags);
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
@@ -283,7 +299,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 
 	tstat = readl_relaxed(imxtm->base + imxtm->gpt->reg_tstat);
 
-	gpt_irq_acknowledge(imxtm);
+	imxtm->gpt->gpt_irq_acknowledge(imxtm);
 
 	ced->event_handler(ced);
 
@@ -357,6 +373,9 @@ static const struct imx_gpt_data imx1_gpt_data = {
 	.reg_tstat = MX1_2_TSTAT,
 	.reg_tcn = MX1_2_TCN,
 	.reg_tcmp = MX1_2_TCMP,
+	.gpt_irq_enable = imx1_gpt_irq_enable,
+	.gpt_irq_disable = imx1_gpt_irq_disable,
+	.gpt_irq_acknowledge = imx1_gpt_irq_acknowledge,
 	.gpt_setup_tctl = imx1_gpt_setup_tctl,
 	.set_next_event = mx1_2_set_next_event,
 };
@@ -365,6 +384,9 @@ static const struct imx_gpt_data imx21_gpt_data = {
 	.reg_tstat = MX1_2_TSTAT,
 	.reg_tcn = MX1_2_TCN,
 	.reg_tcmp = MX1_2_TCMP,
+	.gpt_irq_enable = imx21_gpt_irq_enable,
+	.gpt_irq_disable = imx21_gpt_irq_disable,
+	.gpt_irq_acknowledge = imx21_gpt_irq_acknowledge,
 	.gpt_setup_tctl = imx21_gpt_setup_tctl,
 	.set_next_event = mx1_2_set_next_event,
 };
@@ -373,6 +395,9 @@ static const struct imx_gpt_data imx31_gpt_data = {
 	.reg_tstat = V2_TSTAT,
 	.reg_tcn = V2_TCN,
 	.reg_tcmp = V2_TCMP,
+	.gpt_irq_enable = imx31_gpt_irq_enable,
+	.gpt_irq_disable = imx31_gpt_irq_disable,
+	.gpt_irq_acknowledge = imx31_gpt_irq_acknowledge,
 	.gpt_setup_tctl = imx31_gpt_setup_tctl,
 	.set_next_event = v2_set_next_event,
 };
@@ -381,6 +406,9 @@ static const struct imx_gpt_data imx6dl_gpt_data = {
 	.reg_tstat = V2_TSTAT,
 	.reg_tcn = V2_TCN,
 	.reg_tcmp = V2_TCMP,
+	.gpt_irq_enable = imx6dl_gpt_irq_enable,
+	.gpt_irq_disable = imx6dl_gpt_irq_disable,
+	.gpt_irq_acknowledge = imx6dl_gpt_irq_acknowledge,
 	.gpt_setup_tctl = imx6dl_gpt_setup_tctl,
 	.set_next_event = v2_set_next_event,
 };
Signature · 1 line
1.9.1
author
#17 lore raw

PATCH v2 11/12 ARM: imx: remove platform headers from timer driver

In reply to Shawn Guo

With the cleanup done before, the platform specific headers now can be removed.

---
 arch/arm/mach-imx/time.c | 6 ------
 1 file changed, 6 deletions(-)
arch/arm/mach-imx/time.c +0 -6
index 5fb8397d8fe2..ec144ce9f880 100644
@@ -36,9 +36,6 @@
 
 #include <asm/mach/time.h>
 
-#include "common.h"
-#include "hardware.h"
-
 /*
  * There are 4 versions of the timer hardware on Freescale MXC hardware.
  *  - MX1/MXL
@@ -80,9 +77,6 @@
 
 #define V2_TIMER_RATE_OSC_DIV8	3000000
 
-#define timer_is_v1()	(cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
-#define timer_is_v2()	(!timer_is_v1())
-
 struct imx_timer {
 	enum imx_gpt_type type;
 	void __iomem *base;
Signature · 1 line
1.9.1
author
#18 lore raw

PATCH v2 12/12 ARM: imx: move timer driver into drivers/clocksource

In reply to Shawn Guo

After the cleanup on imx timer driver, now it's ready to be moved into drivers/clocksource/. Let's do it.

---
 arch/arm/mach-imx/Makefile                                  | 2 +-
 drivers/clocksource/Makefile                                | 1 +
 arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx.c | 0
 3 files changed, 2 insertions(+), 1 deletion(-)
 rename arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx.c (100%)
arch/arm/mach-imx/Makefile +1 -1
index 799e65a530be..f70e18470799 100644
@@ -1,4 +1,4 @@
-obj-y := time.o cpu.o system.o irq-common.o
+obj-y := cpu.o system.o irq-common.o
 
 obj-$(CONFIG_SOC_IMX1) += mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += mm-imx21.o
drivers/clocksource/Makefile +1 -0
index 5b85f6adb258..5c5a89479631 100644
@@ -52,3 +52,4 @@ obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+= timer-integrator-ap.o
 obj-$(CONFIG_CLKSRC_VERSATILE)		+= versatile.o
 obj-$(CONFIG_CLKSRC_MIPS_GIC)		+= mips-gic-timer.o
 obj-$(CONFIG_ASM9260_TIMER)		+= asm9260_timer.o
+obj-$(CONFIG_ARCH_MXC)			+= timer-imx.o
drivers/clocksource/timer-imx.c renamed from arch/arm/mach-imx/time.c +0 -0
similarity index 100%
rename from arch/arm/mach-imx/time.c
rename to drivers/clocksource/timer-imx.c
Signature · 1 line
1.9.1
#19 lore raw

PATCH v2 12/12 ARM: imx: move timer driver into drivers/clocksource

Hi Shawn Guo

Quoted 34 lines

-----Original Message-----
From: Shawn Guo [mailto:shawn.guo at linaro.org]
Sent: 2015?5?22? 10:30
To: linux-arm-kernel at lists.infradead.org
Cc: kernel at pengutronix.de; Daniel Lezcano; Wang Shenwei-B38339; Arnd Bergmann; Shawn Guo
Subject: [PATCH v2 12/12] ARM: imx: move timer driver into drivers/clocksource

After the cleanup on imx timer driver, now it's ready to be moved into drivers/clocksource/. Let's do it.

---
 arch/arm/mach-imx/Makefile                                  | 2 +-
 drivers/clocksource/Makefile                                | 1 +
 arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx.c | 0
 3 files changed, 2 insertions(+), 1 deletion(-)  rename

arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx.c (100%)

arch/arm/mach-imx/Makefile index renamed from arch/arm/mach-imx/Makefile +0 -0

799e65a530be..f70e18470799 100644

arch/arm/mach-imx/Makefile +1 -1
@@ -1,4 +1,4 @@
-obj-y := time.o cpu.o system.o irq-common.o
+obj-y := cpu.o system.o irq-common.o
 
 obj-$(CONFIG_SOC_IMX1) += mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += mm-imx21.o
drivers/clocksource/Makefile index renamed from drivers/clocksource/Makefile +0 -0

5b85f6adb258..5c5a89479631 100644

drivers/clocksource/Makefile +0 -0
@@ -52,3 +52,4 @@ obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+=
Quoted 5 lines

timer-integrator-ap.o
obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o
obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o
obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
+obj-$(CONFIG_ARCH_MXC) += timer-imx.o

Because there are several types of timers on imx family socs, and this is the driver for the GPT block only, so it would be better to change the file name to timer-gpt.c

Regards,
Shenwei

Quoted 5 lines
drivers/clocksource/timer-imx.c renamed from arch/arm/mach-imx/time.c +0 -0
similarity index 100% rename from arch/arm/mach-imx/time.c rename to

drivers/clocksource/timer-imx.c
--
1.9.1

author
#20 lore raw

PATCH v2 12/12 ARM: imx: move timer driver into drivers/clocksource

Quoted 9 lines · Shenwei Wang
Quoted 6 lines
(quoted diff) +0 -0
@@ -52,3 +52,4 @@ obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+=

timer-integrator-ap.o
obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o
obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o
obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
+obj-$(CONFIG_ARCH_MXC) += timer-imx.o

Because there are several types of timers on imx family socs, and this is the driver for the GPT block only, so it would be better to change the file name to timer-gpt.c

Okay, I decided to name it timer-imx-gpt.c, so that when people try to find the timer driver for i.MX in drivers/clocksource folder, it will be easier.

Shawn

author
#21 lore raw

PATCH v3 12/12 ARM: imx: move timer driver into drivers/clocksource

In reply to Shawn Guo

After the cleanup on imx timer driver, now it's ready to be moved into drivers/clocksource/. Let's do it.

---
Changes since v2:
- Rename the file to timer-imx-gpt.c

 arch/arm/mach-imx/Makefile                                      | 2 +-
 drivers/clocksource/Makefile                                    | 1 +
 arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx-gpt.c | 0
 3 files changed, 2 insertions(+), 1 deletion(-)
 rename arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx-gpt.c (100%)
arch/arm/mach-imx/Makefile +1 -1
index 799e65a530be..f70e18470799 100644
@@ -1,4 +1,4 @@
-obj-y := time.o cpu.o system.o irq-common.o
+obj-y := cpu.o system.o irq-common.o
 
 obj-$(CONFIG_SOC_IMX1) += mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += mm-imx21.o
drivers/clocksource/Makefile +1 -0
index 5b85f6adb258..579e4bcf8763 100644
@@ -52,3 +52,4 @@ obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+= timer-integrator-ap.o
 obj-$(CONFIG_CLKSRC_VERSATILE)		+= versatile.o
 obj-$(CONFIG_CLKSRC_MIPS_GIC)		+= mips-gic-timer.o
 obj-$(CONFIG_ASM9260_TIMER)		+= asm9260_timer.o
+obj-$(CONFIG_ARCH_MXC)			+= timer-imx-gpt.o
drivers/clocksource/timer-imx-gpt.c renamed from arch/arm/mach-imx/time.c +0 -0
similarity index 100%
rename from arch/arm/mach-imx/time.c
rename to drivers/clocksource/timer-imx-gpt.c
Signature · 1 line
1.9.1
author
#22 lore raw

PATCH v3 12/12 ARM: imx: move timer driver into drivers/clocksource

Quoted 4 lines · Shawn Guo

After the cleanup on imx timer driver, now it's ready to be moved into drivers/clocksource/. Let's do it.

Hi Daniel,

What's your option on this? I plan to send this to arm-soc folks via i.MX tree for 4.2, but need your ACK on this one.

Shawn

Quoted 36 lines

---
Changes since v2:
- Rename the file to timer-imx-gpt.c

 arch/arm/mach-imx/Makefile                                      | 2 +-
 drivers/clocksource/Makefile                                    | 1 +
 arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx-gpt.c | 0
 3 files changed, 2 insertions(+), 1 deletion(-)
 rename arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx-gpt.c (100%)
arch/arm/mach-imx/Makefile +1 -1
index 799e65a530be..f70e18470799 100644
@@ -1,4 +1,4 @@
-obj-y := time.o cpu.o system.o irq-common.o
+obj-y := cpu.o system.o irq-common.o
 
 obj-$(CONFIG_SOC_IMX1) += mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += mm-imx21.o
drivers/clocksource/Makefile +1 -0
index 5b85f6adb258..579e4bcf8763 100644
@@ -52,3 +52,4 @@ obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+= timer-integrator-ap.o
 obj-$(CONFIG_CLKSRC_VERSATILE)		+= versatile.o
 obj-$(CONFIG_CLKSRC_MIPS_GIC)		+= mips-gic-timer.o
 obj-$(CONFIG_ASM9260_TIMER)		+= asm9260_timer.o
+obj-$(CONFIG_ARCH_MXC)			+= timer-imx-gpt.o
drivers/clocksource/timer-imx-gpt.c renamed from arch/arm/mach-imx/time.c +0 -0
similarity index 100%
rename from arch/arm/mach-imx/time.c
rename to drivers/clocksource/timer-imx-gpt.c
Signature · 1 line
1.9.1
#23 lore raw

PATCH v3 12/12 ARM: imx: move timer driver into drivers/clocksource

In reply to Shawn Guo
Quoted 4 lines · Shawn Guo

After the cleanup on imx timer driver, now it's ready to be moved into drivers/clocksource/. Let's do it.

I don't see the Kconfig change.

Signature · 5 lines
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
author
#24 lore raw

PATCH v3 12/12 ARM: imx: move timer driver into drivers/clocksource

Quoted 7 lines · Daniel Lezcano
Quoted 4 lines · Shawn Guo

After the cleanup on imx timer driver, now it's ready to be moved into drivers/clocksource/. Let's do it.

I don't see the Kconfig change.

As timer-imx-gpt is the only supported timer for i.MX, we use architecture option CONFIG_ARCH_MXC to control it for now.

Shawn

#25 lore raw

PATCH v3 12/12 ARM: imx: move timer driver into drivers/clocksource

Quoted 11 lines · Shawn Guo
Quoted 7 lines · Daniel Lezcano
Quoted 4 lines · Shawn Guo

After the cleanup on imx timer driver, now it's ready to be moved into drivers/clocksource/. Let's do it.

I don't see the Kconfig change.

As timer-imx-gpt is the only supported timer for i.MX, we use architecture option CONFIG_ARCH_MXC to control it for now.

Hi Shawn,

please use the same as:

https://lkml.org/lkml/2015/5/22/855

and then add in the platform's Kconfig the timer option as:

https://lkml.org/lkml/2015/5/22/937

Thanks

-- Daniel

Signature · 5 lines
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
author
#26 lore raw

PATCH v3 12/12 ARM: imx: move timer driver into drivers/clocksource

Quoted 7 lines · Daniel Lezcano

please use the same as:

https://lkml.org/lkml/2015/5/22/855

and then add in the platform's Kconfig the timer option as:

https://lkml.org/lkml/2015/5/22/937

Okay, here it is.

------8<--------------------------

Quoted 1 line

From fac8436459ad63531b2c39d4f060fd9420f93efd Mon Sep 17 00:00:00 2001

From: Shawn Guo <[email protected]>
Date: Fri, 15 May 2015 15:41:00 +0800
Subject: [PATCH] ARM: imx: move timer driver into drivers/clocksource

After the cleanup on imx timer driver, now it's ready to be moved into drivers/clocksource/. Let's do it.

---
 arch/arm/mach-imx/Kconfig                                       | 2 +-
 arch/arm/mach-imx/Makefile                                      | 2 +-
 drivers/clocksource/Kconfig                                     | 6 ++++++
 drivers/clocksource/Makefile                                    | 1 +
 arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx-gpt.c | 0
 5 files changed, 9 insertions(+), 2 deletions(-)
 rename arch/arm/mach-imx/time.c => drivers/clocksource/timer-imx-gpt.c (100%)
arch/arm/mach-imx/Kconfig +1 -1
index 1d8707885c57..f5813f9f31df 100644
@@ -2,7 +2,7 @@ menuconfig ARCH_MXC
 	bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_CPU_SUSPEND if PM
-	select CLKSRC_MMIO
+	select CLKSRC_IMX_GPT
 	select GENERIC_IRQ_CHIP
 	select PINCTRL
 	select PM_OPP if PM
arch/arm/mach-imx/Makefile +1 -1
index 799e65a530be..f70e18470799 100644
@@ -1,4 +1,4 @@
-obj-y := time.o cpu.o system.o irq-common.o
+obj-y := cpu.o system.o irq-common.o
 
 obj-$(CONFIG_SOC_IMX1) += mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += mm-imx21.o
drivers/clocksource/Kconfig +6 -0
index 51d7865fdddb..139a20795073 100644
@@ -258,4 +258,10 @@ config CLKSRC_PXA
 	help
 	  This enables OST0 support available on PXA and SA-11x0
 	  platforms.
+
+config CLKSRC_IMX_GPT
+	bool "Clocksource using i.MX GPT" if COMPILE_TEST
+	depends on OF
+	select CLKSRC_MMIO
+
 endmenu
drivers/clocksource/Makefile +1 -0
index 5b85f6adb258..fce332cac646 100644
@@ -51,4 +51,5 @@ obj-$(CONFIG_ARCH_KEYSTONE)		+= timer-keystone.o
 obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+= timer-integrator-ap.o
 obj-$(CONFIG_CLKSRC_VERSATILE)		+= versatile.o
 obj-$(CONFIG_CLKSRC_MIPS_GIC)		+= mips-gic-timer.o
+obj-$(CONFIG_CLKSRC_IMX_GPT)		+= timer-imx-gpt.o
 obj-$(CONFIG_ASM9260_TIMER)		+= asm9260_timer.o
drivers/clocksource/timer-imx-gpt.c renamed from arch/arm/mach-imx/time.c +0 -0
similarity index 100%
rename from arch/arm/mach-imx/time.c
rename to drivers/clocksource/timer-imx-gpt.c
Signature · 1 line
1.9.1
#27 lore raw

PATCH v3 12/12 ARM: imx: move timer driver into drivers/clocksource

Quoted 18 lines · Shawn Guo
Quoted 7 lines · Daniel Lezcano

please use the same as:

https://lkml.org/lkml/2015/5/22/855

and then add in the platform's Kconfig the timer option as:

https://lkml.org/lkml/2015/5/22/937

Okay, here it is.

------8<--------------------------

From fac8436459ad63531b2c39d4f060fd9420f93efd Mon Sep 17 00:00:00 2001
From: Shawn Guo <[email protected]>
Date: Fri, 15 May 2015 15:41:00 +0800
Subject: [PATCH] ARM: imx: move timer driver into drivers/clocksource

Quoted 5 lines

After the cleanup on imx timer driver, now it's ready to be moved into drivers/clocksource/. Let's do it.

---

Signature · 5 lines
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog