m68k: mvme147,mvme16x: Don't wipe PCC timer config bits
authorFinn Thain <fthain@telegraphics.com.au>
Tue, 30 Mar 2021 07:37:51 +0000 (18:37 +1100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 14 May 2021 07:50:14 +0000 (09:50 +0200)
[ Upstream commit 43262178c043032e7c42d00de44c818ba05f9967 ]

Don't clear the timer 1 configuration bits when clearing the interrupt flag
and counter overflow. As Michael reported, "This results in no timer
interrupts being delivered after the first. Initialization then hangs
in calibrate_delay as the jiffies counter is not updated."

On mvme16x, enable the timer after requesting the irq, consistent with
mvme147.

Cc: Michael Pavone <pavone@retrodev.com>
Fixes: 7529b90d051e ("m68k: mvme147: Handle timer counter overflow")
Fixes: 19999a8b8782 ("m68k: mvme16x: Handle timer counter overflow")
Reported-and-tested-by: Michael Pavone <pavone@retrodev.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Link: https://lore.kernel.org/r/4fdaa113db089b8fb607f7dd818479f8cdcc4547.1617089871.git.fthain@telegraphics.com.au
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/m68k/include/asm/mvme147hw.h
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c

index 257b29184af913f8613b3cbcacb91a08e14ef924..e28eb1c0e0bfb37986e520102214fd6e5e1cd5b3 100644 (file)
@@ -66,6 +66,9 @@ struct pcc_regs {
 #define PCC_INT_ENAB           0x08
 
 #define PCC_TIMER_INT_CLR      0x80
+
+#define PCC_TIMER_TIC_EN       0x01
+#define PCC_TIMER_COC_EN       0x02
 #define PCC_TIMER_CLR_OVF      0x04
 
 #define PCC_LEVEL_ABORT                0x07
index 490700aa2212eadd8fef21425778cfbcd38f6ecd..aab7880e078df523aa26bf865a1d29fcac045982 100644 (file)
@@ -116,8 +116,10 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
        unsigned long flags;
 
        local_irq_save(flags);
-       m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
-       m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF;
+       m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF | PCC_TIMER_COC_EN |
+                            PCC_TIMER_TIC_EN;
+       m147_pcc->t1_int_cntrl = PCC_INT_ENAB | PCC_TIMER_INT_CLR |
+                                PCC_LEVEL_TIMER1;
        clk_total += PCC_TIMER_CYCLES;
        timer_routine(0, NULL);
        local_irq_restore(flags);
@@ -135,10 +137,10 @@ void mvme147_sched_init (irq_handler_t timer_routine)
        /* Init the clock with a value */
        /* The clock counter increments until 0xFFFF then reloads */
        m147_pcc->t1_preload = PCC_TIMER_PRELOAD;
-       m147_pcc->t1_cntrl = 0x0;       /* clear timer */
-       m147_pcc->t1_cntrl = 0x3;       /* start timer */
-       m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;  /* clear pending ints */
-       m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+       m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF | PCC_TIMER_COC_EN |
+                            PCC_TIMER_TIC_EN;
+       m147_pcc->t1_int_cntrl = PCC_INT_ENAB | PCC_TIMER_INT_CLR |
+                                PCC_LEVEL_TIMER1;
 
        clocksource_register_hz(&mvme147_clk, PCC_TIMER_CLOCK_FREQ);
 }
index 5b86d10e0f84e2abb9539d104a6692a62676f3e9..d43d128b774719b46e92e818cab9060ada161c11 100644 (file)
@@ -367,6 +367,7 @@ static u32 clk_total;
 #define PCCTOVR1_COC_EN      0x02
 #define PCCTOVR1_OVR_CLR     0x04
 
+#define PCCTIC1_INT_LEVEL    6
 #define PCCTIC1_INT_CLR      0x08
 #define PCCTIC1_INT_EN       0x10
 
@@ -376,8 +377,8 @@ static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
        unsigned long flags;
 
        local_irq_save(flags);
-       out_8(PCCTIC1, in_8(PCCTIC1) | PCCTIC1_INT_CLR);
-       out_8(PCCTOVR1, PCCTOVR1_OVR_CLR);
+       out_8(PCCTOVR1, PCCTOVR1_OVR_CLR | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN);
+       out_8(PCCTIC1, PCCTIC1_INT_EN | PCCTIC1_INT_CLR | PCCTIC1_INT_LEVEL);
        clk_total += PCC_TIMER_CYCLES;
        timer_routine(0, NULL);
        local_irq_restore(flags);
@@ -391,14 +392,15 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
     int irq;
 
     /* Using PCCchip2 or MC2 chip tick timer 1 */
-    out_be32(PCCTCNT1, 0);
-    out_be32(PCCTCMP1, PCC_TIMER_CYCLES);
-    out_8(PCCTOVR1, in_8(PCCTOVR1) | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN);
-    out_8(PCCTIC1, PCCTIC1_INT_EN | 6);
     if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, IRQF_TIMER, "timer",
                     timer_routine))
        panic ("Couldn't register timer int");
 
+    out_be32(PCCTCNT1, 0);
+    out_be32(PCCTCMP1, PCC_TIMER_CYCLES);
+    out_8(PCCTOVR1, PCCTOVR1_OVR_CLR | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN);
+    out_8(PCCTIC1, PCCTIC1_INT_EN | PCCTIC1_INT_CLR | PCCTIC1_INT_LEVEL);
+
     clocksource_register_hz(&mvme16x_clk, PCC_TIMER_CLOCK_FREQ);
 
     if (brdno == 0x0162 || brdno == 0x172)