Merge branch 'irq/qcom-pdc-wakeup' into irq/irqchip-next
Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
commit
04e8c5b2fa
|
@ -205,7 +205,8 @@ static struct irq_chip qcom_pdc_gic_chip = {
|
||||||
.irq_set_type = qcom_pdc_gic_set_type,
|
.irq_set_type = qcom_pdc_gic_set_type,
|
||||||
.flags = IRQCHIP_MASK_ON_SUSPEND |
|
.flags = IRQCHIP_MASK_ON_SUSPEND |
|
||||||
IRQCHIP_SET_TYPE_MASKED |
|
IRQCHIP_SET_TYPE_MASKED |
|
||||||
IRQCHIP_SKIP_SET_WAKE,
|
IRQCHIP_SKIP_SET_WAKE |
|
||||||
|
IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,
|
||||||
.irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
|
.irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
|
||||||
.irq_set_affinity = irq_chip_set_affinity_parent,
|
.irq_set_affinity = irq_chip_set_affinity_parent,
|
||||||
};
|
};
|
||||||
|
@ -340,7 +341,8 @@ static const struct irq_domain_ops qcom_pdc_gpio_ops = {
|
||||||
|
|
||||||
static int pdc_setup_pin_mapping(struct device_node *np)
|
static int pdc_setup_pin_mapping(struct device_node *np)
|
||||||
{
|
{
|
||||||
int ret, n;
|
int ret, n, i;
|
||||||
|
u32 irq_index, reg_index, val;
|
||||||
|
|
||||||
n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32));
|
n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32));
|
||||||
if (n <= 0 || n % 3)
|
if (n <= 0 || n % 3)
|
||||||
|
@ -369,6 +371,14 @@ static int pdc_setup_pin_mapping(struct device_node *np)
|
||||||
&pdc_region[n].cnt);
|
&pdc_region[n].cnt);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
for (i = 0; i < pdc_region[n].cnt; i++) {
|
||||||
|
reg_index = (i + pdc_region[n].pin_base) >> 5;
|
||||||
|
irq_index = (i + pdc_region[n].pin_base) & 0x1f;
|
||||||
|
val = pdc_reg_read(IRQ_ENABLE_BANK, reg_index);
|
||||||
|
val &= ~BIT(irq_index);
|
||||||
|
pdc_reg_write(IRQ_ENABLE_BANK, reg_index, val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1077,12 +1077,10 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||||
* when TLMM is powered on. To allow that, enable the GPIO
|
* when TLMM is powered on. To allow that, enable the GPIO
|
||||||
* summary line to be wakeup capable at GIC.
|
* summary line to be wakeup capable at GIC.
|
||||||
*/
|
*/
|
||||||
if (d->parent_data)
|
if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
|
||||||
irq_chip_set_wake_parent(d, on);
|
return irq_chip_set_wake_parent(d, on);
|
||||||
|
|
||||||
irq_set_irq_wake(pctrl->irq, on);
|
return irq_set_irq_wake(pctrl->irq, on);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int msm_gpio_irq_reqres(struct irq_data *d)
|
static int msm_gpio_irq_reqres(struct irq_data *d)
|
||||||
|
@ -1243,6 +1241,9 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
|
||||||
pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres;
|
pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres;
|
||||||
pctrl->irq_chip.irq_set_affinity = msm_gpio_irq_set_affinity;
|
pctrl->irq_chip.irq_set_affinity = msm_gpio_irq_set_affinity;
|
||||||
pctrl->irq_chip.irq_set_vcpu_affinity = msm_gpio_irq_set_vcpu_affinity;
|
pctrl->irq_chip.irq_set_vcpu_affinity = msm_gpio_irq_set_vcpu_affinity;
|
||||||
|
pctrl->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND |
|
||||||
|
IRQCHIP_SET_TYPE_MASKED |
|
||||||
|
IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND;
|
||||||
|
|
||||||
np = of_parse_phandle(pctrl->dev->of_node, "wakeup-parent", 0);
|
np = of_parse_phandle(pctrl->dev->of_node, "wakeup-parent", 0);
|
||||||
if (np) {
|
if (np) {
|
||||||
|
|
|
@ -217,6 +217,8 @@ struct irq_data {
|
||||||
* from actual interrupt context.
|
* from actual interrupt context.
|
||||||
* IRQD_AFFINITY_ON_ACTIVATE - Affinity is set on activation. Don't call
|
* IRQD_AFFINITY_ON_ACTIVATE - Affinity is set on activation. Don't call
|
||||||
* irq_chip::irq_set_affinity() when deactivated.
|
* irq_chip::irq_set_affinity() when deactivated.
|
||||||
|
* IRQD_IRQ_ENABLED_ON_SUSPEND - Interrupt is enabled on suspend by irq pm if
|
||||||
|
* irqchip have flag IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND set.
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
IRQD_TRIGGER_MASK = 0xf,
|
IRQD_TRIGGER_MASK = 0xf,
|
||||||
|
@ -242,6 +244,7 @@ enum {
|
||||||
IRQD_MSI_NOMASK_QUIRK = (1 << 27),
|
IRQD_MSI_NOMASK_QUIRK = (1 << 27),
|
||||||
IRQD_HANDLE_ENFORCE_IRQCTX = (1 << 28),
|
IRQD_HANDLE_ENFORCE_IRQCTX = (1 << 28),
|
||||||
IRQD_AFFINITY_ON_ACTIVATE = (1 << 29),
|
IRQD_AFFINITY_ON_ACTIVATE = (1 << 29),
|
||||||
|
IRQD_IRQ_ENABLED_ON_SUSPEND = (1 << 30),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
|
#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)
|
||||||
return __irqd_to_state(d) & IRQD_HANDLE_ENFORCE_IRQCTX;
|
return __irqd_to_state(d) & IRQD_HANDLE_ENFORCE_IRQCTX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool irqd_is_enabled_on_suspend(struct irq_data *d)
|
||||||
|
{
|
||||||
|
return __irqd_to_state(d) & IRQD_IRQ_ENABLED_ON_SUSPEND;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool irqd_is_wakeup_set(struct irq_data *d)
|
static inline bool irqd_is_wakeup_set(struct irq_data *d)
|
||||||
{
|
{
|
||||||
return __irqd_to_state(d) & IRQD_WAKEUP_STATE;
|
return __irqd_to_state(d) & IRQD_WAKEUP_STATE;
|
||||||
|
@ -555,8 +563,10 @@ struct irq_chip {
|
||||||
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
|
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
|
||||||
* IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
|
* IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
|
||||||
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
|
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
|
||||||
* IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs
|
* IRQCHIP_SUPPORTS_LEVEL_MSI: Chip can provide two doorbells for Level MSIs
|
||||||
* IRQCHIP_SUPPORTS_NMI: Chip can deliver NMIs, only for root irqchips
|
* IRQCHIP_SUPPORTS_NMI: Chip can deliver NMIs, only for root irqchips
|
||||||
|
* IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND: Invokes __enable_irq()/__disable_irq() for wake irqs
|
||||||
|
* in the suspend path if they are in disabled state
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
IRQCHIP_SET_TYPE_MASKED = (1 << 0),
|
IRQCHIP_SET_TYPE_MASKED = (1 << 0),
|
||||||
|
@ -568,6 +578,7 @@ enum {
|
||||||
IRQCHIP_EOI_THREADED = (1 << 6),
|
IRQCHIP_EOI_THREADED = (1 << 6),
|
||||||
IRQCHIP_SUPPORTS_LEVEL_MSI = (1 << 7),
|
IRQCHIP_SUPPORTS_LEVEL_MSI = (1 << 7),
|
||||||
IRQCHIP_SUPPORTS_NMI = (1 << 8),
|
IRQCHIP_SUPPORTS_NMI = (1 << 8),
|
||||||
|
IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = (1 << 9),
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <linux/irqdesc.h>
|
#include <linux/irqdesc.h>
|
||||||
|
|
|
@ -57,6 +57,7 @@ static const struct irq_bit_descr irqchip_flags[] = {
|
||||||
BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
|
BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
|
||||||
BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
|
BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
|
||||||
BIT_MASK_DESCR(IRQCHIP_SUPPORTS_NMI),
|
BIT_MASK_DESCR(IRQCHIP_SUPPORTS_NMI),
|
||||||
|
BIT_MASK_DESCR(IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND),
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -125,6 +126,8 @@ static const struct irq_bit_descr irqdata_states[] = {
|
||||||
BIT_MASK_DESCR(IRQD_DEFAULT_TRIGGER_SET),
|
BIT_MASK_DESCR(IRQD_DEFAULT_TRIGGER_SET),
|
||||||
|
|
||||||
BIT_MASK_DESCR(IRQD_HANDLE_ENFORCE_IRQCTX),
|
BIT_MASK_DESCR(IRQD_HANDLE_ENFORCE_IRQCTX),
|
||||||
|
|
||||||
|
BIT_MASK_DESCR(IRQD_IRQ_ENABLED_ON_SUSPEND),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct irq_bit_descr irqdesc_states[] = {
|
static const struct irq_bit_descr irqdesc_states[] = {
|
||||||
|
|
|
@ -69,12 +69,26 @@ void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action)
|
||||||
|
|
||||||
static bool suspend_device_irq(struct irq_desc *desc)
|
static bool suspend_device_irq(struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
|
unsigned long chipflags = irq_desc_get_chip(desc)->flags;
|
||||||
|
struct irq_data *irqd = &desc->irq_data;
|
||||||
|
|
||||||
if (!desc->action || irq_desc_is_chained(desc) ||
|
if (!desc->action || irq_desc_is_chained(desc) ||
|
||||||
desc->no_suspend_depth)
|
desc->no_suspend_depth)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (irqd_is_wakeup_set(&desc->irq_data)) {
|
if (irqd_is_wakeup_set(irqd)) {
|
||||||
irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
|
irqd_set(irqd, IRQD_WAKEUP_ARMED);
|
||||||
|
|
||||||
|
if ((chipflags & IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND) &&
|
||||||
|
irqd_irq_disabled(irqd)) {
|
||||||
|
/*
|
||||||
|
* Interrupt marked for wakeup is in disabled state.
|
||||||
|
* Enable interrupt here to unmask/enable in irqchip
|
||||||
|
* to be able to resume with such interrupts.
|
||||||
|
*/
|
||||||
|
__enable_irq(desc);
|
||||||
|
irqd_set(irqd, IRQD_IRQ_ENABLED_ON_SUSPEND);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* We return true here to force the caller to issue
|
* We return true here to force the caller to issue
|
||||||
* synchronize_irq(). We need to make sure that the
|
* synchronize_irq(). We need to make sure that the
|
||||||
|
@ -93,7 +107,7 @@ static bool suspend_device_irq(struct irq_desc *desc)
|
||||||
* chip level. The chip implementation indicates that with
|
* chip level. The chip implementation indicates that with
|
||||||
* IRQCHIP_MASK_ON_SUSPEND.
|
* IRQCHIP_MASK_ON_SUSPEND.
|
||||||
*/
|
*/
|
||||||
if (irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
|
if (chipflags & IRQCHIP_MASK_ON_SUSPEND)
|
||||||
mask_irq(desc);
|
mask_irq(desc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +151,19 @@ EXPORT_SYMBOL_GPL(suspend_device_irqs);
|
||||||
|
|
||||||
static void resume_irq(struct irq_desc *desc)
|
static void resume_irq(struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
irqd_clear(&desc->irq_data, IRQD_WAKEUP_ARMED);
|
struct irq_data *irqd = &desc->irq_data;
|
||||||
|
|
||||||
|
irqd_clear(irqd, IRQD_WAKEUP_ARMED);
|
||||||
|
|
||||||
|
if (irqd_is_enabled_on_suspend(irqd)) {
|
||||||
|
/*
|
||||||
|
* Interrupt marked for wakeup was enabled during suspend
|
||||||
|
* entry. Disable such interrupts to restore them back to
|
||||||
|
* original state.
|
||||||
|
*/
|
||||||
|
__disable_irq(desc);
|
||||||
|
irqd_clear(irqd, IRQD_IRQ_ENABLED_ON_SUSPEND);
|
||||||
|
}
|
||||||
|
|
||||||
if (desc->istate & IRQS_SUSPENDED)
|
if (desc->istate & IRQS_SUSPENDED)
|
||||||
goto resume;
|
goto resume;
|
||||||
|
|
Loading…
Reference in New Issue