sbi_timer.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2019 Western Digital Corporation or its affiliates.
  5. *
  6. * Authors:
  7. * Anup Patel <anup.patel@wdc.com>
  8. */
  9. #include <sbi/riscv_asm.h>
  10. #include <sbi/riscv_encoding.h>
  11. #include <sbi/sbi_error.h>
  12. #include <sbi/sbi_hart.h>
  13. #include <sbi/sbi_platform.h>
  14. #include <sbi/sbi_scratch.h>
  15. #include <sbi/sbi_timer.h>
  16. static unsigned long time_delta_off;
  17. static u64 (*get_time_val)(void);
  18. static const struct sbi_timer_device *timer_dev = NULL;
  19. #if __riscv_xlen == 32
  20. static u64 get_ticks(void)
  21. {
  22. u32 lo, hi, tmp;
  23. __asm__ __volatile__("1:\n"
  24. "rdtimeh %0\n"
  25. "rdtime %1\n"
  26. "rdtimeh %2\n"
  27. "bne %0, %2, 1b"
  28. : "=&r"(hi), "=&r"(lo), "=&r"(tmp));
  29. return ((u64)hi << 32) | lo;
  30. }
  31. #else
  32. static u64 get_ticks(void)
  33. {
  34. unsigned long n;
  35. __asm__ __volatile__("rdtime %0" : "=r"(n));
  36. return n;
  37. }
  38. #endif
  39. static u64 get_platform_ticks(void)
  40. {
  41. return timer_dev->timer_value();
  42. }
  43. u64 sbi_timer_value(void)
  44. {
  45. if (get_time_val)
  46. return get_time_val();
  47. return 0;
  48. }
  49. u64 sbi_timer_virt_value(void)
  50. {
  51. u64 *time_delta = sbi_scratch_offset_ptr(sbi_scratch_thishart_ptr(),
  52. time_delta_off);
  53. return sbi_timer_value() + *time_delta;
  54. }
  55. u64 sbi_timer_get_delta(void)
  56. {
  57. u64 *time_delta = sbi_scratch_offset_ptr(sbi_scratch_thishart_ptr(),
  58. time_delta_off);
  59. return *time_delta;
  60. }
  61. void sbi_timer_set_delta(ulong delta)
  62. {
  63. u64 *time_delta = sbi_scratch_offset_ptr(sbi_scratch_thishart_ptr(),
  64. time_delta_off);
  65. *time_delta = (u64)delta;
  66. }
  67. void sbi_timer_set_delta_upper(ulong delta_upper)
  68. {
  69. u64 *time_delta = sbi_scratch_offset_ptr(sbi_scratch_thishart_ptr(),
  70. time_delta_off);
  71. *time_delta &= 0xffffffffULL;
  72. *time_delta |= ((u64)delta_upper << 32);
  73. }
  74. void sbi_timer_event_start(u64 next_event)
  75. {
  76. if (timer_dev && timer_dev->timer_event_start)
  77. timer_dev->timer_event_start(next_event);
  78. csr_clear(CSR_MIP, MIP_STIP);
  79. csr_set(CSR_MIE, MIP_MTIP);
  80. }
  81. void sbi_timer_process(void)
  82. {
  83. csr_clear(CSR_MIE, MIP_MTIP);
  84. csr_set(CSR_MIP, MIP_STIP);
  85. }
  86. const struct sbi_timer_device *sbi_timer_get_device(void)
  87. {
  88. return timer_dev;
  89. }
  90. void sbi_timer_set_device(const struct sbi_timer_device *dev)
  91. {
  92. if (!dev || timer_dev)
  93. return;
  94. timer_dev = dev;
  95. if (!get_time_val && timer_dev->timer_value)
  96. get_time_val = get_platform_ticks;
  97. }
  98. int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot)
  99. {
  100. u64 *time_delta;
  101. const struct sbi_platform *plat = sbi_platform_ptr(scratch);
  102. if (cold_boot) {
  103. time_delta_off = sbi_scratch_alloc_offset(sizeof(*time_delta),
  104. "TIME_DELTA");
  105. if (!time_delta_off)
  106. return SBI_ENOMEM;
  107. if (sbi_hart_has_feature(scratch, SBI_HART_HAS_TIME))
  108. get_time_val = get_ticks;
  109. } else {
  110. if (!time_delta_off)
  111. return SBI_ENOMEM;
  112. }
  113. time_delta = sbi_scratch_offset_ptr(scratch, time_delta_off);
  114. *time_delta = 0;
  115. return sbi_platform_timer_init(plat, cold_boot);
  116. }
  117. void sbi_timer_exit(struct sbi_scratch *scratch)
  118. {
  119. if (timer_dev && timer_dev->timer_event_stop)
  120. timer_dev->timer_event_stop();
  121. csr_clear(CSR_MIP, MIP_STIP);
  122. csr_clear(CSR_MIE, MIP_MTIP);
  123. sbi_platform_timer_exit(sbi_platform_ptr(scratch));
  124. }