Skip to content

Commit 04e8c5b

Browse files
author
Marc Zyngier
committed
Merge branch 'irq/qcom-pdc-wakeup' into irq/irqchip-next
Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents 9b64efa + d7bc63f commit 04e8c5b

5 files changed

Lines changed: 81 additions & 30 deletions

File tree

drivers/irqchip/qcom-pdc.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ static struct irq_chip qcom_pdc_gic_chip = {
205205
.irq_set_type = qcom_pdc_gic_set_type,
206206
.flags = IRQCHIP_MASK_ON_SUSPEND |
207207
IRQCHIP_SET_TYPE_MASKED |
208-
IRQCHIP_SKIP_SET_WAKE,
208+
IRQCHIP_SKIP_SET_WAKE |
209+
IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,
209210
.irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
210211
.irq_set_affinity = irq_chip_set_affinity_parent,
211212
};
@@ -340,7 +341,8 @@ static const struct irq_domain_ops qcom_pdc_gpio_ops = {
340341

341342
static int pdc_setup_pin_mapping(struct device_node *np)
342343
{
343-
int ret, n;
344+
int ret, n, i;
345+
u32 irq_index, reg_index, val;
344346

345347
n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32));
346348
if (n <= 0 || n % 3)
@@ -369,6 +371,14 @@ static int pdc_setup_pin_mapping(struct device_node *np)
369371
&pdc_region[n].cnt);
370372
if (ret)
371373
return ret;
374+
375+
for (i = 0; i < pdc_region[n].cnt; i++) {
376+
reg_index = (i + pdc_region[n].pin_base) >> 5;
377+
irq_index = (i + pdc_region[n].pin_base) & 0x1f;
378+
val = pdc_reg_read(IRQ_ENABLE_BANK, reg_index);
379+
val &= ~BIT(irq_index);
380+
pdc_reg_write(IRQ_ENABLE_BANK, reg_index, val);
381+
}
372382
}
373383

374384
return 0;

drivers/pinctrl/qcom/pinctrl-msm.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,12 +1077,10 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
10771077
* when TLMM is powered on. To allow that, enable the GPIO
10781078
* summary line to be wakeup capable at GIC.
10791079
*/
1080-
if (d->parent_data)
1081-
irq_chip_set_wake_parent(d, on);
1082-
1083-
irq_set_irq_wake(pctrl->irq, on);
1080+
if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
1081+
return irq_chip_set_wake_parent(d, on);
10841082

1085-
return 0;
1083+
return irq_set_irq_wake(pctrl->irq, on);
10861084
}
10871085

10881086
static int msm_gpio_irq_reqres(struct irq_data *d)
@@ -1243,6 +1241,9 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
12431241
pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres;
12441242
pctrl->irq_chip.irq_set_affinity = msm_gpio_irq_set_affinity;
12451243
pctrl->irq_chip.irq_set_vcpu_affinity = msm_gpio_irq_set_vcpu_affinity;
1244+
pctrl->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND |
1245+
IRQCHIP_SET_TYPE_MASKED |
1246+
IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND;
12461247

