All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] lpc32xx clockevent: Support periodic mode and ARM delay timer
@ 2016-02-10  1:54 Ezequiel Garcia
  2016-02-10  1:54 ` [PATCH v2 1/3] clocksource/drivers/lpc32xx: Don't use the prescaler counter for clockevents Ezequiel Garcia
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Ezequiel Garcia @ 2016-02-10  1:54 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset introduces periodic timer mode. As was discussed on v1,
the current implementation (MR0=1, PR=ticks) is not suitable for
implementing a periodoc timer mode.

This can be seen with a very simple test, by counting the number of
interrupts during 1-second.

Implementing the periodic timer mode with MR0=1, PR=ticks_per_jiffy
results in half the expected number of interrupts (CONFIG_HZ=100):

(See: http://git.infradead.org/users/ezequielg/linux/shortlog/refs/heads/lpc32xx_periodic_with_pr)

$ cat /proc/interrupts | grep clockevent && sleep 1 && cat /proc/interrupts | grep clockevent
 16:        846  nvic_irq  13 Edge      lpc3220 clockevent
 16:        900  nvic_irq  13 Edge      lpc3220 clockevent

On the other side, with this patchset the number of interrupts
is closer to the expected:

$ cat /proc/interrupts | grep clockevent && sleep 1 && cat /proc/interrupts | grep clockevent
 16:       1580  nvic_irq  13 Edge      lpc3220 clockevent
 16:       1688  nvic_irq  13 Edge      lpc3220 clockevent

Therefore, the first patch switches the timer one-shot implementation
to use PR=0 and MR0=ticks. The second patch implements periodic mode
using this.

The last patch adds support for the ARM delay timer, which is used
for udelay and also to skip the delay loop calibration.

Ezequiel Garcia (3):
  clocksource/drivers/lpc32xx: Don't use the prescaler counter for
    clockevents
  clocksource/drivers/lpc32xx: Support periodic mode
  clocksource/drivers/lpc32xx: Support timer-based ARM delay

 drivers/clocksource/Kconfig        |  1 +
 drivers/clocksource/time-lpc32xx.c | 66 ++++++++++++++++++++++++++++++--------
 2 files changed, 54 insertions(+), 13 deletions(-)

-- 
2.7.0

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

* [PATCH v2 1/3] clocksource/drivers/lpc32xx: Don't use the prescaler counter for clockevents
  2016-02-10  1:54 [PATCH v2 0/3] lpc32xx clockevent: Support periodic mode and ARM delay timer Ezequiel Garcia
@ 2016-02-10  1:54 ` Ezequiel Garcia
  2016-02-13 13:06   ` Joachim Eastwood
  2016-02-10  1:54 ` [PATCH v2 2/3] clocksource/drivers/lpc32xx: Support periodic mode Ezequiel Garcia
  2016-02-10  1:54 ` [PATCH v2 3/3] clocksource/drivers/lpc32xx: Support timer-based ARM delay Ezequiel Garcia
  2 siblings, 1 reply; 7+ messages in thread
From: Ezequiel Garcia @ 2016-02-10  1:54 UTC (permalink / raw)
  To: linux-arm-kernel

This commit switches the clockevents one-shot current implementation
to avoid using the prescaler counter. The clockevents timer currently
uses MR0=1, PR=ticks; and after this commit is uses MR0=ticks, PR=0.

While using the prescaler with PR=1 works fine in one-shot mode,
it seems it doesn't work as expected in periodic mode.

By using the only match channel register (MR0) for the timer we make
the periodic mode introduction easier, and consistent with one-shot mode.

Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
---
 drivers/clocksource/time-lpc32xx.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c
index 1316876b487a..50d1a63cbe1e 100644
--- a/drivers/clocksource/time-lpc32xx.c
+++ b/drivers/clocksource/time-lpc32xx.c
@@ -60,14 +60,13 @@ static int lpc32xx_clkevt_next_event(unsigned long delta,
 		container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev);
 
 	/*
-	 * Place timer in reset and program the delta in the prescale
-	 * register (PR). When the prescale counter matches the value
-	 * in PR the counter register is incremented and the compare
-	 * match will trigger. After setup the timer is released from
-	 * reset and enabled.
+	 * Place timer in reset and program the delta in the match
+	 * channel 0 (MR0). When the timer counter matches the value
+	 * in MR0 register the match will trigger an interrupt.
+	 * After setup the timer is released from reset and enabled.
 	 */
 	writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR);
-	writel_relaxed(delta, ddata->base + LPC32XX_TIMER_PR);
+	writel_relaxed(delta, ddata->base + LPC32XX_TIMER_MR0);
 	writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR);
 
 	return 0;
@@ -210,13 +209,13 @@ static int __init lpc32xx_clockevent_init(struct device_node *np)
 
 	/*
 	 * Disable timer and clear any pending interrupt (IR) on match
-	 * channel 0 (MR0). Configure a compare match value of 1 on MR0
-	 * and enable interrupt, reset on match and stop on match (MCR).
+	 * channel 0 (MR0). Clear the prescaler as it's not used.
+	 * Enable interrupt, reset on match and stop on match (MCR).
 	 */
 	writel_relaxed(0, base + LPC32XX_TIMER_TCR);
+	writel_relaxed(0, base + LPC32XX_TIMER_PR);
 	writel_relaxed(0, base + LPC32XX_TIMER_CTCR);
 	writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR);
-	writel_relaxed(1, base + LPC32XX_TIMER_MR0);
 	writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R |
 		       LPC32XX_TIMER_MCR_MR0S, base + LPC32XX_TIMER_MCR);
 
-- 
2.7.0

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

* [PATCH v2 2/3] clocksource/drivers/lpc32xx: Support periodic mode
  2016-02-10  1:54 [PATCH v2 0/3] lpc32xx clockevent: Support periodic mode and ARM delay timer Ezequiel Garcia
  2016-02-10  1:54 ` [PATCH v2 1/3] clocksource/drivers/lpc32xx: Don't use the prescaler counter for clockevents Ezequiel Garcia
