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