* [PATCH v1] ARM: l2x0: Fix OF node reference leak in l2x0_of_init
From: Yuho Choi @ 2026-06-08 4:23 UTC (permalink / raw)
To: Russell King; +Cc: Kuninori Morimoto, linux-arm-kernel, linux-kernel, Yuho Choi
l2x0_of_init() gets the cache controller node with
of_find_matching_node(), which returns the node with a reference held.
The node is only needed while parsing the cache controller resources and
properties, but the function returns without dropping that reference on
the resource/ioremap failure paths or after __l2c_init() returns.
Use a single exit path after the node lookup and put the node before
returning.
Fixes: 8c369264b6de ("ARM: 7009/1: l2x0: Add OF based initialization")
Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
---
arch/arm/mm/cache-l2x0.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 470867160076..e20ac79dd500 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -1767,17 +1767,22 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
u32 cache_id, old_aux;
u32 cache_level = 2;
bool nosync = false;
+ int ret;
np = of_find_matching_node(NULL, l2x0_ids);
if (!np)
return -ENODEV;
- if (of_address_to_resource(np, 0, &res))
- return -ENODEV;
+ if (of_address_to_resource(np, 0, &res)) {
+ ret = -ENODEV;
+ goto out_put_node;
+ }
l2x0_base = ioremap(res.start, resource_size(&res));
- if (!l2x0_base)
- return -ENOMEM;
+ if (!l2x0_base) {
+ ret = -ENOMEM;
+ goto out_put_node;
+ }
l2x0_saved_regs.phy_base = res.start;
@@ -1821,6 +1826,10 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
else
cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
- return __l2c_init(data, aux_val, aux_mask, cache_id, nosync);
+ ret = __l2c_init(data, aux_val, aux_mask, cache_id, nosync);
+
+out_put_node:
+ of_node_put(np);
+ return ret;
}
#endif
--
2.43.0
^ permalink raw reply related
* Re: [RFC PATCH v3 6/9] iommu/rockchip: Clear AUTO_GATING bit 1 on the RK356x v1 IOMMU
From: Chaoyi Chen @ 2026-06-08 3:40 UTC (permalink / raw)
To: Midgy Balon
Cc: Simon Xue, tomeu, ogabbay, heiko, robh, krzk+dt, conor+dt, joro,
will, robin.murphy, dri-devel, linux-rockchip, devicetree,
linux-arm-kernel, iommu, linux-kernel
In-Reply-To: <0919ffcc-81c3-483a-a3ba-404b455c2040@rock-chips.com>
On 6/8/2026 9:45 AM, Chaoyi Chen wrote:
> Hi Midgy,
>
> On 6/8/2026 5:05 AM, Midgy Balon wrote:
>> Hi Chaoyi,
>>
>>> As I said, it is v2. Could you please try using the code below instead and
>>> see if it works?
>>> [ auto_gate = read(RK_MMU_AUTO_GATING); auto_gate |= BIT(31); write(...) ]
>>
>> Thanks -- that's clearly the right shape (read-modify-write, before paging is
>> enabled, keeping the reset value instead of my clobbering 0x2).
>>
>> I rebuilt v7.1-rc6 (with the rocket RK3568 series + your per-device-ops work)
>> using your bit-31 version and tested it on a ROCK 3B: the NPU IOMMU comes up and
>> services the NPU's DMA cleanly -- the NPU probes, attaches its domain, and runs
>> repeated conv submissions with no DMA_READ_ERROR and no page-walk stall. No
>> regression from the write.
>>
>> To be precise about what I can and can't show: I tested both ways on v7.1-rc6 --
>> with your bit-31 write, and on the reset value (0x3) -- and the NPU
>> IOMMU services
>> the NPU's reads with zero faults in both cases (no DMA_READ_ERROR, no page-walk
>> stall). So I don't have a failing baseline here that bit-31 visibly
>> fixes. Is the
>> AUTO_GATING write needed on current mainline, or only under conditions I'm not
>> reproducing (a particular traffic pattern / silicon rev)? I'll keep the patch in
>> your form unless you'd prefer to drop it.
>>
>> One question so I document it correctly: what does bit 31 of RK_MMU_AUTO_GATING
>> control on the v2 block -- is it a master "disable internal auto clock-gating"
>> for the page-table walker (i.e. so a TLB-miss walk's AXI master keeps its clock
>> to completion)? The RK3568 TRM I have doesn't cover the IOMMU registers, so a
>> one-line description would let me write an accurate comment.
>>
>
> Glad to hear this works. Please refer to the commit below.
>
> [0]: https://github.com/rockchip-linux/kernel/commit/7f8158fb41b5cc8e738aaeebc3637c50ebd74cae
> [1]: https://github.com/rockchip-linux/kernel/commit/6a355e5f9a2069a2309e240791bc3aad63b7324e
>
It looks like RGA needs this patch too, and it has already been merged :).
https://lore.kernel.org/all/20260428-spu-iommudtefix-v2-1-f592f579e508@pengutronix.de/
--
Best,
Chaoyi
^ permalink raw reply
* [PATCH v1] dmaengine: qcom: hidma-mgmt: Fix sysfs cleanup on setup failure
From: Yuho Choi @ 2026-06-08 3:08 UTC (permalink / raw)
To: Vinod Koul, Sinan Kaya
Cc: dmaengine, Frank Li, linux-arm-kernel, linux-arm-msm,
linux-kernel, Yuho Choi
hidma_mgmt_init_sys() creates the chanops kobject, per-channel
kobjects and sysfs files incrementally. If a later creation step fails,
the function returns without tearing down the objects already created.
Those sysfs callbacks reference devm-managed driver data. A later probe
failure can free that data while the sysfs entries and kobjects remain
registered.
Track the chanops kobject in struct hidma_mgmt_dev, unwind the sysfs
files and channel kobjects on setup failure, and register the same
cleanup with devm after successful setup.
Fixes: 7f8f209fd6e0 ("dmaengine: add Qualcomm Technologies HIDMA management driver")
Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
---
drivers/dma/qcom/hidma_mgmt.h | 1 +
drivers/dma/qcom/hidma_mgmt_sys.c | 65 +++++++++++++++++++++++++------
2 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/drivers/dma/qcom/hidma_mgmt.h b/drivers/dma/qcom/hidma_mgmt.h
index 30e8095988bf..4fb6759e3371 100644
--- a/drivers/dma/qcom/hidma_mgmt.h
+++ b/drivers/dma/qcom/hidma_mgmt.h
@@ -24,6 +24,7 @@ struct hidma_mgmt_dev {
resource_size_t addrsize;
struct kobject **chroots;
+ struct kobject *chanops;
struct platform_device *pdev;
};
diff --git a/drivers/dma/qcom/hidma_mgmt_sys.c b/drivers/dma/qcom/hidma_mgmt_sys.c
index 930eae0a6257..280b3af6ec03 100644
--- a/drivers/dma/qcom/hidma_mgmt_sys.c
+++ b/drivers/dma/qcom/hidma_mgmt_sys.c
@@ -231,20 +231,52 @@ static int create_sysfs_entry_channel(struct hidma_mgmt_dev *mdev, char *name,
return sysfs_create_file(parent, &chattr->attr.attr);
}
+static void hidma_mgmt_uninit_sys(struct hidma_mgmt_dev *mdev,
+ unsigned int sysfs_count,
+ unsigned int chroot_count)
+{
+ unsigned int i;
+
+ for (i = 0; i < sysfs_count; i++) {
+ struct attribute attr = { .name = hidma_mgmt_files[i].name };
+
+ sysfs_remove_file(&mdev->pdev->dev.kobj, &attr);
+ }
+
+ for (i = 0; i < chroot_count; i++) {
+ kobject_put(mdev->chroots[i]);
+ mdev->chroots[i] = NULL;
+ }
+
+ if (mdev->chanops) {
+ kobject_put(mdev->chanops);
+ mdev->chanops = NULL;
+ }
+}
+
+static void hidma_mgmt_uninit_sys_action(void *data)
+{
+ struct hidma_mgmt_dev *mdev = data;
+
+ hidma_mgmt_uninit_sys(mdev, ARRAY_SIZE(hidma_mgmt_files),
+ mdev->dma_channels);
+}
+
int hidma_mgmt_init_sys(struct hidma_mgmt_dev *mdev)
{
+ unsigned int chroot_count = 0;
+ unsigned int sysfs_count = 0;
unsigned int i;
- int rc;
int required;
- struct kobject *chanops;
+ int rc;
required = sizeof(*mdev->chroots) * mdev->dma_channels;
mdev->chroots = devm_kmalloc(&mdev->pdev->dev, required, GFP_KERNEL);
if (!mdev->chroots)
return -ENOMEM;
- chanops = kobject_create_and_add("chanops", &mdev->pdev->dev.kobj);
- if (!chanops)
+ mdev->chanops = kobject_create_and_add("chanops", &mdev->pdev->dev.kobj);
+ if (!mdev->chanops)
return -ENOMEM;
/* create each channel directory here */
@@ -252,9 +284,12 @@ int hidma_mgmt_init_sys(struct hidma_mgmt_dev *mdev)
char name[20];
snprintf(name, sizeof(name), "chan%d", i);
- mdev->chroots[i] = kobject_create_and_add(name, chanops);
- if (!mdev->chroots[i])
- return -ENOMEM;
+ mdev->chroots[i] = kobject_create_and_add(name, mdev->chanops);
+ if (!mdev->chroots[i]) {
+ rc = -ENOMEM;
+ goto err_uninit;
+ }
+ chroot_count++;
}
/* populate common parameters */
@@ -262,7 +297,9 @@ int hidma_mgmt_init_sys(struct hidma_mgmt_dev *mdev)
rc = create_sysfs_entry(mdev, hidma_mgmt_files[i].name,
hidma_mgmt_files[i].mode);
if (rc)
- return rc;
+ goto err_uninit;
+
+ sysfs_count++;
}
/* populate parameters that are per channel */
@@ -271,15 +308,21 @@ int hidma_mgmt_init_sys(struct hidma_mgmt_dev *mdev)
(S_IRUGO | S_IWUGO), i,
mdev->chroots[i]);
if (rc)
- return rc;
+ goto err_uninit;
rc = create_sysfs_entry_channel(mdev, "weight",
(S_IRUGO | S_IWUGO), i,
mdev->chroots[i]);
if (rc)
- return rc;
+ goto err_uninit;
}
- return 0;
+ return devm_add_action_or_reset(&mdev->pdev->dev,
+ hidma_mgmt_uninit_sys_action, mdev);
+
+err_uninit:
+ hidma_mgmt_uninit_sys(mdev, sysfs_count, chroot_count);
+
+ return rc;
}
EXPORT_SYMBOL_GPL(hidma_mgmt_init_sys);
--
2.43.0
^ permalink raw reply related
* [PATCH v2 2/2] spi: ma35d1-qspi: Add Nuvoton MA35D1 QSPI controller support
From: Chi-Wen Weng @ 2026-06-08 2:50 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: linux-arm-kernel, linux-spi, devicetree, linux-kernel, cwweng
In-Reply-To: <20260608025009.1504971-1-cwweng@nuvoton.com>
Add SPI controller driver support for the Nuvoton MA35D1 Quad SPI
controller.
The controller supports standard SPI transfers and spi-mem operations
for SPI memory devices such as SPI NOR and SPI NAND flashes. The driver
supports single, dual and quad I/O modes and uses a conservative
word-by-word PIO transfer path for the initial upstream version.
The driver also handles controller reset, clock divider programming,
chip-select control, transfer mode setup and spi-mem command/address/
dummy/data phases.
Signed-off-by: Chi-Wen Weng <cwweng@nuvoton.com>
---
drivers/spi/Kconfig | 10 +
drivers/spi/Makefile | 1 +
drivers/spi/spi-ma35d1-qspi.c | 622 ++++++++++++++++++++++++++++++++++
3 files changed, 633 insertions(+)
create mode 100644 drivers/spi/spi-ma35d1-qspi.c
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b563f49e2197..8b8297ee3f2e 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -694,6 +694,16 @@ config SPI_LJCA
This driver can also be built as a module. If so, the module
will be called spi-ljca.
+config SPI_MA35D1_QSPI
+ tristate "Nuvoton MA35D1 QSPI controller"
+ depends on ARCH_MA35 || COMPILE_TEST
+ help
+ This enables support for the Quad SPI controller found in
+ Nuvoton MA35D1 SoCs.
+
+ The controller supports SPI memory devices such as SPI NOR and
+ SPI NAND flashes in single, dual and quad I/O modes.
+
config SPI_MESON_SPICC
tristate "Amlogic Meson SPICC controller"
depends on COMMON_CLK
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 9d36190a9884..c5bb0efd108c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_SPI_LOONGSON_CORE) += spi-loongson-core.o
obj-$(CONFIG_SPI_LOONGSON_PCI) += spi-loongson-pci.o
obj-$(CONFIG_SPI_LOONGSON_PLATFORM) += spi-loongson-plat.o
obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o
+obj-$(CONFIG_SPI_MA35D1_QSPI) += spi-ma35d1-qspi.o
obj-$(CONFIG_SPI_MESON_SPICC) += spi-meson-spicc.o
obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
obj-$(CONFIG_SPI_MICROCHIP_CORE_QSPI) += spi-microchip-core-qspi.o
diff --git a/drivers/spi/spi-ma35d1-qspi.c b/drivers/spi/spi-ma35d1-qspi.c
new file mode 100644
index 000000000000..93b60b6142e5
--- /dev/null
+++ b/drivers/spi/spi-ma35d1-qspi.c
@@ -0,0 +1,622 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// Nuvoton MA35D1 QSPI controller driver
+//
+// Copyright (c) 2026 Nuvoton Technology Corp.
+// Author: Chi-Wen Weng <cwweng@nuvoton.com>
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-mem.h>
+
+/* Register offset definitions */
+#define NUVOTON_QSPI_CTL_OFFSET 0x00 /* Control Register, RW */
+#define NUVOTON_QSPI_CLKDIV_OFFSET 0x04 /* Clock Divider Register, RW */
+#define NUVOTON_QSPI_SSCTL_OFFSET 0x08 /* Slave Select Register, RW */
+#define NUVOTON_QSPI_FIFOCTL_OFFSET 0x10 /* FIFO Control Register, RW */
+#define NUVOTON_QSPI_STATUS_OFFSET 0x14 /* Status Register, RW */
+#define NUVOTON_QSPI_TX_OFFSET 0x20 /* Data Transmit Register, WO */
+#define NUVOTON_QSPI_RX_OFFSET 0x30 /* Data Receive Register, RO */
+
+/* QSPI Control Register bit masks */
+#define NUVOTON_QSPI_CTL_QUADIOEN_MASK BIT(22) /* Quad I/O Mode Enable */
+#define NUVOTON_QSPI_CTL_DUALIOEN_MASK BIT(21) /* Dual I/O Mode Enable */
+#define NUVOTON_QSPI_CTL_DATDIR_MASK BIT(20) /* Data Port Direction Control */
+#define NUVOTON_QSPI_CTL_REORDER_MASK BIT(19) /* Byte Reorder Function Enable */
+#define NUVOTON_QSPI_CTL_LSB_MASK BIT(13) /* Send LSB First */
+#define NUVOTON_QSPI_CTL_DWIDTH_MASK GENMASK(12, 8) /* Data Width */
+#define NUVOTON_QSPI_CTL_SUSPITV_MASK GENMASK(7, 4) /* Suspend Interval */
+#define NUVOTON_QSPI_CTL_CLKPOL_MASK BIT(3) /* Clock Polarity */
+#define NUVOTON_QSPI_CTL_TXNEG_MASK BIT(2) /* Transmit on Negative Edge */
+#define NUVOTON_QSPI_CTL_RXNEG_MASK BIT(1) /* Receive on Negative Edge */
+#define NUVOTON_QSPI_CTL_SPIEN_MASK BIT(0) /* QSPI Transfer Control Enable */
+
+/* QSPI Clock Divider Register bit masks */
+#define NUVOTON_QSPI_CLKDIV_MASK GENMASK(8, 0) /* Clock Divider */
+
+/* QSPI Slave Select Control Register bit masks */
+#define NUVOTON_QSPI_SSCTL_SSACTPOL_MASK BIT(2) /* Slave Selection Active Polarity */
+#define NUVOTON_QSPI_SSCTL_SS1_MASK BIT(1) /* Slave Selection 1 Control */
+#define NUVOTON_QSPI_SSCTL_SS0_MASK BIT(0) /* Slave Selection 0 Control */
+
+/* QSPI FIFO Control Register bit masks */
+#define NUVOTON_QSPI_FIFOCTL_TXRST_MASK BIT(1) /* Transmit Reset */
+#define NUVOTON_QSPI_FIFOCTL_RXRST_MASK BIT(0) /* Receive Reset */
+
+/* QSPI Status Register bit masks */
+#define NUVOTON_QSPI_STATUS_TXRXRST_MASK BIT(23) /* TX or RX Reset Status */
+#define NUVOTON_QSPI_STATUS_TXFULL_MASK BIT(17) /* Transmit FIFO Full */
+#define NUVOTON_QSPI_STATUS_TXEMPTY_MASK BIT(16) /* Transmit FIFO Empty */
+#define NUVOTON_QSPI_STATUS_SPIENSTS_MASK BIT(15) /* QSPI Enable Status */
+#define NUVOTON_QSPI_STATUS_RXFULL_MASK BIT(9) /* Receive FIFO Full */
+#define NUVOTON_QSPI_STATUS_RXEMPTY_MASK BIT(8) /* Receive FIFO Empty */
+#define NUVOTON_QSPI_STATUS_UNITIF_MASK BIT(1) /* Unit Transfer Interrupt Flag */
+#define NUVOTON_QSPI_STATUS_BUSY_MASK BIT(0) /* Busy Status */
+
+#define NUVOTON_QSPI_DEFAULT_NUM_CS 2
+#define NUVOTON_QSPI_DEFAULT_BPW 8
+#define NUVOTON_QSPI_TIMEOUT_US 10000
+
+struct nuvoton_qspi {
+ void __iomem *regs;
+ struct clk *clk;
+ struct device *dev;
+ u32 speed_hz;
+ u8 bits_per_word;
+};
+
+static u32 nuvoton_qspi_read(struct nuvoton_qspi *qspi, u32 reg)
+{
+ return readl(qspi->regs + reg);
+}
+
+static void nuvoton_qspi_write(struct nuvoton_qspi *qspi, u32 val, u32 reg)
+{
+ writel(val, qspi->regs + reg);
+}
+
+static void nuvoton_qspi_update_bits(struct nuvoton_qspi *qspi, u32 reg,
+ u32 mask, u32 val)
+{
+ u32 tmp;
+
+ tmp = nuvoton_qspi_read(qspi, reg);
+ tmp &= ~mask;
+ tmp |= val & mask;
+ nuvoton_qspi_write(qspi, tmp, reg);
+}
+
+static int nuvoton_qspi_wait_ready(struct nuvoton_qspi *qspi)
+{
+ u32 val;
+
+ return readl_poll_timeout(qspi->regs + NUVOTON_QSPI_STATUS_OFFSET,
+ val,
+ !(val & NUVOTON_QSPI_STATUS_BUSY_MASK),
+ 0, NUVOTON_QSPI_TIMEOUT_US);
+}
+
+static int nuvoton_qspi_reset_fifo(struct nuvoton_qspi *qspi)
+{
+ u32 val;
+
+ val = nuvoton_qspi_read(qspi, NUVOTON_QSPI_FIFOCTL_OFFSET);
+ val |= NUVOTON_QSPI_FIFOCTL_TXRST_MASK |
+ NUVOTON_QSPI_FIFOCTL_RXRST_MASK;
+ nuvoton_qspi_write(qspi, val, NUVOTON_QSPI_FIFOCTL_OFFSET);
+
+ /* FIFO reset is extremely fast, safe to keep atomic for this micro-wait */
+ return readl_poll_timeout_atomic(qspi->regs + NUVOTON_QSPI_STATUS_OFFSET,
+ val,
+ !(val & NUVOTON_QSPI_STATUS_TXRXRST_MASK),
+ 1, NUVOTON_QSPI_TIMEOUT_US);
+}
+
+static int nuvoton_qspi_set_speed(struct nuvoton_qspi *qspi, u32 speed_hz)
+{
+ unsigned long clk_rate;
+ u32 div;
+
+ if (!speed_hz)
+ return -EINVAL;
+
+ if (qspi->speed_hz == speed_hz)
+ return 0;
+
+ clk_rate = clk_get_rate(qspi->clk);
+ if (!clk_rate) {
+ dev_err(qspi->dev, "failed to get clock rate\n");
+ return -EINVAL;
+ }
+
+ div = DIV_ROUND_UP(clk_rate, speed_hz) - 1;
+ if (div > FIELD_MAX(NUVOTON_QSPI_CLKDIV_MASK)) {
+ dev_err(qspi->dev, "unsupported SPI clock %u Hz\n", speed_hz);
+ return -EINVAL;
+ }
+
+ nuvoton_qspi_write(qspi, FIELD_PREP(NUVOTON_QSPI_CLKDIV_MASK, div),
+ NUVOTON_QSPI_CLKDIV_OFFSET);
+ qspi->speed_hz = speed_hz;
+
+ return 0;
+}
+
+static int nuvoton_qspi_set_bits_per_word(struct nuvoton_qspi *qspi, u8 bpw)
+{
+ u32 val;
+
+ if (bpw != 8 && bpw != 16 && bpw != 32)
+ return -EINVAL;
+
+ if (bpw == 32)
+ val = NUVOTON_QSPI_CTL_REORDER_MASK;
+ else
+ val = FIELD_PREP(NUVOTON_QSPI_CTL_DWIDTH_MASK, bpw);
+
+ nuvoton_qspi_update_bits(qspi, NUVOTON_QSPI_CTL_OFFSET,
+ NUVOTON_QSPI_CTL_DWIDTH_MASK |
+ NUVOTON_QSPI_CTL_REORDER_MASK, val);
+ qspi->bits_per_word = bpw;
+
+ return 0;
+}
+
+static int nuvoton_qspi_setup_transfer(struct spi_device *spi,
+ u32 speed_hz, u8 bpw)
+{
+ struct nuvoton_qspi *qspi = spi_controller_get_devdata(spi->controller);
+ u32 mode = spi->mode & SPI_MODE_X_MASK;
+ u32 ctl = 0;
+ int ret;
+
+ if (!speed_hz)
+ speed_hz = spi->max_speed_hz;
+
+ if (!bpw)
+ bpw = NUVOTON_QSPI_DEFAULT_BPW;
+
+ ret = nuvoton_qspi_set_speed(qspi, speed_hz);
+ if (ret)
+ return ret;
+
+ ret = nuvoton_qspi_set_bits_per_word(qspi, bpw);
+ if (ret)
+ return ret;
+
+ if (mode == SPI_MODE_0 || mode == SPI_MODE_3)
+ ctl |= NUVOTON_QSPI_CTL_TXNEG_MASK;
+ else
+ ctl |= NUVOTON_QSPI_CTL_RXNEG_MASK;
+
+ if (spi->mode & SPI_CPOL)
+ ctl |= NUVOTON_QSPI_CTL_CLKPOL_MASK;
+
+ if (spi->mode & SPI_LSB_FIRST)
+ ctl |= NUVOTON_QSPI_CTL_LSB_MASK;
+
+ nuvoton_qspi_update_bits(qspi, NUVOTON_QSPI_CTL_OFFSET,
+ NUVOTON_QSPI_CTL_TXNEG_MASK |
+ NUVOTON_QSPI_CTL_RXNEG_MASK |
+ NUVOTON_QSPI_CTL_CLKPOL_MASK |
+ NUVOTON_QSPI_CTL_LSB_MASK, ctl);
+
+ return 0;
+}
+
+static void nuvoton_qspi_set_bus_width(struct nuvoton_qspi *qspi,
+ unsigned int buswidth,
+ enum spi_mem_data_dir dir)
+{
+ u32 ctl = 0;
+
+ if (buswidth == 4)
+ ctl |= NUVOTON_QSPI_CTL_QUADIOEN_MASK;
+ else if (buswidth == 2)
+ ctl |= NUVOTON_QSPI_CTL_DUALIOEN_MASK;
+
+ if (buswidth > 1 && dir == SPI_MEM_DATA_OUT)
+ ctl |= NUVOTON_QSPI_CTL_DATDIR_MASK;
+
+ nuvoton_qspi_update_bits(qspi, NUVOTON_QSPI_CTL_OFFSET,
+ NUVOTON_QSPI_CTL_QUADIOEN_MASK |
+ NUVOTON_QSPI_CTL_DUALIOEN_MASK |
+ NUVOTON_QSPI_CTL_DATDIR_MASK, ctl);
+}
+
+static u32 nuvoton_qspi_tx_word(const void *txbuf, unsigned int idx, u8 bpw)
+{
+ if (!txbuf)
+ return 0;
+
+ if (bpw <= 8)
+ return ((const u8 *)txbuf)[idx];
+ if (bpw <= 16)
+ return ((const u16 *)txbuf)[idx];
+
+ return ((const u32 *)txbuf)[idx];
+}
+
+static void nuvoton_qspi_rx_word(void *rxbuf, unsigned int idx, u32 val, u8 bpw)
+{
+ if (!rxbuf)
+ return;
+
+ if (bpw <= 8)
+ ((u8 *)rxbuf)[idx] = val;
+ else if (bpw <= 16)
+ ((u16 *)rxbuf)[idx] = val;
+ else
+ ((u32 *)rxbuf)[idx] = val;
+}
+
+static int nuvoton_qspi_wait_tx_not_full(struct nuvoton_qspi *qspi)
+{
+ u32 val;
+
+ return readl_poll_timeout_atomic(qspi->regs + NUVOTON_QSPI_STATUS_OFFSET,
+ val,
+ !(val & NUVOTON_QSPI_STATUS_TXFULL_MASK),
+ 0, NUVOTON_QSPI_TIMEOUT_US);
+}
+
+static int nuvoton_qspi_wait_rx_not_empty(struct nuvoton_qspi *qspi)
+{
+ u32 val;
+
+ return readl_poll_timeout_atomic(qspi->regs + NUVOTON_QSPI_STATUS_OFFSET,
+ val,
+ !(val & NUVOTON_QSPI_STATUS_RXEMPTY_MASK),
+ 0, NUVOTON_QSPI_TIMEOUT_US);
+}
+
+static int nuvoton_qspi_txrx(struct nuvoton_qspi *qspi, const void *txbuf,
+ void *rxbuf, unsigned int len)
+{
+ unsigned int bytes_per_word = DIV_ROUND_UP(qspi->bits_per_word, 8);
+ unsigned int words;
+ u32 val;
+ int ret;
+ int i;
+
+ if (!len)
+ return 0;
+
+ if (len % bytes_per_word)
+ return -EINVAL;
+
+ words = len / bytes_per_word;
+
+ ret = nuvoton_qspi_reset_fifo(qspi);
+ if (ret) {
+ dev_err(qspi->dev, "FIFO reset timed out\n");
+ return ret;
+ }
+
+ /*
+ * Use conservative word-by-word PIO access. This keeps the initial driver
+ * simple and avoids relying on FIFO threshold interrupts or DMA support.
+ */
+ for (i = 0; i < words; i++) {
+ ret = nuvoton_qspi_wait_tx_not_full(qspi);
+ if (ret) {
+ dev_err(qspi->dev, "TX FIFO full timeout\n");
+ return ret;
+ }
+
+ nuvoton_qspi_write(qspi, nuvoton_qspi_tx_word(txbuf, i,
+ qspi->bits_per_word),
+ NUVOTON_QSPI_TX_OFFSET);
+
+ ret = nuvoton_qspi_wait_rx_not_empty(qspi);
+ if (ret) {
+ dev_err(qspi->dev, "RX FIFO empty timeout\n");
+ return ret;
+ }
+
+ val = nuvoton_qspi_read(qspi, NUVOTON_QSPI_RX_OFFSET);
+ if (rxbuf)
+ nuvoton_qspi_rx_word(rxbuf, i, val, qspi->bits_per_word);
+ }
+
+ ret = nuvoton_qspi_wait_ready(qspi);
+ if (ret)
+ dev_err(qspi->dev, "controller busy timeout\n");
+
+ return ret;
+}
+
+static int nuvoton_qspi_hw_init(struct nuvoton_qspi *qspi)
+{
+ u32 val;
+ int ret;
+
+ ret = nuvoton_qspi_set_bits_per_word(qspi, NUVOTON_QSPI_DEFAULT_BPW);
+ if (ret)
+ return ret;
+
+ nuvoton_qspi_update_bits(qspi, NUVOTON_QSPI_CTL_OFFSET,
+ NUVOTON_QSPI_CTL_SUSPITV_MASK |
+ NUVOTON_QSPI_CTL_TXNEG_MASK |
+ NUVOTON_QSPI_CTL_RXNEG_MASK |
+ NUVOTON_QSPI_CTL_CLKPOL_MASK |
+ NUVOTON_QSPI_CTL_LSB_MASK,
+ NUVOTON_QSPI_CTL_TXNEG_MASK);
+
+ val = nuvoton_qspi_read(qspi, NUVOTON_QSPI_CTL_OFFSET);
+ nuvoton_qspi_write(qspi, val | NUVOTON_QSPI_CTL_SPIEN_MASK,
+ NUVOTON_QSPI_CTL_OFFSET);
+
+ ret = readl_poll_timeout(qspi->regs + NUVOTON_QSPI_STATUS_OFFSET, val,
+ (val & NUVOTON_QSPI_STATUS_SPIENSTS_MASK),
+ 1, NUVOTON_QSPI_TIMEOUT_US);
+ if (ret) {
+ dev_err(qspi->dev, "failed to enable controller\n");
+ return ret;
+ }
+
+ ret = nuvoton_qspi_reset_fifo(qspi);
+ if (ret)
+ dev_err(qspi->dev, "FIFO reset timed out\n");
+
+ return ret;
+}
+
+static bool nuvoton_qspi_mem_supports_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ if (!spi_mem_default_supports_op(mem, op))
+ return false;
+
+ if (op->cmd.buswidth > 4 || op->addr.buswidth > 4 ||
+ op->dummy.buswidth > 4 || op->data.buswidth > 4)
+ return false;
+
+ if (op->cmd.nbytes != 1)
+ return false;
+
+ if (op->addr.nbytes > 4)
+ return false;
+
+ return true;
+}
+
+static void nuvoton_qspi_set_cs_level(struct nuvoton_qspi *qspi,
+ unsigned int cs, bool assert)
+{
+ u32 mask;
+ u32 val;
+
+ switch (cs) {
+ case 0:
+ mask = NUVOTON_QSPI_SSCTL_SS0_MASK;
+ break;
+ case 1:
+ mask = NUVOTON_QSPI_SSCTL_SS1_MASK;
+ break;
+ default:
+ dev_warn(qspi->dev, "invalid chip select %u\n", cs);
+ return;
+ }
+
+ val = nuvoton_qspi_read(qspi, NUVOTON_QSPI_SSCTL_OFFSET);
+
+ if (assert)
+ val |= mask;
+ else
+ val &= ~mask;
+
+ nuvoton_qspi_write(qspi, val, NUVOTON_QSPI_SSCTL_OFFSET);
+}
+
+static void nuvoton_qspi_set_cs(struct spi_device *spi, bool enable)
+{
+ struct nuvoton_qspi *qspi = spi_controller_get_devdata(spi->controller);
+
+ nuvoton_qspi_set_cs_level(qspi, spi_get_chipselect(spi, 0), enable);
+}
+
+static void nuvoton_qspi_mem_set_cs(struct spi_device *spi, bool enable)
+{
+ struct nuvoton_qspi *qspi = spi_controller_get_devdata(spi->controller);
+ bool assert = enable;
+
+ if (spi->mode & SPI_CS_HIGH)
+ assert = !assert;
+
+ nuvoton_qspi_set_cs_level(qspi, spi_get_chipselect(spi, 0), assert);
+}
+
+static int nuvoton_qspi_mem_exec_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ struct spi_device *spi = mem->spi;
+ struct nuvoton_qspi *qspi = spi_controller_get_devdata(spi->controller);
+ u8 opcode = op->cmd.opcode;
+ u8 addr[4];
+ int ret;
+ int i;
+
+ ret = nuvoton_qspi_setup_transfer(spi, op->max_freq, NUVOTON_QSPI_DEFAULT_BPW);
+ if (ret)
+ return ret;
+
+ nuvoton_qspi_mem_set_cs(spi, true);
+
+ nuvoton_qspi_set_bus_width(qspi, op->cmd.buswidth, SPI_MEM_DATA_OUT);
+ ret = nuvoton_qspi_txrx(qspi, &opcode, NULL, 1);
+ if (ret)
+ goto out_deassert_cs;
+
+ if (op->addr.nbytes) {
+ for (i = 0; i < op->addr.nbytes; i++)
+ addr[i] = op->addr.val >> (8 * (op->addr.nbytes - i - 1));
+
+ nuvoton_qspi_set_bus_width(qspi, op->addr.buswidth,
+ SPI_MEM_DATA_OUT);
+ ret = nuvoton_qspi_txrx(qspi, addr, NULL, op->addr.nbytes);
+ if (ret)
+ goto out_deassert_cs;
+ }
+
+ if (op->dummy.nbytes) {
+ nuvoton_qspi_set_bus_width(qspi, op->dummy.buswidth,
+ SPI_MEM_DATA_IN);
+ ret = nuvoton_qspi_txrx(qspi, NULL, NULL, op->dummy.nbytes);
+ if (ret)
+ goto out_deassert_cs;
+ }
+
+ if (op->data.nbytes) {
+ nuvoton_qspi_set_bus_width(qspi, op->data.buswidth,
+ op->data.dir);
+ ret = nuvoton_qspi_txrx(qspi,
+ op->data.dir == SPI_MEM_DATA_OUT ?
+ op->data.buf.out : NULL,
+ op->data.dir == SPI_MEM_DATA_IN ?
+ op->data.buf.in : NULL,
+ op->data.nbytes);
+ }
+
+out_deassert_cs:
+ nuvoton_qspi_set_bus_width(qspi, 1, SPI_MEM_DATA_IN);
+ nuvoton_qspi_mem_set_cs(spi, false);
+
+ return ret;
+}
+
+static const struct spi_controller_mem_ops nuvoton_qspi_mem_ops = {
+ .supports_op = nuvoton_qspi_mem_supports_op,
+ .exec_op = nuvoton_qspi_mem_exec_op,
+};
+
+static int nuvoton_qspi_transfer_one(struct spi_controller *ctlr,
+ struct spi_device *spi,
+ struct spi_transfer *xfer)
+{
+ struct nuvoton_qspi *qspi = spi_controller_get_devdata(ctlr);
+ enum spi_mem_data_dir dir = SPI_MEM_DATA_IN;
+ unsigned int buswidth = 1;
+ int ret;
+
+ ret = nuvoton_qspi_setup_transfer(spi, xfer->speed_hz, xfer->bits_per_word);
+ if (ret)
+ return ret;
+
+ if (xfer->tx_buf && xfer->rx_buf) {
+ if (xfer->tx_nbits != SPI_NBITS_SINGLE ||
+ xfer->rx_nbits != SPI_NBITS_SINGLE)
+ return -EOPNOTSUPP;
+ }
+
+ if (xfer->tx_buf) {
+ dir = SPI_MEM_DATA_OUT;
+ if (xfer->tx_nbits == SPI_NBITS_QUAD)
+ buswidth = 4;
+ else if (xfer->tx_nbits == SPI_NBITS_DUAL)
+ buswidth = 2;
+ } else if (xfer->rx_buf) {
+ if (xfer->rx_nbits == SPI_NBITS_QUAD)
+ buswidth = 4;
+ else if (xfer->rx_nbits == SPI_NBITS_DUAL)
+ buswidth = 2;
+ }
+
+ nuvoton_qspi_set_bus_width(qspi, buswidth, dir);
+ ret = nuvoton_qspi_txrx(qspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
+ nuvoton_qspi_set_bus_width(qspi, 1, SPI_MEM_DATA_IN);
+
+ return ret;
+}
+
+static int nuvoton_qspi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct spi_controller *ctlr;
+ struct nuvoton_qspi *qspi;
+ struct reset_control *rst;
+ int ret;
+
+ ctlr = devm_spi_alloc_host(dev, sizeof(*qspi));
+ if (!ctlr)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ctlr);
+
+ qspi = spi_controller_get_devdata(ctlr);
+ qspi->dev = dev;
+ qspi->bits_per_word = NUVOTON_QSPI_DEFAULT_BPW;
+
+ qspi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(qspi->regs))
+ return PTR_ERR(qspi->regs);
+
+ rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(rst))
+ return dev_err_probe(dev, PTR_ERR(rst),
+ "failed to get reset\n");
+
+ qspi->clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(qspi->clk))
+ return dev_err_probe(dev, PTR_ERR(qspi->clk),
+ "failed to get and enable clock\n");
+
+ ret = reset_control_assert(rst);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to assert reset\n");
+
+ udelay(2);
+
+ ret = reset_control_deassert(rst);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to deassert reset\n");
+
+ ctlr->num_chipselect = NUVOTON_QSPI_DEFAULT_NUM_CS;
+ ctlr->mem_ops = &nuvoton_qspi_mem_ops;
+ ctlr->set_cs = nuvoton_qspi_set_cs;
+ ctlr->transfer_one = nuvoton_qspi_transfer_one;
+ ctlr->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) |
+ SPI_BPW_MASK(32);
+ ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST |
+ SPI_RX_DUAL | SPI_TX_DUAL |
+ SPI_RX_QUAD | SPI_TX_QUAD;
+ ctlr->dev.of_node = dev->of_node;
+
+ ret = nuvoton_qspi_hw_init(qspi);
+ if (ret)
+ return ret;
+
+ ret = devm_spi_register_controller(dev, ctlr);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to register spi controller\n");
+
+ return 0;
+}
+
+static const struct of_device_id nuvoton_qspi_of_match[] = {
+ { .compatible = "nuvoton,ma35d1-qspi" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, nuvoton_qspi_of_match);
+
+static struct platform_driver nuvoton_qspi_driver = {
+ .driver = {
+ .name = "ma35d1-qspi",
+ .of_match_table = nuvoton_qspi_of_match,
+ },
+ .probe = nuvoton_qspi_probe,
+};
+module_platform_driver(nuvoton_qspi_driver);
+
+MODULE_DESCRIPTION("Nuvoton MA35D1 QSPI controller driver");
+MODULE_AUTHOR("Chi-Wen Weng <cwweng@nuvoton.com>");
+MODULE_LICENSE("GPL");
--
2.25.1
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: spi: nuvoton,ma35d1-qspi: Add Nuvoton MA35D1 QSPI
From: Chi-Wen Weng @ 2026-06-08 2:50 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: linux-arm-kernel, linux-spi, devicetree, linux-kernel, cwweng
In-Reply-To: <20260608025009.1504971-1-cwweng@nuvoton.com>
Add a devicetree binding for the Quad SPI controller found in
Nuvoton MA35D1 SoCs.
The controller supports SPI memory devices such as SPI NOR and SPI NAND
flashes. It has one register range, one clock input and one reset line,
and supports up to two chip selects.
Signed-off-by: Chi-Wen Weng <cwweng@nuvoton.com>
---
.../bindings/spi/nuvoton,ma35d1-qspi.yaml | 62 +++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 Documentation/devicetree/bindings/spi/nuvoton,ma35d1-qspi.yaml
diff --git a/Documentation/devicetree/bindings/spi/nuvoton,ma35d1-qspi.yaml b/Documentation/devicetree/bindings/spi/nuvoton,ma35d1-qspi.yaml
new file mode 100644
index 000000000000..68e6d79e6b7d
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/nuvoton,ma35d1-qspi.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/nuvoton,ma35d1-qspi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton MA35D1 Quad SPI Controller
+
+maintainers:
+ - Chi-Wen Weng <cwweng@nuvoton.com>
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+properties:
+ compatible:
+ const: nuvoton,ma35d1-qspi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ num-cs:
+ maximum: 2
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
+ #include <dt-bindings/reset/nuvoton,ma35d1-reset.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ spi@40680000 {
+ compatible = "nuvoton,ma35d1-qspi";
+ reg = <0 0x40680000 0 0x100>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk QSPI0_GATE>;
+ resets = <&sys MA35D1_RESET_QSPI0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
--
2.25.1
^ permalink raw reply related
* [PATCH v2 0/2] spi: ma35d1-qspi: Add Nuvoton MA35D1 QSPI controller
From: Chi-Wen Weng @ 2026-06-08 2:50 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: linux-arm-kernel, linux-spi, devicetree, linux-kernel, cwweng
Add devicetree binding and SPI controller driver support for the
Nuvoton MA35D1 Quad SPI controller.
The MA35D1 QSPI controller supports SPI memory devices such as SPI NOR
and SPI NAND flashes in single, dual and quad I/O modes. This initial
driver implements a conservative PIO-based transfer path and spi-mem
operation support.
Changes in v2:
- Updated patch subject lines to match SPI subsystem style.
- Added commit message to the dt-bindings patch.
- Added ARCH_MA35 || COMPILE_TEST dependency to Kconfig.
- Expanded Kconfig help text.
- Converted the driver file header to // comments.
- Added reset control handling to the driver.
- Added resets property to the binding.
- Added num-cs constraint to the binding.
- Dropped the flash child node from the binding example.
- Used op->max_freq for spi-mem operations.
- Split low-level CS register handling from the SPI core .set_cs()
callback.
- Handled SPI_CS_HIGH explicitly for the spi-mem direct CS path.
- Fixed spi-mem opcode transfer to use a u8 buffer.
- Limited spi-mem command opcode length to one byte.
- Forced spi-mem operations to 8-bit word size.
- Avoided driving bidirectional data pins during dummy cycles.
- Drained RX FIFO during TX-only transfers.
- Rejected invalid chip-select numbers instead of mapping them to SS1.
- Rejected unsupported dual/quad full-duplex generic SPI transfers.
- Fixed checkpatch style issues.
Chi-Wen Weng (2):
dt-bindings: spi: nuvoton,ma35d1-qspi: Add Nuvoton MA35D1 QSPI
spi: ma35d1-qspi: Add Nuvoton MA35D1 QSPI controller support
.../bindings/spi/nuvoton,ma35d1-qspi.yaml | 62 ++
drivers/spi/Kconfig | 10 +
drivers/spi/Makefile | 1 +
drivers/spi/spi-ma35d1-qspi.c | 622 ++++++++++++++++++
4 files changed, 695 insertions(+)
create mode 100644 Documentation/devicetree/bindings/spi/nuvoton,ma35d1-qspi.yaml
create mode 100644 drivers/spi/spi-ma35d1-qspi.c
--
2.25.1
^ permalink raw reply
* [PATCH v5 2/2] ARM: dts: aspeed: ventura2: Add Meta ventura2 BMC
From: Kyle Hsieh @ 2026-06-08 2:42 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
Kyle Hsieh
In-Reply-To: <20260608-ventura2_initial_dts-v5-0-37ee5bcf58b6@gmail.com>
Add linux device tree entry related to the Meta(Facebook) rmc-node.
The system use an AT2600 BMC.
This node is named "ventura2".
Signed-off-by: Kyle Hsieh <kylehsieh1995@gmail.com>
---
arch/arm/boot/dts/aspeed/Makefile | 1 +
.../dts/aspeed/aspeed-bmc-facebook-ventura2.dts | 2888 ++++++++++++++++++++
2 files changed, 2889 insertions(+)
diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index 9adf9278dc94..6b96997629d4 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -32,6 +32,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-facebook-minipack.dtb \
aspeed-bmc-facebook-santabarbara.dtb \
aspeed-bmc-facebook-tiogapass.dtb \
+ aspeed-bmc-facebook-ventura2.dtb \
aspeed-bmc-facebook-wedge40.dtb \
aspeed-bmc-facebook-wedge100.dtb \
aspeed-bmc-facebook-wedge400-data64.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura2.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura2.dts
new file mode 100644
index 000000000000..9bf7d6e52e40
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura2.dts
@@ -0,0 +1,2888 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2023 Facebook Inc.
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/i2c/i2c.h>
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+/ {
+ model = "Facebook Ventura2 RMC";
+ compatible = "facebook,ventura2-rmc", "aspeed,ast2600";
+ aliases {
+ serial2 = &uart3;
+ serial4 = &uart5;
+
+ /*
+ * Pre-allocate I2C bus aliases for userspace predictability.
+ * Several I2C channels are intentionally left empty in this DTS
+ * as they are strictly reserved for future hardware feature expansions
+ * and add-on boards that will interface with these busses.
+ */
+ /*
+ * i2c switch 0-0077, pca9548, 8 child channels assigned
+ * with bus number 16-23.
+ */
+ i2c16 = &i2c0mux0ch0;
+ i2c17 = &i2c0mux0ch1;
+ i2c18 = &i2c0mux0ch2;
+ i2c19 = &i2c0mux0ch3;
+ i2c20 = &i2c0mux0ch4;
+ i2c21 = &i2c0mux0ch5;
+ i2c22 = &i2c0mux0ch6;
+ i2c23 = &i2c0mux0ch7;
+
+ /*
+ * i2c switch 1-0077, pca9548, 8 child channels assigned
+ * with bus number 24-31.
+ */
+ i2c24 = &i2c1mux0ch0;
+ i2c25 = &i2c1mux0ch1;
+ i2c26 = &i2c1mux0ch2;
+ i2c27 = &i2c1mux0ch3;
+ i2c28 = &i2c1mux0ch4;
+ i2c29 = &i2c1mux0ch5;
+ i2c30 = &i2c1mux0ch6;
+ i2c31 = &i2c1mux0ch7;
+
+ /*
+ * i2c switch 4-0077, pca9548, 8 child channels assigned
+ * with bus number 32-39.
+ */
+ i2c32 = &i2c4mux0ch0;
+ i2c33 = &i2c4mux0ch1;
+ i2c34 = &i2c4mux0ch2;
+ i2c35 = &i2c4mux0ch3;
+ i2c36 = &i2c4mux0ch4;
+ i2c37 = &i2c4mux0ch5;
+ i2c38 = &i2c4mux0ch6;
+ i2c39 = &i2c4mux0ch7;
+
+ /*
+ * i2c switch 5-0077, pca9548, 8 child channels assigned
+ * with bus number 40-47.
+ */
+ i2c40 = &i2c5mux0ch0;
+ i2c41 = &i2c5mux0ch1;
+ i2c42 = &i2c5mux0ch2;
+ i2c43 = &i2c5mux0ch3;
+ i2c44 = &i2c5mux0ch4;
+ i2c45 = &i2c5mux0ch5;
+ i2c46 = &i2c5mux0ch6;
+ i2c47 = &i2c5mux0ch7;
+
+ /*
+ * i2c switch 8-0077, pca9548, 8 child channels assigned
+ * with bus number 48-55.
+ */
+ i2c48 = &i2c8mux0ch0;
+ i2c49 = &i2c8mux0ch1;
+ i2c50 = &i2c8mux0ch2;
+ i2c51 = &i2c8mux0ch3;
+ i2c52 = &i2c8mux0ch4;
+ i2c53 = &i2c8mux0ch5;
+ i2c54 = &i2c8mux0ch6;
+ i2c55 = &i2c8mux0ch7;
+
+ /*
+ * i2c switch 11-0077, pca9548, 8 child channels assigned
+ * with bus number 56-63.
+ */
+ i2c56 = &i2c11mux0ch0;
+ i2c57 = &i2c11mux0ch1;
+ i2c58 = &i2c11mux0ch2;
+ i2c59 = &i2c11mux0ch3;
+ i2c60 = &i2c11mux0ch4;
+ i2c61 = &i2c11mux0ch5;
+ i2c62 = &i2c11mux0ch6;
+ i2c63 = &i2c11mux0ch7;
+
+ /*
+ * i2c switch 13-0077, pca9548, 8 child channels assigned
+ * with bus number 64-71.
+ */
+ i2c64 = &i2c13mux0ch0;
+ i2c65 = &i2c13mux0ch1;
+ i2c66 = &i2c13mux0ch2;
+ i2c67 = &i2c13mux0ch3;
+ i2c68 = &i2c13mux0ch4;
+ i2c69 = &i2c13mux0ch5;
+ i2c70 = &i2c13mux0ch6;
+ i2c71 = &i2c13mux0ch7;
+
+ /*
+ * i2c switch 15-0077, pca9548, 8 child channels assigned
+ * with bus number 72-79.
+ */
+ i2c72 = &i2c15mux0ch0;
+ i2c73 = &i2c15mux0ch1;
+ i2c74 = &i2c15mux0ch2;
+ i2c75 = &i2c15mux0ch3;
+ i2c76 = &i2c15mux0ch4;
+ i2c77 = &i2c15mux0ch5;
+ i2c78 = &i2c15mux0ch6;
+ i2c79 = &i2c15mux0ch7;
+ };
+
+ chosen {
+ stdout-path = "serial4:57600n8";
+ };
+
+ fan_leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ /* The 'ledd' intentionally matches the hardware schematic */
+ label = "fcb0fan0_ledd1_blue";
+ default-state = "off";
+ gpios = <&fan_io_expander0 0 GPIO_ACTIVE_LOW>;
+ };
+
+ led-1 {
+ label = "fcb0fan1_ledd2_blue";
+ default-state = "off";
+ gpios = <&fan_io_expander0 1 GPIO_ACTIVE_LOW>;
+ };
+
+ led-2 {
+ label = "fcb0fan2_ledd3_blue";
+ default-state = "off";
+ gpios = <&fan_io_expander1 0 GPIO_ACTIVE_LOW>;
+ };
+
+ led-3 {
+ label = "fcb0fan3_ledd4_blue";
+ default-state = "off";
+ gpios = <&fan_io_expander1 1 GPIO_ACTIVE_LOW>;
+ };
+
+ led-4 {
+ label = "fcb0fan0_ledd1_amber";
+ default-state = "off";
+ gpios = <&fan_io_expander0 4 GPIO_ACTIVE_LOW>;
+ };
+
+ led-5 {
+ label = "fcb0fan1_ledd2_amber";
+ default-state = "off";
+ gpios = <&fan_io_expander0 5 GPIO_ACTIVE_LOW>;
+ };
+
+ led-6 {
+ label = "fcb0fan2_ledd3_amber";
+ default-state = "off";
+ gpios = <&fan_io_expander1 4 GPIO_ACTIVE_LOW>;
+ };
+
+ led-7 {
+ label = "fcb0fan3_ledd4_amber";
+ default-state = "off";
+ gpios = <&fan_io_expander1 5 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>,
+ <&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>,
+ <&adc1 2>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ label = "bmc_heartbeat_amber";
+ gpios = <&gpio0 ASPEED_GPIO(P, 7) GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led-1 {
+ label = "fp_id_amber";
+ default-state = "off";
+ gpios = <&gpio0 ASPEED_GPIO(B, 5) GPIO_ACTIVE_HIGH>;
+ };
+
+ led-2 {
+ label = "bmc_ready_noled";
+ default-state = "on";
+ gpios = <&gpio0 ASPEED_GPIO(B, 3) (GPIO_ACTIVE_HIGH|GPIO_TRANSITORY)>;
+ };
+
+ led-3 {
+ label = "power_blue";
+ default-state = "off";
+ gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x80000000>;
+ };
+
+ p1v8_bmc_aux: regulator-p1v8-bmc-aux {
+ compatible = "regulator-fixed";
+ regulator-name = "p1v8_bmc_aux";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ p2v5_bmc_aux: regulator-p2v5-bmc-aux {
+ compatible = "regulator-fixed";
+ regulator-name = "p2v5_bmc_aux";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ p5v_dac_aux: regulator-p5v-bmc-aux {
+ compatible = "regulator-fixed";
+ regulator-name = "p5v_dac_aux";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ spi1_gpio: spi {
+ compatible = "spi-gpio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sck-gpios = <&gpio0 ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>;
+ mosi-gpios = <&gpio0 ASPEED_GPIO(Z, 4) GPIO_ACTIVE_HIGH>;
+ miso-gpios = <&gpio0 ASPEED_GPIO(Z, 5) GPIO_ACTIVE_HIGH>;
+ cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>;
+ num-chipselects = <1>;
+
+ tpm@0 {
+ compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+ spi-max-frequency = <33000000>;
+ reg = <0>;
+ };
+ };
+};
+
+&adc0 {
+ vref-supply = <&p1v8_bmc_aux>;
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default
+ &pinctrl_adc2_default &pinctrl_adc3_default
+ &pinctrl_adc4_default &pinctrl_adc5_default
+ &pinctrl_adc6_default &pinctrl_adc7_default>;
+};
+
+&adc1 {
+ vref-supply = <&p2v5_bmc_aux>;
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc8_default &pinctrl_adc10_default>;
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "bmc";
+ spi-max-frequency = <50000000>;
+ #include "openbmc-flash-layout-128.dtsi"
+ };
+ flash@1 {
+ status = "okay";
+ m25p,fast-read;
+ label = "alt-bmc";
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&gpio0 {
+ gpio-line-names =
+ /*A0-A7*/ "","","","","","","","",
+ /*B0-B7*/ "BATTERY_DETECT","","","BMC_READY_R",
+ "","FM_ID_LED","","",
+ /*C0-C7*/ "","","","","","","","",
+ /*D0-D7*/ "","","","","","","","",
+ /*E0-E7*/ "","","","","","","","",
+ /*F0-F7*/ "","","","","","","","",
+ /*G0-G7*/ "FM_MUX1_SEL_R","","","",
+ "","","","",
+ /*H0-H7*/ "","","","","","","","",
+ /*I0-I7*/ "","","","","","","","",
+ /*J0-J7*/ "","","","","","","","",
+ /*K0-K7*/ "","","","","","","","",
+ /*L0-L7*/ "","","","","","","","",
+ /*M0-M7*/ "","","","","STBY_POWER_PG_3V3","","","",
+ /*N0-N7*/ "LED_POSTCODE_0","LED_POSTCODE_1",
+ "LED_POSTCODE_2","LED_POSTCODE_3",
+ "LED_POSTCODE_4","LED_POSTCODE_5",
+ "LED_POSTCODE_6","LED_POSTCODE_7",
+ /*O0-O7*/ "","","","","","","","debug-card-mux",
+ /*P0-P7*/ "PWR_BTN_BMC_BUF_N","","ID_RST_BTN_BMC_N","",
+ "PWR_LED","","","BMC_HEARTBEAT_N",
+ /*Q0-Q7*/ "","","","","","","","",
+ /*R0-R7*/ "","","","","","","","",
+ /*S0-S7*/ "","","SYS_BMC_PWRBTN_R_N","","","","","",
+ /*T0-T7*/ "","","","","","","","",
+ /*U0-U7*/ "","","","","","","","",
+ /*V0-V7*/ "","","","","","","","",
+ /*W0-W7*/ "","","","","","","","",
+ /*X0-X7*/ "","","","","","","","",
+ /*Y0-Y7*/ "","","","","","","","",
+ /*Z0-Z7*/ "","","","","","","","";
+};
+
+&gpio1 {
+ gpio-line-names =
+ /*18A0-18A7*/ "","","","","","","","",
+ /*18B0-18B7*/ "","","","",
+ "FM_BOARD_BMC_REV_ID0","FM_BOARD_BMC_REV_ID1",
+ "FM_BOARD_BMC_REV_ID2","",
+ /*18C0-18C7*/ "SPI_BMC_BIOS_ROM_IRQ0_R_N","","","","","","","",
+ /*18D0-18D7*/ "","","","","","","","",
+ /*18E0-18E3*/ "FM_BMC_PROT_LS_EN","AC_PWR_BMC_BTN_R_N","","";
+};
+
+&i2c0 {
+ status = "okay";
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9548";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ i2c0mux0ch0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ i2c0mux0ch1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ i2c0mux0ch2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ i2c0mux0ch3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ status = "okay";
+ };
+
+ i2c0mux0ch4: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ status = "okay";
+ };
+
+ i2c0mux0ch5: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ status = "okay";
+
+ eeprom@56 {
+ compatible = "atmel,24c128";
+ reg = <0x56>;
+ };
+ };
+
+ i2c0mux0ch6: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+
+ eeprom@56 {
+ compatible = "atmel,24c128";
+ reg = <0x56>;
+ };
+
+ fan_io_expander0: gpio@20 {
+ compatible = "nxp,pca9555";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ fan_io_expander1: gpio@21 {
+ compatible = "nxp,pca9555";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ adc@1d {
+ compatible = "ti,adc128d818";
+ reg = <0x1d>;
+ ti,mode = /bits/ 8 <1>;
+ };
+
+ adc@35 {
+ compatible = "maxim,max11617";
+ reg = <0x35>;
+ };
+ };
+
+ i2c0mux0ch7: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+
+ fanctl0: fan-controller@20 {
+ compatible = "maxim,max31790";
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ channel@2 {
+ reg = <2>;
+ sensor-type = "TACH";
+ };
+ channel@5 {
+ reg = <5>;
+ sensor-type = "TACH";
+ };
+ };
+
+ fanctl1: fan-controller@23 {
+ compatible = "nuvoton,nct7363";
+ reg = <0x23>;
+ #pwm-cells = <2>;
+
+ fan-9 {
+ pwms = <&fanctl1 0 20000>;
+ tach-ch = /bits/ 8 <0x09>;
+ };
+
+ fan-11 {
+ pwms = <&fanctl1 0 20000>;
+ tach-ch = /bits/ 8 <0x0B>;
+ };
+
+ fan-10 {
+ pwms = <&fanctl1 4 20000>;
+ tach-ch = /bits/ 8 <0x0A>;
+ };
+
+ fan-13 {
+ pwms = <&fanctl1 4 20000>;
+ tach-ch = /bits/ 8 <0x0D>;
+ };
+
+ fan-15 {
+ pwms = <&fanctl1 6 20000>;
+ tach-ch = /bits/ 8 <0x0F>;
+ };
+
+ fan-1 {
+ pwms = <&fanctl1 6 20000>;
+ tach-ch = /bits/ 8 <0x01>;
+ };
+
+ fan-0 {
+ pwms = <&fanctl1 10 20000>;
+ tach-ch = /bits/ 8 <0x00>;
+ };
+
+ fan-3 {
+ pwms = <&fanctl1 10 20000>;
+ tach-ch = /bits/ 8 <0x03>;
+ };
+ };
+ };
+ };
+};
+
+&i2c1 {
+ status = "okay";
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9548";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ i2c1mux0ch0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ status = "okay";
+ };
+
+ i2c1mux0ch1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ status = "okay";
+ };
+
+ i2c1mux0ch2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ status = "okay";
+ };
+
+ i2c1mux0ch3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ status = "okay";
+ };
+
+ i2c1mux0ch4: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ status = "okay";
+ };
+
+ i2c1mux0ch5: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ status = "okay";
+ };
+
+ i2c1mux0ch6: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ status = "okay";
+ };
+
+ i2c1mux0ch7: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ status = "okay";
+ };
+ };
+};
+
+&i2c2 {
+ status = "okay";
+ bus-frequency = <400000>;
+};
+
+&i2c3 {
+ status = "okay";
+ bus-frequency = <400000>;
+
+ dac@c {
+ reg = <0x0c>;
+ compatible = "adi,ad5612";
+ vcc-supply = <&p5v_dac_aux>;
+ };
+
+ dac@e {
+ reg = <0x0e>;
+ compatible = "adi,ad5612";
+ vcc-supply = <&p5v_dac_aux>;
+ };
+
+ dac@f {
+ reg = <0x0f>;
+ compatible = "adi,ad5612";
+ vcc-supply = <&p5v_dac_aux>;
+ };
+
+ io_expander6: gpio@23 {
+ compatible = "nxp,pca9555";
+ reg = <0x23>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&io_expander7>;
+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ prsnt_io_expander0: gpio@40 {
+ compatible = "nxp,pca9698";
+ reg = <0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <48 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN1_TRAY1_PRSNT", "CAN1_TRAY2_PRSNT",
+ "CAN1_TRAY3_PRSNT", "CAN1_TRAY4_PRSNT",
+ "CAN1_TRAY5_PRSNT", "CAN1_TRAY6_PRSNT",
+ "CAN1_TRAY7_PRSNT", "CAN1_TRAY8_PRSNT",
+ "CAN1_TRAY9_PRSNT", "CAN1_TRAY10_PRSNT",
+ "CAN1_TRAY11_PRSNT", "CAN1_TRAY12_PRSNT",
+ "CAN1_TRAY13_PRSNT", "CAN1_TRAY14_PRSNT",
+ "CAN1_TRAY15_PRSNT", "CAN1_TRAY16_PRSNT",
+ "CAN1_TRAY17_PRSNT", "CAN1_TRAY18_PRSNT",
+ "CAN1_TRAY19_PRSNT", "CAN1_TRAY20_PRSNT",
+ "CAN1_TRAY21_PRSNT", "CAN1_TRAY22_PRSNT",
+ "CAN1_TRAY23_PRSNT", "CAN1_TRAY24_PRSNT",
+ "CAN1_TRAY25_PRSNT", "CAN1_TRAY26_PRSNT",
+ "CAN1_TRAY27_PRSNT", "CAN1_TRAY28_PRSNT",
+ "CAN1_TRAY29_PRSNT", "CAN1_TRAY30_PRSNT",
+ "CAN1_TRAY31_PRSNT", "CAN1_TRAY32_PRSNT",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ prsnt_io_expander1: gpio@41 {
+ compatible = "nxp,pca9698";
+ reg = <0x41>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <56 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN2_TRAY1_PRSNT", "CAN2_TRAY2_PRSNT",
+ "CAN2_TRAY3_PRSNT", "CAN2_TRAY4_PRSNT",
+ "CAN2_TRAY5_PRSNT", "CAN2_TRAY6_PRSNT",
+ "CAN2_TRAY7_PRSNT", "CAN2_TRAY8_PRSNT",
+ "CAN2_TRAY9_PRSNT", "CAN2_TRAY10_PRSNT",
+ "CAN2_TRAY11_PRSNT", "CAN2_TRAY12_PRSNT",
+ "CAN2_TRAY13_PRSNT", "CAN2_TRAY14_PRSNT",
+ "CAN2_TRAY15_PRSNT", "CAN2_TRAY16_PRSNT",
+ "CAN2_TRAY17_PRSNT", "CAN2_TRAY18_PRSNT",
+ "CAN2_TRAY19_PRSNT", "CAN2_TRAY20_PRSNT",
+ "CAN2_TRAY21_PRSNT", "CAN2_TRAY22_PRSNT",
+ "CAN2_TRAY23_PRSNT", "CAN2_TRAY24_PRSNT",
+ "CAN2_TRAY25_PRSNT", "CAN2_TRAY26_PRSNT",
+ "CAN2_TRAY27_PRSNT", "CAN2_TRAY28_PRSNT",
+ "CAN2_TRAY29_PRSNT", "CAN2_TRAY30_PRSNT",
+ "CAN2_TRAY31_PRSNT", "CAN2_TRAY32_PRSNT",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ prsnt_io_expander2: gpio@42 {
+ compatible = "nxp,pca9698";
+ reg = <0x42>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <64 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN3_TRAY1_PRSNT", "CAN3_TRAY2_PRSNT",
+ "CAN3_TRAY3_PRSNT", "CAN3_TRAY4_PRSNT",
+ "CAN3_TRAY5_PRSNT", "CAN3_TRAY6_PRSNT",
+ "CAN3_TRAY7_PRSNT", "CAN3_TRAY8_PRSNT",
+ "CAN3_TRAY9_PRSNT", "CAN3_TRAY10_PRSNT",
+ "CAN3_TRAY11_PRSNT", "CAN3_TRAY12_PRSNT",
+ "CAN3_TRAY13_PRSNT", "CAN3_TRAY14_PRSNT",
+ "CAN3_TRAY15_PRSNT", "CAN3_TRAY16_PRSNT",
+ "CAN3_TRAY17_PRSNT", "CAN3_TRAY18_PRSNT",
+ "CAN3_TRAY19_PRSNT", "CAN3_TRAY20_PRSNT",
+ "CAN3_TRAY21_PRSNT", "CAN3_TRAY22_PRSNT",
+ "CAN3_TRAY23_PRSNT", "CAN3_TRAY24_PRSNT",
+ "CAN3_TRAY25_PRSNT", "CAN3_TRAY26_PRSNT",
+ "CAN3_TRAY27_PRSNT", "CAN3_TRAY28_PRSNT",
+ "CAN3_TRAY29_PRSNT", "CAN3_TRAY30_PRSNT",
+ "CAN3_TRAY31_PRSNT", "CAN3_TRAY32_PRSNT",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ prsnt_io_expander3: gpio@43 {
+ compatible = "nxp,pca9698";
+ reg = <0x43>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <72 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN4_TRAY1_PRSNT", "CAN4_TRAY2_PRSNT",
+ "CAN4_TRAY3_PRSNT", "CAN4_TRAY4_PRSNT",
+ "CAN4_TRAY5_PRSNT", "CAN4_TRAY6_PRSNT",
+ "CAN4_TRAY7_PRSNT", "CAN4_TRAY8_PRSNT",
+ "CAN4_TRAY9_PRSNT", "CAN4_TRAY10_PRSNT",
+ "CAN4_TRAY11_PRSNT", "CAN4_TRAY12_PRSNT",
+ "CAN4_TRAY13_PRSNT", "CAN4_TRAY14_PRSNT",
+ "CAN4_TRAY15_PRSNT", "CAN4_TRAY16_PRSNT",
+ "CAN4_TRAY17_PRSNT", "CAN4_TRAY18_PRSNT",
+ "CAN4_TRAY19_PRSNT", "CAN4_TRAY20_PRSNT",
+ "CAN4_TRAY21_PRSNT", "CAN4_TRAY22_PRSNT",
+ "CAN4_TRAY23_PRSNT", "CAN4_TRAY24_PRSNT",
+ "CAN4_TRAY25_PRSNT", "CAN4_TRAY26_PRSNT",
+ "CAN4_TRAY27_PRSNT", "CAN4_TRAY28_PRSNT",
+ "CAN4_TRAY29_PRSNT", "CAN4_TRAY30_PRSNT",
+ "CAN4_TRAY31_PRSNT", "CAN4_TRAY32_PRSNT",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ prsnt_io_expander4: gpio@44 {
+ compatible = "nxp,pca9698";
+ reg = <0x44>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <80 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN5_TRAY1_PRSNT", "CAN5_TRAY2_PRSNT",
+ "CAN5_TRAY3_PRSNT", "CAN5_TRAY4_PRSNT",
+ "CAN5_TRAY5_PRSNT", "CAN5_TRAY6_PRSNT",
+ "CAN5_TRAY7_PRSNT", "CAN5_TRAY8_PRSNT",
+ "CAN5_TRAY9_PRSNT", "CAN5_TRAY10_PRSNT",
+ "CAN5_TRAY11_PRSNT", "CAN5_TRAY12_PRSNT",
+ "CAN5_TRAY13_PRSNT", "CAN5_TRAY14_PRSNT",
+ "CAN5_TRAY15_PRSNT", "CAN5_TRAY16_PRSNT",
+ "CAN5_TRAY17_PRSNT", "CAN5_TRAY18_PRSNT",
+ "CAN5_TRAY19_PRSNT", "CAN5_TRAY20_PRSNT",
+ "CAN5_TRAY21_PRSNT", "CAN5_TRAY22_PRSNT",
+ "CAN5_TRAY23_PRSNT", "CAN5_TRAY24_PRSNT",
+ "CAN5_TRAY25_PRSNT", "CAN5_TRAY26_PRSNT",
+ "CAN5_TRAY27_PRSNT", "CAN5_TRAY28_PRSNT",
+ "CAN5_TRAY29_PRSNT", "CAN5_TRAY30_PRSNT",
+ "CAN5_TRAY31_PRSNT", "CAN5_TRAY32_PRSNT",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ prsnt_io_expander5: gpio@45 {
+ compatible = "nxp,pca9698";
+ reg = <0x45>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <88 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN6_TRAY1_PRSNT", "CAN6_TRAY2_PRSNT",
+ "CAN6_TRAY3_PRSNT", "CAN6_TRAY4_PRSNT",
+ "CAN6_TRAY5_PRSNT", "CAN6_TRAY6_PRSNT",
+ "CAN6_TRAY7_PRSNT", "CAN6_TRAY8_PRSNT",
+ "CAN6_TRAY9_PRSNT", "CAN6_TRAY10_PRSNT",
+ "CAN6_TRAY11_PRSNT", "CAN6_TRAY12_PRSNT",
+ "CAN6_TRAY13_PRSNT", "CAN6_TRAY14_PRSNT",
+ "CAN6_TRAY15_PRSNT", "CAN6_TRAY16_PRSNT",
+ "CAN6_TRAY17_PRSNT", "CAN6_TRAY18_PRSNT",
+ "CAN6_TRAY19_PRSNT", "CAN6_TRAY20_PRSNT",
+ "CAN6_TRAY21_PRSNT", "CAN6_TRAY22_PRSNT",
+ "CAN6_TRAY23_PRSNT", "CAN6_TRAY24_PRSNT",
+ "CAN6_TRAY25_PRSNT", "CAN6_TRAY26_PRSNT",
+ "CAN6_TRAY27_PRSNT", "CAN6_TRAY28_PRSNT",
+ "CAN6_TRAY29_PRSNT", "CAN6_TRAY30_PRSNT",
+ "CAN6_TRAY31_PRSNT", "CAN6_TRAY32_PRSNT",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ prsnt_io_expander6: gpio@46 {
+ compatible = "nxp,pca9698";
+ reg = <0x46>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <96 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN7_TRAY1_PRSNT", "CAN7_TRAY2_PRSNT",
+ "CAN7_TRAY3_PRSNT", "CAN7_TRAY4_PRSNT",
+ "CAN7_TRAY5_PRSNT", "CAN7_TRAY6_PRSNT",
+ "CAN7_TRAY7_PRSNT", "CAN7_TRAY8_PRSNT",
+ "CAN7_TRAY9_PRSNT", "CAN7_TRAY10_PRSNT",
+ "CAN7_TRAY11_PRSNT", "CAN7_TRAY12_PRSNT",
+ "CAN7_TRAY13_PRSNT", "CAN7_TRAY14_PRSNT",
+ "CAN7_TRAY15_PRSNT", "CAN7_TRAY16_PRSNT",
+ "CAN7_TRAY17_PRSNT", "CAN7_TRAY18_PRSNT",
+ "CAN7_TRAY19_PRSNT", "CAN7_TRAY20_PRSNT",
+ "CAN7_TRAY21_PRSNT", "CAN7_TRAY22_PRSNT",
+ "CAN7_TRAY23_PRSNT", "CAN7_TRAY24_PRSNT",
+ "CAN7_TRAY25_PRSNT", "CAN7_TRAY26_PRSNT",
+ "CAN7_TRAY27_PRSNT", "CAN7_TRAY28_PRSNT",
+ "CAN7_TRAY29_PRSNT", "CAN7_TRAY30_PRSNT",
+ "CAN7_TRAY31_PRSNT", "CAN7_TRAY32_PRSNT",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ prsnt_io_expander7: gpio@47 {
+ compatible = "nxp,pca9698";
+ reg = <0x47>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <104 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN8_TRAY1_PRSNT", "CAN8_TRAY2_PRSNT",
+ "CAN8_TRAY3_PRSNT", "CAN8_TRAY4_PRSNT",
+ "CAN8_TRAY5_PRSNT", "CAN8_TRAY6_PRSNT",
+ "CAN8_TRAY7_PRSNT", "CAN8_TRAY8_PRSNT",
+ "CAN8_TRAY9_PRSNT", "CAN8_TRAY10_PRSNT",
+ "CAN8_TRAY11_PRSNT", "CAN8_TRAY12_PRSNT",
+ "CAN8_TRAY13_PRSNT", "CAN8_TRAY14_PRSNT",
+ "CAN8_TRAY15_PRSNT", "CAN8_TRAY16_PRSNT",
+ "CAN8_TRAY17_PRSNT", "CAN8_TRAY18_PRSNT",
+ "CAN8_TRAY19_PRSNT", "CAN8_TRAY20_PRSNT",
+ "CAN8_TRAY21_PRSNT", "CAN8_TRAY22_PRSNT",
+ "CAN8_TRAY23_PRSNT", "CAN8_TRAY24_PRSNT",
+ "CAN8_TRAY25_PRSNT", "CAN8_TRAY26_PRSNT",
+ "CAN8_TRAY27_PRSNT", "CAN8_TRAY28_PRSNT",
+ "CAN8_TRAY29_PRSNT", "CAN8_TRAY30_PRSNT",
+ "CAN8_TRAY31_PRSNT", "CAN8_TRAY32_PRSNT",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ pwrgd_io_expander0: gpio@48 {
+ compatible = "nxp,pca9698";
+ reg = <0x48>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <50 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN1_TRAY1_PWRGD", "CAN1_TRAY2_PWRGD",
+ "CAN1_TRAY3_PWRGD", "CAN1_TRAY4_PWRGD",
+ "CAN1_TRAY5_PWRGD", "CAN1_TRAY6_PWRGD",
+ "CAN1_TRAY7_PWRGD", "CAN1_TRAY8_PWRGD",
+ "CAN1_TRAY9_PWRGD", "CAN1_TRAY10_PWRGD",
+ "CAN1_TRAY11_PWRGD", "CAN1_TRAY12_PWRGD",
+ "CAN1_TRAY13_PWRGD", "CAN1_TRAY14_PWRGD",
+ "CAN1_TRAY15_PWRGD", "CAN1_TRAY16_PWRGD",
+ "CAN1_TRAY17_PWRGD", "CAN1_TRAY18_PWRGD",
+ "CAN1_TRAY19_PWRGD", "CAN1_TRAY20_PWRGD",
+ "CAN1_TRAY21_PWRGD", "CAN1_TRAY22_PWRGD",
+ "CAN1_TRAY23_PWRGD", "CAN1_TRAY24_PWRGD",
+ "CAN1_TRAY25_PWRGD", "CAN1_TRAY26_PWRGD",
+ "CAN1_TRAY27_PWRGD", "CAN1_TRAY28_PWRGD",
+ "CAN1_TRAY29_PWRGD", "CAN1_TRAY30_PWRGD",
+ "CAN1_TRAY31_PWRGD", "CAN1_TRAY32_PWRGD",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ pwrgd_io_expander1: gpio@49 {
+ compatible = "nxp,pca9698";
+ reg = <0x49>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <58 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN2_TRAY1_PWRGD", "CAN2_TRAY2_PWRGD",
+ "CAN2_TRAY3_PWRGD", "CAN2_TRAY4_PWRGD",
+ "CAN2_TRAY5_PWRGD", "CAN2_TRAY6_PWRGD",
+ "CAN2_TRAY7_PWRGD", "CAN2_TRAY8_PWRGD",
+ "CAN2_TRAY9_PWRGD", "CAN2_TRAY10_PWRGD",
+ "CAN2_TRAY11_PWRGD", "CAN2_TRAY12_PWRGD",
+ "CAN2_TRAY13_PWRGD", "CAN2_TRAY14_PWRGD",
+ "CAN2_TRAY15_PWRGD", "CAN2_TRAY16_PWRGD",
+ "CAN2_TRAY17_PWRGD", "CAN2_TRAY18_PWRGD",
+ "CAN2_TRAY19_PWRGD", "CAN2_TRAY20_PWRGD",
+ "CAN2_TRAY21_PWRGD", "CAN2_TRAY22_PWRGD",
+ "CAN2_TRAY23_PWRGD", "CAN2_TRAY24_PWRGD",
+ "CAN2_TRAY25_PWRGD", "CAN2_TRAY26_PWRGD",
+ "CAN2_TRAY27_PWRGD", "CAN2_TRAY28_PWRGD",
+ "CAN2_TRAY29_PWRGD", "CAN2_TRAY30_PWRGD",
+ "CAN2_TRAY31_PWRGD", "CAN2_TRAY32_PWRGD",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ pwrgd_io_expander2: gpio@4a {
+ compatible = "nxp,pca9698";
+ reg = <0x4a>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <66 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN3_TRAY1_PWRGD", "CAN3_TRAY2_PWRGD",
+ "CAN3_TRAY3_PWRGD", "CAN3_TRAY4_PWRGD",
+ "CAN3_TRAY5_PWRGD", "CAN3_TRAY6_PWRGD",
+ "CAN3_TRAY7_PWRGD", "CAN3_TRAY8_PWRGD",
+ "CAN3_TRAY9_PWRGD", "CAN3_TRAY10_PWRGD",
+ "CAN3_TRAY11_PWRGD", "CAN3_TRAY12_PWRGD",
+ "CAN3_TRAY13_PWRGD", "CAN3_TRAY14_PWRGD",
+ "CAN3_TRAY15_PWRGD", "CAN3_TRAY16_PWRGD",
+ "CAN3_TRAY17_PWRGD", "CAN3_TRAY18_PWRGD",
+ "CAN3_TRAY19_PWRGD", "CAN3_TRAY20_PWRGD",
+ "CAN3_TRAY21_PWRGD", "CAN3_TRAY22_PWRGD",
+ "CAN3_TRAY23_PWRGD", "CAN3_TRAY24_PWRGD",
+ "CAN3_TRAY25_PWRGD", "CAN3_TRAY26_PWRGD",
+ "CAN3_TRAY27_PWRGD", "CAN3_TRAY28_PWRGD",
+ "CAN3_TRAY29_PWRGD", "CAN3_TRAY30_PWRGD",
+ "CAN3_TRAY31_PWRGD", "CAN3_TRAY32_PWRGD",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ pwrgd_io_expander3: gpio@4b {
+ compatible = "nxp,pca9698";
+ reg = <0x4b>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <74 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN4_TRAY1_PWRGD", "CAN4_TRAY2_PWRGD",
+ "CAN4_TRAY3_PWRGD", "CAN4_TRAY4_PWRGD",
+ "CAN4_TRAY5_PWRGD", "CAN4_TRAY6_PWRGD",
+ "CAN4_TRAY7_PWRGD", "CAN4_TRAY8_PWRGD",
+ "CAN4_TRAY9_PWRGD", "CAN4_TRAY10_PWRGD",
+ "CAN4_TRAY11_PWRGD", "CAN4_TRAY12_PWRGD",
+ "CAN4_TRAY13_PWRGD", "CAN4_TRAY14_PWRGD",
+ "CAN4_TRAY15_PWRGD", "CAN4_TRAY16_PWRGD",
+ "CAN4_TRAY17_PWRGD", "CAN4_TRAY18_PWRGD",
+ "CAN4_TRAY19_PWRGD", "CAN4_TRAY20_PWRGD",
+ "CAN4_TRAY21_PWRGD", "CAN4_TRAY22_PWRGD",
+ "CAN4_TRAY23_PWRGD", "CAN4_TRAY24_PWRGD",
+ "CAN4_TRAY25_PWRGD", "CAN4_TRAY26_PWRGD",
+ "CAN4_TRAY27_PWRGD", "CAN4_TRAY28_PWRGD",
+ "CAN4_TRAY29_PWRGD", "CAN4_TRAY30_PWRGD",
+ "CAN4_TRAY31_PWRGD", "CAN4_TRAY32_PWRGD",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ pwrgd_io_expander4: gpio@4c {
+ compatible = "nxp,pca9698";
+ reg = <0x4c>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <82 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN5_TRAY1_PWRGD", "CAN5_TRAY2_PWRGD",
+ "CAN5_TRAY3_PWRGD", "CAN5_TRAY4_PWRGD",
+ "CAN5_TRAY5_PWRGD", "CAN5_TRAY6_PWRGD",
+ "CAN5_TRAY7_PWRGD", "CAN5_TRAY8_PWRGD",
+ "CAN5_TRAY9_PWRGD", "CAN5_TRAY10_PWRGD",
+ "CAN5_TRAY11_PWRGD", "CAN5_TRAY12_PWRGD",
+ "CAN5_TRAY13_PWRGD", "CAN5_TRAY14_PWRGD",
+ "CAN5_TRAY15_PWRGD", "CAN5_TRAY16_PWRGD",
+ "CAN5_TRAY17_PWRGD", "CAN5_TRAY18_PWRGD",
+ "CAN5_TRAY19_PWRGD", "CAN5_TRAY20_PWRGD",
+ "CAN5_TRAY21_PWRGD", "CAN5_TRAY22_PWRGD",
+ "CAN5_TRAY23_PWRGD", "CAN5_TRAY24_PWRGD",
+ "CAN5_TRAY25_PWRGD", "CAN5_TRAY26_PWRGD",
+ "CAN5_TRAY27_PWRGD", "CAN5_TRAY28_PWRGD",
+ "CAN5_TRAY29_PWRGD", "CAN5_TRAY30_PWRGD",
+ "CAN5_TRAY31_PWRGD", "CAN5_TRAY32_PWRGD",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ pwrgd_io_expander5: gpio@4d {
+ compatible = "nxp,pca9698";
+ reg = <0x4d>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <90 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN6_TRAY1_PWRGD", "CAN6_TRAY2_PWRGD",
+ "CAN6_TRAY3_PWRGD", "CAN6_TRAY4_PWRGD",
+ "CAN6_TRAY5_PWRGD", "CAN6_TRAY6_PWRGD",
+ "CAN6_TRAY7_PWRGD", "CAN6_TRAY8_PWRGD",
+ "CAN6_TRAY9_PWRGD", "CAN6_TRAY10_PWRGD",
+ "CAN6_TRAY11_PWRGD", "CAN6_TRAY12_PWRGD",
+ "CAN6_TRAY13_PWRGD", "CAN6_TRAY14_PWRGD",
+ "CAN6_TRAY15_PWRGD", "CAN6_TRAY16_PWRGD",
+ "CAN6_TRAY17_PWRGD", "CAN6_TRAY18_PWRGD",
+ "CAN6_TRAY19_PWRGD", "CAN6_TRAY20_PWRGD",
+ "CAN6_TRAY21_PWRGD", "CAN6_TRAY22_PWRGD",
+ "CAN6_TRAY23_PWRGD", "CAN6_TRAY24_PWRGD",
+ "CAN6_TRAY25_PWRGD", "CAN6_TRAY26_PWRGD",
+ "CAN6_TRAY27_PWRGD", "CAN6_TRAY28_PWRGD",
+ "CAN6_TRAY29_PWRGD", "CAN6_TRAY30_PWRGD",
+ "CAN6_TRAY31_PWRGD", "CAN6_TRAY32_PWRGD",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ pwrgd_io_expander6: gpio@4e {
+ compatible = "nxp,pca9698";
+ reg = <0x4e>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <98 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN7_TRAY1_PWRGD", "CAN7_TRAY2_PWRGD",
+ "CAN7_TRAY3_PWRGD", "CAN7_TRAY4_PWRGD",
+ "CAN7_TRAY5_PWRGD", "CAN7_TRAY6_PWRGD",
+ "CAN7_TRAY7_PWRGD", "CAN7_TRAY8_PWRGD",
+ "CAN7_TRAY9_PWRGD", "CAN7_TRAY10_PWRGD",
+ "CAN7_TRAY11_PWRGD", "CAN7_TRAY12_PWRGD",
+ "CAN7_TRAY13_PWRGD", "CAN7_TRAY14_PWRGD",
+ "CAN7_TRAY15_PWRGD", "CAN7_TRAY16_PWRGD",
+ "CAN7_TRAY17_PWRGD", "CAN7_TRAY18_PWRGD",
+ "CAN7_TRAY19_PWRGD", "CAN7_TRAY20_PWRGD",
+ "CAN7_TRAY21_PWRGD", "CAN7_TRAY22_PWRGD",
+ "CAN7_TRAY23_PWRGD", "CAN7_TRAY24_PWRGD",
+ "CAN7_TRAY25_PWRGD", "CAN7_TRAY26_PWRGD",
+ "CAN7_TRAY27_PWRGD", "CAN7_TRAY28_PWRGD",
+ "CAN7_TRAY29_PWRGD", "CAN7_TRAY30_PWRGD",
+ "CAN7_TRAY31_PWRGD", "CAN7_TRAY32_PWRGD",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ pwrgd_io_expander7: gpio@4f {
+ compatible = "nxp,pca9698";
+ reg = <0x4f>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <106 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN8_TRAY1_PWRGD", "CAN8_TRAY2_PWRGD",
+ "CAN8_TRAY3_PWRGD", "CAN8_TRAY4_PWRGD",
+ "CAN8_TRAY5_PWRGD", "CAN8_TRAY6_PWRGD",
+ "CAN8_TRAY7_PWRGD", "CAN8_TRAY8_PWRGD",
+ "CAN8_TRAY9_PWRGD", "CAN8_TRAY10_PWRGD",
+ "CAN8_TRAY11_PWRGD", "CAN8_TRAY12_PWRGD",
+ "CAN8_TRAY13_PWRGD", "CAN8_TRAY14_PWRGD",
+ "CAN8_TRAY15_PWRGD", "CAN8_TRAY16_PWRGD",
+ "CAN8_TRAY17_PWRGD", "CAN8_TRAY18_PWRGD",
+ "CAN8_TRAY19_PWRGD", "CAN8_TRAY20_PWRGD",
+ "CAN8_TRAY21_PWRGD", "CAN8_TRAY22_PWRGD",
+ "CAN8_TRAY23_PWRGD", "CAN8_TRAY24_PWRGD",
+ "CAN8_TRAY25_PWRGD", "CAN8_TRAY26_PWRGD",
+ "CAN8_TRAY27_PWRGD", "CAN8_TRAY28_PWRGD",
+ "CAN8_TRAY29_PWRGD", "CAN8_TRAY30_PWRGD",
+ "CAN8_TRAY31_PWRGD", "CAN8_TRAY32_PWRGD",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ large_leak_io_expander0: gpio@50 {
+ compatible = "nxp,pca9698";
+ reg = <0x50>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <54 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN1_TRAY1_LARGE_LEAK", "CAN1_TRAY2_LARGE_LEAK",
+ "CAN1_TRAY3_LARGE_LEAK", "CAN1_TRAY4_LARGE_LEAK",
+ "CAN1_TRAY5_LARGE_LEAK", "CAN1_TRAY6_LARGE_LEAK",
+ "CAN1_TRAY7_LARGE_LEAK", "CAN1_TRAY8_LARGE_LEAK",
+ "CAN1_TRAY9_LARGE_LEAK", "CAN1_TRAY10_LARGE_LEAK",
+ "CAN1_TRAY11_LARGE_LEAK", "CAN1_TRAY12_LARGE_LEAK",
+ "CAN1_TRAY13_LARGE_LEAK", "CAN1_TRAY14_LARGE_LEAK",
+ "CAN1_TRAY15_LARGE_LEAK", "CAN1_TRAY16_LARGE_LEAK",
+ "CAN1_TRAY17_LARGE_LEAK", "CAN1_TRAY18_LARGE_LEAK",
+ "CAN1_TRAY19_LARGE_LEAK", "CAN1_TRAY20_LARGE_LEAK",
+ "CAN1_TRAY21_LARGE_LEAK", "CAN1_TRAY22_LARGE_LEAK",
+ "CAN1_TRAY23_LARGE_LEAK", "CAN1_TRAY24_LARGE_LEAK",
+ "CAN1_TRAY25_LARGE_LEAK", "CAN1_TRAY26_LARGE_LEAK",
+ "CAN1_TRAY27_LARGE_LEAK", "CAN1_TRAY28_LARGE_LEAK",
+ "CAN1_TRAY29_LARGE_LEAK", "CAN1_TRAY30_LARGE_LEAK",
+ "CAN1_TRAY31_LARGE_LEAK", "CAN1_TRAY32_LARGE_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ large_leak_io_expander1: gpio@51 {
+ compatible = "nxp,pca9698";
+ reg = <0x51>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <62 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN2_TRAY1_LARGE_LEAK", "CAN2_TRAY2_LARGE_LEAK",
+ "CAN2_TRAY3_LARGE_LEAK", "CAN2_TRAY4_LARGE_LEAK",
+ "CAN2_TRAY5_LARGE_LEAK", "CAN2_TRAY6_LARGE_LEAK",
+ "CAN2_TRAY7_LARGE_LEAK", "CAN2_TRAY8_LARGE_LEAK",
+ "CAN2_TRAY9_LARGE_LEAK", "CAN2_TRAY10_LARGE_LEAK",
+ "CAN2_TRAY11_LARGE_LEAK", "CAN2_TRAY12_LARGE_LEAK",
+ "CAN2_TRAY13_LARGE_LEAK", "CAN2_TRAY14_LARGE_LEAK",
+ "CAN2_TRAY15_LARGE_LEAK", "CAN2_TRAY16_LARGE_LEAK",
+ "CAN2_TRAY17_LARGE_LEAK", "CAN2_TRAY18_LARGE_LEAK",
+ "CAN2_TRAY19_LARGE_LEAK", "CAN2_TRAY20_LARGE_LEAK",
+ "CAN2_TRAY21_LARGE_LEAK", "CAN2_TRAY22_LARGE_LEAK",
+ "CAN2_TRAY23_LARGE_LEAK", "CAN2_TRAY24_LARGE_LEAK",
+ "CAN2_TRAY25_LARGE_LEAK", "CAN2_TRAY26_LARGE_LEAK",
+ "CAN2_TRAY27_LARGE_LEAK", "CAN2_TRAY28_LARGE_LEAK",
+ "CAN2_TRAY29_LARGE_LEAK", "CAN2_TRAY30_LARGE_LEAK",
+ "CAN2_TRAY31_LARGE_LEAK", "CAN2_TRAY32_LARGE_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ large_leak_io_expander2: gpio@52 {
+ compatible = "nxp,pca9698";
+ reg = <0x52>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <70 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN3_TRAY1_LARGE_LEAK", "CAN3_TRAY2_LARGE_LEAK",
+ "CAN3_TRAY3_LARGE_LEAK", "CAN3_TRAY4_LARGE_LEAK",
+ "CAN3_TRAY5_LARGE_LEAK", "CAN3_TRAY6_LARGE_LEAK",
+ "CAN3_TRAY7_LARGE_LEAK", "CAN3_TRAY8_LARGE_LEAK",
+ "CAN3_TRAY9_LARGE_LEAK", "CAN3_TRAY10_LARGE_LEAK",
+ "CAN3_TRAY11_LARGE_LEAK", "CAN3_TRAY12_LARGE_LEAK",
+ "CAN3_TRAY13_LARGE_LEAK", "CAN3_TRAY14_LARGE_LEAK",
+ "CAN3_TRAY15_LARGE_LEAK", "CAN3_TRAY16_LARGE_LEAK",
+ "CAN3_TRAY17_LARGE_LEAK", "CAN3_TRAY18_LARGE_LEAK",
+ "CAN3_TRAY19_LARGE_LEAK", "CAN3_TRAY20_LARGE_LEAK",
+ "CAN3_TRAY21_LARGE_LEAK", "CAN3_TRAY22_LARGE_LEAK",
+ "CAN3_TRAY23_LARGE_LEAK", "CAN3_TRAY24_LARGE_LEAK",
+ "CAN3_TRAY25_LARGE_LEAK", "CAN3_TRAY26_LARGE_LEAK",
+ "CAN3_TRAY27_LARGE_LEAK", "CAN3_TRAY28_LARGE_LEAK",
+ "CAN3_TRAY29_LARGE_LEAK", "CAN3_TRAY30_LARGE_LEAK",
+ "CAN3_TRAY31_LARGE_LEAK", "CAN3_TRAY32_LARGE_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ large_leak_io_expander3: gpio@53 {
+ compatible = "nxp,pca9698";
+ reg = <0x53>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <78 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN4_TRAY1_LARGE_LEAK", "CAN4_TRAY2_LARGE_LEAK",
+ "CAN4_TRAY3_LARGE_LEAK", "CAN4_TRAY4_LARGE_LEAK",
+ "CAN4_TRAY5_LARGE_LEAK", "CAN4_TRAY6_LARGE_LEAK",
+ "CAN4_TRAY7_LARGE_LEAK", "CAN4_TRAY8_LARGE_LEAK",
+ "CAN4_TRAY9_LARGE_LEAK", "CAN4_TRAY10_LARGE_LEAK",
+ "CAN4_TRAY11_LARGE_LEAK", "CAN4_TRAY12_LARGE_LEAK",
+ "CAN4_TRAY13_LARGE_LEAK", "CAN4_TRAY14_LARGE_LEAK",
+ "CAN4_TRAY15_LARGE_LEAK", "CAN4_TRAY16_LARGE_LEAK",
+ "CAN4_TRAY17_LARGE_LEAK", "CAN4_TRAY18_LARGE_LEAK",
+ "CAN4_TRAY19_LARGE_LEAK", "CAN4_TRAY20_LARGE_LEAK",
+ "CAN4_TRAY21_LARGE_LEAK", "CAN4_TRAY22_LARGE_LEAK",
+ "CAN4_TRAY23_LARGE_LEAK", "CAN4_TRAY24_LARGE_LEAK",
+ "CAN4_TRAY25_LARGE_LEAK", "CAN4_TRAY26_LARGE_LEAK",
+ "CAN4_TRAY27_LARGE_LEAK", "CAN4_TRAY28_LARGE_LEAK",
+ "CAN4_TRAY29_LARGE_LEAK", "CAN4_TRAY30_LARGE_LEAK",
+ "CAN4_TRAY31_LARGE_LEAK", "CAN4_TRAY32_LARGE_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ large_leak_io_expander4: gpio@54 {
+ compatible = "nxp,pca9698";
+ reg = <0x54>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <86 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN5_TRAY1_LARGE_LEAK", "CAN5_TRAY2_LARGE_LEAK",
+ "CAN5_TRAY3_LARGE_LEAK", "CAN5_TRAY4_LARGE_LEAK",
+ "CAN5_TRAY5_LARGE_LEAK", "CAN5_TRAY6_LARGE_LEAK",
+ "CAN5_TRAY7_LARGE_LEAK", "CAN5_TRAY8_LARGE_LEAK",
+ "CAN5_TRAY9_LARGE_LEAK", "CAN5_TRAY10_LARGE_LEAK",
+ "CAN5_TRAY11_LARGE_LEAK", "CAN5_TRAY12_LARGE_LEAK",
+ "CAN5_TRAY13_LARGE_LEAK", "CAN5_TRAY14_LARGE_LEAK",
+ "CAN5_TRAY15_LARGE_LEAK", "CAN5_TRAY16_LARGE_LEAK",
+ "CAN5_TRAY17_LARGE_LEAK", "CAN5_TRAY18_LARGE_LEAK",
+ "CAN5_TRAY19_LARGE_LEAK", "CAN5_TRAY20_LARGE_LEAK",
+ "CAN5_TRAY21_LARGE_LEAK", "CAN5_TRAY22_LARGE_LEAK",
+ "CAN5_TRAY23_LARGE_LEAK", "CAN5_TRAY24_LARGE_LEAK",
+ "CAN5_TRAY25_LARGE_LEAK", "CAN5_TRAY26_LARGE_LEAK",
+ "CAN5_TRAY27_LARGE_LEAK", "CAN5_TRAY28_LARGE_LEAK",
+ "CAN5_TRAY29_LARGE_LEAK", "CAN5_TRAY30_LARGE_LEAK",
+ "CAN5_TRAY31_LARGE_LEAK", "CAN5_TRAY32_LARGE_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ large_leak_io_expander5: gpio@55 {
+ compatible = "nxp,pca9698";
+ reg = <0x55>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <94 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN6_TRAY1_LARGE_LEAK", "CAN6_TRAY2_LARGE_LEAK",
+ "CAN6_TRAY3_LARGE_LEAK", "CAN6_TRAY4_LARGE_LEAK",
+ "CAN6_TRAY5_LARGE_LEAK", "CAN6_TRAY6_LARGE_LEAK",
+ "CAN6_TRAY7_LARGE_LEAK", "CAN6_TRAY8_LARGE_LEAK",
+ "CAN6_TRAY9_LARGE_LEAK", "CAN6_TRAY10_LARGE_LEAK",
+ "CAN6_TRAY11_LARGE_LEAK", "CAN6_TRAY12_LARGE_LEAK",
+ "CAN6_TRAY13_LARGE_LEAK", "CAN6_TRAY14_LARGE_LEAK",
+ "CAN6_TRAY15_LARGE_LEAK", "CAN6_TRAY16_LARGE_LEAK",
+ "CAN6_TRAY17_LARGE_LEAK", "CAN6_TRAY18_LARGE_LEAK",
+ "CAN6_TRAY19_LARGE_LEAK", "CAN6_TRAY20_LARGE_LEAK",
+ "CAN6_TRAY21_LARGE_LEAK", "CAN6_TRAY22_LARGE_LEAK",
+ "CAN6_TRAY23_LARGE_LEAK", "CAN6_TRAY24_LARGE_LEAK",
+ "CAN6_TRAY25_LARGE_LEAK", "CAN6_TRAY26_LARGE_LEAK",
+ "CAN6_TRAY27_LARGE_LEAK", "CAN6_TRAY28_LARGE_LEAK",
+ "CAN6_TRAY29_LARGE_LEAK", "CAN6_TRAY30_LARGE_LEAK",
+ "CAN6_TRAY31_LARGE_LEAK", "CAN6_TRAY32_LARGE_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ large_leak_io_expander6: gpio@56 {
+ compatible = "nxp,pca9698";
+ reg = <0x56>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <102 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN7_TRAY1_LARGE_LEAK", "CAN7_TRAY2_LARGE_LEAK",
+ "CAN7_TRAY3_LARGE_LEAK", "CAN7_TRAY4_LARGE_LEAK",
+ "CAN7_TRAY5_LARGE_LEAK", "CAN7_TRAY6_LARGE_LEAK",
+ "CAN7_TRAY7_LARGE_LEAK", "CAN7_TRAY8_LARGE_LEAK",
+ "CAN7_TRAY9_LARGE_LEAK", "CAN7_TRAY10_LARGE_LEAK",
+ "CAN7_TRAY11_LARGE_LEAK", "CAN7_TRAY12_LARGE_LEAK",
+ "CAN7_TRAY13_LARGE_LEAK", "CAN7_TRAY14_LARGE_LEAK",
+ "CAN7_TRAY15_LARGE_LEAK", "CAN7_TRAY16_LARGE_LEAK",
+ "CAN7_TRAY17_LARGE_LEAK", "CAN7_TRAY18_LARGE_LEAK",
+ "CAN7_TRAY19_LARGE_LEAK", "CAN7_TRAY20_LARGE_LEAK",
+ "CAN7_TRAY21_LARGE_LEAK", "CAN7_TRAY22_LARGE_LEAK",
+ "CAN7_TRAY23_LARGE_LEAK", "CAN7_TRAY24_LARGE_LEAK",
+ "CAN7_TRAY25_LARGE_LEAK", "CAN7_TRAY26_LARGE_LEAK",
+ "CAN7_TRAY27_LARGE_LEAK", "CAN7_TRAY28_LARGE_LEAK",
+ "CAN7_TRAY29_LARGE_LEAK", "CAN7_TRAY30_LARGE_LEAK",
+ "CAN7_TRAY31_LARGE_LEAK", "CAN7_TRAY32_LARGE_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ large_leak_io_expander7: gpio@57 {
+ compatible = "nxp,pca9698";
+ reg = <0x57>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <110 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN8_TRAY1_LARGE_LEAK", "CAN8_TRAY2_LARGE_LEAK",
+ "CAN8_TRAY3_LARGE_LEAK", "CAN8_TRAY4_LARGE_LEAK",
+ "CAN8_TRAY5_LARGE_LEAK", "CAN8_TRAY6_LARGE_LEAK",
+ "CAN8_TRAY7_LARGE_LEAK", "CAN8_TRAY8_LARGE_LEAK",
+ "CAN8_TRAY9_LARGE_LEAK", "CAN8_TRAY10_LARGE_LEAK",
+ "CAN8_TRAY11_LARGE_LEAK", "CAN8_TRAY12_LARGE_LEAK",
+ "CAN8_TRAY13_LARGE_LEAK", "CAN8_TRAY14_LARGE_LEAK",
+ "CAN8_TRAY15_LARGE_LEAK", "CAN8_TRAY16_LARGE_LEAK",
+ "CAN8_TRAY17_LARGE_LEAK", "CAN8_TRAY18_LARGE_LEAK",
+ "CAN8_TRAY19_LARGE_LEAK", "CAN8_TRAY20_LARGE_LEAK",
+ "CAN8_TRAY21_LARGE_LEAK", "CAN8_TRAY22_LARGE_LEAK",
+ "CAN8_TRAY23_LARGE_LEAK", "CAN8_TRAY24_LARGE_LEAK",
+ "CAN8_TRAY25_LARGE_LEAK", "CAN8_TRAY26_LARGE_LEAK",
+ "CAN8_TRAY27_LARGE_LEAK", "CAN8_TRAY28_LARGE_LEAK",
+ "CAN8_TRAY29_LARGE_LEAK", "CAN8_TRAY30_LARGE_LEAK",
+ "CAN8_TRAY31_LARGE_LEAK", "CAN8_TRAY32_LARGE_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ small_leak_io_expander0: gpio@58 {
+ compatible = "nxp,pca9698";
+ reg = <0x58>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <52 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN1_TRAY1_SMALL_LEAK", "CAN1_TRAY2_SMALL_LEAK",
+ "CAN1_TRAY3_SMALL_LEAK", "CAN1_TRAY4_SMALL_LEAK",
+ "CAN1_TRAY5_SMALL_LEAK", "CAN1_TRAY6_SMALL_LEAK",
+ "CAN1_TRAY7_SMALL_LEAK", "CAN1_TRAY8_SMALL_LEAK",
+ "CAN1_TRAY9_SMALL_LEAK", "CAN1_TRAY10_SMALL_LEAK",
+ "CAN1_TRAY11_SMALL_LEAK", "CAN1_TRAY12_SMALL_LEAK",
+ "CAN1_TRAY13_SMALL_LEAK", "CAN1_TRAY14_SMALL_LEAK",
+ "CAN1_TRAY15_SMALL_LEAK", "CAN1_TRAY16_SMALL_LEAK",
+ "CAN1_TRAY17_SMALL_LEAK", "CAN1_TRAY18_SMALL_LEAK",
+ "CAN1_TRAY19_SMALL_LEAK", "CAN1_TRAY20_SMALL_LEAK",
+ "CAN1_TRAY21_SMALL_LEAK", "CAN1_TRAY22_SMALL_LEAK",
+ "CAN1_TRAY23_SMALL_LEAK", "CAN1_TRAY24_SMALL_LEAK",
+ "CAN1_TRAY25_SMALL_LEAK", "CAN1_TRAY26_SMALL_LEAK",
+ "CAN1_TRAY27_SMALL_LEAK", "CAN1_TRAY28_SMALL_LEAK",
+ "CAN1_TRAY29_SMALL_LEAK", "CAN1_TRAY30_SMALL_LEAK",
+ "CAN1_TRAY31_SMALL_LEAK", "CAN1_TRAY32_SMALL_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ small_leak_io_expander1: gpio@59 {
+ compatible = "nxp,pca9698";
+ reg = <0x59>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <60 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN2_TRAY1_SMALL_LEAK", "CAN2_TRAY2_SMALL_LEAK",
+ "CAN2_TRAY3_SMALL_LEAK", "CAN2_TRAY4_SMALL_LEAK",
+ "CAN2_TRAY5_SMALL_LEAK", "CAN2_TRAY6_SMALL_LEAK",
+ "CAN2_TRAY7_SMALL_LEAK", "CAN2_TRAY8_SMALL_LEAK",
+ "CAN2_TRAY9_SMALL_LEAK", "CAN2_TRAY10_SMALL_LEAK",
+ "CAN2_TRAY11_SMALL_LEAK", "CAN2_TRAY12_SMALL_LEAK",
+ "CAN2_TRAY13_SMALL_LEAK", "CAN2_TRAY14_SMALL_LEAK",
+ "CAN2_TRAY15_SMALL_LEAK", "CAN2_TRAY16_SMALL_LEAK",
+ "CAN2_TRAY17_SMALL_LEAK", "CAN2_TRAY18_SMALL_LEAK",
+ "CAN2_TRAY19_SMALL_LEAK", "CAN2_TRAY20_SMALL_LEAK",
+ "CAN2_TRAY21_SMALL_LEAK", "CAN2_TRAY22_SMALL_LEAK",
+ "CAN2_TRAY23_SMALL_LEAK", "CAN2_TRAY24_SMALL_LEAK",
+ "CAN2_TRAY25_SMALL_LEAK", "CAN2_TRAY26_SMALL_LEAK",
+ "CAN2_TRAY27_SMALL_LEAK", "CAN2_TRAY28_SMALL_LEAK",
+ "CAN2_TRAY29_SMALL_LEAK", "CAN2_TRAY30_SMALL_LEAK",
+ "CAN2_TRAY31_SMALL_LEAK", "CAN2_TRAY32_SMALL_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ small_leak_io_expander2: gpio@5a {
+ compatible = "nxp,pca9698";
+ reg = <0x5a>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <68 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN3_TRAY1_SMALL_LEAK", "CAN3_TRAY2_SMALL_LEAK",
+ "CAN3_TRAY3_SMALL_LEAK", "CAN3_TRAY4_SMALL_LEAK",
+ "CAN3_TRAY5_SMALL_LEAK", "CAN3_TRAY6_SMALL_LEAK",
+ "CAN3_TRAY7_SMALL_LEAK", "CAN3_TRAY8_SMALL_LEAK",
+ "CAN3_TRAY9_SMALL_LEAK", "CAN3_TRAY10_SMALL_LEAK",
+ "CAN3_TRAY11_SMALL_LEAK", "CAN3_TRAY12_SMALL_LEAK",
+ "CAN3_TRAY13_SMALL_LEAK", "CAN3_TRAY14_SMALL_LEAK",
+ "CAN3_TRAY15_SMALL_LEAK", "CAN3_TRAY16_SMALL_LEAK",
+ "CAN3_TRAY17_SMALL_LEAK", "CAN3_TRAY18_SMALL_LEAK",
+ "CAN3_TRAY19_SMALL_LEAK", "CAN3_TRAY20_SMALL_LEAK",
+ "CAN3_TRAY21_SMALL_LEAK", "CAN3_TRAY22_SMALL_LEAK",
+ "CAN3_TRAY23_SMALL_LEAK", "CAN3_TRAY24_SMALL_LEAK",
+ "CAN3_TRAY25_SMALL_LEAK", "CAN3_TRAY26_SMALL_LEAK",
+ "CAN3_TRAY27_SMALL_LEAK", "CAN3_TRAY28_SMALL_LEAK",
+ "CAN3_TRAY29_SMALL_LEAK", "CAN3_TRAY30_SMALL_LEAK",
+ "CAN3_TRAY31_SMALL_LEAK", "CAN3_TRAY32_SMALL_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ small_leak_io_expander3: gpio@5b {
+ compatible = "nxp,pca9698";
+ reg = <0x5b>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <76 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN4_TRAY1_SMALL_LEAK", "CAN4_TRAY2_SMALL_LEAK",
+ "CAN4_TRAY3_SMALL_LEAK", "CAN4_TRAY4_SMALL_LEAK",
+ "CAN4_TRAY5_SMALL_LEAK", "CAN4_TRAY6_SMALL_LEAK",
+ "CAN4_TRAY7_SMALL_LEAK", "CAN4_TRAY8_SMALL_LEAK",
+ "CAN4_TRAY9_SMALL_LEAK", "CAN4_TRAY10_SMALL_LEAK",
+ "CAN4_TRAY11_SMALL_LEAK", "CAN4_TRAY12_SMALL_LEAK",
+ "CAN4_TRAY13_SMALL_LEAK", "CAN4_TRAY14_SMALL_LEAK",
+ "CAN4_TRAY15_SMALL_LEAK", "CAN4_TRAY16_SMALL_LEAK",
+ "CAN4_TRAY17_SMALL_LEAK", "CAN4_TRAY18_SMALL_LEAK",
+ "CAN4_TRAY19_SMALL_LEAK", "CAN4_TRAY20_SMALL_LEAK",
+ "CAN4_TRAY21_SMALL_LEAK", "CAN4_TRAY22_SMALL_LEAK",
+ "CAN4_TRAY23_SMALL_LEAK", "CAN4_TRAY24_SMALL_LEAK",
+ "CAN4_TRAY25_SMALL_LEAK", "CAN4_TRAY26_SMALL_LEAK",
+ "CAN4_TRAY27_SMALL_LEAK", "CAN4_TRAY28_SMALL_LEAK",
+ "CAN4_TRAY29_SMALL_LEAK", "CAN4_TRAY30_SMALL_LEAK",
+ "CAN4_TRAY31_SMALL_LEAK", "CAN4_TRAY32_SMALL_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ small_leak_io_expander4: gpio@5c {
+ compatible = "nxp,pca9698";
+ reg = <0x5c>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <84 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN5_TRAY1_SMALL_LEAK", "CAN5_TRAY2_SMALL_LEAK",
+ "CAN5_TRAY3_SMALL_LEAK", "CAN5_TRAY4_SMALL_LEAK",
+ "CAN5_TRAY5_SMALL_LEAK", "CAN5_TRAY6_SMALL_LEAK",
+ "CAN5_TRAY7_SMALL_LEAK", "CAN5_TRAY8_SMALL_LEAK",
+ "CAN5_TRAY9_SMALL_LEAK", "CAN5_TRAY10_SMALL_LEAK",
+ "CAN5_TRAY11_SMALL_LEAK", "CAN5_TRAY12_SMALL_LEAK",
+ "CAN5_TRAY13_SMALL_LEAK", "CAN5_TRAY14_SMALL_LEAK",
+ "CAN5_TRAY15_SMALL_LEAK", "CAN5_TRAY16_SMALL_LEAK",
+ "CAN5_TRAY17_SMALL_LEAK", "CAN5_TRAY18_SMALL_LEAK",
+ "CAN5_TRAY19_SMALL_LEAK", "CAN5_TRAY20_SMALL_LEAK",
+ "CAN5_TRAY21_SMALL_LEAK", "CAN5_TRAY22_SMALL_LEAK",
+ "CAN5_TRAY23_SMALL_LEAK", "CAN5_TRAY24_SMALL_LEAK",
+ "CAN5_TRAY25_SMALL_LEAK", "CAN5_TRAY26_SMALL_LEAK",
+ "CAN5_TRAY27_SMALL_LEAK", "CAN5_TRAY28_SMALL_LEAK",
+ "CAN5_TRAY29_SMALL_LEAK", "CAN5_TRAY30_SMALL_LEAK",
+ "CAN5_TRAY31_SMALL_LEAK", "CAN5_TRAY32_SMALL_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ small_leak_io_expander5: gpio@5d {
+ compatible = "nxp,pca9698";
+ reg = <0x5d>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <92 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN6_TRAY1_SMALL_LEAK", "CAN6_TRAY2_SMALL_LEAK",
+ "CAN6_TRAY3_SMALL_LEAK", "CAN6_TRAY4_SMALL_LEAK",
+ "CAN6_TRAY5_SMALL_LEAK", "CAN6_TRAY6_SMALL_LEAK",
+ "CAN6_TRAY7_SMALL_LEAK", "CAN6_TRAY8_SMALL_LEAK",
+ "CAN6_TRAY9_SMALL_LEAK", "CAN6_TRAY10_SMALL_LEAK",
+ "CAN6_TRAY11_SMALL_LEAK", "CAN6_TRAY12_SMALL_LEAK",
+ "CAN6_TRAY13_SMALL_LEAK", "CAN6_TRAY14_SMALL_LEAK",
+ "CAN6_TRAY15_SMALL_LEAK", "CAN6_TRAY16_SMALL_LEAK",
+ "CAN6_TRAY17_SMALL_LEAK", "CAN6_TRAY18_SMALL_LEAK",
+ "CAN6_TRAY19_SMALL_LEAK", "CAN6_TRAY20_SMALL_LEAK",
+ "CAN6_TRAY21_SMALL_LEAK", "CAN6_TRAY22_SMALL_LEAK",
+ "CAN6_TRAY23_SMALL_LEAK", "CAN6_TRAY24_SMALL_LEAK",
+ "CAN6_TRAY25_SMALL_LEAK", "CAN6_TRAY26_SMALL_LEAK",
+ "CAN6_TRAY27_SMALL_LEAK", "CAN6_TRAY28_SMALL_LEAK",
+ "CAN6_TRAY29_SMALL_LEAK", "CAN6_TRAY30_SMALL_LEAK",
+ "CAN6_TRAY31_SMALL_LEAK", "CAN6_TRAY32_SMALL_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ small_leak_io_expander6: gpio@5e {
+ compatible = "nxp,pca9698";
+ reg = <0x5e>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <100 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN7_TRAY1_SMALL_LEAK", "CAN7_TRAY2_SMALL_LEAK",
+ "CAN7_TRAY3_SMALL_LEAK", "CAN7_TRAY4_SMALL_LEAK",
+ "CAN7_TRAY5_SMALL_LEAK", "CAN7_TRAY6_SMALL_LEAK",
+ "CAN7_TRAY7_SMALL_LEAK", "CAN7_TRAY8_SMALL_LEAK",
+ "CAN7_TRAY9_SMALL_LEAK", "CAN7_TRAY10_SMALL_LEAK",
+ "CAN7_TRAY11_SMALL_LEAK", "CAN7_TRAY12_SMALL_LEAK",
+ "CAN7_TRAY13_SMALL_LEAK", "CAN7_TRAY14_SMALL_LEAK",
+ "CAN7_TRAY15_SMALL_LEAK", "CAN7_TRAY16_SMALL_LEAK",
+ "CAN7_TRAY17_SMALL_LEAK", "CAN7_TRAY18_SMALL_LEAK",
+ "CAN7_TRAY19_SMALL_LEAK", "CAN7_TRAY20_SMALL_LEAK",
+ "CAN7_TRAY21_SMALL_LEAK", "CAN7_TRAY22_SMALL_LEAK",
+ "CAN7_TRAY23_SMALL_LEAK", "CAN7_TRAY24_SMALL_LEAK",
+ "CAN7_TRAY25_SMALL_LEAK", "CAN7_TRAY26_SMALL_LEAK",
+ "CAN7_TRAY27_SMALL_LEAK", "CAN7_TRAY28_SMALL_LEAK",
+ "CAN7_TRAY29_SMALL_LEAK", "CAN7_TRAY30_SMALL_LEAK",
+ "CAN7_TRAY31_SMALL_LEAK", "CAN7_TRAY32_SMALL_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ small_leak_io_expander7: gpio@5f {
+ compatible = "nxp,pca9698";
+ reg = <0x5f>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <108 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "CAN8_TRAY1_SMALL_LEAK", "CAN8_TRAY2_SMALL_LEAK",
+ "CAN8_TRAY3_SMALL_LEAK", "CAN8_TRAY4_SMALL_LEAK",
+ "CAN8_TRAY5_SMALL_LEAK", "CAN8_TRAY6_SMALL_LEAK",
+ "CAN8_TRAY7_SMALL_LEAK", "CAN8_TRAY8_SMALL_LEAK",
+ "CAN8_TRAY9_SMALL_LEAK", "CAN8_TRAY10_SMALL_LEAK",
+ "CAN8_TRAY11_SMALL_LEAK", "CAN8_TRAY12_SMALL_LEAK",
+ "CAN8_TRAY13_SMALL_LEAK", "CAN8_TRAY14_SMALL_LEAK",
+ "CAN8_TRAY15_SMALL_LEAK", "CAN8_TRAY16_SMALL_LEAK",
+ "CAN8_TRAY17_SMALL_LEAK", "CAN8_TRAY18_SMALL_LEAK",
+ "CAN8_TRAY19_SMALL_LEAK", "CAN8_TRAY20_SMALL_LEAK",
+ "CAN8_TRAY21_SMALL_LEAK", "CAN8_TRAY22_SMALL_LEAK",
+ "CAN8_TRAY23_SMALL_LEAK", "CAN8_TRAY24_SMALL_LEAK",
+ "CAN8_TRAY25_SMALL_LEAK", "CAN8_TRAY26_SMALL_LEAK",
+ "CAN8_TRAY27_SMALL_LEAK", "CAN8_TRAY28_SMALL_LEAK",
+ "CAN8_TRAY29_SMALL_LEAK", "CAN8_TRAY30_SMALL_LEAK",
+ "CAN8_TRAY31_SMALL_LEAK", "CAN8_TRAY32_SMALL_LEAK",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+};
+
+&i2c4 {
+ status = "okay";
+ multi-master;
+ mctp-controller;
+ mctp0: mctp@10 {
+ compatible = "mctp-i2c-controller";
+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+ };
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9548";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c4mux0ch0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ io_expander3: gpio@23 {
+ compatible = "nxp,pca9555";
+ reg = <0x23>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&io_expander7>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "", "",
+ "", "RST_I2CRST_MUX1_N",
+ "RST_I2CRST_MUX2_N", "RST_I2CRST_MUX3_N",
+ "RST_I2CRST_MUX4_N", "RST_I2CRST_MUX5_N",
+ "RST_I2CRST_MUX6_N", "RST_I2CRST_MUX7_N",
+ "RST_I2CRST_MUX8_N", "",
+ "TRAY30_PWRGD_BUF_R", "TRAY31_PWRGD_BUF_R",
+ "TRAY32_PWRGD_BUF_R", "TRAY37_PWRGD_BUF_R";
+ };
+ };
+
+ i2c4mux0ch1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ temp-sensor@48 {
+ compatible = "ti,tmp75";
+ reg = <0x48>;
+ };
+
+ temp-sensor@4a {
+ compatible = "ti,tmp75";
+ reg = <0x4a>;
+ };
+
+ eeprom@56 {
+ compatible = "atmel,24c128";
+ reg = <0x56>;
+ };
+ };
+
+ i2c4mux0ch2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ status = "okay";
+ };
+
+ i2c4mux0ch3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ status = "okay";
+ };
+
+ i2c4mux0ch4: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ status = "okay";
+ };
+
+ i2c4mux0ch5: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ status = "okay";
+ };
+
+ i2c4mux0ch6: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ mctp-controller;
+ };
+
+ i2c4mux0ch7: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ status = "okay";
+ };
+ };
+};
+
+&i2c5 {
+ status = "okay";
+
+ io_expander4: gpio@22 {
+ compatible = "nxp,pca9555";
+ reg = <0x22>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&io_expander7>;
+ interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "R_COME_THERMTRIP_L", "R_PWRGD_PCH_PWROK",
+ "", "",
+ "", "",
+ "", "",
+ "", "",
+ "", "",
+ "", "TRAY38_PWRGD_BUF_R",
+ "TRAY39_PWRGD_BUF_R", "TRAY40_PWRGD_BUF_R";
+ };
+
+ io_expander5: gpio@23 {
+ compatible = "nxp,pca9555";
+ reg = <0x23>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&io_expander7>;
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "PWRGD_P5V_AUX_R2", "",
+ "PWRGD_P1V5_AUX_R", "PWRGD_P1V05_AUX_R",
+ "PWRGD_P52V_HSC_PWROK_R", "PWRGD_P24V_AUX_2_R",
+ "PWRGD_P24V_AUX_R", "PWRGD_P12V_AUX_R2",
+ "PWRGD_P12V_SCM_R", "P24V_AUX_INA230_ALERT_N_R",
+ "", "PRSNT_CAN1_MCIO_N",
+ "PRSNT_CAN2_MCIO_N", "PRSNT_AALC_MCIO_N",
+ "PRSNT_RACKMON_MCIO_N", "PRSNT_RIO_RACKMON_N";
+ };
+
+ temp-sensor@4f {
+ compatible = "ti,tmp75";
+ reg = <0x4f>;
+ };
+
+ eeprom@54 {
+ compatible = "atmel,24c128";
+ reg = <0x54>;
+ };
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9548";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ i2c5mux0ch0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ i2c5mux0ch1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ i2c5mux0ch2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+
+ eeprom@56 {
+ compatible = "atmel,24c128";
+ reg = <0x56>;
+ };
+ };
+
+ i2c5mux0ch3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+
+ eeprom@56 {
+ compatible = "atmel,24c128";
+ reg = <0x56>;
+ };
+ };
+
+ i2c5mux0ch4: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+
+ eeprom@56 {
+ compatible = "atmel,24c128";
+ reg = <0x56>;
+ };
+ };
+
+ i2c5mux0ch5: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+
+ eeprom@56 {
+ compatible = "atmel,24c128";
+ reg = <0x56>;
+ };
+ };
+
+ i2c5mux0ch6: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+
+ eeprom@56 {
+ compatible = "atmel,24c128";
+ reg = <0x56>;
+ };
+ };
+
+ i2c5mux0ch7: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+
+ eeprom@56 {
+ compatible = "atmel,24c128";
+ reg = <0x56>;
+ };
+ };
+ };
+};
+
+&i2c6 {
+ status = "okay";
+
+ dac@0c {
+ reg = <0x0c>;
+ compatible = "adi,ad5612";
+ vcc-supply = <&p5v_dac_aux>;
+ };
+
+ dac@0e {
+ reg = <0x0e>;
+ compatible = "adi,ad5612";
+ vcc-supply = <&p5v_dac_aux>;
+ };
+
+ dac@0f {
+ reg = <0x0f>;
+ compatible = "adi,ad5612";
+ vcc-supply = <&p5v_dac_aux>;
+ };
+
+ io_expander0: gpio@20 {
+ compatible = "nxp,pca9555";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&io_expander7>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "", "",
+ "", "",
+ "", "PRSNT_FANBP_0_PWR_N",
+ "PRSNT_FANBP_0_SIG_N", "PRSNT_POE_PWR_N",
+ "PRSNT_POE_SIG_N", "",
+ "PWRGD_P3V3_ISO_POE_BMC_R", "",
+ "", "",
+ "DEV_DIS_N", "PCI_DIS_N";
+ };
+
+ io_expander1: gpio@21 {
+ compatible = "nxp,pca9555";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&io_expander7>;
+ interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "PWRGD_CPU_LVC3_BMC", "R_FM_BIOS_POST_CMPLT_BMC",
+ "", "",
+ "", "",
+ "", "",
+ "", "",
+ "", "PCIE_SSD1_PRSNT_N",
+ "", "TRAY23_PWRGD_BUF_R",
+ "TRAY24_PWRGD_BUF_R", "TRAY29_PWRGD_BUF_R";
+ };
+
+ io_expander2: gpio@22 {
+ compatible = "nxp,pca9555";
+ reg = <0x22>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&io_expander7>;
+ interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "BOARD_ID_0", "BOARD_ID_1",
+ "BOARD_ID_2", "BOARD_ID_3",
+ "SKU_ID_3", "SKU_ID_2",
+ "SKU_ID_1", "SKU_ID_0",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ io_expander7: gpio@23 {
+ compatible = "nxp,pca9555";
+ reg = <0x23>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <32 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "IOEXP1_INT_N", "IOEXP2_INT_N",
+ "IOEXP3_INT_N", "IOEXP4_INT_N",
+ "IOEXP5_INT_N", "IOEXP6_INT_N",
+ "IOEXP7_INT_N", "",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ io_expander8: gpio@24 {
+ compatible = "nxp,pca9555";
+ reg = <0x24>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&io_expander7>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "PRSNT_MGMT_J54_N", "PRSNT_RACKMON_J47_N",
+ "PRSNT_MGMT_DEBUG_J53_N", "PRSNT_MINISAS_TOP_J49_N",
+ "PRSNT_MINISAS_TOP_J50_N", "PRSNT_MINISAS_BOT_J51_N",
+ "PRSNT_MINISAS_BOT_J52_N", "JTAG_PLD_JTAGEN",
+ "PU_PLD_CONFIG_N", "",
+ "", "",
+ "", "",
+ "", "";
+};
+
+ // Marvell 88E6393X EEPROM
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ };
+
+ rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+};
+
+&i2c7 {
+ status = "okay";
+ bus-frequency = <100000>;
+ multi-master;
+ aspeed,hw-timeout-ms = <1000>;
+
+ ipmb@10 {
+ compatible = "ipmb-dev";
+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+ i2c-protocol;
+ };
+};
+
+&i2c8 {
+ status = "okay";
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9548";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ i2c8mux0ch0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ status = "okay";
+ };
+
+ i2c8mux0ch1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ status = "okay";
+ };
+
+ i2c8mux0ch2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ status = "okay";
+ };
+
+ i2c8mux0ch3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ status = "okay";
+ };
+
+ i2c8mux0ch4: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ status = "okay";
+ };
+
+ i2c8mux0ch5: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ status = "okay";
+ };
+
+ i2c8mux0ch6: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ status = "okay";
+ };
+
+ i2c8mux0ch7: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ status = "okay";
+ };
+ };
+};
+
+&i2c9 {
+ status = "okay";
+
+ temperature-sensor@4b {
+ compatible = "ti,tmp75";
+ reg = <0x4b>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c128";
+ reg = <0x50>;
+ };
+
+ eeprom@51 {
+ compatible = "atmel,24c128";
+ reg = <0x51>;
+ };
+
+ eeprom@56 {
+ compatible = "atmel,24c64";
+ reg = <0x56>;
+ };
+};
+
+&i2c10 {
+ status = "okay";
+ /*
+ * This board physically routes two sets of presence signals to support
+ * both new and older tray designs concurrently.
+ * The 'legacy_' prefix is used to distinguish these backward-compatible
+ * PCA9555 expanders from the new CAN-based PCA9698 expanders (e.g., gpio@40)
+ * and to prevent device tree label collisions.
+ */
+ legacy_prsnt_io_expander0: gpio@11 {
+ compatible = "nxp,pca9555";
+ reg = <0x11>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <40 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_PRSNT1_N_BUF_R", "TRAY_PRSNT2_N_BUF_R",
+ "TRAY_PRSNT3_N_BUF_R", "TRAY_PRSNT4_N_BUF_R",
+ "TRAY_PRSNT5_N_BUF_R", "TRAY_PRSNT6_N_BUF_R",
+ "TRAY_PRSNT7_N_BUF_R", "TRAY_PRSNT8_N_BUF_R",
+ "TRAY_PRSNT9_N_BUF_R", "TRAY_PRSNT10_N_BUF_R",
+ "TRAY_PRSNT11_N_BUF_R", "TRAY_PRSNT12_N_BUF_R",
+ "TRAY_PRSNT13_N_BUF_R", "TRAY_PRSNT14_N_BUF_R",
+ "TRAY_PRSNT15_N_BUF_R", "TRAY_PRSNT16_N_BUF_R";
+ };
+
+ legacy_prsnt_io_expander1: gpio@12 {
+ compatible = "nxp,pca9555";
+ reg = <0x12>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <40 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_PRSNT17_N_BUF_R", "TRAY_PRSNT18_N_BUF_R",
+ "TRAY_PRSNT19_N_BUF_R", "TRAY_PRSNT20_N_BUF_R",
+ "TRAY_PRSNT21_N_BUF_R", "TRAY_PRSNT22_N_BUF_R",
+ "TRAY_PRSNT23_N_BUF_R", "TRAY_PRSNT24_N_BUF_R",
+ "TRAY_PRSNT25_N_BUF_R", "TRAY_PRSNT26_N_BUF_R",
+ "TRAY_PRSNT27_N_BUF_R", "TRAY_PRSNT28_N_BUF_R",
+ "TRAY_PRSNT29_N_BUF_R", "TRAY_PRSNT30_N_BUF_R",
+ "TRAY_PRSNT31_N_BUF_R", "TRAY_PRSNT32_N_BUF_R";
+ };
+
+ legacy_prsnt_io_expander2: gpio@13 {
+ compatible = "nxp,pca9555";
+ reg = <0x13>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <40 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_PRSNT33_N_BUF_R", "TRAY_PRSNT34_N_BUF_R",
+ "TRAY_PRSNT35_N_BUF_R", "TRAY_PRSNT36_N_BUF_R",
+ "TRAY_PRSNT37_N_BUF_R", "TRAY_PRSNT38_N_BUF_R",
+ "TRAY_PRSNT39_N_BUF_R", "TRAY_PRSNT40_N_BUF_R",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ power-monitor@14 {
+ compatible = "infineon,xdp710";
+ reg = <0x14>;
+ };
+
+ legacy_pwrgd_io_expander1: gpio@15 {
+ compatible = "nxp,pca9555";
+ reg = <0x15>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_PWRGD17_N_BUF_R", "TRAY_PWRGD18_N_BUF_R",
+ "TRAY_PWRGD19_N_BUF_R", "TRAY_PWRGD20_N_BUF_R",
+ "TRAY_PWRGD21_N_BUF_R", "TRAY_PWRGD22_N_BUF_R",
+ "TRAY_PWRGD23_N_BUF_R", "TRAY_PWRGD24_N_BUF_R",
+ "TRAY_PWRGD25_N_BUF_R", "TRAY_PWRGD26_N_BUF_R",
+ "TRAY_PWRGD27_N_BUF_R", "TRAY_PWRGD28_N_BUF_R",
+ "TRAY_PWRGD29_N_BUF_R", "TRAY_PWRGD30_N_BUF_R",
+ "TRAY_PWRGD31_N_BUF_R", "TRAY_PWRGD32_N_BUF_R";
+ };
+
+ legacy_pwrgd_io_expander2: gpio@16 {
+ compatible = "nxp,pca9555";
+ reg = <0x16>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_PWRGD33_N_BUF_R", "TRAY_PWRGD34_N_BUF_R",
+ "TRAY_PWRGD35_N_BUF_R", "TRAY_PWRGD36_N_BUF_R",
+ "TRAY_PWRGD37_N_BUF_R", "TRAY_PWRGD38_N_BUF_R",
+ "TRAY_PWRGD39_N_BUF_R", "TRAY_PWRGD40_N_BUF_R",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ legacy_leak_io_expander0: gpio@17 {
+ compatible = "nxp,pca9555";
+ reg = <0x17>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <46 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_LEAK_DETECT1_N_BUF_R", "TRAY_LEAK_DETECT2_N_BUF_R",
+ "TRAY_LEAK_DETECT3_N_BUF_R", "TRAY_LEAK_DETECT4_N_BUF_R",
+ "TRAY_LEAK_DETECT5_N_BUF_R", "TRAY_LEAK_DETECT6_N_BUF_R",
+ "TRAY_LEAK_DETECT7_N_BUF_R", "TRAY_LEAK_DETECT8_N_BUF_R",
+ "TRAY_LEAK_DETECT9_N_BUF_R", "TRAY_LEAK_DETECT10_N_BUF_R",
+ "TRAY_LEAK_DETECT11_N_BUF_R", "TRAY_LEAK_DETECT12_N_BUF_R",
+ "TRAY_LEAK_DETECT13_N_BUF_R", "TRAY_LEAK_DETECT14_N_BUF_R",
+ "TRAY_LEAK_DETECT15_N_BUF_R", "TRAY_LEAK_DETECT16_N_BUF_R";
+ };
+
+ legacy_leak_io_expander1: gpio@18 {
+ compatible = "nxp,pca9555";
+ reg = <0x18>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <46 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_LEAK_DETECT17_N_BUF_R", "TRAY_LEAK_DETECT18_N_BUF_R",
+ "TRAY_LEAK_DETECT19_N_BUF_R", "TRAY_LEAK_DETECT20_N_BUF_R",
+ "TRAY_LEAK_DETECT21_N_BUF_R", "TRAY_LEAK_DETECT22_N_BUF_R",
+ "TRAY_LEAK_DETECT23_N_BUF_R", "TRAY_LEAK_DETECT24_N_BUF_R",
+ "TRAY_LEAK_DETECT25_N_BUF_R", "TRAY_LEAK_DETECT26_N_BUF_R",
+ "TRAY_LEAK_DETECT27_N_BUF_R", "TRAY_LEAK_DETECT28_N_BUF_R",
+ "TRAY_LEAK_DETECT29_N_BUF_R", "TRAY_LEAK_DETECT30_N_BUF_R",
+ "TRAY_LEAK_DETECT31_N_BUF_R", "TRAY_LEAK_DETECT32_N_BUF_R";
+ };
+
+ legacy_leak_io_expander2: gpio@19 {
+ compatible = "nxp,pca9555";
+ reg = <0x19>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <46 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_LEAK_DETECT33_N_BUF_R", "TRAY_LEAK_DETECT34_N_BUF_R",
+ "TRAY_LEAK_DETECT35_N_BUF_R", "TRAY_LEAK_DETECT36_N_BUF_R",
+ "TRAY_LEAK_DETECT37_N_BUF_R", "TRAY_LEAK_DETECT38_N_BUF_R",
+ "TRAY_LEAK_DETECT39_N_BUF_R", "TRAY_LEAK_DETECT40_N_BUF_R",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ legacy_small_leak_io_expander0: gpio@1a {
+ compatible = "nxp,pca9555";
+ reg = <0x1a>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <44 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_SMALL_LEAK1_N_BUF_R", "TRAY_SMALL_LEAK2_N_BUF_R",
+ "TRAY_SMALL_LEAK3_N_BUF_R", "TRAY_SMALL_LEAK4_N_BUF_R",
+ "TRAY_SMALL_LEAK5_N_BUF_R", "TRAY_SMALL_LEAK6_N_BUF_R",
+ "TRAY_SMALL_LEAK7_N_BUF_R", "TRAY_SMALL_LEAK8_N_BUF_R",
+ "TRAY_SMALL_LEAK9_N_BUF_R", "TRAY_SMALL_LEAK10_N_BUF_R",
+ "TRAY_SMALL_LEAK11_N_BUF_R", "TRAY_SMALL_LEAK12_N_BUF_R",
+ "TRAY_SMALL_LEAK13_N_BUF_R", "TRAY_SMALL_LEAK14_N_BUF_R",
+ "TRAY_SMALL_LEAK15_N_BUF_R", "TRAY_SMALL_LEAK16_N_BUF_R";
+ };
+
+ legacy_small_leak_io_expander1: gpio@1b {
+ compatible = "nxp,pca9555";
+ reg = <0x1b>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <44 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_SMALL_LEAK17_N_BUF_R", "TRAY_SMALL_LEAK18_N_BUF_R",
+ "TRAY_SMALL_LEAK19_N_BUF_R", "TRAY_SMALL_LEAK20_N_BUF_R",
+ "TRAY_SMALL_LEAK21_N_BUF_R", "TRAY_SMALL_LEAK22_N_BUF_R",
+ "TRAY_SMALL_LEAK23_N_BUF_R", "TRAY_SMALL_LEAK24_N_BUF_R",
+ "TRAY_SMALL_LEAK25_N_BUF_R", "TRAY_SMALL_LEAK26_N_BUF_R",
+ "TRAY_SMALL_LEAK27_N_BUF_R", "TRAY_SMALL_LEAK28_N_BUF_R",
+ "TRAY_SMALL_LEAK29_N_BUF_R", "TRAY_SMALL_LEAK30_N_BUF_R",
+ "TRAY_SMALL_LEAK31_N_BUF_R", "TRAY_SMALL_LEAK32_N_BUF_R";
+ };
+
+ legacy_small_leak_io_expander2: gpio@1c {
+ compatible = "nxp,pca9555";
+ reg = <0x1c>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <44 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_SMALL_LEAK33_N_BUF_R", "TRAY_SMALL_LEAK34_N_BUF_R",
+ "TRAY_SMALL_LEAK35_N_BUF_R", "TRAY_SMALL_LEAK36_N_BUF_R",
+ "TRAY_SMALL_LEAK37_N_BUF_R", "TRAY_SMALL_LEAK38_N_BUF_R",
+ "TRAY_SMALL_LEAK39_N_BUF_R", "TRAY_SMALL_LEAK40_N_BUF_R",
+ "", "",
+ "", "",
+ "", "",
+ "", "";
+ };
+
+ legacy_pwrgd_io_expander0: gpio@28 {
+ compatible = "nxp,pca9555";
+ reg = <0x28>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&sgpiom0>;
+ interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
+
+ gpio-line-names =
+ "TRAY_PWRGD1_N_BUF_R", "TRAY_PWRGD2_N_BUF_R",
+ "TRAY_PWRGD3_N_BUF_R", "TRAY_PWRGD4_N_BUF_R",
+ "TRAY_PWRGD5_N_BUF_R", "TRAY_PWRGD6_N_BUF_R",
+ "TRAY_PWRGD7_N_BUF_R", "TRAY_PWRGD8_N_BUF_R",
+ "TRAY_PWRGD9_N_BUF_R", "TRAY_PWRGD10_N_BUF_R",
+ "TRAY_PWRGD11_N_BUF_R", "TRAY_PWRGD12_N_BUF_R",
+ "TRAY_PWRGD13_N_BUF_R", "TRAY_PWRGD14_N_BUF_R",
+ "TRAY_PWRGD15_N_BUF_R", "TRAY_PWRGD16_N_BUF_R";
+ };
+
+ adc@35 {
+ compatible = "maxim,max11617";
+ reg = <0x35>;
+ };
+
+ power-monitor@44 {
+ compatible = "lltc,ltc4287";
+ reg = <0x44>;
+ shunt-resistor-micro-ohms = <500>;
+ };
+
+ adc@48 {
+ compatible = "ti,ads1015";
+ reg = <0x48>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ temp-sensor@4c {
+ compatible = "ti,tmp75";
+ reg = <0x4c>;
+ };
+
+ temp-sensor@4d {
+ compatible = "ti,tmp75";
+ reg = <0x4d>;
+ };
+
+ temp-sensor@4e {
+ compatible = "ti,tmp75";
+ reg = <0x4e>;
+ };
+
+ power-monitor@4f {
+ compatible = "ti,ina230";
+ reg = <0x4f>;
+ shunt-resistor = <1000>;
+ };
+
+ power-monitor@69 {
+ compatible = "pmbus";
+ reg = <0x69>;
+ };
+
+ fpga_io_expander64: gpio@64 {
+ compatible = "nxp,pca9555";
+ reg = <0x64>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio-line-names =
+ "", "",
+ "", "",
+ "", "",
+ "LEAK_CONFIG0", "LEAK_CONFIG1",
+ "FPGA_PWRGD_P24V_AUX_R", "FPGA_PWRGD_P24V_AUX_2_R",
+ "FPGA_PWRGD_P12V_SCM_R", "FPGA_PWRGD_P12V_AUX_R2",
+ "FPGA_PRSNT_FANBP_0_SIG_R_PLD_N", "FPGA_PRSNT_FANBP_0_PWR_R_PLD_N",
+ "FPGA_P24V_AUX_INA230_ALERT_N_R", "FPGA_SMB_TMC75_TEMP_ALERT_N_R";
+ };
+
+ fpga_io_expander65: gpio@65 {
+ compatible = "nxp,pca9555";
+ reg = <0x65>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio-line-names =
+ "FPGA_PCI_DIS_N", "FPGA_DEV_DIS_N",
+ "FPGA_PWRGD_P3V3_AUX_R", "FPGA_PWRGD_P5V_AUX_R2",
+ "FPGA_PWRGD_P1V05_AUX_R", "FPGA_P48V_HSC_ALERT_N",
+ "FPGA_PWRGD_P1V5_AUX_R", "FPGA_PWRGD_P52V_HSC_PWROK_R",
+ "FPGA_R_COME_THERMTRIP_L", "FPGA_PRSNT_POE_SIG_PLD_N",
+ "FPGA_PRSNT_POE_PWR_PLD_N", "FPGA_PRSNT_RIO_RACKMON_N",
+ "FPGA_PRSNT_CAN2_MCIO_N", "FPGA_PRSNT_CAN1_MCIO_N",
+ "FPGA_PRSNT_RACKMON_MCIO_N", "FPGA_PRSNT_AALC_MCIO_N";
+ };
+
+ fpga_io_expander66: gpio@66 {
+ compatible = "nxp,pca9555";
+ reg = <0x66>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio-line-names =
+ "FPGA_R_FM_CPU_ERR0_LVT3_L", "FPGA_FPGA_R_FM_PCHHOT_L",
+ "FPGA_R_FM_BIOS_POST_CMPLT_L", "FPGA_R_FM_SOC_BMC_RST_L",
+ "FPGA_R_CPU_MSMI_CATERR_N", "FPGA_R_H_MEMHOT_OUT_FET_L",
+ "FPGA_R_PWRGD_P3V3_STBY", "FPGA_R_PWRGD_PCH_PWROK",
+ "FPGA_TRAY23_PWRGD_BUF_R", "FPGA_TRAY24_PWRGD_BUF_R",
+ "FPGA_P24V_AUX_2_INA230_ALERT_N_R", "FPGA_R_IRQ_BMC_PCH_SMI_N",
+ "FPGA_R_FM_CPU_DIMM_EVENT_COD_BUF", "FPGA_R_BIOS_MSG_DIS_L",
+ "FPGA_R_ISO_FM_USB_OC0_L", "FPGA_SPI_LVC_EN";
+ };
+
+ fpga_io_expander67: gpio@67 {
+ compatible = "nxp,pca9555";
+ reg = <0x67>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio-line-names =
+ "FPGA_TRAY29_PWRGD_BUF_R", "FPGA_TRAY30_PWRGD_BUF_R",
+ "FPGA_TRAY31_PWRGD_BUF_R", "FPGA_TRAY32_PWRGD_BUF_R",
+ "FPGA_TRAY37_PWRGD_BUF_R", "FPGA_TRAY38_PWRGD_BUF_R",
+ "FPGA_TRAY39_PWRGD_BUF_R", "FPGA_TRAY40_PWRGD_BUF_R",
+ "FPGA_ISO_CARRIER_BOARD_PWR_OK", "FPGA_UART_MUX_SEL",
+ "", "",
+ "", "",
+ "", "";
+ };
+};
+
+&i2c11 {
+ status = "okay";
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9548";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ i2c11mux0ch0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ status = "okay";
+ };
+
+ i2c11mux0ch1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ status = "okay";
+ };
+
+ i2c11mux0ch2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ status = "okay";
+ };
+
+ i2c11mux0ch3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ status = "okay";
+ };
+
+ i2c11mux0ch4: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ status = "okay";
+ };
+
+ i2c11mux0ch5: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ status = "okay";
+ };
+
+ i2c11mux0ch6: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ status = "okay";
+ };
+
+ i2c11mux0ch7: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ status = "okay";
+ };
+ };
+};
+
+&i2c12 {
+ status = "okay";
+ bus-frequency = <400000>;
+};
+
+&i2c13 {
+ status = "okay";
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9548";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ i2c13mux0ch0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ status = "okay";
+ };
+
+ i2c13mux0ch1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ status = "okay";
+ };
+
+ i2c13mux0ch2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ status = "okay";
+ };
+
+ i2c13mux0ch3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ status = "okay";
+ };
+
+ i2c13mux0ch4: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ status = "okay";
+ };
+
+ i2c13mux0ch5: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ status = "okay";
+ };
+
+ i2c13mux0ch6: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ status = "okay";
+ };
+
+ i2c13mux0ch7: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ status = "okay";
+ };
+ };
+};
+
+&i2c14 {
+ status = "okay";
+};
+
+&i2c15 {
+ status = "okay";
+
+ i2c-mux@77 {
+ compatible = "nxp,pca9548";
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ i2c-mux-idle-disconnect;
+
+ i2c15mux0ch0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ status = "okay";
+ };
+
+ i2c15mux0ch1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ status = "okay";
+ };
+
+ i2c15mux0ch2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ status = "okay";
+ };
+
+ i2c15mux0ch3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ status = "okay";
+ };
+
+ i2c15mux0ch4: i2c@4 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <4>;
+ status = "okay";
+ };
+
+ i2c15mux0ch5: i2c@5 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <5>;
+ status = "okay";
+ };
+
+ i2c15mux0ch6: i2c@6 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <6>;
+ status = "okay";
+ };
+
+ i2c15mux0ch7: i2c@7 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <7>;
+ status = "okay";
+ };
+ };
+};
+
+&kcs3 {
+ aspeed,lpc-io-reg = <0xca2>;
+ status = "okay";
+};
+
+&lpc_ctrl {
+ status = "okay";
+};
+
+&mac2 {
+ status = "okay";
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii3_default>;
+
+ /*
+ * The Marvell 88E6393X is initialized at boot via EEPROM
+ * configuration and hardware straps.
+ * The BMC connects via an RMII fixed-link; link parameters are fixed
+ * by board design.
+ */
+ fixed-link {
+ speed = <100>;
+ full-duplex;
+ };
+};
+
+&mac3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii4_default>;
+ use-ncsi;
+};
+
+&peci0 {
+ status = "okay";
+};
+
+&sgpiom0 {
+ status = "okay";
+ ngpios = <128>;
+ bus-frequency = <100000>;
+ gpio-line-names =
+ /*"input pin","output pin"*/
+ /*A0 - A7*/
+ "power-chassis-good","FM_PLD_HEARTBEAT_LVC3_R",
+ "host0-ready","R_BMC_PTH_RST_BTN_L",
+ "CONTROL_VT2_SUPPLY1_CLOSE","FM_MDIO_SW_SEL_PLD",
+ "CONTROL_VT2_SUPPLY2_CLOSE","FM_88E6393X_BIN_UPDATE_EN_N",
+ "CONTROL_VT2_SUPPLY3_CLOSE","Sequence_TransFR_Alert",
+ "RETURN_CNTL1_FB","WATER_VALVE1_OPEN",
+ "RETURN_CNTL2_FB","WATER_VALVE2_OPEN",
+ "RETURN_CNTL3_FB","WATER_VALVE3_OPEN",
+ /*B0 - B7*/
+ "IT_STOP_PUMP_R_CPLD","WATER_VALVE1_CLOSE",
+ "IT_STOP_PUMP_SPARE_R_CPLD","WATER_VALVE2_CLOSE",
+ "IT_STOP_PUMP_2_R_CPLD","WATER_VALVE3_CLOSE",
+ "IT_STOP_PUMP_SPARE_2_R_CPLD","REPORT_VT2_SUPPLY1_CLOSE",
+ "RPU_2_READY_SPARE_PLD_R","REPORT_VT2_SUPPLY2_CLOSE",
+ "RPU_2_READY_PLD_R","REPORT_VT2_SUPPLY3_CLOSE",
+ "RPU_READY_SPARE_PLD_R","PCIE_SSD1_PRSNT_N",
+ "RPU_READY_PLD_R","",
+ /*C0 - C7*/
+ "IOEXP8_INT_N","",
+ "SUPPLY_CNTL1_FB","",
+ "SUPPLY_CNTL2_FB","",
+ "SUPPLY_CNTL3_FB","",
+ "PRSNT_TRAY1_TO_40_R_BUF_N","",
+ "PWRGD_TRAY1_TO_40_R_BUF","",
+ "SMALL_LEAK_TRAY1_TO_40_R_BUF_N","",
+ "LEAK_DETECT_TRAY1_TO_40_R_BUF_N","",
+ /*D0 - D7*/
+ "PRSNT_CANBUSP1_TRAY1_TO_32_N","",
+ "PWRGD_CANBUSP1_TRAY1_TO_32_PWROK","",
+ "SMALL_LEAK_CANBUSP1_TRAY1_TO_32_N","",
+ "LEAK_DETECT_CANBUSP1_TRAY1_TO_32_N","",
+ "PRSNT_CANBUSP2_TRAY1_TO_32_N","",
+ "PWRGD_CANBUSP2_TRAY1_TO_32_PWROK","",
+ "SMALL_LEAK_CANBUSP2_TRAY1_TO_32_N","",
+ "LEAK_DETECT_CANBUSP2_TRAY1_TO_32_N","",
+ /*E0 - E7*/
+ "PRSNT_CANBUSP3_TRAY1_TO_32_N","",
+ "PWRGD_CANBUSP3_TRAY1_TO_32_PWROK","",
+ "SMALL_LEAK_CANBUSP3_TRAY1_TO_32_N","",
+ "LEAK_DETECT_CANBUSP3_TRAY1_TO_32_N","",
+ "PRSNT_CANBUSP4_TRAY1_TO_32_N","",
+ "PWRGD_CANBUSP4_TRAY1_TO_32_PWROK","",
+ "SMALL_LEAK_CANBUSP4_TRAY1_TO_32_N","",
+ "LEAK_DETECT_CANBUSP4_TRAY1_TO_32_N","",
+ /*F0 - F7*/
+ "PRSNT_CANBUSP5_TRAY1_TO_32_N","",
+ "PWRGD_CANBUSP5_TRAY1_TO_32_PWROK","",
+ "SMALL_LEAK_CANBUSP5_TRAY1_TO_32_N","",
+ "LEAK_DETECT_CANBUSP5_TRAY1_TO_32_N","",
+ "PRSNT_CANBUSP6_TRAY1_TO_32_N","",
+ "PWRGD_CANBUSP6_TRAY1_TO_32_PWROK","",
+ "SMALL_LEAK_CANBUSP6_TRAY1_TO_32_N","",
+ "LEAK_DETECT_CANBUSP6_TRAY1_TO_32_N","",
+ /*G0 - G7*/
+ "PRSNT_CANBUSP7_TRAY1_TO_32_N","",
+ "PWRGD_CANBUSP7_TRAY1_TO_32_PWROK","",
+ "SMALL_LEAK_CANBUSP7_TRAY1_TO_32_N","",
+ "LEAK_DETECT_CANBUSP7_TRAY1_TO_32_N","",
+ "PRSNT_CANBUSP8_TRAY1_TO_32_N","",
+ "PWRGD_CANBUSP8_TRAY1_TO_32_PWROK","",
+ "SMALL_LEAK_CANBUSP8_TRAY1_TO_32_N","",
+ "LEAK_DETECT_CANBUSP8_TRAY1_TO_32_N","",
+ /*H0 - H7*/
+ "CHASSIS0_LEAK_Q_N_R","",
+ "CHASSIS1_LEAK_Q_N_R","",
+ "CHASSIS2_LEAK_Q_N_R","",
+ "CHASSIS3_LEAK_Q_N_R","",
+ "CHASSIS4_LEAK_Q_N_R","",
+ "CHASSIS5_LEAK_Q_N_R","",
+ "CHASSIS6_LEAK_Q_N_R","",
+ "CHASSIS7_LEAK_Q_N_R","",
+ /*I0 - I7*/
+ "CHASSIS8_LEAK_Q_N_R","",
+ "CHASSIS9_LEAK_Q_N_R","",
+ "CHASSIS10_LEAK_Q_N_R","",
+ "CHASSIS11_LEAK_Q_N_R","",
+ "AALC_RPU_READY","",
+ "","",
+ "","",
+ "","",
+ /*J0 - J7*/
+ "","",
+ "","",
+ "","",
+ "","",
+ "","",
+ "","",
+ "","",
+ "","",
+ /*K0 - K7*/
+ "","",
+ "","",
+ "","",
+ "","",
+ "","",
+ "","",
+ "","",
+ "","",
+ /*L0 - L7*/
+ "IT_GEAR_RPU_2_LINK_PRSNT_SPARE_N_R","",
+ "IT_GEAR_RPU_2_LINK_PRSNT_N_R","",
+ "IT_GEAR_RPU_LINK_PRSNT_SPARE_N_R","",
+ "IT_GEAR_RPU_LINK_PRSNT_N_R","",
+ "","",
+ "","",
+ "","",
+ "","",
+ /*M0 - M7*/
+ "","",
+ "","",
+ "PRSNT_SENSOR_N","",
+ "PRSNT3_VT2_PLD_N","",
+ "PRSNT2_VT2_PLD_N","",
+ "PRSNT1_VT2_PLD_N","",
+ "PRSNT3_RETURN_PLD_N","",
+ "PRSNT2_RETURN_PLD_N","",
+ /*N0 - N7*/
+ "PRSNT1_RETURN_PLD_N","",
+ "PRSNT3_SUPPLY_PLD_N","",
+ "PRSNT2_SUPPLY_PLD_N","",
+ "PRSNT1_SUPPLY_PLD_N","",
+ "PRSNT_LEAK11_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK10_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK9_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK8_SENSOR_R_PLD_N","",
+ /*O0 - O7*/
+ "PRSNT_LEAK7_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK6_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK5_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK4_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK3_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK2_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK1_SENSOR_R_PLD_N","",
+ "PRSNT_LEAK0_SENSOR_R_PLD_N","",
+ /*P0 - P7*/
+ "","",
+ "","",
+ "","",
+ "","",
+ "","SGPIO_REG_VALID_0",
+ "","SGPIO_REG_VALID_1",
+ "","SGPIO_REG_VALID_2",
+ "","SGPIO_REG_VALID_3";
+};
+
+&spi2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi2_default &pinctrl_spi2cs1_default>;
+
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "pnor";
+ spi-max-frequency = <12000000>;
+ spi-tx-bus-width = <2>;
+ spi-rx-bus-width = <2>;
+ };
+
+ flash@1 {
+ status = "okay";
+ m25p,fast-read;
+ label = "e810";
+ spi-max-frequency = <12000000>;
+ spi-tx-bus-width = <2>;
+ spi-rx-bus-width = <2>;
+ };
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&wdt1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdtrst1_default>;
+ aspeed,reset-type = "soc";
+ aspeed,external-signal;
+ aspeed,ext-push-pull;
+ aspeed,ext-active-high;
+ aspeed,ext-pulse-duration = <256>;
+};
+
--
2.34.1
^ permalink raw reply related
* [PATCH v5 1/2] dt-bindings: arm: aspeed: add Meta ventura2 board
From: Kyle Hsieh @ 2026-06-08 2:42 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
Kyle Hsieh, Krzysztof Kozlowski
In-Reply-To: <20260608-ventura2_initial_dts-v5-0-37ee5bcf58b6@gmail.com>
Document the new compatibles used on Facebook ventura2.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Kyle Hsieh <kylehsieh1995@gmail.com>
---
Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 9298c1a75dd1..d48607c86e8e 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -92,6 +92,7 @@ properties:
- facebook,harma-bmc
- facebook,minerva-cmc
- facebook,santabarbara-bmc
+ - facebook,ventura2-rmc
- facebook,yosemite4-bmc
- facebook,yosemite5-bmc
- ibm,balcones-bmc
--
2.34.1
^ permalink raw reply related
* [PATCH v5 0/2] Add Meta(Facebook) ventura2 BMC(AST2600)
From: Kyle Hsieh @ 2026-06-08 2:42 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
Kyle Hsieh, Krzysztof Kozlowski
Summary:
Add linux device tree entry related to Meta(Facebook) ventura2.
specific devices connected to BMC(AST2600) SoC.
Signed-off-by: Kyle Hsieh <kylehsieh1995@gmail.com>
---
Changes in v5:
- Addressed review comments:
* Added comments explaining the necessity of 'legacy_' prefixes (hardware label collision), pre-allocated I2C aliases (future expansions), and the 'ledd1' naming convention (schematic alignment).
* Removed the empty `&mdio0` node to comply with upstream networking subsystem guidelines.
* Removed the redundant `&peci0` node.
* Sorted `&kcs3` and `&lpc_ctrl` nodes in strict alphabetical order.
- Hardware/DT alignment updates:
* Removed unpopulated sensors (adi,adt7461, infineon,tda38640, ti,ina230, ti,ina238) to accurately reflect the current board population.
* Added the secondary flash node (flash@1 labeled "e810") under the &spi2 bus.
- Link to v4: https://lore.kernel.org/r/20260424-ventura2_initial_dts-v4-0-806b00ea4314@gmail.com
Changes in v4:
- Fixed capitalization: "ventura2" -> "Ventura2".
- Reordered I2C child nodes in ascending order of unit addresses.
- Enable PECI, LPC control, and KCS3 interfaces for host communication.
- Configure MCTP controller on I2C4 and enable MCTP support for specific mux channels.
- Add Infineon TDA38640 and TI INA230 power monitor nodes.
- GPIO and Pinmux cleanup for PVT:
- Aligned gpio-line-names as requested.
- Remove unused or non-existent GPIO line names to align with Ventura2 PVT.
- Update specific GPIO pins to empty strings where signals were removed or consolidated.
- Adjust SGPIOM frequency to 200kHz and update signal line names.
- Enable UART3 and add serial2 alias.
- Link to v3: https://lore.kernel.org/r/20260113-ventura2_initial_dts-v3-0-2dbfda6a5b47@gmail.com
Changes in v3:
- Add annotation for marvel 88e6393x
- Modify the gpio-line-name
- Modify the node order alphabetically
- Modify dt-bindings document for rmc instead of bmc
- Move the gpio-line-names to original node
- Link to v2: https://lore.kernel.org/r/20251224-ventura2_initial_dts-v2-0-f193ba5d4073@gmail.com
Changes in v2:
- Remove unused mdio
- Link to v1: https://lore.kernel.org/r/20251222-ventura2_initial_dts-v1-0-1f06166c78a3@gmail.com
---
Kyle Hsieh (2):
dt-bindings: arm: aspeed: add Meta ventura2 board
ARM: dts: aspeed: ventura2: Add Meta ventura2 BMC
.../devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
arch/arm/boot/dts/aspeed/Makefile | 1 +
.../dts/aspeed/aspeed-bmc-facebook-ventura2.dts | 2888 ++++++++++++++++++++
3 files changed, 2890 insertions(+)
---
base-commit: 9448598b22c50c8a5bb77a9103e2d49f134c9578
change-id: 20251222-ventura2_initial_dts-909b3277d665
Best regards,
--
Kyle Hsieh <kylehsieh1995@gmail.com>
^ permalink raw reply
* [PATCH v3 5/5] drm/verisilicon: add DCUltraLite chip identity to HWDB
From: Joey Lu @ 2026-06-08 2:32 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260608023237.305036-1-a0987203069@gmail.com>
Register the Nuvoton MA35D1 DCUltraLite chip identity in
vs_chip_identities[]:
model = 0x0 (DCUltraLite; Verisilicon uses 0 for this IP)
revision = 0x5560
customer_id = 0x305
generation = VSDC_GEN_DC8000
display_count = 1
max_cursor_size = 32
Placing this entry last makes it the gate that enables MA35D1 hardware
recognition only after all the supporting ops and DTS changes are in
place.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/vs_hwdb.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 91524d16f778..7d630a667a3f 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
@@ -129,6 +129,16 @@ static struct vs_chip_identity vs_chip_identities[] = {
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
},
+ {
+ .model = 0x0, /* DCUltraLite */
+ .revision = 0x5560,
+ .customer_id = 0x305,
+
+ .generation = VSDC_GEN_DC8000,
+ .display_count = 1,
+ .max_cursor_size = 32,
+ .formats = &vs_formats_no_yuv444,
+ },
};
int vs_fill_chip_identity(struct regmap *regs,
--
2.43.0
^ permalink raw reply related
* [PATCH v3 4/5] drm/verisilicon: add Nuvoton MA35D1 DCU Lite display controller support
From: Joey Lu @ 2026-06-08 2:32 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260608023237.305036-1-a0987203069@gmail.com>
The Nuvoton MA35D1 SoC integrates a Verisilicon DCUltraLite display
controller whose register layout differs from the DC8200 in several
important ways:
1. No CONFIG_EX commit path: framebuffer updates use the enable (bit 0)
and reset (bit 4) bits in FB_CONFIG instead of the DC8200 staging
registers (FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT,
FB_BLEND_CONFIG, PANEL_CONFIG_EX).
2. No PANEL_START register: panel output starts when
PANEL_CONFIG.RUNNING is set; there is no multi-display sync start
register.
3. Different IRQ registers: DCUltraLite uses DISP_IRQ_STA (0x147C) /
DISP_IRQ_EN (0x1480) versus DC8200's TOP_IRQ_ACK (0x0010) /
TOP_IRQ_EN (0x0014).
4. Per-frame commit cycle: DCUltraLite requires the VALID bit in
FB_CONFIG to be set at the start of each atomic commit (crtc_begin)
and cleared after (crtc_flush).
5. Simpler clock topology: only 'core' (bus gate) and 'pix0' (pixel
divider) clocks; no axi or ahb clocks required. Make axi_clk and
ahb_clk optional (devm_clk_get_optional_enabled) so DCUltraLite
nodes without those clocks are handled gracefully.
Add vs_dcu_lite.c implementing the vs_dc_funcs vtable for the above
differences. The probe now selects vs_dcu_lite_funcs when the
identified generation is VSDC_GEN_DC8000 (DCUltraLite reads model 0x0,
revision 0x5560, customer_id 0x305).
Extend Kconfig to allow building on ARCH_MA35 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_dc.c | 9 ++-
drivers/gpu/drm/verisilicon/vs_dcu_lite.c | 78 +++++++++++++++++++++++
4 files changed, 86 insertions(+), 5 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dcu_lite.c
diff --git a/drivers/gpu/drm/verisilicon/Kconfig b/drivers/gpu/drm/verisilicon/Kconfig
index 7cce86ec8603..295d246eb4b4 100644
--- a/drivers/gpu/drm/verisilicon/Kconfig
+++ b/drivers/gpu/drm/verisilicon/Kconfig
@@ -2,7 +2,7 @@
config DRM_VERISILICON_DC
tristate "DRM Support for Verisilicon DC-series display controllers"
depends on DRM && COMMON_CLK
- depends on RISCV || COMPILE_TEST
+ depends on RISCV || ARCH_MA35 || COMPILE_TEST
select DRM_BRIDGE_CONNECTOR
select DRM_CLIENT_SELECTION
select DRM_DISPLAY_HELPER
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index 9d4cd16452fa..960af0861dfa 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o \
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_dcu_lite.o vs_drm.o vs_hwdb.o \
vs_plane.o vs_primary_plane.o vs_cursor_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index c94957024189..81a8d9bf85bd 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -90,13 +90,13 @@ static int vs_dc_probe(struct platform_device *pdev)
return PTR_ERR(dc->core_clk);
}
- dc->axi_clk = devm_clk_get_enabled(dev, "axi");
+ dc->axi_clk = devm_clk_get_optional_enabled(dev, "axi");
if (IS_ERR(dc->axi_clk)) {
dev_err(dev, "can't get axi clock\n");
return PTR_ERR(dc->axi_clk);
}
- dc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
+ dc->ahb_clk = devm_clk_get_optional_enabled(dev, "ahb");
if (IS_ERR(dc->ahb_clk)) {
dev_err(dev, "can't get ahb clock\n");
return PTR_ERR(dc->ahb_clk);
@@ -134,7 +134,10 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
- dc->funcs = &vs_dc8200_funcs;
+ if (dc->identity.generation == VSDC_GEN_DC8200)
+ dc->funcs = &vs_dc8200_funcs;
+ else
+ dc->funcs = &vs_dcu_lite_funcs;
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
diff --git a/drivers/gpu/drm/verisilicon/vs_dcu_lite.c b/drivers/gpu/drm/verisilicon/vs_dcu_lite.c
new file mode 100644
index 000000000000..11ef57d5ebaa
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dcu_lite.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Joey Lu <yclu4@nuvoton.com>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_crtc_regs.h"
+#include "vs_dc.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dcu_lite_bridge_enable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dcu_lite_bridge_disable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_RESET);
+}
+
+static void vs_dcu_lite_crtc_begin(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dcu_lite_crtc_flush(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_VALID);
+}
+
+static void vs_dcu_lite_crtc_enable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dcu_lite_crtc_disable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_FB_CONFIG(output),
+ VSDC_FB_CONFIG_ENABLE);
+}
+
+static void vs_dcu_lite_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static void vs_dcu_lite_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_IRQ_EN,
+ VSDC_DISP_IRQ_VSYNC(output));
+}
+
+static u32 vs_dcu_lite_irq_handler(struct vs_dc *dc)
+{
+ u32 irqs;
+
+ regmap_read(dc->regs, VSDC_DISP_IRQ_STA, &irqs);
+ return irqs;
+}
+
+const struct vs_dc_funcs vs_dcu_lite_funcs = {
+ .bridge_enable = vs_dcu_lite_bridge_enable,
+ .bridge_disable = vs_dcu_lite_bridge_disable,
+ .crtc_begin = vs_dcu_lite_crtc_begin,
+ .crtc_flush = vs_dcu_lite_crtc_flush,
+ .crtc_enable = vs_dcu_lite_crtc_enable,
+ .crtc_disable = vs_dcu_lite_crtc_disable,
+ .enable_vblank = vs_dcu_lite_enable_vblank,
+ .disable_vblank = vs_dcu_lite_disable_vblank,
+ .irq_handler = vs_dcu_lite_irq_handler,
+};
--
2.43.0
^ permalink raw reply related
* [PATCH v3 3/5] drm/verisilicon: introduce per-variant hardware ops table
From: Joey Lu @ 2026-06-08 2:32 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260608023237.305036-1-a0987203069@gmail.com>
The DC8200 and DCUltraLite share a broadly similar register layout but
differ in how the bridge, CRTC, primary plane and IRQ paths are driven.
Introduce a vs_dc_funcs vtable so each variant can supply its own
implementation without scattering conditionals across multiple files.
Add enum vs_dc_generation (VSDC_GEN_DC8000 / VSDC_GEN_DC8200) to
vs_hwdb.h and a generation field to struct vs_chip_identity. Annotate
all four existing DC8200 HWDB entries with VSDC_GEN_DC8200.
Extract the DC8200-specific hardware ops into a new vs_dc8200.c:
bridge_enable / bridge_disable - PANEL_CONFIG/START + CONFIG_EX commit
enable_vblank / disable_vblank - TOP_IRQ_EN VSYNC bit
plane_enable_ex / disable_ex / update_ex - FB_CONFIG_EX path
irq_handler - reads TOP_IRQ_ACK
Update vs_bridge.c, vs_crtc.c, vs_primary_plane.c and vs_dc.c to
dispatch through dc->funcs instead of directly touching registers.
vs_crtc.c gains atomic_begin and atomic_flush hooks to allow variants
to gate per-frame commit cycles.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +---
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 ++++++-
drivers/gpu/drm/verisilicon/vs_dc.c | 6 +-
drivers/gpu/drm/verisilicon/vs_dc.h | 33 ++++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 107 ++++++++++++++++++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 4 +
drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +-----
9 files changed, 197 insertions(+), 51 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
diff --git a/drivers/gpu/drm/verisilicon/Makefile b/drivers/gpu/drm/verisilicon/Makefile
index 426f4bcaa834..9d4cd16452fa 100644
--- a/drivers/gpu/drm/verisilicon/Makefile
+++ b/drivers/gpu/drm/verisilicon/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_drm.o vs_hwdb.o \
+verisilicon-dc-objs := vs_bridge.o vs_crtc.o vs_dc.o vs_dc8200.o vs_drm.o vs_hwdb.o \
vs_plane.o vs_primary_plane.o vs_cursor_plane.o
obj-$(CONFIG_DRM_VERISILICON_DC) += verisilicon-dc.o
diff --git a/drivers/gpu/drm/verisilicon/vs_bridge.c b/drivers/gpu/drm/verisilicon/vs_bridge.c
index 7a93049368db..6a9af10c64e6 100644
--- a/drivers/gpu/drm/verisilicon/vs_bridge.c
+++ b/drivers/gpu/drm/verisilicon/vs_bridge.c
@@ -162,15 +162,8 @@ static void vs_bridge_enable_common(struct vs_crtc *crtc,
VSDC_DISP_PANEL_CONFIG_DE_EN |
VSDC_DISP_PANEL_CONFIG_DAT_EN |
VSDC_DISP_PANEL_CONFIG_CLK_EN);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_RUNNING(output));
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+
+ dc->funcs->bridge_enable(dc, output);
}
static void vs_bridge_atomic_enable_dpi(struct drm_bridge *bridge,
@@ -228,14 +221,7 @@ static void vs_bridge_atomic_disable(struct drm_bridge *bridge,
struct vs_dc *dc = crtc->dc;
unsigned int output = crtc->id;
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
- VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
- VSDC_DISP_PANEL_START_RUNNING(output));
- regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
- VSDC_DISP_PANEL_CONFIG_RUNNING);
-
- regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(crtc->id),
- VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+ dc->funcs->bridge_disable(dc, output);
}
static const struct drm_bridge_funcs vs_dpi_bridge_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc.c b/drivers/gpu/drm/verisilicon/vs_crtc.c
index 0b8a35d09cd2..679d6541ba1b 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc.c
+++ b/drivers/gpu/drm/verisilicon/vs_crtc.c
@@ -16,10 +16,33 @@
#include "vs_crtc_regs.h"
#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_plane.h"
+static void vs_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_begin)
+ dc->funcs->crtc_begin(dc, output);
+}
+
+static void vs_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_commit *state)
+{
+ struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
+ struct vs_dc *dc = vcrtc->dc;
+ unsigned int output = vcrtc->id;
+
+ if (dc->funcs->crtc_flush)
+ dc->funcs->crtc_flush(dc, output);
+
+ drm_crtc_vblank_atomic_flush(crtc, state);
+}
+
static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_commit *state)
{
@@ -30,6 +53,9 @@ static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
clk_disable_unprepare(dc->pix_clk[output]);
+
+ if (dc->funcs->crtc_disable)
+ dc->funcs->crtc_disable(dc, output);
}
static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -42,6 +68,9 @@ static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
drm_WARN_ON(&dc->drm_dev->base,
clk_prepare_enable(dc->pix_clk[output]));
+ if (dc->funcs->crtc_enable)
+ dc->funcs->crtc_enable(dc, output);
+
drm_crtc_vblank_on(crtc);
}
@@ -119,7 +148,8 @@ static bool vs_crtc_mode_fixup(struct drm_crtc *crtc,
}
static const struct drm_crtc_helper_funcs vs_crtc_helper_funcs = {
- .atomic_flush = drm_crtc_vblank_atomic_flush,
+ .atomic_begin = vs_crtc_atomic_begin,
+ .atomic_flush = vs_crtc_atomic_flush,
.atomic_enable = vs_crtc_atomic_enable,
.atomic_disable = vs_crtc_atomic_disable,
.mode_set_nofb = vs_crtc_mode_set_nofb,
@@ -132,7 +162,7 @@ static int vs_crtc_enable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->enable_vblank(dc, vcrtc->id);
return 0;
}
@@ -142,7 +172,7 @@ static void vs_crtc_disable_vblank(struct drm_crtc *crtc)
struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
struct vs_dc *dc = vcrtc->dc;
- regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN, VSDC_TOP_IRQ_VSYNC(vcrtc->id));
+ dc->funcs->disable_vblank(dc, vcrtc->id);
}
static const struct drm_crtc_funcs vs_crtc_funcs = {
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c
index dad9967bc10b..c94957024189 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.c
+++ b/drivers/gpu/drm/verisilicon/vs_dc.c
@@ -8,9 +8,7 @@
#include <linux/of.h>
#include <linux/of_graph.h>
-#include "vs_crtc.h"
#include "vs_dc.h"
-#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_hwdb.h"
@@ -33,7 +31,7 @@ static irqreturn_t vs_dc_irq_handler(int irq, void *private)
struct vs_dc *dc = private;
u32 irqs;
- regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
+ irqs = dc->funcs->irq_handler(dc);
vs_drm_handle_irq(dc, irqs);
@@ -136,6 +134,8 @@ static int vs_dc_probe(struct platform_device *pdev)
dev_info(dev, "Found DC%x rev %x customer %x\n", dc->identity.model,
dc->identity.revision, dc->identity.customer_id);
+ dc->funcs = &vs_dc8200_funcs;
+
if (port_count > dc->identity.display_count) {
dev_err(dev, "too many downstream ports than HW capability\n");
ret = -EINVAL;
diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h
index ed1016f18758..d77d4a1babdf 100644
--- a/drivers/gpu/drm/verisilicon/vs_dc.h
+++ b/drivers/gpu/drm/verisilicon/vs_dc.h
@@ -14,6 +14,7 @@
#include <linux/reset.h>
#include <drm/drm_device.h>
+#include <drm/drm_plane.h>
#include "vs_hwdb.h"
@@ -22,6 +23,34 @@
struct vs_drm_dev;
struct vs_crtc;
+struct vs_dc;
+
+struct vs_dc_funcs {
+ /* Bridge: atomic_enable, atomic_disable */
+ void (*bridge_enable)(struct vs_dc *dc, unsigned int output);
+ void (*bridge_disable)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_begin, atomic_flush */
+ void (*crtc_begin)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_flush)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: atomic_enable, atomic_disable */
+ void (*crtc_enable)(struct vs_dc *dc, unsigned int output);
+ void (*crtc_disable)(struct vs_dc *dc, unsigned int output);
+
+ /* CRTC: enable_vblank, disable_vblank */
+ void (*enable_vblank)(struct vs_dc *dc, unsigned int output);
+ void (*disable_vblank)(struct vs_dc *dc, unsigned int output);
+
+ /* Primary plane: atomic_enable, atomic_disable, atomic_update */
+ void (*plane_enable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*plane_disable_ex)(struct vs_dc *dc, unsigned int output);
+ void (*plane_update_ex)(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state);
+
+ /* IRQ handler */
+ u32 (*irq_handler)(struct vs_dc *dc);
+};
struct vs_dc {
struct regmap *regs;
@@ -33,6 +62,10 @@ struct vs_dc {
struct vs_drm_dev *drm_dev;
struct vs_chip_identity identity;
+ const struct vs_dc_funcs *funcs;
};
+extern const struct vs_dc_funcs vs_dc8200_funcs;
+extern const struct vs_dc_funcs vs_dcu_lite_funcs;
+
#endif /* _VS_DC_H_ */
diff --git a/drivers/gpu/drm/verisilicon/vs_dc8200.c b/drivers/gpu/drm/verisilicon/vs_dc8200.c
new file mode 100644
index 000000000000..db9e1b3cd903
--- /dev/null
+++ b/drivers/gpu/drm/verisilicon/vs_dc8200.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
+ */
+
+#include <linux/regmap.h>
+
+#include "vs_bridge_regs.h"
+#include "vs_dc.h"
+#include "vs_dc_top_regs.h"
+#include "vs_plane.h"
+#include "vs_primary_plane_regs.h"
+
+static void vs_dc8200_bridge_enable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC);
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_bridge_disable(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_CONFIG(output),
+ VSDC_DISP_PANEL_CONFIG_RUNNING);
+ regmap_clear_bits(dc->regs, VSDC_DISP_PANEL_START,
+ VSDC_DISP_PANEL_START_MULTI_DISP_SYNC |
+ VSDC_DISP_PANEL_START_RUNNING(output));
+
+ regmap_set_bits(dc->regs, VSDC_DISP_PANEL_CONFIG_EX(output),
+ VSDC_DISP_PANEL_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_enable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_disable_vblank(struct vs_dc *dc, unsigned int output)
+{
+ regmap_clear_bits(dc->regs, VSDC_TOP_IRQ_EN,
+ VSDC_TOP_IRQ_VSYNC(output));
+}
+
+static void vs_dc8200_plane_commit(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_COMMIT);
+}
+
+static void vs_dc8200_plane_enable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+ regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
+ VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_plane_disable_ex(struct vs_dc *dc, unsigned int output)
+{
+ regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
+ VSDC_FB_CONFIG_EX_FB_EN);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static void vs_dc8200_plane_update_ex(struct vs_dc *dc, unsigned int output,
+ struct drm_plane_state *state)
+{
+ regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
+ regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
+ VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
+ state->crtc_y + state->crtc_h));
+ regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
+ VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
+
+ vs_dc8200_plane_commit(dc, output);
+}
+
+static u32 vs_dc8200_irq_handler(struct vs_dc *dc)
+{
+ u32 irqs;
+
+ regmap_read(dc->regs, VSDC_TOP_IRQ_ACK, &irqs);
+ return irqs;
+}
+
+const struct vs_dc_funcs vs_dc8200_funcs = {
+ .bridge_enable = vs_dc8200_bridge_enable,
+ .bridge_disable = vs_dc8200_bridge_disable,
+ .enable_vblank = vs_dc8200_enable_vblank,
+ .disable_vblank = vs_dc8200_disable_vblank,
+ .plane_enable_ex = vs_dc8200_plane_enable_ex,
+ .plane_disable_ex = vs_dc8200_plane_disable_ex,
+ .plane_update_ex = vs_dc8200_plane_update_ex,
+ .irq_handler = vs_dc8200_irq_handler,
+};
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.c b/drivers/gpu/drm/verisilicon/vs_hwdb.c
index 2a0f7c59afa3..91524d16f778 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.c
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.c
@@ -94,6 +94,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = ~0U,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
@@ -103,6 +104,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5721,
.customer_id = 0x30B,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
@@ -112,6 +114,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = 0x310,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_with_yuv444,
@@ -121,6 +124,7 @@ static struct vs_chip_identity vs_chip_identities[] = {
.revision = 0x5720,
.customer_id = 0x311,
+ .generation = VSDC_GEN_DC8200,
.display_count = 2,
.max_cursor_size = 64,
.formats = &vs_formats_no_yuv444,
diff --git a/drivers/gpu/drm/verisilicon/vs_hwdb.h b/drivers/gpu/drm/verisilicon/vs_hwdb.h
index 2065ecb73043..a15c8b565604 100644
--- a/drivers/gpu/drm/verisilicon/vs_hwdb.h
+++ b/drivers/gpu/drm/verisilicon/vs_hwdb.h
@@ -9,6 +9,11 @@
#include <linux/regmap.h>
#include <linux/types.h>
+enum vs_dc_generation {
+ VSDC_GEN_DC8000,
+ VSDC_GEN_DC8200,
+};
+
struct vs_formats {
const u32 *array;
unsigned int num;
@@ -19,6 +24,7 @@ struct vs_chip_identity {
u32 revision;
u32 customer_id;
+ enum vs_dc_generation generation;
u32 display_count;
/*
* The hardware only supports square cursor planes, so this field
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane.c b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
index 1f2be41ae496..75bc36a078f7 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane.c
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane.c
@@ -53,12 +53,6 @@ static int vs_primary_plane_atomic_check(struct drm_plane *plane,
return 0;
}
-static void vs_primary_plane_commit(struct vs_dc *dc, unsigned int output)
-{
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_COMMIT);
-}
-
static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
struct drm_atomic_commit *atomic_state)
{
@@ -69,13 +63,8 @@ static void vs_primary_plane_atomic_enable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
- regmap_update_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_DISPLAY_ID_MASK,
- VSDC_FB_CONFIG_EX_DISPLAY_ID(output));
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->plane_enable_ex)
+ dc->funcs->plane_enable_ex(dc, output);
}
static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
@@ -88,10 +77,8 @@ static void vs_primary_plane_atomic_disable(struct drm_plane *plane,
unsigned int output = vcrtc->id;
struct vs_dc *dc = vcrtc->dc;
- regmap_set_bits(dc->regs, VSDC_FB_CONFIG_EX(output),
- VSDC_FB_CONFIG_EX_FB_EN);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->plane_disable_ex)
+ dc->funcs->plane_disable_ex(dc, output);
}
static void vs_primary_plane_atomic_update(struct drm_plane *plane,
@@ -133,18 +120,11 @@ static void vs_primary_plane_atomic_update(struct drm_plane *plane,
regmap_write(dc->regs, VSDC_FB_STRIDE(output),
fb->pitches[0]);
- regmap_write(dc->regs, VSDC_FB_TOP_LEFT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x, state->crtc_y));
- regmap_write(dc->regs, VSDC_FB_BOTTOM_RIGHT(output),
- VSDC_MAKE_PLANE_POS(state->crtc_x + state->crtc_w,
- state->crtc_y + state->crtc_h));
regmap_write(dc->regs, VSDC_FB_SIZE(output),
VSDC_MAKE_PLANE_SIZE(state->crtc_w, state->crtc_h));
- regmap_write(dc->regs, VSDC_FB_BLEND_CONFIG(output),
- VSDC_FB_BLEND_CONFIG_BLEND_DISABLE);
-
- vs_primary_plane_commit(dc, output);
+ if (dc->funcs->plane_update_ex)
+ dc->funcs->plane_update_ex(dc, output, state);
}
static const struct drm_plane_helper_funcs vs_primary_plane_helper_funcs = {
--
2.43.0
^ permalink raw reply related
* [PATCH v3 2/5] drm/verisilicon: add register-level macros for DCU Lite
From: Joey Lu @ 2026-06-08 2:32 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260608023237.305036-1-a0987203069@gmail.com>
Add register-level constants needed by the forthcoming DCUltraLite
hardware ops:
VSDC_DISP_IRQ_VSYNC(n) in vs_crtc_regs.h: bit mask for per-output
VSYNC interrupt bits in DISP_IRQ_STA (0x147C) / DISP_IRQ_EN (0x1480),
which are the IRQ registers used by DCUltraLite in place of the DC8200
TOP_IRQ_ACK / TOP_IRQ_EN registers.
VSDC_FB_CONFIG_ENABLE (bit 0), VSDC_FB_CONFIG_VALID (bit 3) and
VSDC_FB_CONFIG_RESET (bit 4) in vs_primary_plane_regs.h: control bits
in the FB_CONFIG register used by DCUltraLite for framebuffer enable
and per-frame commit handshake.
No behaviour change for existing DC8200 platforms.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h | 3 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
index c7930e817635..d4da22b08cd5 100644
--- a/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_crtc_regs.h
@@ -54,6 +54,7 @@
#define VSDC_DISP_GAMMA_DATA(n) (0x1460 + 0x4 * (n))
#define VSDC_DISP_IRQ_STA 0x147C
+#define VSDC_DISP_IRQ_VSYNC(n) BIT(n)
#define VSDC_DISP_IRQ_EN 0x1480
diff --git a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
index cbb125c46b39..67d4b00f294e 100644
--- a/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
+++ b/drivers/gpu/drm/verisilicon/vs_primary_plane_regs.h
@@ -16,6 +16,9 @@
#define VSDC_FB_STRIDE(n) (0x1408 + 0x4 * (n))
#define VSDC_FB_CONFIG(n) (0x1518 + 0x4 * (n))
+#define VSDC_FB_CONFIG_ENABLE BIT(0)
+#define VSDC_FB_CONFIG_VALID BIT(3)
+#define VSDC_FB_CONFIG_RESET BIT(4)
#define VSDC_FB_CONFIG_CLEAR_EN BIT(8)
#define VSDC_FB_CONFIG_ROT_MASK GENMASK(13, 11)
#define VSDC_FB_CONFIG_ROT(v) ((v) << 11)
--
2.43.0
^ permalink raw reply related
* [PATCH v3 1/5] dt-bindings: display: verisilicon,dc: generalize for single-output variants
From: Joey Lu @ 2026-06-08 2:32 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
In-Reply-To: <20260608023237.305036-1-a0987203069@gmail.com>
The existing schema hard-codes the five-clock/three-reset/dual-port
topology of the DC8200 IP block, preventing reuse for single-output
variants such as the Verisilicon DCUltraLite used in the Nuvoton MA35D1
SoC.
Rework the schema so that variant-specific constraints are expressed via
allOf/if blocks:
- Add nuvoton,ma35d1-dcu to the SoC-specific compatible enum. The
generic verisilicon,dc fallback remains the driver-binding string.
- Relax the top-level clocks/resets definitions to minItems ranges so
the base schema accepts both variants.
- Keep ports in the global required list and keep additionalProperties
tightened to unevaluatedProperties.
- Add an allOf/if block for thead,th1520-dc8200: five-clock (core, axi,
ahb, pix0, pix1), three-reset (core, axi, ahb).
- Add an allOf/if block for nuvoton,ma35d1-dcu: two-clock (core, pix0),
one-reset (core).
- Fix a stray space in the port@0 description.
- Add a DT example for the Nuvoton MA35D1 DCU Lite using ports/port@0.
Signed-off-by: Joey Lu <a0987203069@gmail.com>
---
.../bindings/display/verisilicon,dc.yaml | 103 +++++++++++++++---
1 file changed, 90 insertions(+), 13 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
index 9dc35ab973f2..db0260d874c5 100644
--- a/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
+++ b/Documentation/devicetree/bindings/display/verisilicon,dc.yaml
@@ -17,7 +17,8 @@ properties:
items:
- enum:
- thead,th1520-dc8200
- - const: verisilicon,dc # DC IPs have discoverable ID/revision registers
+ - nuvoton,ma35d1-dcu
+ - const: verisilicon,dc # DC IPs have discoverable ID/revision registers
reg:
maxItems: 1
@@ -26,6 +27,7 @@ properties:
maxItems: 1
clocks:
+ minItems: 2
items:
- description: DC Core clock
- description: DMA AXI bus clock
@@ -34,24 +36,19 @@ properties:
- description: Pixel clock of output 1
clock-names:
- items:
- - const: core
- - const: axi
- - const: ahb
- - const: pix0
- - const: pix1
+ minItems: 2
+ maxItems: 5
resets:
+ minItems: 1
items:
- description: DC Core reset
- description: DMA AXI bus reset
- description: Configuration AHB bus reset
reset-names:
- items:
- - const: core
- - const: axi
- - const: ahb
+ minItems: 1
+ maxItems: 3
ports:
$ref: /schemas/graph.yaml#/properties/ports
@@ -59,7 +56,7 @@ properties:
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
- description: The first output channel , endpoint 0 should be
+ description: The first output channel, endpoint 0 should be
used for DPI format output and endpoint 1 should be used
for DP format output.
@@ -77,7 +74,60 @@ required:
- clock-names
- ports
-additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: thead,th1520-dc8200
+ then:
+ properties:
+ clocks:
+ minItems: 5
+ maxItems: 5
+
+ clock-names:
+ items:
+ - const: core
+ - const: axi
+ - const: ahb
+ - const: pix0
+ - const: pix1
+
+ resets:
+ minItems: 3
+ maxItems: 3
+
+ reset-names:
+ items:
+ - const: core
+ - const: axi
+ - const: ahb
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: nuvoton,ma35d1-dcu
+ then:
+ properties:
+ clocks:
+ minItems: 2
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: core
+ - const: pix0
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ items:
+ - const: core
+
+unevaluatedProperties: false
examples:
- |
@@ -120,3 +170,30 @@ examples:
};
};
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
+ #include <dt-bindings/reset/nuvoton,ma35d1-reset.h>
+
+ display@40260000 {
+ compatible = "nuvoton,ma35d1-dcu", "verisilicon,dc";
+ reg = <0x40260000 0x20000>;
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk DCU_GATE>, <&clk DCUP_DIV>;
+ clock-names = "core", "pix0";
+ resets = <&sys MA35D1_RESET_DISP>;
+ reset-names = "core";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpi_out: endpoint {
+ remote-endpoint = <&panel_in>;
+ };
+ };
+ };
+ };
--
2.43.0
^ permalink raw reply related
* [PATCH v3 0/5] drm/verisilicon: add Nuvoton MA35D1 DCU Lite support
From: Joey Lu @ 2026-06-08 2:32 UTC (permalink / raw)
To: zhengxingda, maarten.lankhorst, mripard, tzimmermann, airlied,
simona, robh, krzk+dt, conor+dt
Cc: ychuang3, schung, yclu4, dri-devel, devicetree, linux-arm-kernel,
linux-kernel, Joey Lu
This series adds support for the Verisilicon DCUltraLite display
controller as integrated in the Nuvoton MA35D1 SoC.
The Verisilicon DC driver and its DT binding were originally written by
Icenowy Zheng <zhengxingda@iscas.ac.cn> for the T-Head TH1520 SoC, which
carries a DC8200 IP block. The present series builds on that foundation
with gratitude to Icenowy for the original work.
The DCUltraLite is a different variant in the DC IP family. While the two
IPs share a broadly similar register layout, a number of differences
prevent the existing driver from working on the MA35D1 without
modification:
- No CONFIG_EX commit path: the DC8200 staging registers
(FB_CONFIG_EX, FB_TOP_LEFT, FB_BOTTOM_RIGHT, FB_BLEND_CONFIG,
PANEL_CONFIG_EX) are absent. The DCUltraLite uses enable (bit 0) and
reset (bit 4) bits in FB_CONFIG for direct framebuffer updates, and
requires a per-frame VALID bit toggle (FB_CONFIG bit 3) to latch
configuration changes.
- No PANEL_START register: panel output begins when
PANEL_CONFIG.RUNNING is set; the DC8200 multi-display sync start
register at 0x1CCC does not exist.
- Different IRQ registers: DISP_IRQ_STA at 0x147C / DISP_IRQ_EN at
0x1480, versus the DC8200's TOP_IRQ_ACK at 0x0010 / TOP_IRQ_EN at
0x0014.
- Simpler clock topology: two clocks ("core" bus gate and "pix0" pixel
divider); no axi or ahb clocks required.
- Single display output: no per-output indexing beyond index 0 is
needed.
- Hardware-discoverable identity: the DCUltraLite exposes chip identity
registers whose model field reads 0x0 (revision 0x5560,
customer_id 0x305), allowing the existing vs_fill_chip_identity()
path to identify the variant purely through register reads.
Patch 1 generalises the verisilicon,dc DT binding to accommodate the
Nuvoton MA35D1 SoC-specific compatible and the variant's two-clock,
one-reset, single-port topology.
Patch 2 adds the register-level macros needed by the DCUltraLite ops.
Patches 3-5 introduce the driver changes in three logical steps: the
vs_dc_funcs hardware ops vtable with DC8200 ops extracted into
vs_dc8200.c; the DCUltraLite ops in vs_dcu_lite.c with the necessary
Kconfig and clock-optionality changes; and finally the DCUltraLite HWDB
entry that gates hardware recognition once all support is in place.
All patches have been tested on Nuvoton MA35D1 hardware.
Changes from v2:
- [dt-bindings] Replaced standalone verisilicon,dc compatible with the
SoC-specific nuvoton,ma35d1-dcu added to the existing enum list,
paired with verisilicon,dc as the generic fallback; this matches the
thead,th1520-dc8200 pattern and was explicitly requested by the
reviewer.
- [dt-bindings] Removed standalone 'port' property; kept 'ports' in the
global required list; MA35D1 example now uses ports/port@0 structure,
following reviewer feedback that a 'port' alias should not be added
since DC8000 (single-port) also supports DP output.
- [dt-bindings] Replaced additionalProperties with unevaluatedProperties
to allow per-variant if/then clauses to add constraints cleanly.
- [dt-bindings] Added separate allOf/if block for nuvoton,ma35d1-dcu
constraining clock-names to [core, pix0] and reset-names to [core];
the if/else structure from v2 is replaced by two independent if blocks.
- [dt-bindings] Removed all description strings from if/then branches per
reviewer request; descriptions remain only in the top-level properties.
- [hwdb] Removed VSDC_MODEL_DC8200 and VSDC_MODEL_DCU_LITE macros; HWDB
entries use literal values (0x8200, 0x0) with inline comments.
- [hwdb] Added enum vs_dc_generation (VSDC_GEN_DC8000 / VSDC_GEN_DC8200)
and a generation field to vs_chip_identity; funcs dispatch now uses
generation instead of the model register value, per reviewer suggestion
(DC8000 has model 0x8000 yet behaves like DCUltraLite with model 0x0).
- [hwdb] Moved the DCUltraLite HWDB entry to the final patch in the
series per reviewer request, making it a gate that is opened only
after all supporting code is in place.
- [ops] Split v2 patch 2 into two patches: register macros first, then
the per-variant ops table, per reviewer suggestion.
- [ops] Extracted DC8200-specific ops into vs_dc8200.c; DCUltraLite ops
are in vs_dcu_lite.c; dispatch in vs_dc_probe uses generation field.
Joey Lu (5):
dt-bindings: display: verisilicon,dc: generalize for single-output
variants
drm/verisilicon: add register-level macros for DCU Lite
drm/verisilicon: introduce per-variant hardware ops table
drm/verisilicon: add Nuvoton MA35D1 DCU Lite display controller
support
drm/verisilicon: add DCUltraLite chip identity to HWDB
.../bindings/display/verisilicon,dc.yaml | 103 ++++++++++++++---
drivers/gpu/drm/verisilicon/Kconfig | 2 +-
drivers/gpu/drm/verisilicon/Makefile | 2 +-
drivers/gpu/drm/verisilicon/vs_bridge.c | 20 +---
drivers/gpu/drm/verisilicon/vs_crtc.c | 38 ++++++-
drivers/gpu/drm/verisilicon/vs_crtc_regs.h | 1 +
drivers/gpu/drm/verisilicon/vs_dc.c | 13 ++-
drivers/gpu/drm/verisilicon/vs_dc.h | 33 ++++++
drivers/gpu/drm/verisilicon/vs_dc8200.c | 107 ++++++++++++++++++
drivers/gpu/drm/verisilicon/vs_dcu_lite.c | 78 +++++++++++++
drivers/gpu/drm/verisilicon/vs_hwdb.c | 14 +++
drivers/gpu/drm/verisilicon/vs_hwdb.h | 6 +
.../gpu/drm/verisilicon/vs_primary_plane.c | 32 +-----
.../drm/verisilicon/vs_primary_plane_regs.h | 3 +
14 files changed, 385 insertions(+), 67 deletions(-)
create mode 100644 drivers/gpu/drm/verisilicon/vs_dc8200.c
create mode 100644 drivers/gpu/drm/verisilicon/vs_dcu_lite.c
--
2.43.0
^ permalink raw reply
* [PATCH 1/1] MAINTAINERS: remove my name from CIX Maintainer
From: Peter Chen @ 2026-06-08 2:17 UTC (permalink / raw)
To: arnd
Cc: fugang.duan, cix-kernel-upstream, linux-arm-kernel, peter.chen,
Peter Chen
Since I am going to leave CIX, and could not maintain it any more.
Signed-off-by: Peter Chen <peter.chen@cixtech.com>
---
MAINTAINERS | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 2fb1c75afd16..ca7d0f090906 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2692,12 +2692,11 @@ F: arch/arm/mach-ep93xx/
F: drivers/iio/adc/ep93xx_adc.c
ARM/CIX SOC SUPPORT
-M: Peter Chen <peter.chen@cixtech.com>
M: Fugang Duan <fugang.duan@cixtech.com>
R: CIX Linux Kernel Upstream Group <cix-kernel-upstream@cixtech.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/cix.git
+T: git https://github.com/cixtech/linux-mainline.git
F: Documentation/devicetree/bindings/arm/cix.yaml
F: Documentation/devicetree/bindings/mailbox/cix,sky1-mbox.yaml
F: arch/arm64/boot/dts/cix/
--
2.50.1
^ permalink raw reply related
* [PATCH v1] mfd: mt6397-irq: Fix PM notifier use-after-free
From: Yuho Choi @ 2026-06-08 2:10 UTC (permalink / raw)
To: Lee Jones, Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-kernel, linux-arm-kernel, linux-mediatek, Yuho Choi
mt6397_irq_init() registers chip->pm_nb with the global PM notifier
chain. The notifier callback uses container_of() to recover struct
mt6397_chip and then dereferences chip fields.
The chip structure is allocated with devm_kzalloc() in mt6397_probe().
If probe fails after mt6397_irq_init() succeeds, for example when
devm_mfd_add_devices() fails, devres can release the chip while the PM
notifier remains registered. The same lifetime mismatch exists when the
driver is unbound.
Check the register_pm_notifier() return value and add a devm cleanup
action to unregister the notifier before the devm-managed chip is freed.
If adding the cleanup action fails, devm_add_action_or_reset()
unregisters the notifier immediately; then remove the IRQ domain in the
remaining error path.
Fixes: 4e2e7cfec13a ("mfd: mt6397: Modify suspend/resume behavior")
Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
---
drivers/mfd/mt6397-irq.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
index 5d2e5459f744..8947f7e732fa 100644
--- a/drivers/mfd/mt6397-irq.c
+++ b/drivers/mfd/mt6397-irq.c
@@ -169,6 +169,13 @@ static int mt6397_irq_pm_notifier(struct notifier_block *notifier,
return NOTIFY_DONE;
}
+static void mt6397_irq_pm_notifier_unregister(void *data)
+{
+ struct mt6397_chip *chip = data;
+
+ unregister_pm_notifier(&chip->pm_nb);
+}
+
int mt6397_irq_init(struct mt6397_chip *chip)
{
int ret;
@@ -233,6 +240,17 @@ int mt6397_irq_init(struct mt6397_chip *chip)
return ret;
}
- register_pm_notifier(&chip->pm_nb);
- return 0;
+ ret = register_pm_notifier(&chip->pm_nb);
+ if (ret) {
+ dev_err(chip->dev, "failed to register PM notifier: %d\n", ret);
+ irq_domain_remove(chip->irq_domain);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(chip->dev,
+ mt6397_irq_pm_notifier_unregister, chip);
+ if (ret)
+ irq_domain_remove(chip->irq_domain);
+
+ return ret;
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v6 3/4] media: uapi: mediatek: Add MT8188 AIE control definitions
From: CK Hu (胡俊光) @ 2026-06-08 2:06 UTC (permalink / raw)
To: robh@kernel.org, mchehab@kernel.org, AngeloGioacchino Del Regno,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Sarang Chaudhari,
linux-mediatek@lists.infradead.org
Cc: Zhaoyuan Chen (陈兆远),
Teddy Chen (陳乾元),
Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260605082956.2590511-1-sarang.chaudhari@mediatek.com>
On Fri, 2026-06-05 at 16:29 +0800, Sarang Chaudhari wrote:
> Add AIE (AI Engine) UAPI control definitions and register the
> V4L2_META_FMT_MTFD_RESULT metadata format for the MediaTek face
> detection hardware accelerator.
>
> This patch adds:
> - include/uapi/linux/mtk_aie_v4l2_controls.h: Custom V4L2 control IDs
> for AIE initialization and per-frame parameters.
> - V4L2_META_FMT_MTFD_RESULT format in videodev2.h for face detection
> result metadata output.
> - Format description in v4l2-ioctl.c.
>
> Signed-off-by: Sarang Chaudhari <sarang.chaudhari@mediatek.com>
> ---
> Changes in v6:
> - Simplify UAPI header to contain only control ID definitions. Full
> structures kept in kernel-internal header for now, pending UAPI
> structure redesign per CK Hu's feedback.
> - Drop V4L2_CTRL_TYPE_AIE_INIT and V4L2_CTRL_TYPE_AIE_PARAM from
> v4l2_ctrl_type enum (use V4L2_CTRL_TYPE_U32 compound control instead).
> - Address CK Hu's review feedback: remove freq_level, improve
> feature_threshold docs, clarify pyramid multi-scale detection, clarify
> FLD mode uses FD results via Binary Tree Traversal.
>
> Changes in v5:
> - Add an introduction for feature_threshold.
> - Rename v4l2_aie_roi to aie_roi_coordinate.
> - Rename v4l2_aie_padding to aie_padding_size.
> - Explain en_padding and the three modes of fd_mode.
> - Move structures from mtk_aie.h to the uapi directory.
>
> Changes in v4:
> - Document the detail of V4L2_META_FMT_MTFD_RESULT.
> - Add the introduction of related variables.
>
> Changes in v3: None
>
> Changes in v2:
> - Fix coding style.
>
> drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
> include/uapi/linux/mtk_aie_v4l2_controls.h | 23 ++++++++++++++++++++++
> include/uapi/linux/videodev2.h | 1 +
> 3 files changed, 25 insertions(+)
> create mode 100644 include/uapi/linux/mtk_aie_v4l2_controls.h
>
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index e50e517..8754098 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -11,6 +11,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
> case V4L2_META_FMT_GENERIC_CSI2_16: descr = "8-bit Generic Meta, 16b CSI-2"; break;
> case V4L2_META_FMT_GENERIC_CSI2_20: descr = "8-bit Generic Meta, 20b CSI-2"; break;
> case V4L2_META_FMT_GENERIC_CSI2_24: descr = "8-bit Generic Meta, 24b CSI-2"; break;
> + case V4L2_META_FMT_MTFD_RESULT: descr = "Mediatek Face Detect Result"; break;
>
> default:
> /* Compressed formats */
> diff --git a/include/uapi/linux/mtk_aie_v4l2_controls.h b/include/uapi/linux/mtk_aie_v4l2_controls.h
> new file mode 100644
> index 0000000..a8b2927
> --- /dev/null
> +++ b/include/uapi/linux/mtk_aie_v4l2_controls.h
> @@ -0,0 +1,23 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * MediaTek AI Engine (AIE) V4L2 control definitions
> + *
> + * Copyright (c) 2020 MediaTek Inc.
> + * Author: Fish Wu <fish.wu@mediatek.com>
> + */
> +
> +#ifndef __UAPI_MTK_AIE_V4L2_CONTROLS_H__
> +#define __UAPI_MTK_AIE_V4L2_CONTROLS_H__
> +
> +#include <linux/videodev2.h>
> +
> +/*
> + * The base for the MediaTek AIE driver controls.
> + * We reserve 16 controls for this driver.
> + */
> +#define V4L2_CID_USER_MTK_FD_BASE (V4L2_CID_USER_BASE + 0x1fd0)
> +
> +#define V4L2_CID_MTK_AIE_INIT (V4L2_CID_USER_MTK_FD_BASE + 1)
> +#define V4L2_CID_MTK_AIE_PARAM (V4L2_CID_USER_MTK_FD_BASE + 2)
Add definition of parameter of V4L2_CID_MTK_AIE_INIT and V4L2_CID_MTK_AIE_PARAM,
so user space would know how to control this driver.
If this patch is not ready to apply. Add 'RFC' prefix in title.
> +
> +#endif /* __UAPI_MTK_AIE_V4L2_CONTROLS_H__ */
> diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
> index 7668201..6d6866d 100644
> --- a/include/uapi/linux/videodev2.h
> +++ b/include/uapi/linux/videodev2.h
> @@ -10,6 +10,7 @@ struct v4l2_pix_format {
> #define V4L2_META_FMT_GENERIC_CSI2_16 v4l2_fourcc('M', 'C', '1', 'G') /* 16-bit CSI-2 packed 8-bit metadata */
> #define V4L2_META_FMT_GENERIC_CSI2_20 v4l2_fourcc('M', 'C', '1', 'K') /* 20-bit CSI-2 packed 8-bit metadata */
> #define V4L2_META_FMT_GENERIC_CSI2_24 v4l2_fourcc('M', 'C', '1', 'O') /* 24-bit CSI-2 packed 8-bit metadata */
> +#define V4L2_META_FMT_MTFD_RESULT v4l2_fourcc('M', 'T', 'f', 'd') /* Mediatek face detection result */
Add document to describe the detail of V4L2_META_FMT_MTFD_RESULT. [1] is the example document for V4L2_META_FMT_RPI_FE_CFG.
There are many document in Documentation/userspace-api/media/v4l/ for your reference.
[1] https://patchwork.kernel.org/project/linux-media/patch/20241003-rp1-cfe-v6-1-d6762edd98a8@ideasonboard.com/
Regards,
CK
> #endif
>
> /* priv field value to indicates that subsequent fields are valid. */
^ permalink raw reply
* Re: [RFC PATCH v3 6/9] iommu/rockchip: Clear AUTO_GATING bit 1 on the RK356x v1 IOMMU
From: Chaoyi Chen @ 2026-06-08 1:45 UTC (permalink / raw)
To: Midgy Balon
Cc: Simon Xue, tomeu, ogabbay, heiko, robh, krzk+dt, conor+dt, joro,
will, robin.murphy, dri-devel, linux-rockchip, devicetree,
linux-arm-kernel, iommu, linux-kernel
In-Reply-To: <CA+GS1Y16++cztPxdUGLrPA73ENm4vJGFrjm-jP8r=8OQqcMJGA@mail.gmail.com>
Hi Midgy,
On 6/8/2026 5:05 AM, Midgy Balon wrote:
> Hi Chaoyi,
>
>> As I said, it is v2. Could you please try using the code below instead and
>> see if it works?
>> [ auto_gate = read(RK_MMU_AUTO_GATING); auto_gate |= BIT(31); write(...) ]
>
> Thanks -- that's clearly the right shape (read-modify-write, before paging is
> enabled, keeping the reset value instead of my clobbering 0x2).
>
> I rebuilt v7.1-rc6 (with the rocket RK3568 series + your per-device-ops work)
> using your bit-31 version and tested it on a ROCK 3B: the NPU IOMMU comes up and
> services the NPU's DMA cleanly -- the NPU probes, attaches its domain, and runs
> repeated conv submissions with no DMA_READ_ERROR and no page-walk stall. No
> regression from the write.
>
> To be precise about what I can and can't show: I tested both ways on v7.1-rc6 --
> with your bit-31 write, and on the reset value (0x3) -- and the NPU
> IOMMU services
> the NPU's reads with zero faults in both cases (no DMA_READ_ERROR, no page-walk
> stall). So I don't have a failing baseline here that bit-31 visibly
> fixes. Is the
> AUTO_GATING write needed on current mainline, or only under conditions I'm not
> reproducing (a particular traffic pattern / silicon rev)? I'll keep the patch in
> your form unless you'd prefer to drop it.
>
> One question so I document it correctly: what does bit 31 of RK_MMU_AUTO_GATING
> control on the v2 block -- is it a master "disable internal auto clock-gating"
> for the page-table walker (i.e. so a TLB-miss walk's AXI master keeps its clock
> to completion)? The RK3568 TRM I have doesn't cover the IOMMU registers, so a
> one-line description would let me write an accurate comment.
>
Glad to hear this works. Please refer to the commit below.
[0]: https://github.com/rockchip-linux/kernel/commit/7f8158fb41b5cc8e738aaeebc3637c50ebd74cae
[1]: https://github.com/rockchip-linux/kernel/commit/6a355e5f9a2069a2309e240791bc3aad63b7324e
--
Best,
Chaoyi
^ permalink raw reply
* Re: [RFC PATCH v3 0/9] accel: rocket: Add RK3568 NPU support
From: Chaoyi Chen @ 2026-06-08 1:40 UTC (permalink / raw)
To: Midgy Balon
Cc: tomeu, ogabbay, heiko, robh, krzk+dt, conor+dt, joro, will,
robin.murphy, dri-devel, linux-rockchip, devicetree,
linux-arm-kernel, iommu, linux-kernel, Simon Xue, Finley Xiao
In-Reply-To: <CA+GS1Y1s78PwN63X2YJoS8VEGp7CpTERo_K65yKs00U4VRAw4Q@mail.gmail.com>
Hi Midgy,
On 6/8/2026 5:03 AM, Midgy Balon wrote:
> Hi Chaoyi,
>
> Thanks a lot for looking at this -- input from Rockchip is exactly what this
> series needs.
>
>> Hmmm. If I understand correctly, the NPU IOMMU should be v2 rather than v1,
>> implying it should support 40-bit PAs. Nevertheless, please note that the
>> upper limit for DTE is 32 bits.
>
> Understood, and that 32-bit-DTE note is the crux of the trouble I had, so let
> me lay out what I see and ask how you'd prefer to solve it.
>
> The mainline node is already v2 (rockchip,rk3568-iommu in rk356x-base.dtsi).
> The problem on this 8 GiB board: with the v2 ops the page-table allocations
> (gfp_flags == 0) can land above 4 GiB, so the DTE ends up > 32 bits and the
> NPU's first translation faults with DMA_READ_ERROR. To work around that I had
> switched the NPU MMU to the v1 compatible (rockchip,iommu), whose ops set
> GFP_DMA32 and keep the DTE sub-4 GiB. That works in isolation, but because the
> driver keeps a single global rk_ops, a v1 NPU MMU then trips
> WARN_ON(rk_ops != ops) against the SoC's v2 instances (VOP/VDEC), which is why
> I based the series on Simon's per-device-ops work.
>
> So my question: with per-device ops in place, what's the intended way to keep
> the NPU MMU on v2 *and* cap its DTE at 32 bits on boards with >4 GiB of RAM?
> A v2 ops variant carrying GFP_DMA32 for this device, or is there a register/
> config bit that constrains the DTE address? I'd rather follow the Rockchip
> intent here than carry the v1 workaround. (Simon, cc'd -- this is right next to
> your per-device-ops series.)
>
If Simon's method works, please use it :)
>> Can these operations not be completed via the pmdomain driver?
>> If some operations are controlled by TF-A, are you using open source TF-A?
>
> Most of it is in pmdomain already. Power-on and NoC de-idle are done by the
> RK3568 NPU power domain (genpd) at power-on -- the driver no longer pokes the
> PMU directly. Two things remain outside it:
>
> - vdd_npu: I mark it regulator-always-on in DT rather than wiring it as the
> domain's domain-supply, because as a domain-supply it created a device-link
> to the I2C PMIC (rk809) and genpd's power-off QoS-save path then hung
> reading the NPU QoS registers behind the (gated) NoC. If there's a clean way
> to let genpd own vdd_npu without that I2C ordering deadlock I'd much prefer
> that -- pointers welcome.
>
Please refer to the patch below regarding the RK3588 NPU pmdomain.
In short, you need to set a "need_regulator" for the RK3568 NPU pmdomain.
https://lore.kernel.org/all/20251216055247.13150-1-rmxpzlb@gmail.com/
> - the NPU compute clock (PVTPLL): set from the driver via SCMI, and only
> needed for actual compute, not for bring-up.
>
> One more pmdomain observation from testing, possibly relevant to how the NPU
> domain should be modelled: the domain's power-off/on cycle doesn't reliably
> re-de-idle the NoC. If the NPU is probed after genpd has already powered the
> (unused) domain off, the power-on de-idle fails ("failed to set idle on domain
> 'npu'") and the NPU IOMMU then takes an external abort on its first MMIO access.
> Probing the NPU before the unused-domain power-off, or marking the domain
> always-on, both avoid it. Is the NoC de-idle expected to work on a genpd
> re-power here, or should this domain effectively stay on?
>
Not quite sure what's going on with PVTPLL and NOC.
Maybe @Finley knows about this?
> On TF-A: yes -- bl31 is built from upstream arm-trusted-firmware
> (github.com/ARM-software/arm-trusted-firmware, RK3568 platform), providing PSCI
> and the SCMI clock service. The only closed blob in the boot chain is Rockchip's
> DDR init (rkbin), which is the standard situation for mainline RK356x.
--
Best,
Chaoyi
^ permalink raw reply
* Re: [PATCH v6 4/4] media: platform: mediatek: Add MT8188 AIE driver
From: CK Hu (胡俊光) @ 2026-06-08 1:36 UTC (permalink / raw)
To: robh@kernel.org, mchehab@kernel.org, AngeloGioacchino Del Regno,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Sarang Chaudhari,
linux-mediatek@lists.infradead.org
Cc: Zhaoyuan Chen (陈兆远),
Teddy Chen (陳乾元),
Project_Global_Chrome_Upstream_Group
In-Reply-To: <20260605083039.2591285-1-sarang.chaudhari@mediatek.com>
On Fri, 2026-06-05 at 16:30 +0800, Sarang Chaudhari wrote:
> Add the MediaTek AI Engine (AIE) V4L2 memory-to-memory driver for the
> MT8188 SoC. The AIE hardware accelerator provides face detection, facial
> landmark detection (FLD), and face attribute analysis (age, gender, race)
> capabilities.
>
> The driver implements:
> - V4L2 mem2mem device with multi-planar video and metadata capture
> - Three operation modes: face detection (FD), attribute analysis, and
> facial landmark detection (FLD) using Binary Tree Traversal
> - Pyramid-based multi-scale face detection (640x480 base, 2x downscale
> per level)
> - Hardware configuration via DMA descriptor tables
> - Clock and power management integration
This patch looks similar to v3[1], so I think you should look my comment in v3, v4[2], v5[3].
Or more simple way, base on v5, fix with my v5 comment, and generate a real v6.
[1] https://patchwork.kernel.org/project/linux-mediatek/patch/20241225090113.17027-4-bo.kong@mediatek.com/
[2] https://patchwork.kernel.org/project/linux-mediatek/patch/20250220070114.15015-5-bo.kong@mediatek.com/
[3] https://patchwork.kernel.org/project/linux-mediatek/patch/20250403074005.21472-5-bo.kong@mediatek.com/
Regards,
CK
>
> Signed-off-by: Sarang Chaudhari <sarang.chaudhari@mediatek.com>
> ---
>
^ permalink raw reply
* Re: [PATCH] Documentation: ABI: sysfs-class-reboot-mode-reboot_modes: fix doc warnings
From: Randy Dunlap @ 2026-06-08 1:04 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: linux-pm, linux-arm-kernel, Sebastian Reichel, Shivendra Pratap,
linux-doc, linux-kernel
In-Reply-To: <d7cd7bb3-520f-4e80-8242-583f689f60db@infradead.org>
On 5/24/26 3:48 PM, Randy Dunlap wrote:
> Sebastian,
>
> On 4/27/26 2:11 AM, Bartosz Golaszewski wrote:
>> On Mon, 27 Apr 2026 01:27:05 +0200, Randy Dunlap <rdunlap@infradead.org> said:
>>> Repair the docs build warnings in this file by unindenting the description,
>>> adding blank lines, and using `` to quote *arg.
>>>
>>> WARNING: Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:36: abi_sys_class_reboot_mode_driver_reboot_modes doesn't have a description
>>> Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:1: ERROR: Unexpected indentation. [docutils]
>>> Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:1: ERROR: Unexpected indentation. [docutils]
>>> Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:1: WARNING: Inline emphasis start-string without end-string. [docutils]
>>> Documentation/ABI/testing/sysfs-class-reboot-mode-reboot_modes:1: ERROR: Unexpected indentation. [docutils]
>>>
>>> Fixes: d3da03025e6d ("Documentation: ABI: Add sysfs-class-reboot-mode-reboot_modes")
>>> Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
>>> ---
>>
>> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
>
> This build warning is now in mainline.
> Will you be merging this patch soon?
ping.
> thanks.
--
~Randy
^ permalink raw reply
* [PATCH v2] arm64: dts: nuvoton: ma35d1: add CAN nodes
From: Zi-Yu Chen @ 2026-06-08 1:00 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt
Cc: ychuang3, schung, linux-arm-kernel, devicetree, linux-kernel,
Zi-Yu Chen
Add controller nodes for the four Bosch M_CAN blocks found on the
Nuvoton MA35D1 SoC.
Additionally, configure pinctrl and enable CAN1 and CAN3 on the
MA35D1 SOM board. Also, update the APLL frequency to 200MHz to ensure
the CAN controllers receive the required input clock for 50MHz operation.
Signed-off-by: Zi-Yu Chen <zychennvt@gmail.com>
---
v2:
- Move assigned-clocks and assigned-clock-rates configurations of
CAN_DIV from SoC-level ma35d1.dtsi to board-level ma35d1-som-256m.dts
- Update APLL frequency to 200MHz to ensure the CAN controllers
receive the required 50MHz input clock.
.../boot/dts/nuvoton/ma35d1-som-256m.dts | 32 +++++++++++-
arch/arm64/boot/dts/nuvoton/ma35d1.dtsi | 52 +++++++++++++++++++
2 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts
index f6f20a17e501..fb23b0573bdc 100644
--- a/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts
+++ b/arch/arm64/boot/dts/nuvoton/ma35d1-som-256m.dts
@@ -37,6 +37,22 @@ clk_hxt: clock-hxt {
};
};
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can1>;
+ assigned-clocks = <&clk CAN1_DIV>;
+ assigned-clock-rates = <50000000>;
+ status = "okay";
+};
+
+&can3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can3>;
+ assigned-clocks = <&clk CAN3_DIV>;
+ assigned-clock-rates = <50000000>;
+ status = "okay";
+};
+
&clk {
assigned-clocks = <&clk CAPLL>,
<&clk DDRPLL>,
@@ -45,7 +61,7 @@ &clk {
<&clk VPLL>;
assigned-clock-rates = <800000000>,
<266000000>,
- <180000000>,
+ <200000000>,
<500000000>,
<102000000>;
nuvoton,pll-mode = "integer",
@@ -56,6 +72,20 @@ &clk {
};
&pinctrl {
+ can-grp {
+ pinctrl_can1: can1-pins {
+ nuvoton,pins = <11 14 4>,
+ <11 15 4>;
+ bias-disable;
+ };
+
+ pinctrl_can3: can3-pins {
+ nuvoton,pins = <11 10 3>,
+ <11 11 3>;
+ bias-disable;
+ };
+ };
+
uart-grp {
pinctrl_uart0: uart0-pins {
nuvoton,pins = <4 14 1>,
diff --git a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi
index e51b98f5bdce..494724a25f3b 100644
--- a/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi
+++ b/arch/arm64/boot/dts/nuvoton/ma35d1.dtsi
@@ -244,6 +244,58 @@ gpion: gpio@340 {
};
};
+ can0: can@403c0000 {
+ compatible = "bosch,m_can";
+ reg = <0x0 0x403c0000 0x0 0x200>, <0x0 0x403c0200 0x0 0x2000>;
+ reg-names = "m_can", "message_ram";
+ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ clocks = <&clk HCLK3>, <&clk CAN0_GATE>;
+ clock-names = "hclk", "cclk";
+ bosch,mram-cfg = <0x0 4 4 32 32 32 8 8>;
+ status = "disabled";
+ };
+
+ can1: can@403d0000 {
+ compatible = "bosch,m_can";
+ reg = <0x0 0x403d0000 0x0 0x200>, <0x0 0x403d0200 0x0 0x2000>;
+ reg-names = "m_can", "message_ram";
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ clocks = <&clk HCLK3>, <&clk CAN1_GATE>;
+ clock-names = "hclk", "cclk";
+ bosch,mram-cfg = <0x0 4 4 32 32 32 8 8>;
+ status = "disabled";
+ };
+
+ can2: can@403e0000 {
+ compatible = "bosch,m_can";
+ reg = <0x0 0x403e0000 0x0 0x200>, <0x0 0x403e0200 0x0 0x2000>;
+ reg-names = "m_can", "message_ram";
+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ clocks = <&clk HCLK3>, <&clk CAN2_GATE>;
+ clock-names = "hclk", "cclk";
+ bosch,mram-cfg = <0x0 4 4 32 32 32 8 8>;
+ status = "disabled";
+ };
+
+ can3: can@403f0000 {
+ compatible = "bosch,m_can";
+ reg = <0x0 0x403f0000 0x0 0x200>, <0x0 0x403f0200 0x0 0x2000>;
+ reg-names = "m_can", "message_ram";
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1";
+ clocks = <&clk HCLK3>, <&clk CAN3_GATE>;
+ clock-names = "hclk", "cclk";
+ bosch,mram-cfg = <0x0 4 4 32 32 32 8 8>;
+ status = "disabled";
+ };
+
uart0: serial@40700000 {
compatible = "nuvoton,ma35d1-uart";
reg = <0x0 0x40700000 0x0 0x100>;
--
2.34.1
^ permalink raw reply related
* [PATCH 1/3] gpio: rockchip: fix generic IRQ chip leak on remove
From: Marco Scardovi @ 2026-06-07 23:05 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski
Cc: Heiko Stuebner, Jianqun Xu, linux-gpio, linux-arm-kernel,
linux-rockchip, linux-kernel
In-Reply-To: <20260607230504.35392-1-scardracs@disroot.org>
The driver allocates domain generic chips using
irq_alloc_domain_generic_chips() during probe. However, on driver
remove/teardown, the generic chips are not automatically freed when the
IRQ domain is removed because the domain flags do not include
IRQ_DOMAIN_FLAG_DESTROY_GC.
This causes both the domain generic chips structure and the associated
generic chips to be leaked. Additionally, the generic chips remain on
the global gc_list and may later be visited by generic IRQ chip suspend,
resume, or shutdown callbacks after the GPIO bank has been removed,
potentially resulting in a use-after-free and kernel crash.
Fix the resource leak by explicitly calling
irq_domain_remove_generic_chips() before removing the IRQ domain in
rockchip_gpio_remove().
Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Marco Scardovi <scardracs@disroot.org>
---
drivers/gpio/gpio-rockchip.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
index bc97d5d5d329..9478a58f1caa 100644
--- a/drivers/gpio/gpio-rockchip.c
+++ b/drivers/gpio/gpio-rockchip.c
@@ -802,8 +802,10 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
irq_set_chained_handler_and_data(bank->irq, NULL, NULL);
- if (bank->domain)
+ if (bank->domain) {
+ irq_domain_remove_generic_chips(bank->domain);
irq_domain_remove(bank->domain);
+ }
gpiochip_remove(&bank->gpio_chip);
}
--
2.54.0
^ permalink raw reply related
* [PATCH 2/3] gpio: rockchip: use devm_platform_ioremap_resource() to map registers
From: Marco Scardovi @ 2026-06-07 23:05 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski
Cc: Heiko Stuebner, Jianqun Xu, linux-gpio, linux-arm-kernel,
linux-rockchip, linux-kernel
In-Reply-To: <20260607230504.35392-1-scardracs@disroot.org>
Currently, the driver retrieves the memory resource with
of_address_to_resource() and maps it with devm_ioremap_resource().
Since the bank device is a platform_device, simplify and modernize the
code by using devm_platform_ioremap_resource(). This also removes the
need for the local struct resource variable.
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Marco Scardovi <scardracs@disroot.org>
---
drivers/gpio/gpio-rockchip.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
index 9478a58f1caa..8647d006d103 100644
--- a/drivers/gpio/gpio-rockchip.c
+++ b/drivers/gpio/gpio-rockchip.c
@@ -647,15 +647,10 @@ static void rockchip_clk_put(void *data)
static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
{
- struct resource res;
+ struct platform_device *pdev = to_platform_device(bank->dev);
int id = 0, ret;
- if (of_address_to_resource(bank->of_node, 0, &res)) {
- dev_err(bank->dev, "cannot find IO resource for bank\n");
- return -ENOENT;
- }
-
- bank->reg_base = devm_ioremap_resource(bank->dev, &res);
+ bank->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bank->reg_base))
return PTR_ERR(bank->reg_base);
--
2.54.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox