Re: [RFC PATCH v2 10/14] m68k: mac: Convert to clocksource API

2018-11-20 Thread Linus Walleij
On Tue, Nov 20, 2018 at 10:00 AM Finn Thain  wrote:

> If you use one timer as a clock event device and the other as a
> clocksource, there are no timers left to run the existing
> timer_interrupt() handler. So this arrangement would require
> GENERIC_CLOCKEVENTS=y, right?

I think so, yes.

> Then, wouldn't all relevant platforms have to support
> GENERIC_CLOCKEVENTS=y, if a single binary was to support all of those
> platforms?

Good point. I wonder of there is a path forward where we
could have peaceful GENERIC_CLOCKEVENTS and
!GENERIC_CLOCKEVENTS co-existence.

Yours,
Linus Walleij


Re: [RFC PATCH v2 10/14] m68k: mac: Convert to clocksource API

2018-11-20 Thread Finn Thain
On Tue, 20 Nov 2018, Linus Walleij wrote:

> On Mon, Nov 19, 2018 at 2:22 AM Finn Thain  wrote:
> 
> > Add a platform clocksource by adapting the existing arch_gettimeoffset
> > implementation.
> >
> > Signed-off-by: Finn Thain 
> > Acked-by: Linus Walleij 
> > Tested-by: Stan Johnson 
> 
> As noted for the Amiga CIA (which is pretty much a sibling to this MOS 
> 6522 VIA) this chip also has two counters and could use one as 
> clocksource and the other as clock event.
> 
> Again I bet this is just using one timer out of habit.
> 
> It will be an easy feat to make a clean clocksource+clock event for this 
> hardware as well once this refactoring is complete.
> 

Right. Both timer 1 and timer 2 have a timed interrupt mode, and either 
could probably serve as a clock event device or a clocksource. Some Mac 
models have a second VIA with two more timers, but not all.

(As clock event devices, the longest interval you can program is about 83 
ms. As 783360 Hz, 16-bit clocksources, they wrap about 12 times every 
second.)

If you use one timer as a clock event device and the other as a 
clocksource, there are no timers left to run the existing 
timer_interrupt() handler. So this arrangement would require 
GENERIC_CLOCKEVENTS=y, right?

Then, wouldn't all relevant platforms have to support 
GENERIC_CLOCKEVENTS=y, if a single binary was to support all of those 
platforms?

-- 

> Yours,
> Linus Walleij
> 


Re: [RFC PATCH v2 10/14] m68k: mac: Convert to clocksource API

2018-11-20 Thread Linus Walleij
On Mon, Nov 19, 2018 at 2:22 AM Finn Thain  wrote:

> Add a platform clocksource by adapting the existing arch_gettimeoffset
> implementation.
>
> Signed-off-by: Finn Thain 
> Acked-by: Linus Walleij 
> Tested-by: Stan Johnson 

As noted for the Amiga CIA (which is pretty much a sibling to this
MOS 6522 VIA) this chip also has two counters and could use one
as clocksource and the other as clock event.

Again I bet this is just using one timer out of habit.

It will be an easy feat to make a clean clocksource+clock event
for this hardware as well once this refactoring is complete.

Yours,
Linus Walleij


[RFC PATCH v2 10/14] m68k: mac: Convert to clocksource API

2018-11-18 Thread Finn Thain
Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: Finn Thain 
Acked-by: Linus Walleij 
Tested-by: Stan Johnson 
---
Changed since v1:
 - Moved clk_total access to within the irq lock.
 - Use type u32 for tick counter.
---
 arch/m68k/mac/via.c | 46 -
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index d1dbf9017300..de59a5cb4250 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -23,6 +23,7 @@
  *
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -573,16 +574,40 @@ 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 (100 / 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)
 
+static u64 mac_read_clk(struct clocksource *cs);
+
+static struct clocksource mac_clk = {
+   .name   = "via1",
+   .rating = 250,
+   .read   = mac_read_clk,
+   .mask   = CLOCKSOURCE_MASK(32),
+   .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static u32 clk_total;
+static u32 clk_offset;
+
+static irqreturn_t via_timer_handler(int irq, void *dev_id)
+{
+   irq_handler_t timer_routine = dev_id;
+
+   clk_total += VIA_TIMER_CYCLES;
+   clk_offset = 0;
+   timer_routine(0, NULL);
+
+   return IRQ_HANDLED;
+}
+
 void __init via_init_clock(irq_handler_t timer_routine)
 {
-   if (request_irq(IRQ_MAC_TIMER_1, timer_routine, 0, "timer", NULL)) {
+   if (request_irq(IRQ_MAC_TIMER_1, via_timer_handler, IRQF_TIMER, "timer",
+   timer_routine)) {
pr_err("Couldn't register %s interrupt\n", "timer");
return;
}
@@ -592,13 +617,16 @@ void __init via_init_clock(irq_handler_t timer_routine)
via1[vT1CL] = VIA_TC_LOW;
via1[vT1CH] = VIA_TC_HIGH;
via1[vACR] |= 0x40;
+
+   clocksource_register_hz(_clk, VIA_CLOCK_FREQ);
 }
 
-u32 mac_gettimeoffset(void)
+static u64 mac_read_clk(struct clocksource *cs)
 {
unsigned long flags;
u8 count_high;
-   u16 count, offset = 0;
+   u16 count;
+   u32 ticks;
 
/*
 * Timer counter wrap-around is detected with the timer interrupt flag
@@ -617,11 +645,11 @@ u32 mac_gettimeoffset(void)
/* spin */;
}
if (via1[vIFR] & VIA_TIMER_1_INT)
-   offset = VIA_TIMER_CYCLES;
-   local_irq_restore(flags);
-
+   clk_offset = VIA_TIMER_CYCLES;
count = count_high << 8;
-   count = VIA_TIMER_CYCLES - count + offset;
+   ticks = VIA_TIMER_CYCLES - count;
+   ticks += clk_offset + clk_total;
+   local_irq_restore(flags);
 
-   return ((count * VIA_TIMER_INTERVAL) / VIA_TIMER_CYCLES) * 1000;
+   return ticks;
 }
-- 
2.18.1