arch: m68k: Introduce trivial PIT based timer
authorMarek Vasut <marek.vasut+renesas@mailbox.org>
Thu, 23 Mar 2023 00:20:40 +0000 (01:20 +0100)
committerAngelo Dureghello <angelo@kernel-space.org>
Sat, 15 Apr 2023 19:36:07 +0000 (21:36 +0200)
The QEMU emulation of m68k does not support DMA timer, the only
timer that is supported is the PIT timer. Implement trivial PIT
timer support for m68k.

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
arch/m68k/include/asm/immap.h
arch/m68k/lib/time.c
common/board_f.c

index 3b515fe..aafa4f4 100644 (file)
@@ -25,6 +25,8 @@
 #define CFG_SYS_TMRINTR_PEND           (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (6)
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 
 #define CFG_SYS_INTR_BASE              (MMAP_INTC0)
@@ -47,6 +49,8 @@
 #define CFG_SYS_TMRINTR_PEND   (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (0x1E)          /* Level must include inorder to work */
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 
 #define CFG_SYS_INTR_BASE              (MMAP_INTC0)
@@ -72,6 +76,8 @@
 #define CFG_SYS_TMRINTR_PEND   (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3)
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 2000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 #endif                         /* CONFIG_M5249 */
 
 #define CFG_SYS_TMRINTR_PEND   (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL3 | MCFSIM_ICR_PRI3)
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 2000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 #endif                         /* CONFIG_M5253 */
 
 #define CFG_SYS_TMRINTR_PEND   (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (0x1E) /* Interrupt level 3, priority 6 */
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 
 #define CFG_SYS_INTR_BASE              (MMAP_INTC0)
 #define CFG_SYS_TMRINTR_PEND   (0)
 #define CFG_SYS_TMRINTR_PRI            (INT_ICR1_TMR3PI | INT_ICR1_TMR3IPL(5))
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 #endif                         /* CONFIG_M5272 */
 
 #define CFG_SYS_TMRINTR_PEND   (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (0x1E)
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 #endif                         /* CONFIG_M5275 */
 
 #define CFG_SYS_TMRINTR_PEND   (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (0x1E)          /* Level must include inorder to work */
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 #endif                         /* CONFIG_M5282 */
 
 #define CFG_SYS_TMRINTR_PRI          (MCFSIM_ICR_AUTOVEC | \
                                        MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3)
 #define CFG_SYS_TIMER_PRESCALER      (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 #endif                          /* CONFIG_M5307 */
 
 #define CFG_SYS_TMRINTR_PEND           (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (6)
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 
 #define CFG_SYS_INTR_BASE              (MMAP_INTC0)
 #define CFG_SYS_TMRINTR_PEND   (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (6)
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 
 #define CFG_SYS_INTR_BASE              (MMAP_INTC0)
 #define CFG_SYS_TMRINTR_PEND           (CFG_SYS_TMRINTR_MASK)
 #define CFG_SYS_TMRINTR_PRI            (6)
 #define CFG_SYS_TIMER_PRESCALER        (((gd->bus_clk / 1000000) - 1) << 8)
+#else
+#define CFG_SYS_UDELAY_BASE            (MMAP_PIT0)
 #endif
 
 #define CFG_SYS_INTR_BASE              (MMAP_INTC0)
index 500e4db..61db1e6 100644 (file)
@@ -111,8 +111,6 @@ ulong get_timer(ulong base)
        return (timestamp - base);
 }
 
-#endif                         /* CONFIG_MCFTMR */
-
 /*
  * This function is derived from PowerPC code (read timebase as long long).
  * On M68K it just returns the timer value.
@@ -121,6 +119,40 @@ unsigned long long get_ticks(void)
 {
        return get_timer(0);
 }
+#else
+static u64 timer64 __section(".data");
+static u16 timer16 __section(".data");
+
+uint64_t __weak get_ticks(void)
+{
+       volatile pit_t *timerp = (pit_t *) (CFG_SYS_UDELAY_BASE);
+       u16 val = ~timerp->pcntr;
+
+       if (timer16 > val)
+               timer64 += 0xffff - timer16 + val;
+       else
+               timer64 += val - timer16;
+
+       timer16 = val;
+
+       return timer64;
+}
+
+/* PIT timer */
+int timer_init(void)
+{
+       volatile pit_t *timerp = (pit_t *) (CFG_SYS_UDELAY_BASE);
+
+       timer16 = 0;
+       timer64 = 0;
+
+       /* Set up PIT as timebase clock */
+       timerp->pmr = 0xffff;
+       timerp->pcsr = PIT_PCSR_EN | PIT_PCSR_OVW;
+
+       return 0;
+}
+#endif                         /* CONFIG_MCFTMR */
 
 unsigned long usec2ticks(unsigned long usec)
 {
index f3c1ab5..1688e27 100644 (file)
@@ -863,7 +863,7 @@ static const init_fnc_t init_sequence_f[] = {
        /* get CPU and bus clocks according to the environment variable */
        get_clocks,             /* get CPU and bus clocks (etc.) */
 #endif
-#if !defined(CONFIG_M68K)
+#if !defined(CONFIG_M68K) || (defined(CONFIG_M68K) && !defined(CONFIG_MCFTMR))
        timer_init,             /* initialize timer */
 #endif
 #if defined(CONFIG_BOARD_POSTCLK_INIT)