mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 15:02:32 +00:00
81 lines
2.7 KiB
Diff
81 lines
2.7 KiB
Diff
|
From 8070fa91b95e20cd270c8d76bf45f2a5423358bf Mon Sep 17 00:00:00 2001
|
||
|
From: Song Hui <hui.song_1@nxp.com>
|
||
|
Date: Fri, 6 Sep 2019 19:42:59 +0800
|
||
|
Subject: [PATCH] gpio/mpc8xxx: change irq handler from chained to normal
|
||
|
|
||
|
More than one gpio controllers can share one interrupt, change the
|
||
|
driver to request shared irq.
|
||
|
|
||
|
While this will work, it will mess up userspace accounting of the number
|
||
|
of interrupts per second in tools such as vmstat. The reason is that
|
||
|
for every GPIO interrupt, /proc/interrupts records the count against GIC
|
||
|
interrupt 68 or 69, as well as the GPIO itself. So, for every GPIO
|
||
|
interrupt, the total number of interrupts that the system has seen
|
||
|
increments by two.
|
||
|
|
||
|
Signed-off-by: Laurentiu Tudor <Laurentiu.Tudor@nxp.com>
|
||
|
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
|
||
|
Signed-off-by: Song Hui <hui.song_1@nxp.com>
|
||
|
---
|
||
|
drivers/gpio/gpio-mpc8xxx.c | 30 +++++++++++++++++++-----------
|
||
|
1 file changed, 19 insertions(+), 11 deletions(-)
|
||
|
|
||
|
--- 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 gp
|
||
|
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)
|
||
|
@@ -414,8 +414,16 @@ static int mpc8xxx_probe(struct platform
|
||
|
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);
|