[v1,v/1] gpio: mlxbf: enable GPIO interface and ACPI event for host-gpio[7]
Commit Message
This commit adds ACPI handling for host-gpio[7] to trigger
the power-button event.
Signed-off-by: David Thompson <davthompson@nvidia.com>
Reviewed-by: Liming Sun <limings@nvidia.com>
---
drivers/gpio/gpio-mlxbf.c | 65 +++++++++++++++++++++++++++++++++------
1 file changed, 55 insertions(+), 10 deletions(-)
Comments
On Fri, Feb 03, 2023 at 01:49:07PM -0500, David Thompson wrote:
> This commit adds ACPI handling for host-gpio[7] to trigger
> the power-button event.
This has something to discuss...
...
> /* Pad Electrical Controls. */
> -#define MLXBF_GPIO_PAD_CONTROL_FIRST_WORD 0x0700
> -#define MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD 0x0708
> -#define MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD 0x0710
> -#define MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD 0x0718
> +#define MLXBF_GPIO_PAD_CONTROL_FIRST_WORD 0x0700
> +#define MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD 0x0708
> +#define MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD 0x0710
> +#define MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD 0x0718
Unrelated change.
> +#define MLXBF_GPIO_PIN_DIR_I 0x1040
> +#define MLXBF_GPIO_PIN_DIR_O 0x1048
> +#define MLXBF_GPIO_PIN_STATE 0x1000
> +#define MLXBF_GPIO_SCRATCHPAD 0x20
Ditto. You already have it defined, why to change?
> -#define MLXBF_GPIO_PIN_DIR_I 0x1040
> -#define MLXBF_GPIO_PIN_DIR_O 0x1048
> -#define MLXBF_GPIO_PIN_STATE 0x1000
> -#define MLXBF_GPIO_SCRATCHPAD 0x20
...
> + gs->hwirq = irq;
> + gc->to_irq = mlxbf_gpio_to_irq;
This sounds incorrect. Seems like for _any_ interrupt you will give the same
result. Moreover, you should not use to_irq(). Try to model proper IRQ chip.
...
> platform_set_drvdata(pdev, gs);
> + acpi_gpiochip_request_interrupts(gc);
This is done by GPIO library, no?
...
> dev_info(&pdev->dev, "registered Mellanox BlueField GPIO");
> +
> return 0;
Stray change.
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/acpi.h>
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/gpio/driver.h>
@@ -12,19 +13,30 @@
#include <linux/resource.h>
#include <linux/types.h>
+#include "gpiolib-acpi.h"
+
/* Number of pins on BlueField */
#define MLXBF_GPIO_NR 54
/* Pad Electrical Controls. */
-#define MLXBF_GPIO_PAD_CONTROL_FIRST_WORD 0x0700
-#define MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD 0x0708
-#define MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD 0x0710
-#define MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD 0x0718
+#define MLXBF_GPIO_PAD_CONTROL_FIRST_WORD 0x0700
+#define MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD 0x0708
+#define MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD 0x0710
+#define MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD 0x0718
+
+#define MLXBF_GPIO_PIN_DIR_I 0x1040
+#define MLXBF_GPIO_PIN_DIR_O 0x1048
+#define MLXBF_GPIO_PIN_STATE 0x1000
+#define MLXBF_GPIO_SCRATCHPAD 0x20
+#define MLXBF_GPIO_INT_SETUP 0x0040
+#define MLXBF_GPIO_INT_SETUP_GBL_ENA_MASK 0x1
+
+/* GPIO pin 7 is reserved for power good indication on BlueField. */
+#define MLXBF_GPIO_POWER_GOOD_PIN 7
-#define MLXBF_GPIO_PIN_DIR_I 0x1040
-#define MLXBF_GPIO_PIN_DIR_O 0x1048
-#define MLXBF_GPIO_PIN_STATE 0x1000
-#define MLXBF_GPIO_SCRATCHPAD 0x20
+/* GPIO pins enabled for interrupt */
+#define MLXBF_GPIO_INT_ENA_DEASSERT 0x3008
+#define MLXBF_GPIO_INT_DEASSERT_ENA_BITS BIT(MLXBF_GPIO_POWER_GOOD_PIN)
#ifdef CONFIG_PM
struct mlxbf_gpio_context_save_regs {
@@ -42,17 +54,39 @@ struct mlxbf_gpio_state {
/* Memory Address */
void __iomem *base;
+ int hwirq;
+
#ifdef CONFIG_PM
struct mlxbf_gpio_context_save_regs csave_regs;
#endif
};
+static int mlxbf_gpio_to_irq(struct gpio_chip *chip, u32 gpio)
+{
+ struct mlxbf_gpio_state *gs = gpiochip_get_data(chip);
+
+ return gs->hwirq;
+}
+
+static void mlxbf_gpio_cfg_irq(struct mlxbf_gpio_state *gs)
+{
+ u64 intr_cfg;
+
+ intr_cfg = readq(gs->base + MLXBF_GPIO_INT_SETUP);
+ intr_cfg |= MLXBF_GPIO_INT_SETUP_GBL_ENA_MASK;
+ writeq(intr_cfg, gs->base + MLXBF_GPIO_INT_SETUP);
+
+ intr_cfg = readq(gs->base + MLXBF_GPIO_INT_ENA_DEASSERT);
+ intr_cfg |= MLXBF_GPIO_INT_DEASSERT_ENA_BITS;
+ writeq(intr_cfg, gs->base + MLXBF_GPIO_INT_ENA_DEASSERT);
+}
+
static int mlxbf_gpio_probe(struct platform_device *pdev)
{
- struct mlxbf_gpio_state *gs;
struct device *dev = &pdev->dev;
+ struct mlxbf_gpio_state *gs;
struct gpio_chip *gc;
- int ret;
+ int ret, irq;
gs = devm_kzalloc(&pdev->dev, sizeof(*gs), GFP_KERNEL);
if (!gs)
@@ -63,6 +97,7 @@ static int mlxbf_gpio_probe(struct platform_device *pdev)
return PTR_ERR(gs->base);
gc = &gs->gc;
+
ret = bgpio_init(gc, dev, 8,
gs->base + MLXBF_GPIO_PIN_STATE,
NULL,
@@ -73,8 +108,16 @@ static int mlxbf_gpio_probe(struct platform_device *pdev)
if (ret)
return -ENODEV;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
gc->owner = THIS_MODULE;
gc->ngpio = MLXBF_GPIO_NR;
+ gs->hwirq = irq;
+ gc->to_irq = mlxbf_gpio_to_irq;
+
+ mlxbf_gpio_cfg_irq(gs);
ret = devm_gpiochip_add_data(dev, &gs->gc, gs);
if (ret) {
@@ -83,7 +126,9 @@ static int mlxbf_gpio_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, gs);
+ acpi_gpiochip_request_interrupts(gc);
dev_info(&pdev->dev, "registered Mellanox BlueField GPIO");
+
return 0;
}