rtc-brcmstb-waketimer.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright © 2014-2023 Broadcom
  4. */
  5. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  6. #include <linux/clk.h>
  7. #include <linux/device.h>
  8. #include <linux/err.h>
  9. #include <linux/init.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/io.h>
  12. #include <linux/irqreturn.h>
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/of.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/pm.h>
  18. #include <linux/pm_wakeup.h>
  19. #include <linux/reboot.h>
  20. #include <linux/rtc.h>
  21. #include <linux/stat.h>
  22. #include <linux/suspend.h>
  23. struct brcmstb_waketmr {
  24. struct rtc_device *rtc;
  25. struct device *dev;
  26. void __iomem *base;
  27. unsigned int wake_irq;
  28. unsigned int alarm_irq;
  29. struct notifier_block reboot_notifier;
  30. struct clk *clk;
  31. u32 rate;
  32. unsigned long rtc_alarm;
  33. bool alarm_en;
  34. bool alarm_expired;
  35. };
  36. #define BRCMSTB_WKTMR_EVENT 0x00
  37. #define WKTMR_ALARM_EVENT BIT(0)
  38. #define BRCMSTB_WKTMR_COUNTER 0x04
  39. #define BRCMSTB_WKTMR_ALARM 0x08
  40. #define BRCMSTB_WKTMR_PRESCALER 0x0C
  41. #define BRCMSTB_WKTMR_PRESCALER_VAL 0x10
  42. #define BRCMSTB_WKTMR_DEFAULT_FREQ 27000000
  43. static inline bool brcmstb_waketmr_is_pending(struct brcmstb_waketmr *timer)
  44. {
  45. u32 reg;
  46. reg = readl_relaxed(timer->base + BRCMSTB_WKTMR_EVENT);
  47. return !!(reg & WKTMR_ALARM_EVENT);
  48. }
  49. static inline void brcmstb_waketmr_clear_alarm(struct brcmstb_waketmr *timer)
  50. {
  51. u32 reg;
  52. if (timer->alarm_en && timer->alarm_irq)
  53. disable_irq(timer->alarm_irq);
  54. timer->alarm_en = false;
  55. reg = readl_relaxed(timer->base + BRCMSTB_WKTMR_COUNTER);
  56. writel_relaxed(reg - 1, timer->base + BRCMSTB_WKTMR_ALARM);
  57. writel_relaxed(WKTMR_ALARM_EVENT, timer->base + BRCMSTB_WKTMR_EVENT);
  58. (void)readl_relaxed(timer->base + BRCMSTB_WKTMR_EVENT);
  59. if (timer->alarm_expired) {
  60. timer->alarm_expired = false;
  61. /* maintain call balance */
  62. enable_irq(timer->alarm_irq);
  63. }
  64. }
  65. static void brcmstb_waketmr_set_alarm(struct brcmstb_waketmr *timer,
  66. unsigned int secs)
  67. {
  68. unsigned int now;
  69. brcmstb_waketmr_clear_alarm(timer);
  70. /* Make sure we are actually counting in seconds */
  71. writel_relaxed(timer->rate, timer->base + BRCMSTB_WKTMR_PRESCALER);
  72. writel_relaxed(secs, timer->base + BRCMSTB_WKTMR_ALARM);
  73. now = readl_relaxed(timer->base + BRCMSTB_WKTMR_COUNTER);
  74. while ((int)(secs - now) <= 0 &&
  75. !brcmstb_waketmr_is_pending(timer)) {
  76. secs = now + 1;
  77. writel_relaxed(secs, timer->base + BRCMSTB_WKTMR_ALARM);
  78. now = readl_relaxed(timer->base + BRCMSTB_WKTMR_COUNTER);
  79. }
  80. }
  81. static irqreturn_t brcmstb_waketmr_irq(int irq, void *data)
  82. {
  83. struct brcmstb_waketmr *timer = data;
  84. if (!timer->alarm_irq)
  85. pm_wakeup_event(timer->dev, 0);
  86. return IRQ_HANDLED;
  87. }
  88. static irqreturn_t brcmstb_alarm_irq(int irq, void *data)
  89. {
  90. struct brcmstb_waketmr *timer = data;
  91. /* Ignore spurious interrupts */
  92. if (!brcmstb_waketmr_is_pending(timer))
  93. return IRQ_HANDLED;
  94. if (timer->alarm_en) {
  95. if (device_may_wakeup(timer->dev)) {
  96. disable_irq_nosync(irq);
  97. timer->alarm_expired = true;
  98. } else {
  99. writel_relaxed(WKTMR_ALARM_EVENT,
  100. timer->base + BRCMSTB_WKTMR_EVENT);
  101. }
  102. rtc_update_irq(timer->rtc, 1, RTC_IRQF | RTC_AF);
  103. } else {
  104. writel_relaxed(WKTMR_ALARM_EVENT,
  105. timer->base + BRCMSTB_WKTMR_EVENT);
  106. }
  107. return IRQ_HANDLED;
  108. }
  109. struct wktmr_time {
  110. u32 sec;
  111. u32 pre;
  112. };
  113. static void wktmr_read(struct brcmstb_waketmr *timer,
  114. struct wktmr_time *t)
  115. {
  116. u32 tmp;
  117. do {
  118. t->sec = readl_relaxed(timer->base + BRCMSTB_WKTMR_COUNTER);
  119. tmp = readl_relaxed(timer->base + BRCMSTB_WKTMR_PRESCALER_VAL);
  120. } while (tmp >= timer->rate);
  121. t->pre = timer->rate - tmp;
  122. }
  123. static int brcmstb_waketmr_prepare_suspend(struct brcmstb_waketmr *timer)
  124. {
  125. struct device *dev = timer->dev;
  126. int ret;
  127. if (device_may_wakeup(dev)) {
  128. ret = enable_irq_wake(timer->wake_irq);
  129. if (ret) {
  130. dev_err(dev, "failed to enable wake-up interrupt\n");
  131. return ret;
  132. }
  133. if (timer->alarm_en && timer->alarm_irq) {
  134. ret = enable_irq_wake(timer->alarm_irq);
  135. if (ret) {
  136. dev_err(dev, "failed to enable rtc interrupt\n");
  137. disable_irq_wake(timer->wake_irq);
  138. return ret;
  139. }
  140. }
  141. }
  142. return 0;
  143. }
  144. /* If enabled as a wakeup-source, arm the timer when powering off */
  145. static int brcmstb_waketmr_reboot(struct notifier_block *nb,
  146. unsigned long action, void *data)
  147. {
  148. struct brcmstb_waketmr *timer;
  149. timer = container_of(nb, struct brcmstb_waketmr, reboot_notifier);
  150. /* Set timer for cold boot */
  151. if (action == SYS_POWER_OFF)
  152. brcmstb_waketmr_prepare_suspend(timer);
  153. return NOTIFY_DONE;
  154. }
  155. static int brcmstb_waketmr_gettime(struct device *dev,
  156. struct rtc_time *tm)
  157. {
  158. struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
  159. struct wktmr_time now;
  160. wktmr_read(timer, &now);
  161. rtc_time64_to_tm(now.sec, tm);
  162. return 0;
  163. }
  164. static int brcmstb_waketmr_settime(struct device *dev,
  165. struct rtc_time *tm)
  166. {
  167. struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
  168. time64_t sec;
  169. sec = rtc_tm_to_time64(tm);
  170. writel_relaxed(sec, timer->base + BRCMSTB_WKTMR_COUNTER);
  171. return 0;
  172. }
  173. static int brcmstb_waketmr_getalarm(struct device *dev,
  174. struct rtc_wkalrm *alarm)
  175. {
  176. struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
  177. alarm->enabled = timer->alarm_en;
  178. rtc_time64_to_tm(timer->rtc_alarm, &alarm->time);
  179. alarm->pending = brcmstb_waketmr_is_pending(timer);
  180. return 0;
  181. }
  182. static int brcmstb_waketmr_alarm_enable(struct device *dev,
  183. unsigned int enabled)
  184. {
  185. struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
  186. if (enabled && !timer->alarm_en) {
  187. if ((int)(readl_relaxed(timer->base + BRCMSTB_WKTMR_COUNTER) -
  188. readl_relaxed(timer->base + BRCMSTB_WKTMR_ALARM)) >= 0 &&
  189. !brcmstb_waketmr_is_pending(timer))
  190. return -EINVAL;
  191. timer->alarm_en = true;
  192. if (timer->alarm_irq) {
  193. if (timer->alarm_expired) {
  194. timer->alarm_expired = false;
  195. /* maintain call balance */
  196. enable_irq(timer->alarm_irq);
  197. }
  198. enable_irq(timer->alarm_irq);
  199. }
  200. } else if (!enabled && timer->alarm_en) {
  201. if (timer->alarm_irq)
  202. disable_irq(timer->alarm_irq);
  203. timer->alarm_en = false;
  204. }
  205. return 0;
  206. }
  207. static int brcmstb_waketmr_setalarm(struct device *dev,
  208. struct rtc_wkalrm *alarm)
  209. {
  210. struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
  211. timer->rtc_alarm = rtc_tm_to_time64(&alarm->time);
  212. brcmstb_waketmr_set_alarm(timer, timer->rtc_alarm);
  213. return brcmstb_waketmr_alarm_enable(dev, alarm->enabled);
  214. }
  215. static const struct rtc_class_ops brcmstb_waketmr_ops = {
  216. .read_time = brcmstb_waketmr_gettime,
  217. .set_time = brcmstb_waketmr_settime,
  218. .read_alarm = brcmstb_waketmr_getalarm,
  219. .set_alarm = brcmstb_waketmr_setalarm,
  220. .alarm_irq_enable = brcmstb_waketmr_alarm_enable,
  221. };
  222. static int brcmstb_waketmr_probe(struct platform_device *pdev)
  223. {
  224. struct device *dev = &pdev->dev;
  225. struct brcmstb_waketmr *timer;
  226. int ret;
  227. timer = devm_kzalloc(dev, sizeof(*timer), GFP_KERNEL);
  228. if (!timer)
  229. return -ENOMEM;
  230. platform_set_drvdata(pdev, timer);
  231. timer->dev = dev;
  232. timer->base = devm_platform_ioremap_resource(pdev, 0);
  233. if (IS_ERR(timer->base))
  234. return PTR_ERR(timer->base);
  235. timer->rtc = devm_rtc_allocate_device(dev);
  236. if (IS_ERR(timer->rtc))
  237. return PTR_ERR(timer->rtc);
  238. /*
  239. * Set wakeup capability before requesting wakeup interrupt, so we can
  240. * process boot-time "wakeups" (e.g., from S5 soft-off)
  241. */
  242. device_init_wakeup(dev, true);
  243. ret = platform_get_irq(pdev, 0);
  244. if (ret < 0)
  245. return -ENODEV;
  246. timer->wake_irq = (unsigned int)ret;
  247. timer->clk = devm_clk_get(dev, NULL);
  248. if (!IS_ERR(timer->clk)) {
  249. ret = clk_prepare_enable(timer->clk);
  250. if (ret)
  251. return ret;
  252. timer->rate = clk_get_rate(timer->clk);
  253. if (!timer->rate)
  254. timer->rate = BRCMSTB_WKTMR_DEFAULT_FREQ;
  255. } else {
  256. timer->rate = BRCMSTB_WKTMR_DEFAULT_FREQ;
  257. timer->clk = NULL;
  258. }
  259. ret = devm_request_irq(dev, timer->wake_irq, brcmstb_waketmr_irq, 0,
  260. "brcmstb-waketimer", timer);
  261. if (ret < 0)
  262. goto err_clk;
  263. brcmstb_waketmr_clear_alarm(timer);
  264. /* Attempt to initialize non-wake irq */
  265. ret = platform_get_irq(pdev, 1);
  266. if (ret > 0) {
  267. timer->alarm_irq = (unsigned int)ret;
  268. ret = devm_request_irq(dev, timer->alarm_irq, brcmstb_alarm_irq,
  269. IRQF_NO_AUTOEN, "brcmstb-waketimer-rtc",
  270. timer);
  271. if (ret < 0)
  272. timer->alarm_irq = 0;
  273. }
  274. timer->reboot_notifier.notifier_call = brcmstb_waketmr_reboot;
  275. register_reboot_notifier(&timer->reboot_notifier);
  276. timer->rtc->ops = &brcmstb_waketmr_ops;
  277. timer->rtc->range_max = U32_MAX;
  278. ret = devm_rtc_register_device(timer->rtc);
  279. if (ret)
  280. goto err_notifier;
  281. return 0;
  282. err_notifier:
  283. unregister_reboot_notifier(&timer->reboot_notifier);
  284. err_clk:
  285. clk_disable_unprepare(timer->clk);
  286. return ret;
  287. }
  288. static void brcmstb_waketmr_remove(struct platform_device *pdev)
  289. {
  290. struct brcmstb_waketmr *timer = dev_get_drvdata(&pdev->dev);
  291. unregister_reboot_notifier(&timer->reboot_notifier);
  292. clk_disable_unprepare(timer->clk);
  293. }
  294. #ifdef CONFIG_PM_SLEEP
  295. static int brcmstb_waketmr_suspend(struct device *dev)
  296. {
  297. struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
  298. return brcmstb_waketmr_prepare_suspend(timer);
  299. }
  300. static int brcmstb_waketmr_suspend_noirq(struct device *dev)
  301. {
  302. struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
  303. /* Catch any alarms occurring prior to noirq */
  304. if (timer->alarm_expired && device_may_wakeup(dev))
  305. return -EBUSY;
  306. return 0;
  307. }
  308. static int brcmstb_waketmr_resume(struct device *dev)
  309. {
  310. struct brcmstb_waketmr *timer = dev_get_drvdata(dev);
  311. int ret;
  312. if (!device_may_wakeup(dev))
  313. return 0;
  314. ret = disable_irq_wake(timer->wake_irq);
  315. if (timer->alarm_en && timer->alarm_irq)
  316. disable_irq_wake(timer->alarm_irq);
  317. brcmstb_waketmr_clear_alarm(timer);
  318. return ret;
  319. }
  320. #else
  321. #define brcmstb_waketmr_suspend NULL
  322. #define brcmstb_waketmr_suspend_noirq NULL
  323. #define brcmstb_waketmr_resume NULL
  324. #endif /* CONFIG_PM_SLEEP */
  325. static const struct dev_pm_ops brcmstb_waketmr_pm_ops = {
  326. .suspend = brcmstb_waketmr_suspend,
  327. .suspend_noirq = brcmstb_waketmr_suspend_noirq,
  328. .resume = brcmstb_waketmr_resume,
  329. };
  330. static const __maybe_unused struct of_device_id brcmstb_waketmr_of_match[] = {
  331. { .compatible = "brcm,brcmstb-waketimer" },
  332. { /* sentinel */ },
  333. };
  334. static struct platform_driver brcmstb_waketmr_driver = {
  335. .probe = brcmstb_waketmr_probe,
  336. .remove_new = brcmstb_waketmr_remove,
  337. .driver = {
  338. .name = "brcmstb-waketimer",
  339. .pm = &brcmstb_waketmr_pm_ops,
  340. .of_match_table = of_match_ptr(brcmstb_waketmr_of_match),
  341. }
  342. };
  343. module_platform_driver(brcmstb_waketmr_driver);
  344. MODULE_LICENSE("GPL v2");
  345. MODULE_AUTHOR("Brian Norris");
  346. MODULE_AUTHOR("Markus Mayer");
  347. MODULE_AUTHOR("Doug Berger");
  348. MODULE_DESCRIPTION("Wake-up timer driver for STB chips");