blob: 5627c2331cabbe682fe83b66bd6ca46f7d3d1f59 [file] [log] [blame]
Jim Liu5cb640a2022-04-19 13:32:22 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2022 Nuvoton Technology Corp.
4 */
5
Jim Liu5cb640a2022-04-19 13:32:22 +08006#include <dm.h>
7#include <timer.h>
8#include <asm/io.h>
9
Jim Liu4e88c962024-07-29 17:04:06 +080010#define NPCM_TIMER_CLOCK_RATE 25000000UL /* 25MHz */
Jim Liu5cb640a2022-04-19 13:32:22 +080011
12/* Register offsets */
Jim Liu4e88c962024-07-29 17:04:06 +080013#define SECCNT 0x0 /* Seconds Counter Register */
14#define CNTR25M 0x4 /* 25MHz Counter Register */
Jim Liu5cb640a2022-04-19 13:32:22 +080015
Jim Liu5cb640a2022-04-19 13:32:22 +080016struct npcm_timer_priv {
17 void __iomem *base;
Jim Liu5cb640a2022-04-19 13:32:22 +080018};
19
20static u64 npcm_timer_get_count(struct udevice *dev)
21{
22 struct npcm_timer_priv *priv = dev_get_priv(dev);
Jim Liu4e88c962024-07-29 17:04:06 +080023 u64 reg_sec, reg_25m;
24 u64 counter;
Jim Liu5cb640a2022-04-19 13:32:22 +080025
Jim Liu4e88c962024-07-29 17:04:06 +080026 reg_sec = readl(priv->base + SECCNT);
27 reg_25m = readl(priv->base + CNTR25M);
28 /*
29 * When CNTR25M reaches 25M, it goes to 0 and SECCNT is increased by 1.
30 * When CNTR25M is zero, wait for CNTR25M to become non-zero in case
31 * SECCNT is not updated yet.
32 */
33 if (reg_25m == 0) {
34 while (reg_25m == 0)
35 reg_25m = readl(priv->base + CNTR25M);
36 reg_sec = readl(priv->base + SECCNT);
37 }
38 counter = reg_sec * NPCM_TIMER_CLOCK_RATE + reg_25m;
Jim Liu5cb640a2022-04-19 13:32:22 +080039
Jim Liu4e88c962024-07-29 17:04:06 +080040 return counter;
Jim Liu5cb640a2022-04-19 13:32:22 +080041}
42
43static int npcm_timer_probe(struct udevice *dev)
44{
45 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
46 struct npcm_timer_priv *priv = dev_get_priv(dev);
Jim Liu5cb640a2022-04-19 13:32:22 +080047
48 priv->base = dev_read_addr_ptr(dev);
49 if (!priv->base)
50 return -EINVAL;
51 uc_priv->clock_rate = NPCM_TIMER_CLOCK_RATE;
52
Jim Liu5cb640a2022-04-19 13:32:22 +080053 return 0;
54}
55
56static const struct timer_ops npcm_timer_ops = {
57 .get_count = npcm_timer_get_count,
58};
59
60static const struct udevice_id npcm_timer_ids[] = {
Jim Liu4e88c962024-07-29 17:04:06 +080061 { .compatible = "nuvoton,npcm845-timer"},
62 { .compatible = "nuvoton,npcm750-timer"},
Jim Liu5cb640a2022-04-19 13:32:22 +080063 {}
64};
65
66U_BOOT_DRIVER(npcm_timer) = {
67 .name = "npcm_timer",
68 .id = UCLASS_TIMER,
69 .of_match = npcm_timer_ids,
70 .priv_auto = sizeof(struct npcm_timer_priv),
71 .probe = npcm_timer_probe,
72 .ops = &npcm_timer_ops,
73 .flags = DM_FLAG_PRE_RELOC,
74};