linux-acpi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] synquacer: implement ACPI gpio/interrupt support
@ 2019-04-29 13:12 Ard Biesheuvel
  2019-04-29 13:12 ` Ard Biesheuvel
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: Lorenzo Pieralisi, Graeme Gregory, Ard Biesheuvel, Marc Zyngier,
	Linus Walleij, Rafael J. Wysocki, linux-acpi, Masahisa Kojima,
	Mika Westerberg, linux-arm-kernel, Len Brown

Wire up the existing GPIO and interrupt controller drivers to the ACPI
subsystem so they can be used on ACPI systems for ACPI event (power
button, hardware error notification etc)

Changes since v1:
- Describe the EXIU controller as a separate device, which is a more accurate
  depiction of reality, and untangles the code a bit as well. Note that this
  requires the GPIO AML device to describe the EXIU interrupts explicitly.
- Add a patch to obtain the ACPI GSI irqdomain. The EXIU driver needs this
  to obtain the default parent domain, since the GIC is not modeled as an
  ACPI object in the namespace, and so the parent<->child link cannot be
  expressed in AML.
- Drop the Kconfig symbol for the GPIO controller. Just include the ACPI part
  when CONFIG_ACPI is defined.

Cc: Masahisa Kojima <masahisa.kojima@linaro.org>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Graeme Gregory <graeme.gregory@linaro.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>

Ard Biesheuvel (4):
  acpi/irq: implement getter for GSI irqdomain
  irqchip/exiu: preparatory refactor for ACPI support
  irqchip/exiu: implement ACPI support
  gpio: mb86s7x: enable ACPI support

 drivers/acpi/irq.c             |  14 +-
 drivers/gpio/gpio-mb86s7x.c    |  57 ++++++--
 drivers/irqchip/irq-sni-exiu.c | 147 +++++++++++++++-----
 include/linux/acpi.h           |   1 +
 4 files changed, 170 insertions(+), 49 deletions(-)

-- 
2.20.1

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 0/4] synquacer: implement ACPI gpio/interrupt support
  2019-04-29 13:12 [PATCH v2 0/4] synquacer: implement ACPI gpio/interrupt support Ard Biesheuvel
@ 2019-04-29 13:12 ` Ard Biesheuvel
  2019-04-29 13:12 ` [PATCH v2 1/4] acpi/irq: implement getter for GSI irqdomain Ard Biesheuvel
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: linux-acpi, linux-arm-kernel, Ard Biesheuvel, Masahisa Kojima,
	Linus Walleij, Marc Zyngier, Graeme Gregory, Lorenzo Pieralisi,
	Mika Westerberg, Rafael J. Wysocki, Len Brown

Wire up the existing GPIO and interrupt controller drivers to the ACPI
subsystem so they can be used on ACPI systems for ACPI event (power
button, hardware error notification etc)

Changes since v1:
- Describe the EXIU controller as a separate device, which is a more accurate
  depiction of reality, and untangles the code a bit as well. Note that this
  requires the GPIO AML device to describe the EXIU interrupts explicitly.
- Add a patch to obtain the ACPI GSI irqdomain. The EXIU driver needs this
  to obtain the default parent domain, since the GIC is not modeled as an
  ACPI object in the namespace, and so the parent<->child link cannot be
  expressed in AML.
- Drop the Kconfig symbol for the GPIO controller. Just include the ACPI part
  when CONFIG_ACPI is defined.

Cc: Masahisa Kojima <masahisa.kojima@linaro.org>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Graeme Gregory <graeme.gregory@linaro.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>

Ard Biesheuvel (4):
  acpi/irq: implement getter for GSI irqdomain
  irqchip/exiu: preparatory refactor for ACPI support
  irqchip/exiu: implement ACPI support
  gpio: mb86s7x: enable ACPI support

 drivers/acpi/irq.c             |  14 +-
 drivers/gpio/gpio-mb86s7x.c    |  57 ++++++--
 drivers/irqchip/irq-sni-exiu.c | 147 +++++++++++++++-----
 include/linux/acpi.h           |   1 +
 4 files changed, 170 insertions(+), 49 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 1/4] acpi/irq: implement getter for GSI irqdomain
  2019-04-29 13:12 [PATCH v2 0/4] synquacer: implement ACPI gpio/interrupt support Ard Biesheuvel
  2019-04-29 13:12 ` Ard Biesheuvel
@ 2019-04-29 13:12 ` Ard Biesheuvel
  2019-04-29 13:12   ` Ard Biesheuvel
  2019-05-24 10:00   ` Lorenzo Pieralisi
  2019-04-29 13:12 ` [PATCH v2 2/4] irqchip/exiu: preparatory refactor for ACPI support Ard Biesheuvel
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: Lorenzo Pieralisi, Graeme Gregory, Ard Biesheuvel, Marc Zyngier,
	Linus Walleij, Rafael J. Wysocki, linux-acpi, Masahisa Kojima,
	Mika Westerberg, linux-arm-kernel, Len Brown

ACPI permits arbitrary producer->consumer interrupt links to be
described in AML, which means a topology such as the following
is perfectly legal:

  Device (EXIU) {
    Name (_HID, "SCX0008")
    Name (_UID, Zero)
    Name (_CRS, ResourceTemplate () {
      ...
    })
  }

  Device (GPIO) {
    Name (_HID, "SCX0007")
    Name (_UID, Zero)
    Name (_CRS, ResourceTemplate () {
      Memory32Fixed (ReadWrite, SYNQUACER_GPIO_BASE, SYNQUACER_GPIO_SIZE)
      Interrupt (ResourceConsumer, Edge, ActiveHigh, ExclusiveAndWake, 0, "\\_SB.EXIU") {
        7,
      }
    })
    ...
  }

The EXIU in this example is the external interrupt unit as can be found
on Socionext SynQuacer based platforms, which converts a block of 32 SPIs
from arbitrary polarity/trigger into level-high, with a separate set
of config/mask/unmask/clear controls.

The existing DT based driver in drivers/irqchip/irq-sni-exiu.c models
this as a hierarchical domain stacked on top of the GIC's irqdomain.
Since the GIC is modeled as a DT node as well, obtaining a reference
to this irqdomain is easily done by going through the parent link.

On ACPI systems, however, the GIC is not modeled as an object in the
namespace, and so device objects cannot refer to it directly. So in
order to obtain the irqdomain reference when driving the EXIU in ACPI
mode, we need a helper that returns the default domain for unqualified
interrupts.

This is essentially what the ACPI GSI domain provides, so add a helper
that returns a reference to this domain.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/acpi/irq.c   | 14 ++++++++++----
 include/linux/acpi.h |  1 +
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index c3b2222e2129..d47bbd54d4aa 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -17,6 +17,14 @@ enum acpi_irq_model_id acpi_irq_model;
 
 static struct fwnode_handle *acpi_gsi_domain_id;
 
