rtc-ntxec.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * The Netronix embedded controller is a microcontroller found in some
  4. * e-book readers designed by the original design manufacturer Netronix, Inc.
  5. * It contains RTC, battery monitoring, system power management, and PWM
  6. * functionality.
  7. *
  8. * This driver implements access to the RTC time and date.
  9. *
  10. * Copyright 2020 Jonathan Neuschäfer <[email protected]>
  11. */
  12. #include <linux/mfd/ntxec.h>
  13. #include <linux/module.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/regmap.h>
  16. #include <linux/rtc.h>
  17. #include <linux/types.h>
  18. struct ntxec_rtc {
  19. struct device *dev;
  20. struct ntxec *ec;
  21. };
  22. #define NTXEC_REG_WRITE_YEAR 0x10
  23. #define NTXEC_REG_WRITE_MONTH 0x11
  24. #define NTXEC_REG_WRITE_DAY 0x12
  25. #define NTXEC_REG_WRITE_HOUR 0x13
  26. #define NTXEC_REG_WRITE_MINUTE 0x14
  27. #define NTXEC_REG_WRITE_SECOND 0x15
  28. #define NTXEC_REG_READ_YEAR_MONTH 0x20
  29. #define NTXEC_REG_READ_MDAY_HOUR 0x21
  30. #define NTXEC_REG_READ_MINUTE_SECOND 0x23
  31. static int ntxec_read_time(struct device *dev, struct rtc_time *tm)
  32. {
  33. struct ntxec_rtc *rtc = dev_get_drvdata(dev);
  34. unsigned int value;
  35. int res;
  36. retry:
  37. res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_MINUTE_SECOND, &value);
  38. if (res < 0)
  39. return res;
  40. tm->tm_min = value >> 8;
  41. tm->tm_sec = value & 0xff;
  42. res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_MDAY_HOUR, &value);
  43. if (res < 0)
  44. return res;
  45. tm->tm_mday = value >> 8;
  46. tm->tm_hour = value & 0xff;
  47. res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_YEAR_MONTH, &value);
  48. if (res < 0)
  49. return res;
  50. tm->tm_year = (value >> 8) + 100;
  51. tm->tm_mon = (value & 0xff) - 1;
  52. /*
  53. * Read the minutes/seconds field again. If it changed since the first
  54. * read, we can't assume that the values read so far are consistent,
  55. * and should start from the beginning.
  56. */
  57. res = regmap_read(rtc->ec->regmap, NTXEC_REG_READ_MINUTE_SECOND, &value);
  58. if (res < 0)
  59. return res;
  60. if (tm->tm_min != value >> 8 || tm->tm_sec != (value & 0xff))
  61. goto retry;
  62. return 0;
  63. }
  64. static int ntxec_set_time(struct device *dev, struct rtc_time *tm)
  65. {
  66. struct ntxec_rtc *rtc = dev_get_drvdata(dev);
  67. /*
  68. * To avoid time overflows while we're writing the full date/time,
  69. * set the seconds field to zero before doing anything else. For the
  70. * next 59 seconds (plus however long it takes until the RTC's next
  71. * update of the second field), the seconds field will not overflow
  72. * into the other fields.
  73. */
  74. struct reg_sequence regs[] = {
  75. { NTXEC_REG_WRITE_SECOND, ntxec_reg8(0) },
  76. { NTXEC_REG_WRITE_YEAR, ntxec_reg8(tm->tm_year - 100) },
  77. { NTXEC_REG_WRITE_MONTH, ntxec_reg8(tm->tm_mon + 1) },
  78. { NTXEC_REG_WRITE_DAY, ntxec_reg8(tm->tm_mday) },
  79. { NTXEC_REG_WRITE_HOUR, ntxec_reg8(tm->tm_hour) },
  80. { NTXEC_REG_WRITE_MINUTE, ntxec_reg8(tm->tm_min) },
  81. { NTXEC_REG_WRITE_SECOND, ntxec_reg8(tm->tm_sec) },
  82. };
  83. return regmap_multi_reg_write(rtc->ec->regmap, regs, ARRAY_SIZE(regs));
  84. }
  85. static const struct rtc_class_ops ntxec_rtc_ops = {
  86. .read_time = ntxec_read_time,
  87. .set_time = ntxec_set_time,
  88. };
  89. static int ntxec_rtc_probe(struct platform_device *pdev)
  90. {
  91. struct rtc_device *dev;
  92. struct ntxec_rtc *rtc;
  93. pdev->dev.of_node = pdev->dev.parent->of_node;
  94. rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
  95. if (!rtc)
  96. return -ENOMEM;
  97. rtc->dev = &pdev->dev;
  98. rtc->ec = dev_get_drvdata(pdev->dev.parent);
  99. platform_set_drvdata(pdev, rtc);
  100. dev = devm_rtc_allocate_device(&pdev->dev);
  101. if (IS_ERR(dev))
  102. return PTR_ERR(dev);
  103. dev->ops = &ntxec_rtc_ops;
  104. dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
  105. dev->range_max = 9025257599LL; /* 2255-12-31 23:59:59 */
  106. return devm_rtc_register_device(dev);
  107. }
  108. static struct platform_driver ntxec_rtc_driver = {
  109. .driver = {
  110. .name = "ntxec-rtc",
  111. },
  112. .probe = ntxec_rtc_probe,
  113. };
  114. module_platform_driver(ntxec_rtc_driver);
  115. MODULE_AUTHOR("Jonathan Neuschäfer <[email protected]>");
  116. MODULE_DESCRIPTION("RTC driver for Netronix EC");
  117. MODULE_LICENSE("GPL");
  118. MODULE_ALIAS("platform:ntxec-rtc");