tegra-timer.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2022 Svyatoslav Ryhel <clamor95@gmail.com>
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <errno.h>
  8. #include <timer.h>
  9. #include <asm/io.h>
  10. #include <asm/arch/clock.h>
  11. #include <asm/arch/tegra.h>
  12. #define TEGRA_OSC_CLK_ENB_L_SET (NV_PA_CLK_RST_BASE + 0x320)
  13. #define TEGRA_OSC_SET_CLK_ENB_TMR BIT(5)
  14. #define TEGRA_TIMER_USEC_CNTR (NV_PA_TMRUS_BASE + 0)
  15. #define TEGRA_TIMER_USEC_CFG (NV_PA_TMRUS_BASE + 4)
  16. #define TEGRA_TIMER_RATE 1000000 /* 1 MHz */
  17. /*
  18. * On pre-DM stage timer should be left configured by
  19. * previous bootloader for correct 1MHz clock.
  20. * In the case of reset default value is set to 1/13 of
  21. * CLK_M which should be decent enough to safely
  22. * get to DM stage.
  23. */
  24. u64 notrace timer_early_get_count(void)
  25. {
  26. /* At this stage raw timer is used */
  27. return readl(TEGRA_TIMER_USEC_CNTR);
  28. }
  29. unsigned long notrace timer_early_get_rate(void)
  30. {
  31. return TEGRA_TIMER_RATE;
  32. }
  33. ulong timer_get_boot_us(void)
  34. {
  35. return timer_early_get_count();
  36. }
  37. /*
  38. * At moment of calling get_count, timer driver is already
  39. * probed and is configured to have precise 1MHz clock.
  40. * Tegra timer has a step of 1 microsecond which removes
  41. * need of using adjusments involving uc_priv->clock_rate.
  42. */
  43. static notrace u64 tegra_timer_get_count(struct udevice *dev)
  44. {
  45. u32 val = timer_early_get_count();
  46. return timer_conv_64(val);
  47. }
  48. static int tegra_timer_probe(struct udevice *dev)
  49. {
  50. struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  51. u32 usec_config, value;
  52. /* Timer rate has to be set unconditionally */
  53. uc_priv->clock_rate = TEGRA_TIMER_RATE;
  54. /*
  55. * Configure microsecond timers to have 1MHz clock
  56. * Config register is 0xqqww, where qq is "dividend", ww is "divisor"
  57. * Uses n+1 scheme
  58. */
  59. switch (clock_get_rate(CLOCK_ID_CLK_M)) {
  60. case 12000000:
  61. usec_config = 0x000b; /* (11+1)/(0+1) */
  62. break;
  63. case 12800000:
  64. usec_config = 0x043f; /* (63+1)/(4+1) */
  65. break;
  66. case 13000000:
  67. usec_config = 0x000c; /* (12+1)/(0+1) */
  68. break;
  69. case 16800000:
  70. usec_config = 0x0453; /* (83+1)/(4+1) */
  71. break;
  72. case 19200000:
  73. usec_config = 0x045f; /* (95+1)/(4+1) */
  74. break;
  75. case 26000000:
  76. usec_config = 0x0019; /* (25+1)/(0+1) */
  77. break;
  78. case 38400000:
  79. usec_config = 0x04bf; /* (191+1)/(4+1) */
  80. break;
  81. case 48000000:
  82. usec_config = 0x002f; /* (47+1)/(0+1) */
  83. break;
  84. default:
  85. return -EINVAL;
  86. }
  87. /* Enable clock to timer hardware */
  88. value = readl_relaxed(TEGRA_OSC_CLK_ENB_L_SET);
  89. writel_relaxed(value | TEGRA_OSC_SET_CLK_ENB_TMR,
  90. TEGRA_OSC_CLK_ENB_L_SET);
  91. writel_relaxed(usec_config, TEGRA_TIMER_USEC_CFG);
  92. return 0;
  93. }
  94. static const struct timer_ops tegra_timer_ops = {
  95. .get_count = tegra_timer_get_count,
  96. };
  97. static const struct udevice_id tegra_timer_ids[] = {
  98. { .compatible = "nvidia,tegra20-timer" },
  99. { .compatible = "nvidia,tegra30-timer" },
  100. { .compatible = "nvidia,tegra114-timer" },
  101. { .compatible = "nvidia,tegra124-timer" },
  102. { .compatible = "nvidia,tegra210-timer" },
  103. { }
  104. };
  105. U_BOOT_DRIVER(tegra_timer) = {
  106. .name = "tegra_timer",
  107. .id = UCLASS_TIMER,
  108. .of_match = tegra_timer_ids,
  109. .probe = tegra_timer_probe,
  110. .ops = &tegra_timer_ops,
  111. .flags = DM_FLAG_PRE_RELOC,
  112. };