rtc-cros-ec.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. * RTC driver for Chrome OS Embedded Controller
  3. *
  4. * Copyright (c) 2017, Google, Inc
  5. *
  6. * Author: Stephen Barber <smbarber@chromium.org>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms and conditions of the GNU General Public License,
  10. * version 2, as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope it will be useful, but WITHOUT
  13. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  15. * more details.
  16. */
  17. #include <linux/kernel.h>
  18. #include <linux/mfd/cros_ec.h>
  19. #include <linux/mfd/cros_ec_commands.h>
  20. #include <linux/module.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/rtc.h>
  23. #include <linux/slab.h>
  24. #define DRV_NAME "cros-ec-rtc"
  25. /**
  26. * struct cros_ec_rtc - Driver data for EC RTC
  27. *
  28. * @cros_ec: Pointer to EC device
  29. * @rtc: Pointer to RTC device
  30. * @notifier: Notifier info for responding to EC events
  31. * @saved_alarm: Alarm to restore when interrupts are reenabled
  32. */
  33. struct cros_ec_rtc {
  34. struct cros_ec_device *cros_ec;
  35. struct rtc_device *rtc;
  36. struct notifier_block notifier;
  37. u32 saved_alarm;
  38. };
  39. static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command,
  40. u32 *response)
  41. {
  42. int ret;
  43. struct {
  44. struct cros_ec_command msg;
  45. struct ec_response_rtc data;
  46. } __packed msg;
  47. memset(&msg, 0, sizeof(msg));
  48. msg.msg.command = command;
  49. msg.msg.insize = sizeof(msg.data);
  50. ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
  51. if (ret < 0) {
  52. dev_err(cros_ec->dev,
  53. "error getting %s from EC: %d\n",
  54. command == EC_CMD_RTC_GET_VALUE ? "time" : "alarm",
  55. ret);
  56. return ret;
  57. }
  58. *response = msg.data.time;
  59. return 0;
  60. }
  61. static int cros_ec_rtc_set(struct cros_ec_device *cros_ec, u32 command,
  62. u32 param)
  63. {
  64. int ret = 0;
  65. struct {
  66. struct cros_ec_command msg;
  67. struct ec_response_rtc data;
  68. } __packed msg;
  69. memset(&msg, 0, sizeof(msg));
  70. msg.msg.command = command;
  71. msg.msg.outsize = sizeof(msg.data);
  72. msg.data.time = param;
  73. ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
  74. if (ret < 0) {
  75. dev_err(cros_ec->dev, "error setting %s on EC: %d\n",
  76. command == EC_CMD_RTC_SET_VALUE ? "time" : "alarm",
  77. ret);
  78. return ret;
  79. }
  80. return 0;
  81. }
  82. /* Read the current time from the EC. */
  83. static int cros_ec_rtc_read_time(struct device *dev, struct rtc_time *tm)
  84. {
  85. struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
  86. struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
  87. int ret;
  88. u32 time;
  89. ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &time);
  90. if (ret) {
  91. dev_err(dev, "error getting time: %d\n", ret);
  92. return ret;
  93. }
  94. rtc_time64_to_tm(time, tm);
  95. return 0;
  96. }
  97. /* Set the current EC time. */
  98. static int cros_ec_rtc_set_time(struct device *dev, struct rtc_time *tm)
  99. {
  100. struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
  101. struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
  102. int ret;
  103. time64_t time;
  104. time = rtc_tm_to_time64(tm);
  105. if (time < 0 || time > U32_MAX)
  106. return -EINVAL;
  107. ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_VALUE, (u32)time);
  108. if (ret < 0) {
  109. dev_err(dev, "error setting time: %d\n", ret);
  110. return ret;
  111. }
  112. return 0;
  113. }
  114. /* Read alarm time from RTC. */
  115. static int cros_ec_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  116. {
  117. struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
  118. struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
  119. int ret;
  120. u32 current_time, alarm_offset;
  121. /*
  122. * The EC host command for getting the alarm is relative (i.e. 5
  123. * seconds from now) whereas rtc_wkalrm is absolute. Get the current
  124. * RTC time first so we can calculate the relative time.
  125. */
  126. ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
  127. if (ret < 0) {
  128. dev_err(dev, "error getting time: %d\n", ret);
  129. return ret;
  130. }
  131. ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_ALARM, &alarm_offset);
  132. if (ret < 0) {
  133. dev_err(dev, "error getting alarm: %d\n", ret);
  134. return ret;
  135. }
  136. rtc_time64_to_tm(current_time + alarm_offset, &alrm->time);
  137. return 0;
  138. }
  139. /* Set the EC's RTC alarm. */
  140. static int cros_ec_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  141. {
  142. struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
  143. struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
  144. int ret;
  145. time64_t alarm_time;
  146. u32 current_time, alarm_offset;
  147. /*
  148. * The EC host command for setting the alarm is relative
  149. * (i.e. 5 seconds from now) whereas rtc_wkalrm is absolute.
  150. * Get the current RTC time first so we can calculate the
  151. * relative time.
  152. */
  153. ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
  154. if (ret < 0) {
  155. dev_err(dev, "error getting time: %d\n", ret);
  156. return ret;
  157. }
  158. alarm_time = rtc_tm_to_time64(&alrm->time);
  159. if (alarm_time < 0 || alarm_time > U32_MAX)
  160. return -EINVAL;
  161. if (!alrm->enabled) {
  162. /*
  163. * If the alarm is being disabled, send an alarm
  164. * clear command.
  165. */
  166. alarm_offset = EC_RTC_ALARM_CLEAR;
  167. cros_ec_rtc->saved_alarm = (u32)alarm_time;
  168. } else {
  169. /* Don't set an alarm in the past. */
  170. if ((u32)alarm_time <= current_time)
  171. return -ETIME;
  172. alarm_offset = (u32)alarm_time - current_time;
  173. }
  174. ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM, alarm_offset);
  175. if (ret < 0) {
  176. dev_err(dev, "error setting alarm: %d\n", ret);
  177. return ret;
  178. }
  179. return 0;
  180. }
  181. static int cros_ec_rtc_alarm_irq_enable(struct device *dev,
  182. unsigned int enabled)
  183. {
  184. struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(dev);
  185. struct cros_ec_device *cros_ec = cros_ec_rtc->cros_ec;
  186. int ret;
  187. u32 current_time, alarm_offset, alarm_value;
  188. ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_VALUE, &current_time);
  189. if (ret < 0) {
  190. dev_err(dev, "error getting time: %d\n", ret);
  191. return ret;
  192. }
  193. if (enabled) {
  194. /* Restore saved alarm if it's still in the future. */
  195. if (cros_ec_rtc->saved_alarm < current_time)
  196. alarm_offset = EC_RTC_ALARM_CLEAR;
  197. else
  198. alarm_offset = cros_ec_rtc->saved_alarm - current_time;
  199. ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM,
  200. alarm_offset);
  201. if (ret < 0) {
  202. dev_err(dev, "error restoring alarm: %d\n", ret);
  203. return ret;
  204. }
  205. } else {
  206. /* Disable alarm, saving the old alarm value. */
  207. ret = cros_ec_rtc_get(cros_ec, EC_CMD_RTC_GET_ALARM,
  208. &alarm_offset);
  209. if (ret < 0) {
  210. dev_err(dev, "error saving alarm: %d\n", ret);
  211. return ret;
  212. }
  213. alarm_value = current_time + alarm_offset;
  214. /*
  215. * If the current EC alarm is already past, we don't want
  216. * to set an alarm when we go through the alarm irq enable
  217. * path.
  218. */
  219. if (alarm_value < current_time)
  220. cros_ec_rtc->saved_alarm = EC_RTC_ALARM_CLEAR;
  221. else
  222. cros_ec_rtc->saved_alarm = alarm_value;
  223. alarm_offset = EC_RTC_ALARM_CLEAR;
  224. ret = cros_ec_rtc_set(cros_ec, EC_CMD_RTC_SET_ALARM,
  225. alarm_offset);
  226. if (ret < 0) {
  227. dev_err(dev, "error disabling alarm: %d\n", ret);
  228. return ret;
  229. }
  230. }
  231. return 0;
  232. }
  233. static int cros_ec_rtc_event(struct notifier_block *nb,
  234. unsigned long queued_during_suspend,
  235. void *_notify)
  236. {
  237. struct cros_ec_rtc *cros_ec_rtc;
  238. struct rtc_device *rtc;
  239. struct cros_ec_device *cros_ec;
  240. u32 host_event;
  241. cros_ec_rtc = container_of(nb, struct cros_ec_rtc, notifier);
  242. rtc = cros_ec_rtc->rtc;
  243. cros_ec = cros_ec_rtc->cros_ec;
  244. host_event = cros_ec_get_host_event(cros_ec);
  245. if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) {
  246. rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
  247. return NOTIFY_OK;
  248. } else {
  249. return NOTIFY_DONE;
  250. }
  251. }
  252. static const struct rtc_class_ops cros_ec_rtc_ops = {
  253. .read_time = cros_ec_rtc_read_time,
  254. .set_time = cros_ec_rtc_set_time,
  255. .read_alarm = cros_ec_rtc_read_alarm,
  256. .set_alarm = cros_ec_rtc_set_alarm,
  257. .alarm_irq_enable = cros_ec_rtc_alarm_irq_enable,
  258. };
  259. #ifdef CONFIG_PM_SLEEP
  260. static int cros_ec_rtc_suspend(struct device *dev)
  261. {
  262. struct platform_device *pdev = to_platform_device(dev);
  263. struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev);
  264. if (device_may_wakeup(dev))
  265. enable_irq_wake(cros_ec_rtc->cros_ec->irq);
  266. return 0;
  267. }
  268. static int cros_ec_rtc_resume(struct device *dev)
  269. {
  270. struct platform_device *pdev = to_platform_device(dev);
  271. struct cros_ec_rtc *cros_ec_rtc = dev_get_drvdata(&pdev->dev);
  272. if (device_may_wakeup(dev))
  273. disable_irq_wake(cros_ec_rtc->cros_ec->irq);
  274. return 0;
  275. }
  276. #endif
  277. static SIMPLE_DEV_PM_OPS(cros_ec_rtc_pm_ops, cros_ec_rtc_suspend,
  278. cros_ec_rtc_resume);
  279. static int cros_ec_rtc_probe(struct platform_device *pdev)
  280. {
  281. struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
  282. struct cros_ec_device *cros_ec = ec_dev->ec_dev;
  283. struct cros_ec_rtc *cros_ec_rtc;
  284. struct rtc_time tm;
  285. int ret;
  286. cros_ec_rtc = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_rtc),
  287. GFP_KERNEL);
  288. if (!cros_ec_rtc)
  289. return -ENOMEM;
  290. platform_set_drvdata(pdev, cros_ec_rtc);
  291. cros_ec_rtc->cros_ec = cros_ec;
  292. /* Get initial time */
  293. ret = cros_ec_rtc_read_time(&pdev->dev, &tm);
  294. if (ret) {
  295. dev_err(&pdev->dev, "failed to read RTC time\n");
  296. return ret;
  297. }
  298. ret = device_init_wakeup(&pdev->dev, 1);
  299. if (ret) {
  300. dev_err(&pdev->dev, "failed to initialize wakeup\n");
  301. return ret;
  302. }
  303. cros_ec_rtc->rtc = devm_rtc_device_register(&pdev->dev, DRV_NAME,
  304. &cros_ec_rtc_ops,
  305. THIS_MODULE);
  306. if (IS_ERR(cros_ec_rtc->rtc)) {
  307. ret = PTR_ERR(cros_ec_rtc->rtc);
  308. dev_err(&pdev->dev, "failed to register rtc device\n");
  309. return ret;
  310. }
  311. /* Get RTC events from the EC. */
  312. cros_ec_rtc->notifier.notifier_call = cros_ec_rtc_event;
  313. ret = blocking_notifier_chain_register(&cros_ec->event_notifier,
  314. &cros_ec_rtc->notifier);
  315. if (ret) {
  316. dev_err(&pdev->dev, "failed to register notifier\n");
  317. return ret;
  318. }
  319. return 0;
  320. }
  321. static int cros_ec_rtc_remove(struct platform_device *pdev)
  322. {
  323. struct cros_ec_rtc *cros_ec_rtc = platform_get_drvdata(pdev);
  324. struct device *dev = &pdev->dev;
  325. int ret;
  326. ret = blocking_notifier_chain_unregister(
  327. &cros_ec_rtc->cros_ec->event_notifier,
  328. &cros_ec_rtc->notifier);
  329. if (ret) {
  330. dev_err(dev, "failed to unregister notifier\n");
  331. return ret;
  332. }
  333. return 0;
  334. }
  335. static struct platform_driver cros_ec_rtc_driver = {
  336. .probe = cros_ec_rtc_probe,
  337. .remove = cros_ec_rtc_remove,
  338. .driver = {
  339. .name = DRV_NAME,
  340. .pm = &cros_ec_rtc_pm_ops,
  341. },
  342. };
  343. module_platform_driver(cros_ec_rtc_driver);
  344. MODULE_DESCRIPTION("RTC driver for Chrome OS ECs");
  345. MODULE_AUTHOR("Stephen Barber <smbarber@chromium.org>");
  346. MODULE_LICENSE("GPL");
  347. MODULE_ALIAS("platform:" DRV_NAME);