From 9b6d5690b543b8fbf3daf8fc2d7ec7b59b3a3467 Mon Sep 17 00:00:00 2001 From: sachin agarwal Date: Sun, 9 Feb 2020 16:46:20 +0530 Subject: [PATCH 1/7] gpio: ich: fix a typo We had written "Mangagment" rather than "Management". Signed-off-by: Sachin Agarwal Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-ich.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 2f086d0aa1f4..9960bb8b0f5b 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -89,7 +89,7 @@ static struct { struct device *dev; struct gpio_chip chip; struct resource *gpio_base; /* GPIO IO base */ - struct resource *pm_base; /* Power Mangagment IO base */ + struct resource *pm_base; /* Power Management IO base */ struct ichx_desc *desc; /* Pointer to chipset-specific description */ u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */ u8 use_gpio; /* Which GPIO groups are usable */ From 5c85418ab35bc84d33947e45b2e0ffe55aa8a484 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 14 Apr 2020 20:48:57 +0300 Subject: [PATCH 2/7] gpio: pch: Use BIT() and GENMASK() where it's appropriate Use BIT() and GENMASK() where it's appropriate. At the same time drop it where it's not appropriate. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-pch.c | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 3f3d9a94b709..03eeacdb04fb 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. */ +#include #include #include #include @@ -11,11 +12,11 @@ #include #define PCH_EDGE_FALLING 0 -#define PCH_EDGE_RISING BIT(0) -#define PCH_LEVEL_L BIT(1) -#define PCH_LEVEL_H (BIT(0) | BIT(1)) -#define PCH_EDGE_BOTH BIT(2) -#define PCH_IM_MASK (BIT(0) | BIT(1) | BIT(2)) +#define PCH_EDGE_RISING 1 +#define PCH_LEVEL_L 2 +#define PCH_LEVEL_H 3 +#define PCH_EDGE_BOTH 4 +#define PCH_IM_MASK GENMASK(2, 0) #define PCH_IRQ_BASE 24 @@ -103,9 +104,9 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) spin_lock_irqsave(&chip->spinlock, flags); reg_val = ioread32(&chip->reg->po); if (val) - reg_val |= (1 << nr); + reg_val |= BIT(nr); else - reg_val &= ~(1 << nr); + reg_val &= ~BIT(nr); iowrite32(reg_val, &chip->reg->po); spin_unlock_irqrestore(&chip->spinlock, flags); @@ -115,7 +116,7 @@ static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr) { struct pch_gpio *chip = gpiochip_get_data(gpio); - return (ioread32(&chip->reg->pi) >> nr) & 1; + return !!(ioread32(&chip->reg->pi) & BIT(nr)); } static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, @@ -130,13 +131,14 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, reg_val = ioread32(&chip->reg->po); if (val) - reg_val |= (1 << nr); + reg_val |= BIT(nr); else - reg_val &= ~(1 << nr); + reg_val &= ~BIT(nr); iowrite32(reg_val, &chip->reg->po); - pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); - pm |= (1 << nr); + pm = ioread32(&chip->reg->pm); + pm &= BIT(gpio_pins[chip->ioh]) - 1; + pm |= BIT(nr); iowrite32(pm, &chip->reg->pm); spin_unlock_irqrestore(&chip->spinlock, flags); @@ -151,8 +153,9 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) unsigned long flags; spin_lock_irqsave(&chip->spinlock, flags); - pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); - pm &= ~(1 << nr); + pm = ioread32(&chip->reg->pm); + pm &= BIT(gpio_pins[chip->ioh]) - 1; + pm &= ~BIT(nr); iowrite32(pm, &chip->reg->pm); spin_unlock_irqrestore(&chip->spinlock, flags); @@ -277,7 +280,7 @@ static void pch_irq_unmask(struct irq_data *d) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct pch_gpio *chip = gc->private; - iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imaskclr); + iowrite32(BIT(d->irq - chip->irq_base), &chip->reg->imaskclr); } static void pch_irq_mask(struct irq_data *d) @@ -285,7 +288,7 @@ static void pch_irq_mask(struct irq_data *d) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct pch_gpio *chip = gc->private; - iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->imask); + iowrite32(BIT(d->irq - chip->irq_base), &chip->reg->imask); } static void pch_irq_ack(struct irq_data *d) @@ -293,7 +296,7 @@ static void pch_irq_ack(struct irq_data *d) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); struct pch_gpio *chip = gc->private; - iowrite32(1 << (d->irq - chip->irq_base), &chip->reg->iclr); + iowrite32(BIT(d->irq - chip->irq_base), &chip->reg->iclr); } static irqreturn_t pch_gpio_handler(int irq, void *dev_id) @@ -344,7 +347,6 @@ static int pch_gpio_probe(struct pci_dev *pdev, s32 ret; struct pch_gpio *chip; int irq_base; - u32 msk; chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); if (chip == NULL) @@ -357,7 +359,7 @@ static int pch_gpio_probe(struct pci_dev *pdev, return ret; } - ret = pcim_iomap_regions(pdev, 1 << 1, KBUILD_MODNAME); + ret = pcim_iomap_regions(pdev, BIT(1), KBUILD_MODNAME); if (ret) { dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret); return ret; @@ -393,9 +395,8 @@ static int pch_gpio_probe(struct pci_dev *pdev, chip->irq_base = irq_base; /* Mask all interrupts, but enable them */ - msk = (1 << gpio_pins[chip->ioh]) - 1; - iowrite32(msk, &chip->reg->imask); - iowrite32(msk, &chip->reg->ien); + iowrite32(BIT(gpio_pins[chip->ioh]) - 1, &chip->reg->imask); + iowrite32(BIT(gpio_pins[chip->ioh]) - 1, &chip->reg->ien); ret = devm_request_irq(&pdev->dev, pdev->irq, pch_gpio_handler, IRQF_SHARED, KBUILD_MODNAME, chip); From 5a4245de48d87f9300c3cac7c62e1af18916fb22 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 14 Apr 2020 20:48:58 +0300 Subject: [PATCH 3/7] gpio: pch: Get rid of unneeded variable in IRQ handler There is no need to have an additional variable in IRQ handler. We may simple rely on the fact of having non-zero register value we read from the hardware. While here, drop repetitive messages in time critical function. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-pch.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 03eeacdb04fb..708272db6baf 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -303,14 +303,15 @@ static irqreturn_t pch_gpio_handler(int irq, void *dev_id) { struct pch_gpio *chip = dev_id; unsigned long reg_val = ioread32(&chip->reg->istatus); - int i, ret = IRQ_NONE; + int i; - for_each_set_bit(i, ®_val, gpio_pins[chip->ioh]) { - dev_dbg(chip->dev, "[%d]:irq=%d status=0x%lx\n", i, irq, reg_val); + dev_dbg(chip->dev, "irq=%d status=0x%lx\n", irq, reg_val); + + reg_val &= BIT(gpio_pins[chip->ioh]) - 1; + for_each_set_bit(i, ®_val, gpio_pins[chip->ioh]) generic_handle_irq(chip->irq_base + i); - ret = IRQ_HANDLED; - } - return ret; + + return IRQ_RETVAL(reg_val); } static int pch_gpio_alloc_generic_chip(struct pch_gpio *chip, From 368b8436011ac5138230b98bb34923b7f77ae533 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 14 Apr 2020 20:48:59 +0300 Subject: [PATCH 4/7] gpio: pch: Refactor pch_irq_type() to avoid unnecessary locking When type is not supported there is no need to lock and check. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-pch.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 708272db6baf..9c34230f2e84 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -229,17 +229,15 @@ static int pch_irq_type(struct irq_data *d, unsigned int type) int ch, irq = d->irq; ch = irq - chip->irq_base; - if (irq <= chip->irq_base + 7) { + if (irq < chip->irq_base + 8) { im_reg = &chip->reg->im0; - im_pos = ch; + im_pos = ch - 0; } else { im_reg = &chip->reg->im1; im_pos = ch - 8; } dev_dbg(chip->dev, "irq=%d type=%d ch=%d pos=%d\n", irq, type, ch, im_pos); - spin_lock_irqsave(&chip->spinlock, flags); - switch (type) { case IRQ_TYPE_EDGE_RISING: val = PCH_EDGE_RISING; @@ -257,9 +255,11 @@ static int pch_irq_type(struct irq_data *d, unsigned int type) val = PCH_LEVEL_L; break; default: - goto unlock; + return 0; } + spin_lock_irqsave(&chip->spinlock, flags); + /* Set interrupt mode */ im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4)); iowrite32(im | (val << (im_pos * 4)), im_reg); @@ -270,7 +270,6 @@ static int pch_irq_type(struct irq_data *d, unsigned int type) else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) irq_set_handler_locked(d, handle_edge_irq); -unlock: spin_unlock_irqrestore(&chip->spinlock, flags); return 0; } From 5376b0b31295364f3a166ee82f1a7d893bcbf8e9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 14 Apr 2020 20:49:00 +0300 Subject: [PATCH 5/7] gpio: pch: Use in pch_irq_type() macros provided by IRQ core Use in pch_irq_type() the macros provided by IRQ core for IRQ type. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-pch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 9c34230f2e84..e96d28bf43b4 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -265,9 +265,9 @@ static int pch_irq_type(struct irq_data *d, unsigned int type) iowrite32(im | (val << (im_pos * 4)), im_reg); /* And the handler */ - if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) + if (type & IRQ_TYPE_LEVEL_MASK) irq_set_handler_locked(d, handle_level_irq); - else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) + else if (type & IRQ_TYPE_EDGE_BOTH) irq_set_handler_locked(d, handle_edge_irq); spin_unlock_irqrestore(&chip->spinlock, flags); From 6b1c7837af0e29ad630f0ae18634f6c58a3381ee Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 8 Apr 2020 18:41:54 +0300 Subject: [PATCH 6/7] gpio: merrifield: Switch over to MSI interrupts Some devices may support MSI interrupts. Let's at least try to use them in platforms that provide MSI capability. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-merrifield.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 48918a016cd8..11e6ea70568a 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -473,6 +473,10 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id raw_spin_lock_init(&priv->lock); + retval = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (retval < 0) + return retval; + girq = &priv->chip.irq; girq->chip = &mrfld_irqchip; girq->init_hw = mrfld_irq_init_hw; @@ -482,7 +486,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id sizeof(*girq->parents), GFP_KERNEL); if (!girq->parents) return -ENOMEM; - girq->parents[0] = pdev->irq; + girq->parents[0] = pci_irq_vector(pdev, 0); girq->first = irq_base; girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_bad_irq; From 7e73aa90a38c8815acea7af71e285658bf5ab879 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 8 Apr 2020 18:41:55 +0300 Subject: [PATCH 7/7] gpio: merrifield: Better show how GPIO and IRQ bases are derived from hardware It's a bit hard to realize what the BAR1 is for and what is the layout of the data in it. Be slightly more verbose to better show how GPIO and IRQ bases are derived from the hardware. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-merrifield.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 11e6ea70568a..706687fab634 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -443,8 +443,8 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id base = pcim_iomap_table(pdev)[1]; - irq_base = readl(base); - gpio_base = readl(sizeof(u32) + base); + irq_base = readl(base + 0 * sizeof(u32)); + gpio_base = readl(base + 1 * sizeof(u32)); /* Release the IO mapping, since we already get the info from BAR1 */ pcim_iounmap_regions(pdev, BIT(1));