linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Finn Thain <fthain@telegraphics.com.au>
To: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Andreas Schwab <schwab@linux-m68k.org>,
	Arnd Bergmann <arnd@arndb.de>,
	Stephen N Chivers <schivers@csc.com.au>,
	Thomas Gleixner <tglx@linutronix.de>,
	Kars de Jong <jongk@linux-m68k.org>,
	Daniel Lezcano <daniel.lezcano@linaro.org>,
	Michael Schmitz <schmitzmic@gmail.com>,
	John Stultz <john.stultz@linaro.org>,
	Linus Walleij <linus.walleij@linaro.org>,
	linux-m68k@lists.linux-m68k.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH v3 06/14] m68k: atari: Convert to clocksource API
Date: Sat, 24 Nov 2018 14:09:03 +1100	[thread overview]
Message-ID: <d736dba8698479b330be8c371c3882e376c6769a.1543028943.git.fthain@telegraphics.com.au> (raw)
In-Reply-To: <cover.1543028943.git.fthain@telegraphics.com.au>

Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Normally the MFP timer C interrupt flag would be used to check for
timer counter wrap-around. Unfortunately, that flag gets cleared by the
MFP itself (due to automatic End-of-Interrupt mode). This means that
mfp_timer_c_handler() and atari_read_clk() must race when accounting
for counter wrap-around.

That problem is avoided by effectively stopping the clock when it might
otherwise jump backwards (due to interrupt latency). Note that this may
affect clock accuracy.

After the timer interrupt is asserted, wait for the counter to be
reloaded so that atari_read_clk() will not see the intermediate state
as that would cause the clock to jump backwards.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
---
TODO: find a spare counter for the clocksource, rather than hanging
it off the HZ timer.

Changed since v2:
 - Wait for timer reload after timer interrupt.
 - Add comment and improve code style for better clarity.

Changed since v1:
 - Moved clk_total access to within the irq lock.
 - Renamed mfp_timer_handler and mfptimer_handler.
 - Avoid accessing the timer interrupt flag in atari_read_clk(). To
get monotonicity, keep track of the previous timer counter value.
---
 arch/m68k/atari/time.c | 53 ++++++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 17 deletions(-)

diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index fafa20f75ab9..ce923a523695 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/rtc.h>
 #include <linux/bcd.h>
+#include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 
@@ -24,12 +25,29 @@
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL_GPL(rtc_lock);
 
+static u64 atari_read_clk(struct clocksource *cs);
+
+static struct clocksource atari_clk = {
+	.name   = "mfp",
+	.rating = 100,
+	.read   = atari_read_clk,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 clk_total;
+static u8 last_timer_count;
+
 static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id)
 {
 	irq_handler_t timer_routine = dev_id;
 	unsigned long flags;
 
 	local_irq_save(flags);
+	do {
+		last_timer_count = st_mfp.tim_dt_c;
+	} while (last_timer_count == 1);
+	clk_total += INT_TICKS;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
 
@@ -44,32 +62,33 @@ atari_sched_init(irq_handler_t timer_routine)
     /* start timer C, div = 1:100 */
     st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
     /* install interrupt service routine for MFP Timer C */
-    if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, 0, "timer",
+    if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, IRQF_TIMER, "timer",
                     timer_routine))
 	pr_err("Couldn't register timer interrupt\n");
+
+    clocksource_register_hz(&atari_clk, INT_CLK);
 }
 
 /* ++andreas: gettimeoffset fixed to check for pending interrupt */
 
-#define TICK_SIZE 10000
-
-/* This is always executed with interrupts disabled.  */
-u32 atari_gettimeoffset(void)
+static u64 atari_read_clk(struct clocksource *cs)
 {
-  u32 ticks, offset = 0;
-
-  /* read MFP timer C current value */
-  ticks = st_mfp.tim_dt_c;
-  /* The probability of underflow is less than 2% */
-  if (ticks > INT_TICKS - INT_TICKS / 50)
-    /* Check for pending timer interrupt */
-    if (st_mfp.int_pn_b & (1 << 5))
-      offset = TICK_SIZE;
+	unsigned long flags;
+	u8 count;
+	u32 ticks;
 
-  ticks = INT_TICKS - ticks;
-  ticks = ticks * 10000L / INT_TICKS;
+	local_irq_save(flags);
+	/* Ensure that the count is monotonically decreasing, even though
+	 * the result may briefly stop changing after counter wrap-around.
+	 */
+	count = min(st_mfp.tim_dt_c, last_timer_count);
+	last_timer_count = count;
+
+	ticks = INT_TICKS - count;
+	ticks += clk_total;
+	local_irq_restore(flags);
 
-  return (ticks + offset) * 1000;
+	return ticks;
 }
 
 
-- 
2.18.1


  parent reply	other threads:[~2018-11-24  3:11 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-24  3:09 [RFC PATCH v3 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 11/14] m68k: mvme147: Convert to " Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 04/14] m68k: Drop ARCH_USES_GETTIMEOFFSET Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 07/14] m68k: bvme6000: Convert to clocksource API Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 14/14] m68k: mvme16x: Handle timer counter overflow Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 02/14] m68k: mac: Fix VIA timer counter accesses Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 05/14] m68k: amiga: Convert to clocksource API Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 03/14] m68k: apollo, q40, sun3, sun3x: Remove arch_gettimeoffset implementations Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 12/14] m68k: mvme147: Handle timer counter overflow Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 08/14] m68k: hp300: Convert to clocksource API Finn Thain
2018-11-24  3:09 ` Finn Thain [this message]
2018-11-24  3:09 ` [RFC PATCH v3 01/14] m68k: Call timer_interrupt() with interrupts disabled Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 10/14] m68k: mac: Convert to clocksource API Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 13/14] m68k: mvme16x: " Finn Thain
2018-11-24  3:09 ` [RFC PATCH v3 09/14] m68k: hp300: Handle timer counter overflow Finn Thain

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=d736dba8698479b330be8c371c3882e376c6769a.1543028943.git.fthain@telegraphics.com.au \
    --to=fthain@telegraphics.com.au \
    --cc=arnd@arndb.de \
    --cc=daniel.lezcano@linaro.org \
    --cc=geert@linux-m68k.org \
    --cc=john.stultz@linaro.org \
    --cc=jongk@linux-m68k.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-m68k@lists.linux-m68k.org \
    --cc=schivers@csc.com.au \
    --cc=schmitzmic@gmail.com \
    --cc=schwab@linux-m68k.org \
    --cc=tglx@linutronix.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).