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: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
parent
3d090a36c8
commit
f3d705d506
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue