Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / drivers / gpio / gpio-mb86s7x.c
index 9bfff17..8f46699 100644 (file)
@@ -6,6 +6,7 @@
  *  Copyright (C) 2015 Linaro Ltd.
  */
 
+#include <linux/acpi.h>
 #include <linux/io.h>
 #include <linux/init.h>
 #include <linux/clk.h>
@@ -19,6 +20,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.
@@ -135,6 +138,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;
@@ -150,13 +167,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);
 
@@ -172,19 +191,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);
 
@@ -197,10 +225,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,