Commit f3d705d5 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Marc Zyngier

gpio: mb86s7x: Enable ACPI support

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: default avatarLinus Walleij <linus.walleij@linaro.org>
Reviewed-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 3d090a36
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment