1
2
3
4
5
6#define LOG_CATEGORY UCLASS_TIMER
7
8#include <common.h>
9#include <clk.h>
10#include <cpu.h>
11#include <dm.h>
12#include <asm/global_data.h>
13#include <dm/lists.h>
14#include <dm/device_compat.h>
15#include <dm/device-internal.h>
16#include <dm/root.h>
17#include <errno.h>
18#include <init.h>
19#include <timer.h>
20#include <linux/err.h>
21
22DECLARE_GLOBAL_DATA_PTR;
23
24
25
26
27
28
29
30
31
32
33int notrace timer_get_count(struct udevice *dev, u64 *count)
34{
35 const struct timer_ops *ops = device_get_ops(dev);
36
37 if (!ops->get_count)
38 return -ENOSYS;
39
40 *count = ops->get_count(dev);
41 return 0;
42}
43
44unsigned long notrace timer_get_rate(struct udevice *dev)
45{
46 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
47
48 return uc_priv->clock_rate;
49}
50
51static int timer_pre_probe(struct udevice *dev)
52{
53 if (CONFIG_IS_ENABLED(OF_REAL)) {
54 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
55 struct clk timer_clk;
56 int err;
57 ulong ret;
58
59
60
61
62 if (!dev_has_ofnode(dev))
63 return 0;
64
65 err = clk_get_by_index(dev, 0, &timer_clk);
66 if (!err) {
67 ret = clk_get_rate(&timer_clk);
68 if (IS_ERR_VALUE(ret))
69 return ret;
70 uc_priv->clock_rate = ret;
71 } else {
72 uc_priv->clock_rate =
73 dev_read_u32_default(dev, "clock-frequency", 0);
74 }
75 }
76
77 return 0;
78}
79
80static int timer_post_probe(struct udevice *dev)
81{
82 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
83
84 if (!uc_priv->clock_rate)
85 return -EINVAL;
86
87 return 0;
88}
89
90#if CONFIG_IS_ENABLED(CPU)
91int timer_timebase_fallback(struct udevice *dev)
92{
93 struct udevice *cpu;
94 struct cpu_plat *cpu_plat;
95 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
96
97
98 if (uc_priv->clock_rate)
99 return 0;
100
101
102 dev_dbg(dev, "missing clocks or clock-frequency property; falling back on timebase-frequency\n");
103 cpu = cpu_get_current_dev();
104 if (!cpu)
105 return -ENODEV;
106
107 cpu_plat = dev_get_parent_plat(cpu);
108 if (!cpu_plat)
109 return -ENODEV;
110
111 uc_priv->clock_rate = cpu_plat->timebase_freq;
112 return 0;
113}
114#endif
115
116u64 timer_conv_64(u32 count)
117{
118
119 if (count < gd->timebase_l)
120 gd->timebase_h++;
121 gd->timebase_l = count;
122 return ((u64)gd->timebase_h << 32) | gd->timebase_l;
123}
124
125int notrace dm_timer_init(void)
126{
127 struct udevice *dev = NULL;
128 __maybe_unused ofnode node;
129 int ret;
130
131 if (gd->timer)
132 return 0;
133
134
135
136
137
138 if (gd->dm_root == NULL)
139 return -EAGAIN;
140
141 if (CONFIG_IS_ENABLED(OF_REAL)) {
142
143 node = ofnode_get_chosen_node("tick-timer");
144
145 if (ofnode_valid(node) &&
146 uclass_get_device_by_ofnode(UCLASS_TIMER, node, &dev)) {
147
148
149
150
151 if (!lists_bind_fdt(dm_root(), node, &dev, NULL, false)) {
152 ret = device_probe(dev);
153 if (ret)
154 return ret;
155 }
156 }
157 }
158
159 if (!dev) {
160
161 ret = uclass_first_device_err(UCLASS_TIMER, &dev);
162 if (ret)
163 return ret;
164 }
165
166 if (dev) {
167 gd->timer = dev;
168 return 0;
169 }
170
171 return -ENODEV;
172}
173
174UCLASS_DRIVER(timer) = {
175 .id = UCLASS_TIMER,
176 .name = "timer",
177 .pre_probe = timer_pre_probe,
178 .flags = DM_UC_FLAG_SEQ_ALIAS,
179 .post_probe = timer_post_probe,
180 .per_device_auto = sizeof(struct timer_dev_priv),
181};
182