+/**
+ * acpi_get_gsi_irqdomain - Retrieve the irqdomain that owns the GSI space.
+ */
+struct irq_domain *acpi_get_gsi_irqdomain(void)
+{
+	return irq_find_matching_fwnode(acpi_gsi_domain_id, DOMAIN_BUS_ANY);
+}
+
 /**
  * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI
  * @gsi: GSI IRQ number to map
@@ -29,8 +37,7 @@ static struct fwnode_handle *acpi_gsi_domain_id;
  */
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-							DOMAIN_BUS_ANY);
+	struct irq_domain *d = acpi_get_gsi_irqdomain();
 
 	*irq = irq_find_mapping(d, gsi);
 	/*
@@ -76,8 +83,7 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
  */
 void acpi_unregister_gsi(u32 gsi)
 {
-	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-							DOMAIN_BUS_ANY);
+	struct irq_domain *d = acpi_get_gsi_irqdomain();
 	int irq = irq_find_mapping(d, gsi);
 
 	irq_dispose_mapping(irq);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d5dcebd7aad3..1016027dd626 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -316,6 +316,7 @@ static inline bool acpi_sci_irq_valid(void)
 extern int sbf_port;
 extern unsigned long acpi_realmode_flags;
 
+struct irq_domain *acpi_get_gsi_irqdomain(void);
 int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 1/4] acpi/irq: implement getter for GSI irqdomain
  2019-04-29 13:12 ` [PATCH v2 1/4] acpi/irq: implement getter for GSI irqdomain Ard Biesheuvel
@ 2019-04-29 13:12   ` Ard Biesheuvel
  2019-05-24 10:00   ` Lorenzo Pieralisi
  1 sibling, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: linux-acpi, linux-arm-kernel, Ard Biesheuvel, Masahisa Kojima,
	Linus Walleij, Marc Zyngier, Graeme Gregory, Lorenzo Pieralisi,
	Mika Westerberg, Rafael J. Wysocki, Len Brown

ACPI permits arbitrary producer->consumer interrupt links to be
described in AML, which means a topology such as the following
is perfectly legal:

  Device (EXIU) {
    Name (_HID, "SCX0008")
    Name (_UID, Zero)
    Name (_CRS, ResourceTemplate () {
      ...
    })
  }

  Device (GPIO) {
    Name (_HID, "SCX0007")
    Name (_UID, Zero)
    Name (_CRS, ResourceTemplate () {
      Memory32Fixed (ReadWrite, SYNQUACER_GPIO_BASE, SYNQUACER_GPIO_SIZE)
      Interrupt (ResourceConsumer, Edge, ActiveHigh, ExclusiveAndWake, 0, "\\_SB.EXIU") {
        7,
      }
    })
    ...
  }

The EXIU in this example is the external interrupt unit as can be found
on Socionext SynQuacer based platforms, which converts a block of 32 SPIs
from arbitrary polarity/trigger into level-high, with a separate set
of config/mask/unmask/clear controls.

The existing DT based driver in drivers/irqchip/irq-sni-exiu.c models
this as a hierarchical domain stacked on top of the GIC's irqdomain.
Since the GIC is modeled as a DT node as well, obtaining a reference
to this irqdomain is easily done by going through the parent link.

On ACPI systems, however, the GIC is not modeled as an object in the
namespace, and so device objects cannot refer to it directly. So in
order to obtain the irqdomain reference when driving the EXIU in ACPI
mode, we need a helper that returns the default domain for unqualified
interrupts.

This is essentially what the ACPI GSI domain provides, so add a helper
that returns a reference to this domain.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/acpi/irq.c   | 14 ++++++++++----
 include/linux/acpi.h |  1 +
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index c3b2222e2129..d47bbd54d4aa 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -17,6 +17,14 @@ enum acpi_irq_model_id acpi_irq_model;
 
 static struct fwnode_handle *acpi_gsi_domain_id;
 
+/**
+ * acpi_get_gsi_irqdomain - Retrieve the irqdomain that owns the GSI space.
+ */
+struct irq_domain *acpi_get_gsi_irqdomain(void)
+{
+	return irq_find_matching_fwnode(acpi_gsi_domain_id, DOMAIN_BUS_ANY);
+}
+
 /**
  * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI
  * @gsi: GSI IRQ number to map
@@ -29,8 +37,7 @@ static struct fwnode_handle *acpi_gsi_domain_id;
  */
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-							DOMAIN_BUS_ANY);
+	struct irq_domain *d = acpi_get_gsi_irqdomain();
 
 	*irq = irq_find_mapping(d, gsi);
 	/*
@@ -76,8 +83,7 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
  */
 void acpi_unregister_gsi(u32 gsi)
 {
-	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
-							DOMAIN_BUS_ANY);
+	struct irq_domain *d = acpi_get_gsi_irqdomain();
 	int irq = irq_find_mapping(d, gsi);
 
 	irq_dispose_mapping(irq);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d5dcebd7aad3..1016027dd626 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -316,6 +316,7 @@ static inline bool acpi_sci_irq_valid(void)
 extern int sbf_port;
 extern unsigned long acpi_realmode_flags;
 
+struct irq_domain *acpi_get_gsi_irqdomain(void);
 int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 2/4] irqchip/exiu: preparatory refactor for ACPI support
  2019-04-29 13:12 [PATCH v2 0/4] synquacer: implement ACPI gpio/interrupt support Ard Biesheuvel
  2019-04-29 13:12 ` Ard Biesheuvel
  2019-04-29 13:12 ` [PATCH v2 1/4] acpi/irq: implement getter for GSI irqdomain Ard Biesheuvel
@ 2019-04-29 13:12 ` Ard Biesheuvel
  2019-04-29 13:12   ` Ard Biesheuvel
  2019-04-29 13:12 ` [PATCH v2 3/4] irqchip/exiu: implement " Ard Biesheuvel
  2019-04-29 13:12 ` [PATCH v2 4/4] gpio: mb86s7x: enable " Ard Biesheuvel
  4 siblings, 1 reply; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: Lorenzo Pieralisi, Graeme Gregory, Ard Biesheuvel, Marc Zyngier,
	Linus Walleij, Rafael J. Wysocki, linux-acpi, Masahisa Kojima,
	Mika Westerberg, linux-arm-kernel, Len Brown

In preparation of adding support for EXIU controller devices described
via ACPI, split the DT init function in a DT specific and a generic part,
where the latter will be reused for ACPI support later.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/irqchip/irq-sni-exiu.c | 77 ++++++++++++--------
 1 file changed, 48 insertions(+), 29 deletions(-)

diff --git a/drivers/irqchip/irq-sni-exiu.c b/drivers/irqchip/irq-sni-exiu.c
index 1927b2f36ff6..52ce662334d4 100644
--- a/drivers/irqchip/irq-sni-exiu.c
+++ b/drivers/irqchip/irq-sni-exiu.c
@@ -1,7 +1,7 @@
 /*
  * Driver for Socionext External Interrupt Unit (EXIU)
  *
- * Copyright (c) 2017 Linaro, Ltd. <ard.biesheuvel@linaro.org>
+ * Copyright (c) 2017-2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
  *
  * Based on irq-tegra.c:
  *   Copyright (C) 2011 Google, Inc.
@@ -167,35 +167,25 @@ static const struct irq_domain_ops exiu_domain_ops = {
 	.free		= irq_domain_free_irqs_common,
 };
 
-static int __init exiu_init(struct device_node *node,
-			    struct device_node *parent)
+static struct irq_domain *exiu_init(struct irq_domain *parent_domain,
+				    struct fwnode_handle *fwnode,
+				    struct resource *res)
 {
-	struct irq_domain *parent_domain, *domain;
+	struct irq_domain *domain;
 	struct exiu_irq_data *data;
 	int err;
 
-	if (!parent) {
-		pr_err("%pOF: no parent, giving up\n", node);
-		return -ENODEV;
-	}
-
-	parent_domain = irq_find_host(parent);
-	if (!parent_domain) {
-		pr_err("%pOF: unable to obtain parent domain\n", node);
-		return -ENXIO;
-	}
-
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	if (of_property_read_u32(node, "socionext,spi-base", &data->spi_base)) {
-		pr_err("%pOF: failed to parse 'spi-base' property\n", node);
+	if (fwnode_property_read_u32_array(fwnode, "socionext,spi-base",
+					   &data->spi_base, 1)) {
 		err = -ENODEV;
 		goto out_free;
 	}
 
-	data->base = of_iomap(node, 0);
+	data->base = ioremap(res->start, resource_size(res));
 	if (!data->base) {
 		err = -ENODEV;
 		goto out_free;
@@ -205,23 +195,52 @@ static int __init exiu_init(struct device_node *node,
 	writel_relaxed(0xFFFFFFFF, data->base + EIREQCLR);
 	writel_relaxed(0xFFFFFFFF, data->base + EIMASK);
 
-	domain = irq_domain_add_hierarchy(parent_domain, 0, NUM_IRQS, node,
-					  &exiu_domain_ops, data);
+	domain = irq_domain_create_hierarchy(parent_domain, 0, NUM_IRQS,
+					     fwnode, &exiu_domain_ops, data);
 	if (!domain) {
-		pr_err("%pOF: failed to allocate domain\n", node);
 		err = -ENOMEM;
 		goto out_unmap;
 	}
+	return domain;
+out_unmap:
+	iounmap(data->base);
+out_free:
+	kfree(data);
+	return ERR_PTR(err);
+}
+
+static int __init exiu_dt_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	struct irq_domain *parent_domain, *domain;
+	struct resource res;
+
+	if (!parent) {
+		pr_err("%pOF: no parent, giving up\n", node);
+		return -ENODEV;
+	}
+
+	parent_domain = irq_find_host(parent);
+	if (!parent_domain) {
+		pr_err("%pOF: unable to obtain parent domain\n", node);
+		return -ENXIO;
+	}
+
+	if (of_address_to_resource(node, 0, &res)) {
+		pr_err("%pOF: failed to parse memory resource\n", node);
+		return -ENXIO;
+	}
+
+	domain = exiu_init(parent_domain, of_node_to_fwnode(node), &res);
+	if (IS_ERR(domain)) {
+		pr_err("%pOF: failed to create IRQ domain (%ld)\n", node,
+		       PTR_ERR(domain));
+		return PTR_ERR(domain);
+	}
 
 	pr_info("%pOF: %d interrupts forwarded to %pOF\n", node, NUM_IRQS,
 		parent);
 
 	return 0;
-
-out_unmap:
-	iounmap(data->base);
-out_free:
-	kfree(data);
-	return err;
 }
-IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_init);
+IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_dt_init);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 2/4] irqchip/exiu: preparatory refactor for ACPI support
  2019-04-29 13:12 ` [PATCH v2 2/4] irqchip/exiu: preparatory refactor for ACPI support Ard Biesheuvel
