rtc-brcmstb-waketimer.c 10 KB

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