@ 2016-02-10  1:54 ` Ezequiel Garcia
  2016-02-13 13:08   ` Joachim Eastwood
  2016-02-10  1:54 ` [PATCH v2 3/3] clocksource/drivers/lpc32xx: Support timer-based ARM delay Ezequiel Garcia
  2 siblings, 1 reply; 7+ messages in thread
From: Ezequiel Garcia @ 2016-02-10  1:54 UTC (permalink / raw)
  To: linux-arm-kernel

This commit adds the support for periodic mode. This is done by not
setting the MR0S (Stop on TnMR0) bit on MCR, thus allowing
interrupts to be periodically generated on MR0 matches.

In order to do this, move the initial configuration that is specific to
the one-shot mode to set_state_oneshot().

Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
---
 drivers/clocksource/time-lpc32xx.c | 39 +++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c
index 50d1a63cbe1e..5694eddade15 100644
--- a/drivers/clocksource/time-lpc32xx.c
+++ b/drivers/clocksource/time-lpc32xx.c
@@ -43,6 +43,7 @@
 struct lpc32xx_clock_event_ddata {
 	struct clock_event_device evtdev;
 	void __iomem *base;
+	u32 ticks_per_jiffy;
 };
 
 /* Needed for the sched clock */
@@ -85,11 +86,39 @@ static int lpc32xx_clkevt_shutdown(struct clock_event_device *evtdev)
 
 static int lpc32xx_clkevt_oneshot(struct clock_event_device *evtdev)
 {
+	struct lpc32xx_clock_event_ddata *ddata =
+		container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev);
+
 	/*
 	 * When using oneshot, we must also disable the timer
 	 * to wait for the first call to set_next_event().
 	 */
-	return lpc32xx_clkevt_shutdown(evtdev);
+	writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR);
+
+	/* Enable interrupt, reset on match and stop on match (MCR). */
+	writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R |
+		       LPC32XX_TIMER_MCR_MR0S, ddata->base + LPC32XX_TIMER_MCR);
+	return 0;
+}
+
+static int lpc32xx_clkevt_periodic(struct clock_event_device *evtdev)
+{
+	struct lpc32xx_clock_event_ddata *ddata =
+		container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev);
+
+	/* Enable interrupt and reset on match. */
+	writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R,
+		       ddata->base + LPC32XX_TIMER_MCR);
+
+	/*
+	 * Place timer in reset and program the delta in the match
+	 * channel 0 (MR0).
+	 */
+	writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR);
+	writel_relaxed(ddata->ticks_per_jiffy, ddata->base + LPC32XX_TIMER_MR0);
+	writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR);
+
+	return 0;
 }
 
 static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id)
@@ -107,11 +136,13 @@ static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id)
 static struct lpc32xx_clock_event_ddata lpc32xx_clk_event_ddata = {
 	.evtdev = {
 		.name			= "lpc3220 clockevent",
-		.features		= CLOCK_EVT_FEAT_ONESHOT,
+		.features		= CLOCK_EVT_FEAT_ONESHOT |
+					  CLOCK_EVT_FEAT_PERIODIC,
 		.rating			= 300,
 		.set_next_event		= lpc32xx_clkevt_next_event,
 		.set_state_shutdown	= lpc32xx_clkevt_shutdown,
 		.set_state_oneshot	= lpc32xx_clkevt_oneshot,
+		.set_state_periodic	= lpc32xx_clkevt_periodic,
 	},
 };
 
@@ -210,17 +241,15 @@ static int __init lpc32xx_clockevent_init(struct device_node *np)
 	/*
 	 * Disable timer and clear any pending interrupt (IR) on match
 	 * channel 0 (MR0). Clear the prescaler as it's not used.
-	 * Enable interrupt, reset on match and stop on match (MCR).
 	 */
 	writel_relaxed(0, base + LPC32XX_TIMER_TCR);
 	writel_relaxed(0, base + LPC32XX_TIMER_PR);
 	writel_relaxed(0, base + LPC32XX_TIMER_CTCR);
 	writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR);
-	writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R |
-		       LPC32XX_TIMER_MCR_MR0S, base + LPC32XX_TIMER_MCR);
 
 	rate = clk_get_rate(clk);
 	lpc32xx_clk_event_ddata.base = base;
+	lpc32xx_clk_event_ddata.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
 	clockevents_config_and_register(&lpc32xx_clk_event_ddata.evtdev,
 					rate, 1, -1);
 
-- 
2.7.0

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

* [PATCH v2 3/3] clocksource/drivers/lpc32xx: Support timer-based ARM delay
  2016-02-10  1:54 [PATCH v2 0/3] lpc32xx clockevent: Support periodic mode and ARM delay timer Ezequiel Garcia
  2016-02-10  1:54 ` [PATCH v2 1/3] clocksource/drivers/lpc32xx: Don't use the prescaler counter for clockevents Ezequiel Garcia
  2016-02-10  1:54 ` [PATCH v2 2/3] clocksource/drivers/lpc32xx: Support periodic mode Ezequiel Garcia
@ 2016-02-10  1:54 ` Ezequiel Garcia
  2016-02-13 13:10   ` Joachim Eastwood
  2 siblings, 1 reply; 7+ messages in thread
From: Ezequiel Garcia @ 2016-02-10  1:54 UTC (permalink / raw)
  To: linux-arm-kernel

This commit implements the ARM timer-based delay timer for the
LPC32xx, LPC18xx, LPC43xx family of SoCs.

Also, add a dependency to restrict compiling this driver for
the ARM architecture.

Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
---
 drivers/clocksource/Kconfig        |  1 +
 drivers/clocksource/time-lpc32xx.c | 12 ++++++++++++
 2 files changed, 13 insertions(+)

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 33db7406c0e2..c346be650892 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -160,6 +160,7 @@ config CLKSRC_EFM32
 config CLKSRC_LPC32XX
 	bool "Clocksource for LPC32XX" if COMPILE_TEST
 	depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
+	depends on ARM
 	select CLKSRC_MMIO
 	select CLKSRC_OF
 	help
diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c
index 5694eddade15..daae61e8c820 100644
--- a/drivers/clocksource/time-lpc32xx.c
+++ b/drivers/clocksource/time-lpc32xx.c
@@ -18,6 +18,7 @@
 #include <linux/clk.h>
 #include <linux/clockchips.h>
 #include <linux/clocksource.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
@@ -54,6 +55,15 @@ static u64 notrace lpc32xx_read_sched_clock(void)
 	return readl(clocksource_timer_counter);
 }
 
+static unsigned long lpc32xx_delay_timer_read(void)
+{
+	return readl(clocksource_timer_counter);
+}
+
+static struct delay_timer lpc32xx_delay_timer = {
+	.read_current_timer = lpc32xx_delay_timer_read,
+};
+
 static int lpc32xx_clkevt_next_event(unsigned long delta,
 				     struct clock_event_device *evtdev)
 {
@@ -192,6 +202,8 @@ static int __init lpc32xx_clocksource_init(struct device_node *np)
 	}
 
 	clocksource_timer_counter = base + LPC32XX_TIMER_TC;
+	lpc32xx_delay_timer.freq = rate;
+	register_current_timer_delay(&lpc32xx_delay_timer);
 	sched_clock_register(lpc32xx_read_sched_clock, 32, rate);
 
 	return 0;
-- 
2.7.0

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

* [PATCH v2 1/3] clocksource/drivers/lpc32xx: Don't use the prescaler counter for clockevents
  2016-02-10  1:54 ` [PATCH v2 1/3] clocksource/drivers/lpc32xx: Don't use the prescaler counter for clockevents Ezequiel Garcia
