rtc-lp8788.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * TI LP8788 MFD - rtc driver
  4. *
  5. * Copyright 2012 Texas Instruments
  6. *
  7. * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
  8. */
  9. #include <linux/err.h>
  10. #include <linux/irqdomain.h>
  11. #include <linux/mfd/lp8788.h>
  12. #include <linux/module.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/rtc.h>
  15. #include <linux/slab.h>
  16. /* register address */
  17. #define LP8788_INTEN_3 0x05
  18. #define LP8788_RTC_UNLOCK 0x64
  19. #define LP8788_RTC_SEC 0x70
  20. #define LP8788_ALM1_SEC 0x77
  21. #define LP8788_ALM1_EN 0x7D
  22. #define LP8788_ALM2_SEC 0x7E
  23. #define LP8788_ALM2_EN 0x84
  24. /* mask/shift bits */
  25. #define LP8788_INT_RTC_ALM1_M BIT(1) /* Addr 05h */
  26. #define LP8788_INT_RTC_ALM1_S 1
  27. #define LP8788_INT_RTC_ALM2_M BIT(2) /* Addr 05h */
  28. #define LP8788_INT_RTC_ALM2_S 2
  29. #define LP8788_ALM_EN_M BIT(7) /* Addr 7Dh or 84h */
  30. #define LP8788_ALM_EN_S 7
  31. #define DEFAULT_ALARM_SEL LP8788_ALARM_1
  32. #define LP8788_MONTH_OFFSET 1
  33. #define LP8788_BASE_YEAR 2000
  34. #define MAX_WDAY_BITS 7
  35. #define LP8788_WDAY_SET 1
  36. #define RTC_UNLOCK 0x1
  37. #define RTC_LATCH 0x2
  38. #define ALARM_IRQ_FLAG (RTC_IRQF | RTC_AF)
  39. enum lp8788_time {
  40. LPTIME_SEC,
  41. LPTIME_MIN,
  42. LPTIME_HOUR,
  43. LPTIME_MDAY,
  44. LPTIME_MON,
  45. LPTIME_YEAR,
  46. LPTIME_WDAY,
  47. LPTIME_MAX,
  48. };
  49. struct lp8788_rtc {
  50. struct lp8788 *lp;
  51. struct rtc_device *rdev;
  52. enum lp8788_alarm_sel alarm;
  53. int irq;
  54. };
  55. static const u8 addr_alarm_sec[LP8788_ALARM_MAX] = {
  56. LP8788_ALM1_SEC,
  57. LP8788_ALM2_SEC,
  58. };
  59. static const u8 addr_alarm_en[LP8788_ALARM_MAX] = {
  60. LP8788_ALM1_EN,
  61. LP8788_ALM2_EN,
  62. };
  63. static const u8 mask_alarm_en[LP8788_ALARM_MAX] = {
  64. LP8788_INT_RTC_ALM1_M,
  65. LP8788_INT_RTC_ALM2_M,
  66. };
  67. static const u8 shift_alarm_en[LP8788_ALARM_MAX] = {
  68. LP8788_INT_RTC_ALM1_S,
  69. LP8788_INT_RTC_ALM2_S,
  70. };
  71. static int _to_tm_wday(u8 lp8788_wday)
  72. {
  73. int i;
  74. if (lp8788_wday == 0)
  75. return 0;
  76. /* lookup defined weekday from read register value */
  77. for (i = 0; i < MAX_WDAY_BITS; i++) {
  78. if ((lp8788_wday >> i) == LP8788_WDAY_SET)
  79. break;
  80. }
  81. return i + 1;
  82. }
  83. static inline int _to_lp8788_wday(int tm_wday)
  84. {
  85. return LP8788_WDAY_SET << (tm_wday - 1);
  86. }
  87. static void lp8788_rtc_unlock(struct lp8788 *lp)
  88. {
  89. lp8788_write_byte(lp, LP8788_RTC_UNLOCK, RTC_UNLOCK);
  90. lp8788_write_byte(lp, LP8788_RTC_UNLOCK, RTC_LATCH);
  91. }
  92. static int lp8788_rtc_read_time(struct device *dev, struct rtc_time *tm)
  93. {
  94. struct lp8788_rtc *rtc = dev_get_drvdata(dev);
  95. struct lp8788 *lp = rtc->lp;
  96. u8 data[LPTIME_MAX];
  97. int ret;
  98. lp8788_rtc_unlock(lp);
  99. ret = lp8788_read_multi_bytes(lp, LP8788_RTC_SEC, data, LPTIME_MAX);
  100. if (ret)
  101. return ret;
  102. tm->tm_sec = data[LPTIME_SEC];
  103. tm->tm_min = data[LPTIME_MIN];
  104. tm->tm_hour = data[LPTIME_HOUR];
  105. tm->tm_mday = data[LPTIME_MDAY];
  106. tm->tm_mon = data[LPTIME_MON] - LP8788_MONTH_OFFSET;
  107. tm->tm_year = data[LPTIME_YEAR] + LP8788_BASE_YEAR - 1900;
  108. tm->tm_wday = _to_tm_wday(data[LPTIME_WDAY]);
  109. return 0;
  110. }
  111. static int lp8788_rtc_set_time(struct device *dev, struct rtc_time *tm)
  112. {
  113. struct lp8788_rtc *rtc = dev_get_drvdata(dev);
  114. struct lp8788 *lp = rtc->lp;
  115. u8 data[LPTIME_MAX - 1];
  116. int ret, i, year;
  117. year = tm->tm_year + 1900 - LP8788_BASE_YEAR;
  118. if (year < 0) {
  119. dev_err(lp->dev, "invalid year: %d\n", year);
  120. return -EINVAL;
  121. }
  122. /* because rtc weekday is a readonly register, do not update */
  123. data[LPTIME_SEC] = tm->tm_sec;
  124. data[LPTIME_MIN] = tm->tm_min;
  125. data[LPTIME_HOUR] = tm->tm_hour;
  126. data[LPTIME_MDAY] = tm->tm_mday;
  127. data[LPTIME_MON] = tm->tm_mon + LP8788_MONTH_OFFSET;
  128. data[LPTIME_YEAR] = year;
  129. for (i = 0; i < ARRAY_SIZE(data); i++) {
  130. ret = lp8788_write_byte(lp, LP8788_RTC_SEC + i, data[i]);
  131. if (ret)
  132. return ret;
  133. }
  134. return 0;
  135. }
  136. static int lp8788_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
  137. {
  138. struct lp8788_rtc *rtc = dev_get_drvdata(dev);
  139. struct lp8788 *lp = rtc->lp;
  140. struct rtc_time *tm = &alarm->time;
  141. u8 addr, data[LPTIME_MAX];
  142. int ret;
  143. addr = addr_alarm_sec[rtc->alarm];
  144. ret = lp8788_read_multi_bytes(lp, addr, data, LPTIME_MAX);
  145. if (ret)
  146. return ret;
  147. tm->tm_sec = data[LPTIME_SEC];
  148. tm->tm_min = data[LPTIME_MIN];
  149. tm->tm_hour = data[LPTIME_HOUR];
  150. tm->tm_mday = data[LPTIME_MDAY];
  151. tm->tm_mon = data[LPTIME_MON] - LP8788_MONTH_OFFSET;
  152. tm->tm_year = data[LPTIME_YEAR] + LP8788_BASE_YEAR - 1900;
  153. tm->tm_wday = _to_tm_wday(data[LPTIME_WDAY]);
  154. alarm->enabled = data[LPTIME_WDAY] & LP8788_ALM_EN_M;
  155. return 0;
  156. }
  157. static int lp8788_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
  158. {
  159. struct lp8788_rtc *rtc = dev_get_drvdata(dev);
  160. struct lp8788 *lp = rtc->lp;
  161. struct rtc_time *tm = &alarm->time;
  162. u8 addr, data[LPTIME_MAX];
  163. int ret, i, year;
  164. year = tm->tm_year + 1900 - LP8788_BASE_YEAR;
  165. if (year < 0) {
  166. dev_err(lp->dev, "invalid year: %d\n", year);
  167. return -EINVAL;
  168. }
  169. data[LPTIME_SEC] = tm->tm_sec;
  170. data[LPTIME_MIN] = tm->tm_min;
  171. data[LPTIME_HOUR] = tm->tm_hour;
  172. data[LPTIME_MDAY] = tm->tm_mday;
  173. data[LPTIME_MON] = tm->tm_mon + LP8788_MONTH_OFFSET;
  174. data[LPTIME_YEAR] = year;
  175. data[LPTIME_WDAY] = _to_lp8788_wday(tm->tm_wday);
  176. for (i = 0; i < ARRAY_SIZE(data); i++) {
  177. addr = addr_alarm_sec[rtc->alarm] + i;
  178. ret = lp8788_write_byte(lp, addr, data[i]);
  179. if (ret)
  180. return ret;
  181. }
  182. alarm->enabled = 1;
  183. addr = addr_alarm_en[rtc->alarm];
  184. return lp8788_update_bits(lp, addr, LP8788_ALM_EN_M,
  185. alarm->enabled << LP8788_ALM_EN_S);
  186. }
  187. static int lp8788_alarm_irq_enable(struct device *dev, unsigned int enable)
  188. {
  189. struct lp8788_rtc *rtc = dev_get_drvdata(dev);
  190. struct lp8788 *lp = rtc->lp;
  191. u8 mask, shift;
  192. if (!rtc->irq)
  193. return -EIO;
  194. mask = mask_alarm_en[rtc->alarm];
  195. shift = shift_alarm_en[rtc->alarm];
  196. return lp8788_update_bits(lp, LP8788_INTEN_3, mask, enable << shift);
  197. }
  198. static const struct rtc_class_ops lp8788_rtc_ops = {
  199. .read_time = lp8788_rtc_read_time,
  200. .set_time = lp8788_rtc_set_time,
  201. .read_alarm = lp8788_read_alarm,
  202. .set_alarm = lp8788_set_alarm,
  203. .alarm_irq_enable = lp8788_alarm_irq_enable,
  204. };
  205. static irqreturn_t lp8788_alarm_irq_handler(int irq, void *ptr)
  206. {
  207. struct lp8788_rtc *rtc = ptr;
  208. rtc_update_irq(rtc->rdev, 1, ALARM_IRQ_FLAG);
  209. return IRQ_HANDLED;
  210. }
  211. static int lp8788_alarm_irq_register(struct platform_device *pdev,
  212. struct lp8788_rtc *rtc)
  213. {
  214. struct resource *r;
  215. struct lp8788 *lp = rtc->lp;
  216. struct irq_domain *irqdm = lp->irqdm;
  217. int irq;
  218. rtc->irq = 0;
  219. /* even the alarm IRQ number is not specified, rtc time should work */
  220. r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, LP8788_ALM_IRQ);
  221. if (!r)
  222. return 0;
  223. if (rtc->alarm == LP8788_ALARM_1)
  224. irq = r->start;
  225. else
  226. irq = r->end;
  227. rtc->irq = irq_create_mapping(irqdm, irq);
  228. return devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
  229. lp8788_alarm_irq_handler,
  230. 0, LP8788_ALM_IRQ, rtc);
  231. }
  232. static int lp8788_rtc_probe(struct platform_device *pdev)
  233. {
  234. struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
  235. struct lp8788_rtc *rtc;
  236. struct device *dev = &pdev->dev;
  237. rtc = devm_kzalloc(dev, sizeof(struct lp8788_rtc), GFP_KERNEL);
  238. if (!rtc)
  239. return -ENOMEM;
  240. rtc->lp = lp;
  241. rtc->alarm = lp->pdata ? lp->pdata->alarm_sel : DEFAULT_ALARM_SEL;
  242. platform_set_drvdata(pdev, rtc);
  243. device_init_wakeup(dev, 1);
  244. rtc->rdev = devm_rtc_device_register(dev, "lp8788_rtc",
  245. &lp8788_rtc_ops, THIS_MODULE);
  246. if (IS_ERR(rtc->rdev)) {
  247. dev_err(dev, "can not register rtc device\n");
  248. return PTR_ERR(rtc->rdev);
  249. }
  250. if (lp8788_alarm_irq_register(pdev, rtc))
  251. dev_warn(lp->dev, "no rtc irq handler\n");
  252. return 0;
  253. }
  254. static struct platform_driver lp8788_rtc_driver = {
  255. .probe = lp8788_rtc_probe,
  256. .driver = {
  257. .name = LP8788_DEV_RTC,
  258. },
  259. };
  260. module_platform_driver(lp8788_rtc_driver);
  261. MODULE_DESCRIPTION("Texas Instruments LP8788 RTC Driver");
  262. MODULE_AUTHOR("Milo Kim");
  263. MODULE_LICENSE("GPL");
  264. MODULE_ALIAS("platform:lp8788-rtc");