From: Asmaa Mnebhi <asmaa@nvidia.com>
To: andy.shevchenko@gmail.com, linux-gpio@vger.kernel.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-acpi@vger.kernel.org
Cc: Asmaa Mnebhi <asmaa@nvidia.com>,
andrew@lunn.ch, kuba@kernel.org, linus.walleij@linaro.org,
bgolaszewski@baylibre.com, davem@davemloft.net,
rjw@rjwysocki.net, davthompson@nvidia.com
Subject: [PATCH v3 1/2] gpio: mlxbf2: Introduce IRQ support
Date: Thu, 23 Sep 2021 16:18:03 -0400 [thread overview]
Message-ID: <20210923201804.15733-2-asmaa@nvidia.com> (raw)
In-Reply-To: <20210923201804.15733-1-asmaa@nvidia.com>
Introduce standard IRQ handling in the gpio-mlxbf2.c
driver.
Signed-off-by: Asmaa Mnebhi <asmaa@nvidia.com>
---
drivers/gpio/gpio-mlxbf2.c | 150 ++++++++++++++++++++++++++++++++++++-
1 file changed, 148 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c
index 177d03ef4529..21c53d18ecd3 100644
--- a/drivers/gpio/gpio-mlxbf2.c
+++ b/drivers/gpio/gpio-mlxbf2.c
@@ -1,9 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES
+ */
+
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
@@ -43,9 +48,14 @@
#define YU_GPIO_MODE0 0x0c
#define YU_GPIO_DATASET 0x14
#define YU_GPIO_DATACLEAR 0x18
+#define YU_GPIO_CAUSE_RISE_EN 0x44
+#define YU_GPIO_CAUSE_FALL_EN 0x48
#define YU_GPIO_MODE1_CLEAR 0x50
#define YU_GPIO_MODE0_SET 0x54
#define YU_GPIO_MODE0_CLEAR 0x58
+#define YU_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x80
+#define YU_GPIO_CAUSE_OR_EVTEN0 0x94
+#define YU_GPIO_CAUSE_OR_CLRCAUSE 0x98
struct mlxbf2_gpio_context_save_regs {
u32 gpio_mode0;
@@ -55,6 +65,7 @@ struct mlxbf2_gpio_context_save_regs {
/* BlueField-2 gpio block context structure. */
struct mlxbf2_gpio_context {
struct gpio_chip gc;
+ struct irq_chip irq_chip;
/* YU GPIO blocks address */
void __iomem *gpio_io;
@@ -218,15 +229,117 @@ static int mlxbf2_gpio_direction_output(struct gpio_chip *chip,
return ret;
}
+static void mlxbf2_gpio_irq_enable(struct irq_data *irqd)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);
+ int offset = irqd_to_hwirq(irqd);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&gs->gc.bgpio_lock, flags);
+ val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE);
+ val |= BIT(offset);
+ writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE);
+
+ val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0);
+ val |= BIT(offset);
+ writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0);
+ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
+}
+
+static void mlxbf2_gpio_irq_disable(struct irq_data *irqd)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);
+ int offset = irqd_to_hwirq(irqd);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&gs->gc.bgpio_lock, flags);
+ val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0);
+ val &= ~BIT(offset);
+ writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0);
+ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
+}
+
+static irqreturn_t mlxbf2_gpio_irq_handler(int irq, void *ptr)
+{
+ struct mlxbf2_gpio_context *gs = ptr;
+ struct gpio_chip *gc = &gs->gc;
+ unsigned long pending;
+ u32 level;
+
+ pending = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CAUSE_EVTEN0);
+ writel(pending, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE);
+
+ for_each_set_bit(level, &pending, gc->ngpio) {
+ int gpio_irq = irq_find_mapping(gc->irq.domain, level);
+ generic_handle_irq(gpio_irq);
+ }
+
+ return IRQ_RETVAL(pending);
+}
+
+static int
+mlxbf2_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+ struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);
+ int offset = irqd_to_hwirq(irqd);
+ unsigned long flags;
+ bool fall = false;
+ bool rise = false;
+ u32 val;
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_BOTH:
+ case IRQ_TYPE_LEVEL_MASK:
+ fall = true;
+ rise = true;
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ case IRQ_TYPE_LEVEL_HIGH:
+ rise = true;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ case IRQ_TYPE_LEVEL_LOW:
+ fall = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&gs->gc.bgpio_lock, flags);
+ if (fall) {
+ val = readl(gs->gpio_io + YU_GPIO_CAUSE_FALL_EN);
+ val |= BIT(offset);
+ writel(val, gs->gpio_io + YU_GPIO_CAUSE_FALL_EN);
+ }
+
+ if (rise) {
+ val = readl(gs->gpio_io + YU_GPIO_CAUSE_RISE_EN);
+ val |= BIT(offset);
+ writel(val, gs->gpio_io + YU_GPIO_CAUSE_RISE_EN);
+ }
+ spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
+
+ return 0;
+}
+
/* BlueField-2 GPIO driver initialization routine. */
static int
mlxbf2_gpio_probe(struct platform_device *pdev)
{
struct mlxbf2_gpio_context *gs;
struct device *dev = &pdev->dev;
+ struct gpio_irq_chip *girq;
struct gpio_chip *gc;
unsigned int npins;
- int ret;
+ const char *name;
+ int ret, irq;
+
+ name = dev_name(dev);
gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL);
if (!gs)
@@ -256,11 +369,44 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
NULL,
0);
+ if (ret) {
+ dev_err(dev, "bgpio_init failed\n");
+ return ret;
+ }
+
gc->direction_input = mlxbf2_gpio_direction_input;
gc->direction_output = mlxbf2_gpio_direction_output;
gc->ngpio = npins;
gc->owner = THIS_MODULE;
+ irq = platform_get_irq(pdev, 0);
+ if (irq >= 0) {
+ gs->irq_chip.name = name;
+ gs->irq_chip.irq_set_type = mlxbf2_gpio_irq_set_type;
+ gs->irq_chip.irq_enable = mlxbf2_gpio_irq_enable;
+ gs->irq_chip.irq_disable = mlxbf2_gpio_irq_disable;
+
+ girq = &gs->gc.irq;
+ girq->chip = &gs->irq_chip;
+ girq->handler = handle_simple_irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ /* This will let us handle the parent IRQ in the driver */
+ girq->num_parents = 0;
+ girq->parents = NULL;
+ girq->parent_handler = NULL;
+
+ /*
+ * Directly request the irq here instead of passing
+ * a flow-handler because the irq is shared.
+ */
+ ret = devm_request_irq(dev, irq, mlxbf2_gpio_irq_handler,
+ IRQF_SHARED, name, gs);
+ if (ret) {
+ dev_err(dev, "failed to request IRQ");
+ return ret;
+ }
+ }
+
platform_set_drvdata(pdev, gs);
ret = devm_gpiochip_add_data(dev, &gs->gc, gs);
@@ -315,5 +461,5 @@ static struct platform_driver mlxbf2_gpio_driver = {
module_platform_driver(mlxbf2_gpio_driver);
MODULE_DESCRIPTION("Mellanox BlueField-2 GPIO Driver");
-MODULE_AUTHOR("Mellanox Technologies");
+MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>");
MODULE_LICENSE("GPL v2");
--
2.30.1
next prev parent reply other threads:[~2021-09-23 20:18 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-09-23 20:18 [PATCH v3 0/2] gpio: mlxbf2: Introduce proper interrupt handling Asmaa Mnebhi
2021-09-23 20:18 ` Asmaa Mnebhi [this message]
2021-09-23 20:18 ` [PATCH v2 2/2] net: mellanox: mlxbf_gige: Replace non-standard " Asmaa Mnebhi
2021-09-23 20:22 [PATCH v3 0/2] gpio: mlxbf2: Introduce proper " Asmaa Mnebhi
2021-09-23 20:22 ` [PATCH v3 1/2] gpio: mlxbf2: Introduce IRQ support Asmaa Mnebhi
2021-09-24 11:46 ` Andrew Lunn
2021-09-24 23:48 ` Linus Walleij
2021-09-27 14:04 ` Asmaa Mnebhi
2021-09-27 14:08 ` Andrew Lunn
2021-09-27 14:19 ` Asmaa Mnebhi
2021-09-27 14:26 ` Asmaa Mnebhi
2021-09-27 14:56 ` Andrew Lunn
2021-09-27 15:52 ` Asmaa Mnebhi
2021-09-27 19:10 ` Andrew Lunn
2021-09-29 19:14 ` Asmaa Mnebhi
2021-09-28 15:02 ` Asmaa Mnebhi
2021-09-29 20:24 ` Andrew Lunn
2021-10-08 14:47 ` Asmaa Mnebhi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210923201804.15733-2-asmaa@nvidia.com \
--to=asmaa@nvidia.com \
--cc=andrew@lunn.ch \
--cc=andy.shevchenko@gmail.com \
--cc=bgolaszewski@baylibre.com \
--cc=davem@davemloft.net \
--cc=davthompson@nvidia.com \
--cc=kuba@kernel.org \
--cc=linus.walleij@linaro.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=rjw@rjwysocki.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.