All of lore.kernel.org
 help / color / mirror / Atom feed
From: Russell King <rmk+kernel@armlinux.org.uk>
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/8] ARM: riscpc: replace gettimeoffset() with clocksource
Date: Mon, 20 May 2019 15:46:53 +0100	[thread overview]
Message-ID: <E1hSjYz-0000Xh-VV@rmk-PC.armlinux.org.uk> (raw)
In-Reply-To: <20190520144615.gzrztyhoncyfc5xr@shell.armlinux.org.uk>

Replace the old gettimeoffset() interface (which became buggy in
several ways) with a clocksource that atomically reads the count
and status from the timer, and corrects the count as appropriate
ensuring proper resolution of time without time warping backwards.

We keep the original periodic timer non-clock event implementation
to provide the kernel with a regular source of interrupts, which
are required to keep the clocksource properly updated.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/Kconfig         |  1 -
 arch/arm/mach-rpc/time.c | 38 +++++++++++++++++++++++++-------------
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9aed25a6019b..08a4915a69d2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -528,7 +528,6 @@ config ARCH_RPC
 	select ARCH_ACORN
 	select ARCH_MAY_HAVE_PC_FDC
 	select ARCH_SPARSEMEM_ENABLE
-	select ARCH_USES_GETTIMEOFFSET
 	select CPU_SA110
 	select FIQ
 	select HAVE_IDE
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index 2689771c1d38..1c84efc9db1f 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -13,7 +13,7 @@
  *   04-Dec-1997	RMK	Updated for new arch/arm/time.c
  *   13=Jun-2004	DS	Moved to arch/arm/common b/c shared w/CLPS7500
  */
-#include <linux/timex.h>
+#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -27,11 +27,15 @@
 #define RPC_CLOCK_FREQ 2000000
 #define RPC_LATCH DIV_ROUND_CLOSEST(RPC_CLOCK_FREQ, HZ)
 
-static u32 ioc_timer_gettimeoffset(void)
+static u32 ioc_time;
+
+static u64 ioc_timer_read(struct clocksource *cs)
 {
 	unsigned int count1, count2, status;
-	long offset;
+	unsigned long flags;
+	u32 ticks;
 
+	local_irq_save(flags);
 	ioc_writeb (0, IOC_T0LATCH);
 	barrier ();
 	count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
@@ -41,27 +45,34 @@ static u32 ioc_timer_gettimeoffset(void)
 	ioc_writeb (0, IOC_T0LATCH);
 	barrier ();
 	count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
+	ticks = ioc_time + RPC_LATCH - count2;
+	local_irq_restore(flags);
 
-	offset = count2;
 	if (count2 < count1) {
 		/*
-		 * We have not had an interrupt between reading count1
-		 * and count2.
+		 * The timer has not reloaded between reading count1 and
+		 * count2, check whether an interrupt was actually pending.
 		 */
 		if (status & (1 << 5))
-			offset -= RPC_LATCH;
+			ticks += RPC_LATCH;
 	} else if (count2 > count1) {
 		/*
-		 * We have just had another interrupt between reading
-		 * count1 and count2.
+		 * The timer has reloaded, so count2 indicates the new
+		 * count since the wrap.  The interrupt would not have
+		 * been processed, so add the missed ticks.
 		 */
-		offset -= RPC_LATCH;
+		ticks += RPC_LATCH;
 	}
 
-	offset = (RPC_LATCH - offset) * (tick_nsec / 1000);
-	return DIV_ROUND_CLOSEST(offset, RPC_LATCH) * 1000;
+	return ticks;
 }
 
+static struct clocksource ioctime_clocksource = {
+	.read = ioc_timer_read,
+	.mask = CLOCKSOURCE_MASK(32),
+	.rating = 100,
+};
+
 void __init ioctime_init(void)
 {
 	ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
@@ -72,6 +83,7 @@ void __init ioctime_init(void)
 static irqreturn_t
 ioc_timer_interrupt(int irq, void *dev_id)
 {
+	ioc_time += RPC_LATCH;
 	timer_tick();
 	return IRQ_HANDLED;
 }
@@ -86,7 +98,7 @@ static struct irqaction ioc_timer_irq = {
  */
 void __init ioc_timer_init(void)
 {
-	arch_gettimeoffset = ioc_timer_gettimeoffset;
+	WARN_ON(clocksource_register_hz(&ioctime_clocksource, RPC_CLOCK_FREQ));
 	ioctime_init();
 	setup_irq(IRQ_TIMER0, &ioc_timer_irq);
 }
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2019-05-20 14:47 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-20 14:46 [PATCH 0/8] Resurect RiscPC support Russell King - ARM Linux admin
2019-05-20 14:46 ` Russell King [this message]
2019-05-20 14:46 ` [PATCH 2/8] ARM: riscpc: fix lack of keyboard interrupts after irq conversion Russell King
2019-05-20 14:47 ` [PATCH 3/8] ARM: riscpc: fix ecard printing Russell King
2019-05-20 14:47 ` [PATCH 4/8] ARM: riscpc: fix DMA Russell King
2019-05-20 14:47 ` [PATCH 5/8] ARM: riscpc: dma: eliminate "cur_sg" scatterlist usage Russell King
2019-05-20 14:47 ` [PATCH 6/8] ARM: riscpc: dma: make state a local variable Russell King
2019-05-20 14:47 ` [PATCH 7/8] ARM: riscpc: dma: improve address/length writing Russell King
2019-05-20 14:47 ` [PATCH 8/8] ARM: riscpc: dma: use __iomem pointers for writing DMA Russell King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E1hSjYz-0000Xh-VV@rmk-PC.armlinux.org.uk \
    --to=rmk+kernel@armlinux.org.uk \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.