// SPDX-License-Identifier: GPL-2.01/* Device wakeirq helper functions */2#include <linux/device.h>3#include <linux/interrupt.h>4#include <linux/irq.h>5#include <linux/slab.h>6#include <linux/pm_runtime.h>7#include <linux/pm_wakeirq.h>89#include "power.h"1011/**12* dev_pm_attach_wake_irq - Attach device interrupt as a wake IRQ13* @dev: Device entry14* @wirq: Wake irq specific data15*16* Internal function to attach a dedicated wake-up interrupt as a wake IRQ.17*/18static int dev_pm_attach_wake_irq(struct device *dev, struct wake_irq *wirq)19{20unsigned long flags;2122if (!dev || !wirq)23return -EINVAL;2425spin_lock_irqsave(&dev->power.lock, flags);26if (dev_WARN_ONCE(dev, dev->power.wakeirq,27"wake irq already initialized\n")) {28spin_unlock_irqrestore(&dev->power.lock, flags);29return -EEXIST;30}3132dev->power.wakeirq = wirq;33device_wakeup_attach_irq(dev, wirq);3435spin_unlock_irqrestore(&dev->power.lock, flags);36return 0;37}3839/**40* dev_pm_set_wake_irq - Attach device IO interrupt as wake IRQ41* @dev: Device entry42* @irq: Device IO interrupt43*44* Attach a device IO interrupt as a wake IRQ. The wake IRQ gets45* automatically configured for wake-up from suspend based46* on the device specific sysfs wakeup entry. Typically called47* during driver probe after calling device_init_wakeup().48*/49int dev_pm_set_wake_irq(struct device *dev, int irq)50{51struct wake_irq *wirq;52int err;5354if (irq < 0)55return -EINVAL;5657wirq = kzalloc(sizeof(*wirq), GFP_KERNEL);58if (!wirq)59return -ENOMEM;6061wirq->dev = dev;62wirq->irq = irq;6364err = dev_pm_attach_wake_irq(dev, wirq);65if (err)66kfree(wirq);6768return err;69}70EXPORT_SYMBOL_GPL(dev_pm_set_wake_irq);7172/**73* dev_pm_clear_wake_irq - Detach a device IO interrupt wake IRQ74* @dev: Device entry75*76* Detach a device wake IRQ and free resources.77*78* Note that it's OK for drivers to call this without calling79* dev_pm_set_wake_irq() as all the driver instances may not have80* a wake IRQ configured. This avoid adding wake IRQ specific81* checks into the drivers.82*/83void dev_pm_clear_wake_irq(struct device *dev)84{85struct wake_irq *wirq;86unsigned long flags;8788spin_lock_irqsave(&dev->power.lock, flags);89wirq = dev->power.wakeirq;90if (!wirq) {91spin_unlock_irqrestore(&dev->power.lock, flags);92return;93}9495device_wakeup_detach_irq(dev);96dev->power.wakeirq = NULL;97spin_unlock_irqrestore(&dev->power.lock, flags);9899if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED) {100free_irq(wirq->irq, wirq);101wirq->status &= ~WAKE_IRQ_DEDICATED_MASK;102}103kfree(wirq->name);104kfree(wirq);105}106EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq);107108static void devm_pm_clear_wake_irq(void *dev)109{110dev_pm_clear_wake_irq(dev);111}112113/**114* devm_pm_set_wake_irq - device-managed variant of dev_pm_set_wake_irq115* @dev: Device entry116* @irq: Device IO interrupt117*118*119* Attach a device IO interrupt as a wake IRQ, same with dev_pm_set_wake_irq,120* but the device will be auto clear wake capability on driver detach.121*/122int devm_pm_set_wake_irq(struct device *dev, int irq)123{124int ret;125126ret = dev_pm_set_wake_irq(dev, irq);127if (ret)128return ret;129130return devm_add_action_or_reset(dev, devm_pm_clear_wake_irq, dev);131}132EXPORT_SYMBOL_GPL(devm_pm_set_wake_irq);133134/**135* handle_threaded_wake_irq - Handler for dedicated wake-up interrupts136* @irq: Device specific dedicated wake-up interrupt137* @_wirq: Wake IRQ data138*139* Some devices have a separate wake-up interrupt in addition to the140* device IO interrupt. The wake-up interrupt signals that a device141* should be woken up from it's idle state. This handler uses device142* specific pm_runtime functions to wake the device, and then it's143* up to the device to do whatever it needs to. Note that as the144* device may need to restore context and start up regulators, we145* use a threaded IRQ.146*147* Also note that we are not resending the lost device interrupts.148* We assume that the wake-up interrupt just needs to wake-up the149* device, and then device's pm_runtime_resume() can deal with the150* situation.151*/152static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq)153{154struct wake_irq *wirq = _wirq;155int res;156157/* Maybe abort suspend? */158if (irqd_is_wakeup_set(irq_get_irq_data(irq))) {159pm_wakeup_event(wirq->dev, 0);160161return IRQ_HANDLED;162}163164/* We don't want RPM_ASYNC or RPM_NOWAIT here */165res = pm_runtime_resume(wirq->dev);166if (res < 0)167dev_warn(wirq->dev,168"wake IRQ with no resume: %i\n", res);169170return IRQ_HANDLED;171}172173static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag)174{175struct wake_irq *wirq;176int err;177178if (irq < 0)179return -EINVAL;180181wirq = kzalloc(sizeof(*wirq), GFP_KERNEL);182if (!wirq)183return -ENOMEM;184185wirq->name = kasprintf(GFP_KERNEL, "%s:wakeup", dev_name(dev));186if (!wirq->name) {187err = -ENOMEM;188goto err_free;189}190191wirq->dev = dev;192wirq->irq = irq;193194/* Prevent deferred spurious wakeirqs with disable_irq_nosync() */195irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);196197/*198* Consumer device may need to power up and restore state199* so we use a threaded irq.200*/201err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq,202IRQF_ONESHOT | IRQF_NO_AUTOEN,203wirq->name, wirq);204if (err)205goto err_free_name;206207err = dev_pm_attach_wake_irq(dev, wirq);208if (err)209goto err_free_irq;210211wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED | flag;212213return err;214215err_free_irq:216free_irq(irq, wirq);217err_free_name:218kfree(wirq->name);219err_free:220kfree(wirq);221222return err;223}224225/**226* dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt227* @dev: Device entry228* @irq: Device wake-up interrupt229*230* Unless your hardware has separate wake-up interrupts in addition231* to the device IO interrupts, you don't need this.232*233* Sets up a threaded interrupt handler for a device that has234* a dedicated wake-up interrupt in addition to the device IO235* interrupt.236*/237int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)238{239return __dev_pm_set_dedicated_wake_irq(dev, irq, 0);240}241EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);242243/**244* dev_pm_set_dedicated_wake_irq_reverse - Request a dedicated wake-up interrupt245* with reverse enable ordering246* @dev: Device entry247* @irq: Device wake-up interrupt248*249* Unless your hardware has separate wake-up interrupts in addition250* to the device IO interrupts, you don't need this.251*252* Sets up a threaded interrupt handler for a device that has a dedicated253* wake-up interrupt in addition to the device IO interrupt. It sets254* the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend()255* to enable dedicated wake-up interrupt after running the runtime suspend256* callback for @dev.257*/258int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)259{260return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE);261}262EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse);263264/**265* dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt266* @dev: Device267* @can_change_status: Can change wake-up interrupt status268*269* Enables wakeirq conditionally. We need to enable wake-up interrupt270* lazily on the first rpm_suspend(). This is needed as the consumer device271* starts in RPM_SUSPENDED state, and the first pm_runtime_get() would272* otherwise try to disable already disabled wakeirq. The wake-up interrupt273* starts disabled with IRQ_NOAUTOEN set.274*275* Should be only called from rpm_suspend() and rpm_resume() path.276* Caller must hold &dev->power.lock to change wirq->status277*/278void dev_pm_enable_wake_irq_check(struct device *dev,279bool can_change_status)280{281struct wake_irq *wirq = dev->power.wakeirq;282283if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))284return;285286if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) {287goto enable;288} else if (can_change_status) {289wirq->status |= WAKE_IRQ_DEDICATED_MANAGED;290goto enable;291}292293return;294295enable:296if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) {297enable_irq(wirq->irq);298wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;299}300}301302/**303* dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt304* @dev: Device305* @cond_disable: if set, also check WAKE_IRQ_DEDICATED_REVERSE306*307* Disables wake-up interrupt conditionally based on status.308* Should be only called from rpm_suspend() and rpm_resume() path.309*/310void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable)311{312struct wake_irq *wirq = dev->power.wakeirq;313314if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))315return;316317if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE))318return;319320if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) {321wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED;322disable_irq_nosync(wirq->irq);323}324}325326/**327* dev_pm_enable_wake_irq_complete - enable wake IRQ not enabled before328* @dev: Device using the wake IRQ329*330* Enable wake IRQ conditionally based on status, mainly used if want to331* enable wake IRQ after running ->runtime_suspend() which depends on332* WAKE_IRQ_DEDICATED_REVERSE.333*334* Should be only called from rpm_suspend() path.335*/336void dev_pm_enable_wake_irq_complete(struct device *dev)337{338struct wake_irq *wirq = dev->power.wakeirq;339340if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))341return;342343if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED &&344wirq->status & WAKE_IRQ_DEDICATED_REVERSE) {345enable_irq(wirq->irq);346wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;347}348}349350/**351* dev_pm_arm_wake_irq - Arm device wake-up352* @wirq: Device wake-up interrupt353*354* Sets up the wake-up event conditionally based on the355* device_may_wake().356*/357void dev_pm_arm_wake_irq(struct wake_irq *wirq)358{359if (!wirq)360return;361362if (device_may_wakeup(wirq->dev)) {363if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&364!(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))365enable_irq(wirq->irq);366367enable_irq_wake(wirq->irq);368}369}370371/**372* dev_pm_disarm_wake_irq - Disarm device wake-up373* @wirq: Device wake-up interrupt374*375* Clears up the wake-up event conditionally based on the376* device_may_wake().377*/378void dev_pm_disarm_wake_irq(struct wake_irq *wirq)379{380if (!wirq)381return;382383if (device_may_wakeup(wirq->dev)) {384disable_irq_wake(wirq->irq);385386if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&387!(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))388disable_irq_nosync(wirq->irq);389}390}391392393