@ 2016-02-13 13:06   ` Joachim Eastwood
  0 siblings, 0 replies; 7+ messages in thread
From: Joachim Eastwood @ 2016-02-13 13:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ezequiel,

On 10 February 2016 at 02:54, Ezequiel Garcia
<ezequiel@vanguardiasur.com.ar> wrote:
> This commit switches the clockevents one-shot current implementation
> to avoid using the prescaler counter. The clockevents timer currently
> uses MR0=1, PR=ticks; and after this commit is uses MR0=ticks, PR=0.
>
> While using the prescaler with PR=1 works fine in one-shot mode,
> it seems it doesn't work as expected in periodic mode.
>
> By using the only match channel register (MR0) for the timer we make
> the periodic mode introduction easier, and consistent with one-shot mode.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
> ---
>  drivers/clocksource/time-lpc32xx.c | 17 ++++++++---------
>  1 file changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c
> index 1316876b487a..50d1a63cbe1e 100644
> --- a/drivers/clocksource/time-lpc32xx.c
> +++ b/drivers/clocksource/time-lpc32xx.c
> @@ -60,14 +60,13 @@ static int lpc32xx_clkevt_next_event(unsigned long delta,
>                 container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev);
>
>         /*
> -        * Place timer in reset and program the delta in the prescale
> -        * register (PR). When the prescale counter matches the value
> -        * in PR the counter register is incremented and the compare
> -        * match will trigger. After setup the timer is released from
> -        * reset and enabled.
> +        * Place timer in reset and program the delta in the match
> +        * channel 0 (MR0). When the timer counter matches the value
> +        * in MR0 register the match will trigger an interrupt.
> +        * After setup the timer is released from reset and enabled.
>          */
>         writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR);
> -       writel_relaxed(delta, ddata->base + LPC32XX_TIMER_PR);
> +       writel_relaxed(delta, ddata->base + LPC32XX_TIMER_MR0);
>         writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR);
>
>         return 0;
> @@ -210,13 +209,13 @@ static int __init lpc32xx_clockevent_init(struct device_node *np)
>
>         /*
>          * Disable timer and clear any pending interrupt (IR) on match
> -        * channel 0 (MR0). Configure a compare match value of 1 on MR0
> -        * and enable interrupt, reset on match and stop on match (MCR).
> +        * channel 0 (MR0). Clear the prescaler as it's not used.
> +        * Enable interrupt, reset on match and stop on match (MCR).
>          */
>         writel_relaxed(0, base + LPC32XX_TIMER_TCR);
> +       writel_relaxed(0, base + LPC32XX_TIMER_PR);
>         writel_relaxed(0, base + LPC32XX_TIMER_CTCR);
>         writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR);
> -       writel_relaxed(1, base + LPC32XX_TIMER_MR0);
>         writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R |
>                        LPC32XX_TIMER_MCR_MR0S, base + LPC32XX_TIMER_MCR);
>
> --

There were fewer changes need to switch to MR0 than I thought. Good.

Reviewed-by: Joachim Eastwood <manabian@gmail.com>
Tested-by: Joachim Eastwood <manabian@gmail.com>

Boot tested on EA4357.


regards,
Joachim Eastwood

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

* [PATCH v2 2/3] clocksource/drivers/lpc32xx: Support periodic mode
  2016-02-10  1:54 ` [PATCH v2 2/3] clocksource/drivers/lpc32xx: Support periodic mode Ezequiel Garcia
