19961a0b6SThomas Chou /*
29961a0b6SThomas Chou * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
39961a0b6SThomas Chou *
49961a0b6SThomas Chou * SPDX-License-Identifier: GPL-2.0+
59961a0b6SThomas Chou */
69961a0b6SThomas Chou
79961a0b6SThomas Chou #include <common.h>
89961a0b6SThomas Chou #include <dm.h>
99961a0b6SThomas Chou #include <errno.h>
109961a0b6SThomas Chou #include <timer.h>
119961a0b6SThomas Chou #include <os.h>
129961a0b6SThomas Chou
13*01476eafSSimon Glass #define SANDBOX_TIMER_RATE 1000000
14*01476eafSSimon Glass
159961a0b6SThomas Chou /* system timer offset in ms */
169961a0b6SThomas Chou static unsigned long sandbox_timer_offset;
179961a0b6SThomas Chou
sandbox_timer_add_offset(unsigned long offset)189961a0b6SThomas Chou void sandbox_timer_add_offset(unsigned long offset)
199961a0b6SThomas Chou {
209961a0b6SThomas Chou sandbox_timer_offset += offset;
219961a0b6SThomas Chou }
229961a0b6SThomas Chou
timer_early_get_count(void)23*01476eafSSimon Glass u64 notrace timer_early_get_count(void)
249961a0b6SThomas Chou {
25*01476eafSSimon Glass return os_get_nsec() / 1000 + sandbox_timer_offset * 1000;
26*01476eafSSimon Glass }
27*01476eafSSimon Glass
timer_early_get_rate(void)28*01476eafSSimon Glass unsigned long notrace timer_early_get_rate(void)
29*01476eafSSimon Glass {
30*01476eafSSimon Glass return SANDBOX_TIMER_RATE;
31*01476eafSSimon Glass }
32*01476eafSSimon Glass
sandbox_timer_get_count(struct udevice * dev,u64 * count)33*01476eafSSimon Glass static notrace int sandbox_timer_get_count(struct udevice *dev, u64 *count)
34*01476eafSSimon Glass {
35*01476eafSSimon Glass *count = timer_early_get_count();
369961a0b6SThomas Chou
379961a0b6SThomas Chou return 0;
389961a0b6SThomas Chou }
399961a0b6SThomas Chou
sandbox_timer_probe(struct udevice * dev)409961a0b6SThomas Chou static int sandbox_timer_probe(struct udevice *dev)
419961a0b6SThomas Chou {
42bb883f82SStephen Warren struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
43bb883f82SStephen Warren
44bb883f82SStephen Warren if (!uc_priv->clock_rate)
45*01476eafSSimon Glass uc_priv->clock_rate = SANDBOX_TIMER_RATE;
46bb883f82SStephen Warren
479961a0b6SThomas Chou return 0;
489961a0b6SThomas Chou }
499961a0b6SThomas Chou
509961a0b6SThomas Chou static const struct timer_ops sandbox_timer_ops = {
519961a0b6SThomas Chou .get_count = sandbox_timer_get_count,
529961a0b6SThomas Chou };
539961a0b6SThomas Chou
549961a0b6SThomas Chou static const struct udevice_id sandbox_timer_ids[] = {
559961a0b6SThomas Chou { .compatible = "sandbox,timer" },
569961a0b6SThomas Chou { }
579961a0b6SThomas Chou };
589961a0b6SThomas Chou
599961a0b6SThomas Chou U_BOOT_DRIVER(sandbox_timer) = {
609961a0b6SThomas Chou .name = "sandbox_timer",
619961a0b6SThomas Chou .id = UCLASS_TIMER,
629961a0b6SThomas Chou .of_match = sandbox_timer_ids,
639961a0b6SThomas Chou .probe = sandbox_timer_probe,
649961a0b6SThomas Chou .ops = &sandbox_timer_ops,
659961a0b6SThomas Chou .flags = DM_FLAG_PRE_RELOC,
669961a0b6SThomas Chou };
67bb883f82SStephen Warren
68bb883f82SStephen Warren /* This is here in case we don't have a device tree */
69bb883f82SStephen Warren U_BOOT_DEVICE(sandbox_timer_non_fdt) = {
70bb883f82SStephen Warren .name = "sandbox_timer",
71bb883f82SStephen Warren };
72