sec_pon_alarm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * /drivers/rtc/power-on-alarm.c
  3. *
  4. * Copyright (C) 2021 Samsung Electronics
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <linux/time.h>
  17. #include <linux/module.h>
  18. #include <linux/device.h>
  19. #include <linux/miscdevice.h>
  20. #include <linux/fs.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/uaccess.h>
  23. #include <linux/alarmtimer.h>
  24. #include <linux/ioctl.h>
  25. #include <linux/sec_param.h>
  26. #include <linux/rtc.h>
  27. #include <linux/of_device.h>
  28. #define PON_ALARM_KPARAM_MAGIC 0x41504153
  29. #define PON_ALARM_START_POLL_TIME (10LL * NSEC_PER_SEC) /* 10 sec */
  30. #define PON_ALARM_BOOTING_TIME (5 * 60)
  31. #define PON_ALARM_POLL_TIME (15 * 60)
  32. #define BOOTALM_BIT_EN 0
  33. #define BOOTALM_BIT_YEAR 1
  34. #define BOOTALM_BIT_MONTH 5
  35. #define BOOTALM_BIT_DAY 7
  36. #define BOOTALM_BIT_HOUR 9
  37. #define BOOTALM_BIT_MIN 11
  38. #define BOOTALM_BIT_TOTAL 13
  39. #define PRIME_EPOCH_YEAR 1900
  40. enum {
  41. PON_ALARM_DISTANT = 0,
  42. PON_ALARM_NEAR,
  43. PON_ALARM_EXPIRED,
  44. PON_ALARM_OVER,
  45. PON_ALARM_ERROR,
  46. };
  47. struct pon_alarm_info {
  48. struct device *dev;
  49. struct rtc_device *rtcdev;
  50. struct rtc_wkalrm val;
  51. struct alarm check_poll;
  52. struct work_struct check_func;
  53. struct wakeup_source *ws;
  54. uint lpm_mode;
  55. unsigned char triggered;
  56. };
  57. struct alarm_timespec {
  58. char alarm[14];
  59. };
  60. #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0)))
  61. #define ANDROID_ALARM_SET_ALARM_BOOT _IOW('a', 7, struct alarm_timespec)
  62. extern void pmic_rtc_setalarm(struct rtc_wkalrm *alm);
  63. static unsigned int __read_mostly rtcalarm;
  64. static unsigned int __read_mostly lpcharge;
  65. module_param(rtcalarm, uint, 0444);
  66. module_param(lpcharge, uint, 0444);
  67. struct pon_alarm_info pon_alarm;
  68. static void pon_alarm_normalize(struct rtc_wkalrm *alarm)
  69. {
  70. if (!alarm->enabled) {
  71. /* RTC reset + 50 years = 1580518864 = 0x5e34cdd0 */
  72. alarm->time.tm_year = 70 + 50;
  73. alarm->time.tm_mon = 1;
  74. alarm->time.tm_mday = 1;
  75. alarm->time.tm_hour = 1;
  76. alarm->time.tm_min = 1;
  77. alarm->time.tm_sec = 4;
  78. }
  79. }
  80. static void pon_alarm_set(struct rtc_wkalrm *alarm)
  81. {
  82. time64_t secs_pwron;
  83. unsigned int sapa[3];
  84. int ret;
  85. memcpy(&pon_alarm.val, alarm, sizeof(struct rtc_wkalrm));
  86. pon_alarm_normalize(&pon_alarm.val);
  87. pr_info("%s: reserve pmic alarm\n", __func__);
  88. pmic_rtc_setalarm(&pon_alarm.val);
  89. secs_pwron = rtc_tm_to_time64(&pon_alarm.val.time);
  90. sapa[0] = PON_ALARM_KPARAM_MAGIC;
  91. sapa[1] = (unsigned int)pon_alarm.val.enabled;
  92. sapa[2] = (unsigned int)secs_pwron;
  93. ret = sec_set_param(param_index_sapa, sapa);
  94. pr_info("%s: ret=%d, enabled=%d, alarm=%u\n",
  95. __func__, ret, sapa[1], sapa[2]);
  96. }
  97. static void pon_get_alarm_time(struct rtc_wkalrm *alm, u8 *buf_ptr)
  98. {
  99. /*
  100. 0|1234|56|78|90|12
  101. 1|2010|01|01|00|00
  102. en|yyyy|mm|dd|hh|mm
  103. */
  104. alm->time.tm_sec = 0;
  105. alm->time.tm_min = (buf_ptr[BOOTALM_BIT_MIN]-'0') * 10
  106. + (buf_ptr[BOOTALM_BIT_MIN+1]-'0');
  107. alm->time.tm_hour = (buf_ptr[BOOTALM_BIT_HOUR]-'0') * 10
  108. + (buf_ptr[BOOTALM_BIT_HOUR+1]-'0');
  109. alm->time.tm_mday = (buf_ptr[BOOTALM_BIT_DAY]-'0') * 10
  110. + (buf_ptr[BOOTALM_BIT_DAY+1]-'0');
  111. alm->time.tm_mon = (buf_ptr[BOOTALM_BIT_MONTH]-'0') * 10
  112. + (buf_ptr[BOOTALM_BIT_MONTH+1]-'0');
  113. alm->time.tm_year = (buf_ptr[BOOTALM_BIT_YEAR]-'0') * 1000
  114. + (buf_ptr[BOOTALM_BIT_YEAR+1]-'0') * 100
  115. + (buf_ptr[BOOTALM_BIT_YEAR+2]-'0') * 10
  116. + (buf_ptr[BOOTALM_BIT_YEAR+3]-'0');
  117. alm->enabled = (*buf_ptr == '1');
  118. if (*buf_ptr == '2')
  119. alm->enabled = 2;
  120. pr_info("%s: %s => tm(%d %04d-%02d-%02d %02d:%02d:%02d)\n",
  121. __func__, buf_ptr, alm->enabled,
  122. alm->time.tm_year, alm->time.tm_mon, alm->time.tm_mday,
  123. alm->time.tm_hour, alm->time.tm_min, alm->time.tm_sec);
  124. }
  125. static void pon_read_kernel_time(struct timespec64 *ktm_ts, struct rtc_wkalrm *alm)
  126. {
  127. struct rtc_time ktm_tm;
  128. /* read kernel time */
  129. ktime_get_real_ts64(ktm_ts);
  130. ktm_tm = rtc_ktime_to_tm(timespec64_to_ktime(*ktm_ts));
  131. pr_info("%s: <KTM > %4d-%02d-%02d %02d:%02d:%02d\n",
  132. __func__, ktm_tm.tm_year+PRIME_EPOCH_YEAR, ktm_tm.tm_mon+1, ktm_tm.tm_mday,
  133. ktm_tm.tm_hour, ktm_tm.tm_min, ktm_tm.tm_sec);
  134. alm->time.tm_mon -= 1;
  135. alm->time.tm_year -= PRIME_EPOCH_YEAR;
  136. pr_info("%s: <ALRM> %4d-%02d-%02d %02d:%02d:%02d\n",
  137. __func__, alm->time.tm_year+PRIME_EPOCH_YEAR, alm->time.tm_mon+1, alm->time.tm_mday,
  138. alm->time.tm_hour, alm->time.tm_min, alm->time.tm_sec);
  139. }
  140. static int pon_read_current_time(time64_t *rtc_sec, struct rtc_time *rtc_tm)
  141. {
  142. int ret = 0;
  143. ret = rtc_read_time(pon_alarm.rtcdev, rtc_tm);
  144. if (ret) {
  145. pr_err("%s: rtc read failed, ret=%d\n", __func__, ret);
  146. return ret;
  147. }
  148. *rtc_sec = rtc_tm_to_time64(rtc_tm);
  149. pr_info("%s: <rtc > %4d-%02d-%02d %02d:%02d:%02d -> %lu\n",
  150. __func__, rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
  151. rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec, *rtc_sec);
  152. return ret;
  153. }
  154. static void pon_calculate_offset(struct timespec64 *delta, struct timespec64 ktm_ts, time64_t rtc_sec)
  155. {
  156. set_normalized_timespec64(delta,
  157. (time64_t)ktm_ts.tv_sec - rtc_sec,
  158. (s64)ktm_ts.tv_nsec);
  159. }
  160. static void pon_convert_utc_to_rtc(struct timespec64 delta, struct rtc_wkalrm *alm)
  161. {
  162. time64_t rtc_alm_sec;
  163. rtc_alm_sec = rtc_tm_to_time64(&alm->time) - delta.tv_sec;
  164. rtc_alm_sec = (rtc_alm_sec & ~0x00000003) | ((alm->enabled-1)<<1);
  165. alm->enabled = 1;
  166. rtc_time64_to_tm(rtc_alm_sec, &alm->time);
  167. pr_info("%s: <alrm> %4d-%02d-%02d %02d:%02d:%02d -> %lu\n",
  168. __func__, alm->time.tm_year, alm->time.tm_mon, alm->time.tm_mday,
  169. alm->time.tm_hour, alm->time.tm_min, alm->time.tm_sec, rtc_alm_sec);
  170. }
  171. static void pon_alarm_parse_data(char *alarm_data, struct rtc_wkalrm *alm)
  172. {
  173. char buf_ptr[BOOTALM_BIT_TOTAL + 1] = {0,};
  174. struct rtc_time rtc_tm;
  175. struct timespec64 delta, ktm_ts;
  176. time64_t rtc_sec;
  177. int ret;
  178. alarm_data[BOOTALM_BIT_TOTAL] = '\0';
  179. strlcpy(buf_ptr, alarm_data, BOOTALM_BIT_TOTAL+1);
  180. pon_get_alarm_time(alm, buf_ptr);
  181. if (!alm->enabled) {
  182. pr_info("%s: pon alarm is not enabled!\n", __func__);
  183. return;
  184. }
  185. pon_read_kernel_time(&ktm_ts, alm);
  186. ret = pon_read_current_time(&rtc_sec, &rtc_tm);
  187. if (ret < 0) {
  188. pr_info("%s: pon read current time fail!\n", __func__);
  189. return;
  190. }
  191. pon_calculate_offset(&delta, ktm_ts, rtc_sec);
  192. pon_convert_utc_to_rtc(delta, alm);
  193. }
  194. static int pon_alarm_check_state(time64_t *data)
  195. {
  196. struct rtc_time tm;
  197. time64_t rtc_secs;
  198. time64_t secs_pwron;
  199. int res = PON_ALARM_NEAR;
  200. int rc;
  201. rc = rtc_read_time(pon_alarm.rtcdev, &tm);
  202. if (rc) {
  203. pr_err("%s: rtc read failed.\n", __func__);
  204. return PON_ALARM_ERROR;
  205. }
  206. rtc_secs = rtc_tm_to_time64(&tm);
  207. secs_pwron = rtc_tm_to_time64(&pon_alarm.val.time);
  208. if (rtc_secs < secs_pwron) {
  209. if (secs_pwron - rtc_secs > PON_ALARM_POLL_TIME)
  210. res = PON_ALARM_DISTANT;
  211. if (data)
  212. *data = secs_pwron - rtc_secs;
  213. } else if (rtc_secs <= secs_pwron + PON_ALARM_BOOTING_TIME) {
  214. res = PON_ALARM_EXPIRED;
  215. if (data)
  216. *data = rtc_secs + 10;
  217. } else
  218. res = PON_ALARM_OVER;
  219. pr_info("%s: rtc:%lu, alrm:%lu[%d]\n",
  220. __func__, rtc_secs, secs_pwron, res);
  221. return res;
  222. }
  223. static void pon_alarm_check_func(struct work_struct *work)
  224. {
  225. struct pon_alarm_info *pona = container_of(work, struct pon_alarm_info, check_func);
  226. int res;
  227. time64_t remain;
  228. res = pon_alarm_check_state(&remain);
  229. if (res <= PON_ALARM_NEAR) {
  230. ktime_t kt;
  231. if (res == PON_ALARM_DISTANT)
  232. remain = PON_ALARM_POLL_TIME;
  233. kt = ns_to_ktime((u64)remain * NSEC_PER_SEC);
  234. alarm_start_relative(&pona->check_poll, kt);
  235. pr_info("%s: next %lu s\n", __func__, remain);
  236. } else if (res == PON_ALARM_EXPIRED) {
  237. __pm_stay_awake(pona->ws);
  238. pona->triggered = 1;
  239. }
  240. }
  241. static enum alarmtimer_restart pon_alarm_check_callback(struct alarm *alarm, ktime_t now)
  242. {
  243. struct pon_alarm_info *pona = container_of(alarm, struct pon_alarm_info, check_poll);
  244. schedule_work(&pona->check_func);
  245. return ALARMTIMER_NORESTART;
  246. }
  247. static int pon_alarm_open(struct inode *inode, struct file *file)
  248. {
  249. file->private_data = NULL;
  250. return 0;
  251. }
  252. static ssize_t pon_alarm_read(struct file *file,
  253. char __user *buff, size_t count, loff_t *ppos)
  254. {
  255. char trigger = (pon_alarm.triggered) ? '1':'0';
  256. if (copy_to_user((void __user *)buff, &trigger, 1)) {
  257. pr_err("%s: read failed.\n", __func__);
  258. return -EFAULT;
  259. }
  260. pr_info("%s: trigger=%c\n", __func__, trigger);
  261. return 1;
  262. }
  263. static long pon_alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  264. {
  265. int rv = 0;
  266. struct alarm_timespec data;
  267. struct rtc_wkalrm alm;
  268. pr_info("%s: cmd=%08x\n", __func__, cmd);
  269. switch (ANDROID_ALARM_BASE_CMD(cmd)) {
  270. case ANDROID_ALARM_SET_ALARM_BOOT:
  271. if (copy_from_user(data.alarm, (void __user *)arg, 14)) {
  272. rv = -EFAULT;
  273. pr_err("%s: SET ret=%s\n", __func__, rv);
  274. return rv;
  275. }
  276. pon_alarm_parse_data(data.alarm, &alm);
  277. pon_alarm_set(&alm);
  278. break;
  279. }
  280. return rv;
  281. }
  282. static int pon_alarm_release(struct inode *inode, struct file *file)
  283. {
  284. return 0;
  285. }
  286. static const struct file_operations pon_alarm_fops = {
  287. .owner = THIS_MODULE,
  288. .open = pon_alarm_open,
  289. .read = pon_alarm_read,
  290. .unlocked_ioctl = pon_alarm_ioctl,
  291. .release = pon_alarm_release,
  292. };
  293. static struct miscdevice pon_alarm_device = {
  294. .minor = MISC_DYNAMIC_MINOR,
  295. .name = "power_on_alarm",
  296. .fops = &pon_alarm_fops,
  297. };
  298. static int __init pon_alarm_init(void)
  299. {
  300. struct rtc_device *rtcdev;
  301. int ret;
  302. rtcdev = alarmtimer_get_rtcdev();
  303. if (!rtcdev) {
  304. pr_err("%s: no rtcdev (defer)\n", __func__);
  305. return -ENODEV;
  306. }
  307. ret = misc_register(&pon_alarm_device);
  308. if (ret) {
  309. pr_err("%s: ret=%d\n", __func__, ret);
  310. return ret;
  311. }
  312. pr_info("%s: rtcalarm=%u, lpcharge=%u\n", __func__, rtcalarm, lpcharge);
  313. pon_alarm.rtcdev = rtcdev;
  314. pon_alarm.lpm_mode = lpcharge;
  315. pon_alarm.triggered = 0;
  316. pon_alarm.val.enabled = (rtcalarm) ? 1 : 0;
  317. rtc_time64_to_tm((time64_t)rtcalarm, &pon_alarm.val.time);
  318. if (pon_alarm.lpm_mode && pon_alarm.val.enabled) {
  319. pr_info("%s: reserve pmic alarm\n", __func__);
  320. pmic_rtc_setalarm(&pon_alarm.val);
  321. pon_alarm.ws = wakeup_source_register(pon_alarm.dev, "PON_ALARM");
  322. alarm_init(&pon_alarm.check_poll, ALARM_REALTIME, pon_alarm_check_callback);
  323. INIT_WORK(&pon_alarm.check_func, pon_alarm_check_func);
  324. alarm_start_relative(&pon_alarm.check_poll, ns_to_ktime(PON_ALARM_START_POLL_TIME));
  325. }
  326. pr_info("%s: done\n", __func__);
  327. return 0;
  328. }
  329. static void __exit pon_alarm_exit(void)
  330. {
  331. misc_deregister(&pon_alarm_device);
  332. if (pon_alarm.lpm_mode && pon_alarm.val.enabled) {
  333. pr_info("%s: clear for lpm_mode\n", __func__);
  334. cancel_work_sync(&pon_alarm.check_func);
  335. alarm_cancel(&pon_alarm.check_poll);
  336. wakeup_source_unregister(pon_alarm.ws);
  337. }
  338. }
  339. module_init(pon_alarm_init);
  340. module_exit(pon_alarm_exit);
  341. MODULE_ALIAS("platform:sec_pon_alarm");
  342. MODULE_DESCRIPTION("SEC_PON_ALARM driver");
  343. MODULE_LICENSE("GPL v2");