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 189961a0b6SThomas Chou void sandbox_timer_add_offset(unsigned long offset) 199961a0b6SThomas Chou { 209961a0b6SThomas Chou sandbox_timer_offset += offset; 219961a0b6SThomas Chou } 229961a0b6SThomas Chou 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 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 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 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