diff options
Diffstat (limited to 'drivers/gpio/gpio-mpc8xxx.c')
-rw-r--r-- | drivers/gpio/gpio-mpc8xxx.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 16a47de29c94..f1e164cecff8 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -22,6 +22,7 @@ #include <linux/irq.h> #include <linux/gpio/driver.h> #include <linux/bitops.h> +#include <linux/interrupt.h> #define MPC8XXX_GPIO_PINS 32 @@ -127,20 +128,19 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset) return -ENXIO; } -static void mpc8xxx_gpio_irq_cascade(struct irq_desc *desc) +static irqreturn_t mpc8xxx_gpio_irq_cascade(int irq, void *data) { - struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); + struct mpc8xxx_gpio_chip *mpc8xxx_gc = data; struct gpio_chip *gc = &mpc8xxx_gc->gc; - unsigned int mask; + unsigned long mask; + int i; mask = gc->read_reg(mpc8xxx_gc->regs + GPIO_IER) & gc->read_reg(mpc8xxx_gc->regs + GPIO_IMR); - if (mask) - generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, - 32 - ffs(mask))); - if (chip->irq_eoi) - chip->irq_eoi(&desc->irq_data); + for_each_set_bit(i, &mask, 32) + generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, 31 - i)); + + return IRQ_HANDLED; } static void mpc8xxx_irq_unmask(struct irq_data *d) @@ -377,7 +377,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) * It's assumed that only a single type of gpio controller is available * on the current machine, so overwriting global data is fine. */ - mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type; + if (devtype->irq_set_type) + mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type; if (devtype->gpio_dir_out) gc->direction_output = devtype->gpio_dir_out; @@ -386,6 +387,9 @@ static int mpc8xxx_probe(struct platform_device *pdev) gc->to_irq = mpc8xxx_gpio_to_irq; + if (of_device_is_compatible(np, "fsl,qoriq-gpio")) + gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff); + ret = gpiochip_add_data(gc, mpc8xxx_gc); if (ret) { pr_err("%pOF: GPIO chip registration failed with status %d\n", @@ -409,8 +413,16 @@ static int mpc8xxx_probe(struct platform_device *pdev) if (devtype->gpio_dir_in_init) devtype->gpio_dir_in_init(gc); - irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, - mpc8xxx_gpio_irq_cascade, mpc8xxx_gc); + ret = devm_request_irq(&pdev->dev, mpc8xxx_gc->irqn, + mpc8xxx_gpio_irq_cascade, + IRQF_NO_THREAD | IRQF_SHARED, "gpio-cascade", + mpc8xxx_gc); + if (ret) { + dev_err(&pdev->dev, "%s: failed to devm_request_irq(%d), ret = %d\n", + np->full_name, mpc8xxx_gc->irqn, ret); + goto err; + } + return 0; err: iounmap(mpc8xxx_gc->regs); |