@ 2016-02-13 13:08   ` Joachim Eastwood
  0 siblings, 0 replies; 7+ messages in thread
From: Joachim Eastwood @ 2016-02-13 13:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ezequiel,

On 10 February 2016 at 02:54, Ezequiel Garcia
<ezequiel@vanguardiasur.com.ar> wrote:
> This commit adds the support for periodic mode. This is done by not
> setting the MR0S (Stop on TnMR0) bit on MCR, thus allowing
> interrupts to be periodically generated on MR0 matches.
>
> In order to do this, move the initial configuration that is specific to
> the one-shot mode to set_state_oneshot().
>
> Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
> ---
>  drivers/clocksource/time-lpc32xx.c | 39 +++++++++++++++++++++++++++++++++-----
>  1 file changed, 34 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c
> index 50d1a63cbe1e..5694eddade15 100644
> --- a/drivers/clocksource/time-lpc32xx.c
> +++ b/drivers/clocksource/time-lpc32xx.c
> @@ -43,6 +43,7 @@
>  struct lpc32xx_clock_event_ddata {
>         struct clock_event_device evtdev;
>         void __iomem *base;
> +       u32 ticks_per_jiffy;
>  };
>
>  /* Needed for the sched clock */
> @@ -85,11 +86,39 @@ static int lpc32xx_clkevt_shutdown(struct clock_event_device *evtdev)
>
>  static int lpc32xx_clkevt_oneshot(struct clock_event_device *evtdev)
>  {
> +       struct lpc32xx_clock_event_ddata *ddata =
> +               container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev);
> +
>         /*
>          * When using oneshot, we must also disable the timer
>          * to wait for the first call to set_next_event().
>          */
> -       return lpc32xx_clkevt_shutdown(evtdev);
> +       writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR);
> +
> +       /* Enable interrupt, reset on match and stop on match (MCR). */
> +       writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R |
> +                      LPC32XX_TIMER_MCR_MR0S, ddata->base + LPC32XX_TIMER_MCR);
> +       return 0;
> +}
> +
> +static int lpc32xx_clkevt_periodic(struct clock_event_device *evtdev)
> +{
> +       struct lpc32xx_clock_event_ddata *ddata =
> +               container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev);
> +
> +       /* Enable interrupt and reset on match. */
> +       writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R,
> +                      ddata->base + LPC32XX_TIMER_MCR);
> +
> +       /*
> +        * Place timer in reset and program the delta in the match
> +        * channel 0 (MR0).
> +        */
> +       writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR);
> +       writel_relaxed(ddata->ticks_per_jiffy, ddata->base + LPC32XX_TIMER_MR0);
> +       writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR);
> +
> +       return 0;
>  }
>
>  static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id)
> @@ -107,11 +136,13 @@ static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id)
>  static struct lpc32xx_clock_event_ddata lpc32xx_clk_event_ddata = {
>         .evtdev = {
>                 .name                   = "lpc3220 clockevent",
> -               .features               = CLOCK_EVT_FEAT_ONESHOT,
> +               .features               = CLOCK_EVT_FEAT_ONESHOT |
> +                                         CLOCK_EVT_FEAT_PERIODIC,
>                 .rating                 = 300,
>                 .set_next_event         = lpc32xx_clkevt_next_event,
>                 .set_state_shutdown     = lpc32xx_clkevt_shutdown,
>                 .set_state_oneshot      = lpc32xx_clkevt_oneshot,
> +               .set_state_periodic     = lpc32xx_clkevt_periodic,
>         },
>  };
>
> @@ -210,17 +241,15 @@ static int __init lpc32xx_clockevent_init(struct device_node *np)
>         /*
>          * Disable timer and clear any pending interrupt (IR) on match
>          * channel 0 (MR0). Clear the prescaler as it's not used.
> -        * Enable interrupt, reset on match and stop on match (MCR).
>          */
>         writel_relaxed(0, base + LPC32XX_TIMER_TCR);
>         writel_relaxed(0, base + LPC32XX_TIMER_PR);
>         writel_relaxed(0, base + LPC32XX_TIMER_CTCR);
>         writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR);
> -       writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R |
> -                      LPC32XX_TIMER_MCR_MR0S, base + LPC32XX_TIMER_MCR);
>
>         rate = clk_get_rate(clk);
>         lpc32xx_clk_event_ddata.base = base;
> +       lpc32xx_clk_event_ddata.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
>         clockevents_config_and_register(&lpc32xx_clk_event_ddata.evtdev,
>                                         rate, 1, -1);


Reviewed-by: Joachim Eastwood <manabian@gmail.com>
Tested-by: Joachim Eastwood <manabian@gmail.com>

Boot tested on EA4357.

regards,
Joachim Eastwood

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

* [PATCH v2 3/3] clocksource/drivers/lpc32xx: Support timer-based ARM delay
  2016-02-10  1:54 ` [PATCH v2 3/3] clocksource/drivers/lpc32xx: Support timer-based ARM delay Ezequiel Garcia
