All of lore.kernel.org
 help / color / mirror / Atom feed
From: Finn Thain <fthain@telegraphics.com.au>
To: Geert Uytterhoeven <geert@linux-m68k.org>,
	Joshua Thompson <funaho@jurai.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>,
	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 v2 02/14] m68k: mac: Fix VIA timer counter accesses
Date: Mon, 19 Nov 2018 12:10:38 +1100	[thread overview]
Message-ID: <423caba434560f3cff60ab68ae0b71d5e635663c.1542589838.git.fthain@telegraphics.com.au> (raw)
In-Reply-To: <cover.1542589838.git.fthain@telegraphics.com.au>

This resolves some bugs that affect VIA timer counter accesses.
Avoid lost interrupts caused by reading the counter low byte register.
Make allowance for the fact that the counter will be decremented to
0xFFFF before being reloaded.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
Changed since v1:
 - Test the timer interrupt flag unconditionally.
 - Drop some extraneous clean up.
 - Don't try to recover from lost timer interrupts. Don't lose them
in the first place. That means giving up on the timer counter low byte.
The extra precision is probably not worth the extra complexity and
I couldn't make it work anyway.
---
 arch/m68k/mac/via.c | 105 +++++++++++++++++++++++---------------------
 1 file changed, 56 insertions(+), 49 deletions(-)

diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 2ab85b6eb4fe..d1dbf9017300 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -54,16 +54,6 @@ static __u8 rbv_clear;
 
 static int gIER,gIFR,gBufA,gBufB;
 
-/*
- * Timer defs.
- */
-
-#define TICK_SIZE		10000
-#define MAC_CLOCK_TICK		(783300/HZ)		/* ticks per HZ */
-#define MAC_CLOCK_LOW		(MAC_CLOCK_TICK&0xFF)
-#define MAC_CLOCK_HIGH		(MAC_CLOCK_TICK>>8)
-
-
 /*
  * On Macs with a genuine VIA chip there is no way to mask an individual slot
  * interrupt. This limitation also seems to apply to VIA clone logic cores in
@@ -267,22 +257,6 @@ void __init via_init(void)
 	}
 }
 
-/*
- * Start the 100 Hz clock
- */
-
-void __init via_init_clock(irq_handler_t func)
-{
-	via1[vACR] |= 0x40;
-	via1[vT1LL] = MAC_CLOCK_LOW;
-	via1[vT1LH] = MAC_CLOCK_HIGH;
-	via1[vT1CL] = MAC_CLOCK_LOW;
-	via1[vT1CH] = MAC_CLOCK_HIGH;
-
-	if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
-		pr_err("Couldn't register %s interrupt\n", "timer");
-}
-
 /*
  * Debugging dump, used in various places to see what's going on.
  */
@@ -310,29 +284,6 @@ void via_debug_dump(void)
 	}
 }
 