@ 2019-04-29 13:12   ` Ard Biesheuvel
  0 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: linux-acpi, linux-arm-kernel, Ard Biesheuvel, Masahisa Kojima,
	Linus Walleij, Marc Zyngier, Graeme Gregory, Lorenzo Pieralisi,
	Mika Westerberg, Rafael J. Wysocki, Len Brown

In preparation of adding support for EXIU controller devices described
via ACPI, split the DT init function in a DT specific and a generic part,
where the latter will be reused for ACPI support later.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/irqchip/irq-sni-exiu.c | 77 ++++++++++++--------
 1 file changed, 48 insertions(+), 29 deletions(-)

diff --git a/drivers/irqchip/irq-sni-exiu.c b/drivers/irqchip/irq-sni-exiu.c
index 1927b2f36ff6..52ce662334d4 100644
--- a/drivers/irqchip/irq-sni-exiu.c
+++ b/drivers/irqchip/irq-sni-exiu.c
@@ -1,7 +1,7 @@
 /*
  * Driver for Socionext External Interrupt Unit (EXIU)
  *
- * Copyright (c) 2017 Linaro, Ltd. <ard.biesheuvel@linaro.org>
+ * Copyright (c) 2017-2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
  *
  * Based on irq-tegra.c:
  *   Copyright (C) 2011 Google, Inc.
@@ -167,35 +167,25 @@ static const struct irq_domain_ops exiu_domain_ops = {
 	.free		= irq_domain_free_irqs_common,
 };
 
-static int __init exiu_init(struct device_node *node,
-			    struct device_node *parent)
+static struct irq_domain *exiu_init(struct irq_domain *parent_domain,
+				    struct fwnode_handle *fwnode,
+				    struct resource *res)
 {
-	struct irq_domain *parent_domain, *domain;
+	struct irq_domain *domain;
 	struct exiu_irq_data *data;
 	int err;
 
-	if (!parent) {
-		pr_err("%pOF: no parent, giving up\n", node);
-		return -ENODEV;
-	}
-
-	parent_domain = irq_find_host(parent);
-	if (!parent_domain) {
-		pr_err("%pOF: unable to obtain parent domain\n", node);
-		return -ENXIO;
-	}
-
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	if (of_property_read_u32(node, "socionext,spi-base", &data->spi_base)) {
-		pr_err("%pOF: failed to parse 'spi-base' property\n", node);
+	if (fwnode_property_read_u32_array(fwnode, "socionext,spi-base",
+					   &data->spi_base, 1)) {
 		err = -ENODEV;
 		goto out_free;
 	}
 
-	data->base = of_iomap(node, 0);
+	data->base = ioremap(res->start, resource_size(res));
 	if (!data->base) {
 		err = -ENODEV;
 		goto out_free;
@@ -205,23 +195,52 @@ static int __init exiu_init(struct device_node *node,
 	writel_relaxed(0xFFFFFFFF, data->base + EIREQCLR);
 	writel_relaxed(0xFFFFFFFF, data->base + EIMASK);
 
-	domain = irq_domain_add_hierarchy(parent_domain, 0, NUM_IRQS, node,
-					  &exiu_domain_ops, data);
+	domain = irq_domain_create_hierarchy(parent_domain, 0, NUM_IRQS,
+					     fwnode, &exiu_domain_ops, data);
 	if (!domain) {
-		pr_err("%pOF: failed to allocate domain\n", node);
 		err = -ENOMEM;
 		goto out_unmap;
 	}
+	return domain;
+out_unmap:
+	iounmap(data->base);
+out_free:
+	kfree(data);
+	return ERR_PTR(err);
+}
+
+static int __init exiu_dt_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	struct irq_domain *parent_domain, *domain;
+	struct resource res;
+
+	if (!parent) {
+		pr_err("%pOF: no parent, giving up\n", node);
+		return -ENODEV;
+	}
+
+	parent_domain = irq_find_host(parent);
+	if (!parent_domain) {
+		pr_err("%pOF: unable to obtain parent domain\n", node);
+		return -ENXIO;
+	}
+
+	if (of_address_to_resource(node, 0, &res)) {
+		pr_err("%pOF: failed to parse memory resource\n", node);
+		return -ENXIO;
+	}
+
+	domain = exiu_init(parent_domain, of_node_to_fwnode(node), &res);
+	if (IS_ERR(domain)) {
+		pr_err("%pOF: failed to create IRQ domain (%ld)\n", node,
+		       PTR_ERR(domain));
+		return PTR_ERR(domain);
+	}
 
 	pr_info("%pOF: %d interrupts forwarded to %pOF\n", node, NUM_IRQS,
 		parent);
 
 	return 0;
-
-out_unmap:
-	iounmap(data->base);
-out_free:
-	kfree(data);
-	return err;
 }
-IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_init);
+IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_dt_init);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/4] irqchip/exiu: implement ACPI support
  2019-04-29 13:12 [PATCH v2 0/4] synquacer: implement ACPI gpio/interrupt support Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2019-04-29 13:12 ` [PATCH v2 2/4] irqchip/exiu: preparatory refactor for ACPI support Ard Biesheuvel
