[PATCH] timer: npcm: Change counter source

From: Stanley Chu yschu@nuvoton.com
The counter value read from TDR register may not be correct. Read SECCNT and CNTR25M instead to get the correct timestamp.
Signed-off-by: Stanley Chu yschu@nuvoton.com --- arch/arm/dts/nuvoton-common-npcm7xx.dtsi | 12 ++-- arch/arm/dts/nuvoton-common-npcm8xx.dtsi | 13 ++-- drivers/timer/npcm-timer.c | 81 ++++++------------------ 3 files changed, 30 insertions(+), 76 deletions(-)
diff --git a/arch/arm/dts/nuvoton-common-npcm7xx.dtsi b/arch/arm/dts/nuvoton-common-npcm7xx.dtsi index feb88872fc..093d5427e3 100644 --- a/arch/arm/dts/nuvoton-common-npcm7xx.dtsi +++ b/arch/arm/dts/nuvoton-common-npcm7xx.dtsi @@ -95,6 +95,11 @@ compatible = "nuvoton,npcm750-rst", "syscon", "simple-mfd"; reg = <0x801000 0x6C>; }; + + timer0: timer@f0801068 { + compatible = "nuvoton,npcm750-timer"; + reg = <0x801068 0x8>; + }; };
ahb { @@ -245,13 +250,6 @@ status = "disabled"; };
- timer0: timer@8000 { - compatible = "nuvoton,npcm750-timer"; - interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; - reg = <0x8000 0x1C>; - clocks = <&clk NPCM7XX_CLK_TIMER>; - }; - watchdog0: watchdog@801C { compatible = "nuvoton,npcm750-wdt"; interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; diff --git a/arch/arm/dts/nuvoton-common-npcm8xx.dtsi b/arch/arm/dts/nuvoton-common-npcm8xx.dtsi index db7517cc9b..be06b2a0ca 100644 --- a/arch/arm/dts/nuvoton-common-npcm8xx.dtsi +++ b/arch/arm/dts/nuvoton-common-npcm8xx.dtsi @@ -62,6 +62,11 @@ reg = <0x0 0xf0801000 0x0 0x1000>; };
+ timer0: timer@f0801068 { + compatible = "nuvoton,npcm845-timer"; + reg = <0x0 0xf0801068 0x0 0x8>; + }; + sdhci0: sdhci@f0842000 { compatible = "nuvoton,npcm845-sdhci"; reg = <0x0 0xf0842000 0x0 0x100>; @@ -157,14 +162,6 @@ status = "disabled"; };
- timer0: timer@8000 { - compatible = "nuvoton,npcm845-timer"; - interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; - reg = <0x8000 0x1C>; - clocks = <&clk NPCM8XX_CLK_REFCLK>; - clock-names = "refclk"; - }; - serial0: serial@0 { compatible = "nuvoton,npcm845-uart", "nuvoton,npcm750-uart"; reg = <0x0 0x1000>; diff --git a/drivers/timer/npcm-timer.c b/drivers/timer/npcm-timer.c index 4562a6f231..af683b4c11 100644 --- a/drivers/timer/npcm-timer.c +++ b/drivers/timer/npcm-timer.c @@ -4,93 +4,52 @@ */
#include <common.h> -#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 counter, reg_sec, reg_25m;
- /* 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; }
@@ -99,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"}, {} };

On Mon, May 13, 2024 at 03:26:03PM +0800, Jim Liu wrote:
From: Stanley Chu yschu@nuvoton.com
The counter value read from TDR register may not be correct. Read SECCNT and CNTR25M instead to get the correct timestamp.
Signed-off-by: Stanley Chu yschu@nuvoton.com
arch/arm/dts/nuvoton-common-npcm7xx.dtsi | 12 ++-- arch/arm/dts/nuvoton-common-npcm8xx.dtsi | 13 ++-- drivers/timer/npcm-timer.c | 81 ++++++------------------ 3 files changed, 30 insertions(+), 76 deletions(-)
This no longer applies to u-boot/next, please rebase, thanks.
participants (2)
-
Jim Liu
-
Tom Rini