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