Re: [RFC PATCH v2 06/14] m68k: amiga: 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 
> ---
> Changed since v1:
>  - Moved clk_total access to within the irq lock.

Came to think of it, Geert can probably answer to the use cases
for the CIAs in Linux: the Amiga CIA has two counters.

It would make sense to use one as a free-runing clocksource and
the other one as clock event. Then Linux is extremely happy
without any complex workarounds trying to use just one timer
for both jobs.

Is there some specific reason why we can't use both counters
like this, except for legacy? (I am thinking it would be an improvement
on top of Finn's series once they go in.)

Yours,
Linus Walleij


[RFC PATCH v2 06/14] m68k: amiga: 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 
---
Changed since v1:
 - Moved clk_total access to within the irq lock.
---
 arch/m68k/amiga/config.c | 43 
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index d4976c1aa0cc..c498f8419c87 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -461,7 +462,28 @@ void __init config_amiga(void)
*(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
 }
 
+static u64 amiga_read_clk(struct clocksource *cs);
+
+static struct clocksource amiga_clk = {
+   .name   = "ciab",
+   .rating = 250,
+   .read   = amiga_read_clk,
+   .mask   = CLOCKSOURCE_MASK(32),
+   .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
 static unsigned short jiffy_ticks;
+static u32 clk_total;
+
+static irqreturn_t ciab_timer_handler(int irq, void *dev_id)
+{
+   irq_handler_t timer_routine = dev_id;
+
+   clk_total += jiffy_ticks;
+   timer_routine(0, NULL);
+
+   return IRQ_HANDLED;
+}
 
 static void __init amiga_sched_init(irq_handler_t timer_routine)
 {
@@ -481,20 +503,23 @@ static void __init amiga_sched_init(irq_handler_t 
timer_routine)
 * Please don't change this to use ciaa, as it interferes with the
 * SCSI code. We'll have to take a look at this later
 */
-   if (request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL))
+   if (request_irq(IRQ_AMIGA_CIAB_TA, ciab_timer_handler, IRQF_TIMER,
+   "timer", timer_routine))
pr_err("Couldn't register timer interrupt\n");
/* start timer */
ciab.cra |= 0x11;
-}
 
-#define TICK_SIZE 1
+   clocksource_register_hz(_clk, amiga_eclock);
+}
 
-/* This is always executed with interrupts disabled.  */
-static u32 amiga_gettimeoffset(void)
+static u64 amiga_read_clk(struct clocksource *cs)
 {
+   unsigned long flags;
unsigned short hi, lo, hi2;
u32 ticks, offset = 0;
 
+   local_irq_save(flags);
+
/* read CIA B timer A current value */
hi  = ciab.tahi;
lo  = ciab.talo;
@@ -510,12 +535,14 @@ static u32 amiga_gettimeoffset(void)
if (ticks > jiffy_ticks / 2)
/* check for pending interrupt */
if (cia_set_irq(_base, 0) & CIA_ICR_TA)
-   offset = 1;
+   offset = jiffy_ticks;
 
ticks = jiffy_ticks - ticks;
-   ticks = (1 * ticks) / jiffy_ticks;
+   ticks += offset + clk_total;
+
+   local_irq_restore(flags);
 
-   return (ticks + offset) * 1000;
+   return ticks;
 }
 
 static void amiga_reset(void)  __noreturn;
-- 
2.18.1