-/*
- * This is always executed with interrupts disabled.
- *
- * TBI: get time offset between scheduling timer ticks
- */
-
-u32 mac_gettimeoffset(void)
-{
-	unsigned long ticks, offset = 0;
-
-	/* read VIA1 timer 2 current value */
-	ticks = via1[vT1CL] | (via1[vT1CH] << 8);
-	/* The probability of underflow is less than 2% */
-	if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
-		/* Check for pending timer interrupt in VIA1 IFR */
-		if (via1[vIFR] & 0x40) offset = TICK_SIZE;
-
-	ticks = MAC_CLOCK_TICK - ticks;
-	ticks = ticks * 10000L / MAC_CLOCK_TICK;
-
-	return (ticks + offset) * 1000;
-}
-
 /*
  * Flush the L2 cache on Macs that have it by flipping
  * the system into 24-bit mode for an instant.
@@ -618,3 +569,59 @@ int via2_scsi_drq_pending(void)
 	return via2[gIFR] & (1 << IRQ_IDX(IRQ_MAC_SCSIDRQ));
 }
 EXPORT_SYMBOL(via2_scsi_drq_pending);
+
+/* timer and clock source */
+
+#define VIA_CLOCK_FREQ     783360                /* VIA "phase 2" clock in Hz */
+#define VIA_TIMER_INTERVAL (1000000 / HZ)        /* microseconds per jiffy */
+#define VIA_TIMER_CYCLES   (VIA_CLOCK_FREQ / HZ) /* clock cycles per jiffy */
+
+#define VIA_TC             (VIA_TIMER_CYCLES - 2) /* including 0 and -1 */
+#define VIA_TC_LOW         (VIA_TC & 0xFF)
+#define VIA_TC_HIGH        (VIA_TC >> 8)
+
+void __init via_init_clock(irq_handler_t timer_routine)
+{
+	if (request_irq(IRQ_MAC_TIMER_1, timer_routine, 0, "timer", NULL)) {
+		pr_err("Couldn't register %s interrupt\n", "timer");
+		return;
+	}
+
+	via1[vT1LL] = VIA_TC_LOW;
+	via1[vT1LH] = VIA_TC_HIGH;
+	via1[vT1CL] = VIA_TC_LOW;
+	via1[vT1CH] = VIA_TC_HIGH;
+	via1[vACR] |= 0x40;
+}
+
+u32 mac_gettimeoffset(void)
+{
+	unsigned long flags;
+	u8 count_high;
+	u16 count, offset = 0;
+
+	/*
+	 * Timer counter wrap-around is detected with the timer interrupt flag
+	 * but reading the counter low byte (vT1CL) would reset the flag.
+	 * Also, accessing both counter registers is essentially a data race.
+	 * These problems are avoided by ignoring the low byte. Clock accuracy
+	 * is 256 times worse (error can reach 0.327 ms) but CPU overhead is
+	 * reduced by avoiding slow VIA register accesses.
+	 */
+
+	local_irq_save(flags);
+	count_high = via1[vT1CH];
+	if (count_high == 0xFF) {
+		count_high = 0;
+		while (via1[vT1CH] == 0xFF)
+			/* spin */;
+	}
+	if (via1[vIFR] & VIA_TIMER_1_INT)
+		offset = VIA_TIMER_CYCLES;
+	local_irq_restore(flags);
+
+	count = count_high << 8;
+	count = VIA_TIMER_CYCLES - count + offset;
+
+	return ((count * VIA_TIMER_INTERVAL) / VIA_TIMER_CYCLES) * 1000;
+}
-- 
2.18.1


  parent reply	other threads:[~2018-11-19  1:23 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-19  1:10 [RFC PATCH v2 00/14] m68k: Drop arch_gettimeoffset and adopt clocksource API Finn Thain
2018-11-19  1:10 ` [RFC PATCH v2 09/14] m68k: hp300: Remove hp300_gettimeoffset() Finn Thain
2018-11-20  9:09   ` Kars de Jong
2018-11-20 23:13     ` Finn Thain
2018-11-21  8:10       ` Geert Uytterhoeven
2018-11-21  8:41         ` Finn Thain
2018-11-21  8:55           ` Geert Uytterhoeven
2018-11-21  9:47             ` Finn Thain
2018-11-21 10:02               ` Geert Uytterhoeven
2018-11-21 11:14                 ` Finn Thain
2018-11-25  1:15                   ` Finn Thain
2018-11-25  2:44                     ` Michael Schmitz
2018-11-25  3:25                       ` Finn Thain
2018-11-21  8:22       ` Kars de Jong
2018-11-19  1:10 ` [RFC PATCH v2 07/14] m68k: atari: Convert to clocksource API Finn Thain
2018-11-19  8:35   ` Michael Schmitz
2018-11-20  8:10   ` Linus Walleij
2018-11-20  8:19     ` Geert Uytterhoeven
2018-11-20  9:30     ` Finn Thain
2018-11-20  9:53       ` Linus Walleij
2018-11-20 10:02     ` Andreas Schwab
2018-11-24  2:03       ` Michael Schmitz
2018-11-24  3:08         ` Finn Thain
2018-11-19  1:10 ` [RFC PATCH v2 08/14] m68k: bvme6000: " Finn Thain
2018-11-19  1:10 ` [RFC PATCH v2 11/14] m68k: mvme147: " Finn Thain
2018-11-19  1:10 ` [RFC PATCH v2 10/14] m68k: mac: " Finn Thain
2018-11-20  8:15   ` Linus Walleij
2018-11-20  9:00     ` Finn Thain
2018-11-20  9:59       ` Linus Walleij
2018-11-19  1:10 ` [RFC PATCH v2 04/14] m68k: apollo, q40, sun3, sun3x: Remove arch_gettimeoffset implementations Finn Thain
2018-11-19  1:10 ` [RFC PATCH v2 01/14] m68k: Call timer_interrupt() with interrupts disabled Finn Thain
2018-11-19  1:10 ` [RFC PATCH v2 03/14] m68k: mac: Clean up unused timer definitions Finn Thain
2018-11-20  1:02   ` Finn Thain
2018-11-19  1:10 ` [RFC PATCH v2 12/14] m68k: mvme147: Handle timer counter overflow Finn Thain
2018-11-19  1:10 ` [RFC PATCH v2 13/14] m68k: mvme16x: Convert to clocksource API Finn Thain
2018-11-19  1:10 ` Finn Thain [this message]
2018-11-19  1:10 ` [RFC PATCH v2 06/14] m68k: amiga: " Finn Thain
2018-11-20  8:04   ` Linus Walleij
2018-11-19  1:10 ` [RFC PATCH v2 05/14] m68k: Drop ARCH_USES_GETTIMEOFFSET Finn Thain
2018-11-19  1:10 ` [RFC PATCH v2 14/14] m68k: mvme16x: 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=423caba434560f3cff60ab68ae0b71d5e635663c.1542589838.git.fthain@telegraphics.com.au \
    --to=fthain@telegraphics.com.au \
    --cc=arnd@arndb.de \
    --cc=daniel.lezcano@linaro.org \
    --cc=funaho@jurai.org \
    --cc=geert@linux-m68k.org \
    --cc=john.stultz@linaro.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 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.