1139823Simp// SPDX-License-Identifier: GPL-2.0 21541Srgrimes/* Device wakeirq helper functions */ 31541Srgrimes#include <linux/device.h> 4137668Smlaier#include <linux/interrupt.h> 51541Srgrimes#include <linux/irq.h> 61541Srgrimes#include <linux/slab.h> 71541Srgrimes#include <linux/pm_runtime.h> 81541Srgrimes#include <linux/pm_wakeirq.h> 91541Srgrimes 101541Srgrimes#include "power.h" 111541Srgrimes 121541Srgrimes/** 131541Srgrimes * dev_pm_attach_wake_irq - Attach device interrupt as a wake IRQ 141541Srgrimes * @dev: Device entry 151541Srgrimes * @wirq: Wake irq specific data 161541Srgrimes * 171541Srgrimes * Internal function to attach a dedicated wake-up interrupt as a wake IRQ. 181541Srgrimes */ 191541Srgrimesstatic int dev_pm_attach_wake_irq(struct device *dev, struct wake_irq *wirq) 201541Srgrimes{ 211541Srgrimes unsigned long flags; 221541Srgrimes 231541Srgrimes if (!dev || !wirq) 241541Srgrimes return -EINVAL; 251541Srgrimes 261541Srgrimes spin_lock_irqsave(&dev->power.lock, flags); 271541Srgrimes if (dev_WARN_ONCE(dev, dev->power.wakeirq, 281541Srgrimes "wake irq already initialized\n")) { 291541Srgrimes spin_unlock_irqrestore(&dev->power.lock, flags); 3010939Swollman return -EEXIST; 3150477Speter } 321541Srgrimes 331541Srgrimes dev->power.wakeirq = wirq; 34143868Sglebius device_wakeup_attach_irq(dev, wirq); 35143868Sglebius 361541Srgrimes spin_unlock_irqrestore(&dev->power.lock, flags); 371549Srgrimes return 0; 3824204Sbde} 391541Srgrimes 401541Srgrimes/** 4112704Sphk * dev_pm_set_wake_irq - Attach device IO interrupt as wake IRQ 4212704Sphk * @dev: Device entry 431541Srgrimes * @irq: Device IO interrupt 441541Srgrimes * 4555009Sshin * Attach a device IO interrupt as a wake IRQ. The wake IRQ gets 461541Srgrimes * automatically configured for wake-up from suspend based 471541Srgrimes * on the device specific sysfs wakeup entry. Typically called 481541Srgrimes * during driver probe after calling device_init_wakeup(). 491541Srgrimes */ 5081127Sumeint dev_pm_set_wake_irq(struct device *dev, int irq) 511541Srgrimes{ 526363Sphk struct wake_irq *wirq; 536363Sphk int err; 5430354Sphk 5530309Sphk if (irq < 0) 5692723Salfred return -EINVAL; 5792723Salfred 5892723Salfred wirq = kzalloc(sizeof(*wirq), GFP_KERNEL); 5992723Salfred if (!wirq) 6055009Sshin return -ENOMEM; 61137628Smlaier 62137628Smlaier wirq->dev = dev; 6392723Salfred wirq->irq = irq; 6492723Salfred 6592723Salfred err = dev_pm_attach_wake_irq(dev, wirq); 661541Srgrimes if (err) 6718193Swollman kfree(wirq); 68133874Srwatson 69123998Sru return err; 7021666Swollman} 7121666SwollmanEXPORT_SYMBOL_GPL(dev_pm_set_wake_irq); 7221666Swollman 7381127Sume/** 7481127Sume * dev_pm_clear_wake_irq - Detach a device IO interrupt wake IRQ 7581127Sume * @dev: Device entry 761541Srgrimes * 771541Srgrimes * Detach a device wake IRQ and free resources. 781541Srgrimes * 791541Srgrimes * Note that it's OK for drivers to call this without calling 801541Srgrimes * dev_pm_set_wake_irq() as all the driver instances may not have 811541Srgrimes * a wake IRQ configured. This avoid adding wake IRQ specific 821549Srgrimes * checks into the drivers. 831541Srgrimes */ 841541Srgrimesvoid dev_pm_clear_wake_irq(struct device *dev) 851541Srgrimes{ 861541Srgrimes struct wake_irq *wirq = dev->power.wakeirq; 871541Srgrimes unsigned long flags; 881541Srgrimes 891541Srgrimes if (!wirq) 9074362Sphk return; 911541Srgrimes 921541Srgrimes spin_lock_irqsave(&dev->power.lock, flags); 931541Srgrimes device_wakeup_detach_irq(dev); 9472012Sphk dev->power.wakeirq = NULL; 951541Srgrimes spin_unlock_irqrestore(&dev->power.lock, flags); 961541Srgrimes 971541Srgrimes if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED) { 981541Srgrimes free_irq(wirq->irq, wirq); 991541Srgrimes wirq->status &= ~WAKE_IRQ_DEDICATED_MASK; 1001541Srgrimes } 1011541Srgrimes kfree(wirq->name); 102133486Sandre kfree(wirq); 103133486Sandre} 104133486SandreEXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq); 105133486Sandre 106133486Sandre/** 107133486Sandre * handle_threaded_wake_irq - Handler for dedicated wake-up interrupts 108133486Sandre * @irq: Device specific dedicated wake-up interrupt 109133486Sandre * @_wirq: Wake IRQ data 110133486Sandre * 111133486Sandre * Some devices have a separate wake-up interrupt in addition to the 112133486Sandre * device IO interrupt. The wake-up interrupt signals that a device 113133486Sandre * should be woken up from it's idle state. This handler uses device 114133486Sandre * specific pm_runtime functions to wake the device, and then it's 115133486Sandre * up to the device to do whatever it needs to. Note that as the 116133486Sandre * device may need to restore context and start up regulators, we 117133486Sandre * use a threaded IRQ. 118133486Sandre * 1191541Srgrimes * Also note that we are not resending the lost device interrupts. 1201541Srgrimes * We assume that the wake-up interrupt just needs to wake-up the 1211541Srgrimes * device, and then device's pm_runtime_resume() can deal with the 1221541Srgrimes * situation. 1231549Srgrimes */ 1241541Srgrimesstatic irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq) 1251541Srgrimes{ 1261541Srgrimes struct wake_irq *wirq = _wirq; 1271541Srgrimes int res; 1281541Srgrimes 1291541Srgrimes /* Maybe abort suspend? */ 1301541Srgrimes if (irqd_is_wakeup_set(irq_get_irq_data(irq))) { 1311541Srgrimes pm_wakeup_event(wirq->dev, 0); 1321541Srgrimes 1331541Srgrimes return IRQ_HANDLED; 1341541Srgrimes } 1351541Srgrimes 1361541Srgrimes /* We don't want RPM_ASYNC or RPM_NOWAIT here */ 1371541Srgrimes res = pm_runtime_resume(wirq->dev); 1381541Srgrimes if (res < 0) 1391541Srgrimes dev_warn(wirq->dev, 1401541Srgrimes "wake IRQ with no resume: %i\n", res); 1411541Srgrimes 1421541Srgrimes return IRQ_HANDLED; 14312296Sphk} 1441541Srgrimes 1451541Srgrimesstatic int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag) 1461541Srgrimes{ 1471541Srgrimes struct wake_irq *wirq; 1481541Srgrimes int err; 1491541Srgrimes 1501541Srgrimes if (irq < 0) 1514127Swollman return -EINVAL; 152133874Srwatson 1531541Srgrimes wirq = kzalloc(sizeof(*wirq), GFP_KERNEL); 1541541Srgrimes if (!wirq) 1551541Srgrimes return -ENOMEM; 1561541Srgrimes 1571541Srgrimes wirq->name = kasprintf(GFP_KERNEL, "%s:wakeup", dev_name(dev)); 15855009Sshin if (!wirq->name) { 15955009Sshin err = -ENOMEM; 16055009Sshin goto err_free; 16155009Sshin } 16255009Sshin 16355009Sshin wirq->dev = dev; 16455009Sshin wirq->irq = irq; 16555009Sshin 16655009Sshin /* Prevent deferred spurious wakeirqs with disable_irq_nosync() */ 16755009Sshin irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY); 16855009Sshin 16955009Sshin /* 17055009Sshin * Consumer device may need to power up and restore state 17155009Sshin * so we use a threaded irq. 17255009Sshin */ 17355009Sshin err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq, 17455009Sshin IRQF_ONESHOT | IRQF_NO_AUTOEN, 17555009Sshin wirq->name, wirq); 17655009Sshin if (err) 17755009Sshin goto err_free_name; 17855009Sshin 17955009Sshin err = dev_pm_attach_wake_irq(dev, wirq); 18055009Sshin if (err) 18155009Sshin goto err_free_irq; 18255009Sshin 18355009Sshin wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED | flag; 18455009Sshin 18555009Sshin return err; 18655009Sshin 18755009Sshinerr_free_irq: 18855009Sshin free_irq(irq, wirq); 18955009Sshinerr_free_name: 19055009Sshin kfree(wirq->name); 19155009Sshinerr_free: 19255009Sshin kfree(wirq); 19355009Sshin 19455009Sshin return err; 19555009Sshin} 1961541Srgrimes 1971541Srgrimes/** 1981541Srgrimes * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt 1991541Srgrimes * @dev: Device entry 2001541Srgrimes * @irq: Device wake-up interrupt 2011549Srgrimes * 20283366Sjulian * Unless your hardware has separate wake-up interrupts in addition 2031541Srgrimes * to the device IO interrupts, you don't need this. 20436735Sdfr * 2051541Srgrimes * Sets up a threaded interrupt handler for a device that has 2061541Srgrimes * a dedicated wake-up interrupt in addition to the device IO 20783366Sjulian * interrupt. 2081541Srgrimes */ 2091541Srgrimesint dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) 21014632Sfenner{ 2111541Srgrimes return __dev_pm_set_dedicated_wake_irq(dev, irq, 0); 21284102Sjlemon} 2131541SrgrimesEXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq); 2141541Srgrimes 2151541Srgrimes/** 21687124Sbrian * dev_pm_set_dedicated_wake_irq_reverse - Request a dedicated wake-up interrupt 2171541Srgrimes * with reverse enable ordering 21887124Sbrian * @dev: Device entry 21987124Sbrian * @irq: Device wake-up interrupt 22055009Sshin * 22155009Sshin * Unless your hardware has separate wake-up interrupts in addition 22255009Sshin * to the device IO interrupts, you don't need this. 22393593Sjhb * 22455009Sshin * Sets up a threaded interrupt handler for a device that has a dedicated 22555009Sshin * wake-up interrupt in addition to the device IO interrupt. It sets 22655009Sshin * the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend() 22755009Sshin * to enable dedicated wake-up interrupt after running the runtime suspend 22855009Sshin * callback for @dev. 22983366Sjulian */ 23055009Sshinint dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq) 23155009Sshin{ 2321541Srgrimes return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE); 2331541Srgrimes} 23414632SfennerEXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse); 23514632Sfenner 23684102Sjlemon/** 2371541Srgrimes * dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt 23884102Sjlemon * @dev: Device 23984102Sjlemon * @can_change_status: Can change wake-up interrupt status 24084102Sjlemon * 24184102Sjlemon * Enables wakeirq conditionally. We need to enable wake-up interrupt 24284102Sjlemon * lazily on the first rpm_suspend(). This is needed as the consumer device 24384102Sjlemon * starts in RPM_SUSPENDED state, and the first pm_runtime_get() would 24484102Sjlemon * otherwise try to disable already disabled wakeirq. The wake-up interrupt 24584102Sjlemon * starts disabled with IRQ_NOAUTOEN set. 24684102Sjlemon * 24784102Sjlemon * Should be only called from rpm_suspend() and rpm_resume() path. 24884102Sjlemon * Caller must hold &dev->power.lock to change wirq->status 24984102Sjlemon */ 25014632Sfennervoid dev_pm_enable_wake_irq_check(struct device *dev, 25114632Sfenner bool can_change_status) 25214632Sfenner{ 25314632Sfenner struct wake_irq *wirq = dev->power.wakeirq; 25484102Sjlemon 2551541Srgrimes if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK)) 2561541Srgrimes return; 2571541Srgrimes 2581541Srgrimes if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) { 2591541Srgrimes goto enable; 26041575Seivind } else if (can_change_status) { 26141575Seivind wirq->status |= WAKE_IRQ_DEDICATED_MANAGED; 2628071Swollman goto enable; 26371999Sphk } 2648071Swollman 2658071Swollman return; 2668071Swollman 2678071Swollmanenable: 2688071Swollman if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) { 2698876Srgrimes enable_irq(wirq->irq); 2708071Swollman wirq->status |= WAKE_IRQ_DEDICATED_ENABLED; 2718071Swollman } 2728071Swollman} 2739563Swollman 2748071Swollman/** 2751541Srgrimes * dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt 2761541Srgrimes * @dev: Device 2771541Srgrimes * @cond_disable: if set, also check WAKE_IRQ_DEDICATED_REVERSE 2781541Srgrimes * 2791541Srgrimes * Disables wake-up interrupt conditionally based on status. 2801541Srgrimes * Should be only called from rpm_suspend() and rpm_resume() path. 2811541Srgrimes */ 28293593Sjhbvoid dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable) 28325201Swollman{ 2841541Srgrimes struct wake_irq *wirq = dev->power.wakeirq; 2851541Srgrimes 28641575Seivind if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK)) 2871541Srgrimes return; 28820407Swollman 289111119Simp if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) 29020407Swollman return; 2911541Srgrimes 29215092Sdg if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) { 29315092Sdg wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED; 29415092Sdg disable_irq_nosync(wirq->irq); 29515092Sdg } 29615092Sdg} 29720407Swollman 298108033Shsu/** 29920407Swollman * dev_pm_enable_wake_irq_complete - enable wake IRQ not enabled before 300108033Shsu * @dev: Device using the wake IRQ 30120407Swollman * 30220407Swollman * Enable wake IRQ conditionally based on status, mainly used if want to 30320407Swollman * enable wake IRQ after running ->runtime_suspend() which depends on 304108033Shsu * WAKE_IRQ_DEDICATED_REVERSE. 305108033Shsu * 306108033Shsu * Should be only called from rpm_suspend() path. 3071541Srgrimes */ 30885740Sdesvoid dev_pm_enable_wake_irq_complete(struct device *dev) 3091541Srgrimes{ 3101541Srgrimes struct wake_irq *wirq = dev->power.wakeirq; 3111541Srgrimes 3121541Srgrimes if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK)) 3131541Srgrimes return; 31415092Sdg 31587124Sbrian if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED && 3161541Srgrimes wirq->status & WAKE_IRQ_DEDICATED_REVERSE) { 3171541Srgrimes enable_irq(wirq->irq); 3181541Srgrimes wirq->status |= WAKE_IRQ_DEDICATED_ENABLED; 3191541Srgrimes } 32093593Sjhb} 32125201Swollman 3221541Srgrimes/** 3231541Srgrimes * dev_pm_arm_wake_irq - Arm device wake-up 3241541Srgrimes * @wirq: Device wake-up interrupt 3251541Srgrimes * 3261541Srgrimes * Sets up the wake-up event conditionally based on the 3271541Srgrimes * device_may_wake(). 3281541Srgrimes */ 3291541Srgrimesvoid dev_pm_arm_wake_irq(struct wake_irq *wirq) 3301541Srgrimes{ 3311541Srgrimes if (!wirq) 3321541Srgrimes return; 3331541Srgrimes 3341541Srgrimes if (device_may_wakeup(wirq->dev)) { 3351541Srgrimes if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && 33687124Sbrian !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED)) 3371541Srgrimes enable_irq(wirq->irq); 3381541Srgrimes 3391541Srgrimes enable_irq_wake(wirq->irq); 3401541Srgrimes } 3411541Srgrimes} 34287124Sbrian 3431541Srgrimes/** 3441541Srgrimes * dev_pm_disarm_wake_irq - Disarm device wake-up 3451541Srgrimes * @wirq: Device wake-up interrupt 3461541Srgrimes * 3471541Srgrimes * Clears up the wake-up event conditionally based on the 34887124Sbrian * device_may_wake(). 3491541Srgrimes */ 3501541Srgrimesvoid dev_pm_disarm_wake_irq(struct wake_irq *wirq) 3511541Srgrimes{ 35287124Sbrian if (!wirq) 3531541Srgrimes return; 3541541Srgrimes 3551541Srgrimes if (device_may_wakeup(wirq->dev)) { 3561541Srgrimes disable_irq_wake(wirq->irq); 3571541Srgrimes 3581541Srgrimes if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && 3591541Srgrimes !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED)) 3601541Srgrimes disable_irq_nosync(wirq->irq); 3611541Srgrimes } 3621541Srgrimes} 3631541Srgrimes