blob: 73fb87912851ff60a5a4a4b20e19262982f4fc62 [file] [log] [blame]
Sean Anderson47d7e3b2020-10-25 21:46:58 -04001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020, Sean Anderson <seanga2@gmail.com>
4 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5 */
6
7#include <common.h>
8#include <clk.h>
Chanho Park6d784732023-09-06 14:18:14 +09009#include <div64.h>
Sean Anderson47d7e3b2020-10-25 21:46:58 -040010#include <dm.h>
11#include <timer.h>
12#include <asm/io.h>
Simon Glass0fd3d912020-12-22 19:30:28 -070013#include <dm/device-internal.h>
Sean Anderson47d7e3b2020-10-25 21:46:58 -040014#include <linux/err.h>
15
Bin Meng5764acb2023-06-21 23:11:44 +080016#define CLINT_MTIME_OFFSET 0xbff8
17#define ACLINT_MTIME_OFFSET 0
18
Sean Anderson47d7e3b2020-10-25 21:46:58 -040019/* mtime register */
Bin Meng5764acb2023-06-21 23:11:44 +080020#define MTIME_REG(base, offset) ((ulong)(base) + (offset))
Sean Anderson47d7e3b2020-10-25 21:46:58 -040021
Bin Meng9675d922023-06-21 23:11:46 +080022static u64 notrace riscv_aclint_timer_get_count(struct udevice *dev)
Sean Anderson47d7e3b2020-10-25 21:46:58 -040023{
Bin Meng5764acb2023-06-21 23:11:44 +080024 return readq((void __iomem *)MTIME_REG(dev_get_priv(dev),
25 dev_get_driver_data(dev)));
Sean Anderson47d7e3b2020-10-25 21:46:58 -040026}
27
Pragnesh Patelbc8d12b2021-01-17 18:11:25 +053028#if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY)
29/**
30 * timer_early_get_rate() - Get the timer rate before driver model
31 */
32unsigned long notrace timer_early_get_rate(void)
33{
34 return RISCV_MMODE_TIMER_FREQ;
35}
36
37/**
38 * timer_early_get_count() - Get the timer count before driver model
39 *
40 */
41u64 notrace timer_early_get_count(void)
42{
Bin Meng5764acb2023-06-21 23:11:44 +080043 return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE,
44 RISCV_MMODE_TIMEROFF));
Pragnesh Patelbc8d12b2021-01-17 18:11:25 +053045}
46#endif
47
Chanho Park6d784732023-09-06 14:18:14 +090048#if CONFIG_IS_ENABLED(RISCV_MMODE) && CONFIG_IS_ENABLED(BOOTSTAGE)
49ulong timer_get_boot_us(void)
50{
51 int ret;
52 u64 ticks = 0;
53 u32 rate;
54
55 ret = dm_timer_init();
56 if (!ret) {
57 rate = timer_get_rate(gd->timer);
58 timer_get_count(gd->timer, &ticks);
59 } else {
60 rate = RISCV_MMODE_TIMER_FREQ;
61 ticks = readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE,
62 RISCV_MMODE_TIMEROFF));
63 }
64
65 /* Below is converted from time(us) = (tick / rate) * 10000000 */
66 return lldiv(ticks * 1000, (rate / 1000));
67}
68#endif
69
Bin Meng9675d922023-06-21 23:11:46 +080070static const struct timer_ops riscv_aclint_timer_ops = {
71 .get_count = riscv_aclint_timer_get_count,
Sean Anderson47d7e3b2020-10-25 21:46:58 -040072};
73
Bin Meng9675d922023-06-21 23:11:46 +080074static int riscv_aclint_timer_probe(struct udevice *dev)
Sean Anderson47d7e3b2020-10-25 21:46:58 -040075{
Simon Glass0fd3d912020-12-22 19:30:28 -070076 dev_set_priv(dev, dev_read_addr_ptr(dev));
77 if (!dev_get_priv(dev))
Sean Anderson47d7e3b2020-10-25 21:46:58 -040078 return -EINVAL;
79
80 return timer_timebase_fallback(dev);
81}
82
Bin Meng9675d922023-06-21 23:11:46 +080083static const struct udevice_id riscv_aclint_timer_ids[] = {
Bin Meng5764acb2023-06-21 23:11:44 +080084 { .compatible = "riscv,clint0", .data = CLINT_MTIME_OFFSET },
85 { .compatible = "sifive,clint0", .data = CLINT_MTIME_OFFSET },
86 { .compatible = "riscv,aclint-mtimer", .data = ACLINT_MTIME_OFFSET },
Sean Anderson47d7e3b2020-10-25 21:46:58 -040087 { }
88};
89
Bin Meng9675d922023-06-21 23:11:46 +080090U_BOOT_DRIVER(riscv_aclint_timer) = {
91 .name = "riscv_aclint_timer",
Sean Anderson47d7e3b2020-10-25 21:46:58 -040092 .id = UCLASS_TIMER,
Bin Meng9675d922023-06-21 23:11:46 +080093 .of_match = riscv_aclint_timer_ids,
94 .probe = riscv_aclint_timer_probe,
95 .ops = &riscv_aclint_timer_ops,
Sean Anderson47d7e3b2020-10-25 21:46:58 -040096 .flags = DM_FLAG_PRE_RELOC,
97};