rtc-lp8788.c 7.7 KB

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