1 /* 2 * wakeirq.c - Device wakeirq helper functions 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 9 * kind, whether express or implied; without even the implied warranty 10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14 #include <linux/device.h> 15 #include <linux/interrupt.h> 16 #include <linux/irq.h> 17 #include <linux/slab.h> 18 #include <linux/pm_runtime.h> 19 #include <linux/pm_wakeirq.h> 20 21 #include "power.h" 22 23 /** 24 * dev_pm_attach_wake_irq - Attach device interrupt as a wake IRQ 25 * @dev: Device entry 26 * @irq: Device wake-up capable interrupt 27 * @wirq: Wake irq specific data 28 * 29 * Internal function to attach either a device IO interrupt or a 30 * dedicated wake-up interrupt as a wake IRQ. 31 */ 32 static int dev_pm_attach_wake_irq(struct device *dev, int irq, 33 struct wake_irq *wirq) 34 { 35 unsigned long flags; 36 int err; 37 38 if (!dev || !wirq) 39 return -EINVAL; 40 41 spin_lock_irqsave(&dev->power.lock, flags); 42 if (dev_WARN_ONCE(dev, dev->power.wakeirq, 43 "wake irq already initialized\n")) { 44 spin_unlock_irqrestore(&dev->power.lock, flags); 45 return -EEXIST; 46 } 47 48 dev->power.wakeirq = wirq; 49 spin_unlock_irqrestore(&dev->power.lock, flags); 50 51 err = device_wakeup_attach_irq(dev, wirq); 52 if (err) 53 return err; 54 55 return 0; 56 } 57 58 /** 59 * dev_pm_set_wake_irq - Attach device IO interrupt as wake IRQ 60 * @dev: Device entry 61 * @irq: Device IO interrupt 62 * 63 * Attach a device IO interrupt as a wake IRQ. The wake IRQ gets 64 * automatically configured for wake-up from suspend based 65 * on the device specific sysfs wakeup entry. Typically called 66 * during driver probe after calling device_init_wakeup(). 67 */ 68 int dev_pm_set_wake_irq(struct device *dev, int irq) 69 { 70 struct wake_irq *wirq; 71 int err; 72 73 wirq = kzalloc(sizeof(*wirq), GFP_KERNEL); 74 if (!wirq) 75 return -ENOMEM; 76 77 wirq->dev = dev; 78 wirq->irq = irq; 79 80 err = dev_pm_attach_wake_irq(dev, irq, wirq); 81 if (err) 82 kfree(wirq); 83 84 return err; 85 } 86 EXPORT_SYMBOL_GPL(dev_pm_set_wake_irq); 87 88 /** 89 * dev_pm_clear_wake_irq - Detach a device IO interrupt wake IRQ 90 * @dev: Device entry 91 * 92 * Detach a device wake IRQ and free resources. 93 * 94 * Note that it's OK for drivers to call this without calling 95 * dev_pm_set_wake_irq() as all the driver instances may not have 96 * a wake IRQ configured. This avoid adding wake IRQ specific 97 * checks into the drivers. 98 */ 99 void dev_pm_clear_wake_irq(struct device *dev) 100 { 101 struct wake_irq *wirq = dev->power.wakeirq; 102 unsigned long flags; 103 104 if (!wirq) 105 return; 106 107 spin_lock_irqsave(&dev->power.lock, flags); 108 dev->power.wakeirq = NULL; 109 spin_unlock_irqrestore(&dev->power.lock, flags); 110 111 device_wakeup_detach_irq(dev); 112 if (wirq->dedicated_irq) 113 free_irq(wirq->irq, wirq); 114 kfree(wirq); 115 } 116 EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq); 117 118 /** 119 * handle_threaded_wake_irq - Handler for dedicated wake-up interrupts 120 * @irq: Device specific dedicated wake-up interrupt 121 * @_wirq: Wake IRQ data 122 * 123 * Some devices have a separate wake-up interrupt in addition to the 124 * device IO interrupt. The wake-up interrupt signals that a device 125 * should be woken up from it's idle state. This handler uses device 126 * specific pm_runtime functions to wake the device, and then it's 127 * up to the device to do whatever it needs to. Note that as the 128 * device may need to restore context and start up regulators, we 129 * use a threaded IRQ. 130 * 131 * Also note that we are not resending the lost device interrupts. 132 * We assume that the wake-up interrupt just needs to wake-up the 133 * device, and then device's pm_runtime_resume() can deal with the 134 * situation. 135 */ 136 static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq) 137 { 138 struct wake_irq *wirq = _wirq; 139 int res; 140 141 /* We don't want RPM_ASYNC or RPM_NOWAIT here */ 142 res = pm_runtime_resume(wirq->dev); 143 if (res < 0) 144 dev_warn(wirq->dev, 145 "wake IRQ with no resume: %i\n", res); 146 147 return IRQ_HANDLED; 148 } 149 150 /** 151 * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt 152 * @dev: Device entry 153 * @irq: Device wake-up interrupt 154 * 155 * Unless your hardware has separate wake-up interrupts in addition 156 * to the device IO interrupts, you don't need this. 157 * 158 * Sets up a threaded interrupt handler for a device that has 159 * a dedicated wake-up interrupt in addition to the device IO 160 * interrupt. 161 * 162 * The interrupt starts disabled, and needs to be managed for 163 * the device by the bus code or the device driver using 164 * dev_pm_enable_wake_irq() and dev_pm_disable_wake_irq() 165 * functions. 166 */ 167 int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) 168 { 169 struct wake_irq *wirq; 170 int err; 171 172 wirq = kzalloc(sizeof(*wirq), GFP_KERNEL); 173 if (!wirq) 174 return -ENOMEM; 175 176 wirq->dev = dev; 177 wirq->irq = irq; 178 wirq->dedicated_irq = true; 179 irq_set_status_flags(irq, IRQ_NOAUTOEN); 180 181 /* 182 * Consumer device may need to power up and restore state 183 * so we use a threaded irq. 184 */ 185 err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq, 186 IRQF_ONESHOT, dev_name(dev), wirq); 187 if (err) 188 goto err_free; 189 190 err = dev_pm_attach_wake_irq(dev, irq, wirq); 191 if (err) 192 goto err_free_irq; 193 194 return err; 195 196 err_free_irq: 197 free_irq(irq, wirq); 198 err_free: 199 kfree(wirq); 200 201 return err; 202 } 203 EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq); 204 205 /** 206 * dev_pm_enable_wake_irq - Enable device wake-up interrupt 207 * @dev: Device 208 * 209 * Called from the bus code or the device driver for 210 * runtime_suspend() to enable the wake-up interrupt while 211 * the device is running. 212 * 213 * Note that for runtime_suspend()) the wake-up interrupts 214 * should be unconditionally enabled unlike for suspend() 215 * that is conditional. 216 */ 217 void dev_pm_enable_wake_irq(struct device *dev) 218 { 219 struct wake_irq *wirq = dev->power.wakeirq; 220 221 if (wirq && wirq->dedicated_irq) 222 enable_irq(wirq->irq); 223 } 224 EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq); 225 226 /** 227 * dev_pm_disable_wake_irq - Disable device wake-up interrupt 228 * @dev: Device 229 * 230 * Called from the bus code or the device driver for 231 * runtime_resume() to disable the wake-up interrupt while 232 * the device is running. 233 */ 234 void dev_pm_disable_wake_irq(struct device *dev) 235 { 236 struct wake_irq *wirq = dev->power.wakeirq; 237 238 if (wirq && wirq->dedicated_irq) 239 disable_irq_nosync(wirq->irq); 240 } 241 EXPORT_SYMBOL_GPL(dev_pm_disable_wake_irq); 242 243 /** 244 * dev_pm_arm_wake_irq - Arm device wake-up 245 * @wirq: Device wake-up interrupt 246 * 247 * Sets up the wake-up event conditionally based on the 248 * device_may_wake(). 249 */ 250 void dev_pm_arm_wake_irq(struct wake_irq *wirq) 251 { 252 if (!wirq) 253 return; 254 255 if (device_may_wakeup(wirq->dev)) 256 enable_irq_wake(wirq->irq); 257 } 258 259 /** 260 * dev_pm_disarm_wake_irq - Disarm device wake-up 261 * @wirq: Device wake-up interrupt 262 * 263 * Clears up the wake-up event conditionally based on the 264 * device_may_wake(). 265 */ 266 void dev_pm_disarm_wake_irq(struct wake_irq *wirq) 267 { 268 if (!wirq) 269 return; 270 271 if (device_may_wakeup(wirq->dev)) 272 disable_irq_wake(wirq->irq); 273 } 274