0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/irq.h>
0009 #include <linux/module.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/suspend.h>
0012 #include <linux/syscore_ops.h>
0013
0014 #include "internals.h"
0015
0016 bool irq_pm_check_wakeup(struct irq_desc *desc)
0017 {
0018 if (irqd_is_wakeup_armed(&desc->irq_data)) {
0019 irqd_clear(&desc->irq_data, IRQD_WAKEUP_ARMED);
0020 desc->istate |= IRQS_SUSPENDED | IRQS_PENDING;
0021 desc->depth++;
0022 irq_disable(desc);
0023 pm_system_irq_wakeup(irq_desc_get_irq(desc));
0024 return true;
0025 }
0026 return false;
0027 }
0028
0029
0030
0031
0032
0033 void irq_pm_install_action(struct irq_desc *desc, struct irqaction *action)
0034 {
0035 desc->nr_actions++;
0036
0037 if (action->flags & IRQF_FORCE_RESUME)
0038 desc->force_resume_depth++;
0039
0040 WARN_ON_ONCE(desc->force_resume_depth &&
0041 desc->force_resume_depth != desc->nr_actions);
0042
0043 if (action->flags & IRQF_NO_SUSPEND)
0044 desc->no_suspend_depth++;
0045 else if (action->flags & IRQF_COND_SUSPEND)
0046 desc->cond_suspend_depth++;
0047
0048 WARN_ON_ONCE(desc->no_suspend_depth &&
0049 (desc->no_suspend_depth +
0050 desc->cond_suspend_depth) != desc->nr_actions);
0051 }
0052
0053
0054
0055
0056
0057 void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action)
0058 {
0059 desc->nr_actions--;
0060
0061 if (action->flags & IRQF_FORCE_RESUME)
0062 desc->force_resume_depth--;
0063
0064 if (action->flags & IRQF_NO_SUSPEND)
0065 desc->no_suspend_depth--;
0066 else if (action->flags & IRQF_COND_SUSPEND)
0067 desc->cond_suspend_depth--;
0068 }
0069
0070 static bool suspend_device_irq(struct irq_desc *desc)
0071 {
0072 unsigned long chipflags = irq_desc_get_chip(desc)->flags;
0073 struct irq_data *irqd = &desc->irq_data;
0074
0075 if (!desc->action || irq_desc_is_chained(desc) ||
0076 desc->no_suspend_depth)
0077 return false;
0078
0079 if (irqd_is_wakeup_set(irqd)) {
0080 irqd_set(irqd, IRQD_WAKEUP_ARMED);
0081
0082 if ((chipflags & IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND) &&
0083 irqd_irq_disabled(irqd)) {
0084
0085
0086
0087
0088
0089 __enable_irq(desc);
0090 irqd_set(irqd, IRQD_IRQ_ENABLED_ON_SUSPEND);
0091 }
0092
0093
0094
0095
0096
0097
0098 return true;
0099 }
0100
0101 desc->istate |= IRQS_SUSPENDED;
0102 __disable_irq(desc);
0103
0104
0105
0106
0107
0108
0109
0110 if (chipflags & IRQCHIP_MASK_ON_SUSPEND)
0111 mask_irq(desc);
0112 return true;
0113 }
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 void suspend_device_irqs(void)
0132 {
0133 struct irq_desc *desc;
0134 int irq;
0135
0136 for_each_irq_desc(irq, desc) {
0137 unsigned long flags;
0138 bool sync;
0139
0140 if (irq_settings_is_nested_thread(desc))
0141 continue;
0142 raw_spin_lock_irqsave(&desc->lock, flags);
0143 sync = suspend_device_irq(desc);
0144 raw_spin_unlock_irqrestore(&desc->lock, flags);
0145
0146 if (sync)
0147 synchronize_irq(irq);
0148 }
0149 }
0150
0151 static void resume_irq(struct irq_desc *desc)
0152 {
0153 struct irq_data *irqd = &desc->irq_data;
0154
0155 irqd_clear(irqd, IRQD_WAKEUP_ARMED);
0156
0157 if (irqd_is_enabled_on_suspend(irqd)) {
0158
0159
0160
0161
0162
0163 __disable_irq(desc);
0164 irqd_clear(irqd, IRQD_IRQ_ENABLED_ON_SUSPEND);
0165 }
0166
0167 if (desc->istate & IRQS_SUSPENDED)
0168 goto resume;
0169
0170
0171 if (!desc->force_resume_depth)
0172 return;
0173
0174
0175 desc->depth++;
0176 irq_state_set_disabled(desc);
0177 irq_state_set_masked(desc);
0178 resume:
0179 desc->istate &= ~IRQS_SUSPENDED;
0180 __enable_irq(desc);
0181 }
0182
0183 static void resume_irqs(bool want_early)
0184 {
0185 struct irq_desc *desc;
0186 int irq;
0187
0188 for_each_irq_desc(irq, desc) {
0189 unsigned long flags;
0190 bool is_early = desc->action &&
0191 desc->action->flags & IRQF_EARLY_RESUME;
0192
0193 if (!is_early && want_early)
0194 continue;
0195 if (irq_settings_is_nested_thread(desc))
0196 continue;
0197
0198 raw_spin_lock_irqsave(&desc->lock, flags);
0199 resume_irq(desc);
0200 raw_spin_unlock_irqrestore(&desc->lock, flags);
0201 }
0202 }
0203
0204
0205
0206
0207
0208 void rearm_wake_irq(unsigned int irq)
0209 {
0210 unsigned long flags;
0211 struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
0212
0213 if (!desc)
0214 return;
0215
0216 if (!(desc->istate & IRQS_SUSPENDED) ||
0217 !irqd_is_wakeup_set(&desc->irq_data))
0218 goto unlock;
0219
0220 desc->istate &= ~IRQS_SUSPENDED;
0221 irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
0222 __enable_irq(desc);
0223
0224 unlock:
0225 irq_put_desc_busunlock(desc, flags);
0226 }
0227
0228
0229
0230
0231
0232
0233 static void irq_pm_syscore_resume(void)
0234 {
0235 resume_irqs(true);
0236 }
0237
0238 static struct syscore_ops irq_pm_syscore_ops = {
0239 .resume = irq_pm_syscore_resume,
0240 };
0241
0242 static int __init irq_pm_init_ops(void)
0243 {
0244 register_syscore_ops(&irq_pm_syscore_ops);
0245 return 0;
0246 }
0247
0248 device_initcall(irq_pm_init_ops);
0249
0250
0251
0252
0253
0254
0255
0256
0257 void resume_device_irqs(void)
0258 {
0259 resume_irqs(false);
0260 }