Commit 63ab33c0 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch irq/loongarch-acpi into irq/irqchip-next



* irq/loongarch-acpi:
  : .
  : More APCI fixes and improvements for the LoongArch architecture:
  :
  : - Work around trigger type for INTx interrupts described
  :   via ACPI (Jianmin Lv).
  :
  : - ACPI support got the HTVEC controller (Huacai Chen)
  :
  : - Suspend/resume across the board (Huacai Chen)
  :
  : - Fixes and random cleanups
  : .
  irqchip/loongarch: Adjust acpi_cascade_irqdomain_init() and sub-routines
  irqchip/loongson-pch-lpc: Add suspend/resume support
  irqchip/loongson-pch-pic: Add suspend/resume support
  irqchip/loongson-eiointc: Add suspend/resume support
  irqchip/loongson-htvec: Add suspend/resume support
  irqchip/loongson-htvec: Add ACPI init support
  irqchip/loongson-liointc: Support to set IRQ type for ACPI path
  irqchip/loongson-pch-pic: Support to set IRQ type for ACPI path
  irqchip/loongson-pch-pic: Fix translate callback for DT path
  ACPI / PCI: fix LPIC IRQ model default PCI IRQ polarity

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 247f34f7 3d12938d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ int liointc_acpi_init(struct irq_domain *parent,
int eiointc_acpi_init(struct irq_domain *parent,
					struct acpi_madt_eio_pic *acpi_eiointc);

struct irq_domain *htvec_acpi_init(struct irq_domain *parent,
int htvec_acpi_init(struct irq_domain *parent,
					struct acpi_madt_ht_pic *acpi_htvec);
int pch_lpc_acpi_init(struct irq_domain *parent,
					struct acpi_madt_lpc_pic *acpi_pchlpc);
+4 −2
Original line number Diff line number Diff line
@@ -387,13 +387,15 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
	u8 pin;
	int triggering = ACPI_LEVEL_SENSITIVE;
	/*
	 * On ARM systems with the GIC interrupt model, level interrupts
	 * On ARM systems with the GIC interrupt model, or LoongArch
	 * systems with the LPIC interrupt model, level interrupts
	 * are always polarity high by specification; PCI legacy
	 * IRQs lines are inverted before reaching the interrupt
	 * controller and must therefore be considered active high
	 * as default.
	 */
	int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ?
	int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ||
		       acpi_irq_model == ACPI_IRQ_MODEL_LPIC ?
				      ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW;
	char *link = NULL;
	char link_desc[16];
+1 −0
Original line number Diff line number Diff line
@@ -576,6 +576,7 @@ config IRQ_LOONGARCH_CPU
	select GENERIC_IRQ_CHIP
	select IRQ_DOMAIN
	select GENERIC_IRQ_EFFECTIVE_AFF_MASK
	select LOONGSON_HTVEC
	select LOONGSON_LIOINTC
	select LOONGSON_EIOINTC
	select LOONGSON_PCH_PIC
+18 −12
Original line number Diff line number Diff line
@@ -92,8 +92,7 @@ static const struct irq_domain_ops loongarch_cpu_intc_irq_domain_ops = {
	.xlate = irq_domain_xlate_onecell,
};

static int __init
liointc_parse_madt(union acpi_subtable_headers *header,
static int __init liointc_parse_madt(union acpi_subtable_headers *header,
					const unsigned long end)
{
	struct acpi_madt_lio_pic *liointc_entry = (struct acpi_madt_lio_pic *)header;
@@ -101,8 +100,7 @@ liointc_parse_madt(union acpi_subtable_headers *header,
	return liointc_acpi_init(irq_domain, liointc_entry);
}

static int __init
eiointc_parse_madt(union acpi_subtable_headers *header,
static int __init eiointc_parse_madt(union acpi_subtable_headers *header,
					const unsigned long end)
{
	struct acpi_madt_eio_pic *eiointc_entry = (struct acpi_madt_eio_pic *)header;
@@ -112,16 +110,24 @@ eiointc_parse_madt(union acpi_subtable_headers *header,

static int __init acpi_cascade_irqdomain_init(void)
{
	acpi_table_parse_madt(ACPI_MADT_TYPE_LIO_PIC,
			      liointc_parse_madt, 0);
	acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC,
			      eiointc_parse_madt, 0);
	int r;

	r = acpi_table_parse_madt(ACPI_MADT_TYPE_LIO_PIC, liointc_parse_madt, 0);
	if (r < 0)
		return r;

	r = acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, eiointc_parse_madt, 0);
	if (r < 0)
		return r;

	return 0;
}

static int __init cpuintc_acpi_init(union acpi_subtable_headers *header,
				   const unsigned long end)
{
	int ret;

	if (irq_domain)
		return 0;

@@ -139,9 +145,9 @@ static int __init cpuintc_acpi_init(union acpi_subtable_headers *header,
	set_handle_irq(&handle_cpu_irq);
	acpi_set_irq_model(ACPI_IRQ_MODEL_LPIC, lpic_get_gsi_domain_id);
	acpi_set_gsi_to_irq_fallback(lpic_gsi_to_irq);
	acpi_cascade_irqdomain_init();
	ret = acpi_cascade_irqdomain_init();

	return 0;
	return ret;
}

IRQCHIP_ACPI_DECLARE(cpuintc_v1, ACPI_MADT_TYPE_CORE_PIC,
+50 −13
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/syscore_ops.h>

#define EIOINTC_REG_NODEMAP	0x14a0
#define EIOINTC_REG_IPMAP	0x14c0
@@ -301,8 +302,38 @@ static struct irq_domain *acpi_get_vec_parent(int node, struct acpi_vector_group
	return NULL;
}

static int __init
pch_pic_parse_madt(union acpi_subtable_headers *header,
static int eiointc_suspend(void)
{
	return 0;
}

static void eiointc_resume(void)
{
	int i, j;
	struct irq_desc *desc;
	struct irq_data *irq_data;

	eiointc_router_init(0);

	for (i = 0; i < nr_pics; i++) {
		for (j = 0; j < VEC_COUNT; j++) {
			desc = irq_resolve_mapping(eiointc_priv[i]->eiointc_domain, j);
			if (desc && desc->handle_irq && desc->handle_irq != handle_bad_irq) {
				raw_spin_lock(&desc->lock);
				irq_data = &desc->irq_data;
				eiointc_set_irq_affinity(irq_data, irq_data->common->affinity, 0);
				raw_spin_unlock(&desc->lock);
			}
		}
	}
}

static struct syscore_ops eiointc_syscore_ops = {
	.suspend = eiointc_suspend,
	.resume = eiointc_resume,
};

static int __init pch_pic_parse_madt(union acpi_subtable_headers *header,
					const unsigned long end)
{
	struct acpi_madt_bio_pic *pchpic_entry = (struct acpi_madt_bio_pic *)header;
@@ -315,8 +346,7 @@ pch_pic_parse_madt(union acpi_subtable_headers *header,
	return -EINVAL;
}

static int __init
pch_msi_parse_madt(union acpi_subtable_headers *header,
static int __init pch_msi_parse_madt(union acpi_subtable_headers *header,
					const unsigned long end)
{
	struct acpi_madt_msi_pic *pchmsi_entry = (struct acpi_madt_msi_pic *)header;
@@ -330,17 +360,23 @@ pch_msi_parse_madt(union acpi_subtable_headers *header,

static int __init acpi_cascade_irqdomain_init(void)
{
	acpi_table_parse_madt(ACPI_MADT_TYPE_BIO_PIC,
			      pch_pic_parse_madt, 0);
	acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC,
			      pch_msi_parse_madt, 1);
	int r;

	r = acpi_table_parse_madt(ACPI_MADT_TYPE_BIO_PIC, pch_pic_parse_madt, 0);
	if (r < 0)
		return r;

	r = acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC, pch_msi_parse_madt, 1);
	if (r < 0)
		return r;

	return 0;
}

int __init eiointc_acpi_init(struct irq_domain *parent,
				     struct acpi_madt_eio_pic *acpi_eiointc)
{
	int i, parent_irq;
	int i, ret, parent_irq;
	unsigned long node_map;
	struct eiointc_priv *priv;

@@ -380,15 +416,16 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
	parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade);
	irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);

	register_syscore_ops(&eiointc_syscore_ops);
	cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
				  "irqchip/loongarch/intc:starting",
				  eiointc_router_init, NULL);

	acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group);
	acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group);
	acpi_cascade_irqdomain_init();
	ret = acpi_cascade_irqdomain_init();

	return 0;
	return ret;

out_free_handle:
	irq_domain_free_fwnode(priv->domain_handle);
Loading