@ 2019-04-29 13:12 ` Ard Biesheuvel
  2019-04-29 13:12   ` Ard Biesheuvel
  2019-04-29 13:12 ` [PATCH v2 4/4] gpio: mb86s7x: enable " Ard Biesheuvel
  4 siblings, 1 reply; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: Lorenzo Pieralisi, Graeme Gregory, Ard Biesheuvel, Marc Zyngier,
	Linus Walleij, Rafael J. Wysocki, linux-acpi, Masahisa Kojima,
	Mika Westerberg, linux-arm-kernel, Len Brown

Expose the existing EXIU hierarchical irqchip domain code to permit
the interrupt controller to be used as the irqchip component of a
GPIO controller on ACPI systems, or as the target of ordinary
interrupt resources.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/irqchip/irq-sni-exiu.c | 72 +++++++++++++++++---
 1 file changed, 64 insertions(+), 8 deletions(-)

diff --git a/drivers/irqchip/irq-sni-exiu.c b/drivers/irqchip/irq-sni-exiu.c
index 52ce662334d4..68394f804af1 100644
--- a/drivers/irqchip/irq-sni-exiu.c
+++ b/drivers/irqchip/irq-sni-exiu.c
@@ -20,6 +20,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/platform_device.h>
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
@@ -134,9 +135,13 @@ static int exiu_domain_translate(struct irq_domain *domain,
 
 		*hwirq = fwspec->param[1] - info->spi_base;
 		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
-		return 0;
+	} else {
+		if (fwspec->param_count != 2)
+			return -EINVAL;
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
 	}
-	return -EINVAL;
+	return 0;
 }
 
 static int exiu_domain_alloc(struct irq_domain *dom, unsigned int virq,
@@ -147,16 +152,21 @@ static int exiu_domain_alloc(struct irq_domain *dom, unsigned int virq,
 	struct exiu_irq_data *info = dom->host_data;
 	irq_hw_number_t hwirq;
 
-	if (fwspec->param_count != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (fwspec->param[0] != GIC_SPI)
-		return -EINVAL;	/* No PPI should point to this domain */
+	parent_fwspec = *fwspec;
+	if (is_of_node(dom->parent->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;	/* Not GIC compliant */
+		if (fwspec->param[0] != GIC_SPI)
+			return -EINVAL;	/* No PPI should point to this domain */
 
+		hwirq = fwspec->param[1] - info->spi_base;
+	} else {
+		hwirq = fwspec->param[0];
+		parent_fwspec.param[0] = hwirq + info->spi_base + 32;
+	}
 	WARN_ON(nr_irqs != 1);
-	hwirq = fwspec->param[1] - info->spi_base;
 	irq_domain_set_hwirq_and_chip(dom, virq, hwirq, &exiu_irq_chip, info);
 
-	parent_fwspec = *fwspec;
 	parent_fwspec.fwnode = dom->parent->fwnode;
 	return irq_domain_alloc_irqs_parent(dom, virq, nr_irqs, &parent_fwspec);
 }
@@ -244,3 +254,49 @@ static int __init exiu_dt_init(struct device_node *node,
 	return 0;
 }
 IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_dt_init);
+
+#ifdef CONFIG_ACPI
+static int exiu_acpi_probe(struct platform_device *pdev)
+{
+	struct irq_domain *parent_domain, *domain;
+	struct resource *res;
+
+	parent_domain = acpi_get_gsi_irqdomain();
+	if (!parent_domain) {
+		dev_err(&pdev->dev, "unable to obtain parent domain\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to parse memory resource\n");
+		return -ENXIO;
+	}
+
+	domain = exiu_init(parent_domain, dev_fwnode(&pdev->dev), res);
+	if (IS_ERR(domain)) {
+		dev_err(&pdev->dev, "failed to create IRQ domain (%ld)\n",
+			PTR_ERR(domain));
+		return PTR_ERR(domain);
+	}
+
+	dev_info(&pdev->dev, "%d interrupts forwarded\n", NUM_IRQS);
+
+	return 0;
+}
+
+static const struct acpi_device_id exiu_acpi_ids[] = {
+	{ "SCX0008" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, exiu_acpi_ids);
+
+static struct platform_driver exiu_driver = {
+	.driver = {
+		.name = "exiu",
+		.acpi_match_table = exiu_acpi_ids,
+	},
+	.probe = exiu_acpi_probe,
+};
+builtin_platform_driver(exiu_driver);
+#endif
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/4] irqchip/exiu: implement ACPI support
  2019-04-29 13:12 ` [PATCH v2 3/4] irqchip/exiu: implement " Ard Biesheuvel
