From: a0282524688@gmail.com
To: lee@kernel.org, Ming Yu <tmyu0@nuvoton.com>
Cc: linux-kernel@vger.kernel.org, Ming Yu <a0282524688@gmail.com>
Subject: [PATCH v6 7/7] mfd: nct6694: Add Host Interface (HIF) eSPI transport driver
Date: Wed, 1 Jul 2026 11:50:25 +0800 [thread overview]
Message-ID: <20260701035025.3082927-8-a0282524688@gmail.com> (raw)
In-Reply-To: <20260701035025.3082927-1-a0282524688@gmail.com>
From: Ming Yu <a0282524688@gmail.com>
Add support for the Host Interface (HIF) transport via eSPI for the
Nuvoton NCT6694 peripheral expander.
This transport driver initializes the Super-I/O to configure the
device's shared memory base address and SIRQ. It provides a regmap_bus
implementation that drives the firmware command/response exchange over
the shared-memory window, plus an internal regmap_mmio for the report
region. The initialized device config is then passed to the MFD core
(nct6694_core_probe) for sub-device registration and IRQ domain setup.
Signed-off-by: Ming Yu <a0282524688@gmail.com>
---
Changes in v6:
- Reworked the transport to implement a regmap_bus instead of the v5
read_msg/write_msg function pointers.
Changes in v5:
- Split from the monolithic v4 patch.
- Adapted to re-use the newly introduced nct6694_core_probe() and
abstracted I/O APIs.
Changes since version 3:
- Remove redundant module type macro definitions from sub-device drivers
that are now provided by the shared header <linux/mfd/nct6694.h>,
fixing -Wmacro-redefined warnings.
Changes since version 2:
- Restore per-device IDA and mfd_add_hotplug_devices()/PLATFORM_DEVID_AUTO
to avoid child device ID conflicts with multiple NCT6694 chips.
- Validate irq_find_mapping() return value before dispatching IRQs.
- Check superio_enter() return value in nct6694_irq_init().
Changes since version 1:
- Drop function pointers from Super-I/O access and use static inline
helpers with proper types.
drivers/mfd/Kconfig | 16 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/nct6694-hif.c | 565 ++++++++++++++++++++++++++++++++++++++
3 files changed, 582 insertions(+)
create mode 100644 drivers/mfd/nct6694-hif.c
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 742fc26e6ff7..f37acf585671 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1175,6 +1175,22 @@ config MFD_NCT6694
It is selected automatically by the transport interface drivers.
+config MFD_NCT6694_HIF
+ tristate "Nuvoton NCT6694 HIF (eSPI) interface support"
+ depends on HAS_IOPORT && ACPI
+ select MFD_NCT6694
+ select REGMAP_MMIO
+ help
+ This enables support for the Nuvoton NCT6694 peripheral expander
+ connected via the Host Interface (HIF) using eSPI transport.
+
+ The transport driver uses Super-I/O mapping and shared memory to
+ communicate with the NCT6694 firmware. Enable this option if you
+ are using the NCT6694 over an eSPI interface on an ACPI platform.
+
+ To compile this driver as a module, choose M here: the module
+ will be called nct6694-hif.
+
config MFD_NCT6694_USB
tristate "Nuvoton NCT6694 USB interface support"
select MFD_NCT6694
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 10c19a19541e..97924dd3552c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -125,6 +125,7 @@ obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
obj-$(CONFIG_MFD_PF1550) += pf1550.o
obj-$(CONFIG_MFD_NCT6694) += nct6694-core.o
+obj-$(CONFIG_MFD_NCT6694_HIF) += nct6694-hif.o
obj-$(CONFIG_MFD_NCT6694_USB) += nct6694-usb.o
obj-$(CONFIG_MFD_CORE) += mfd-core.o
diff --git a/drivers/mfd/nct6694-hif.c b/drivers/mfd/nct6694-hif.c
new file mode 100644
index 000000000000..c47534a1e526
--- /dev/null
+++ b/drivers/mfd/nct6694-hif.c
@@ -0,0 +1,565 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 Nuvoton Technology Corp.
+ *
+ * Nuvoton NCT6694 host-interface (eSPI) transport driver.
+ */
+
+#include <linux/acpi.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/nct6694.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/unaligned.h>
+
+#define DRVNAME "nct6694-hif"
+
+#define NCT6694_POLL_INTERVAL_US 10
+#define NCT6694_POLL_TIMEOUT_US 10000
+
+/*
+ * Super-I/O registers
+ */
+#define SIO_REG_LDSEL 0x07 /* Logical device select */
+#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
+#define SIO_REG_LD_SHM 0x0F /* Logical device shared memory control */
+
+#define SIO_REG_SHM_ENABLE 0x30 /* Enable shared memory */
+#define SIO_REG_SHM_BASE_ADDR 0x60 /* Shared memory base address (2 bytes) */
+#define SIO_REG_SHM_IRQ_NR 0x70 /* Shared memory interrupt number */
+
+#define SIO_REG_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
+#define SIO_REG_LOCK_KEY 0xAA /* Key to disable Super-I/O */
+
+#define SIO_NCT6694B_ID 0xD029
+#define SIO_NCT6694D_ID 0x5832
+
+/*
+ * Super-I/O Shared Memory Logical Device registers
+ */
+#define NCT6694_SHM_COFS_STS 0x2E
+#define NCT6694_SHM_COFS_STS_COFS4W BIT(7)
+
+#define NCT6694_SHM_COFS_CTL2 0x3B
+#define NCT6694_SHM_COFS_CTL2_COFS4W_IE BIT(3)
+
+/* COFS register block [STS..CTL2] is the only SHM range driven via inb/outb */
+#define NCT6694_SHM_COFS_LEN \
+ (NCT6694_SHM_COFS_CTL2 - NCT6694_SHM_COFS_STS + 1)
+
+#define NCT6694_SHM_INTR_STATUS 0x9C /* Interrupt status register (4 bytes) */
+
+enum nct6694_chips {
+ NCT6694B = 0,
+ NCT6694D,
+};
+
+struct __packed nct6694_hif_msg {
+ struct nct6694_cmd_header cmd_header;
+ struct nct6694_response_header response_header;
+ unsigned char data[];
+};
+
+struct nct6694_sio_data {
+ enum nct6694_chips chip;
+ int sioreg; /* Super-I/O index port */
+};
+
+struct nct6694_hif_data {
+ struct regmap *rpt_regmap;
+ struct nct6694_sio_data *sio_data;
+ void __iomem *msg_base;
+ void *xfer_buf;
+ unsigned int shm_base;
+};
+
+static const char * const nct6694_chip_names[] = {
+ [NCT6694B] = "NCT6694B",
+ [NCT6694D] = "NCT6694D",
+};
+
+/*
+ * Super-I/O functions.
+ */
+static inline int superio_enter(struct nct6694_sio_data *sio_data)
+{
+ int ioreg = sio_data->sioreg;
+
+ /*
+ * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
+ */
+ if (!request_muxed_region(ioreg, 2, DRVNAME))
+ return -EBUSY;
+
+ outb(SIO_REG_UNLOCK_KEY, ioreg);
+ outb(SIO_REG_UNLOCK_KEY, ioreg);
+
+ return 0;
+}
+
+static inline void superio_exit(struct nct6694_sio_data *sio_data)
+{
+ int ioreg = sio_data->sioreg;
+
+ outb(SIO_REG_LOCK_KEY, ioreg);
+
+ release_region(ioreg, 2);
+}
+
+static inline void superio_select(struct nct6694_sio_data *sio_data, int ld)
+{
+ int ioreg = sio_data->sioreg;
+
+ outb(SIO_REG_LDSEL, ioreg);
+ outb(ld, ioreg + 1);
+}
+
+static inline int superio_inb(struct nct6694_sio_data *sio_data, int reg)
+{
+ int ioreg = sio_data->sioreg;
+
+ outb(reg, ioreg);
+ return inb(ioreg + 1);
+}
+
+static inline int superio_inw(struct nct6694_sio_data *sio_data, int reg)
+{
+ int ioreg = sio_data->sioreg;
+ int val;
+
+ outb(reg++, ioreg);
+ val = inb(ioreg + 1) << 8;
+ outb(reg, ioreg);
+ val |= inb(ioreg + 1);
+
+ return val;
+}
+
+static inline void superio_outb(struct nct6694_sio_data *sio_data, int reg, u8 val)
+{
+ int ioreg = sio_data->sioreg;
+
+ outb(reg, ioreg);
+ outb(val, ioreg + 1);
+}
+
+static int nct6694_sio_find(struct nct6694_sio_data *sio_data, u8 sioreg)
+{
+ int ret;
+ u16 devid;
+
+ sio_data->sioreg = sioreg;
+
+ ret = superio_enter(sio_data);
+ if (ret)
+ return ret;
+
+ /* Check Chip ID */
+ devid = superio_inw(sio_data, SIO_REG_DEVID);
+ switch (devid) {
+ case SIO_NCT6694B_ID:
+ sio_data->chip = NCT6694B;
+ break;
+ case SIO_NCT6694D_ID:
+ sio_data->chip = NCT6694D;
+ break;
+ default:
+ superio_exit(sio_data);
+ return -ENODEV;
+ }
+
+ superio_exit(sio_data);
+
+ return 0;
+}
+
+static const struct mfd_cell nct6694_hif_devs[] = {
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+ MFD_CELL_NAME("nct6694-gpio"),
+
+ MFD_CELL_NAME("nct6694-i2c"),
+ MFD_CELL_NAME("nct6694-i2c"),
+ MFD_CELL_NAME("nct6694-i2c"),
+ MFD_CELL_NAME("nct6694-i2c"),
+ MFD_CELL_NAME("nct6694-i2c"),
+ MFD_CELL_NAME("nct6694-i2c"),
+
+ MFD_CELL_NAME("nct6694-canfd"),
+ MFD_CELL_NAME("nct6694-canfd"),
+};
+
+static int nct6694_hif_err_handling(struct nct6694 *nct6694, unsigned char err_status)
+{
+ switch (err_status) {
+ case NCT6694_NO_ERROR:
+ return 0;
+ case NCT6694_NOT_SUPPORT_ERROR:
+ dev_err(nct6694->dev, "Command is not supported!\n");
+ break;
+ case NCT6694_NO_RESPONSE_ERROR:
+ dev_warn(nct6694->dev, "Command received no response!\n");
+ break;
+ case NCT6694_TIMEOUT_ERROR:
+ dev_warn(nct6694->dev, "Command timed out!\n");
+ break;
+ case NCT6694_PENDING:
+ dev_err(nct6694->dev, "Command is pending!\n");
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return -EIO;
+}
+
+static int nct6694_hif_xfer_msg(struct nct6694 *nct6694,
+ const struct nct6694_cmd_header *cmd_hd,
+ u8 hctrl, void *buf)
+{
+ struct nct6694_hif_data *hdata = nct6694->priv;
+ void __iomem *hdr = hdata->msg_base + offsetof(struct nct6694_hif_msg, cmd_header);
+ struct nct6694_cmd_header cmd = *cmd_hd;
+ struct nct6694_response_header resp;
+ u16 len = le16_to_cpu(cmd.len);
+ u8 status;
+ int ret;
+
+ /* Wait until the previous command is completed */
+ ret = readb_poll_timeout(hdr + offsetof(struct nct6694_cmd_header, hctrl),
+ status, status == 0, NCT6694_POLL_INTERVAL_US,
+ NCT6694_POLL_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /*
+ * Write cmd header fields, but skip hctrl — writing to it triggers
+ * firmware command processing and must be deferred until data is ready.
+ */
+ memcpy_toio(hdr, &cmd, offsetof(struct nct6694_cmd_header, hctrl));
+ memcpy_toio(hdr + offsetof(struct nct6694_cmd_header, rsv2), &cmd.rsv2,
+ sizeof(cmd) - offsetof(struct nct6694_cmd_header, rsv2));
+
+ if (hctrl == NCT6694_HCTRL_SET && len)
+ memcpy_toio(hdata->msg_base + offsetof(struct nct6694_hif_msg, data),
+ buf, len);
+
+ /* Write hctrl last to trigger command processing */
+ writeb(hctrl, hdr + offsetof(struct nct6694_cmd_header, hctrl));
+
+ ret = readb_poll_timeout(hdr + offsetof(struct nct6694_cmd_header, hctrl),
+ status, status == 0, NCT6694_POLL_INTERVAL_US,
+ NCT6694_POLL_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ memcpy_fromio(&resp, hdata->msg_base + offsetof(struct nct6694_hif_msg, response_header),
+ sizeof(resp));
+
+ ret = nct6694_hif_err_handling(nct6694, resp.sts);
+ if (ret)
+ return ret;
+
+ if (le16_to_cpu(resp.len))
+ memcpy_fromio(buf, hdata->msg_base + offsetof(struct nct6694_hif_msg, data),
+ min(len, le16_to_cpu(resp.len)));
+
+ return 0;
+}
+
+static int nct6694_hif_regmap_read(void *context, const void *reg_buf,
+ size_t reg_size, void *val_buf,
+ size_t val_size)
+{
+ struct nct6694 *nct6694 = context;
+ struct nct6694_hif_data *hdata = nct6694->priv;
+ u32 reg = get_unaligned_be32(reg_buf);
+ const struct nct6694_cmd_header cmd_hd = {
+ .mod = FIELD_GET(NCT6694_REG_MOD, reg),
+ .offset = cpu_to_le16(FIELD_GET(NCT6694_REG_OFFSET, reg)),
+ .len = cpu_to_le16(val_size),
+ };
+
+ if (FIELD_GET(NCT6694_REG_MOD, reg) == NCT6694_RPT_MOD)
+ return regmap_bulk_read(hdata->rpt_regmap,
+ FIELD_GET(NCT6694_REG_OFFSET, reg),
+ val_buf, val_size);
+
+ return nct6694_hif_xfer_msg(nct6694, &cmd_hd,
+ FIELD_GET(NCT6694_REG_HCTRL, reg), val_buf);
+}
+
+static int nct6694_hif_regmap_write(void *context, const void *data,
+ size_t count)
+{
+ struct nct6694 *nct6694 = context;
+ struct nct6694_hif_data *hdata = nct6694->priv;
+ u32 reg = get_unaligned_be32(data);
+ size_t len = count - sizeof(reg);
+ const struct nct6694_cmd_header cmd_hd = {
+ .mod = FIELD_GET(NCT6694_REG_MOD, reg),
+ .offset = cpu_to_le16(FIELD_GET(NCT6694_REG_OFFSET, reg)),
+ .len = cpu_to_le16(len),
+ };
+
+ if (FIELD_GET(NCT6694_REG_MOD, reg) == NCT6694_RPT_MOD)
+ return regmap_bulk_write(hdata->rpt_regmap,
+ FIELD_GET(NCT6694_REG_OFFSET, reg),
+ data + sizeof(reg), len);
+
+ if (len > NCT6694_MAX_PACKET_SIZE)
+ return -EINVAL;
+
+ /*
+ * nct6694_hif_xfer_msg() reads the firmware response back into the
+ * payload buffer, so copy the const regmap data into a scratch buffer
+ * it can write to.
+ */
+ memcpy(hdata->xfer_buf, data + sizeof(reg), len);
+
+ return nct6694_hif_xfer_msg(nct6694, &cmd_hd, NCT6694_HCTRL_SET,
+ hdata->xfer_buf);
+}
+
+static const struct regmap_bus nct6694_hif_regmap_bus = {
+ .read = nct6694_hif_regmap_read,
+ .write = nct6694_hif_regmap_write,
+};
+
+static const struct regmap_config nct6694_hif_msg_regmap_config = {
+ .name = "msg",
+ .reg_bits = 32,
+ .val_bits = 8,
+ .reg_stride = 1,
+ .max_raw_read = NCT6694_MAX_PACKET_SIZE,
+ .max_raw_write = NCT6694_MAX_PACKET_SIZE,
+};
+
+static const struct regmap_config nct6694_hif_rpt_regmap_config = {
+ .name = "rpt",
+ .reg_bits = 8,
+ .val_bits = 8,
+ .reg_stride = 1,
+};
+
+static irqreturn_t nct6694_hif_irq_handler(int irq, void *data)
+{
+ struct nct6694 *nct6694 = data;
+ struct nct6694_hif_data *hdata = nct6694->priv;
+ u8 reg_data[4];
+ u32 intr_status;
+ int ret;
+
+ /* Check interrupt status is set */
+ if (!(inb(hdata->shm_base + NCT6694_SHM_COFS_STS) & NCT6694_SHM_COFS_STS_COFS4W))
+ return IRQ_NONE;
+
+ /* Clear interrupt status */
+ outb(NCT6694_SHM_COFS_STS_COFS4W, hdata->shm_base + NCT6694_SHM_COFS_STS);
+
+ ret = regmap_bulk_read(hdata->rpt_regmap, NCT6694_SHM_INTR_STATUS,
+ reg_data, ARRAY_SIZE(reg_data));
+ if (ret)
+ return IRQ_NONE;
+
+ intr_status = get_unaligned_le32(reg_data);
+
+ while (intr_status) {
+ int hwirq = __ffs(intr_status);
+
+ generic_handle_irq_safe(irq_find_mapping(nct6694->domain, hwirq));
+ intr_status &= ~BIT(hwirq);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void nct6694_hif_irq_disable(void *data)
+{
+ struct nct6694 *nct6694 = data;
+ struct nct6694_hif_data *hdata = nct6694->priv;
+ u8 cofs_ctl2;
+
+ /* Disable SIRQ interrupt */
+ cofs_ctl2 = inb(hdata->shm_base + NCT6694_SHM_COFS_CTL2);
+ cofs_ctl2 &= ~NCT6694_SHM_COFS_CTL2_COFS4W_IE;
+ outb(cofs_ctl2, hdata->shm_base + NCT6694_SHM_COFS_CTL2);
+}
+
+static void nct6694_hif_irq_enable(struct nct6694 *nct6694)
+{
+ struct nct6694_hif_data *hdata = nct6694->priv;
+ u8 cofs_ctl2;
+
+ /* Enable SIRQ interrupt */
+ cofs_ctl2 = inb(hdata->shm_base + NCT6694_SHM_COFS_CTL2);
+ cofs_ctl2 |= NCT6694_SHM_COFS_CTL2_COFS4W_IE;
+ outb(cofs_ctl2, hdata->shm_base + NCT6694_SHM_COFS_CTL2);
+}
+
+static int nct6694_hif_irq_init(struct nct6694 *nct6694, int irq)
+{
+ struct nct6694_hif_data *hdata = nct6694->priv;
+ struct nct6694_sio_data *sio_data = hdata->sio_data;
+ int ret;
+
+ /* Set SIRQ number */
+ ret = superio_enter(sio_data);
+ if (ret)
+ return ret;
+
+ superio_select(sio_data, SIO_REG_LD_SHM);
+
+ if (!superio_inb(sio_data, SIO_REG_SHM_ENABLE)) {
+ superio_exit(sio_data);
+ return -EIO;
+ }
+
+ hdata->shm_base = superio_inw(sio_data, SIO_REG_SHM_BASE_ADDR);
+ superio_outb(sio_data, SIO_REG_SHM_IRQ_NR, irq);
+
+ superio_exit(sio_data);
+
+ if (!devm_request_region(nct6694->dev,
+ hdata->shm_base + NCT6694_SHM_COFS_STS,
+ NCT6694_SHM_COFS_LEN, DRVNAME))
+ return -EBUSY;
+
+ return 0;
+}
+
+static void nct6694_hif_core_remove_action(void *data)
+{
+ struct nct6694 *nct6694 = data;
+
+ nct6694_core_remove(nct6694);
+}
+
+static const u8 sio_addrs[] = { 0x2e, 0x4e };
+
+static int nct6694_hif_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct nct6694_sio_data *sio_data;
+ struct nct6694_hif_data *hdata;
+ struct nct6694 *nct6694;
+ void __iomem *rpt_base, *msg_base;
+ int ret, i, irq;
+
+ rpt_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(rpt_base))
+ return PTR_ERR(rpt_base);
+
+ msg_base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(msg_base))
+ return PTR_ERR(msg_base);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ sio_data = devm_kzalloc(dev, sizeof(*sio_data), GFP_KERNEL);
+ if (!sio_data)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(sio_addrs); i++) {
+ if (!nct6694_sio_find(sio_data, sio_addrs[i]))
+ break;
+ }
+ if (i == ARRAY_SIZE(sio_addrs))
+ return -ENODEV;
+
+ dev_dbg(dev, "Found %s at %#x\n", nct6694_chip_names[sio_data->chip], sio_data->sioreg);
+
+ nct6694 = devm_kzalloc(dev, sizeof(*nct6694), GFP_KERNEL);
+ if (!nct6694)
+ return -ENOMEM;
+
+ hdata = devm_kzalloc(dev, sizeof(*hdata), GFP_KERNEL);
+ if (!hdata)
+ return -ENOMEM;
+
+ hdata->xfer_buf = devm_kzalloc(dev, NCT6694_MAX_PACKET_SIZE, GFP_KERNEL);
+ if (!hdata->xfer_buf)
+ return -ENOMEM;
+
+ hdata->sio_data = sio_data;
+ hdata->msg_base = msg_base;
+ hdata->rpt_regmap = devm_regmap_init_mmio(dev, rpt_base,
+ &nct6694_hif_rpt_regmap_config);
+ if (IS_ERR(hdata->rpt_regmap))
+ return PTR_ERR(hdata->rpt_regmap);
+
+ nct6694->dev = dev;
+ nct6694->priv = hdata;
+ nct6694->regmap = devm_regmap_init(dev, &nct6694_hif_regmap_bus, nct6694,
+ &nct6694_hif_msg_regmap_config);
+ if (IS_ERR(nct6694->regmap))
+ return PTR_ERR(nct6694->regmap);
+
+ ret = nct6694_hif_irq_init(nct6694, irq);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, nct6694);
+
+ ret = nct6694_core_probe(dev, nct6694, nct6694_hif_devs,
+ ARRAY_SIZE(nct6694_hif_devs));
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, nct6694_hif_core_remove_action, nct6694);
+ if (ret)
+ return ret;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, nct6694_hif_irq_handler,
+ IRQF_ONESHOT | IRQF_SHARED,
+ dev_name(dev), nct6694);
+ if (ret)
+ return ret;
+
+ nct6694_hif_irq_enable(nct6694);
+
+ return devm_add_action_or_reset(dev, nct6694_hif_irq_disable, nct6694);
+}
+
+static const struct acpi_device_id nct6694_hif_acpi_ids[] = {
+ { "NTN0538", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, nct6694_hif_acpi_ids);
+
+static struct platform_driver nct6694_hif_driver = {
+ .driver = {
+ .name = DRVNAME,
+ .acpi_match_table = nct6694_hif_acpi_ids,
+ },
+ .probe = nct6694_hif_probe,
+};
+module_platform_driver(nct6694_hif_driver);
+
+MODULE_DESCRIPTION("Nuvoton NCT6694 host-interface transport driver");
+MODULE_AUTHOR("Ming Yu <tmyu0@nuvoton.com>");
+MODULE_LICENSE("GPL");
--
2.34.1
next prev parent reply other threads:[~2026-07-01 3:51 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-01 3:50 [PATCH v6 0/7] mfd: nct6694: Refactor transport layer and add HIF (eSPI) support a0282524688
2026-07-01 3:50 ` [PATCH v6 1/7] mfd: nct6694: Move module type macros to shared header a0282524688
2026-07-01 3:50 ` [PATCH v6 2/7] mfd: nct6694: Refactor USB-specific data into nct6694_usb_data a0282524688
2026-07-01 3:50 ` [PATCH v6 3/7] mfd: nct6694: Rename USB transport functions with _usb_ prefix a0282524688
2026-07-01 3:50 ` [PATCH v6 4/7] mfd: nct6694: Rename driver to nct6694-usb and update Kconfig a0282524688
2026-07-01 3:50 ` [PATCH v6 5/7] mfd: nct6694: Extract core device management into a separate module a0282524688
2026-07-01 3:50 ` [PATCH v6 6/7] mfd: nct6694: Introduce regmap-based transport abstraction a0282524688
2026-07-09 9:27 ` Lee Jones
2026-07-01 3:50 ` a0282524688 [this message]
2026-07-02 19:08 ` [PATCH v6 7/7] mfd: nct6694: Add Host Interface (HIF) eSPI transport driver Julian Braha
2026-07-09 9:27 ` Lee Jones
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=20260701035025.3082927-8-a0282524688@gmail.com \
--to=a0282524688@gmail.com \
--cc=lee@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=tmyu0@nuvoton.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox