diff options
Diffstat (limited to 'target/linux/layerscape/patches-5.4/807-gpio-0001-gpio-mpc8xxx-change-irq-handler-from-chained-to-norm.patch')
-rw-r--r-- | target/linux/layerscape/patches-5.4/807-gpio-0001-gpio-mpc8xxx-change-irq-handler-from-chained-to-norm.patch | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/807-gpio-0001-gpio-mpc8xxx-change-irq-handler-from-chained-to-norm.patch b/target/linux/layerscape/patches-5.4/807-gpio-0001-gpio-mpc8xxx-change-irq-handler-from-chained-to-norm.patch new file mode 100644 index 0000000000..01d2772138 --- /dev/null +++ b/target/linux/layerscape/patches-5.4/807-gpio-0001-gpio-mpc8xxx-change-irq-handler-from-chained-to-norm.patch @@ -0,0 +1,80 @@ +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); |