@ 2016-02-13 13:10   ` Joachim Eastwood
  0 siblings, 0 replies; 7+ messages in thread
From: Joachim Eastwood @ 2016-02-13 13:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 10 February 2016 at 02:54, Ezequiel Garcia
<ezequiel@vanguardiasur.com.ar> wrote:
> This commit implements the ARM timer-based delay timer for the
> LPC32xx, LPC18xx, LPC43xx family of SoCs.
>
> Also, add a dependency to restrict compiling this driver for
> the ARM architecture.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
> ---
>  drivers/clocksource/Kconfig        |  1 +
>  drivers/clocksource/time-lpc32xx.c | 12 ++++++++++++
>  2 files changed, 13 insertions(+)
>
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 33db7406c0e2..c346be650892 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -160,6 +160,7 @@ config CLKSRC_EFM32
>  config CLKSRC_LPC32XX
>         bool "Clocksource for LPC32XX" if COMPILE_TEST
>         depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
> +       depends on ARM
>         select CLKSRC_MMIO
>         select CLKSRC_OF
>         help
> diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c
> index 5694eddade15..daae61e8c820 100644
> --- a/drivers/clocksource/time-lpc32xx.c
> +++ b/drivers/clocksource/time-lpc32xx.c
> @@ -18,6 +18,7 @@
>  #include <linux/clk.h>
>  #include <linux/clockchips.h>
>  #include <linux/clocksource.h>
> +#include <linux/delay.h>
>  #include <linux/interrupt.h>
>  #include <linux/irq.h>
>  #include <linux/kernel.h>
> @@ -54,6 +55,15 @@ static u64 notrace lpc32xx_read_sched_clock(void)
>         return readl(clocksource_timer_counter);
>  }
>
> +static unsigned long lpc32xx_delay_timer_read(void)
> +{
> +       return readl(clocksource_timer_counter);
> +}
> +
> +static struct delay_timer lpc32xx_delay_timer = {
> +       .read_current_timer = lpc32xx_delay_timer_read,
> +};
> +
>  static int lpc32xx_clkevt_next_event(unsigned long delta,
>                                      struct clock_event_device *evtdev)
>  {
> @@ -192,6 +202,8 @@ static int __init lpc32xx_clocksource_init(struct device_node *np)
>         }
>
>         clocksource_timer_counter = base + LPC32XX_TIMER_TC;
> +       lpc32xx_delay_timer.freq = rate;
> +       register_current_timer_delay(&lpc32xx_delay_timer);
>         sched_clock_register(lpc32xx_read_sched_clock, 32, rate);
>
>         return 0;

Reviewed-by: Joachim Eastwood <manabian@gmail.com>
Tested-by: Joachim Eastwood <manabian@gmail.com>

Boot tested on EA4357.

regards,
Joachim Eastwood

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

end of thread, other threads:[~2016-02-13 13:10 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-10  1:54 [PATCH v2 0/3] lpc32xx clockevent: Support periodic mode and ARM delay timer Ezequiel Garcia
2016-02-10  1:54 ` [PATCH v2 1/3] clocksource/drivers/lpc32xx: Don't use the prescaler counter for clockevents Ezequiel Garcia
2016-02-13 13:06   ` Joachim Eastwood
2016-02-10  1:54 ` [PATCH v2 2/3] clocksource/drivers/lpc32xx: Support periodic mode Ezequiel Garcia
2016-02-13 13:08   ` Joachim Eastwood
2016-02-10  1:54 ` [PATCH v2 3/3] clocksource/drivers/lpc32xx: Support timer-based ARM delay Ezequiel Garcia
2016-02-13 13:10   ` Joachim Eastwood

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