[v4,4/4] gpio: mb86s7x: enable ACPI support

Message ID 20190528133647.3362-5-ard.biesheuvel@linaro.org
State Accepted
Commit f3d705d506a2afa6c21c2c728783967e80863b31
Headers show
Series
  • synquacer: implement ACPI gpio/interrupt support
Related show

Commit Message

Ard Biesheuvel May 28, 2019, 1:36 p.m.
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.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

---
 drivers/gpio/gpio-mb86s7x.c | 51 +++++++++++++++++---
 1 file changed, 44 insertions(+), 7 deletions(-)

-- 
2.20.1

Comments

Ard Biesheuvel May 29, 2019, 7:38 a.m. | #1
On Wed, 29 May 2019 at 09:31, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
>

> On Tue, May 28, 2019 at 03:36:47PM +0200, Ard Biesheuvel wrote:

> > 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.

> >

> > Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

>

> Hmm, I thought I reviewed this already? Well anyway,

>

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


Yes, you did. Apologies.

Marc, can you still incorporate this? Or is it too late?
Marc Zyngier May 29, 2019, 9:39 a.m. | #2
On 29/05/2019 08:38, Ard Biesheuvel wrote:
> On Wed, 29 May 2019 at 09:31, Mika Westerberg

> <mika.westerberg@linux.intel.com> wrote:

>>

>> On Tue, May 28, 2019 at 03:36:47PM +0200, Ard Biesheuvel wrote:

>>> 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.

>>>

>>> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

>>

>> Hmm, I thought I reviewed this already? Well anyway,

>>

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

> 

> Yes, you did. Apologies.

> 

> Marc, can you still incorporate this? Or is it too late?


Not a problem, I'll add it.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

Patch

diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c
index 9308081e0a4a..64027f57a8aa 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;
@@ -158,13 +175,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 (!has_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);
 
@@ -180,19 +199,28 @@  static int mb86s70_gpio_probe(struct platform_device *pdev)
 	gchip->gc.parent = &pdev->dev;
 	gchip->gc.base = -1;
 
+	if (has_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);
+		return ret;
 	}
 
-	return ret;
+	if (has_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 (has_acpi_companion(&pdev->dev))
+		acpi_gpiochip_free_interrupts(&gchip->gc);
 	gpiochip_remove(&gchip->gc);
 	clk_disable_unprepare(gchip->clk);
 
@@ -205,10 +233,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,