rtc-rtd119x.c 5.7 KB

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