Commit a4c0094f authored by Asmaa Mnebhi's avatar Asmaa Mnebhi Committed by Sebastian Reichel

power: reset: pwr-mlxbf: add BlueField SoC power control driver

This driver supports handling 2 BlueField power states controlled by
GPIO interrupts:

1) chip reset and
2) low power mode
Signed-off-by: default avatarAsmaa Mnebhi <asmaa@nvidia.com>
Signed-off-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
parent e08f8a11
...@@ -297,4 +297,10 @@ config NVMEM_REBOOT_MODE ...@@ -297,4 +297,10 @@ config NVMEM_REBOOT_MODE
then the bootloader can read it and take different then the bootloader can read it and take different
action according to the mode. action according to the mode.
config POWER_MLXBF
tristate "Mellanox BlueField power handling driver"
depends on (GPIO_MLXBF2 && ACPI)
help
This driver supports reset or low power mode handling for Mellanox BlueField.
endif endif
...@@ -35,3 +35,4 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o ...@@ -35,3 +35,4 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o
obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o
obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o
// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause
/*
* Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES.
*/
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/reboot.h>
#include <linux/types.h>
const char *rst_pwr_hid = "MLNXBF24";
const char *low_pwr_hid = "MLNXBF29";
struct pwr_mlxbf {
struct work_struct send_work;
const char *hid;
};
static void pwr_mlxbf_send_work(struct work_struct *work)
{
acpi_bus_generate_netlink_event("button/power.*", "Power Button", 0x80, 1);
}
static irqreturn_t pwr_mlxbf_irq(int irq, void *ptr)
{
struct pwr_mlxbf *priv = ptr;
if (!strncmp(priv->hid, rst_pwr_hid, 8))
emergency_restart();
if (!strncmp(priv->hid, low_pwr_hid, 8))
schedule_work(&priv->send_work);
return IRQ_HANDLED;
}
static int pwr_mlxbf_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acpi_device *adev;
struct pwr_mlxbf *priv;
const char *hid;
int irq, err;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
adev = ACPI_COMPANION(dev);
if (!adev)
return -ENXIO;
hid = acpi_device_hid(adev);
priv->hid = hid;
irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
if (irq < 0)
return dev_err_probe(dev, irq, "Error getting %s irq.\n", priv->hid);
err = devm_work_autocancel(dev, &priv->send_work, pwr_mlxbf_send_work);
if (err)
return err;
err = devm_request_irq(dev, irq, pwr_mlxbf_irq, 0, hid, priv);
if (err)
dev_err(dev, "Failed request of %s irq\n", priv->hid);
return err;
}
static const struct acpi_device_id __maybe_unused pwr_mlxbf_acpi_match[] = {
{ "MLNXBF24", 0 },
{ "MLNXBF29", 0 },
{},
};
MODULE_DEVICE_TABLE(acpi, pwr_mlxbf_acpi_match);
static struct platform_driver pwr_mlxbf_driver = {
.driver = {
.name = "pwr_mlxbf",
.acpi_match_table = pwr_mlxbf_acpi_match,
},
.probe = pwr_mlxbf_probe,
};
module_platform_driver(pwr_mlxbf_driver);
MODULE_DESCRIPTION("Mellanox BlueField power driver");
MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>");
MODULE_LICENSE("Dual BSD/GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment