
Add Nuvoton BMC NPCM7xx/NPCM8xx timer driver.
Signed-off-by: Stanley Chu yschu@nuvoton.com --- drivers/timer/Kconfig | 7 ++++ drivers/timer/Makefile | 1 + drivers/timer/npcm_timer.c | 82 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 drivers/timer/npcm_timer.c
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 8913142654..c17bc5b8b9 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -234,4 +234,11 @@ config IMX_GPT_TIMER Select this to enable support for the timer found on NXP i.MX devices.
+config NPCM_TIMER + bool "Nuvoton NPCM timer support" + depends on TIMER + help + Select this to enable support for the timer found on + Nuvoton NPCM devices. + endmenu diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index e2bd530eb0..d6f04f1cf4 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -26,3 +26,4 @@ obj-$(CONFIG_X86_TSC_TIMER) += tsc_timer.o obj-$(CONFIG_MTK_TIMER) += mtk_timer.o obj-$(CONFIG_MCHP_PIT64B_TIMER) += mchp-pit64b-timer.o obj-$(CONFIG_IMX_GPT_TIMER) += imx-gpt-timer.o +obj-$(CONFIG_NPCM_TIMER) += npcm_timer.o diff --git a/drivers/timer/npcm_timer.c b/drivers/timer/npcm_timer.c new file mode 100644 index 0000000000..499c1003ff --- /dev/null +++ b/drivers/timer/npcm_timer.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology. + */ + +#include <common.h> +#include <dm.h> +#include <timer.h> +#include <asm/io.h> + +#define NPCM_CLOCK_RATE 1000000 +#define NPCM_TIMER_INIT_VAL 0xFFFFFFFF + +/* Register offsets */ +#define TCR0 0x0 +#define TICR0 0x8 +#define TDR0 0x10 + +/* TCR fields */ +#define TCR_MODE_PERIODIC BIT(27) +#define TCR_EN BIT(30) +#define TCR_PRESCALE_25 (25 - 1) + +struct npcm_timer_priv { + void __iomem *base; +}; + +static u64 npcm_timer_get_count(struct udevice *dev) +{ + struct npcm_timer_priv *priv = dev_get_priv(dev); + u32 val; + + val = NPCM_TIMER_INIT_VAL - readl(priv->base + TDR0); + + return timer_conv_64(val); +} + +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); + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) + return -ENOENT; + uc_priv->clock_rate = NPCM_CLOCK_RATE; + + writel(0, priv->base + TCR0); + writel(NPCM_TIMER_INIT_VAL, priv->base + TICR0); + + /* + * Configure timer and start + * periodic mode + * input clock freq = 25Mhz + * prescale = 25 + * clock rate = 25Mhz/25 = 1Mhz + */ + writel(TCR_EN | TCR_MODE_PERIODIC | TCR_PRESCALE_25, + priv->base + TCR0); + + return 0; +} + +static const struct timer_ops npcm_timer_ops = { + .get_count = npcm_timer_get_count, +}; + +static const struct udevice_id npcm_timer_ids[] = { + { .compatible = "nuvoton,npcm845-timer" }, + { .compatible = "nuvoton,npcm750-timer" }, + {} +}; + +U_BOOT_DRIVER(npcm_timer) = { + .name = "npcm_timer", + .id = UCLASS_TIMER, + .of_match = npcm_timer_ids, + .priv_auto = sizeof(struct npcm_timer_priv), + .probe = npcm_timer_probe, + .ops = &npcm_timer_ops, + .flags = DM_FLAG_PRE_RELOC, +};