* [PATCH 1/9] ARM: imx: move timer resources into a structure
2015-05-15 8:11 [PATCH 0/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
@ 2015-05-15 8:11 ` shawnguo at kernel.org
2015-05-15 16:36 ` Shenwei Wang
2015-05-18 10:43 ` Daniel Lezcano
2015-05-15 8:11 ` [PATCH 2/9] ARM: imx: define an enum for gpt timer device type shawnguo at kernel.org
` (7 subsequent siblings)
8 siblings, 2 replies; 19+ messages in thread
From: shawnguo at kernel.org @ 2015-05-15 8:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Shawn Guo <shawn.guo@linaro.org>
Instead of passing around as argument, let's move timer resources like
irq and clocks together with base address into a data structure, and
reference the resources from the struct variable directly to simplify
the function call interface.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/time.c | 119 ++++++++++++++++++++++++-----------------------
1 file changed, 61 insertions(+), 58 deletions(-)
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index ab5ee1c445f3..8ad7cb2a7f08 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -84,27 +84,34 @@
static struct clock_event_device clockevent_mxc;
static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
-static void __iomem *timer_base;
+struct imx_timer {
+ void __iomem *base;
+ int irq;
+ struct clk *clk_per;
+ struct clk *clk_ipg;
+};
+
+static struct imx_timer imxtm;
static inline void gpt_irq_disable(void)
{
unsigned int tmp;
if (timer_is_v2())
- __raw_writel(0, timer_base + V2_IR);
+ __raw_writel(0, imxtm.base + V2_IR);
else {
- tmp = __raw_readl(timer_base + MXC_TCTL);
- __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
+ tmp = __raw_readl(imxtm.base + MXC_TCTL);
+ __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, imxtm.base + MXC_TCTL);
}
}
static inline void gpt_irq_enable(void)
{
if (timer_is_v2())
- __raw_writel(1<<0, timer_base + V2_IR);
+ __raw_writel(1<<0, imxtm.base + V2_IR);
else {
- __raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
- timer_base + MXC_TCTL);
+ __raw_writel(__raw_readl(imxtm.base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
+ imxtm.base + MXC_TCTL);
}
}
@@ -112,12 +119,12 @@ static void gpt_irq_acknowledge(void)
{
if (timer_is_v1()) {
if (cpu_is_mx1())
- __raw_writel(0, timer_base + MX1_2_TSTAT);
+ __raw_writel(0, imxtm.base + MX1_2_TSTAT);
else
__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
- timer_base + MX1_2_TSTAT);
+ imxtm.base + MX1_2_TSTAT);
} else if (timer_is_v2())
- __raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
+ __raw_writel(V2_TSTAT_OF1, imxtm.base + V2_TSTAT);
}
static void __iomem *sched_clock_reg;
@@ -134,10 +141,10 @@ static unsigned long imx_read_current_timer(void)
return __raw_readl(sched_clock_reg);
}
-static int __init mxc_clocksource_init(struct clk *timer_clk)
+static int __init mxc_clocksource_init(void)
{
- 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;
@@ -157,11 +164,11 @@ static int mx1_2_set_next_event(unsigned long evt,
{
unsigned long tcmp;
- tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
+ tcmp = __raw_readl(imxtm.base + MX1_2_TCN) + evt;
- __raw_writel(tcmp, timer_base + MX1_2_TCMP);
+ __raw_writel(tcmp, imxtm.base + MX1_2_TCMP);
- return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
+ return (int)(tcmp - __raw_readl(imxtm.base + MX1_2_TCN)) < 0 ?
-ETIME : 0;
}
@@ -170,12 +177,12 @@ static int v2_set_next_event(unsigned long evt,
{
unsigned long tcmp;
- tcmp = __raw_readl(timer_base + V2_TCN) + evt;
+ tcmp = __raw_readl(imxtm.base + V2_TCN) + evt;
- __raw_writel(tcmp, timer_base + V2_TCMP);
+ __raw_writel(tcmp, imxtm.base + V2_TCMP);
return evt < 0x7fffffff &&
- (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
+ (int)(tcmp - __raw_readl(imxtm.base + V2_TCN)) < 0 ?
-ETIME : 0;
}
@@ -206,11 +213,11 @@ 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,
- timer_base + V2_TCMP);
+ __raw_writel(__raw_readl(imxtm.base + V2_TCN) - 3,
+ imxtm.base + V2_TCMP);
else
- __raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
- timer_base + MX1_2_TCMP);
+ __raw_writel(__raw_readl(imxtm.base + MX1_2_TCN) - 3,
+ imxtm.base + MX1_2_TCMP);
/* Clear pending interrupt */
gpt_irq_acknowledge();
@@ -259,9 +266,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 = __raw_readl(imxtm.base + V2_TSTAT);
else
- tstat = __raw_readl(timer_base + MX1_2_TSTAT);
+ tstat = __raw_readl(imxtm.base + MX1_2_TSTAT);
gpt_irq_acknowledge();
@@ -284,49 +291,48 @@ 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(void)
{
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(void)
{
uint32_t tctl_val;
- if (IS_ERR(clk_per)) {
+ 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)
*/
- __raw_writel(0, timer_base + MXC_TCTL);
- __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
+ __raw_writel(0, imxtm.base + MXC_TCTL);
+ __raw_writel(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 */
__raw_writel(7 << V2_TPRER_PRE24M,
- timer_base + MXC_TPRER);
+ imxtm.base + MXC_TPRER);
tctl_val |= V2_TCTL_24MEN;
}
} else {
@@ -336,47 +342,44 @@ 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);
+ __raw_writel(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();
+ mxc_clockevent_init();
/* 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");
+ imxtm.clk_per = clk_get_sys("imx-gpt.0", "per");
+ imxtm.clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
- timer_base = ioremap(pbase, SZ_4K);
- BUG_ON(!timer_base);
+ imxtm.base = ioremap(pbase, SZ_4K);
+ BUG_ON(!imxtm.base);
- _mxc_timer_init(irq, clk_per, clk_ipg);
+ _mxc_timer_init();
}
static void __init mxc_timer_init_dt(struct device_node *np)
{
- struct clk *clk_per, *clk_ipg;
- int irq;
-
- if (timer_base)
+ if (imxtm.base)
return;
- timer_base = of_iomap(np, 0);
- WARN_ON(!timer_base);
- irq = irq_of_parse_and_map(np, 0);
+ imxtm.base = of_iomap(np, 0);
+ WARN_ON(!imxtm.base);
+ imxtm.irq = irq_of_parse_and_map(np, 0);
- clk_ipg = of_clk_get_by_name(np, "ipg");
+ 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(irq, clk_per, clk_ipg);
+ _mxc_timer_init();
}
CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);
CLOCKSOURCE_OF_DECLARE(mx25_timer, "fsl,imx25-gpt", mxc_timer_init_dt);
--
1.9.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 1/9] ARM: imx: move timer resources into a structure
2015-05-15 8:11 ` [PATCH 1/9] ARM: imx: move timer resources into a structure shawnguo at kernel.org
@ 2015-05-15 16:36 ` Shenwei Wang
2015-05-19 7:57 ` Shawn Guo
2015-05-18 10:43 ` Daniel Lezcano
1 sibling, 1 reply; 19+ messages in thread
From: Shenwei Wang @ 2015-05-15 16:36 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: shawnguo at kernel.org [mailto:shawnguo at kernel.org]
> Sent: 2015?5?15? 3:12
> To: linux-arm-kernel at lists.infradead.org
> Cc: kernel at pengutronix.de; Daniel Lezcano; Wang Shenwei-B38339; Shawn Guo
> Subject: [PATCH 1/9] ARM: imx: move timer resources into a structure
>
> From: Shawn Guo <shawn.guo@linaro.org>
>
> Instead of passing around as argument, let's move timer resources like irq and
> clocks together with base address into a data structure, and reference the
> resources from the struct variable directly to simplify the function call interface.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
> arch/arm/mach-imx/time.c | 119 ++++++++++++++++++++++++-----------------------
> 1 file changed, 61 insertions(+), 58 deletions(-)
>
> diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index
> ab5ee1c445f3..8ad7cb2a7f08 100644
> --- a/arch/arm/mach-imx/time.c
> +++ b/arch/arm/mach-imx/time.c
> @@ -84,27 +84,34 @@
> static struct clock_event_device clockevent_mxc; static enum
> clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
>
> -static void __iomem *timer_base;
> +struct imx_timer {
> + void __iomem *base;
> + int irq;
> + struct clk *clk_per;
> + struct clk *clk_ipg;
> +};
> +
> +static struct imx_timer imxtm;
>
Since the changes still used a global variable to hold the information, it doesn't take advantage of what the clocksource framework provides, and make the driver unable to support multi-instances.
Regards,
Shenwei
> static inline void gpt_irq_disable(void) {
> unsigned int tmp;
>
> if (timer_is_v2())
> - __raw_writel(0, timer_base + V2_IR);
> + __raw_writel(0, imxtm.base + V2_IR);
> else {
> - tmp = __raw_readl(timer_base + MXC_TCTL);
> - __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
> + tmp = __raw_readl(imxtm.base + MXC_TCTL);
> + __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, imxtm.base + MXC_TCTL);
> }
> }
>
> static inline void gpt_irq_enable(void) {
> if (timer_is_v2())
> - __raw_writel(1<<0, timer_base + V2_IR);
> + __raw_writel(1<<0, imxtm.base + V2_IR);
> else {
> - __raw_writel(__raw_readl(timer_base + MXC_TCTL) |
> MX1_2_TCTL_IRQEN,
> - timer_base + MXC_TCTL);
> + __raw_writel(__raw_readl(imxtm.base + MXC_TCTL) |
> MX1_2_TCTL_IRQEN,
> + imxtm.base + MXC_TCTL);
> }
> }
>
> @@ -112,12 +119,12 @@ static void gpt_irq_acknowledge(void) {
> if (timer_is_v1()) {
> if (cpu_is_mx1())
> - __raw_writel(0, timer_base + MX1_2_TSTAT);
> + __raw_writel(0, imxtm.base + MX1_2_TSTAT);
> else
> __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
> - timer_base + MX1_2_TSTAT);
> + imxtm.base + MX1_2_TSTAT);
> } else if (timer_is_v2())
> - __raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
> + __raw_writel(V2_TSTAT_OF1, imxtm.base + V2_TSTAT);
> }
>
> static void __iomem *sched_clock_reg;
> @@ -134,10 +141,10 @@ static unsigned long imx_read_current_timer(void)
> return __raw_readl(sched_clock_reg);
> }
>
> -static int __init mxc_clocksource_init(struct clk *timer_clk)
> +static int __init mxc_clocksource_init(void)
> {
> - 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;
> @@ -157,11 +164,11 @@ static int mx1_2_set_next_event(unsigned long evt,
> {
> unsigned long tcmp;
>
> - tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
> + tcmp = __raw_readl(imxtm.base + MX1_2_TCN) + evt;
>
> - __raw_writel(tcmp, timer_base + MX1_2_TCMP);
> + __raw_writel(tcmp, imxtm.base + MX1_2_TCMP);
>
> - return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
> + return (int)(tcmp - __raw_readl(imxtm.base + MX1_2_TCN)) < 0 ?
> -ETIME : 0;
> }
>
> @@ -170,12 +177,12 @@ static int v2_set_next_event(unsigned long evt, {
> unsigned long tcmp;
>
> - tcmp = __raw_readl(timer_base + V2_TCN) + evt;
> + tcmp = __raw_readl(imxtm.base + V2_TCN) + evt;
>
> - __raw_writel(tcmp, timer_base + V2_TCMP);
> + __raw_writel(tcmp, imxtm.base + V2_TCMP);
>
> return evt < 0x7fffffff &&
> - (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
> + (int)(tcmp - __raw_readl(imxtm.base + V2_TCN)) < 0 ?
> -ETIME : 0;
> }
>
> @@ -206,11 +213,11 @@ 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,
> - timer_base + V2_TCMP);
> + __raw_writel(__raw_readl(imxtm.base + V2_TCN) - 3,
> + imxtm.base + V2_TCMP);
> else
> - __raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
> - timer_base + MX1_2_TCMP);
> + __raw_writel(__raw_readl(imxtm.base + MX1_2_TCN) - 3,
> + imxtm.base + MX1_2_TCMP);
>
> /* Clear pending interrupt */
> gpt_irq_acknowledge();
> @@ -259,9 +266,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 = __raw_readl(imxtm.base + V2_TSTAT);
> else
> - tstat = __raw_readl(timer_base + MX1_2_TSTAT);
> + tstat = __raw_readl(imxtm.base + MX1_2_TSTAT);
>
> gpt_irq_acknowledge();
>
> @@ -284,49 +291,48 @@ 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(void)
> {
> 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(void)
> {
> uint32_t tctl_val;
>
> - if (IS_ERR(clk_per)) {
> + 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)
> */
>
> - __raw_writel(0, timer_base + MXC_TCTL);
> - __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
> + __raw_writel(0, imxtm.base + MXC_TCTL);
> + __raw_writel(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 */
> __raw_writel(7 << V2_TPRER_PRE24M,
> - timer_base + MXC_TPRER);
> + imxtm.base + MXC_TPRER);
> tctl_val |= V2_TCTL_24MEN;
> }
> } else {
> @@ -336,47 +342,44 @@ 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);
> + __raw_writel(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();
> + mxc_clockevent_init();
>
> /* 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");
> + imxtm.clk_per = clk_get_sys("imx-gpt.0", "per");
> + imxtm.clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
>
> - timer_base = ioremap(pbase, SZ_4K);
> - BUG_ON(!timer_base);
> + imxtm.base = ioremap(pbase, SZ_4K);
> + BUG_ON(!imxtm.base);
>
> - _mxc_timer_init(irq, clk_per, clk_ipg);
> + _mxc_timer_init();
> }
>
> static void __init mxc_timer_init_dt(struct device_node *np) {
> - struct clk *clk_per, *clk_ipg;
> - int irq;
> -
> - if (timer_base)
> + if (imxtm.base)
> return;
>
> - timer_base = of_iomap(np, 0);
> - WARN_ON(!timer_base);
> - irq = irq_of_parse_and_map(np, 0);
> + imxtm.base = of_iomap(np, 0);
> + WARN_ON(!imxtm.base);
> + imxtm.irq = irq_of_parse_and_map(np, 0);
>
> - clk_ipg = of_clk_get_by_name(np, "ipg");
> + 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(irq, clk_per, clk_ipg);
> + _mxc_timer_init();
> }
> CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);
> CLOCKSOURCE_OF_DECLARE(mx25_timer, "fsl,imx25-gpt", mxc_timer_init_dt);
> --
> 1.9.1
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH 1/9] ARM: imx: move timer resources into a structure
2015-05-15 16:36 ` Shenwei Wang
@ 2015-05-19 7:57 ` Shawn Guo
0 siblings, 0 replies; 19+ messages in thread
From: Shawn Guo @ 2015-05-19 7:57 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, May 15, 2015 at 04:36:18PM +0000, Shenwei Wang wrote:
>
>
> > -----Original Message-----
> > From: shawnguo at kernel.org [mailto:shawnguo at kernel.org]
> > Sent: 2015?5?15? 3:12
> > To: linux-arm-kernel at lists.infradead.org
> > Cc: kernel at pengutronix.de; Daniel Lezcano; Wang Shenwei-B38339; Shawn Guo
> > Subject: [PATCH 1/9] ARM: imx: move timer resources into a structure
> >
> > From: Shawn Guo <shawn.guo@linaro.org>
> >
> > Instead of passing around as argument, let's move timer resources like irq and
> > clocks together with base address into a data structure, and reference the
> > resources from the struct variable directly to simplify the function call interface.
> >
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > ---
> > arch/arm/mach-imx/time.c | 119 ++++++++++++++++++++++++-----------------------
> > 1 file changed, 61 insertions(+), 58 deletions(-)
> >
> > diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index
> > ab5ee1c445f3..8ad7cb2a7f08 100644
> > --- a/arch/arm/mach-imx/time.c
> > +++ b/arch/arm/mach-imx/time.c
> > @@ -84,27 +84,34 @@
> > static struct clock_event_device clockevent_mxc; static enum
> > clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
> >
> > -static void __iomem *timer_base;
> > +struct imx_timer {
> > + void __iomem *base;
> > + int irq;
> > + struct clk *clk_per;
> > + struct clk *clk_ipg;
> > +};
> > +
> > +static struct imx_timer imxtm;
> >
> Since the changes still used a global variable to hold the information, it doesn't take advantage of what the clocksource framework provides, and make the driver unable to support multi-instances.
>
The goal of the series is to clean up cpu_is_xxx usages, and move the
driver into drivers/clocksource. The multi-instances can be supported
later when we see a need for that.
Shawn
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 1/9] ARM: imx: move timer resources into a structure
2015-05-15 8:11 ` [PATCH 1/9] ARM: imx: move timer resources into a structure shawnguo at kernel.org
2015-05-15 16:36 ` Shenwei Wang
@ 2015-05-18 10:43 ` Daniel Lezcano
2015-05-19 7:58 ` Shawn Guo
1 sibling, 1 reply; 19+ messages in thread
From: Daniel Lezcano @ 2015-05-18 10:43 UTC (permalink / raw)
To: linux-arm-kernel
On 05/15/2015 10:11 AM, shawnguo at kernel.org wrote:
> From: Shawn Guo <shawn.guo@linaro.org>
>
> Instead of passing around as argument, let's move timer resources like
> irq and clocks together with base address into a data structure, and
> reference the resources from the struct variable directly to simplify
> the function call interface.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
I would be nice to embed the clockevent_mxc variable in the structure as
well and use container_of to retrieve the structure from the struct
clockevent.
The struct clockevent can be the unified parameter across the different
functions.
Refer to drivers/clocksource/rockchip_timer.c as an example.
> ---
> arch/arm/mach-imx/time.c | 119 ++++++++++++++++++++++++-----------------------
> 1 file changed, 61 insertions(+), 58 deletions(-)
>
> diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
> index ab5ee1c445f3..8ad7cb2a7f08 100644
> --- a/arch/arm/mach-imx/time.c
> +++ b/arch/arm/mach-imx/time.c
> @@ -84,27 +84,34 @@
> static struct clock_event_device clockevent_mxc;
> static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
>
> -static void __iomem *timer_base;
> +struct imx_timer {
> + void __iomem *base;
> + int irq;
> + struct clk *clk_per;
> + struct clk *clk_ipg;
> +};
> +
> +static struct imx_timer imxtm;
>
> static inline void gpt_irq_disable(void)
> {
> unsigned int tmp;
>
> if (timer_is_v2())
> - __raw_writel(0, timer_base + V2_IR);
> + __raw_writel(0, imxtm.base + V2_IR);
> else {
> - tmp = __raw_readl(timer_base + MXC_TCTL);
> - __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
> + tmp = __raw_readl(imxtm.base + MXC_TCTL);
> + __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, imxtm.base + MXC_TCTL);
> }
> }
>
> static inline void gpt_irq_enable(void)
> {
> if (timer_is_v2())
> - __raw_writel(1<<0, timer_base + V2_IR);
> + __raw_writel(1<<0, imxtm.base + V2_IR);
> else {
> - __raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
> - timer_base + MXC_TCTL);
> + __raw_writel(__raw_readl(imxtm.base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
> + imxtm.base + MXC_TCTL);
> }
> }
>
> @@ -112,12 +119,12 @@ static void gpt_irq_acknowledge(void)
> {
> if (timer_is_v1()) {
> if (cpu_is_mx1())
> - __raw_writel(0, timer_base + MX1_2_TSTAT);
> + __raw_writel(0, imxtm.base + MX1_2_TSTAT);
> else
> __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
> - timer_base + MX1_2_TSTAT);
> + imxtm.base + MX1_2_TSTAT);
> } else if (timer_is_v2())
> - __raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
> + __raw_writel(V2_TSTAT_OF1, imxtm.base + V2_TSTAT);
> }
>
> static void __iomem *sched_clock_reg;
> @@ -134,10 +141,10 @@ static unsigned long imx_read_current_timer(void)
> return __raw_readl(sched_clock_reg);
> }
>
> -static int __init mxc_clocksource_init(struct clk *timer_clk)
> +static int __init mxc_clocksource_init(void)
> {
> - 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;
> @@ -157,11 +164,11 @@ static int mx1_2_set_next_event(unsigned long evt,
> {
> unsigned long tcmp;
>
> - tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
> + tcmp = __raw_readl(imxtm.base + MX1_2_TCN) + evt;
>
> - __raw_writel(tcmp, timer_base + MX1_2_TCMP);
> + __raw_writel(tcmp, imxtm.base + MX1_2_TCMP);
>
> - return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
> + return (int)(tcmp - __raw_readl(imxtm.base + MX1_2_TCN)) < 0 ?
> -ETIME : 0;
> }
>
> @@ -170,12 +177,12 @@ static int v2_set_next_event(unsigned long evt,
> {
> unsigned long tcmp;
>
> - tcmp = __raw_readl(timer_base + V2_TCN) + evt;
> + tcmp = __raw_readl(imxtm.base + V2_TCN) + evt;
>
> - __raw_writel(tcmp, timer_base + V2_TCMP);
> + __raw_writel(tcmp, imxtm.base + V2_TCMP);
>
> return evt < 0x7fffffff &&
> - (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
> + (int)(tcmp - __raw_readl(imxtm.base + V2_TCN)) < 0 ?
> -ETIME : 0;
> }
>
> @@ -206,11 +213,11 @@ 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,
> - timer_base + V2_TCMP);
> + __raw_writel(__raw_readl(imxtm.base + V2_TCN) - 3,
> + imxtm.base + V2_TCMP);
> else
> - __raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
> - timer_base + MX1_2_TCMP);
> + __raw_writel(__raw_readl(imxtm.base + MX1_2_TCN) - 3,
> + imxtm.base + MX1_2_TCMP);
>
> /* Clear pending interrupt */
> gpt_irq_acknowledge();
> @@ -259,9 +266,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 = __raw_readl(imxtm.base + V2_TSTAT);
> else
> - tstat = __raw_readl(timer_base + MX1_2_TSTAT);
> + tstat = __raw_readl(imxtm.base + MX1_2_TSTAT);
>
> gpt_irq_acknowledge();
>
> @@ -284,49 +291,48 @@ 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(void)
> {
> 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(void)
> {
> uint32_t tctl_val;
>
> - if (IS_ERR(clk_per)) {
> + 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)
> */
>
> - __raw_writel(0, timer_base + MXC_TCTL);
> - __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
> + __raw_writel(0, imxtm.base + MXC_TCTL);
> + __raw_writel(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 */
> __raw_writel(7 << V2_TPRER_PRE24M,
> - timer_base + MXC_TPRER);
> + imxtm.base + MXC_TPRER);
> tctl_val |= V2_TCTL_24MEN;
> }
> } else {
> @@ -336,47 +342,44 @@ 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);
> + __raw_writel(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();
> + mxc_clockevent_init();
>
> /* 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");
> + imxtm.clk_per = clk_get_sys("imx-gpt.0", "per");
> + imxtm.clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
>
> - timer_base = ioremap(pbase, SZ_4K);
> - BUG_ON(!timer_base);
> + imxtm.base = ioremap(pbase, SZ_4K);
> + BUG_ON(!imxtm.base);
>
> - _mxc_timer_init(irq, clk_per, clk_ipg);
> + _mxc_timer_init();
> }
>
> static void __init mxc_timer_init_dt(struct device_node *np)
> {
> - struct clk *clk_per, *clk_ipg;
> - int irq;
> -
> - if (timer_base)
> + if (imxtm.base)
> return;
>
> - timer_base = of_iomap(np, 0);
> - WARN_ON(!timer_base);
> - irq = irq_of_parse_and_map(np, 0);
> + imxtm.base = of_iomap(np, 0);
> + WARN_ON(!imxtm.base);
> + imxtm.irq = irq_of_parse_and_map(np, 0);
>
> - clk_ipg = of_clk_get_by_name(np, "ipg");
> + 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(irq, clk_per, clk_ipg);
> + _mxc_timer_init();
> }
> CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);
> CLOCKSOURCE_OF_DECLARE(mx25_timer, "fsl,imx25-gpt", mxc_timer_init_dt);
>
--
<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
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH 1/9] ARM: imx: move timer resources into a structure
2015-05-18 10:43 ` Daniel Lezcano
@ 2015-05-19 7:58 ` Shawn Guo
0 siblings, 0 replies; 19+ messages in thread
From: Shawn Guo @ 2015-05-19 7:58 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, May 18, 2015 at 12:43:10PM +0200, Daniel Lezcano wrote:
> On 05/15/2015 10:11 AM, shawnguo at kernel.org wrote:
> >From: Shawn Guo <shawn.guo@linaro.org>
> >
> >Instead of passing around as argument, let's move timer resources like
> >irq and clocks together with base address into a data structure, and
> >reference the resources from the struct variable directly to simplify
> >the function call interface.
> >
> >Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
>
> I would be nice to embed the clockevent_mxc variable in the
> structure as well and use container_of to retrieve the structure
> from the struct clockevent.
>
> The struct clockevent can be the unified parameter across the
> different functions.
>
> Refer to drivers/clocksource/rockchip_timer.c as an example.
Okay, thanks for the example. I will add a patch to do that.
Shawn
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 2/9] ARM: imx: define an enum for gpt timer device type
2015-05-15 8:11 [PATCH 0/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
2015-05-15 8:11 ` [PATCH 1/9] ARM: imx: move timer resources into a structure shawnguo at kernel.org
@ 2015-05-15 8:11 ` shawnguo at kernel.org
2015-05-15 16:30 ` Shenwei Wang
2015-05-15 8:11 ` [PATCH 3/9] ARM: imx: initialize gpt device type for DT boot shawnguo at kernel.org
` (6 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: shawnguo at kernel.org @ 2015-05-15 8:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Shawn Guo <shawn.guo@linaro.org>
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.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
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
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 8ad7cb2a7f08..5241a173fd60 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -31,6 +31,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>
@@ -85,6 +86,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;
@@ -352,7 +354,7 @@ static void __init _mxc_timer_init(void)
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)
{
imxtm.clk_per = clk_get_sys("imx-gpt.0", "per");
imxtm.clk_ipg = clk_get_sys("imx-gpt.0", "ipg");
@@ -360,6 +362,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();
}
diff --git a/drivers/clk/imx/clk-imx1.c b/drivers/clk/imx/clk-imx1.c
index c9812dbacac2..c2647fa19f28 100644
--- a/drivers/clk/imx/clk-imx1.c
+++ b/drivers/clk/imx/clk-imx1.c
@@ -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;
}
diff --git a/drivers/clk/imx/clk-imx21.c b/drivers/clk/imx/clk-imx21.c
index 0ca842cf4ca7..dba987e3b89f 100644
--- a/drivers/clk/imx/clk-imx21.c
+++ b/drivers/clk/imx/clk-imx21.c
@@ -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;
}
diff --git a/drivers/clk/imx/clk-imx27.c b/drivers/clk/imx/clk-imx27.c
index df2dfc081c71..d9d50d54ef2a 100644
--- a/drivers/clk/imx/clk-imx27.c
+++ b/drivers/clk/imx/clk-imx27.c
@@ -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;
}
diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c
index a55290c1c264..fe66c40b7be2 100644
--- a/drivers/clk/imx/clk-imx31.c
+++ b/drivers/clk/imx/clk-imx31.c
@@ -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;
}
diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c
index f2f3b8164f7b..69138ba3dec7 100644
--- a/drivers/clk/imx/clk-imx35.c
+++ b/drivers/clk/imx/clk-imx35.c
@@ -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;
}
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 6bae5374dc83..b5297e457a8e 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -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);
diff --git a/include/soc/imx/timer.h b/include/soc/imx/timer.h
new file mode 100644
index 000000000000..bbbafd65f464
--- /dev/null
+++ b/include/soc/imx/timer.h
@@ -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__ */
--
1.9.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 2/9] ARM: imx: define an enum for gpt timer device type
2015-05-15 8:11 ` [PATCH 2/9] ARM: imx: define an enum for gpt timer device type shawnguo at kernel.org
@ 2015-05-15 16:30 ` Shenwei Wang
0 siblings, 0 replies; 19+ messages in thread
From: Shenwei Wang @ 2015-05-15 16:30 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: shawnguo at kernel.org [mailto:shawnguo at kernel.org]
> Sent: 2015?5?15? 3:12
> To: linux-arm-kernel at lists.infradead.org
> Cc: kernel at pengutronix.de; Daniel Lezcano; Wang Shenwei-B38339; Shawn Guo
> Subject: [PATCH 2/9] ARM: imx: define an enum for gpt timer device type
>
> From: Shawn Guo <shawn.guo@linaro.org>
>
> 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.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> 000000000000..bbbafd65f464
> --- /dev/null
> +++ b/include/soc/imx/timer.h
> @@ -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 */
> +};
> +
Since there is only one type of GPT IP block with different versions, I think to use the word of "GPT_VER_xxx" would make sense.
Regards,
Shenwei
> +/*
> + * 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__ */
> --
> 1.9.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 3/9] ARM: imx: initialize gpt device type for DT boot
2015-05-15 8:11 [PATCH 0/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
2015-05-15 8:11 ` [PATCH 1/9] ARM: imx: move timer resources into a structure shawnguo at kernel.org
2015-05-15 8:11 ` [PATCH 2/9] ARM: imx: define an enum for gpt timer device type shawnguo at kernel.org
@ 2015-05-15 8:11 ` shawnguo at kernel.org
2015-05-15 8:11 ` [PATCH 4/9] ARM: imx: setup tctl register in device specific function shawnguo at kernel.org
` (5 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: shawnguo at kernel.org @ 2015-05-15 8:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Shawn Guo <shawn.guo@linaro.org>
Use different initialization function in CLOCKSOURCE_OF_DECLARE() to
initialize gpt device type for DT boot.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/time.c | 44 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 36 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 5241a173fd60..ed01813cfc76 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -385,11 +385,39 @@ static void __init mxc_timer_init_dt(struct device_node *np)
_mxc_timer_init();
}
-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)
+{
+ imxtm.type = GPT_TYPE_IMX1;
+ mxc_timer_init_dt(np);
+}
+
+static void __init imx21_timer_init_dt(struct device_node *np)
+{
+ imxtm.type = GPT_TYPE_IMX21;
+ mxc_timer_init_dt(np);
+}
+
+static void __init imx31_timer_init_dt(struct device_node *np)
+{
+ imxtm.type = GPT_TYPE_IMX31;
+ mxc_timer_init_dt(np);
+}
+
+static void __init imx6dl_timer_init_dt(struct device_node *np)
+{
+ imxtm.type = GPT_TYPE_IMX6DL;
+ mxc_timer_init_dt(np);
+}
+
+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);
--
1.9.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 4/9] ARM: imx: setup tctl register in device specific function
2015-05-15 8:11 [PATCH 0/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
` (2 preceding siblings ...)
2015-05-15 8:11 ` [PATCH 3/9] ARM: imx: initialize gpt device type for DT boot shawnguo at kernel.org
@ 2015-05-15 8:11 ` shawnguo at kernel.org
2015-05-15 8:35 ` Arnd Bergmann
2015-05-15 8:11 ` [PATCH 5/9] ARM: imx: set up set_next_event hook in imx_timer_data_init() shawnguo at kernel.org
` (4 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: shawnguo at kernel.org @ 2015-05-15 8:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Shawn Guo <shawn.guo@linaro.org>
It creates device speicific function hook gpt_setup_tctl to set up gpt
TCTL register.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/time.c | 81 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 62 insertions(+), 19 deletions(-)
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index ed01813cfc76..c86e25922eb4 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -91,6 +91,7 @@ struct imx_timer {
int irq;
struct clk *clk_per;
struct clk *clk_ipg;
+ void (*gpt_setup_tctl)(void);
};
static struct imx_timer imxtm;
@@ -306,9 +307,68 @@ static int __init mxc_clockevent_init(void)
return 0;
}
+static void imx1_gpt_setup_tctl(void)
+{
+ u32 tctl_val;
+
+ tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
+ __raw_writel(tctl_val, imxtm.base + MXC_TCTL);
+}
+#define imx21_gpt_setup_tctl imx1_gpt_setup_tctl
+
+static void imx31_gpt_setup_tctl(void)
+{
+ 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;
+
+ __raw_writel(tctl_val, imxtm.base + MXC_TCTL);
+}
+
+static void imx6dl_gpt_setup_tctl(void)
+{
+ 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 */
+ __raw_writel(7 << V2_TPRER_PRE24M, imxtm.base + MXC_TPRER);
+ tctl_val |= V2_TCTL_24MEN;
+ } else {
+ tctl_val |= V2_TCTL_CLK_PER;
+ }
+
+ __raw_writel(tctl_val, imxtm.base + MXC_TCTL);
+}
+
+static void __init imx_timer_data_init(void)
+{
+ switch (imxtm.type) {
+ case GPT_TYPE_IMX1:
+ imxtm.gpt_setup_tctl = imx1_gpt_setup_tctl;
+ break;
+ case GPT_TYPE_IMX21:
+ imxtm.gpt_setup_tctl = imx21_gpt_setup_tctl;
+ break;
+ case GPT_TYPE_IMX31:
+ imxtm.gpt_setup_tctl = imx31_gpt_setup_tctl;
+ break;
+ case GPT_TYPE_IMX6DL:
+ imxtm.gpt_setup_tctl = imx6dl_gpt_setup_tctl;
+ break;
+ default:
+ BUG();
+ }
+}
+
static void __init _mxc_timer_init(void)
{
- uint32_t tctl_val;
+ imx_timer_data_init();
if (IS_ERR(imxtm.clk_per)) {
pr_err("i.MX timer: unable to get clk\n");
@@ -327,24 +387,7 @@ static void __init _mxc_timer_init(void)
__raw_writel(0, imxtm.base + MXC_TCTL);
__raw_writel(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 */
- __raw_writel(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;
- }
-
- __raw_writel(tctl_val, imxtm.base + MXC_TCTL);
+ imxtm.gpt_setup_tctl();
/* init and register the timer to the framework */
mxc_clocksource_init();
--
1.9.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 4/9] ARM: imx: setup tctl register in device specific function
2015-05-15 8:11 ` [PATCH 4/9] ARM: imx: setup tctl register in device specific function shawnguo at kernel.org
@ 2015-05-15 8:35 ` Arnd Bergmann
2015-05-19 8:08 ` Shawn Guo
0 siblings, 1 reply; 19+ messages in thread
From: Arnd Bergmann @ 2015-05-15 8:35 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 15 May 2015 16:11:42 shawnguo at kernel.org wrote:
> }
>
> +static void imx1_gpt_setup_tctl(void)
> +{
> + u32 tctl_val;
> +
> + tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
> + __raw_writel(tctl_val, imxtm.base + MXC_TCTL);
> +}
>
Could you add another upfront patch to convert all the __raw_readl/__raw_writel
to readl_relaxed/writel_relaxed?
It would be nice if the driver was endian-safe by the time it gets moved to
drivers/clocksource, and you don't add any unsafe accesses for the changed
code.
Arnd
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH 4/9] ARM: imx: setup tctl register in device specific function
2015-05-15 8:35 ` Arnd Bergmann
@ 2015-05-19 8:08 ` Shawn Guo
0 siblings, 0 replies; 19+ messages in thread
From: Shawn Guo @ 2015-05-19 8:08 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, May 15, 2015 at 10:35:51AM +0200, Arnd Bergmann wrote:
> On Friday 15 May 2015 16:11:42 shawnguo at kernel.org wrote:
> > }
> >
> > +static void imx1_gpt_setup_tctl(void)
> > +{
> > + u32 tctl_val;
> > +
> > + tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
> > + __raw_writel(tctl_val, imxtm.base + MXC_TCTL);
> > +}
> >
>
> Could you add another upfront patch to convert all the __raw_readl/__raw_writel
> to readl_relaxed/writel_relaxed?
>
> It would be nice if the driver was endian-safe by the time it gets moved to
> drivers/clocksource, and you don't add any unsafe accesses for the changed
> code.
Make sense. Will do.
Shawn
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 5/9] ARM: imx: set up set_next_event hook in imx_timer_data_init()
2015-05-15 8:11 [PATCH 0/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
` (3 preceding siblings ...)
2015-05-15 8:11 ` [PATCH 4/9] ARM: imx: setup tctl register in device specific function shawnguo at kernel.org
@ 2015-05-15 8:11 ` shawnguo at kernel.org
2015-05-15 8:11 ` [PATCH 6/9] ARM: imx: define gpt register offset per device type shawnguo at kernel.org
` (3 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: shawnguo at kernel.org @ 2015-05-15 8:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Shawn Guo <shawn.guo@linaro.org>
Function imx_timer_data_init() was there for setting up device specific
data, so let's move the setup of set_next_event hook into there.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/time.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index c86e25922eb4..d79a00e24084 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -290,15 +290,11 @@ 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(void)
{
- 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(imxtm.clk_per),
@@ -351,15 +347,19 @@ static void __init imx_timer_data_init(void)
switch (imxtm.type) {
case GPT_TYPE_IMX1:
imxtm.gpt_setup_tctl = imx1_gpt_setup_tctl;
+ clockevent_mxc.set_next_event = mx1_2_set_next_event;
break;
case GPT_TYPE_IMX21:
imxtm.gpt_setup_tctl = imx21_gpt_setup_tctl;
+ clockevent_mxc.set_next_event = mx1_2_set_next_event;
break;
case GPT_TYPE_IMX31:
imxtm.gpt_setup_tctl = imx31_gpt_setup_tctl;
+ clockevent_mxc.set_next_event = v2_set_next_event;
break;
case GPT_TYPE_IMX6DL:
imxtm.gpt_setup_tctl = imx6dl_gpt_setup_tctl;
+ clockevent_mxc.set_next_event = v2_set_next_event;
break;
default:
BUG();
--
1.9.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 6/9] ARM: imx: define gpt register offset per device type
2015-05-15 8:11 [PATCH 0/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
` (4 preceding siblings ...)
2015-05-15 8:11 ` [PATCH 5/9] ARM: imx: set up set_next_event hook in imx_timer_data_init() shawnguo at kernel.org
@ 2015-05-15 8:11 ` shawnguo at kernel.org
2015-05-15 8:34 ` Arnd Bergmann
2015-05-15 8:11 ` [PATCH 7/9] ARM: imx: provide gpt device specific irq functions shawnguo at kernel.org
` (2 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: shawnguo at kernel.org @ 2015-05-15 8:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Shawn Guo <shawn.guo@linaro.org>
It initializes offset of gpt registers TSTAT, TCN and TCMP per device
type, so that the access to these registers can be unified.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/time.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index d79a00e24084..5908e78d9552 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -91,6 +91,9 @@ struct imx_timer {
int irq;
struct clk *clk_per;
struct clk *clk_ipg;
+ int reg_tstat;
+ int reg_tcn;
+ int reg_tcmp;
void (*gpt_setup_tctl)(void);
};
@@ -147,7 +150,7 @@ static unsigned long imx_read_current_timer(void)
static int __init mxc_clocksource_init(void)
{
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.reg_tcn;
imx_delay_timer.read_current_timer = &imx_read_current_timer;
imx_delay_timer.freq = c;
@@ -214,13 +217,8 @@ static void mxc_set_mode(enum clock_event_mode mode,
gpt_irq_disable();
if (mode != clockevent_mode) {
- /* Set event time into far-far future */
- if (timer_is_v2())
- __raw_writel(__raw_readl(imxtm.base + V2_TCN) - 3,
- imxtm.base + V2_TCMP);
- else
- __raw_writel(__raw_readl(imxtm.base + MX1_2_TCN) - 3,
- imxtm.base + MX1_2_TCMP);
+ __raw_writel(__raw_readl(imxtm.base + imxtm.reg_tcn) - 3,
+ imxtm.base + imxtm.reg_tcmp);
/* Clear pending interrupt */
gpt_irq_acknowledge();
@@ -268,10 +266,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
struct clock_event_device *evt = &clockevent_mxc;
uint32_t tstat;
- if (timer_is_v2())
- tstat = __raw_readl(imxtm.base + V2_TSTAT);
- else
- tstat = __raw_readl(imxtm.base + MX1_2_TSTAT);
+ tstat = __raw_readl(imxtm.base + imxtm.reg_tstat);
gpt_irq_acknowledge();
@@ -346,18 +341,30 @@ static void __init imx_timer_data_init(void)
{
switch (imxtm.type) {
case GPT_TYPE_IMX1:
+ imxtm.reg_tstat = MX1_2_TSTAT;
+ imxtm.reg_tcn = MX1_2_TCN;
+ imxtm.reg_tcmp = MX1_2_TCMP;
imxtm.gpt_setup_tctl = imx1_gpt_setup_tctl;
clockevent_mxc.set_next_event = mx1_2_set_next_event;
break;
case GPT_TYPE_IMX21:
+ imxtm.reg_tstat = MX1_2_TSTAT;
+ imxtm.reg_tcn = MX1_2_TCN;
+ imxtm.reg_tcmp = MX1_2_TCMP;
imxtm.gpt_setup_tctl = imx21_gpt_setup_tctl;
clockevent_mxc.set_next_event = mx1_2_set_next_event;
break;
case GPT_TYPE_IMX31:
+ imxtm.reg_tstat = V2_TSTAT;
+ imxtm.reg_tcn = V2_TCN;
+ imxtm.reg_tcmp = V2_TCMP;
imxtm.gpt_setup_tctl = imx31_gpt_setup_tctl;
clockevent_mxc.set_next_event = v2_set_next_event;
break;
case GPT_TYPE_IMX6DL:
+ imxtm.reg_tstat = V2_TSTAT;
+ imxtm.reg_tcn = V2_TCN;
+ imxtm.reg_tcmp = V2_TCMP;
imxtm.gpt_setup_tctl = imx6dl_gpt_setup_tctl;
clockevent_mxc.set_next_event = v2_set_next_event;
break;
--
1.9.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 6/9] ARM: imx: define gpt register offset per device type
2015-05-15 8:11 ` [PATCH 6/9] ARM: imx: define gpt register offset per device type shawnguo at kernel.org
@ 2015-05-15 8:34 ` Arnd Bergmann
2015-05-19 8:09 ` Shawn Guo
0 siblings, 1 reply; 19+ messages in thread
From: Arnd Bergmann @ 2015-05-15 8:34 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 15 May 2015 16:11:44 shawnguo at kernel.org wrote:
> {
> switch (imxtm.type) {
> case GPT_TYPE_IMX1:
> + imxtm.reg_tstat = MX1_2_TSTAT;
> + imxtm.reg_tcn = MX1_2_TCN;
> + imxtm.reg_tcmp = MX1_2_TCMP;
> imxtm.gpt_setup_tctl = imx1_gpt_setup_tctl;
> clockevent_mxc.set_next_event = mx1_2_set_next_event;
> break;
> case GPT_TYPE_IMX21:
> + imxtm.reg_tstat = MX1_2_TSTAT;
> + imxtm.reg_tcn = MX1_2_TCN;
> + imxtm.reg_tcmp = MX1_2_TCMP;
> imxtm.gpt_setup_tctl = imx21_gpt_setup_tctl;
> clockevent_mxc.set_next_event = mx1_2_set_next_event;
> break;
> case GPT_TYPE_IMX31:
> + imxtm.reg_tstat = V2_TSTAT;
> + imxtm.reg_tcn = V2_TCN;
> + imxtm.reg_tcmp = V2_TCMP;
> imxtm.gpt_setup_tctl = imx31_gpt_setup_tctl;
> clockevent_mxc.set_next_event = v2_set_next_event;
> break;
> case GPT_TYPE_IMX6DL:
> + imxtm.reg_tstat = V2_TSTAT;
> + imxtm.reg_tcn = V2_TCN;
> + imxtm.reg_tcmp = V2_TCMP;
> imxtm.gpt_setup_tctl = imx6dl_gpt_setup_tctl;
> clockevent_mxc.set_next_event = v2_set_next_event;
> break;
>
Hi Shawn,
I think this could be expressed in a nicer way by defining a structure
that contains all the settings you derive from the type here, and then
setting a pointer to that structure based on the compatible string.
Arnd
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH 6/9] ARM: imx: define gpt register offset per device type
2015-05-15 8:34 ` Arnd Bergmann
@ 2015-05-19 8:09 ` Shawn Guo
0 siblings, 0 replies; 19+ messages in thread
From: Shawn Guo @ 2015-05-19 8:09 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, May 15, 2015 at 10:34:03AM +0200, Arnd Bergmann wrote:
> On Friday 15 May 2015 16:11:44 shawnguo at kernel.org wrote:
> > {
> > switch (imxtm.type) {
> > case GPT_TYPE_IMX1:
> > + imxtm.reg_tstat = MX1_2_TSTAT;
> > + imxtm.reg_tcn = MX1_2_TCN;
> > + imxtm.reg_tcmp = MX1_2_TCMP;
> > imxtm.gpt_setup_tctl = imx1_gpt_setup_tctl;
> > clockevent_mxc.set_next_event = mx1_2_set_next_event;
> > break;
> > case GPT_TYPE_IMX21:
> > + imxtm.reg_tstat = MX1_2_TSTAT;
> > + imxtm.reg_tcn = MX1_2_TCN;
> > + imxtm.reg_tcmp = MX1_2_TCMP;
> > imxtm.gpt_setup_tctl = imx21_gpt_setup_tctl;
> > clockevent_mxc.set_next_event = mx1_2_set_next_event;
> > break;
> > case GPT_TYPE_IMX31:
> > + imxtm.reg_tstat = V2_TSTAT;
> > + imxtm.reg_tcn = V2_TCN;
> > + imxtm.reg_tcmp = V2_TCMP;
> > imxtm.gpt_setup_tctl = imx31_gpt_setup_tctl;
> > clockevent_mxc.set_next_event = v2_set_next_event;
> > break;
> > case GPT_TYPE_IMX6DL:
> > + imxtm.reg_tstat = V2_TSTAT;
> > + imxtm.reg_tcn = V2_TCN;
> > + imxtm.reg_tcmp = V2_TCMP;
> > imxtm.gpt_setup_tctl = imx6dl_gpt_setup_tctl;
> > clockevent_mxc.set_next_event = v2_set_next_event;
> > break;
> >
>
> Hi Shawn,
>
> I think this could be expressed in a nicer way by defining a structure
> that contains all the settings you derive from the type here, and then
> setting a pointer to that structure based on the compatible string.
Yeah, good suggestion. Will change.
Shawn
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 7/9] ARM: imx: provide gpt device specific irq functions
2015-05-15 8:11 [PATCH 0/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
` (5 preceding siblings ...)
2015-05-15 8:11 ` [PATCH 6/9] ARM: imx: define gpt register offset per device type shawnguo at kernel.org
@ 2015-05-15 8:11 ` shawnguo at kernel.org
2015-05-15 8:11 ` [PATCH 8/9] ARM: imx: remove platform headers from timer driver shawnguo at kernel.org
2015-05-15 8:11 ` [PATCH 9/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
8 siblings, 0 replies; 19+ messages in thread
From: shawnguo at kernel.org @ 2015-05-15 8:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Shawn Guo <shawn.guo@linaro.org>
It splits irq enable/disable/acknowledge operations into device specific
functions to get proper hook called in the correct context.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/time.c | 76 ++++++++++++++++++++++++++++++++----------------
1 file changed, 51 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 5908e78d9552..174c553a3bb7 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -95,44 +95,58 @@ struct imx_timer {
int reg_tcn;
int reg_tcmp;
void (*gpt_setup_tctl)(void);
+ void (*gpt_irq_enable)(void);
+ void (*gpt_irq_disable)(void);
+ void (*gpt_irq_acknowledge)(void);
};
static struct imx_timer imxtm;
-static inline void gpt_irq_disable(void)
+static void imx1_gpt_irq_disable(void)
{
unsigned int tmp;
- if (timer_is_v2())
- __raw_writel(0, imxtm.base + V2_IR);
- else {
- tmp = __raw_readl(imxtm.base + MXC_TCTL);
- __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, imxtm.base + MXC_TCTL);
- }
+ tmp = __raw_readl(imxtm.base + MXC_TCTL);
+ __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, imxtm.base + MXC_TCTL);
+}
+#define imx21_gpt_irq_disable imx1_gpt_irq_disable
+
+static void imx31_gpt_irq_disable(void)
+{
+ __raw_writel(0, imxtm.base + V2_IR);
}
+#define imx6dl_gpt_irq_disable imx31_gpt_irq_disable
-static inline void gpt_irq_enable(void)
+static void imx1_gpt_irq_enable(void)
{
- if (timer_is_v2())
- __raw_writel(1<<0, imxtm.base + V2_IR);
- else {
- __raw_writel(__raw_readl(imxtm.base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
+ __raw_writel(__raw_readl(imxtm.base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
imxtm.base + MXC_TCTL);
- }
+}
+#define imx21_gpt_irq_enable imx1_gpt_irq_enable
+
+static void imx31_gpt_irq_enable(void)
+{
+ __raw_writel(1<<0, imxtm.base + V2_IR);
+}
+#define imx6dl_gpt_irq_enable imx31_gpt_irq_enable
+
+static void imx1_gpt_irq_acknowledge(void)
+{
+ __raw_writel(0, imxtm.base + MX1_2_TSTAT);
}
-static void gpt_irq_acknowledge(void)
+static void imx21_gpt_irq_acknowledge(void)
{
- if (timer_is_v1()) {
- if (cpu_is_mx1())
- __raw_writel(0, imxtm.base + MX1_2_TSTAT);
- else
- __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
+ __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
imxtm.base + MX1_2_TSTAT);
- } else if (timer_is_v2())
- __raw_writel(V2_TSTAT_OF1, imxtm.base + V2_TSTAT);
}
+static void imx31_gpt_irq_acknowledge(void)
+{
+ __raw_writel(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)
@@ -214,14 +228,14 @@ static void mxc_set_mode(enum clock_event_mode mode,
local_irq_save(flags);
/* Disable interrupt in GPT module */
- gpt_irq_disable();
+ imxtm.gpt_irq_disable();
if (mode != clockevent_mode) {
__raw_writel(__raw_readl(imxtm.base + imxtm.reg_tcn) - 3,
imxtm.base + imxtm.reg_tcmp);
/* Clear pending interrupt */
- gpt_irq_acknowledge();
+ imxtm.gpt_irq_acknowledge();
}
#ifdef DEBUG
@@ -247,7 +261,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
* mode switching
*/
local_irq_save(flags);
- gpt_irq_enable();
+ imxtm.gpt_irq_enable();
local_irq_restore(flags);
break;
case CLOCK_EVT_MODE_SHUTDOWN:
@@ -268,7 +282,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
tstat = __raw_readl(imxtm.base + imxtm.reg_tstat);
- gpt_irq_acknowledge();
+ imxtm.gpt_irq_acknowledge();
evt->event_handler(evt);
@@ -345,6 +359,9 @@ static void __init imx_timer_data_init(void)
imxtm.reg_tcn = MX1_2_TCN;
imxtm.reg_tcmp = MX1_2_TCMP;
imxtm.gpt_setup_tctl = imx1_gpt_setup_tctl;
+ imxtm.gpt_irq_enable = imx1_gpt_irq_enable;
+ imxtm.gpt_irq_disable = imx1_gpt_irq_disable;
+ imxtm.gpt_irq_acknowledge = imx1_gpt_irq_acknowledge;
clockevent_mxc.set_next_event = mx1_2_set_next_event;
break;
case GPT_TYPE_IMX21:
@@ -352,6 +369,9 @@ static void __init imx_timer_data_init(void)
imxtm.reg_tcn = MX1_2_TCN;
imxtm.reg_tcmp = MX1_2_TCMP;
imxtm.gpt_setup_tctl = imx21_gpt_setup_tctl;
+ imxtm.gpt_irq_enable = imx21_gpt_irq_enable;
+ imxtm.gpt_irq_disable = imx21_gpt_irq_disable;
+ imxtm.gpt_irq_acknowledge = imx21_gpt_irq_acknowledge;
clockevent_mxc.set_next_event = mx1_2_set_next_event;
break;
case GPT_TYPE_IMX31:
@@ -359,6 +379,9 @@ static void __init imx_timer_data_init(void)
imxtm.reg_tcn = V2_TCN;
imxtm.reg_tcmp = V2_TCMP;
imxtm.gpt_setup_tctl = imx31_gpt_setup_tctl;
+ imxtm.gpt_irq_enable = imx31_gpt_irq_enable;
+ imxtm.gpt_irq_disable = imx31_gpt_irq_disable;
+ imxtm.gpt_irq_acknowledge = imx31_gpt_irq_acknowledge;
clockevent_mxc.set_next_event = v2_set_next_event;
break;
case GPT_TYPE_IMX6DL:
@@ -366,6 +389,9 @@ static void __init imx_timer_data_init(void)
imxtm.reg_tcn = V2_TCN;
imxtm.reg_tcmp = V2_TCMP;
imxtm.gpt_setup_tctl = imx6dl_gpt_setup_tctl;
+ imxtm.gpt_irq_enable = imx6dl_gpt_irq_enable;
+ imxtm.gpt_irq_disable = imx6dl_gpt_irq_disable;
+ imxtm.gpt_irq_acknowledge = imx6dl_gpt_irq_acknowledge;
clockevent_mxc.set_next_event = v2_set_next_event;
break;
default:
--
1.9.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 8/9] ARM: imx: remove platform headers from timer driver
2015-05-15 8:11 [PATCH 0/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
` (6 preceding siblings ...)
2015-05-15 8:11 ` [PATCH 7/9] ARM: imx: provide gpt device specific irq functions shawnguo at kernel.org
@ 2015-05-15 8:11 ` shawnguo at kernel.org
2015-05-15 8:11 ` [PATCH 9/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
8 siblings, 0 replies; 19+ messages in thread
From: shawnguo at kernel.org @ 2015-05-15 8:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Shawn Guo <shawn.guo@linaro.org>
With the cleanup done before, the platform specific headers now can be
removed.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/time.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 174c553a3bb7..ecf043f6c6fd 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -35,9 +35,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
@@ -79,9 +76,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())
-
static struct clock_event_device clockevent_mxc;
static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
--
1.9.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH 9/9] ARM: imx: move timer driver into drivers/clocksource
2015-05-15 8:11 [PATCH 0/9] ARM: imx: move timer driver into drivers/clocksource shawnguo at kernel.org
` (7 preceding siblings ...)
2015-05-15 8:11 ` [PATCH 8/9] ARM: imx: remove platform headers from timer driver shawnguo at kernel.org
@ 2015-05-15 8:11 ` shawnguo at kernel.org
8 siblings, 0 replies; 19+ messages in thread
From: shawnguo at kernel.org @ 2015-05-15 8:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Shawn Guo <shawn.guo@linaro.org>
After the cleanup on imx timer driver, now it's ready to be moved into
drivers/clocksource/. Let's do it.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
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%)
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 40df12af5036..0ac47955f3e1 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -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
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 5b85f6adb258..5c5a89479631 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -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
diff --git a/arch/arm/mach-imx/time.c b/drivers/clocksource/timer-imx.c
similarity index 100%
rename from arch/arm/mach-imx/time.c
rename to drivers/clocksource/timer-imx.c
--
1.9.1
^ permalink raw reply related [flat|nested] 19+ messages in thread