diff options
Diffstat (limited to 'drivers/timer')
-rw-r--r-- | drivers/timer/Kconfig | 6 | ||||
-rw-r--r-- | drivers/timer/Makefile | 1 | ||||
-rw-r--r-- | drivers/timer/ast_ibex_timer.c | 45 | ||||
-rw-r--r-- | drivers/timer/npcm-timer.c | 82 |
4 files changed, 73 insertions, 61 deletions
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 6b1de82ae38..cb6fc0e7fda 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -106,6 +106,12 @@ config AST_TIMER This is mostly because they all share several registers which makes it difficult to completely separate them. +config AST_IBEX_TIMER + bool "Aspeed ast2700 Ibex timer" + depends on TIMER + help + Select this to enable a timer support for the Ibex RV32-based MCUs in AST2700. + config ATCPIT100_TIMER bool "ATCPIT100 timer support" depends on TIMER diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index fb95c8899e3..fec4af392e6 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_)ANDES_PLMT_TIMER) += andes_plmt_timer.o obj-$(CONFIG_ARC_TIMER) += arc_timer.o obj-$(CONFIG_ARM_TWD_TIMER) += arm_twd_timer.o obj-$(CONFIG_AST_TIMER) += ast_timer.o +obj-$(CONFIG_AST_IBEX_TIMER) += ast_ibex_timer.o obj-$(CONFIG_ATCPIT100_TIMER) += atcpit100_timer.o obj-$(CONFIG_$(SPL_)ATMEL_PIT_TIMER) += atmel_pit_timer.o obj-$(CONFIG_$(SPL_)ATMEL_TCB_TIMER) += atmel_tcb_timer.o diff --git a/drivers/timer/ast_ibex_timer.c b/drivers/timer/ast_ibex_timer.c new file mode 100644 index 00000000000..261839661e9 --- /dev/null +++ b/drivers/timer/ast_ibex_timer.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024 Aspeed Technology Inc. + */ + +#include <asm/csr.h> +#include <asm/io.h> +#include <dm.h> +#include <errno.h> +#include <timer.h> + +#define CSR_MCYCLE 0xb00 +#define CSR_MCYCLEH 0xb80 + +static u64 ast_ibex_timer_get_count(struct udevice *dev) +{ + uint32_t cnt_l, cnt_h; + + cnt_l = csr_read(CSR_MCYCLE); + cnt_h = csr_read(CSR_MCYCLEH); + + return ((uint64_t)cnt_h << 32) | cnt_l; +} + +static int ast_ibex_timer_probe(struct udevice *dev) +{ + return 0; +} + +static const struct timer_ops ast_ibex_timer_ops = { + .get_count = ast_ibex_timer_get_count, +}; + +static const struct udevice_id ast_ibex_timer_ids[] = { + { .compatible = "aspeed,ast2700-ibex-timer" }, + { } +}; + +U_BOOT_DRIVER(ast_ibex_timer) = { + .name = "ast_ibex_timer", + .id = UCLASS_TIMER, + .of_match = ast_ibex_timer_ids, + .probe = ast_ibex_timer_probe, + .ops = &ast_ibex_timer_ops, +}; diff --git a/drivers/timer/npcm-timer.c b/drivers/timer/npcm-timer.c index 9463fd29ce8..5627c2331ca 100644 --- a/drivers/timer/npcm-timer.c +++ b/drivers/timer/npcm-timer.c @@ -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"}, {} }; |