@ 2019-04-29 13:12   ` Ard Biesheuvel
  0 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: linux-acpi, linux-arm-kernel, Ard Biesheuvel, Masahisa Kojima,
	Linus Walleij, Marc Zyngier, Graeme Gregory, Lorenzo Pieralisi,
	Mika Westerberg, Rafael J. Wysocki, Len Brown

Expose the existing EXIU hierarchical irqchip domain code to permit
the interrupt controller to be used as the irqchip component of a
GPIO controller on ACPI systems, or as the target of ordinary
interrupt resources.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/irqchip/irq-sni-exiu.c | 72 +++++++++++++++++---
 1 file changed, 64 insertions(+), 8 deletions(-)

diff --git a/drivers/irqchip/irq-sni-exiu.c b/drivers/irqchip/irq-sni-exiu.c
index 52ce662334d4..68394f804af1 100644
--- a/drivers/irqchip/irq-sni-exiu.c
+++ b/drivers/irqchip/irq-sni-exiu.c
@@ -20,6 +20,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/platform_device.h>
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
@@ -134,9 +135,13 @@ static int exiu_domain_translate(struct irq_domain *domain,
 
 		*hwirq = fwspec->param[1] - info->spi_base;
 		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
-		return 0;
+	} else {
+		if (fwspec->param_count != 2)
+			return -EINVAL;
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
 	}
-	return -EINVAL;
+	return 0;
 }
 
 static int exiu_domain_alloc(struct irq_domain *dom, unsigned int virq,
@@ -147,16 +152,21 @@ static int exiu_domain_alloc(struct irq_domain *dom, unsigned int virq,
 	struct exiu_irq_data *info = dom->host_data;
 	irq_hw_number_t hwirq;
 
-	if (fwspec->param_count != 3)
-		return -EINVAL;	/* Not GIC compliant */
-	if (fwspec->param[0] != GIC_SPI)
-		return -EINVAL;	/* No PPI should point to this domain */
+	parent_fwspec = *fwspec;
+	if (is_of_node(dom->parent->fwnode)) {
+		if (fwspec->param_count != 3)
+			return -EINVAL;	/* Not GIC compliant */
+		if (fwspec->param[0] != GIC_SPI)
+			return -EINVAL;	/* No PPI should point to this domain */
 
+		hwirq = fwspec->param[1] - info->spi_base;
+	} else {
+		hwirq = fwspec->param[0];
+		parent_fwspec.param[0] = hwirq + info->spi_base + 32;
+	}
 	WARN_ON(nr_irqs != 1);
-	hwirq = fwspec->param[1] - info->spi_base;
 	irq_domain_set_hwirq_and_chip(dom, virq, hwirq, &exiu_irq_chip, info);
 
-	parent_fwspec = *fwspec;
 	parent_fwspec.fwnode = dom->parent->fwnode;
 	return irq_domain_alloc_irqs_parent(dom, virq, nr_irqs, &parent_fwspec);
 }
@@ -244,3 +254,49 @@ static int __init exiu_dt_init(struct device_node *node,
 	return 0;
 }
 IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_dt_init);
+
+#ifdef CONFIG_ACPI
+static int exiu_acpi_probe(struct platform_device *pdev)
+{
+	struct irq_domain *parent_domain, *domain;
+	struct resource *res;
+
+	parent_domain = acpi_get_gsi_irqdomain();
+	if (!parent_domain) {
+		dev_err(&pdev->dev, "unable to obtain parent domain\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to parse memory resource\n");
+		return -ENXIO;
+	}
+
+	domain = exiu_init(parent_domain, dev_fwnode(&pdev->dev), res);
+	if (IS_ERR(domain)) {
+		dev_err(&pdev->dev, "failed to create IRQ domain (%ld)\n",
+			PTR_ERR(domain));
+		return PTR_ERR(domain);
+	}
+
+	dev_info(&pdev->dev, "%d interrupts forwarded\n", NUM_IRQS);
+
+	return 0;
+}
+
+static const struct acpi_device_id exiu_acpi_ids[] = {
+	{ "SCX0008" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, exiu_acpi_ids);
+
+static struct platform_driver exiu_driver = {
+	.driver = {
+		.name = "exiu",
+		.acpi_match_table = exiu_acpi_ids,
+	},
+	.probe = exiu_acpi_probe,
+};
+builtin_platform_driver(exiu_driver);
+#endif
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 4/4] gpio: mb86s7x: enable ACPI support
  2019-04-29 13:12 [PATCH v2 0/4] synquacer: implement ACPI gpio/interrupt support Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2019-04-29 13:12 ` [PATCH v2 3/4] irqchip/exiu: implement " Ard Biesheuvel
