1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2020, Sean Anderson <seanga2@gmail.com>
4 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
12 #include <dm/device-internal.h>
13 #include <linux/err.h>
15 #define CLINT_MTIME_OFFSET 0xbff8
16 #define ACLINT_MTIME_OFFSET 0
19 #define MTIME_REG(base, offset) ((ulong)(base) + (offset))
21 static u64 notrace riscv_aclint_timer_get_count(struct udevice *dev)
23 return readq((void __iomem *)MTIME_REG(dev_get_priv(dev),
24 dev_get_driver_data(dev)));
27 #if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY)
29 * timer_early_get_rate() - Get the timer rate before driver model
31 unsigned long notrace timer_early_get_rate(void)
33 return RISCV_MMODE_TIMER_FREQ;
37 * timer_early_get_count() - Get the timer count before driver model
40 u64 notrace timer_early_get_count(void)
42 return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE,
43 RISCV_MMODE_TIMEROFF));
47 static const struct timer_ops riscv_aclint_timer_ops = {
48 .get_count = riscv_aclint_timer_get_count,
51 static int riscv_aclint_timer_probe(struct udevice *dev)
53 dev_set_priv(dev, dev_read_addr_ptr(dev));
54 if (!dev_get_priv(dev))
57 return timer_timebase_fallback(dev);
60 static const struct udevice_id riscv_aclint_timer_ids[] = {
61 { .compatible = "riscv,clint0", .data = CLINT_MTIME_OFFSET },
62 { .compatible = "sifive,clint0", .data = CLINT_MTIME_OFFSET },
63 { .compatible = "riscv,aclint-mtimer", .data = ACLINT_MTIME_OFFSET },
67 U_BOOT_DRIVER(riscv_aclint_timer) = {
68 .name = "riscv_aclint_timer",
70 .of_match = riscv_aclint_timer_ids,
71 .probe = riscv_aclint_timer_probe,
72 .ops = &riscv_aclint_timer_ops,
73 .flags = DM_FLAG_PRE_RELOC,