This commit adds ACPI handling for host-gpio[7] to trigger the power-button event. Signed-off-by: David Thompson <davthompson@xxxxxxxxxx> Reviewed-by: Liming Sun <limings@xxxxxxxxxx> --- drivers/gpio/gpio-mlxbf.c | 65 +++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-mlxbf.c b/drivers/gpio/gpio-mlxbf.c index 1fa9973f55b9..a8b6117c7593 100644 --- a/drivers/gpio/gpio-mlxbf.c +++ b/drivers/gpio/gpio-mlxbf.c @@ -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; } -- 2.30.1