]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
timer: npcm: Change counter source
authorJim Liu <jim.t90615@gmail.com>
Mon, 29 Jul 2024 09:04:06 +0000 (17:04 +0800)
committerTom Rini <trini@konsulko.com>
Tue, 27 Aug 2024 21:37:18 +0000 (15:37 -0600)
The counter value read from TDR register may not be correct.
Read SECCNT and CNTR25M instead to get the correct timestamp.

Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
drivers/timer/npcm-timer.c

index 9463fd29ce81a597df8c1c395534b28e46993091..5627c2331cabbe682fe83b66bd6ca46f7d3d1f59 100644 (file)
@@ -3,93 +3,53 @@
  * Copyright (c) 2022 Nuvoton Technology Corp.
  */
 
-#include <clk.h>
 #include <dm.h>
 #include <timer.h>
 #include <asm/io.h>
 
-#define NPCM_TIMER_CLOCK_RATE  1000000UL               /* 1MHz timer */
-#define NPCM_TIMER_INPUT_RATE  25000000UL              /* Rate of input clock */
-#define NPCM_TIMER_TDR_MASK    GENMASK(23, 0)
-#define NPCM_TIMER_MAX_VAL     NPCM_TIMER_TDR_MASK     /* max counter value */
+#define NPCM_TIMER_CLOCK_RATE  25000000UL      /* 25MHz */
 
 /* Register offsets */
-#define TCR0   0x0     /* Timer Control and Status Register */
-#define TICR0  0x8     /* Timer Initial Count Register */
-#define TDR0   0x10    /* Timer Data Register */
+#define SECCNT 0x0     /* Seconds Counter Register */
+#define CNTR25M        0x4     /* 25MHz Counter Register */
 
-/* TCR fields */
-#define TCR_MODE_PERIODIC      BIT(27)
-#define TCR_EN                 BIT(30)
-#define TCR_PRESCALE           (NPCM_TIMER_INPUT_RATE / NPCM_TIMER_CLOCK_RATE - 1)
-
-enum input_clock_type {
-       INPUT_CLOCK_FIXED,      /* input clock rate is fixed */
-       INPUT_CLOCK_NON_FIXED
-};
-
-/**
- * struct npcm_timer_priv - private data for npcm timer driver
- * npcm timer is a 24-bits down-counting timer.
- *
- * @last_count: last hw counter value
- * @counter: the value to be returned for get_count ops
- */
 struct npcm_timer_priv {
        void __iomem *base;
-       u32 last_count;
-       u64 counter;
 };
 
 static u64 npcm_timer_get_count(struct udevice *dev)
 {
        struct npcm_timer_priv *priv = dev_get_priv(dev);
-       u32 val;
+       u64 reg_sec, reg_25m;
+       u64 counter;
 
-       /* The timer is counting down */
-       val = readl(priv->base + TDR0) & NPCM_TIMER_TDR_MASK;
-       if (val <= priv->last_count)
-               priv->counter += priv->last_count - val;
-       else
-               priv->counter += priv->last_count + (NPCM_TIMER_MAX_VAL + 1 - val);
-       priv->last_count = val;
+       reg_sec = readl(priv->base + SECCNT);
+       reg_25m = readl(priv->base + CNTR25M);
+       /*
+        * When CNTR25M reaches 25M, it goes to 0 and SECCNT is increased by 1.
+        * When CNTR25M is zero, wait for CNTR25M to become non-zero in case
+        * SECCNT is not updated yet.
+        */
+       if (reg_25m == 0) {
+               while (reg_25m == 0)
+                       reg_25m = readl(priv->base + CNTR25M);
+               reg_sec = readl(priv->base + SECCNT);
+       }
+       counter = reg_sec * NPCM_TIMER_CLOCK_RATE + reg_25m;
 
-       return priv->counter;
+       return counter;
 }
 
 static int npcm_timer_probe(struct udevice *dev)
 {
        struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
        struct npcm_timer_priv *priv = dev_get_priv(dev);
-       enum input_clock_type type = dev_get_driver_data(dev);
-       struct clk clk;
-       int ret;
 
        priv->base = dev_read_addr_ptr(dev);
        if (!priv->base)
                return -EINVAL;
        uc_priv->clock_rate = NPCM_TIMER_CLOCK_RATE;
 
-       if (type == INPUT_CLOCK_NON_FIXED) {
-               ret = clk_get_by_index(dev, 0, &clk);
-               if (ret < 0)
-                       return ret;
-
-               ret = clk_set_rate(&clk, NPCM_TIMER_INPUT_RATE);
-               if (ret < 0)
-                       return ret;
-       }
-
-       /*
-        * Configure timer and start
-        * periodic mode
-        * timer clock rate = input clock / prescale
-        */
-       writel(0, priv->base + TCR0);
-       writel(NPCM_TIMER_MAX_VAL, priv->base + TICR0);
-       writel(TCR_EN | TCR_MODE_PERIODIC | TCR_PRESCALE,
-              priv->base + TCR0);
-
        return 0;
 }
 
@@ -98,8 +58,8 @@ static const struct timer_ops npcm_timer_ops = {
 };
 
 static const struct udevice_id npcm_timer_ids[] = {
-       { .compatible = "nuvoton,npcm845-timer", .data = INPUT_CLOCK_FIXED},
-       { .compatible = "nuvoton,npcm750-timer", .data = INPUT_CLOCK_NON_FIXED},
+       { .compatible = "nuvoton,npcm845-timer"},
+       { .compatible = "nuvoton,npcm750-timer"},
        {}
 };