@ 2019-04-29 13:12 ` Ard Biesheuvel
  2019-04-29 13:12   ` Ard Biesheuvel
  2019-05-02  8:02   ` Mika Westerberg
  4 siblings, 2 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: Lorenzo Pieralisi, Graeme Gregory, Ard Biesheuvel, Marc Zyngier,
	Linus Walleij, Rafael J. Wysocki, linux-acpi, Masahisa Kojima,
	Mika Westerberg, linux-arm-kernel, Len Brown

Make the mb86s7x GPIO block discoverable via ACPI. In addition, add
support for ACPI GPIO interrupts routed via platform interrupts, by
wiring the two together via the to_irq() gpiochip callback.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/gpio/gpio-mb86s7x.c | 57 ++++++++++++++++----
 1 file changed, 48 insertions(+), 9 deletions(-)

diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
index 3134c0d2bfe4..61ad95c3e3d2 100644
--- a/drivers/gpio/gpio-mb86s7x.c
+++ b/drivers/gpio/gpio-mb86s7x.c
@@ -14,6 +14,7 @@
  *  GNU General Public License for more details.
  */
 
+#include <linux/acpi.h>
 #include <linux/io.h>
 #include <linux/init.h>
 #include <linux/clk.h>
@@ -27,6 +28,8 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 
+#include "gpiolib.h"
+
 /*
  * Only first 8bits of a register correspond to each pin,
  * so there are 4 registers for 32 pins.
@@ -143,6 +146,20 @@ static void mb86s70_gpio_set(struct gpio_chip *gc, unsigned gpio, int value)
 	spin_unlock_irqrestore(&gchip->lock, flags);
 }
 
+static int mb86s70_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
+{
+	int irq, index;
+
+	for (index = 0;; index++) {
+		irq = platform_get_irq(to_platform_device(gc->parent), index);
+		if (irq <= 0)
+			break;
+		if (irq_get_irq_data(irq)->hwirq == offset)
+			return irq;
+	}
+	return -EINVAL;
+}
+
 static int mb86s70_gpio_probe(struct platform_device *pdev)
 {
 	struct mb86s70_gpio_chip *gchip;
@@ -160,13 +177,15 @@ static int mb86s70_gpio_probe(struct platform_device *pdev)
 	if (IS_ERR(gchip->base))
 		return PTR_ERR(gchip->base);
 
-	gchip->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(gchip->clk))
-		return PTR_ERR(gchip->clk);
+	if (!ACPI_COMPANION(&pdev->dev)) {
+		gchip->clk = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(gchip->clk))
+			return PTR_ERR(gchip->clk);
 
-	ret = clk_prepare_enable(gchip->clk);
-	if (ret)
-		return ret;
+		ret = clk_prepare_enable(gchip->clk);
+		if (ret)
+			return ret;
+	}
 
 	spin_lock_init(&gchip->lock);
 
@@ -182,21 +201,32 @@ static int mb86s70_gpio_probe(struct platform_device *pdev)
 	gchip->gc.parent = &pdev->dev;
 	gchip->gc.base = -1;
 
+	if (ACPI_COMPANION(&pdev->dev))
+		gchip->gc.to_irq = mb86s70_gpio_to_irq;
+
 	ret = gpiochip_add_data(&gchip->gc, gchip);
 	if (ret) {
 		dev_err(&pdev->dev, "couldn't register gpio driver\n");
-		clk_disable_unprepare(gchip->clk);
+		if (gchip->clk)
+			clk_disable_unprepare(gchip->clk);
+		return ret;
 	}
 
-	return ret;
+	if (ACPI_COMPANION(&pdev->dev))
+		acpi_gpiochip_request_interrupts(&gchip->gc);
+
+	return 0;
 }
 
 static int mb86s70_gpio_remove(struct platform_device *pdev)
 {
 	struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
 
+	if (ACPI_COMPANION(&pdev->dev))
+		acpi_gpiochip_free_interrupts(&gchip->gc);
 	gpiochip_remove(&gchip->gc);
-	clk_disable_unprepare(gchip->clk);
+	if (gchip->clk)
+		clk_disable_unprepare(gchip->clk);
 
 	return 0;
 }
@@ -207,10 +237,19 @@ static const struct of_device_id mb86s70_gpio_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id mb86s70_gpio_acpi_ids[] = {
+	{ "SCX0007" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, mb86s70_gpio_acpi_ids);
+#endif
+
 static struct platform_driver mb86s70_gpio_driver = {
 	.driver = {
 		.name = "mb86s70-gpio",
 		.of_match_table = mb86s70_gpio_dt_ids,
+		.acpi_match_table = ACPI_PTR(mb86s70_gpio_acpi_ids),
 	},
 	.probe = mb86s70_gpio_probe,
 	.remove = mb86s70_gpio_remove,
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 4/4] gpio: mb86s7x: enable ACPI support
  2019-04-29 13:12 ` [PATCH v2 4/4] gpio: mb86s7x: enable " Ard Biesheuvel
@ 2019-04-29 13:12   ` Ard Biesheuvel
  2019-05-02  8:02   ` Mika Westerberg
  1 sibling, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2019-04-29 13:12 UTC (permalink / raw)
  To: linux-gpio
  Cc: linux-acpi, linux-arm-kernel, Ard Biesheuvel, Masahisa Kojima,
	Linus Walleij, Marc Zyngier, Graeme Gregory, Lorenzo Pieralisi,
	Mika Westerberg, Rafael J. Wysocki, Len Brown

Make the mb86s7x GPIO block discoverable via ACPI. In addition, add
support for ACPI GPIO interrupts routed via platform interrupts, by
wiring the two together via the to_irq() gpiochip callback.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/gpio/gpio-mb86s7x.c | 57 ++++++++++++++++----
 1 file changed, 48 insertions(+), 9 deletions(-)

diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
index 3134c0d2bfe4..61ad95c3e3d2 100644
--- a/drivers/gpio/gpio-mb86s7x.c
+++ b/drivers/gpio/gpio-mb86s7x.c
@@ -14,6 +14,7 @@
  *  GNU General Public License for more details.
  */
 
+#include <linux/acpi.h>
 #include <linux/io.h>
 #include <linux/init.h>
 #include <linux/clk.h>
