zynqmp_rtc.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2021, Xilinx, Inc.
  4. */
  5. #define LOG_CATEGORY UCLASS_RTC
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <rtc.h>
  9. #include <asm/io.h>
  10. /* RTC Registers */
  11. #define RTC_SET_TM_WR 0x00
  12. #define RTC_SET_TM_RD 0x04
  13. #define RTC_CALIB_WR 0x08
  14. #define RTC_CUR_TM 0x10
  15. #define RTC_INT_STS 0x20
  16. #define RTC_CTRL 0x40
  17. #define RTC_INT_SEC BIT(0)
  18. #define RTC_BATT_EN BIT(31)
  19. #define RTC_CALIB_DEF 0x198233
  20. #define RTC_CALIB_MASK 0x1FFFFF
  21. struct zynqmp_rtc_priv {
  22. fdt_addr_t base;
  23. unsigned int calibval;
  24. };
  25. static int zynqmp_rtc_get(struct udevice *dev, struct rtc_time *tm)
  26. {
  27. struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
  28. u32 status;
  29. unsigned long read_time;
  30. status = readl(priv->base + RTC_INT_STS);
  31. if (status & RTC_INT_SEC) {
  32. /*
  33. * RTC has updated the CURRENT_TIME with the time written into
  34. * SET_TIME_WRITE register.
  35. */
  36. read_time = readl(priv->base + RTC_CUR_TM);
  37. } else {
  38. /*
  39. * Time written in SET_TIME_WRITE has not yet updated into
  40. * the seconds read register, so read the time from the
  41. * SET_TIME_WRITE instead of CURRENT_TIME register.
  42. * Since we add +1 sec while writing, we need to -1 sec while
  43. * reading.
  44. */
  45. read_time = readl(priv->base + RTC_SET_TM_RD) - 1;
  46. }
  47. rtc_to_tm(read_time, tm);
  48. return 0;
  49. }
  50. static int zynqmp_rtc_set(struct udevice *dev, const struct rtc_time *tm)
  51. {
  52. struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
  53. unsigned long new_time = 0;
  54. if (tm)
  55. /*
  56. * The value written will be updated after 1 sec into the
  57. * seconds read register, so we need to program time +1 sec
  58. * to get the correct time on read.
  59. */
  60. new_time = rtc_mktime(tm) + 1;
  61. /*
  62. * Writing into calibration register will clear the Tick Counter and
  63. * force the next second to be signaled exactly in 1 second period
  64. */
  65. priv->calibval &= RTC_CALIB_MASK;
  66. writel(priv->calibval, (priv->base + RTC_CALIB_WR));
  67. writel(new_time, priv->base + RTC_SET_TM_WR);
  68. /*
  69. * Clear the rtc interrupt status register after setting the
  70. * time. During a read_time function, the code should read the
  71. * RTC_INT_STATUS register and if bit 0 is still 0, it means
  72. * that one second has not elapsed yet since RTC was set and
  73. * the current time should be read from SET_TIME_READ register;
  74. * otherwise, CURRENT_TIME register is read to report the time
  75. */
  76. writel(RTC_INT_SEC, priv->base + RTC_INT_STS);
  77. return 0;
  78. }
  79. static int zynqmp_rtc_reset(struct udevice *dev)
  80. {
  81. return zynqmp_rtc_set(dev, NULL);
  82. }
  83. static int zynqmp_rtc_init(struct udevice *dev)
  84. {
  85. struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
  86. u32 rtc_ctrl;
  87. /* Enable RTC switch to battery when VCC_PSAUX is not available */
  88. rtc_ctrl = readl(priv->base + RTC_CTRL);
  89. rtc_ctrl |= RTC_BATT_EN;
  90. writel(rtc_ctrl, priv->base + RTC_CTRL);
  91. /*
  92. * Based on crystal freq of 33.330 KHz
  93. * set the seconds counter and enable, set fractions counter
  94. * to default value suggested as per design spec
  95. * to correct RTC delay in frequency over period of time.
  96. */
  97. priv->calibval &= RTC_CALIB_MASK;
  98. writel(priv->calibval, (priv->base + RTC_CALIB_WR));
  99. return 0;
  100. }
  101. static int zynqmp_rtc_probe(struct udevice *dev)
  102. {
  103. struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
  104. int ret;
  105. priv->base = dev_read_addr(dev);
  106. if (priv->base == FDT_ADDR_T_NONE)
  107. return -EINVAL;
  108. priv->calibval = dev_read_u32_default(dev, "calibration",
  109. RTC_CALIB_DEF);
  110. ret = zynqmp_rtc_init(dev);
  111. return ret;
  112. }
  113. static const struct rtc_ops zynqmp_rtc_ops = {
  114. .get = zynqmp_rtc_get,
  115. .set = zynqmp_rtc_set,
  116. .reset = zynqmp_rtc_reset,
  117. };
  118. static const struct udevice_id zynqmp_rtc_ids[] = {
  119. { .compatible = "xlnx,zynqmp-rtc" },
  120. { }
  121. };
  122. U_BOOT_DRIVER(rtc_zynqmp) = {
  123. .name = "rtc-zynqmp",
  124. .id = UCLASS_RTC,
  125. .probe = zynqmp_rtc_probe,
  126. .of_match = zynqmp_rtc_ids,
  127. .ops = &zynqmp_rtc_ops,
  128. .priv_auto = sizeof(struct zynqmp_rtc_priv),
  129. };