rtc-rtd119x.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Realtek RTD129x RTC
  4. *
  5. * Copyright (c) 2017 Andreas Färber
  6. */
  7. #include <linux/clk.h>
  8. #include <linux/io.h>
  9. #include <linux/module.h>
  10. #include <linux/of.h>
  11. #include <linux/of_address.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/rtc.h>
  14. #include <linux/spinlock.h>
  15. #define RTD_RTCSEC 0x00
  16. #define RTD_RTCMIN 0x04
  17. #define RTD_RTCHR 0x08
  18. #define RTD_RTCDATE1 0x0c
  19. #define RTD_RTCDATE2 0x10
  20. #define RTD_RTCACR 0x28
  21. #define RTD_RTCEN 0x2c
  22. #define RTD_RTCCR 0x30
  23. #define RTD_RTCSEC_RTCSEC_MASK 0x7f
  24. #define RTD_RTCMIN_RTCMIN_MASK 0x3f
  25. #define RTD_RTCHR_RTCHR_MASK 0x1f
  26. #define RTD_RTCDATE1_RTCDATE1_MASK 0xff
  27. #define RTD_RTCDATE2_RTCDATE2_MASK 0x7f
  28. #define RTD_RTCACR_RTCPWR BIT(7)
  29. #define RTD_RTCEN_RTCEN_MASK 0xff
  30. #define RTD_RTCCR_RTCRST BIT(6)
  31. struct rtd119x_rtc {
  32. void __iomem *base;
  33. struct clk *clk;
  34. struct rtc_device *rtcdev;
  35. unsigned int base_year;
  36. };
  37. static inline int rtd119x_rtc_days_in_year(int year)
  38. {
  39. return 365 + (is_leap_year(year) ? 1 : 0);
  40. }
  41. static void rtd119x_rtc_reset(struct device *dev)
  42. {
  43. struct rtd119x_rtc *data = dev_get_drvdata(dev);
  44. u32 val;
  45. val = readl_relaxed(data->base + RTD_RTCCR);
  46. val |= RTD_RTCCR_RTCRST;
  47. writel_relaxed(val, data->base + RTD_RTCCR);
  48. val &= ~RTD_RTCCR_RTCRST;
  49. writel(val, data->base + RTD_RTCCR);
  50. }
  51. static void rtd119x_rtc_set_enabled(struct device *dev, bool enable)
  52. {
  53. struct rtd119x_rtc *data = dev_get_drvdata(dev);
  54. u32 val;
  55. val = readl_relaxed(data->base + RTD_RTCEN);
  56. if (enable) {
  57. if ((val & RTD_RTCEN_RTCEN_MASK) == 0x5a)
  58. return;
  59. writel_relaxed(0x5a, data->base + RTD_RTCEN);
  60. } else {
  61. writel_relaxed(0, data->base + RTD_RTCEN);
  62. }
  63. }
  64. static int rtd119x_rtc_read_time(struct device *dev, struct rtc_time *tm)
  65. {
  66. struct rtd119x_rtc *data = dev_get_drvdata(dev);
  67. s32 day;
  68. u32 sec;
  69. unsigned int year;
  70. int tries = 0;
  71. while (true) {
  72. tm->tm_sec = (readl_relaxed(data->base + RTD_RTCSEC) & RTD_RTCSEC_RTCSEC_MASK) >> 1;
  73. tm->tm_min = readl_relaxed(data->base + RTD_RTCMIN) & RTD_RTCMIN_RTCMIN_MASK;
  74. tm->tm_hour = readl_relaxed(data->base + RTD_RTCHR) & RTD_RTCHR_RTCHR_MASK;
  75. day = readl_relaxed(data->base + RTD_RTCDATE1) & RTD_RTCDATE1_RTCDATE1_MASK;
  76. day |= (readl_relaxed(data->base + RTD_RTCDATE2) & RTD_RTCDATE2_RTCDATE2_MASK) << 8;
  77. sec = (readl_relaxed(data->base + RTD_RTCSEC) & RTD_RTCSEC_RTCSEC_MASK) >> 1;
  78. tries++;
  79. if (sec == tm->tm_sec)
  80. break;
  81. if (tries >= 3)
  82. return -EINVAL;
  83. }
  84. if (tries > 1)
  85. dev_dbg(dev, "%s: needed %i tries\n", __func__, tries);
  86. year = data->base_year;
  87. while (day >= rtd119x_rtc_days_in_year(year)) {
  88. day -= rtd119x_rtc_days_in_year(year);
  89. year++;
  90. }
  91. tm->tm_year = year - 1900;
  92. tm->tm_yday = day;
  93. tm->tm_mon = 0;
  94. while (day >= rtc_month_days(tm->tm_mon, year)) {
  95. day -= rtc_month_days(tm->tm_mon, year);
  96. tm->tm_mon++;
  97. }
  98. tm->tm_mday = day + 1;
  99. return 0;
  100. }
  101. static int rtd119x_rtc_set_time(struct device *dev, struct rtc_time *tm)
  102. {
  103. struct rtd119x_rtc *data = dev_get_drvdata(dev);
  104. unsigned int day;
  105. int i;
  106. if (1900 + tm->tm_year < data->base_year)
  107. return -EINVAL;
  108. day = 0;
  109. for (i = data->base_year; i < 1900 + tm->tm_year; i++)
  110. day += rtd119x_rtc_days_in_year(i);
  111. day += tm->tm_yday;
  112. if (day > 0x7fff)
  113. return -EINVAL;
  114. rtd119x_rtc_set_enabled(dev, false);
  115. writel_relaxed((tm->tm_sec << 1) & RTD_RTCSEC_RTCSEC_MASK, data->base + RTD_RTCSEC);
  116. writel_relaxed(tm->tm_min & RTD_RTCMIN_RTCMIN_MASK, data->base + RTD_RTCMIN);
  117. writel_relaxed(tm->tm_hour & RTD_RTCHR_RTCHR_MASK, data->base + RTD_RTCHR);
  118. writel_relaxed(day & RTD_RTCDATE1_RTCDATE1_MASK, data->base + RTD_RTCDATE1);
  119. writel_relaxed((day >> 8) & RTD_RTCDATE2_RTCDATE2_MASK, data->base + RTD_RTCDATE2);
  120. rtd119x_rtc_set_enabled(dev, true);
  121. return 0;
  122. }
  123. static const struct rtc_class_ops rtd119x_rtc_ops = {
  124. .read_time = rtd119x_rtc_read_time,
  125. .set_time = rtd119x_rtc_set_time,
  126. };
  127. static const struct of_device_id rtd119x_rtc_dt_ids[] = {
  128. { .compatible = "realtek,rtd1295-rtc" },
  129. { }
  130. };
  131. static int rtd119x_rtc_probe(struct platform_device *pdev)
  132. {
  133. struct rtd119x_rtc *data;
  134. u32 val;
  135. int ret;
  136. data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
  137. if (!data)
  138. return -ENOMEM;
  139. platform_set_drvdata(pdev, data);
  140. data->base_year = 2014;
  141. data->base = devm_platform_ioremap_resource(pdev, 0);
  142. if (IS_ERR(data->base))
  143. return PTR_ERR(data->base);
  144. data->clk = of_clk_get(pdev->dev.of_node, 0);
  145. if (IS_ERR(data->clk))
  146. return PTR_ERR(data->clk);
  147. ret = clk_prepare_enable(data->clk);
  148. if (ret) {
  149. clk_put(data->clk);
  150. return ret;
  151. }
  152. val = readl_relaxed(data->base + RTD_RTCACR);
  153. if (!(val & RTD_RTCACR_RTCPWR)) {
  154. writel_relaxed(RTD_RTCACR_RTCPWR, data->base + RTD_RTCACR);
  155. rtd119x_rtc_reset(&pdev->dev);
  156. writel_relaxed(0, data->base + RTD_RTCMIN);
  157. writel_relaxed(0, data->base + RTD_RTCHR);
  158. writel_relaxed(0, data->base + RTD_RTCDATE1);
  159. writel_relaxed(0, data->base + RTD_RTCDATE2);
  160. }
  161. rtd119x_rtc_set_enabled(&pdev->dev, true);
  162. data->rtcdev = devm_rtc_device_register(&pdev->dev, "rtc",
  163. &rtd119x_rtc_ops, THIS_MODULE);
  164. if (IS_ERR(data->rtcdev)) {
  165. dev_err(&pdev->dev, "failed to register rtc device");
  166. clk_disable_unprepare(data->clk);
  167. clk_put(data->clk);
  168. return PTR_ERR(data->rtcdev);
  169. }
  170. return 0;
  171. }
  172. static int rtd119x_rtc_remove(struct platform_device *pdev)
  173. {
  174. struct rtd119x_rtc *data = platform_get_drvdata(pdev);
  175. rtd119x_rtc_set_enabled(&pdev->dev, false);
  176. clk_disable_unprepare(data->clk);
  177. clk_put(data->clk);
  178. return 0;
  179. }
  180. static struct platform_driver rtd119x_rtc_driver = {
  181. .probe = rtd119x_rtc_probe,
  182. .remove = rtd119x_rtc_remove,
  183. .driver = {
  184. .name = "rtd1295-rtc",
  185. .of_match_table = rtd119x_rtc_dt_ids,
  186. },
  187. };
  188. builtin_platform_driver(rtd119x_rtc_driver);