Commit 6e3b473e authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch irq/qcom-pdc-nowake-cleanup into irq/irqchip-next



* irq/qcom-pdc-nowake-cleanup:
  : Fix the QCOM PDC mishandling of the interrupt hierarchy by trimming
  : it when necessary.
  : Export irq_domain_disconnect_hierarchy as a consequence of it.
  irqchip/qcom-pdc: Trim unused levels of the interrupt hierarchy
  irqdomain: Export irq_domain_disconnect_hierarchy()

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents acdcfd94 9d4f24bf
Loading
Loading
Loading
Loading
+11 −57
Original line number Diff line number Diff line
@@ -53,26 +53,6 @@ static u32 pdc_reg_read(int reg, u32 i)
	return readl_relaxed(pdc_base + reg + i * sizeof(u32));
}

static int qcom_pdc_gic_get_irqchip_state(struct irq_data *d,
					  enum irqchip_irq_state which,
					  bool *state)
{
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return 0;

	return irq_chip_get_parent_state(d, which, state);
}

static int qcom_pdc_gic_set_irqchip_state(struct irq_data *d,
					  enum irqchip_irq_state which,
					  bool value)
{
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return 0;

	return irq_chip_set_parent_state(d, which, value);
}

static void pdc_enable_intr(struct irq_data *d, bool on)
{
	int pin_out = d->hwirq;
@@ -91,38 +71,16 @@ static void pdc_enable_intr(struct irq_data *d, bool on)

static void qcom_pdc_gic_disable(struct irq_data *d)
{
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return;

	pdc_enable_intr(d, false);
	irq_chip_disable_parent(d);
}

static void qcom_pdc_gic_enable(struct irq_data *d)
{
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return;

	pdc_enable_intr(d, true);
	irq_chip_enable_parent(d);
}

static void qcom_pdc_gic_mask(struct irq_data *d)
{
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return;

	irq_chip_mask_parent(d);
}

static void qcom_pdc_gic_unmask(struct irq_data *d)
{
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return;

	irq_chip_unmask_parent(d);
}

/*
 * GIC does not handle falling edge or active low. To allow falling edge and
 * active low interrupts to be handled at GIC, PDC has an inverter that inverts
@@ -159,14 +117,10 @@ enum pdc_irq_config_bits {
 */
static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
{
	int pin_out = d->hwirq;
	enum pdc_irq_config_bits pdc_type;
	enum pdc_irq_config_bits old_pdc_type;
	int ret;

	if (pin_out == GPIO_NO_WAKE_IRQ)
		return 0;

	switch (type) {
	case IRQ_TYPE_EDGE_RISING:
		pdc_type = PDC_EDGE_RISING;
@@ -191,8 +145,8 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
		return -EINVAL;
	}

	old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out);
	pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type);
	old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq);
	pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type);

	ret = irq_chip_set_type_parent(d, type);
	if (ret)
@@ -216,12 +170,12 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
static struct irq_chip qcom_pdc_gic_chip = {
	.name			= "PDC",
	.irq_eoi		= irq_chip_eoi_parent,
	.irq_mask		= qcom_pdc_gic_mask,
	.irq_unmask		= qcom_pdc_gic_unmask,
	.irq_mask		= irq_chip_mask_parent,
	.irq_unmask		= irq_chip_unmask_parent,
	.irq_disable		= qcom_pdc_gic_disable,
	.irq_enable		= qcom_pdc_gic_enable,
	.irq_get_irqchip_state	= qcom_pdc_gic_get_irqchip_state,
	.irq_set_irqchip_state	= qcom_pdc_gic_set_irqchip_state,
	.irq_get_irqchip_state	= irq_chip_get_parent_state,
	.irq_set_irqchip_state	= irq_chip_set_parent_state,
	.irq_retrigger		= irq_chip_retrigger_hierarchy,
	.irq_set_type		= qcom_pdc_gic_set_type,
	.flags			= IRQCHIP_MASK_ON_SUSPEND |
@@ -282,7 +236,7 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,

	parent_hwirq = get_parent_hwirq(hwirq);
	if (parent_hwirq == PDC_NO_PARENT_IRQ)
		return 0;
		return irq_domain_disconnect_hierarchy(domain->parent, virq);

	if (type & IRQ_TYPE_EDGE_BOTH)
		type = IRQ_TYPE_EDGE_RISING;
@@ -319,17 +273,17 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
	if (ret)
		return ret;

	if (hwirq == GPIO_NO_WAKE_IRQ)
		return irq_domain_disconnect_hierarchy(domain, virq);

	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
					    &qcom_pdc_gic_chip, NULL);
	if (ret)
		return ret;

	if (hwirq == GPIO_NO_WAKE_IRQ)
		return 0;

	parent_hwirq = get_parent_hwirq(hwirq);
	if (parent_hwirq == PDC_NO_PARENT_IRQ)
		return 0;
		return irq_domain_disconnect_hierarchy(domain->parent, virq);

	if (type & IRQ_TYPE_EDGE_BOTH)
		type = IRQ_TYPE_EDGE_RISING;
+1 −0
Original line number Diff line number Diff line
@@ -1215,6 +1215,7 @@ int irq_domain_disconnect_hierarchy(struct irq_domain *domain,
	irqd->chip = ERR_PTR(-ENOTCONN);
	return 0;
}
EXPORT_SYMBOL_GPL(irq_domain_disconnect_hierarchy);

static int irq_domain_trim_hierarchy(unsigned int virq)
{