Commit 04e8c5b2 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch 'irq/qcom-pdc-wakeup' into irq/irqchip-next



Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 9b64efa8 d7bc63fa
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -205,7 +205,8 @@ static struct irq_chip qcom_pdc_gic_chip = {
	.irq_set_type		= qcom_pdc_gic_set_type,
	.flags			= IRQCHIP_MASK_ON_SUSPEND |
				  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_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)
{
	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));
	if (n <= 0 || n % 3)
@@ -369,6 +371,14 @@ static int pdc_setup_pin_mapping(struct device_node *np)
						 &pdc_region[n].cnt);
		if (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;
+6 −5
Original line number Diff line number Diff line
@@ -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
	 * summary line to be wakeup capable at GIC.
	 */
	if (d->parent_data)
		irq_chip_set_wake_parent(d, on);

	irq_set_irq_wake(pctrl->irq, on);
	if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
		return irq_chip_set_wake_parent(d, on);

	return 0;
	return irq_set_irq_wake(pctrl->irq, on);
}

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_set_affinity = msm_gpio_irq_set_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);
	if (np) {
+30 −19
Original line number Diff line number Diff line
@@ -217,6 +217,8 @@ struct irq_data {
 *				  from actual interrupt context.
 * IRQD_AFFINITY_ON_ACTIVATE	- Affinity is set on activation. Don't call
 *				  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 {
	IRQD_TRIGGER_MASK		= 0xf,
@@ -242,6 +244,7 @@ enum {
	IRQD_MSI_NOMASK_QUIRK		= (1 << 27),
	IRQD_HANDLE_ENFORCE_IRQCTX	= (1 << 28),
	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)
@@ -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;
}

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)
{
	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_ONESHOT_SAFE:              One shot does not require mask/unmask
 * 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_ENABLE_WAKEUP_ON_SUSPEND:  Invokes __enable_irq()/__disable_irq() for wake irqs
 *                                    in the suspend path if they are in disabled state
 */
enum {
	IRQCHIP_SET_TYPE_MASKED			= (1 <<  0),
@@ -568,6 +578,7 @@ enum {
	IRQCHIP_EOI_THREADED			= (1 <<  6),
	IRQCHIP_SUPPORTS_LEVEL_MSI		= (1 <<  7),
	IRQCHIP_SUPPORTS_NMI			= (1 <<  8),
	IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND	= (1 <<  9),
};

#include <linux/irqdesc.h>
+3 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ static const struct irq_bit_descr irqchip_flags[] = {
	BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
	BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
	BIT_MASK_DESCR(IRQCHIP_SUPPORTS_NMI),
	BIT_MASK_DESCR(IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND),
};

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_HANDLE_ENFORCE_IRQCTX),

	BIT_MASK_DESCR(IRQD_IRQ_ENABLED_ON_SUSPEND),
};

static const struct irq_bit_descr irqdesc_states[] = {
+30 −4
Original line number Diff line number Diff line
@@ -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)
{
	unsigned long chipflags = irq_desc_get_chip(desc)->flags;
	struct irq_data *irqd = &desc->irq_data;

	if (!desc->action || irq_desc_is_chained(desc) ||
	    desc->no_suspend_depth)
		return false;

	if (irqd_is_wakeup_set(&desc->irq_data)) {
		irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
	if (irqd_is_wakeup_set(irqd)) {
		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
		 * 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
	 * IRQCHIP_MASK_ON_SUSPEND.
	 */
	if (irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
	if (chipflags & IRQCHIP_MASK_ON_SUSPEND)
		mask_irq(desc);
	return true;
}
@@ -137,7 +151,19 @@ EXPORT_SYMBOL_GPL(suspend_device_irqs);

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)
		goto resume;