From b70865e6b94fe81ddc4eb48f45b574eae80ee035 Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Mon, 29 Jul 2024 17:04:06 +0800 Subject: [PATCH] timer: npcm: Change counter source 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 --- drivers/timer/npcm-timer.c | 82 ++++++++++---------------------------- 1 file changed, 21 insertions(+), 61 deletions(-) diff --git a/drivers/timer/npcm-timer.c b/drivers/timer/npcm-timer.c index 9463fd29ce..5627c2331c 100644 --- a/drivers/timer/npcm-timer.c +++ b/drivers/timer/npcm-timer.c @@ -3,93 +3,53 @@ * Copyright (c) 2022 Nuvoton Technology Corp. */ -#include #include #include #include -#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"}, {} }; -- 2.39.5