12471248
np = of_parse_phandle(pctrl->dev->of_node, "wakeup-parent", 0);
12481249
if (np) {

include/linux/irq.h

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ struct irq_data {
217217
* from actual interrupt context.
218218
* IRQD_AFFINITY_ON_ACTIVATE - Affinity is set on activation. Don't call
219219
* irq_chip::irq_set_affinity() when deactivated.
220+
* IRQD_IRQ_ENABLED_ON_SUSPEND - Interrupt is enabled on suspend by irq pm if
221+
* irqchip have flag IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND set.
220222
*/
221223
enum {
222224
IRQD_TRIGGER_MASK = 0xf,
@@ -242,6 +244,7 @@ enum {
242244
IRQD_MSI_NOMASK_QUIRK = (1 << 27),
243245
IRQD_HANDLE_ENFORCE_IRQCTX = (1 << 28),
244246
IRQD_AFFINITY_ON_ACTIVATE = (1 << 29),
247+
IRQD_IRQ_ENABLED_ON_SUSPEND = (1 << 30),
245248
};
246249

247250
#define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
@@ -321,6 +324,11 @@ static inline bool irqd_is_handle_enforce_irqctx(struct irq_data *d)
321324
return __irqd_to_state(d) & IRQD_HANDLE_ENFORCE_IRQCTX;
322325
}
323326

327+
static inline bool irqd_is_enabled_on_suspend(struct irq_data *d)
328+
{
329+
return __irqd_to_state(d) & IRQD_IRQ_ENABLED_ON_SUSPEND;
330+
}
331+
324332
static inline bool irqd_is_wakeup_set(struct irq_data *d)
325333
{
326334
return __irqd_to_state(d) & IRQD_WAKEUP_STATE;
@@ -547,27 +555,30 @@ struct irq_chip {
547555
/*
548556
* irq_chip specific flags
549557
*
550-
* IRQCHIP_SET_TYPE_MASKED: Mask before calling chip.irq_set_type()
551-
* IRQCHIP_EOI_IF_HANDLED: Only issue irq_eoi() when irq was handled
552-
* IRQCHIP_MASK_ON_SUSPEND: Mask non wake irqs in the suspend path
553-
* IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks
554-
* when irq enabled
555-
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
556-
* IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
557-
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
558-
* IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs
559-
* IRQCHIP_SUPPORTS_NMI: Chip can deliver NMIs, only for root irqchips
558+
* IRQCHIP_SET_TYPE_MASKED: Mask before calling chip.irq_set_type()
559+
* IRQCHIP_EOI_IF_HANDLED: Only issue irq_eoi() when irq was handled
560+
* IRQCHIP_MASK_ON_SUSPEND: Mask non wake irqs in the suspend path
561+
* IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks
562+
* when irq enabled
563+
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
564+
* IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
565+
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
566+
* IRQCHIP_SUPPORTS_LEVEL_MSI: Chip can provide two doorbells for Level MSIs
567+
* IRQCHIP_SUPPORTS_NMI: Chip can deliver NMIs, only for root irqchips
568+
* IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND: Invokes __enable_irq()/__disable_irq() for wake irqs
569+
* in the suspend path if they are in disabled state
560570
*/
561571
enum {
562-
IRQCHIP_SET_TYPE_MASKED = (1 << 0),
563-
IRQCHIP_EOI_IF_HANDLED = (1 << 1),
564-
IRQCHIP_MASK_ON_SUSPEND = (1 << 2),
565-
IRQCHIP_ONOFFLINE_ENABLED = (1 << 3),
566-
IRQCHIP_SKIP_SET_WAKE = (1 << 4),
567-
IRQCHIP_ONESHOT_SAFE = (1 << 5),
568-
IRQCHIP_EOI_THREADED = (1 << 6),
569-
IRQCHIP_SUPPORTS_LEVEL_MSI = (1 << 7),
570-
IRQCHIP_SUPPORTS_NMI = (1 << 8),
572+
IRQCHIP_SET_TYPE_MASKED = (1 << 0),
573+
IRQCHIP_EOI_IF_HANDLED = (1 << 1),
574+
IRQCHIP_MASK_ON_SUSPEND = (1 << 2),
575+
IRQCHIP_ONOFFLINE_ENABLED = (1 << 3),
576+
IRQCHIP_SKIP_SET_WAKE = (1 << 4),
577+
IRQCHIP_ONESHOT_SAFE = (1 << 5),
578+
IRQCHIP_EOI_THREADED = (1 << 6),
579+
IRQCHIP_SUPPORTS_LEVEL_MSI = (1 << 7),
580+
IRQCHIP_SUPPORTS_NMI = (1 << 8),
581+
IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = (1 << 9),
571582
};
572583

573584
#include <linux/irqdesc.h>

kernel/irq/debugfs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ static const struct irq_bit_descr irqchip_flags[] = {
5757
BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
5858
BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
5959
BIT_MASK_DESCR(IRQCHIP_SUPPORTS_NMI),
60+
BIT_MASK_DESCR(IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND),
6061
};
6162

6263
static void
@@ -125,6 +126,8 @@ static const struct irq_bit_descr irqdata_states[] = {
125126
BIT_MASK_DESCR(IRQD_DEFAULT_TRIGGER_SET),
126127

127128
BIT_MASK_DESCR(IRQD_HANDLE_ENFORCE_IRQCTX),
129+
130+
BIT_MASK_DESCR(IRQD_IRQ_ENABLED_ON_SUSPEND),
128131
};
129132

130133
static const struct irq_bit_descr irqdesc_states[] = {

kernel/irq/pm.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,26 @@ void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action)
6969

7070
static bool suspend_device_irq(struct irq_desc *desc)
7171
{
72+
unsigned long chipflags = irq_desc_get_chip(desc)->flags;
73+
struct irq_data *irqd = &desc->irq_data;
74+
7275
if (!desc->action || irq_desc_is_chained(desc) ||
7376
desc->no_suspend_depth)
7477
return false;
7578

76-
if (irqd_is_wakeup_set(&desc->irq_data)) {
77-
irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
79+
if (irqd_is_wakeup_set(irqd)) {
80+
irqd_set(irqd, IRQD_WAKEUP_ARMED);
81+
82+
if ((chipflags & IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND) &&
83+
irqd_irq_disabled(irqd)) {
84+
/*
85+
* Interrupt marked for wakeup is in disabled state.
86+
* Enable interrupt here to unmask/enable in irqchip
87+
* to be able to resume with such interrupts.
88+
*/
89+
__enable_irq(desc);
90+
irqd_set(irqd, IRQD_IRQ_ENABLED_ON_SUSPEND);
91+
}
7892
/*
7993
* We return true here to force the caller to issue
8094
* synchronize_irq(). We need to make sure that the
@@ -93,7 +107,7 @@ static bool suspend_device_irq(struct irq_desc *desc)
93107
* chip level. The chip implementation indicates that with
94108
* IRQCHIP_MASK_ON_SUSPEND.
95109
*/
96-
if (irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
110+
if (chipflags & IRQCHIP_MASK_ON_SUSPEND)
97111
mask_irq(desc);
98112
return true;
99113
}
@@ -137,7 +151,19 @@ EXPORT_SYMBOL_GPL(suspend_device_irqs);
137151

138152
static void resume_irq(struct irq_desc *desc)
139153
{
140-
irqd_clear(&desc->irq_data, IRQD_WAKEUP_ARMED);
154+
struct irq_data *irqd = &desc->irq_data;
155+
156+
irqd_clear(irqd, IRQD_WAKEUP_ARMED);
157+
158+
if (irqd_is_enabled_on_suspend(irqd)) {
159+
/*
160+
* Interrupt marked for wakeup was enabled during suspend
161+
* entry. Disable such interrupts to restore them back to
162+
* original state.
163+
*/
164+
__disable_irq(desc);
165+
irqd_clear(irqd, IRQD_IRQ_ENABLED_ON_SUSPEND);
166+
}
141167

142168
if (desc->istate & IRQS_SUSPENDED)
143169
goto resume;

0 commit comments

Comments
 (0)