@@ -27,6 +28,8 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 
+#include "gpiolib.h"
+
 /*
  * Only first 8bits of a register correspond to each pin,
  * so there are 4 registers for 32 pins.
@@ -143,6 +146,20 @@ static void mb86s70_gpio_set(struct gpio_chip *gc, unsigned gpio, int value)
 	spin_unlock_irqrestore(&gchip->lock, flags);
 }
 
+static int mb86s70_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
+{
+	int irq, index;
+
+	for (index = 0;; index++) {
+		irq = platform_get_irq(to_platform_device(gc->parent), index);
+		if (irq <= 0)
+			break;
+		if (irq_get_irq_data(irq)->hwirq == offset)
+			return irq;
+	}
+	return -EINVAL;
+}
+
 static int mb86s70_gpio_probe(struct platform_device *pdev)
 {
 	struct mb86s70_gpio_chip *gchip;
@@ -160,13 +177,15 @@ static int mb86s70_gpio_probe(struct platform_device *pdev)
 	if (IS_ERR(gchip->base))
 		return PTR_ERR(gchip->base);
 
-	gchip->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(gchip->clk))
-		return PTR_ERR(gchip->clk);
+	if (!ACPI_COMPANION(&pdev->dev)) {
+		gchip->clk = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(gchip->clk))
+			return PTR_ERR(gchip->clk);
 
-	ret = clk_prepare_enable(gchip->clk);
-	if (ret)
-		return ret;
+		ret = clk_prepare_enable(gchip->clk);
+		if (ret)
+			return ret;
+	}
 
 	spin_lock_init(&gchip->lock);
 
@@ -182,21 +201,32 @@ static int mb86s70_gpio_probe(struct platform_device *pdev)
 	gchip->gc.parent = &pdev->dev;
 	gchip->gc.base = -1;
 
+	if (ACPI_COMPANION(&pdev->dev))
+		gchip->gc.to_irq = mb86s70_gpio_to_irq;
+
 	ret = gpiochip_add_data(&gchip->gc, gchip);
 	if (ret) {
 		dev_err(&pdev->dev, "couldn't register gpio driver\n");
-		clk_disable_unprepare(gchip->clk);
+		if (gchip->clk)
+			clk_disable_unprepare(gchip->clk);
+		return ret;
 	}
 
-	return ret;
+	if (ACPI_COMPANION(&pdev->dev))
+		acpi_gpiochip_request_interrupts(&gchip->gc);
+
+	return 0;
 }
 
 static int mb86s70_gpio_remove(struct platform_device *pdev)
 {
 	struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev);
 
+	if (ACPI_COMPANION(&pdev->dev))
+		acpi_gpiochip_free_interrupts(&gchip->gc);
 	gpiochip_remove(&gchip->gc);
-	clk_disable_unprepare(gchip->clk);
+	if (gchip->clk)
+		clk_disable_unprepare(gchip->clk);
 
 	return 0;
 }
@@ -207,10 +237,19 @@ static const struct of_device_id mb86s70_gpio_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id mb86s70_gpio_acpi_ids[] = {
+	{ "SCX0007" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, mb86s70_gpio_acpi_ids);
+#endif
+
 static struct platform_driver mb86s70_gpio_driver = {
 	.driver = {
 		.name = "mb86s70-gpio",
 		.of_match_table = mb86s70_gpio_dt_ids,
+		.acpi_match_table = ACPI_PTR(mb86s70_gpio_acpi_ids),
 	},
 	.probe = mb86s70_gpio_probe,
 	.remove = mb86s70_gpio_remove,
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 4/4] gpio: mb86s7x: enable ACPI support
  2019-04-29 13:12 ` [PATCH v2 4/4] gpio: mb86s7x: enable " Ard Biesheuvel
  2019-04-29 13:12   ` Ard Biesheuvel
@ 2019-05-02  8:02   ` Mika Westerberg
  2019-05-02  8:02     ` Mika Westerberg
  2019-05-02 11:03     ` Ard Biesheuvel
  1 sibling, 2 replies; 15+ messages in thread
From: Mika Westerberg @ 2019-05-02  8:02 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Lorenzo Pieralisi, Graeme Gregory, linux-acpi, Marc Zyngier,
	Linus Walleij, Rafael J. Wysocki, linux-gpio, Masahisa Kojima,
	linux-arm-kernel, Len Brown

On Mon, Apr 29, 2019 at 03:12:08PM +0200, Ard Biesheuvel wrote:
> @@ -160,13 +177,15 @@ static int mb86s70_gpio_probe(struct platform_device *pdev)
>  	if (IS_ERR(gchip->base))
>  		return PTR_ERR(gchip->base);
>  
> -	gchip->clk = devm_clk_get(&pdev->dev, NULL);
> -	if (IS_ERR(gchip->clk))
> -		return PTR_ERR(gchip->clk);
> +	if (!ACPI_COMPANION(&pdev->dev)) {

Since you don't use the returned ACPI object, you can also use
has_acpi_companion(&pdev->dev) here and other similar places.

Regardless of that,

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 4/4] gpio: mb86s7x: enable ACPI support
  2019-05-02  8:02   ` Mika Westerberg
@ 2019-05-02  8:02     ` Mika Westerberg
  2019-05-02 11:03     ` Ard Biesheuvel
  1 sibling, 0 replies; 15+ messages in thread
From: Mika Westerberg @ 2019-05-02  8:02 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-gpio, linux-acpi, linux-arm-kernel, Masahisa Kojima,
	Linus Walleij, Marc Zyngier, Graeme Gregory, Lorenzo Pieralisi,
	Rafael J. Wysocki, Len Brown

On Mon, Apr 29, 2019 at 03:12:08PM +0200, Ard Biesheuvel wrote:
> @@ -160,13 +177,15 @@ static int mb86s70_gpio_probe(struct platform_device *pdev)
>  	if (IS_ERR(gchip->base))
>  		return PTR_ERR(gchip->base);
>  
> -	gchip->clk = devm_clk_get(&pdev->dev, NULL);
> -	if (IS_ERR(gchip->clk))
> -		return PTR_ERR(gchip->clk);
> +	if (!ACPI_COMPANION(&pdev->dev)) {

Since you don't use the returned ACPI object, you can also use
has_acpi_companion(&pdev->dev) here and other similar places.

Regardless of that,

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 4/4] gpio: mb86s7x: enable ACPI support
  2019-05-02  8:02   ` Mika Westerberg
  2019-05-02  8:02     ` Mika Westerberg
@ 2019-05-02 11:03     ` Ard Biesheuvel
  2019-05-02 11:03       ` Ard Biesheuvel
  1 sibling, 1 reply; 15+ messages in thread
From: Ard Biesheuvel @ 2019-05-02 11:03 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Lorenzo Pieralisi, Graeme Gregory, ACPI Devel Maling List,
	Marc Zyngier, Linus Walleij, Rafael J. Wysocki,
	open list:GPIO SUBSYSTEM, Masahisa Kojima, linux-arm-kernel,
	Len Brown

On Thu, 2 May 2019 at 10:03, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
>
> On Mon, Apr 29, 2019 at 03:12:08PM +0200, Ard Biesheuvel wrote:
> > @@ -160,13 +177,15 @@ static int mb86s70_gpio_probe(struct platform_device *pdev)
> >       if (IS_ERR(gchip->base))
> >               return PTR_ERR(gchip->base);
> >
> > -     gchip->clk = devm_clk_get(&pdev->dev, NULL);
> > -     if (IS_ERR(gchip->clk))
> > -             return PTR_ERR(gchip->clk);
> > +     if (!ACPI_COMPANION(&pdev->dev)) {
>
> Since you don't use the returned ACPI object, you can also use
> has_acpi_companion(&pdev->dev) here and other similar places.
>
> Regardless of that,
>
> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Thanks Mika. I will use has_acpi_companion() instead.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 4/4] gpio: mb86s7x: enable ACPI support
  2019-05-02 11:03     ` Ard Biesheuvel
@ 2019-05-02 11:03       ` Ard Biesheuvel
  0 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2019-05-02 11:03 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: open list:GPIO SUBSYSTEM, ACPI Devel Maling List,
	linux-arm-kernel, Masahisa Kojima, Linus Walleij, Marc Zyngier,
	Graeme Gregory, Lorenzo Pieralisi, Rafael J. Wysocki, Len Brown

On Thu, 2 May 2019 at 10:03, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
>
> On Mon, Apr 29, 2019 at 03:12:08PM +0200, Ard Biesheuvel wrote:
> > @@ -160,13 +177,15 @@ static int mb86s70_gpio_probe(struct platform_device *pdev)
> >       if (IS_ERR(gchip->base))
> >               return PTR_ERR(gchip->base);
> >
> > -     gchip->clk = devm_clk_get(&pdev->dev, NULL);
> > -     if (IS_ERR(gchip->clk))
> > -             return PTR_ERR(gchip->clk);
> > +     if (!ACPI_COMPANION(&pdev->dev)) {
>
> Since you don't use the returned ACPI object, you can also use
> has_acpi_companion(&pdev->dev) here and other similar places.
>
> Regardless of that,
>
> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Thanks Mika. I will use has_acpi_companion() instead.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/4] acpi/irq: implement getter for GSI irqdomain
  2019-04-29 13:12 ` [PATCH v2 1/4] acpi/irq: implement getter for GSI irqdomain Ard Biesheuvel
  2019-04-29 13:12   ` Ard Biesheuvel
@ 2019-05-24 10:00   ` Lorenzo Pieralisi
  1 sibling, 0 replies; 15+ messages in thread
From: Lorenzo Pieralisi @ 2019-05-24 10:00 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-gpio, linux-acpi, linux-arm-kernel, Masahisa Kojima,
	Linus Walleij, Marc Zyngier, Graeme Gregory, Mika Westerberg,
	Rafael J. Wysocki, Len Brown

On Mon, Apr 29, 2019 at 03:12:05PM +0200, Ard Biesheuvel wrote:
> ACPI permits arbitrary producer->consumer interrupt links to be
> described in AML, which means a topology such as the following
> is perfectly legal:
> 
>   Device (EXIU) {
>     Name (_HID, "SCX0008")
>     Name (_UID, Zero)
>     Name (_CRS, ResourceTemplate () {
>       ...
>     })
>   }
> 
>   Device (GPIO) {
>     Name (_HID, "SCX0007")
>     Name (_UID, Zero)
>     Name (_CRS, ResourceTemplate () {
>       Memory32Fixed (ReadWrite, SYNQUACER_GPIO_BASE, SYNQUACER_GPIO_SIZE)
>       Interrupt (ResourceConsumer, Edge, ActiveHigh, ExclusiveAndWake, 0, "\\_SB.EXIU") {
>         7,
>       }
>     })
>     ...
>   }
> 
> The EXIU in this example is the external interrupt unit as can be found
> on Socionext SynQuacer based platforms, which converts a block of 32 SPIs
> from arbitrary polarity/trigger into level-high, with a separate set
> of config/mask/unmask/clear controls.
> 
> The existing DT based driver in drivers/irqchip/irq-sni-exiu.c models
> this as a hierarchical domain stacked on top of the GIC's irqdomain.
> Since the GIC is modeled as a DT node as well, obtaining a reference
> to this irqdomain is easily done by going through the parent link.
> 
> On ACPI systems, however, the GIC is not modeled as an object in the
> namespace, and so device objects cannot refer to it directly. So in
> order to obtain the irqdomain reference when driving the EXIU in ACPI
> mode, we need a helper that returns the default domain for unqualified
> interrupts.
> 
> This is essentially what the ACPI GSI domain provides, so add a helper
> that returns a reference to this domain.

Or we directly export a function in:

drivers/acpi/irq.c

that creates a hierarchical domain with the default GSI domain as a
parent, instead of exporting a function to get that domain from drivers,
this should cut a bit of boilerplate and keep the default GSI domain
handling in ACPI core.

IIUC, the concept is a bit identical to what we did for MBIgen
except that there IORT sets-up the device->msi_domain pointer and
therefore the MBIgen driver does not have to do anything.

Lorenzo

> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  drivers/acpi/irq.c   | 14 ++++++++++----
>  include/linux/acpi.h |  1 +
>  2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> index c3b2222e2129..d47bbd54d4aa 100644
> --- a/drivers/acpi/irq.c
> +++ b/drivers/acpi/irq.c
> @@ -17,6 +17,14 @@ enum acpi_irq_model_id acpi_irq_model;
>  
>  static struct fwnode_handle *acpi_gsi_domain_id;
>  
> +/**
> + * acpi_get_gsi_irqdomain - Retrieve the irqdomain that owns the GSI space.
> + */
> +struct irq_domain *acpi_get_gsi_irqdomain(void)
> +{
> +	return irq_find_matching_fwnode(acpi_gsi_domain_id, DOMAIN_BUS_ANY);
> +}
> +
>  /**
>   * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI
>   * @gsi: GSI IRQ number to map
> @@ -29,8 +37,7 @@ static struct fwnode_handle *acpi_gsi_domain_id;
>   */
>  int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
>  {
> -	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> -							DOMAIN_BUS_ANY);
> +	struct irq_domain *d = acpi_get_gsi_irqdomain();
>  
>  	*irq = irq_find_mapping(d, gsi);
>  	/*
> @@ -76,8 +83,7 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi);
>   */
>  void acpi_unregister_gsi(u32 gsi)
>  {
> -	struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id,
> -							DOMAIN_BUS_ANY);
> +	struct irq_domain *d = acpi_get_gsi_irqdomain();
>  	int irq = irq_find_mapping(d, gsi);
>  
>  	irq_dispose_mapping(irq);
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index d5dcebd7aad3..1016027dd626 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -316,6 +316,7 @@ static inline bool acpi_sci_irq_valid(void)
>  extern int sbf_port;
>  extern unsigned long acpi_realmode_flags;
>  
> +struct irq_domain *acpi_get_gsi_irqdomain(void);
>  int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
> -- 
> 2.20.1
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2019-05-24 10:00 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-29 13:12 [PATCH v2 0/4] synquacer: implement ACPI gpio/interrupt support Ard Biesheuvel
2019-04-29 13:12 ` Ard Biesheuvel
2019-04-29 13:12 ` [PATCH v2 1/4] acpi/irq: implement getter for GSI irqdomain Ard Biesheuvel
2019-04-29 13:12   ` Ard Biesheuvel
2019-05-24 10:00   ` Lorenzo Pieralisi
2019-04-29 13:12 ` [PATCH v2 2/4] irqchip/exiu: preparatory refactor for ACPI support Ard Biesheuvel
2019-04-29 13:12   ` Ard Biesheuvel
2019-04-29 13:12 ` [PATCH v2 3/4] irqchip/exiu: implement " Ard Biesheuvel
2019-04-29 13:12   ` Ard Biesheuvel
2019-04-29 13:12 ` [PATCH v2 4/4] gpio: mb86s7x: enable " Ard Biesheuvel
2019-04-29 13:12   ` Ard Biesheuvel
2019-05-02  8:02   ` Mika Westerberg
2019-05-02  8:02     ` Mika Westerberg
2019-05-02 11:03     ` Ard Biesheuvel
2019-05-02 11:03       ` Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).