Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 5/6] pinctrl: tegra: Add Tegra264 pinmux driver
From: pshete @ 2026-04-20 10:06 UTC (permalink / raw)
  To: linusw, thierry.reding
  Cc: pshete, jonathanh, robh, krzk+dt, conor+dt, webgeek1234, rosenp,
	linux-tegra, linux-gpio, devicetree, linux-kernel
In-Reply-To: <20260420100601.343707-1-pshete@nvidia.com>

From: Prathamesh Shete <pshete@nvidia.com>

Add support for the three pin controllers
(MAIN, UPHY and AON) found on Tegra264.

Signed-off-by: Prathamesh Shete <pshete@nvidia.com>
---
Changes in v2:
  - Add 'default m if ARCH_TEGRA_264_SOC' to the PINCTRL_TEGRA264 Kconfig.
---
 drivers/pinctrl/tegra/Kconfig            |   10 +
 drivers/pinctrl/tegra/Makefile           |    1 +
 drivers/pinctrl/tegra/pinctrl-tegra264.c | 2216 ++++++++++++++++++++++
 3 files changed, 2227 insertions(+)
 create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra264.c

diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig
index cb3a7ab02e72..54263b4554c0 100644
--- a/drivers/pinctrl/tegra/Kconfig
+++ b/drivers/pinctrl/tegra/Kconfig
@@ -46,6 +46,16 @@ config PINCTRL_TEGRA238
 	  and configuration for the MAIN and AON pin controllers found
 	  on Tegra238.
 
+config PINCTRL_TEGRA264
+	tristate "NVIDIA Tegra264 pinctrl driver"
+	default m if ARCH_TEGRA_264_SOC
+	select PINCTRL_TEGRA
+	help
+	  Say Y or M here to enable support for the pinctrl driver for
+	  NVIDIA Tegra264 SoC. This driver controls the pin multiplexing
+	  and configuration for the MAIN, AON and UPHY pin controllers found
+	  on Tegra264.
+
 config PINCTRL_TEGRA_XUSB
 	def_bool y if ARCH_TEGRA
 	select GENERIC_PHY
diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile
index ce700bbcbf6e..71ade768bf9c 100644
--- a/drivers/pinctrl/tegra/Makefile
+++ b/drivers/pinctrl/tegra/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_PINCTRL_TEGRA186)		+= pinctrl-tegra186.o
 obj-$(CONFIG_PINCTRL_TEGRA194)		+= pinctrl-tegra194.o
 obj-$(CONFIG_PINCTRL_TEGRA234)		+= pinctrl-tegra234.o
 obj-$(CONFIG_PINCTRL_TEGRA238)		+= pinctrl-tegra238.o
+obj-$(CONFIG_PINCTRL_TEGRA264)		+= pinctrl-tegra264.o
 obj-$(CONFIG_PINCTRL_TEGRA_XUSB)	+= pinctrl-tegra-xusb.o
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra264.c b/drivers/pinctrl/tegra/pinctrl-tegra264.c
new file mode 100644
index 000000000000..5a0c91aaba3a
--- /dev/null
+++ b/drivers/pinctrl/tegra/pinctrl-tegra264.c
@@ -0,0 +1,2216 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Pinctrl data for the NVIDIA Tegra264 pinmux
+ *
+ * Copyright (c) 2024-2026, NVIDIA CORPORATION.  All rights reserved.
+ */
+
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/* Define unique ID for each pins */
+enum {
+	TEGRA_PIN_PEX_L4_CLKREQ_N_PD0,
+	TEGRA_PIN_PEX_L4_RST_N_PD1,
+	TEGRA_PIN_PEX_L5_CLKREQ_N_PD2,
+	TEGRA_PIN_PEX_L5_RST_N_PD3,
+	TEGRA_PIN_ETH0_MDIO_PD4,
+	TEGRA_PIN_ETH0_MDC_PD5,
+	TEGRA_PIN_ETH3_MDIO_PD6,
+	TEGRA_PIN_ETH3_MDC_PD7,
+	TEGRA_PIN_ETH1_MDIO_PE0,
+	TEGRA_PIN_ETH1_MDC_PE1,
+	TEGRA_PIN_ETH2_MDIO_PE2,
+	TEGRA_PIN_ETH2_MDC_PE3,
+	TEGRA_PIN_PEX_L1_CLKREQ_N_PB0,
+	TEGRA_PIN_PEX_L1_RST_N_PB1,
+	TEGRA_PIN_PEX_L2_CLKREQ_N_PB2,
+	TEGRA_PIN_PEX_L2_RST_N_PB3,
+	TEGRA_PIN_PEX_L3_CLKREQ_N_PB4,
+	TEGRA_PIN_PEX_L3_RST_N_PB5,
+	TEGRA_PIN_SOC_GPIO113_PB6,
+	TEGRA_PIN_SOC_GPIO114_PB7,
+	TEGRA_PIN_SGMII0_SMA_MDIO_PC0,
+	TEGRA_PIN_SGMII0_SMA_MDC_PC1,
+	TEGRA_PIN_PEX_WAKE_N_PC2,
+	TEGRA_PIN_PWM1_PA0,
+	TEGRA_PIN_PWM6_PA1,
+	TEGRA_PIN_PWM7_PA2,
+	TEGRA_PIN_PWM8_PA3,
+	TEGRA_PIN_UFS0_REF_CLK_PA4,
+	TEGRA_PIN_UFS0_RST_N_PA5,
+};
+
+enum {
+	TEGRA_PIN_SOC_GPIO250_PF0,
+	TEGRA_PIN_SOC_GPIO251_PF1,
+	TEGRA_PIN_SOC_GPIO252_PF2,
+	TEGRA_PIN_DP_AUX_CH0_HPD_PF3,
+	TEGRA_PIN_DP_AUX_CH1_HPD_PF4,
+	TEGRA_PIN_DP_AUX_CH2_HPD_PF5,
+	TEGRA_PIN_DP_AUX_CH3_HPD_PF6,
+	TEGRA_PIN_PWM2_PF7,
+	TEGRA_PIN_PWM3_PG0,
+	TEGRA_PIN_GEN7_I2C_SCL_PG1,
+	TEGRA_PIN_GEN7_I2C_SDA_PG2,
+	TEGRA_PIN_GEN9_I2C_SCL_PG3,
+	TEGRA_PIN_GEN9_I2C_SDA_PG4,
+	TEGRA_PIN_SDMMC1_CLK_PX0,
+	TEGRA_PIN_SDMMC1_CMD_PX1,
+	TEGRA_PIN_SDMMC1_DAT0_PX2,
+	TEGRA_PIN_SDMMC1_DAT1_PX3,
+	TEGRA_PIN_SDMMC1_DAT2_PX4,
+	TEGRA_PIN_SDMMC1_DAT3_PX5,
+	TEGRA_PIN_SDMMC1_COMP,
+	TEGRA_PIN_SOC_GPIO124_PL0,
+	TEGRA_PIN_SOC_GPIO125_PL1,
+	TEGRA_PIN_FAN_TACH0_PL2,
+	TEGRA_PIN_SOC_GPIO127_PL3,
+	TEGRA_PIN_SOC_GPIO128_PL4,
+	TEGRA_PIN_SOC_GPIO129_PL5,
+	TEGRA_PIN_SOC_GPIO130_PL6,
+	TEGRA_PIN_SOC_GPIO131_PL7,
+	TEGRA_PIN_GP_PWM9_PM0,
+	TEGRA_PIN_SOC_GPIO133_PM1,
+	TEGRA_PIN_UART9_TX_PM2,
+	TEGRA_PIN_UART9_RX_PM3,
+	TEGRA_PIN_UART9_RTS_N_PM4,
+	TEGRA_PIN_UART9_CTS_N_PM5,
+	TEGRA_PIN_SOC_GPIO170_PU0,
+	TEGRA_PIN_SOC_GPIO171_PU1,
+	TEGRA_PIN_SOC_GPIO172_PU2,
+	TEGRA_PIN_SOC_GPIO173_PU3,
+	TEGRA_PIN_SOC_GPIO174_PU4,
+	TEGRA_PIN_SOC_GPIO175_PU5,
+	TEGRA_PIN_SOC_GPIO176_PU6,
+	TEGRA_PIN_SOC_GPIO177_PU7,
+	TEGRA_PIN_SOC_GPIO178_PV0,
+	TEGRA_PIN_PWM10_PV1,
+	TEGRA_PIN_UART4_TX_PV2,
+	TEGRA_PIN_UART4_RX_PV3,
+	TEGRA_PIN_UART4_RTS_N_PV4,
+	TEGRA_PIN_UART4_CTS_N_PV5,
+	TEGRA_PIN_DAP2_CLK_PV6,
+	TEGRA_PIN_DAP2_DIN_PV7,
+	TEGRA_PIN_DAP2_DOUT_PW0,
+	TEGRA_PIN_DAP2_FS_PW1,
+	TEGRA_PIN_GEN1_I2C_SCL_PW2,
+	TEGRA_PIN_GEN1_I2C_SDA_PW3,
+	TEGRA_PIN_GEN0_I2C_SCL_PW4,
+	TEGRA_PIN_GEN0_I2C_SDA_PW5,
+	TEGRA_PIN_PWR_I2C_SCL_PW6,
+	TEGRA_PIN_PWR_I2C_SDA_PW7,
+	TEGRA_PIN_SOC_GPIO138_PP0,
+	TEGRA_PIN_SOC_GPIO139_PP1,
+	TEGRA_PIN_DAP6_SCLK_PP2,
+	TEGRA_PIN_DAP6_DOUT_PP3,
+	TEGRA_PIN_DAP6_DIN_PP4,
+	TEGRA_PIN_DAP6_FS_PP5,
+	TEGRA_PIN_DAP4_SCLK_PP6,
+	TEGRA_PIN_DAP4_DOUT_PP7,
+	TEGRA_PIN_DAP4_DIN_PQ0,
+	TEGRA_PIN_DAP4_FS_PQ1,
+	TEGRA_PIN_SPI5_SCK_PQ2,
+	TEGRA_PIN_SPI5_MISO_PQ3,
+	TEGRA_PIN_SPI5_MOSI_PQ4,
+	TEGRA_PIN_SPI5_CS0_PQ5,
+	TEGRA_PIN_SOC_GPIO152_PQ6,
+	TEGRA_PIN_SOC_GPIO153_PQ7,
+	TEGRA_PIN_AUD_MCLK_PR0,
+	TEGRA_PIN_SOC_GPIO155_PR1,
+	TEGRA_PIN_DAP1_SCLK_PR2,
+	TEGRA_PIN_DAP1_OUT_PR3,
+	TEGRA_PIN_DAP1_IN_PR4,
+	TEGRA_PIN_DAP1_FS_PR5,
+	TEGRA_PIN_GEN11_I2C_SCL_PR6,
+	TEGRA_PIN_GEN11_I2C_SDA_PR7,
+	TEGRA_PIN_SOC_GPIO350_PS0,
+	TEGRA_PIN_SOC_GPIO351_PS1,
+	TEGRA_PIN_QSPI0_SCK_PT0,
+	TEGRA_PIN_QSPI0_CS_N_PT1,
+	TEGRA_PIN_QSPI0_IO0_PT2,
+	TEGRA_PIN_QSPI0_IO1_PT3,
+	TEGRA_PIN_QSPI0_IO2_PT4,
+	TEGRA_PIN_QSPI0_IO3_PT5,
+	TEGRA_PIN_SOC_GPIO192_PT6,
+	TEGRA_PIN_SOC_GPIO270_PY0,
+	TEGRA_PIN_SOC_GPIO271_PY1,
+	TEGRA_PIN_SOC_GPIO272_PY2,
+	TEGRA_PIN_SOC_GPIO273_PY3,
+	TEGRA_PIN_SOC_GPIO274_PY4,
+	TEGRA_PIN_SOC_GPIO275_PY5,
+	TEGRA_PIN_SOC_GPIO276_PY6,
+	TEGRA_PIN_SOC_GPIO277_PY7,
+	TEGRA_PIN_SOC_GPIO278_PZ0,
+	TEGRA_PIN_SOC_GPIO279_PZ1,
+	TEGRA_PIN_XHALT_TRIG_PZ2,
+	TEGRA_PIN_SOC_GPIO281_PZ3,
+	TEGRA_PIN_SOC_GPIO282_PZ4,
+	TEGRA_PIN_SOC_GPIO283_PZ5,
+	TEGRA_PIN_SOC_GPIO284_PZ6,
+	TEGRA_PIN_SOC_GPIO285_PZ7,
+	TEGRA_PIN_SOC_GPIO286_PAL0,
+	TEGRA_PIN_SOC_GPIO287_PAL1,
+	TEGRA_PIN_SOC_GPIO288_PAL2,
+	TEGRA_PIN_CPU_PWR_REQ_PH0,
+	TEGRA_PIN_GPU_PWR_REQ_PH1,
+	TEGRA_PIN_UART10_TX_PH2,
+	TEGRA_PIN_UART10_RX_PH3,
+	TEGRA_PIN_UART10_RTS_N_PH4,
+	TEGRA_PIN_UART10_CTS_N_PH5,
+	TEGRA_PIN_SPI3_SCK_PH6,
+	TEGRA_PIN_SPI3_MISO_PH7,
+	TEGRA_PIN_SPI3_MOSI_PJ0,
+	TEGRA_PIN_SPI3_CS0_PJ1,
+	TEGRA_PIN_SPI3_CS3_PJ2,
+	TEGRA_PIN_UART5_TX_PJ3,
+	TEGRA_PIN_UART5_RX_PJ4,
+	TEGRA_PIN_UART5_RTS_N_PJ5,
+	TEGRA_PIN_UART5_CTS_N_PJ6,
+	TEGRA_PIN_SPI1_SCK_PJ7,
+	TEGRA_PIN_SPI1_MISO_PK0,
+	TEGRA_PIN_SPI1_MOSI_PK1,
+	TEGRA_PIN_SPI1_CS0_PK2,
+	TEGRA_PIN_SPI1_CS1_PK3,
+	TEGRA_PIN_EXTPERIPH1_CLK_PK4,
+	TEGRA_PIN_EXTPERIPH2_CLK_PK5,
+	TEGRA_PIN_GEN12_I2C_SCL_PK6,
+	TEGRA_PIN_GEN12_I2C_SDA_PK7,
+};
+
+enum {
+	TEGRA_PIN_SOC_GPIO00_PAA0,
+	TEGRA_PIN_VCOMP_ALERT_PAA1,
+	TEGRA_PIN_AO_RETENTION_N_PAA2,
+	TEGRA_PIN_BATT_OC_PAA3,
+	TEGRA_PIN_BOOTV_CTL_N_PAA4,
+	TEGRA_PIN_POWER_ON_PAA5,
+	TEGRA_PIN_HDMI_CEC_PAA6,
+	TEGRA_PIN_SOC_GPIO07_PAA7,
+	TEGRA_PIN_SOC_GPIO08_PBB0,
+	TEGRA_PIN_SOC_GPIO09_PBB1,
+	TEGRA_PIN_GEN2_I2C_SCL_PCC0,
+	TEGRA_PIN_GEN2_I2C_SDA_PCC1,
+	TEGRA_PIN_GEN3_I2C_SCL_PCC2,
+	TEGRA_PIN_GEN3_I2C_SDA_PCC3,
+	TEGRA_PIN_GP_PWM4_PCC4,
+	TEGRA_PIN_UART0_TX_PCC5,
+	TEGRA_PIN_UART0_RX_PCC6,
+	TEGRA_PIN_SPI2_SCK_PCC7,
+	TEGRA_PIN_SPI2_MISO_PDD0,
+	TEGRA_PIN_SPI2_MOSI_PDD1,
+	TEGRA_PIN_SPI2_CS0_N_PDD2,
+	TEGRA_PIN_SOC_GPIO21_PDD3,
+	TEGRA_PIN_SOC_GPIO22_PDD4,
+	TEGRA_PIN_SOC_GPIO23_PDD5,
+	TEGRA_PIN_SOC_GPIO24_PDD6,
+	TEGRA_PIN_SOC_GPIO25_PDD7,
+	TEGRA_PIN_SOC_GPIO26_PEE0,
+	TEGRA_PIN_SOC_GPIO27_PEE1,
+	TEGRA_PIN_SOC_GPIO28_PEE2,
+	TEGRA_PIN_SOC_GPIO29_PEE3,
+};
+
+static const struct pinctrl_pin_desc tegra264_uphy_pins[] = {
+	PINCTRL_PIN(TEGRA_PIN_PEX_L4_CLKREQ_N_PD0, "PEX_L4_CLKREQ_N_PD0"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_L4_RST_N_PD1, "PEX_L4_RST_N_PD1"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_L5_CLKREQ_N_PD2, "PEX_L5_CLKREQ_N_PD2"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_L5_RST_N_PD3, "PEX_L5_RST_N_PD3"),
+	PINCTRL_PIN(TEGRA_PIN_ETH0_MDIO_PD4, "ETH0_MDIO_PD4"),
+	PINCTRL_PIN(TEGRA_PIN_ETH0_MDC_PD5, "ETH0_MDC_PD5"),
+	PINCTRL_PIN(TEGRA_PIN_ETH3_MDIO_PD6, "ETH3_MDIO_PD6"),
+	PINCTRL_PIN(TEGRA_PIN_ETH3_MDC_PD7, "ETH3_MDC_PD7"),
+	PINCTRL_PIN(TEGRA_PIN_ETH1_MDIO_PE0, "ETH1_MDIO_PE0"),
+	PINCTRL_PIN(TEGRA_PIN_ETH1_MDC_PE1, "ETH1_MDC_PE1"),
+	PINCTRL_PIN(TEGRA_PIN_ETH2_MDIO_PE2, "ETH2_MDIO_PE2"),
+	PINCTRL_PIN(TEGRA_PIN_ETH2_MDC_PE3, "ETH2_MDC_PE3"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PB0, "PEX_L1_CLKREQ_N_PB0"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PB1, "PEX_L1_RST_N_PB1"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PB2, "PEX_L2_CLKREQ_N_PB2"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PB3, "PEX_L2_RST_N_PB3"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_L3_CLKREQ_N_PB4, "PEX_L3_CLKREQ_N_PB4"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_L3_RST_N_PB5, "PEX_L3_RST_N_PB5"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO113_PB6, "SOC_GPIO113_PB6"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO114_PB7, "SOC_GPIO114_PB7"),
+	PINCTRL_PIN(TEGRA_PIN_SGMII0_SMA_MDIO_PC0, "SGMII0_SMA_MDIO_PC0"),
+	PINCTRL_PIN(TEGRA_PIN_SGMII0_SMA_MDC_PC1, "SGMII0_SMA_MDC_PC1"),
+	PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PC2, "PEX_WAKE_N_PC2"),
+	PINCTRL_PIN(TEGRA_PIN_PWM1_PA0, "PWM1_PA0"),
+	PINCTRL_PIN(TEGRA_PIN_PWM6_PA1, "PWM6_PA1"),
+	PINCTRL_PIN(TEGRA_PIN_PWM7_PA2, "PWM7_PA2"),
+	PINCTRL_PIN(TEGRA_PIN_PWM8_PA3, "PWM8_PA3"),
+	PINCTRL_PIN(TEGRA_PIN_UFS0_REF_CLK_PA4, "UFS0_REF_CLK_PA4"),
+	PINCTRL_PIN(TEGRA_PIN_UFS0_RST_N_PA5, "UFS0_RST_N_PA5"),
+};
+
+static const struct pinctrl_pin_desc tegra264_main_pins[] = {
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO250_PF0, "SOC_GPIO250_PF0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO251_PF1, "SOC_GPIO251_PF1"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO252_PF2, "SOC_GPIO252_PF2"),
+	PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH0_HPD_PF3, "DP_AUX_CH0_HPD_PF3"),
+	PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH1_HPD_PF4, "DP_AUX_CH1_HPD_PF4"),
+	PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH2_HPD_PF5, "DP_AUX_CH2_HPD_PF5"),
+	PINCTRL_PIN(TEGRA_PIN_DP_AUX_CH3_HPD_PF6, "DP_AUX_CH3_HPD_PF6"),
+	PINCTRL_PIN(TEGRA_PIN_PWM2_PF7, "PWM2_PF7"),
+	PINCTRL_PIN(TEGRA_PIN_PWM3_PG0, "PWM3_PG0"),
+	PINCTRL_PIN(TEGRA_PIN_GEN7_I2C_SCL_PG1, "GEN7_I2C_SCL_PG1"),
+	PINCTRL_PIN(TEGRA_PIN_GEN7_I2C_SDA_PG2, "GEN7_I2C_SDA_PG2"),
+	PINCTRL_PIN(TEGRA_PIN_GEN9_I2C_SCL_PG3, "GEN9_I2C_SCL_PG3"),
+	PINCTRL_PIN(TEGRA_PIN_GEN9_I2C_SDA_PG4, "GEN9_I2C_SDA_PG4"),
+	PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PX0, "SDMMC1_CLK_PX0"),
+	PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PX1, "SDMMC1_CMD_PX1"),
+	PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PX2, "SDMMC1_DAT0_PX2"),
+	PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PX3, "SDMMC1_DAT1_PX3"),
+	PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PX4, "SDMMC1_DAT2_PX4"),
+	PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PX5, "SDMMC1_DAT3_PX5"),
+	PINCTRL_PIN(TEGRA_PIN_SDMMC1_COMP, "SDMMC1_COMP"),
+	PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ_PH0, "CPU_PWR_REQ_PH0"),
+	PINCTRL_PIN(TEGRA_PIN_GPU_PWR_REQ_PH1, "GPU_PWR_REQ_PH1"),
+	PINCTRL_PIN(TEGRA_PIN_UART10_TX_PH2, "UART10_TX_PH2"),
+	PINCTRL_PIN(TEGRA_PIN_UART10_RX_PH3, "UART10_RX_PH3"),
+	PINCTRL_PIN(TEGRA_PIN_UART10_RTS_N_PH4, "UART10_RTS_N_PH4"),
+	PINCTRL_PIN(TEGRA_PIN_UART10_CTS_N_PH5, "UART10_CTS_N_PH5"),
+	PINCTRL_PIN(TEGRA_PIN_SPI3_SCK_PH6, "SPI3_SCK_PH6"),
+	PINCTRL_PIN(TEGRA_PIN_SPI3_MISO_PH7, "SPI3_MISO_PH7"),
+	PINCTRL_PIN(TEGRA_PIN_SPI3_MOSI_PJ0, "SPI3_MOSI_PJ0"),
+	PINCTRL_PIN(TEGRA_PIN_SPI3_CS0_PJ1, "SPI3_CS0_PJ1"),
+	PINCTRL_PIN(TEGRA_PIN_SPI3_CS3_PJ2, "SPI3_CS3_PJ2"),
+	PINCTRL_PIN(TEGRA_PIN_UART5_TX_PJ3, "UART5_TX_PJ3"),
+	PINCTRL_PIN(TEGRA_PIN_UART5_RX_PJ4, "UART5_RX_PJ4"),
+	PINCTRL_PIN(TEGRA_PIN_UART5_RTS_N_PJ5, "UART5_RTS_N_PJ5"),
+	PINCTRL_PIN(TEGRA_PIN_UART5_CTS_N_PJ6, "UART5_CTS_N_PJ6"),
+	PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PJ7, "SPI1_SCK_PJ7"),
+	PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PK0, "SPI1_MISO_PK0"),
+	PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PK1, "SPI1_MOSI_PK1"),
+	PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PK2, "SPI1_CS0_PK2"),
+	PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PK3, "SPI1_CS1_PK3"),
+	PINCTRL_PIN(TEGRA_PIN_EXTPERIPH1_CLK_PK4, "EXTPERIPH1_CLK_PK4"),
+	PINCTRL_PIN(TEGRA_PIN_EXTPERIPH2_CLK_PK5, "EXTPERIPH2_CLK_PK5"),
+	PINCTRL_PIN(TEGRA_PIN_GEN12_I2C_SCL_PK6, "GEN12_I2C_SCL_PK6"),
+	PINCTRL_PIN(TEGRA_PIN_GEN12_I2C_SDA_PK7, "GEN12_I2C_SDA_PK7"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO124_PL0, "SOC_GPIO124_PL0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO125_PL1, "SOC_GPIO125_PL1"),
+	PINCTRL_PIN(TEGRA_PIN_FAN_TACH0_PL2, "FAN_TACH0_PL2"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO127_PL3, "SOC_GPIO127_PL3"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO128_PL4, "SOC_GPIO128_PL4"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO129_PL5, "SOC_GPIO129_PL5"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO130_PL6, "SOC_GPIO130_PL6"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO131_PL7, "SOC_GPIO131_PL7"),
+	PINCTRL_PIN(TEGRA_PIN_GP_PWM9_PM0, "GP_PWM9_PM0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO133_PM1, "SOC_GPIO133_PM1"),
+	PINCTRL_PIN(TEGRA_PIN_UART9_TX_PM2, "UART9_TX_PM2"),
+	PINCTRL_PIN(TEGRA_PIN_UART9_RX_PM3, "UART9_RX_PM3"),
+	PINCTRL_PIN(TEGRA_PIN_UART9_RTS_N_PM4, "UART9_RTS_N_PM4"),
+	PINCTRL_PIN(TEGRA_PIN_UART9_CTS_N_PM5, "UART9_CTS_N_PM5"),
+	PINCTRL_PIN(TEGRA_PIN_QSPI0_SCK_PT0, "QSPI0_SCK_PT0"),
+	PINCTRL_PIN(TEGRA_PIN_QSPI0_CS_N_PT1, "QSPI0_CS_N_PT1"),
+	PINCTRL_PIN(TEGRA_PIN_QSPI0_IO0_PT2, "QSPI0_IO0_PT2"),
+	PINCTRL_PIN(TEGRA_PIN_QSPI0_IO1_PT3, "QSPI0_IO1_PT3"),
+	PINCTRL_PIN(TEGRA_PIN_QSPI0_IO2_PT4, "QSPI0_IO2_PT4"),
+	PINCTRL_PIN(TEGRA_PIN_QSPI0_IO3_PT5, "QSPI0_IO3_PT5"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO192_PT6, "SOC_GPIO192_PT6"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO170_PU0, "SOC_GPIO170_PU0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO171_PU1, "SOC_GPIO171_PU1"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO172_PU2, "SOC_GPIO172_PU2"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO173_PU3, "SOC_GPIO173_PU3"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO174_PU4, "SOC_GPIO174_PU4"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO175_PU5, "SOC_GPIO175_PU5"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO176_PU6, "SOC_GPIO176_PU6"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO177_PU7, "SOC_GPIO177_PU7"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO178_PV0, "SOC_GPIO178_PV0"),
+	PINCTRL_PIN(TEGRA_PIN_PWM10_PV1, "PWM10_PV1"),
+	PINCTRL_PIN(TEGRA_PIN_UART4_TX_PV2, "UART4_TX_PV2"),
+	PINCTRL_PIN(TEGRA_PIN_UART4_RX_PV3, "UART4_RX_PV3"),
+	PINCTRL_PIN(TEGRA_PIN_UART4_RTS_N_PV4, "UART4_RTS_N_PV4"),
+	PINCTRL_PIN(TEGRA_PIN_UART4_CTS_N_PV5, "UART4_CTS_N_PV5"),
+	PINCTRL_PIN(TEGRA_PIN_DAP2_CLK_PV6, "DAP2_CLK_PV6"),
+	PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PV7, "DAP2_DIN_PV7"),
+	PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PW0, "DAP2_DOUT_PW0"),
+	PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PW1, "DAP2_FS_PW1"),
+	PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PW2, "GEN1_I2C_SCL_PW2"),
+	PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PW3, "GEN1_I2C_SDA_PW3"),
+	PINCTRL_PIN(TEGRA_PIN_GEN0_I2C_SCL_PW4, "GEN0_I2C_SCL_PW4"),
+	PINCTRL_PIN(TEGRA_PIN_GEN0_I2C_SDA_PW5, "GEN0_I2C_SDA_PW5"),
+	PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PW6, "PWR_I2C_SCL_PW6"),
+	PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PW7, "PWR_I2C_SDA_PW7"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO270_PY0, "SOC_GPIO270_PY0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO271_PY1, "SOC_GPIO271_PY1"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO272_PY2, "SOC_GPIO272_PY2"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO273_PY3, "SOC_GPIO273_PY3"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO274_PY4, "SOC_GPIO274_PY4"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO275_PY5, "SOC_GPIO275_PY5"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO276_PY6, "SOC_GPIO276_PY6"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO277_PY7, "SOC_GPIO277_PY7"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO278_PZ0, "SOC_GPIO278_PZ0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO279_PZ1, "SOC_GPIO279_PZ1"),
+	PINCTRL_PIN(TEGRA_PIN_XHALT_TRIG_PZ2, "XHALT_TRIG_PZ2"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO281_PZ3, "SOC_GPIO281_PZ3"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO282_PZ4, "SOC_GPIO282_PZ4"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO283_PZ5, "SOC_GPIO283_PZ5"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO284_PZ6, "SOC_GPIO284_PZ6"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO285_PZ7, "SOC_GPIO285_PZ7"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO286_PAL0, "SOC_GPIO286_PAL0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO287_PAL1, "SOC_GPIO287_PAL1"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO288_PAL2, "SOC_GPIO288_PAL2"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO138_PP0, "SOC_GPIO138_PP0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO139_PP1, "SOC_GPIO139_PP1"),
+	PINCTRL_PIN(TEGRA_PIN_DAP6_SCLK_PP2, "DAP6_SCLK_PP2"),
+	PINCTRL_PIN(TEGRA_PIN_DAP6_DOUT_PP3, "DAP6_DOUT_PP3"),
+	PINCTRL_PIN(TEGRA_PIN_DAP6_DIN_PP4, "DAP6_DIN_PP4"),
+	PINCTRL_PIN(TEGRA_PIN_DAP6_FS_PP5, "DAP6_FS_PP5"),
+	PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP6, "DAP4_SCLK_PP6"),
+	PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP7, "DAP4_DOUT_PP7"),
+	PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PQ0, "DAP4_DIN_PQ0"),
+	PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PQ1, "DAP4_FS_PQ1"),
+	PINCTRL_PIN(TEGRA_PIN_SPI5_SCK_PQ2, "SPI5_SCK_PQ2"),
+	PINCTRL_PIN(TEGRA_PIN_SPI5_MISO_PQ3, "SPI5_MISO_PQ3"),
+	PINCTRL_PIN(TEGRA_PIN_SPI5_MOSI_PQ4, "SPI5_MOSI_PQ4"),
+	PINCTRL_PIN(TEGRA_PIN_SPI5_CS0_PQ5, "SPI5_CS0_PQ5"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO152_PQ6, "SOC_GPIO152_PQ6"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO153_PQ7, "SOC_GPIO153_PQ7"),
+	PINCTRL_PIN(TEGRA_PIN_AUD_MCLK_PR0, "AUD_MCLK_PR0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO155_PR1, "SOC_GPIO155_PR1"),
+	PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PR2, "DAP1_SCLK_PR2"),
+	PINCTRL_PIN(TEGRA_PIN_DAP1_OUT_PR3, "DAP1_OUT_PR3"),
+	PINCTRL_PIN(TEGRA_PIN_DAP1_IN_PR4, "DAP1_IN_PR4"),
+	PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PR5, "DAP1_FS_PR5"),
+	PINCTRL_PIN(TEGRA_PIN_GEN11_I2C_SCL_PR6, "GEN11_I2C_SCL_PR6"),
+	PINCTRL_PIN(TEGRA_PIN_GEN11_I2C_SDA_PR7, "GEN11_I2C_SDA_PR7"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO350_PS0, "SOC_GPIO350_PS0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO351_PS1, "SOC_GPIO351_PS1"),
+
+};
+
+static const struct pinctrl_pin_desc tegra264_aon_pins[] = {
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO00_PAA0, "SOC_GPIO00_PAA0"),
+	PINCTRL_PIN(TEGRA_PIN_VCOMP_ALERT_PAA1, "VCOMP_ALERT_PAA1"),
+	PINCTRL_PIN(TEGRA_PIN_AO_RETENTION_N_PAA2, "AO_RETENTION_N_PAA2"),
+	PINCTRL_PIN(TEGRA_PIN_BATT_OC_PAA3, "BATT_OC_PAA3"),
+	PINCTRL_PIN(TEGRA_PIN_BOOTV_CTL_N_PAA4, "BOOTV_CTL_N_PAA4"),
+	PINCTRL_PIN(TEGRA_PIN_POWER_ON_PAA5, "POWER_ON_PAA5"),
+	PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PAA6, "HDMI_CEC_PAA6"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO07_PAA7, "SOC_GPIO07_PAA7"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO08_PBB0, "SOC_GPIO08_PBB0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO09_PBB1, "SOC_GPIO09_PBB1"),
+	PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PCC0, "GEN2_I2C_SCL_PCC0"),
+	PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PCC1, "GEN2_I2C_SDA_PCC1"),
+	PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SCL_PCC2, "GEN3_I2C_SCL_PCC2"),
+	PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SDA_PCC3, "GEN3_I2C_SDA_PCC3"),
+	PINCTRL_PIN(TEGRA_PIN_GP_PWM4_PCC4, "GP_PWM4_PCC4"),
+	PINCTRL_PIN(TEGRA_PIN_UART0_TX_PCC5, "UART0_TX_PCC5"),
+	PINCTRL_PIN(TEGRA_PIN_UART0_RX_PCC6, "UART0_RX_PCC6"),
+	PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PCC7, "SPI2_SCK_PCC7"),
+	PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PDD0, "SPI2_MISO_PDD0"),
+	PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PDD1, "SPI2_MOSI_PDD1"),
+	PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PDD2, "SPI2_CS0_N_PDD2"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO21_PDD3, "SOC_GPIO21_PDD3"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO22_PDD4, "SOC_GPIO22_PDD4"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO23_PDD5, "SOC_GPIO23_PDD5"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO24_PDD6, "SOC_GPIO24_PDD6"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO25_PDD7, "SOC_GPIO25_PDD7"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO26_PEE0, "SOC_GPIO26_PEE0"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO27_PEE1, "SOC_GPIO27_PEE1"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO28_PEE2, "SOC_GPIO28_PEE2"),
+	PINCTRL_PIN(TEGRA_PIN_SOC_GPIO29_PEE3, "SOC_GPIO29_PEE3"),
+};
+
+static const unsigned int soc_gpio250_pf0_pins[] = {
+		TEGRA_PIN_SOC_GPIO250_PF0,
+};
+
+static const unsigned int soc_gpio251_pf1_pins[] = {
+	TEGRA_PIN_SOC_GPIO251_PF1,
+};
+
+static const unsigned int soc_gpio252_pf2_pins[] = {
+	TEGRA_PIN_SOC_GPIO252_PF2,
+};
+
+static const unsigned int dp_aux_ch0_hpd_pf3_pins[] = {
+	TEGRA_PIN_DP_AUX_CH0_HPD_PF3,
+};
+
+static const unsigned int dp_aux_ch1_hpd_pf4_pins[] = {
+	TEGRA_PIN_DP_AUX_CH1_HPD_PF4,
+};
+
+static const unsigned int dp_aux_ch2_hpd_pf5_pins[] = {
+	TEGRA_PIN_DP_AUX_CH2_HPD_PF5,
+};
+
+static const unsigned int dp_aux_ch3_hpd_pf6_pins[] = {
+	TEGRA_PIN_DP_AUX_CH3_HPD_PF6,
+};
+
+static const unsigned int pwm2_pf7_pins[] = {
+	TEGRA_PIN_PWM2_PF7,
+};
+
+static const unsigned int pwm3_pg0_pins[] = {
+	TEGRA_PIN_PWM3_PG0,
+};
+
+static const unsigned int gen7_i2c_scl_pg1_pins[] = {
+	TEGRA_PIN_GEN7_I2C_SCL_PG1,
+};
+
+static const unsigned int gen7_i2c_sda_pg2_pins[] = {
+	TEGRA_PIN_GEN7_I2C_SDA_PG2,
+};
+
+static const unsigned int gen9_i2c_scl_pg3_pins[] = {
+	TEGRA_PIN_GEN9_I2C_SCL_PG3,
+};
+
+static const unsigned int gen9_i2c_sda_pg4_pins[] = {
+	TEGRA_PIN_GEN9_I2C_SDA_PG4,
+};
+
+static const unsigned int pwm1_pa0_pins[] = {
+	TEGRA_PIN_PWM1_PA0,
+};
+
+static const unsigned int pwm6_pa1_pins[] = {
+	TEGRA_PIN_PWM6_PA1,
+};
+
+static const unsigned int pwm7_pa2_pins[] = {
+	TEGRA_PIN_PWM7_PA2,
+};
+
+static const unsigned int pwm8_pa3_pins[] = {
+	TEGRA_PIN_PWM8_PA3,
+};
+
+static const unsigned int ufs0_ref_clk_pa4_pins[] = {
+	TEGRA_PIN_UFS0_REF_CLK_PA4,
+};
+
+static const unsigned int ufs0_rst_n_pa5_pins[] = {
+	TEGRA_PIN_UFS0_RST_N_PA5,
+};
+
+static const unsigned int pex_l1_clkreq_n_pb0_pins[] = {
+	TEGRA_PIN_PEX_L1_CLKREQ_N_PB0,
+};
+
+static const unsigned int pex_l1_rst_n_pb1_pins[] = {
+	TEGRA_PIN_PEX_L1_RST_N_PB1,
+};
+
+static const unsigned int pex_l2_clkreq_n_pb2_pins[] = {
+	TEGRA_PIN_PEX_L2_CLKREQ_N_PB2,
+};
+
+static const unsigned int pex_l2_rst_n_pb3_pins[] = {
+	TEGRA_PIN_PEX_L2_RST_N_PB3,
+};
+
+static const unsigned int pex_l3_clkreq_n_pb4_pins[] = {
+	TEGRA_PIN_PEX_L3_CLKREQ_N_PB4,
+};
+
+static const unsigned int pex_l3_rst_n_pb5_pins[] = {
+	TEGRA_PIN_PEX_L3_RST_N_PB5,
+};
+
+static const unsigned int soc_gpio113_pb6_pins[] = {
+	TEGRA_PIN_SOC_GPIO113_PB6,
+};
+
+static const unsigned int soc_gpio114_pb7_pins[] = {
+	TEGRA_PIN_SOC_GPIO114_PB7,
+};
+
+static const unsigned int sgmii0_sma_mdio_pc0_pins[] = {
+	TEGRA_PIN_SGMII0_SMA_MDIO_PC0,
+};
+
+static const unsigned int sgmii0_sma_mdc_pc1_pins[] = {
+	TEGRA_PIN_SGMII0_SMA_MDC_PC1,
+};
+
+static const unsigned int pex_wake_n_pc2_pins[] = {
+	TEGRA_PIN_PEX_WAKE_N_PC2,
+};
+
+static const unsigned int pex_l4_clkreq_n_pd0_pins[] = {
+	TEGRA_PIN_PEX_L4_CLKREQ_N_PD0,
+};
+
+static const unsigned int pex_l4_rst_n_pd1_pins[] = {
+	TEGRA_PIN_PEX_L4_RST_N_PD1,
+};
+
+static const unsigned int pex_l5_clkreq_n_pd2_pins[] = {
+	TEGRA_PIN_PEX_L5_CLKREQ_N_PD2,
+};
+
+static const unsigned int pex_l5_rst_n_pd3_pins[] = {
+	TEGRA_PIN_PEX_L5_RST_N_PD3,
+};
+
+static const unsigned int eth0_mdio_pd4_pins[] = {
+	TEGRA_PIN_ETH0_MDIO_PD4,
+};
+
+static const unsigned int eth0_mdc_pd5_pins[] = {
+	TEGRA_PIN_ETH0_MDC_PD5,
+};
+
+static const unsigned int eth3_mdio_pd6_pins[] = {
+	TEGRA_PIN_ETH3_MDIO_PD6,
+};
+
+static const unsigned int eth3_mdc_pd7_pins[] = {
+	TEGRA_PIN_ETH3_MDC_PD7,
+};
+
+static const unsigned int eth1_mdio_pe0_pins[] = {
+	TEGRA_PIN_ETH1_MDIO_PE0,
+};
+
+static const unsigned int eth1_mdc_pe1_pins[] = {
+	TEGRA_PIN_ETH1_MDC_PE1,
+};
+
+static const unsigned int eth2_mdio_pe2_pins[] = {
+	TEGRA_PIN_ETH2_MDIO_PE2,
+};
+
+static const unsigned int eth2_mdc_pe3_pins[] = {
+	TEGRA_PIN_ETH2_MDC_PE3,
+};
+
+static const unsigned int sdmmc1_clk_px0_pins[] = {
+	TEGRA_PIN_SDMMC1_CLK_PX0,
+};
+
+static const unsigned int sdmmc1_cmd_px1_pins[] = {
+	TEGRA_PIN_SDMMC1_CMD_PX1,
+};
+
+static const unsigned int sdmmc1_dat0_px2_pins[] = {
+	TEGRA_PIN_SDMMC1_DAT0_PX2,
+};
+
+static const unsigned int sdmmc1_dat1_px3_pins[] = {
+	TEGRA_PIN_SDMMC1_DAT1_PX3,
+};
+
+static const unsigned int sdmmc1_dat2_px4_pins[] = {
+	TEGRA_PIN_SDMMC1_DAT2_PX4,
+};
+
+static const unsigned int sdmmc1_dat3_px5_pins[] = {
+	TEGRA_PIN_SDMMC1_DAT3_PX5,
+};
+
+static const unsigned int sdmmc1_comp_pins[] = {
+	TEGRA_PIN_SDMMC1_COMP,
+};
+
+static const unsigned int cpu_pwr_req_ph0_pins[] = {
+	TEGRA_PIN_CPU_PWR_REQ_PH0,
+};
+
+static const unsigned int gpu_pwr_req_ph1_pins[] = {
+	TEGRA_PIN_GPU_PWR_REQ_PH1,
+};
+
+static const unsigned int uart10_tx_ph2_pins[] = {
+	TEGRA_PIN_UART10_TX_PH2,
+};
+
+static const unsigned int uart10_rx_ph3_pins[] = {
+	TEGRA_PIN_UART10_RX_PH3,
+};
+
+static const unsigned int uart10_rts_n_ph4_pins[] = {
+	TEGRA_PIN_UART10_RTS_N_PH4,
+};
+
+static const unsigned int uart10_cts_n_ph5_pins[] = {
+	TEGRA_PIN_UART10_CTS_N_PH5,
+};
+
+static const unsigned int spi3_sck_ph6_pins[] = {
+	TEGRA_PIN_SPI3_SCK_PH6,
+};
+
+static const unsigned int spi3_miso_ph7_pins[] = {
+	TEGRA_PIN_SPI3_MISO_PH7,
+};
+
+static const unsigned int spi3_mosi_pj0_pins[] = {
+	TEGRA_PIN_SPI3_MOSI_PJ0,
+};
+
+static const unsigned int spi3_cs0_pj1_pins[] = {
+	TEGRA_PIN_SPI3_CS0_PJ1,
+};
+
+static const unsigned int spi3_cs3_pj2_pins[] = {
+	TEGRA_PIN_SPI3_CS3_PJ2,
+};
+
+static const unsigned int uart5_tx_pj3_pins[] = {
+	TEGRA_PIN_UART5_TX_PJ3,
+};
+
+static const unsigned int uart5_rx_pj4_pins[] = {
+	TEGRA_PIN_UART5_RX_PJ4,
+};
+
+static const unsigned int uart5_rts_n_pj5_pins[] = {
+	TEGRA_PIN_UART5_RTS_N_PJ5,
+};
+
+static const unsigned int uart5_cts_n_pj6_pins[] = {
+	TEGRA_PIN_UART5_CTS_N_PJ6,
+};
+
+static const unsigned int spi1_sck_pj7_pins[] = {
+	TEGRA_PIN_SPI1_SCK_PJ7,
+};
+
+static const unsigned int spi1_miso_pk0_pins[] = {
+	TEGRA_PIN_SPI1_MISO_PK0,
+};
+
+static const unsigned int spi1_mosi_pk1_pins[] = {
+	TEGRA_PIN_SPI1_MOSI_PK1,
+};
+
+static const unsigned int spi1_cs0_pk2_pins[] = {
+	TEGRA_PIN_SPI1_CS0_PK2,
+};
+
+static const unsigned int spi1_cs1_pk3_pins[] = {
+	TEGRA_PIN_SPI1_CS1_PK3,
+};
+
+static const unsigned int extperiph1_clk_pk4_pins[] = {
+	TEGRA_PIN_EXTPERIPH1_CLK_PK4,
+};
+
+static const unsigned int extperiph2_clk_pk5_pins[] = {
+	TEGRA_PIN_EXTPERIPH2_CLK_PK5,
+};
+
+static const unsigned int gen12_i2c_scl_pk6_pins[] = {
+	TEGRA_PIN_GEN12_I2C_SCL_PK6,
+};
+
+static const unsigned int gen12_i2c_sda_pk7_pins[] = {
+	TEGRA_PIN_GEN12_I2C_SDA_PK7,
+};
+
+static const unsigned int soc_gpio124_pl0_pins[] = {
+	TEGRA_PIN_SOC_GPIO124_PL0,
+};
+
+static const unsigned int soc_gpio125_pl1_pins[] = {
+	TEGRA_PIN_SOC_GPIO125_PL1,
+};
+
+static const unsigned int fan_tach0_pl2_pins[] = {
+	TEGRA_PIN_FAN_TACH0_PL2,
+};
+
+static const unsigned int soc_gpio127_pl3_pins[] = {
+	TEGRA_PIN_SOC_GPIO127_PL3,
+};
+
+static const unsigned int soc_gpio128_pl4_pins[] = {
+	TEGRA_PIN_SOC_GPIO128_PL4,
+};
+
+static const unsigned int soc_gpio129_pl5_pins[] = {
+	TEGRA_PIN_SOC_GPIO129_PL5,
+};
+
+static const unsigned int soc_gpio130_pl6_pins[] = {
+	TEGRA_PIN_SOC_GPIO130_PL6,
+};
+
+static const unsigned int soc_gpio131_pl7_pins[] = {
+	TEGRA_PIN_SOC_GPIO131_PL7,
+};
+
+static const unsigned int gp_pwm9_pm0_pins[] = {
+	TEGRA_PIN_GP_PWM9_PM0,
+};
+
+static const unsigned int soc_gpio133_pm1_pins[] = {
+	TEGRA_PIN_SOC_GPIO133_PM1,
+};
+
+static const unsigned int uart9_tx_pm2_pins[] = {
+	TEGRA_PIN_UART9_TX_PM2,
+};
+
+static const unsigned int uart9_rx_pm3_pins[] = {
+	TEGRA_PIN_UART9_RX_PM3,
+};
+
+static const unsigned int uart9_rts_n_pm4_pins[] = {
+	TEGRA_PIN_UART9_RTS_N_PM4,
+};
+
+static const unsigned int uart9_cts_n_pm5_pins[] = {
+	TEGRA_PIN_UART9_CTS_N_PM5,
+};
+
+static const unsigned int soc_gpio170_pu0_pins[] = {
+	TEGRA_PIN_SOC_GPIO170_PU0,
+};
+
+static const unsigned int soc_gpio171_pu1_pins[] = {
+	TEGRA_PIN_SOC_GPIO171_PU1,
+};
+
+static const unsigned int soc_gpio172_pu2_pins[] = {
+	TEGRA_PIN_SOC_GPIO172_PU2,
+};
+
+static const unsigned int soc_gpio173_pu3_pins[] = {
+	TEGRA_PIN_SOC_GPIO173_PU3,
+};
+
+static const unsigned int soc_gpio174_pu4_pins[] = {
+	TEGRA_PIN_SOC_GPIO174_PU4,
+};
+
+static const unsigned int soc_gpio175_pu5_pins[] = {
+	TEGRA_PIN_SOC_GPIO175_PU5,
+};
+
+static const unsigned int soc_gpio176_pu6_pins[] = {
+	TEGRA_PIN_SOC_GPIO176_PU6,
+};
+
+static const unsigned int soc_gpio177_pu7_pins[] = {
+	TEGRA_PIN_SOC_GPIO177_PU7,
+};
+
+static const unsigned int soc_gpio178_pv0_pins[] = {
+	TEGRA_PIN_SOC_GPIO178_PV0,
+};
+
+static const unsigned int pwm10_pv1_pins[] = {
+	TEGRA_PIN_PWM10_PV1,
+};
+
+static const unsigned int uart4_tx_pv2_pins[] = {
+	TEGRA_PIN_UART4_TX_PV2,
+};
+
+static const unsigned int uart4_rx_pv3_pins[] = {
+	TEGRA_PIN_UART4_RX_PV3,
+};
+
+static const unsigned int uart4_rts_n_pv4_pins[] = {
+	TEGRA_PIN_UART4_RTS_N_PV4,
+};
+
+static const unsigned int uart4_cts_n_pv5_pins[] = {
+	TEGRA_PIN_UART4_CTS_N_PV5,
+};
+
+static const unsigned int dap2_clk_pv6_pins[] = {
+	TEGRA_PIN_DAP2_CLK_PV6,
+};
+
+static const unsigned int dap2_din_pv7_pins[] = {
+	TEGRA_PIN_DAP2_DIN_PV7,
+};
+
+static const unsigned int dap2_dout_pw0_pins[] = {
+	TEGRA_PIN_DAP2_DOUT_PW0,
+};
+
+static const unsigned int dap2_fs_pw1_pins[] = {
+	TEGRA_PIN_DAP2_FS_PW1,
+};
+
+static const unsigned int gen1_i2c_scl_pw2_pins[] = {
+	TEGRA_PIN_GEN1_I2C_SCL_PW2,
+};
+
+static const unsigned int gen1_i2c_sda_pw3_pins[] = {
+	TEGRA_PIN_GEN1_I2C_SDA_PW3,
+};
+
+static const unsigned int gen0_i2c_scl_pw4_pins[] = {
+	TEGRA_PIN_GEN0_I2C_SCL_PW4,
+};
+
+static const unsigned int gen0_i2c_sda_pw5_pins[] = {
+	TEGRA_PIN_GEN0_I2C_SDA_PW5,
+};
+
+static const unsigned int pwr_i2c_scl_pw6_pins[] = {
+	TEGRA_PIN_PWR_I2C_SCL_PW6,
+};
+
+static const unsigned int pwr_i2c_sda_pw7_pins[] = {
+	TEGRA_PIN_PWR_I2C_SDA_PW7,
+};
+
+static const unsigned int qspi0_sck_pt0_pins[] = {
+	TEGRA_PIN_QSPI0_SCK_PT0,
+};
+
+static const unsigned int qspi0_cs_n_pt1_pins[] = {
+	TEGRA_PIN_QSPI0_CS_N_PT1,
+};
+
+static const unsigned int qspi0_io0_pt2_pins[] = {
+	TEGRA_PIN_QSPI0_IO0_PT2,
+};
+
+static const unsigned int qspi0_io1_pt3_pins[] = {
+	TEGRA_PIN_QSPI0_IO1_PT3,
+};
+
+static const unsigned int qspi0_io2_pt4_pins[] = {
+	TEGRA_PIN_QSPI0_IO2_PT4,
+};
+
+static const unsigned int qspi0_io3_pt5_pins[] = {
+	TEGRA_PIN_QSPI0_IO3_PT5,
+};
+
+static const unsigned int soc_gpio192_pt6_pins[] = {
+	TEGRA_PIN_SOC_GPIO192_PT6,
+};
+
+static const unsigned int soc_gpio138_pp0_pins[] = {
+	TEGRA_PIN_SOC_GPIO138_PP0,
+};
+
+static const unsigned int soc_gpio139_pp1_pins[] = {
+	TEGRA_PIN_SOC_GPIO139_PP1,
+};
+
+static const unsigned int dap6_sclk_pp2_pins[] = {
+	TEGRA_PIN_DAP6_SCLK_PP2,
+};
+
+static const unsigned int dap6_dout_pp3_pins[] = {
+	TEGRA_PIN_DAP6_DOUT_PP3,
+};
+
+static const unsigned int dap6_din_pp4_pins[] = {
+	TEGRA_PIN_DAP6_DIN_PP4,
+};
+
+static const unsigned int dap6_fs_pp5_pins[] = {
+	TEGRA_PIN_DAP6_FS_PP5,
+};
+
+static const unsigned int dap4_sclk_pp6_pins[] = {
+	TEGRA_PIN_DAP4_SCLK_PP6,
+};
+
+static const unsigned int dap4_dout_pp7_pins[] = {
+	TEGRA_PIN_DAP4_DOUT_PP7,
+};
+
+static const unsigned int dap4_din_pq0_pins[] = {
+	TEGRA_PIN_DAP4_DIN_PQ0,
+};
+
+static const unsigned int dap4_fs_pq1_pins[] = {
+	TEGRA_PIN_DAP4_FS_PQ1,
+};
+
+static const unsigned int spi5_sck_pq2_pins[] = {
+	TEGRA_PIN_SPI5_SCK_PQ2,
+};
+
+static const unsigned int spi5_miso_pq3_pins[] = {
+	TEGRA_PIN_SPI5_MISO_PQ3,
+};
+
+static const unsigned int spi5_mosi_pq4_pins[] = {
+	TEGRA_PIN_SPI5_MOSI_PQ4,
+};
+
+static const unsigned int spi5_cs0_pq5_pins[] = {
+	TEGRA_PIN_SPI5_CS0_PQ5,
+};
+
+static const unsigned int soc_gpio152_pq6_pins[] = {
+	TEGRA_PIN_SOC_GPIO152_PQ6,
+};
+
+static const unsigned int soc_gpio153_pq7_pins[] = {
+	TEGRA_PIN_SOC_GPIO153_PQ7,
+};
+
+static const unsigned int aud_mclk_pr0_pins[] = {
+	TEGRA_PIN_AUD_MCLK_PR0,
+};
+
+static const unsigned int soc_gpio155_pr1_pins[] = {
+	TEGRA_PIN_SOC_GPIO155_PR1,
+};
+
+static const unsigned int dap1_sclk_pr2_pins[] = {
+	TEGRA_PIN_DAP1_SCLK_PR2,
+};
+
+static const unsigned int dap1_out_pr3_pins[] = {
+	TEGRA_PIN_DAP1_OUT_PR3,
+};
+
+static const unsigned int dap1_in_pr4_pins[] = {
+	TEGRA_PIN_DAP1_IN_PR4,
+};
+
+static const unsigned int dap1_fs_pr5_pins[] = {
+	TEGRA_PIN_DAP1_FS_PR5,
+};
+
+static const unsigned int gen11_i2c_scl_pr6_pins[] = {
+	TEGRA_PIN_GEN11_I2C_SCL_PR6,
+};
+
+static const unsigned int gen11_i2c_sda_pr7_pins[] = {
+	TEGRA_PIN_GEN11_I2C_SDA_PR7,
+};
+
+static const unsigned int soc_gpio350_ps0_pins[] = {
+	TEGRA_PIN_SOC_GPIO350_PS0,
+};
+
+static const unsigned int soc_gpio351_ps1_pins[] = {
+	TEGRA_PIN_SOC_GPIO351_PS1,
+};
+
+static const unsigned int soc_gpio270_py0_pins[] = {
+	TEGRA_PIN_SOC_GPIO270_PY0,
+};
+
+static const unsigned int soc_gpio271_py1_pins[] = {
+	TEGRA_PIN_SOC_GPIO271_PY1,
+};
+
+static const unsigned int soc_gpio272_py2_pins[] = {
+	TEGRA_PIN_SOC_GPIO272_PY2,
+};
+
+static const unsigned int soc_gpio273_py3_pins[] = {
+	TEGRA_PIN_SOC_GPIO273_PY3,
+};
+
+static const unsigned int soc_gpio274_py4_pins[] = {
+	TEGRA_PIN_SOC_GPIO274_PY4,
+};
+
+static const unsigned int soc_gpio275_py5_pins[] = {
+	TEGRA_PIN_SOC_GPIO275_PY5,
+};
+
+static const unsigned int soc_gpio276_py6_pins[] = {
+	TEGRA_PIN_SOC_GPIO276_PY6,
+};
+
+static const unsigned int soc_gpio277_py7_pins[] = {
+	TEGRA_PIN_SOC_GPIO277_PY7,
+};
+
+static const unsigned int soc_gpio278_pz0_pins[] = {
+	TEGRA_PIN_SOC_GPIO278_PZ0,
+};
+
+static const unsigned int soc_gpio279_pz1_pins[] = {
+	TEGRA_PIN_SOC_GPIO279_PZ1,
+};
+
+static const unsigned int xhalt_trig_pz2_pins[] = {
+	TEGRA_PIN_XHALT_TRIG_PZ2,
+};
+
+static const unsigned int soc_gpio281_pz3_pins[] = {
+	TEGRA_PIN_SOC_GPIO281_PZ3,
+};
+
+static const unsigned int soc_gpio282_pz4_pins[] = {
+	TEGRA_PIN_SOC_GPIO282_PZ4,
+};
+
+static const unsigned int soc_gpio283_pz5_pins[] = {
+	TEGRA_PIN_SOC_GPIO283_PZ5,
+};
+
+static const unsigned int soc_gpio284_pz6_pins[] = {
+	TEGRA_PIN_SOC_GPIO284_PZ6,
+};
+
+static const unsigned int soc_gpio285_pz7_pins[] = {
+	TEGRA_PIN_SOC_GPIO285_PZ7,
+};
+
+static const unsigned int soc_gpio286_pal0_pins[] = {
+	TEGRA_PIN_SOC_GPIO286_PAL0,
+};
+
+static const unsigned int soc_gpio287_pal1_pins[] = {
+	TEGRA_PIN_SOC_GPIO287_PAL1,
+};
+
+static const unsigned int soc_gpio288_pal2_pins[] = {
+	TEGRA_PIN_SOC_GPIO288_PAL2,
+};
+
+static const unsigned int soc_gpio00_paa0_pins[] = {
+	TEGRA_PIN_SOC_GPIO00_PAA0,
+};
+
+static const unsigned int vcomp_alert_paa1_pins[] = {
+	TEGRA_PIN_VCOMP_ALERT_PAA1,
+};
+
+static const unsigned int ao_retention_n_paa2_pins[] = {
+	TEGRA_PIN_AO_RETENTION_N_PAA2,
+};
+
+static const unsigned int batt_oc_paa3_pins[] = {
+	TEGRA_PIN_BATT_OC_PAA3,
+};
+
+static const unsigned int bootv_ctl_n_paa4_pins[] = {
+	TEGRA_PIN_BOOTV_CTL_N_PAA4,
+};
+
+static const unsigned int power_on_paa5_pins[] = {
+	TEGRA_PIN_POWER_ON_PAA5,
+};
+
+static const unsigned int hdmi_cec_paa6_pins[] = {
+	TEGRA_PIN_HDMI_CEC_PAA6,
+};
+
+static const unsigned int soc_gpio07_paa7_pins[] = {
+	TEGRA_PIN_SOC_GPIO07_PAA7,
+};
+
+static const unsigned int soc_gpio08_pbb0_pins[] = {
+	TEGRA_PIN_SOC_GPIO08_PBB0,
+};
+
+static const unsigned int soc_gpio09_pbb1_pins[] = {
+	TEGRA_PIN_SOC_GPIO09_PBB1,
+};
+
+static const unsigned int gen2_i2c_scl_pcc0_pins[] = {
+	TEGRA_PIN_GEN2_I2C_SCL_PCC0,
+};
+
+static const unsigned int gen2_i2c_sda_pcc1_pins[] = {
+	TEGRA_PIN_GEN2_I2C_SDA_PCC1,
+};
+
+static const unsigned int gen3_i2c_scl_pcc2_pins[] = {
+	TEGRA_PIN_GEN3_I2C_SCL_PCC2,
+};
+
+static const unsigned int gen3_i2c_sda_pcc3_pins[] = {
+	TEGRA_PIN_GEN3_I2C_SDA_PCC3,
+};
+
+static const unsigned int gp_pwm4_pcc4_pins[] = {
+	TEGRA_PIN_GP_PWM4_PCC4,
+};
+
+static const unsigned int uart0_tx_pcc5_pins[] = {
+	TEGRA_PIN_UART0_TX_PCC5,
+};
+
+static const unsigned int uart0_rx_pcc6_pins[] = {
+	TEGRA_PIN_UART0_RX_PCC6,
+};
+
+static const unsigned int spi2_sck_pcc7_pins[] = {
+	TEGRA_PIN_SPI2_SCK_PCC7,
+};
+
+static const unsigned int spi2_miso_pdd0_pins[] = {
+	TEGRA_PIN_SPI2_MISO_PDD0,
+};
+
+static const unsigned int spi2_mosi_pdd1_pins[] = {
+	TEGRA_PIN_SPI2_MOSI_PDD1,
+};
+
+static const unsigned int spi2_cs0_n_pdd2_pins[] = {
+	TEGRA_PIN_SPI2_CS0_N_PDD2,
+};
+
+static const unsigned int soc_gpio21_pdd3_pins[] = {
+	TEGRA_PIN_SOC_GPIO21_PDD3,
+};
+
+static const unsigned int soc_gpio22_pdd4_pins[] = {
+	TEGRA_PIN_SOC_GPIO22_PDD4,
+};
+
+static const unsigned int soc_gpio23_pdd5_pins[] = {
+	TEGRA_PIN_SOC_GPIO23_PDD5,
+};
+
+static const unsigned int soc_gpio24_pdd6_pins[] = {
+	TEGRA_PIN_SOC_GPIO24_PDD6,
+};
+
+static const unsigned int soc_gpio25_pdd7_pins[] = {
+	TEGRA_PIN_SOC_GPIO25_PDD7,
+};
+
+static const unsigned int soc_gpio26_pee0_pins[] = {
+	TEGRA_PIN_SOC_GPIO26_PEE0,
+};
+
+static const unsigned int soc_gpio27_pee1_pins[] = {
+	TEGRA_PIN_SOC_GPIO27_PEE1,
+};
+
+static const unsigned int soc_gpio28_pee2_pins[] = {
+	TEGRA_PIN_SOC_GPIO28_PEE2,
+};
+
+static const unsigned int soc_gpio29_pee3_pins[] = {
+	TEGRA_PIN_SOC_GPIO29_PEE3,
+};
+
+enum tegra_mux_dt {
+	TEGRA_MUX_DCA_VSYNC,
+	TEGRA_MUX_DCA_HSYNC,
+	TEGRA_MUX_RSVD0,
+	TEGRA_MUX_DP_AUX_CH0_HPD,
+	TEGRA_MUX_DP_AUX_CH1_HPD,
+	TEGRA_MUX_DP_AUX_CH2_HPD,
+	TEGRA_MUX_DP_AUX_CH3_HPD,
+	TEGRA_MUX_GP_PWM2,
+	TEGRA_MUX_GP_PWM3,
+	TEGRA_MUX_I2C7_CLK,
+	TEGRA_MUX_I2C7_DAT,
+	TEGRA_MUX_I2C9_CLK,
+	TEGRA_MUX_I2C9_DAT,
+	TEGRA_MUX_UARTK_CTS,
+	TEGRA_MUX_UARTK_RTS,
+	TEGRA_MUX_UARTK_RXD,
+	TEGRA_MUX_UARTK_TXD,
+	TEGRA_MUX_SPI3_CS0,
+	TEGRA_MUX_SPI3_CS3,
+	TEGRA_MUX_SPI3_DIN,
+	TEGRA_MUX_SPI3_DOUT,
+	TEGRA_MUX_SPI3_SCK,
+	TEGRA_MUX_UARTF_CTS,
+	TEGRA_MUX_UARTF_RTS,
+	TEGRA_MUX_UARTF_RXD,
+	TEGRA_MUX_UARTF_TXD,
+	TEGRA_MUX_SPI1_CS0,
+	TEGRA_MUX_SPI1_CS1,
+	TEGRA_MUX_SPI1_DIN,
+	TEGRA_MUX_SPI1_DOUT,
+	TEGRA_MUX_SPI1_SCK,
+	TEGRA_MUX_EXTPERIPH2_CLK,
+	TEGRA_MUX_EXTPERIPH1_CLK,
+	TEGRA_MUX_I2C12_CLK,
+	TEGRA_MUX_I2C12_DAT,
+	TEGRA_MUX_NV_THERM_FAN_TACH0,
+	TEGRA_MUX_GP_PWM9,
+	TEGRA_MUX_UARTJ_CTS,
+	TEGRA_MUX_UARTJ_RTS,
+	TEGRA_MUX_UARTJ_RXD,
+	TEGRA_MUX_UARTJ_TXD,
+	TEGRA_MUX_I2C0_CLK,
+	TEGRA_MUX_I2C0_DAT,
+	TEGRA_MUX_I2C1_CLK,
+	TEGRA_MUX_I2C1_DAT,
+	TEGRA_MUX_I2S2_LRCK,
+	TEGRA_MUX_I2S2_SCLK,
+	TEGRA_MUX_I2S2_SDATA_OUT,
+	TEGRA_MUX_I2S2_SDATA_IN,
+	TEGRA_MUX_GP_PWM10,
+	TEGRA_MUX_UARTE_CTS,
+	TEGRA_MUX_UARTE_RTS,
+	TEGRA_MUX_UARTE_RXD,
+	TEGRA_MUX_UARTE_TXD,
+	TEGRA_MUX_I2C5_DAT,
+	TEGRA_MUX_I2C5_CLK,
+	TEGRA_MUX_I2S6_SDATA_IN,
+	TEGRA_MUX_I2S6_SDATA_OUT,
+	TEGRA_MUX_I2S6_LRCK,
+	TEGRA_MUX_I2S6_SCLK,
+	TEGRA_MUX_I2S4_SDATA_OUT,
+	TEGRA_MUX_I2S4_SCLK,
+	TEGRA_MUX_I2S4_SDATA_IN,
+	TEGRA_MUX_I2S4_LRCK,
+	TEGRA_MUX_SPI5_CS0,
+	TEGRA_MUX_SPI5_DIN,
+	TEGRA_MUX_SPI5_DOUT,
+	TEGRA_MUX_SPI5_SCK,
+	TEGRA_MUX_AUD_MCLK,
+	TEGRA_MUX_I2S1_SCLK,
+	TEGRA_MUX_I2S1_SDATA_IN,
+	TEGRA_MUX_I2S1_SDATA_OUT,
+	TEGRA_MUX_I2S1_LRCK,
+	TEGRA_MUX_I2C11_CLK,
+	TEGRA_MUX_I2C11_DAT,
+	TEGRA_MUX_XHALT_TRIG,
+	TEGRA_MUX_GP_PWM1,
+	TEGRA_MUX_GP_PWM6,
+	TEGRA_MUX_GP_PWM7,
+	TEGRA_MUX_GP_PWM8,
+	TEGRA_MUX_UFS0,
+	TEGRA_MUX_PE1_CLKREQ_L,
+	TEGRA_MUX_PE1_RST_L,
+	TEGRA_MUX_PE2_RST_L,
+	TEGRA_MUX_PE2_CLKREQ_L,
+	TEGRA_MUX_PE3_CLKREQ_L,
+	TEGRA_MUX_PE3_RST_L,
+	TEGRA_MUX_SGMII0_SMA_MDIO,
+	TEGRA_MUX_SGMII0_SMA_MDC,
+	TEGRA_MUX_USB_VBUS_EN0,
+	TEGRA_MUX_USB_VBUS_EN1,
+	TEGRA_MUX_ETH1_MDIO,
+	TEGRA_MUX_PE4_CLKREQ_L,
+	TEGRA_MUX_PE4_RST_L,
+	TEGRA_MUX_PE5_CLKREQ_L,
+	TEGRA_MUX_PE5_RST_L,
+	TEGRA_MUX_ETH0_MDIO,
+	TEGRA_MUX_ETH0_MDC,
+	TEGRA_MUX_ETH1_MDC,
+	TEGRA_MUX_ETH2_MDIO,
+	TEGRA_MUX_ETH2_MDC,
+	TEGRA_MUX_ETH3_MDIO,
+	TEGRA_MUX_ETH3_MDC,
+	TEGRA_MUX_QSPI0_CS_N,
+	TEGRA_MUX_QSPI0_IO0,
+	TEGRA_MUX_QSPI0_IO1,
+	TEGRA_MUX_QSPI0_IO2,
+	TEGRA_MUX_QSPI0_IO3,
+	TEGRA_MUX_QSPI0_SCK,
+	TEGRA_MUX_SDMMC1_CLK,
+	TEGRA_MUX_SDMMC1_CMD,
+	TEGRA_MUX_SDMMC1_COMP,
+	TEGRA_MUX_SDMMC1_DAT3,
+	TEGRA_MUX_SDMMC1_DAT2,
+	TEGRA_MUX_SDMMC1_DAT1,
+	TEGRA_MUX_SDMMC1_DAT0,
+	TEGRA_MUX_QSPI3_SCK,
+	TEGRA_MUX_QSPI3_CS0,
+	TEGRA_MUX_QSPI3_IO0,
+	TEGRA_MUX_QSPI3_IO1,
+	TEGRA_MUX_DCB_VSYNC,
+	TEGRA_MUX_DCB_HSYNC,
+	TEGRA_MUX_DSA_LSPII,
+	TEGRA_MUX_DCE_VSYNC,
+	TEGRA_MUX_DCE_HSYNC,
+	TEGRA_MUX_DCH_VSYNC,
+	TEGRA_MUX_DCH_HSYNC,
+	TEGRA_MUX_BL_EN,
+	TEGRA_MUX_BL_PWM_DIM0,
+	TEGRA_MUX_RSVD1,
+	TEGRA_MUX_SOC_THERM_OC3,
+	TEGRA_MUX_I2S5_SCLK,
+	TEGRA_MUX_I2S5_SDATA_IN,
+	TEGRA_MUX_EXTPERIPH3_CLK,
+	TEGRA_MUX_EXTPERIPH4_CLK,
+	TEGRA_MUX_I2S5_SDATA_OUT,
+	TEGRA_MUX_I2S5_LRCK,
+	TEGRA_MUX_SDMMC1_CD,
+	TEGRA_MUX_I2S7_SDATA_IN,
+	TEGRA_MUX_SPI4_SCK,
+	TEGRA_MUX_SPI4_DIN,
+	TEGRA_MUX_SPI4_DOUT,
+	TEGRA_MUX_SPI4_CS0,
+	TEGRA_MUX_SPI4_CS1,
+	TEGRA_MUX_GP_PWM5,
+	TEGRA_MUX_I2C14_CLK,
+	TEGRA_MUX_I2C14_DAT,
+	TEGRA_MUX_I2S8_SCLK,
+	TEGRA_MUX_I2S8_SDATA_OUT,
+	TEGRA_MUX_I2S8_LRCK,
+	TEGRA_MUX_I2S8_SDATA_IN,
+	TEGRA_MUX_I2C16_CLK,
+	TEGRA_MUX_I2C16_DAT,
+	TEGRA_MUX_I2S3_SCLK,
+	TEGRA_MUX_I2S3_SDATA_OUT,
+	TEGRA_MUX_I2S3_SDATA_IN,
+	TEGRA_MUX_I2S3_LRCK,
+	TEGRA_MUX_PM_TRIG1,
+	TEGRA_MUX_PM_TRIG0,
+	TEGRA_MUX_QSPI2_SCK,
+	TEGRA_MUX_QSPI2_CS0,
+	TEGRA_MUX_QSPI2_IO0,
+	TEGRA_MUX_QSPI2_IO1,
+	TEGRA_MUX_DCC_VSYNC,
+	TEGRA_MUX_DCC_HSYNC,
+	TEGRA_MUX_RSVD2,
+	TEGRA_MUX_DCF_VSYNC,
+	TEGRA_MUX_DCF_HSYNC,
+	TEGRA_MUX_SOUNDWIRE1_CLK,
+	TEGRA_MUX_SOUNDWIRE1_DAT0,
+	TEGRA_MUX_SOUNDWIRE1_DAT1,
+	TEGRA_MUX_SOUNDWIRE1_DAT2,
+	TEGRA_MUX_DMIC2_CLK,
+	TEGRA_MUX_DMIC2_DAT,
+	TEGRA_MUX_NV_THERM_FAN_TACH1,
+	TEGRA_MUX_I2C15_CLK,
+	TEGRA_MUX_I2C15_DAT,
+	TEGRA_MUX_I2S7_LRCK,
+	TEGRA_MUX_CCLA_LA_TRIGGER_MUX,
+	TEGRA_MUX_I2S7_SCLK,
+	TEGRA_MUX_I2S7_SDATA_OUT,
+	TEGRA_MUX_DMIC1_DAT,
+	TEGRA_MUX_DMIC1_CLK,
+	TEGRA_MUX_DCD_VSYNC,
+	TEGRA_MUX_DCD_HSYNC,
+	TEGRA_MUX_RSVD3,
+	TEGRA_MUX_DCG_VSYNC,
+	TEGRA_MUX_DCG_HSYNC,
+	TEGRA_MUX_DSPK1_CLK,
+	TEGRA_MUX_DSPK1_DAT,
+	TEGRA_MUX_SOC_THERM_OC2,
+	TEGRA_MUX_ISTCTRL_IST_DONE_N,
+	TEGRA_MUX_SOC_THERM_OC1,
+	TEGRA_MUX_TSC_EDGE_OUT0C,
+	TEGRA_MUX_TSC_EDGE_OUT0D,
+	TEGRA_MUX_TSC_EDGE_OUT0A,
+	TEGRA_MUX_TSC_EDGE_OUT0B,
+	TEGRA_MUX_TOUCH_CLK,
+	TEGRA_MUX_HDMI_CEC,
+	TEGRA_MUX_I2C2_CLK,
+	TEGRA_MUX_I2C2_DAT,
+	TEGRA_MUX_I2C3_CLK,
+	TEGRA_MUX_I2C3_DAT,
+	TEGRA_MUX_GP_PWM4,
+	TEGRA_MUX_UARTA_TXD,
+	TEGRA_MUX_UARTA_RXD,
+	TEGRA_MUX_SPI2_SCK,
+	TEGRA_MUX_SPI2_DIN,
+	TEGRA_MUX_SPI2_DOUT,
+	TEGRA_MUX_SPI2_CS0,
+	TEGRA_MUX_TSC_SYNC1,
+	TEGRA_MUX_TSC_EDGE_OUT3,
+	TEGRA_MUX_TSC_EDGE_OUT0,
+	TEGRA_MUX_TSC_EDGE_OUT1,
+	TEGRA_MUX_TSC_SYNC0,
+	TEGRA_MUX_SOUNDWIRE0_CLK,
+	TEGRA_MUX_SOUNDWIRE0_DAT0,
+	TEGRA_MUX_L0L1_RST_OUT_N,
+	TEGRA_MUX_L2_RST_OUT_N,
+	TEGRA_MUX_UARTL_TXD,
+	TEGRA_MUX_UARTL_RXD,
+	TEGRA_MUX_I2S9_SCLK,
+	TEGRA_MUX_I2S9_SDATA_OUT,
+	TEGRA_MUX_I2S9_SDATA_IN,
+	TEGRA_MUX_I2S9_LRCK,
+	TEGRA_MUX_DMIC5_DAT,
+	TEGRA_MUX_DMIC5_CLK,
+	TEGRA_MUX_TSC_EDGE_OUT2,
+};
+
+/* Make list of each function name */
+#define TEGRA_PIN_FUNCTION(lid) #lid
+
+static const char * const tegra264_functions[] = {
+	TEGRA_PIN_FUNCTION(dca_vsync),
+	TEGRA_PIN_FUNCTION(dca_hsync),
+	TEGRA_PIN_FUNCTION(rsvd0),
+	TEGRA_PIN_FUNCTION(dp_aux_ch0_hpd),
+	TEGRA_PIN_FUNCTION(dp_aux_ch1_hpd),
+	TEGRA_PIN_FUNCTION(dp_aux_ch2_hpd),
+	TEGRA_PIN_FUNCTION(dp_aux_ch3_hpd),
+	TEGRA_PIN_FUNCTION(gp_pwm2),
+	TEGRA_PIN_FUNCTION(gp_pwm3),
+	TEGRA_PIN_FUNCTION(i2c7_clk),
+	TEGRA_PIN_FUNCTION(i2c7_dat),
+	TEGRA_PIN_FUNCTION(i2c9_clk),
+	TEGRA_PIN_FUNCTION(i2c9_dat),
+	TEGRA_PIN_FUNCTION(uartk_cts),
+	TEGRA_PIN_FUNCTION(uartk_rts),
+	TEGRA_PIN_FUNCTION(uartk_rxd),
+	TEGRA_PIN_FUNCTION(uartk_txd),
+	TEGRA_PIN_FUNCTION(spi3_cs0),
+	TEGRA_PIN_FUNCTION(spi3_cs3),
+	TEGRA_PIN_FUNCTION(spi3_din),
+	TEGRA_PIN_FUNCTION(spi3_dout),
+	TEGRA_PIN_FUNCTION(spi3_sck),
+	TEGRA_PIN_FUNCTION(uartf_cts),
+	TEGRA_PIN_FUNCTION(uartf_rts),
+	TEGRA_PIN_FUNCTION(uartf_rxd),
+	TEGRA_PIN_FUNCTION(uartf_txd),
+	TEGRA_PIN_FUNCTION(spi1_cs0),
+	TEGRA_PIN_FUNCTION(spi1_cs1),
+	TEGRA_PIN_FUNCTION(spi1_din),
+	TEGRA_PIN_FUNCTION(spi1_dout),
+	TEGRA_PIN_FUNCTION(spi1_sck),
+	TEGRA_PIN_FUNCTION(extperiph2_clk),
+	TEGRA_PIN_FUNCTION(extperiph1_clk),
+	TEGRA_PIN_FUNCTION(i2c12_clk),
+	TEGRA_PIN_FUNCTION(i2c12_dat),
+	TEGRA_PIN_FUNCTION(nv_therm_fan_tach0),
+	TEGRA_PIN_FUNCTION(gp_pwm9),
+	TEGRA_PIN_FUNCTION(uartj_cts),
+	TEGRA_PIN_FUNCTION(uartj_rts),
+	TEGRA_PIN_FUNCTION(uartj_rxd),
+	TEGRA_PIN_FUNCTION(uartj_txd),
+	TEGRA_PIN_FUNCTION(i2c0_clk),
+	TEGRA_PIN_FUNCTION(i2c0_dat),
+	TEGRA_PIN_FUNCTION(i2c1_clk),
+	TEGRA_PIN_FUNCTION(i2c1_dat),
+	TEGRA_PIN_FUNCTION(i2s2_lrck),
+	TEGRA_PIN_FUNCTION(i2s2_sclk),
+	TEGRA_PIN_FUNCTION(i2s2_sdata_out),
+	TEGRA_PIN_FUNCTION(i2s2_sdata_in),
+	TEGRA_PIN_FUNCTION(gp_pwm10),
+	TEGRA_PIN_FUNCTION(uarte_cts),
+	TEGRA_PIN_FUNCTION(uarte_rts),
+	TEGRA_PIN_FUNCTION(uarte_rxd),
+	TEGRA_PIN_FUNCTION(uarte_txd),
+	TEGRA_PIN_FUNCTION(i2c5_dat),
+	TEGRA_PIN_FUNCTION(i2c5_clk),
+	TEGRA_PIN_FUNCTION(i2s6_sdata_in),
+	TEGRA_PIN_FUNCTION(i2s6_sdata_out),
+	TEGRA_PIN_FUNCTION(i2s6_lrck),
+	TEGRA_PIN_FUNCTION(i2s6_sclk),
+	TEGRA_PIN_FUNCTION(i2s4_sdata_out),
+	TEGRA_PIN_FUNCTION(i2s4_sclk),
+	TEGRA_PIN_FUNCTION(i2s4_sdata_in),
+	TEGRA_PIN_FUNCTION(i2s4_lrck),
+	TEGRA_PIN_FUNCTION(spi5_cs0),
+	TEGRA_PIN_FUNCTION(spi5_din),
+	TEGRA_PIN_FUNCTION(spi5_dout),
+	TEGRA_PIN_FUNCTION(spi5_sck),
+	TEGRA_PIN_FUNCTION(aud_mclk),
+	TEGRA_PIN_FUNCTION(i2s1_sclk),
+	TEGRA_PIN_FUNCTION(i2s1_sdata_in),
+	TEGRA_PIN_FUNCTION(i2s1_sdata_out),
+	TEGRA_PIN_FUNCTION(i2s1_lrck),
+	TEGRA_PIN_FUNCTION(i2c11_clk),
+	TEGRA_PIN_FUNCTION(i2c11_dat),
+	TEGRA_PIN_FUNCTION(xhalt_trig),
+	TEGRA_PIN_FUNCTION(gp_pwm1),
+	TEGRA_PIN_FUNCTION(gp_pwm6),
+	TEGRA_PIN_FUNCTION(gp_pwm7),
+	TEGRA_PIN_FUNCTION(gp_pwm8),
+	TEGRA_PIN_FUNCTION(ufs0),
+	TEGRA_PIN_FUNCTION(pe1_clkreq_l),
+	TEGRA_PIN_FUNCTION(pe1_rst_l),
+	TEGRA_PIN_FUNCTION(pe2_rst_l),
+	TEGRA_PIN_FUNCTION(pe2_clkreq_l),
+	TEGRA_PIN_FUNCTION(pe3_clkreq_l),
+	TEGRA_PIN_FUNCTION(pe3_rst_l),
+	TEGRA_PIN_FUNCTION(sgmii0_sma_mdio),
+	TEGRA_PIN_FUNCTION(sgmii0_sma_mdc),
+	TEGRA_PIN_FUNCTION(usb_vbus_en0),
+	TEGRA_PIN_FUNCTION(usb_vbus_en1),
+	TEGRA_PIN_FUNCTION(eth1_mdio),
+	TEGRA_PIN_FUNCTION(pe4_clkreq_l),
+	TEGRA_PIN_FUNCTION(pe4_rst_l),
+	TEGRA_PIN_FUNCTION(pe5_clkreq_l),
+	TEGRA_PIN_FUNCTION(pe5_rst_l),
+	TEGRA_PIN_FUNCTION(eth0_mdio),
+	TEGRA_PIN_FUNCTION(eth0_mdc),
+	TEGRA_PIN_FUNCTION(eth1_mdc),
+	TEGRA_PIN_FUNCTION(eth2_mdio),
+	TEGRA_PIN_FUNCTION(eth2_mdc),
+	TEGRA_PIN_FUNCTION(eth3_mdio),
+	TEGRA_PIN_FUNCTION(eth3_mdc),
+	TEGRA_PIN_FUNCTION(qspi0_cs_n),
+	TEGRA_PIN_FUNCTION(qspi0_io0),
+	TEGRA_PIN_FUNCTION(qspi0_io1),
+	TEGRA_PIN_FUNCTION(qspi0_io2),
+	TEGRA_PIN_FUNCTION(qspi0_io3),
+	TEGRA_PIN_FUNCTION(qspi0_sck),
+	TEGRA_PIN_FUNCTION(sdmmc1_clk),
+	TEGRA_PIN_FUNCTION(sdmmc1_cmd),
+	TEGRA_PIN_FUNCTION(sdmmc1_comp),
+	TEGRA_PIN_FUNCTION(sdmmc1_dat3),
+	TEGRA_PIN_FUNCTION(sdmmc1_dat2),
+	TEGRA_PIN_FUNCTION(sdmmc1_dat1),
+	TEGRA_PIN_FUNCTION(sdmmc1_dat0),
+	TEGRA_PIN_FUNCTION(qspi3_sck),
+	TEGRA_PIN_FUNCTION(qspi3_cs0),
+	TEGRA_PIN_FUNCTION(qspi3_io0),
+	TEGRA_PIN_FUNCTION(qspi3_io1),
+	TEGRA_PIN_FUNCTION(dcb_vsync),
+	TEGRA_PIN_FUNCTION(dcb_hsync),
+	TEGRA_PIN_FUNCTION(dsa_lspii),
+	TEGRA_PIN_FUNCTION(dce_vsync),
+	TEGRA_PIN_FUNCTION(dce_hsync),
+	TEGRA_PIN_FUNCTION(dch_vsync),
+	TEGRA_PIN_FUNCTION(dch_hsync),
+	TEGRA_PIN_FUNCTION(bl_en),
+	TEGRA_PIN_FUNCTION(bl_pwm_dim0),
+	TEGRA_PIN_FUNCTION(rsvd1),
+	TEGRA_PIN_FUNCTION(soc_therm_oc3),
+	TEGRA_PIN_FUNCTION(i2s5_sclk),
+	TEGRA_PIN_FUNCTION(i2s5_sdata_in),
+	TEGRA_PIN_FUNCTION(extperiph3_clk),
+	TEGRA_PIN_FUNCTION(extperiph4_clk),
+	TEGRA_PIN_FUNCTION(i2s5_sdata_out),
+	TEGRA_PIN_FUNCTION(i2s5_lrck),
+	TEGRA_PIN_FUNCTION(sdmmc1_cd),
+	TEGRA_PIN_FUNCTION(i2s7_sdata_in),
+	TEGRA_PIN_FUNCTION(spi4_sck),
+	TEGRA_PIN_FUNCTION(spi4_din),
+	TEGRA_PIN_FUNCTION(spi4_dout),
+	TEGRA_PIN_FUNCTION(spi4_cs0),
+	TEGRA_PIN_FUNCTION(spi4_cs1),
+	TEGRA_PIN_FUNCTION(gp_pwm5),
+	TEGRA_PIN_FUNCTION(i2c14_clk),
+	TEGRA_PIN_FUNCTION(i2c14_dat),
+	TEGRA_PIN_FUNCTION(i2s8_sclk),
+	TEGRA_PIN_FUNCTION(i2s8_sdata_out),
+	TEGRA_PIN_FUNCTION(i2s8_lrck),
+	TEGRA_PIN_FUNCTION(i2s8_sdata_in),
+	TEGRA_PIN_FUNCTION(i2c16_clk),
+	TEGRA_PIN_FUNCTION(i2c16_dat),
+	TEGRA_PIN_FUNCTION(i2s3_sclk),
+	TEGRA_PIN_FUNCTION(i2s3_sdata_out),
+	TEGRA_PIN_FUNCTION(i2s3_sdata_in),
+	TEGRA_PIN_FUNCTION(i2s3_lrck),
+	TEGRA_PIN_FUNCTION(pm_trig1),
+	TEGRA_PIN_FUNCTION(pm_trig0),
+	TEGRA_PIN_FUNCTION(qspi2_sck),
+	TEGRA_PIN_FUNCTION(qspi2_cs0),
+	TEGRA_PIN_FUNCTION(qspi2_io0),
+	TEGRA_PIN_FUNCTION(qspi2_io1),
+	TEGRA_PIN_FUNCTION(dcc_vsync),
+	TEGRA_PIN_FUNCTION(dcc_hsync),
+	TEGRA_PIN_FUNCTION(rsvd2),
+	TEGRA_PIN_FUNCTION(dcf_vsync),
+	TEGRA_PIN_FUNCTION(dcf_hsync),
+	TEGRA_PIN_FUNCTION(soundwire1_clk),
+	TEGRA_PIN_FUNCTION(soundwire1_dat0),
+	TEGRA_PIN_FUNCTION(soundwire1_dat1),
+	TEGRA_PIN_FUNCTION(soundwire1_dat2),
+	TEGRA_PIN_FUNCTION(dmic2_clk),
+	TEGRA_PIN_FUNCTION(dmic2_dat),
+	TEGRA_PIN_FUNCTION(nv_therm_fan_tach1),
+	TEGRA_PIN_FUNCTION(i2c15_clk),
+	TEGRA_PIN_FUNCTION(i2c15_dat),
+	TEGRA_PIN_FUNCTION(i2s7_lrck),
+	TEGRA_PIN_FUNCTION(ccla_la_trigger_mux),
+	TEGRA_PIN_FUNCTION(i2s7_sclk),
+	TEGRA_PIN_FUNCTION(i2s7_sdata_out),
+	TEGRA_PIN_FUNCTION(dmic1_dat),
+	TEGRA_PIN_FUNCTION(dmic1_clk),
+	TEGRA_PIN_FUNCTION(dcd_vsync),
+	TEGRA_PIN_FUNCTION(dcd_hsync),
+	TEGRA_PIN_FUNCTION(rsvd3),
+	TEGRA_PIN_FUNCTION(dcg_vsync),
+	TEGRA_PIN_FUNCTION(dcg_hsync),
+	TEGRA_PIN_FUNCTION(dspk1_clk),
+	TEGRA_PIN_FUNCTION(dspk1_dat),
+	TEGRA_PIN_FUNCTION(soc_therm_oc2),
+	TEGRA_PIN_FUNCTION(istctrl_ist_done_n),
+	TEGRA_PIN_FUNCTION(soc_therm_oc1),
+	TEGRA_PIN_FUNCTION(tsc_edge_out0c),
+	TEGRA_PIN_FUNCTION(tsc_edge_out0d),
+	TEGRA_PIN_FUNCTION(tsc_edge_out0a),
+	TEGRA_PIN_FUNCTION(tsc_edge_out0b),
+	TEGRA_PIN_FUNCTION(touch_clk),
+	TEGRA_PIN_FUNCTION(hdmi_cec),
+	TEGRA_PIN_FUNCTION(i2c2_clk),
+	TEGRA_PIN_FUNCTION(i2c2_dat),
+	TEGRA_PIN_FUNCTION(i2c3_clk),
+	TEGRA_PIN_FUNCTION(i2c3_dat),
+	TEGRA_PIN_FUNCTION(gp_pwm4),
+	TEGRA_PIN_FUNCTION(uarta_txd),
+	TEGRA_PIN_FUNCTION(uarta_rxd),
+	TEGRA_PIN_FUNCTION(spi2_sck),
+	TEGRA_PIN_FUNCTION(spi2_din),
+	TEGRA_PIN_FUNCTION(spi2_dout),
+	TEGRA_PIN_FUNCTION(spi2_cs0),
+	TEGRA_PIN_FUNCTION(tsc_sync1),
+	TEGRA_PIN_FUNCTION(tsc_edge_out3),
+	TEGRA_PIN_FUNCTION(tsc_edge_out0),
+	TEGRA_PIN_FUNCTION(tsc_edge_out1),
+	TEGRA_PIN_FUNCTION(tsc_sync0),
+	TEGRA_PIN_FUNCTION(soundwire0_clk),
+	TEGRA_PIN_FUNCTION(soundwire0_dat0),
+	TEGRA_PIN_FUNCTION(l0l1_rst_out_n),
+	TEGRA_PIN_FUNCTION(l2_rst_out_n),
+	TEGRA_PIN_FUNCTION(uartl_txd),
+	TEGRA_PIN_FUNCTION(uartl_rxd),
+	TEGRA_PIN_FUNCTION(i2s9_sclk),
+	TEGRA_PIN_FUNCTION(i2s9_sdata_out),
+	TEGRA_PIN_FUNCTION(i2s9_sdata_in),
+	TEGRA_PIN_FUNCTION(i2s9_lrck),
+	TEGRA_PIN_FUNCTION(dmic5_dat),
+	TEGRA_PIN_FUNCTION(dmic5_clk),
+	TEGRA_PIN_FUNCTION(tsc_edge_out2),
+};
+
+#define PINGROUP_REG_Y(r) ((r))
+#define PINGROUP_REG_N(r) -1
+
+#define DRV_PINGROUP_Y(r) ((r))
+
+#define DRV_PINGROUP_ENTRY_N					\
+		.drv_reg = -1,					\
+		.drv_bank = -1,					\
+		.drvdn_bit = -1,				\
+		.drvup_bit = -1,				\
+		.slwr_bit = -1,					\
+		.slwf_bit = -1
+
+#define DRV_PINGROUP_ENTRY_Y(r, drvdn_b, drvdn_w, drvup_b,	\
+			     drvup_w, slwr_b, slwr_w, slwf_b,	\
+			     slwf_w, bank)			\
+		.drv_reg = DRV_PINGROUP_Y(r),			\
+		.drv_bank = bank,				\
+		.drvdn_bit = drvdn_b,				\
+		.drvdn_width = drvdn_w,				\
+		.drvup_bit = drvup_b,				\
+		.drvup_width = drvup_w,				\
+		.slwr_bit = slwr_b,				\
+		.slwr_width = slwr_w,				\
+		.slwf_bit = slwf_b,				\
+		.slwf_width = slwf_w
+
+#define PIN_PINGROUP_ENTRY_N					\
+		.mux_reg = -1,					\
+		.pupd_reg = -1,					\
+		.tri_reg = -1,					\
+		.einput_bit = -1,				\
+		.e_io_hv_bit = -1,				\
+		.odrain_bit = -1,				\
+		.lock_bit = -1,					\
+		.parked_bit = -1,				\
+		.lpmd_bit = -1,					\
+		.drvtype_bit = -1,				\
+		.lpdr_bit = -1,					\
+		.pbias_buf_bit = -1,				\
+		.preemp_bit = -1,				\
+		.rfu_in_bit = -1
+
+#define PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_io_hv, e_lpbk, e_input,	\
+				e_lpdr, e_pbias_buf, gpio_sfio_sel,	\
+				schmitt_b)				\
+		.mux_reg = PINGROUP_REG_Y(r),			\
+		.lpmd_bit = -1,					\
+		.lock_bit = -1,					\
+		.hsm_bit = -1,					\
+		.mux_bank = bank,				\
+		.mux_bit = 0,					\
+		.pupd_reg = PINGROUP_REG_##pupd(r),		\
+		.pupd_bank = bank,				\
+		.pupd_bit = 2,					\
+		.tri_reg = PINGROUP_REG_Y(r),			\
+		.tri_bank = bank,				\
+		.tri_bit = 4,					\
+		.einput_bit = e_input,				\
+		.sfsel_bit = gpio_sfio_sel,			\
+		.schmitt_bit = schmitt_b,			\
+		.drvtype_bit = 13,				\
+		.lpdr_bit = e_lpdr,
+
+#define drive_eth1_mdio_pe0 DRV_PINGROUP_ENTRY_Y(0x4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l4_clkreq_n_pd0 DRV_PINGROUP_ENTRY_Y(0xc, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l4_rst_n_pd1 DRV_PINGROUP_ENTRY_Y(0x14, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l5_clkreq_n_pd2 DRV_PINGROUP_ENTRY_Y(0x1c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l5_rst_n_pd3 DRV_PINGROUP_ENTRY_Y(0x24, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_eth0_mdio_pd4 DRV_PINGROUP_ENTRY_Y(0x2c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_eth0_mdc_pd5 DRV_PINGROUP_ENTRY_Y(0x34, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_eth1_mdc_pe1 DRV_PINGROUP_ENTRY_Y(0x3c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_eth2_mdio_pe2 DRV_PINGROUP_ENTRY_Y(0x44, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_eth2_mdc_pe3 DRV_PINGROUP_ENTRY_Y(0x4c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_eth3_mdio_pd6 DRV_PINGROUP_ENTRY_Y(0x54, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_eth3_mdc_pd7 DRV_PINGROUP_ENTRY_Y(0x5c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l1_clkreq_n_pb0 DRV_PINGROUP_ENTRY_Y(0x2004, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l1_rst_n_pb1 DRV_PINGROUP_ENTRY_Y(0x200c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_wake_n_pc2 DRV_PINGROUP_ENTRY_Y(0x2014, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l2_rst_n_pb3 DRV_PINGROUP_ENTRY_Y(0x201c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l2_clkreq_n_pb2 DRV_PINGROUP_ENTRY_Y(0x2024, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l3_clkreq_n_pb4 DRV_PINGROUP_ENTRY_Y(0x202c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pex_l3_rst_n_pb5 DRV_PINGROUP_ENTRY_Y(0x2034, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_sgmii0_sma_mdio_pc0 DRV_PINGROUP_ENTRY_Y(0x203c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_sgmii0_sma_mdc_pc1 DRV_PINGROUP_ENTRY_Y(0x2044, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio113_pb6 DRV_PINGROUP_ENTRY_Y(0x204c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio114_pb7 DRV_PINGROUP_ENTRY_Y(0x2054, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pwm1_pa0 DRV_PINGROUP_ENTRY_Y(0x3004, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pwm6_pa1 DRV_PINGROUP_ENTRY_Y(0x300c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pwm7_pa2 DRV_PINGROUP_ENTRY_Y(0x3014, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pwm8_pa3 DRV_PINGROUP_ENTRY_Y(0x301c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_ufs0_ref_clk_pa4 DRV_PINGROUP_ENTRY_Y(0x3024, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_ufs0_rst_n_pa5 DRV_PINGROUP_ENTRY_Y(0x302c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+
+#define drive_cpu_pwr_req_ph0 DRV_PINGROUP_ENTRY_Y(0x4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gpu_pwr_req_ph1 DRV_PINGROUP_ENTRY_Y(0xc, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart10_cts_n_ph5 DRV_PINGROUP_ENTRY_Y(0x14, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart10_rts_n_ph4 DRV_PINGROUP_ENTRY_Y(0x1c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart10_rx_ph3 DRV_PINGROUP_ENTRY_Y(0x24, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart10_tx_ph2 DRV_PINGROUP_ENTRY_Y(0x2c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi3_cs0_pj1 DRV_PINGROUP_ENTRY_Y(0x34, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi3_cs3_pj2 DRV_PINGROUP_ENTRY_Y(0x3c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi3_miso_ph7 DRV_PINGROUP_ENTRY_Y(0x44, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi3_mosi_pj0 DRV_PINGROUP_ENTRY_Y(0x4c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi3_sck_ph6 DRV_PINGROUP_ENTRY_Y(0x54, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart5_cts_n_pj6 DRV_PINGROUP_ENTRY_Y(0x5c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart5_rts_n_pj5 DRV_PINGROUP_ENTRY_Y(0x64, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart5_rx_pj4 DRV_PINGROUP_ENTRY_Y(0x6c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart5_tx_pj3 DRV_PINGROUP_ENTRY_Y(0x74, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi1_cs0_pk2 DRV_PINGROUP_ENTRY_Y(0x7c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi1_cs1_pk3 DRV_PINGROUP_ENTRY_Y(0x84, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi1_miso_pk0 DRV_PINGROUP_ENTRY_Y(0x8c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi1_mosi_pk1 DRV_PINGROUP_ENTRY_Y(0x94, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi1_sck_pj7 DRV_PINGROUP_ENTRY_Y(0x9c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_extperiph2_clk_pk5 DRV_PINGROUP_ENTRY_Y(0xa4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_extperiph1_clk_pk4 DRV_PINGROUP_ENTRY_Y(0xac, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen12_i2c_scl_pk6 DRV_PINGROUP_ENTRY_Y(0xb4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen12_i2c_sda_pk7 DRV_PINGROUP_ENTRY_Y(0xbc, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio124_pl0 DRV_PINGROUP_ENTRY_Y(0x1004, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio125_pl1 DRV_PINGROUP_ENTRY_Y(0x100c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_fan_tach0_pl2 DRV_PINGROUP_ENTRY_Y(0x1014, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio127_pl3 DRV_PINGROUP_ENTRY_Y(0x101c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio128_pl4 DRV_PINGROUP_ENTRY_Y(0x1024, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio129_pl5 DRV_PINGROUP_ENTRY_Y(0x102c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio130_pl6 DRV_PINGROUP_ENTRY_Y(0x1034, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio131_pl7 DRV_PINGROUP_ENTRY_Y(0x103c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gp_pwm9_pm0 DRV_PINGROUP_ENTRY_Y(0x1044, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio133_pm1 DRV_PINGROUP_ENTRY_Y(0x104c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart9_cts_n_pm5 DRV_PINGROUP_ENTRY_Y(0x1054, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart9_rts_n_pm4 DRV_PINGROUP_ENTRY_Y(0x105c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart9_rx_pm3 DRV_PINGROUP_ENTRY_Y(0x1064, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart9_tx_pm2 DRV_PINGROUP_ENTRY_Y(0x106c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_comp DRV_PINGROUP_ENTRY_N
+#define drive_sdmmc1_clk_px0 DRV_PINGROUP_ENTRY_Y(0x2004, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_cmd_px1 DRV_PINGROUP_ENTRY_Y(0x200c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_dat3_px5 DRV_PINGROUP_ENTRY_Y(0x201c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_dat2_px4 DRV_PINGROUP_ENTRY_Y(0x2024, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_dat1_px3 DRV_PINGROUP_ENTRY_Y(0x202c, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_sdmmc1_dat0_px2 DRV_PINGROUP_ENTRY_Y(0x2034, 28, 2, 30, 2, -1, -1, -1, -1, 0)
+#define drive_qspi0_cs_n_pt1 DRV_PINGROUP_ENTRY_Y(0x3004, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_qspi0_io0_pt2 DRV_PINGROUP_ENTRY_Y(0x300c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_qspi0_io1_pt3 DRV_PINGROUP_ENTRY_Y(0x3014, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_qspi0_io2_pt4 DRV_PINGROUP_ENTRY_Y(0x301c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_qspi0_io3_pt5 DRV_PINGROUP_ENTRY_Y(0x3024, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_qspi0_sck_pt0 DRV_PINGROUP_ENTRY_Y(0x302c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio192_pt6 DRV_PINGROUP_ENTRY_Y(0x3034, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio138_pp0 DRV_PINGROUP_ENTRY_Y(0x5004, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio139_pp1 DRV_PINGROUP_ENTRY_Y(0x500c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap6_din_pp4 DRV_PINGROUP_ENTRY_Y(0x5014, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap6_dout_pp3 DRV_PINGROUP_ENTRY_Y(0x501c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap6_fs_pp5 DRV_PINGROUP_ENTRY_Y(0x5024, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap6_sclk_pp2 DRV_PINGROUP_ENTRY_Y(0x502c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap4_dout_pp7 DRV_PINGROUP_ENTRY_Y(0x5034, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap4_sclk_pp6 DRV_PINGROUP_ENTRY_Y(0x503c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap4_din_pq0 DRV_PINGROUP_ENTRY_Y(0x5044, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap4_fs_pq1 DRV_PINGROUP_ENTRY_Y(0x504c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi5_cs0_pq5 DRV_PINGROUP_ENTRY_Y(0x5054, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi5_miso_pq3 DRV_PINGROUP_ENTRY_Y(0x505c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi5_mosi_pq4 DRV_PINGROUP_ENTRY_Y(0x5064, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi5_sck_pq2 DRV_PINGROUP_ENTRY_Y(0x506c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio152_pq6 DRV_PINGROUP_ENTRY_Y(0x5074, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio153_pq7 DRV_PINGROUP_ENTRY_Y(0x507c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio155_pr1 DRV_PINGROUP_ENTRY_Y(0x5084, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_aud_mclk_pr0 DRV_PINGROUP_ENTRY_Y(0x508c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap1_sclk_pr2 DRV_PINGROUP_ENTRY_Y(0x5094, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap1_in_pr4 DRV_PINGROUP_ENTRY_Y(0x509c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap1_out_pr3 DRV_PINGROUP_ENTRY_Y(0x50a4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap1_fs_pr5 DRV_PINGROUP_ENTRY_Y(0x50ac, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen11_i2c_scl_pr6 DRV_PINGROUP_ENTRY_Y(0x50b4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen11_i2c_sda_pr7 DRV_PINGROUP_ENTRY_Y(0x50bc, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio350_ps0 DRV_PINGROUP_ENTRY_Y(0x50c4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio351_ps1 DRV_PINGROUP_ENTRY_Y(0x50cc, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen0_i2c_scl_pw4 DRV_PINGROUP_ENTRY_Y(0x6004, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen0_i2c_sda_pw5 DRV_PINGROUP_ENTRY_Y(0x600c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen1_i2c_scl_pw2 DRV_PINGROUP_ENTRY_Y(0x6014, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen1_i2c_sda_pw3 DRV_PINGROUP_ENTRY_Y(0x601c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap2_fs_pw1 DRV_PINGROUP_ENTRY_Y(0x6044, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap2_clk_pv6 DRV_PINGROUP_ENTRY_Y(0x604c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap2_din_pv7 DRV_PINGROUP_ENTRY_Y(0x6054, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dap2_dout_pw0 DRV_PINGROUP_ENTRY_Y(0x605c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pwm10_pv1 DRV_PINGROUP_ENTRY_Y(0x6064, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio170_pu0 DRV_PINGROUP_ENTRY_Y(0x606c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio171_pu1 DRV_PINGROUP_ENTRY_Y(0x6074, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio172_pu2 DRV_PINGROUP_ENTRY_Y(0x607c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio173_pu3 DRV_PINGROUP_ENTRY_Y(0x6084, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio174_pu4 DRV_PINGROUP_ENTRY_Y(0x608c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio175_pu5 DRV_PINGROUP_ENTRY_Y(0x6094, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio176_pu6 DRV_PINGROUP_ENTRY_Y(0x609c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio177_pu7 DRV_PINGROUP_ENTRY_Y(0x60a4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio178_pv0 DRV_PINGROUP_ENTRY_Y(0x60ac, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart4_cts_n_pv5 DRV_PINGROUP_ENTRY_Y(0x60b4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart4_rts_n_pv4 DRV_PINGROUP_ENTRY_Y(0x60bc, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart4_rx_pv3 DRV_PINGROUP_ENTRY_Y(0x60c4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart4_tx_pv2 DRV_PINGROUP_ENTRY_Y(0x60cc, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pwr_i2c_sda_pw7 DRV_PINGROUP_ENTRY_Y(0x60d4, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pwr_i2c_scl_pw6 DRV_PINGROUP_ENTRY_Y(0x60dc, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio250_pf0 DRV_PINGROUP_ENTRY_Y(0x7004, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio251_pf1 DRV_PINGROUP_ENTRY_Y(0x700c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio252_pf2 DRV_PINGROUP_ENTRY_Y(0x7014, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch0_hpd_pf3 DRV_PINGROUP_ENTRY_Y(0x701c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch1_hpd_pf4 DRV_PINGROUP_ENTRY_Y(0x7024, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch2_hpd_pf5 DRV_PINGROUP_ENTRY_Y(0x702c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_dp_aux_ch3_hpd_pf6 DRV_PINGROUP_ENTRY_Y(0x7034, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pwm2_pf7 DRV_PINGROUP_ENTRY_Y(0x703c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_pwm3_pg0 DRV_PINGROUP_ENTRY_Y(0x7044, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen7_i2c_scl_pg1 DRV_PINGROUP_ENTRY_Y(0x704c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen7_i2c_sda_pg2 DRV_PINGROUP_ENTRY_Y(0x7054, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen9_i2c_scl_pg3 DRV_PINGROUP_ENTRY_Y(0x705c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen9_i2c_sda_pg4 DRV_PINGROUP_ENTRY_Y(0x7064, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio270_py0 DRV_PINGROUP_ENTRY_Y(0xa004, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio271_py1 DRV_PINGROUP_ENTRY_Y(0xa00c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio272_py2 DRV_PINGROUP_ENTRY_Y(0xa014, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio273_py3 DRV_PINGROUP_ENTRY_Y(0xa01c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio274_py4 DRV_PINGROUP_ENTRY_Y(0xa024, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio275_py5 DRV_PINGROUP_ENTRY_Y(0xa02c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio276_py6 DRV_PINGROUP_ENTRY_Y(0xa034, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio277_py7 DRV_PINGROUP_ENTRY_Y(0xa03c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio278_pz0 DRV_PINGROUP_ENTRY_Y(0xa044, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio279_pz1 DRV_PINGROUP_ENTRY_Y(0xa04c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio282_pz4 DRV_PINGROUP_ENTRY_Y(0xa054, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio283_pz5 DRV_PINGROUP_ENTRY_Y(0xa05c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio284_pz6 DRV_PINGROUP_ENTRY_Y(0xa064, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio285_pz7 DRV_PINGROUP_ENTRY_Y(0xa06c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio286_pal0 DRV_PINGROUP_ENTRY_Y(0xa074, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio287_pal1 DRV_PINGROUP_ENTRY_Y(0xa07c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio288_pal2 DRV_PINGROUP_ENTRY_Y(0xa084, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_xhalt_trig_pz2 DRV_PINGROUP_ENTRY_Y(0xa08c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio281_pz3 DRV_PINGROUP_ENTRY_Y(0xa094, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+
+#define drive_ao_retention_n_paa2 DRV_PINGROUP_ENTRY_Y(0x2c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_batt_oc_paa3 DRV_PINGROUP_ENTRY_Y(0x34, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_power_on_paa5 DRV_PINGROUP_ENTRY_Y(0x3c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_vcomp_alert_paa1 DRV_PINGROUP_ENTRY_Y(0x44, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_bootv_ctl_n_paa4 DRV_PINGROUP_ENTRY_Y(0x4c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio00_paa0 DRV_PINGROUP_ENTRY_Y(0x54, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio07_paa7 DRV_PINGROUP_ENTRY_Y(0x5c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio08_pbb0 DRV_PINGROUP_ENTRY_Y(0x64, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio09_pbb1 DRV_PINGROUP_ENTRY_Y(0x6c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_hdmi_cec_paa6 DRV_PINGROUP_ENTRY_Y(0x74, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen2_i2c_scl_pcc0 DRV_PINGROUP_ENTRY_Y(0x1004, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen2_i2c_sda_pcc1 DRV_PINGROUP_ENTRY_Y(0x100c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen3_i2c_scl_pcc2 DRV_PINGROUP_ENTRY_Y(0x1014, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gen3_i2c_sda_pcc3 DRV_PINGROUP_ENTRY_Y(0x101c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_gp_pwm4_pcc4 DRV_PINGROUP_ENTRY_Y(0x1024, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart0_tx_pcc5 DRV_PINGROUP_ENTRY_Y(0x102c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_uart0_rx_pcc6 DRV_PINGROUP_ENTRY_Y(0x1034, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi2_sck_pcc7 DRV_PINGROUP_ENTRY_Y(0x103c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi2_miso_pdd0 DRV_PINGROUP_ENTRY_Y(0x1044, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi2_mosi_pdd1 DRV_PINGROUP_ENTRY_Y(0x104c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_spi2_cs0_n_pdd2 DRV_PINGROUP_ENTRY_Y(0x1054, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio21_pdd3 DRV_PINGROUP_ENTRY_Y(0x105c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio22_pdd4 DRV_PINGROUP_ENTRY_Y(0x1064, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio23_pdd5 DRV_PINGROUP_ENTRY_Y(0x106c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio24_pdd6 DRV_PINGROUP_ENTRY_Y(0x1074, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio25_pdd7 DRV_PINGROUP_ENTRY_Y(0x107c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio26_pee0 DRV_PINGROUP_ENTRY_Y(0x1084, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio27_pee1 DRV_PINGROUP_ENTRY_Y(0x108c, 12, 4, 20, 4, -1, -1, -1, -1, 0)
+#define drive_soc_gpio28_pee2 DRV_PINGROUP_ENTRY_N
+#define drive_soc_gpio29_pee3 DRV_PINGROUP_ENTRY_N
+
+#define PINGROUP(pg_name, f0, f1, f2, f3, r, bank, pupd, e_io_hv, e_lpbk, e_input, e_lpdr, e_pbias_buf,	\
+			gpio_sfio_sel, schmitt_b)							\
+	{								\
+		.name = #pg_name,					\
+		.pins = pg_name##_pins,					\
+		.npins = ARRAY_SIZE(pg_name##_pins),			\
+			.funcs = {					\
+				TEGRA_MUX_##f0,				\
+				TEGRA_MUX_##f1,				\
+				TEGRA_MUX_##f2,				\
+				TEGRA_MUX_##f3,				\
+			},						\
+		PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_io_hv, e_lpbk,	\
+					e_input, e_lpdr, e_pbias_buf,	\
+					gpio_sfio_sel, schmitt_b)	\
+		drive_##pg_name,					\
+	}
+
+static const struct tegra_pingroup tegra264_uphy_groups[] = {
+	PINGROUP(eth1_mdio_pe0, ETH1_MDIO, RSVD1, RSVD2, RSVD3, 0x0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l4_clkreq_n_pd0, PE4_CLKREQ_L, RSVD1, RSVD2, RSVD3, 0x8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l4_rst_n_pd1, PE4_RST_L, RSVD1, RSVD2, RSVD3, 0x10, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l5_clkreq_n_pd2, PE5_CLKREQ_L, RSVD1, RSVD2, RSVD3, 0x18, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l5_rst_n_pd3, PE5_RST_L, RSVD1, RSVD2, RSVD3, 0x20, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(eth0_mdio_pd4, ETH0_MDIO, RSVD1, RSVD2, RSVD3, 0x28, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(eth0_mdc_pd5, ETH0_MDC, RSVD1, RSVD2, RSVD3, 0x30, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(eth1_mdc_pe1, ETH1_MDC, RSVD1, RSVD2, RSVD3, 0x38, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(eth2_mdio_pe2, ETH2_MDIO, RSVD1, RSVD2, RSVD3, 0x40, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(eth2_mdc_pe3, ETH2_MDC, RSVD1, RSVD2, RSVD3, 0x48, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(eth3_mdio_pd6, ETH3_MDIO, RSVD1, RSVD2, RSVD3, 0x50, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(eth3_mdc_pd7, ETH3_MDC, RSVD1, RSVD2, RSVD3, 0x58, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l1_clkreq_n_pb0, PE1_CLKREQ_L, RSVD1, RSVD2, RSVD3, 0x2000, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l1_rst_n_pb1, PE1_RST_L, RSVD1, RSVD2, RSVD3, 0x2008, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_wake_n_pc2, RSVD0, RSVD1, RSVD2, RSVD3, 0x2010, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l2_rst_n_pb3, PE2_RST_L, RSVD1, RSVD2, RSVD3, 0x2018, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l2_clkreq_n_pb2, PE2_CLKREQ_L, RSVD1, RSVD2, RSVD3, 0x2020, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l3_clkreq_n_pb4, PE3_CLKREQ_L, RSVD1, RSVD2, RSVD3, 0x2028, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pex_l3_rst_n_pb5, PE3_RST_L, RSVD1, RSVD2, RSVD3, 0x2030, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(sgmii0_sma_mdio_pc0, SGMII0_SMA_MDIO, RSVD1, RSVD2, RSVD3, 0x2038, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(sgmii0_sma_mdc_pc1, SGMII0_SMA_MDC, RSVD1, RSVD2, RSVD3, 0x2040, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio113_pb6, USB_VBUS_EN0, RSVD1, RSVD2, RSVD3, 0x2048, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio114_pb7, USB_VBUS_EN1, RSVD1, RSVD2, RSVD3, 0x2050, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pwm1_pa0, GP_PWM1, RSVD1, RSVD2, RSVD3, 0x3000, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pwm6_pa1, GP_PWM6, RSVD1, RSVD2, RSVD3, 0x3008, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pwm7_pa2, GP_PWM7, RSVD1, RSVD2, RSVD3, 0x3010, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pwm8_pa3, GP_PWM8, RSVD1, RSVD2, RSVD3, 0x3018, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(ufs0_ref_clk_pa4, UFS0, RSVD1, RSVD2, RSVD3, 0x3020, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(ufs0_rst_n_pa5, UFS0, RSVD1, RSVD2, RSVD3, 0x3028, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+};
+
+static const struct tegra_pingroup tegra264_main_groups[] = {
+	PINGROUP(cpu_pwr_req_ph0, RSVD0, RSVD1, RSVD2, RSVD3, 0x0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gpu_pwr_req_ph1, RSVD0, RSVD1, RSVD2, RSVD3, 0x8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart10_cts_n_ph5, UARTK_CTS, RSVD1, RSVD2, RSVD3, 0x10, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart10_rts_n_ph4, UARTK_RTS, RSVD1, RSVD2, RSVD3, 0x18, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart10_rx_ph3, UARTK_RXD, RSVD1, RSVD2, RSVD3, 0x20, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart10_tx_ph2, UARTK_TXD, RSVD1, RSVD2, RSVD3, 0x28, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi3_cs0_pj1, SPI3_CS0, RSVD1, RSVD2, RSVD3, 0x30, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi3_cs3_pj2, SPI3_CS3, RSVD1, RSVD2, RSVD3, 0x38, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi3_miso_ph7, SPI3_DIN, RSVD1, RSVD2, RSVD3, 0x40, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi3_mosi_pj0, SPI3_DOUT, RSVD1, RSVD2, RSVD3, 0x48, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi3_sck_ph6, SPI3_SCK, RSVD1, RSVD2, RSVD3, 0x50, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart5_cts_n_pj6, UARTF_CTS, RSVD1, RSVD2, RSVD3, 0x58, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart5_rts_n_pj5, UARTF_RTS, RSVD1, RSVD2, RSVD3, 0x60, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart5_rx_pj4, UARTF_RXD, RSVD1, RSVD2, RSVD3, 0x68, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart5_tx_pj3, UARTF_TXD, RSVD1, RSVD2, RSVD3, 0x70, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi1_cs0_pk2, SPI1_CS0, RSVD1, RSVD2, RSVD3, 0x78, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi1_cs1_pk3, SPI1_CS1, RSVD1, RSVD2, RSVD3, 0x80, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi1_miso_pk0, SPI1_DIN, RSVD1, RSVD2, RSVD3, 0x88, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi1_mosi_pk1, SPI1_DOUT, RSVD1, RSVD2, RSVD3, 0x90, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi1_sck_pj7, SPI1_SCK, RSVD1, RSVD2, RSVD3, 0x98, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(extperiph2_clk_pk5, EXTPERIPH2_CLK, RSVD1, DMIC2_CLK, DSPK1_CLK, 0xa0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(extperiph1_clk_pk4, EXTPERIPH1_CLK, RSVD1, DMIC2_DAT, DSPK1_DAT, 0xa8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen12_i2c_scl_pk6, I2C12_CLK, RSVD1, RSVD2, RSVD3, 0xb0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen12_i2c_sda_pk7, I2C12_DAT, RSVD1, RSVD2, RSVD3, 0xb8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio124_pl0, RSVD0, SOC_THERM_OC3, RSVD2, RSVD3, 0x1000, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio125_pl1, RSVD0, I2S5_SCLK, RSVD2, RSVD3, 0x1008, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(fan_tach0_pl2, NV_THERM_FAN_TACH0, RSVD1, RSVD2, RSVD3, 0x1010, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio127_pl3, RSVD0, RSVD1, NV_THERM_FAN_TACH1, RSVD3, 0x1018, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio128_pl4, RSVD0, I2S5_SDATA_IN, RSVD2, RSVD3, 0x1020, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio129_pl5, RSVD0, EXTPERIPH3_CLK, I2C15_CLK, RSVD3, 0x1028, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio130_pl6, RSVD0, EXTPERIPH4_CLK, I2C15_DAT, RSVD3, 0x1030, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio131_pl7, RSVD0, I2S5_SDATA_OUT, RSVD2, RSVD3, 0x1038, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gp_pwm9_pm0, GP_PWM9, RSVD1, RSVD2, RSVD3, 0x1040, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio133_pm1, RSVD0, I2S5_LRCK, RSVD2, RSVD3, 0x1048, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart9_cts_n_pm5, UARTJ_CTS, RSVD1, RSVD2, RSVD3, 0x1050, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart9_rts_n_pm4, UARTJ_RTS, RSVD1, RSVD2, RSVD3, 0x1058, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart9_rx_pm3, UARTJ_RXD, RSVD1, RSVD2, RSVD3, 0x1060, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart9_tx_pm2, UARTJ_TXD, RSVD1, RSVD2, RSVD3, 0x1068, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(sdmmc1_clk_px0, SDMMC1_CLK, RSVD1, RSVD2, RSVD3, 0x2000, 0, Y, -1, 5, 6, 13, -1, 10, -1),
+	PINGROUP(sdmmc1_cmd_px1, SDMMC1_CMD, RSVD1, RSVD2, RSVD3, 0x2008, 0, Y, -1, 5, 6, 13, -1, 10, -1),
+	PINGROUP(sdmmc1_comp, SDMMC1_COMP, RSVD1, RSVD2, RSVD3, 0x2010, 0, N, -1, -1, -1, -1, -1, -1, -1),
+	PINGROUP(sdmmc1_dat3_px5, SDMMC1_DAT3, RSVD1, RSVD2, RSVD3, 0x2018, 0, Y, -1, 5, 6, 13, -1, 10, -1),
+	PINGROUP(sdmmc1_dat2_px4, SDMMC1_DAT2, RSVD1, RSVD2, RSVD3, 0x2020, 0, Y, -1, 5, 6, 13, -1, 10, -1),
+	PINGROUP(sdmmc1_dat1_px3, SDMMC1_DAT1, RSVD1, RSVD2, RSVD3, 0x2028, 0, Y, -1, 5, 6, 13, -1, 10, -1),
+	PINGROUP(sdmmc1_dat0_px2, SDMMC1_DAT0, RSVD1, RSVD2, RSVD3, 0x2030, 0, Y, -1, 5, 6, 13, -1, 10, -1),
+	PINGROUP(qspi0_cs_n_pt1, QSPI0_CS_N, RSVD1, RSVD2, RSVD3, 0x3000, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(qspi0_io0_pt2, QSPI0_IO0, RSVD1, RSVD2, RSVD3, 0x3008, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(qspi0_io1_pt3, QSPI0_IO1, RSVD1, RSVD2, RSVD3, 0x3010, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(qspi0_io2_pt4, QSPI0_IO2, RSVD1, RSVD2, RSVD3, 0x3018, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(qspi0_io3_pt5, QSPI0_IO3, RSVD1, RSVD2, RSVD3, 0x3020, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(qspi0_sck_pt0, QSPI0_SCK, RSVD1, RSVD2, RSVD3, 0x3028, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio192_pt6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3030, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio138_pp0, RSVD0, I2C14_CLK, DMIC1_DAT, RSVD3, 0x5000, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio139_pp1, RSVD0, I2C14_DAT, DMIC1_CLK, RSVD3, 0x5008, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap6_din_pp4, I2S6_SDATA_IN, RSVD1, RSVD2, RSVD3, 0x5010, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap6_dout_pp3, I2S6_SDATA_OUT, RSVD1, RSVD2, RSVD3, 0x5018, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap6_fs_pp5, I2S6_LRCK, RSVD1, RSVD2, RSVD3, 0x5020, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap6_sclk_pp2, I2S6_SCLK, RSVD1, RSVD2, RSVD3, 0x5028, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap4_dout_pp7, I2S4_SDATA_OUT, RSVD1, RSVD2, RSVD3, 0x5030, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap4_sclk_pp6, I2S4_SCLK, RSVD1, RSVD2, RSVD3, 0x5038, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap4_din_pq0, I2S4_SDATA_IN, RSVD1, RSVD2, RSVD3, 0x5040, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap4_fs_pq1, I2S4_LRCK, RSVD1, RSVD2, RSVD3, 0x5048, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi5_cs0_pq5, SPI5_CS0, RSVD1, RSVD2, RSVD3, 0x5050, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi5_miso_pq3, SPI5_DIN, RSVD1, RSVD2, RSVD3, 0x5058, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi5_mosi_pq4, SPI5_DOUT, RSVD1, RSVD2, RSVD3, 0x5060, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi5_sck_pq2, SPI5_SCK, RSVD1, RSVD2, RSVD3, 0x5068, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio152_pq6, RSVD0, I2S8_SCLK, RSVD2, RSVD3, 0x5070, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio153_pq7, RSVD0, I2S8_SDATA_OUT, RSVD2, RSVD3, 0x5078, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio155_pr1, RSVD0, I2S8_LRCK, RSVD2, RSVD3, 0x5080, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(aud_mclk_pr0, AUD_MCLK, RSVD1, RSVD2, RSVD3, 0x5088, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap1_sclk_pr2, I2S1_SCLK, RSVD1, RSVD2, RSVD3, 0x5090, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap1_in_pr4, I2S1_SDATA_IN, RSVD1, RSVD2, RSVD3, 0x5098, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap1_out_pr3, I2S1_SDATA_OUT, RSVD1, RSVD2, RSVD3, 0x50a0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap1_fs_pr5, I2S1_LRCK, RSVD1, RSVD2, RSVD3, 0x50a8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen11_i2c_scl_pr6, I2C11_CLK, RSVD1, RSVD2, RSVD3, 0x50b0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen11_i2c_sda_pr7, I2C11_DAT, RSVD1, RSVD2, RSVD3, 0x50b8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio350_ps0, RSVD0, I2S8_SDATA_IN, RSVD2, RSVD3, 0x50c0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio351_ps1, RSVD0, RSVD1, RSVD2, RSVD3, 0x50c8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen0_i2c_scl_pw4, I2C0_CLK, RSVD1, RSVD2, RSVD3, 0x6000, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen0_i2c_sda_pw5, I2C0_DAT, RSVD1, RSVD2, RSVD3, 0x6008, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen1_i2c_scl_pw2, I2C1_CLK, RSVD1, RSVD2, RSVD3, 0x6010, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen1_i2c_sda_pw3, I2C1_DAT, RSVD1, RSVD2, RSVD3, 0x6018, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap2_fs_pw1, I2S2_LRCK, RSVD1, RSVD2, RSVD3, 0x6040, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap2_clk_pv6, I2S2_SCLK, RSVD1, RSVD2, RSVD3, 0x6048, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap2_din_pv7, I2S2_SDATA_OUT, RSVD1, RSVD2, RSVD3, 0x6050, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dap2_dout_pw0, I2S2_SDATA_IN, RSVD1, RSVD2, RSVD3, 0x6058, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pwm10_pv1, GP_PWM10, SDMMC1_CD, I2S7_LRCK, RSVD3, 0x6060, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio170_pu0, RSVD0, I2S7_SDATA_IN, CCLA_LA_TRIGGER_MUX, RSVD3, 0x6068, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio171_pu1, RSVD0, SPI4_SCK, RSVD2, RSVD3, 0x6070, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio172_pu2, RSVD0, SPI4_DIN, RSVD2, RSVD3, 0x6078, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio173_pu3, RSVD0, SPI4_DOUT, RSVD2, RSVD3, 0x6080, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio174_pu4, RSVD0, SPI4_CS0, RSVD2, RSVD3, 0x6088, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio175_pu5, RSVD0, SPI4_CS1, RSVD2, RSVD3, 0x6090, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio176_pu6, RSVD0, RSVD1, I2S7_SCLK, RSVD3, 0x6098, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio177_pu7, RSVD0, GP_PWM5, RSVD2, RSVD3, 0x60a0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio178_pv0, RSVD0, RSVD1, I2S7_SDATA_OUT, RSVD3, 0x60a8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart4_cts_n_pv5, UARTE_CTS, RSVD1, RSVD2, RSVD3, 0x60b0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart4_rts_n_pv4, UARTE_RTS, RSVD1, RSVD2, RSVD3, 0x60b8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart4_rx_pv3, UARTE_RXD, RSVD1, RSVD2, RSVD3, 0x60c0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart4_tx_pv2, UARTE_TXD, RSVD1, RSVD2, RSVD3, 0x60c8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pwr_i2c_sda_pw7, I2C5_DAT, RSVD1, RSVD2, RSVD3, 0x60d0, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pwr_i2c_scl_pw6, I2C5_CLK, RSVD1, RSVD2, RSVD3, 0x60d8, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio250_pf0, DCA_VSYNC, DCB_VSYNC, DCC_VSYNC, DCD_VSYNC, 0x7000, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio251_pf1, DCA_HSYNC, DCB_HSYNC, DCC_HSYNC, DCD_HSYNC, 0x7008, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio252_pf2, RSVD0, DSA_LSPII, RSVD2, RSVD3, 0x7010, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dp_aux_ch0_hpd_pf3, DP_AUX_CH0_HPD, DCE_VSYNC, DCF_VSYNC, DCG_VSYNC, 0x7018, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dp_aux_ch1_hpd_pf4, DP_AUX_CH1_HPD, DCE_HSYNC, DCF_HSYNC, DCG_HSYNC, 0x7020, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dp_aux_ch2_hpd_pf5, DP_AUX_CH2_HPD, DCH_VSYNC, RSVD2, RSVD3, 0x7028, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(dp_aux_ch3_hpd_pf6, DP_AUX_CH3_HPD, DCH_HSYNC, RSVD2, RSVD3, 0x7030, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pwm2_pf7, GP_PWM2, BL_EN, RSVD2, RSVD3, 0x7038, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(pwm3_pg0, GP_PWM3, BL_PWM_DIM0, RSVD2, RSVD3, 0x7040, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen7_i2c_scl_pg1, I2C7_CLK, RSVD1, SOUNDWIRE1_CLK, RSVD3, 0x7048, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen7_i2c_sda_pg2, I2C7_DAT, RSVD1, SOUNDWIRE1_DAT0, RSVD3, 0x7050, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen9_i2c_scl_pg3, I2C9_CLK, RSVD1, SOUNDWIRE1_DAT1, RSVD3, 0x7058, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen9_i2c_sda_pg4, I2C9_DAT, RSVD1, SOUNDWIRE1_DAT2, RSVD3, 0x7060, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio270_py0, RSVD0, I2C16_CLK, RSVD2, RSVD3, 0xa000, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio271_py1, RSVD0, I2C16_DAT, RSVD2, RSVD3, 0xa008, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio272_py2, RSVD0, I2S3_SCLK, RSVD2, RSVD3, 0xa010, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio273_py3, RSVD0, I2S3_SDATA_OUT, RSVD2, RSVD3, 0xa018, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio274_py4, RSVD0, I2S3_SDATA_IN, RSVD2, RSVD3, 0xa020, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio275_py5, RSVD0, I2S3_LRCK, RSVD2, RSVD3, 0xa028, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio276_py6, RSVD0, RSVD1, RSVD2, RSVD3, 0xa030, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio277_py7, RSVD0, RSVD1, RSVD2, RSVD3, 0xa038, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio278_pz0, RSVD0, RSVD1, RSVD2, RSVD3, 0xa040, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio279_pz1, RSVD0, RSVD1, RSVD2, RSVD3, 0xa048, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio282_pz4, RSVD0, PM_TRIG1, RSVD2, RSVD3, 0xa050, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio283_pz5, RSVD0, RSVD1, RSVD2, RSVD3, 0xa058, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio284_pz6, RSVD0, RSVD1, RSVD2, RSVD3, 0xa060, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio285_pz7, RSVD0, RSVD1, RSVD2, RSVD3, 0xa068, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio286_pal0, RSVD0, RSVD1, RSVD2, RSVD3, 0xa070, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio287_pal1, RSVD0, RSVD1, RSVD2, RSVD3, 0xa078, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio288_pal2, RSVD0, RSVD1, RSVD2, RSVD3, 0xa080, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(xhalt_trig_pz2, XHALT_TRIG, RSVD1, RSVD2, RSVD3, 0xa088, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio281_pz3, RSVD0, PM_TRIG0, RSVD2, RSVD3, 0xa090, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+};
+
+static const struct tegra_pingroup tegra264_aon_groups[] = {
+	PINGROUP(ao_retention_n_paa2, RSVD0, RSVD1, RSVD2, ISTCTRL_IST_DONE_N, 0x28, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(batt_oc_paa3, SOC_THERM_OC2, RSVD1, RSVD2, RSVD3, 0x30, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(power_on_paa5, RSVD0, RSVD1, RSVD2, RSVD3, 0x38, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(vcomp_alert_paa1, SOC_THERM_OC1, RSVD1, RSVD2, RSVD3, 0x40, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(bootv_ctl_n_paa4, RSVD0, RSVD1, RSVD2, RSVD3, 0x48, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio00_paa0, RSVD0, RSVD1, RSVD2, RSVD3, 0x50, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio07_paa7, RSVD0, RSVD1, RSVD2, RSVD3, 0x58, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio08_pbb0, RSVD0, RSVD1, RSVD2, RSVD3, 0x60, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio09_pbb1, RSVD0, RSVD1, RSVD2, RSVD3, 0x68, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(hdmi_cec_paa6, HDMI_CEC, RSVD1, RSVD2, RSVD3, 0x70, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen2_i2c_scl_pcc0, I2C2_CLK, RSVD1, RSVD2, RSVD3, 0x1000, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen2_i2c_sda_pcc1, I2C2_DAT, RSVD1, RSVD2, RSVD3, 0x1008, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen3_i2c_scl_pcc2, I2C3_CLK, RSVD1, RSVD2, RSVD3, 0x1010, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gen3_i2c_sda_pcc3, I2C3_DAT, RSVD1, RSVD2, RSVD3, 0x1018, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(gp_pwm4_pcc4, GP_PWM4, TOUCH_CLK, RSVD2, RSVD3, 0x1020, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart0_tx_pcc5, UARTA_TXD, RSVD1, UARTL_TXD, RSVD3, 0x1028, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(uart0_rx_pcc6, UARTA_RXD, RSVD1, UARTL_RXD, RSVD3, 0x1030, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi2_sck_pcc7, SPI2_SCK, RSVD1, I2S9_SCLK, SOUNDWIRE0_CLK, 0x1038, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi2_miso_pdd0, SPI2_DIN, RSVD1, I2S9_SDATA_OUT, SOUNDWIRE0_DAT0, 0x1040, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi2_mosi_pdd1, SPI2_DOUT, RSVD1, I2S9_SDATA_IN, RSVD3, 0x1048, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(spi2_cs0_n_pdd2, SPI2_CS0, RSVD1, I2S9_LRCK, RSVD3, 0x1050, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio21_pdd3, RSVD0, TSC_SYNC1, DMIC5_DAT, RSVD3, 0x1058, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio22_pdd4, RSVD0, RSVD1, DMIC5_CLK, RSVD3, 0x1060, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio23_pdd5, RSVD0, RSVD1, TSC_EDGE_OUT2, TSC_EDGE_OUT0C, 0x1068, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio24_pdd6, RSVD0, TSC_EDGE_OUT3, RSVD2, TSC_EDGE_OUT0D, 0x1070, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio25_pdd7, RSVD0, TSC_EDGE_OUT0, RSVD2, TSC_EDGE_OUT0A, 0x1078, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio26_pee0, RSVD0, TSC_EDGE_OUT1, RSVD2, TSC_EDGE_OUT0B, 0x1080, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio27_pee1, RSVD0, TSC_SYNC0, RSVD2, RSVD3, 0x1088, 0, Y, 5, 7, 6, 8, -1, 10, 11),
+	PINGROUP(soc_gpio28_pee2, L0L1_RST_OUT_N, RSVD1, RSVD2, RSVD3, 0x1090, 0, N, -1, -1, -1, -1, -1, 10, -1),
+	PINGROUP(soc_gpio29_pee3, L2_RST_OUT_N, RSVD1, RSVD2, RSVD3, 0x1098, 0, N, -1, -1, -1, -1, -1, 10, -1),
+};
+
+static const struct tegra_pinctrl_soc_data tegra264_uphy_pinctrl = {
+	.pins = tegra264_uphy_pins,
+	.npins = ARRAY_SIZE(tegra264_uphy_pins),
+	.functions = tegra264_functions,
+	.nfunctions = ARRAY_SIZE(tegra264_functions),
+	.groups = tegra264_uphy_groups,
+	.ngroups = ARRAY_SIZE(tegra264_uphy_groups),
+	.hsm_in_mux = false,
+	.schmitt_in_mux = true,
+	.drvtype_in_mux = true,
+	.sfsel_in_mux = true,
+};
+
+static const struct tegra_pinctrl_soc_data tegra264_main_pinctrl = {
+	.pins = tegra264_main_pins,
+	.npins = ARRAY_SIZE(tegra264_main_pins),
+	.functions = tegra264_functions,
+	.nfunctions = ARRAY_SIZE(tegra264_functions),
+	.groups = tegra264_main_groups,
+	.ngroups = ARRAY_SIZE(tegra264_main_groups),
+	.hsm_in_mux = false,
+	.schmitt_in_mux = true,
+	.drvtype_in_mux = true,
+	.sfsel_in_mux = true,
+};
+
+static const struct tegra_pinctrl_soc_data tegra264_aon_pinctrl = {
+	.pins = tegra264_aon_pins,
+	.npins = ARRAY_SIZE(tegra264_aon_pins),
+	.functions = tegra264_functions,
+	.nfunctions = ARRAY_SIZE(tegra264_functions),
+	.groups = tegra264_aon_groups,
+	.ngroups = ARRAY_SIZE(tegra264_aon_groups),
+	.hsm_in_mux = false,
+	.schmitt_in_mux = true,
+	.drvtype_in_mux = true,
+	.sfsel_in_mux = true,
+};
+
+static int tegra264_pinctrl_probe(struct platform_device *pdev)
+{
+	const struct tegra_pinctrl_soc_data *soc = device_get_match_data(&pdev->dev);
+
+	return tegra_pinctrl_probe(pdev, soc);
+}
+
+static const struct of_device_id tegra264_pinctrl_of_match[] = {
+	{ .compatible = "nvidia,tegra264-pinmux-uphy", .data = &tegra264_uphy_pinctrl},
+	{ .compatible = "nvidia,tegra264-pinmux-main", .data = &tegra264_main_pinctrl},
+	{ .compatible = "nvidia,tegra264-pinmux-aon", .data = &tegra264_aon_pinctrl},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tegra264_pinctrl_of_match);
+
+static struct platform_driver tegra264_pinctrl_driver = {
+	.driver = {
+		.name = "tegra264-pinctrl",
+		.of_match_table = tegra264_pinctrl_of_match,
+	},
+	.probe = tegra264_pinctrl_probe,
+};
+
+static int __init tegra264_pinctrl_init(void)
+{
+	return platform_driver_register(&tegra264_pinctrl_driver);
+}
+module_init(tegra264_pinctrl_init);
+
+static void __exit tegra264_pinctrl_exit(void)
+{
+	platform_driver_unregister(&tegra264_pinctrl_driver);
+}
+module_exit(tegra264_pinctrl_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("NVIDIA Corporation");
+MODULE_DESCRIPTION("NVIDIA Tegra264 pinctrl driver");
-- 
2.43.0


^ permalink raw reply related

* [PATCH v9 0/3] iio: adc: ad4080: add support for AD4880 dual-channel ADC
From: Antoniu Miclaus @ 2026-04-20 10:12 UTC (permalink / raw)
  To: Lars-Peter Clausen, Michael Hennerich, Antoniu Miclaus,
	Jonathan Cameron, David Lechner, Nuno Sá, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
	devicetree, linux-kernel

Add support for the AD4880, a dual-channel 20-bit 40MSPS SAR ADC with
integrated fully differential amplifiers (FDA).

Architecture notes:

The AD4880 is modeled as a single IIO device rather than two independent
devices because the channels share power supplies, a voltage reference,
the CNV conversion clock, and a single interleaved data output stream.
Splitting them into separate IIO devices would make synchronized
dual-channel capture impossible from userspace.

An MFD approach does not apply here either - the channels are not
functionally distinct sub-devices but identical ADC paths sharing a
common data interface.

Each channel has fully independent configuration registers accessible
through separate SPI chip selects, so per-channel regmaps are used with
no locking between them. The data path has no software involvement at
runtime: the CNV clock triggers simultaneous conversions and the device
outputs an interleaved bitstream captured directly by the IIO backend
(FPGA). spi_new_ancillary_device() handles the configuration path;
the IIO backend handles the data path.

The debugfs_reg_access callback is not exposed for the dual-channel
variant since the IIO framework provides a single (reg, val) interface
with no channel parameter, and exposing only one channel would be
misleading.

The AD4880 is a fairly unique part - having separate SPI config
interfaces per channel with a shared interleaved data output is not
a common pattern.

NOTE: The AD4880 driver has a cross-tree dependency on two SPI patches
that are queued in spi/for-7.1:

- ffef4123043c ("spi: allow ancillary devices to share parent's chip selects")
- 463279e58811 ("spi: add devm_spi_new_ancillary_device()")

Changes in v9:
  - Rebase on jic23/togreg
  - Add Conor's ack on dt-bindings patch

Antoniu Miclaus (3):
  iio: backend: add devm_iio_backend_get_by_index()
  dt-bindings: iio: adc: ad4080: add AD4880 support
  iio: adc: ad4080: add support for AD4880 dual-channel ADC

 .../bindings/iio/adc/adi,ad4080.yaml          |  53 +++-
 drivers/iio/adc/ad4080.c                      | 257 +++++++++++++-----
 drivers/iio/industrialio-backend.c            |  53 +++-
 include/linux/iio/backend.h                   |   1 +
 4 files changed, 285 insertions(+), 79 deletions(-)


base-commit: d2a4ec19d2a2e54c23b5180e939994d3da4a6b91
-- 
2.43.0


^ permalink raw reply

* [PATCH v9 2/3] dt-bindings: iio: adc: ad4080: add AD4880 support
From: Antoniu Miclaus @ 2026-04-20 10:12 UTC (permalink / raw)
  To: Lars-Peter Clausen, Michael Hennerich, Antoniu Miclaus,
	Jonathan Cameron, David Lechner, Nuno Sá, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
	devicetree, linux-kernel
  Cc: Conor Dooley
In-Reply-To: <20260420101225.4173-1-antoniu.miclaus@analog.com>

Add support for the AD4880, a dual-channel 20-bit 40MSPS SAR ADC
with integrated fully differential amplifiers (FDA).

The AD4880 has two independent ADC channels, each with its own SPI
configuration interface. This requires:
- Two entries in reg property for primary and secondary channel
  chip selects
- Two io-backends entries for the two data channels

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
Changes in v9:
  - Add Conor's ack

 .../bindings/iio/adc/adi,ad4080.yaml          | 53 ++++++++++++++++++-
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml
index 79df2696ef24..9c6a56c7c8ef 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml
@@ -18,7 +18,11 @@ description: |
   service a wide variety of precision, wide bandwidth data acquisition
   applications.
 
+  The AD4880 is a dual-channel variant with two independent ADC channels,
+  each with its own SPI configuration interface.
+
   https://www.analog.com/media/en/technical-documentation/data-sheets/ad4080.pdf
+  https://www.analog.com/media/en/technical-documentation/data-sheets/ad4880.pdf
 
 $ref: /schemas/spi/spi-peripheral-props.yaml#
 
@@ -34,9 +38,15 @@ properties:
       - adi,ad4086
       - adi,ad4087
       - adi,ad4088
+      - adi,ad4880
 
   reg:
-    maxItems: 1
+    minItems: 1
+    maxItems: 2
+    description:
+      SPI chip select(s). For single-channel devices, one chip select.
+      For multi-channel devices like AD4880, two chip selects are required
+      as each channel has its own SPI configuration interface.
 
   spi-max-frequency:
     description: Configuration of the SPI bus.
@@ -60,7 +70,10 @@ properties:
   vrefin-supply: true
 
   io-backends:
-    maxItems: 1
+    minItems: 1
+    items:
+      - description: Backend for channel A (primary)
+      - description: Backend for channel B (secondary)
 
   adi,lvds-cnv-enable:
     description: Enable the LVDS signal type on the CNV pin. Default is CMOS.
@@ -81,6 +94,25 @@ required:
   - vdd33-supply
   - vrefin-supply
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: adi,ad4880
+    then:
+      properties:
+        reg:
+          minItems: 2
+        io-backends:
+          minItems: 2
+    else:
+      properties:
+        reg:
+          maxItems: 1
+        io-backends:
+          maxItems: 1
+
 additionalProperties: false
 
 examples:
@@ -101,4 +133,21 @@ examples:
           io-backends = <&iio_backend>;
         };
     };
+  - |
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        adc@0 {
+          compatible = "adi,ad4880";
+          reg = <0>, <1>;
+          spi-max-frequency = <10000000>;
+          vdd33-supply = <&vdd33>;
+          vddldo-supply = <&vddldo>;
+          vrefin-supply = <&vrefin>;
+          clocks = <&cnv>;
+          clock-names = "cnv";
+          io-backends = <&iio_backend_cha>, <&iio_backend_chb>;
+        };
+    };
 ...
-- 
2.43.0


^ permalink raw reply related

* [PATCH v9 1/3] iio: backend: add devm_iio_backend_get_by_index()
From: Antoniu Miclaus @ 2026-04-20 10:12 UTC (permalink / raw)
  To: Lars-Peter Clausen, Michael Hennerich, Antoniu Miclaus,
	Jonathan Cameron, David Lechner, Nuno Sá, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
	devicetree, linux-kernel
In-Reply-To: <20260420101225.4173-1-antoniu.miclaus@analog.com>

Add a new function to get an IIO backend by its index in the
io-backends device tree property. This is useful for multi-channel
devices that have multiple backends, where looking up by index is
more straightforward than using named backends.

Extract __devm_iio_backend_fwnode_get_by_index() from the existing
__devm_iio_backend_fwnode_get(), taking the index directly as a
parameter. The new public API devm_iio_backend_get_by_index() uses
the index to find the backend reference in the io-backends property,
avoiding the need for io-backend-names.

Reviewed-by: David Lechner <dlechner@baylibre.com>
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
Changes in v9:
  - No changes

 drivers/iio/industrialio-backend.c | 53 +++++++++++++++++++++---------
 include/linux/iio/backend.h        |  1 +
 2 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index 10e689f49441..138ebebc9c0d 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -964,23 +964,13 @@ int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address)
 }
 EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, "IIO_BACKEND");
 
-static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name,
-							 struct fwnode_handle *fwnode)
+static struct iio_backend *__devm_iio_backend_fwnode_get_by_index(struct device *dev,
+								  struct fwnode_handle *fwnode,
+								  unsigned int index)
 {
 	struct iio_backend *back;
-	unsigned int index;
 	int ret;
 
-	if (name) {
-		ret = device_property_match_string(dev, "io-backend-names",
-						   name);
-		if (ret < 0)
-			return ERR_PTR(ret);
-		index = ret;
-	} else {
-		index = 0;
-	}
-
 	struct fwnode_handle *fwnode_back __free(fwnode_handle) =
 		fwnode_find_reference(fwnode, "io-backends", index);
 	if (IS_ERR(fwnode_back))
@@ -996,8 +986,7 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con
 		if (ret)
 			return ERR_PTR(ret);
 
-		if (name)
-			back->idx = index;
+		back->idx = index;
 
 		return back;
 	}
@@ -1005,6 +994,24 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con
 	return ERR_PTR(-EPROBE_DEFER);
 }
 
+static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name,
+							 struct fwnode_handle *fwnode)
+{
+	unsigned int index;
+	int ret;
+
+	if (name) {
+		ret = device_property_match_string(dev, "io-backend-names", name);
+		if (ret < 0)
+			return ERR_PTR(ret);
+		index = ret;
+	} else {
+		index = 0;
+	}
+
+	return __devm_iio_backend_fwnode_get_by_index(dev, fwnode, index);
+}
+
 /**
  * devm_iio_backend_get - Device managed backend device get
  * @dev: Consumer device for the backend
@@ -1021,6 +1028,22 @@ struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name)
 }
 EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get, "IIO_BACKEND");
 
+/**
+ * devm_iio_backend_get_by_index - Device managed backend device get by index
+ * @dev: Consumer device for the backend
+ * @index: Index of the backend in the io-backends property
+ *
+ * Gets the backend at @index associated with @dev.
+ *
+ * RETURNS:
+ * A backend pointer, negative error pointer otherwise.
+ */
+struct iio_backend *devm_iio_backend_get_by_index(struct device *dev, unsigned int index)
+{
+	return __devm_iio_backend_fwnode_get_by_index(dev, dev_fwnode(dev), index);
+}
+EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get_by_index, "IIO_BACKEND");
+
 /**
  * devm_iio_backend_fwnode_get - Device managed backend firmware node get
  * @dev: Consumer device for the backend
diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
index 4d15c2a9802c..3f95ed1fdf9e 100644
--- a/include/linux/iio/backend.h
+++ b/include/linux/iio/backend.h
@@ -261,6 +261,7 @@ int iio_backend_extend_chan_spec(struct iio_backend *back,
 bool iio_backend_has_caps(struct iio_backend *back, u32 caps);
 void *iio_backend_get_priv(const struct iio_backend *conv);
 struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name);
+struct iio_backend *devm_iio_backend_get_by_index(struct device *dev, unsigned int index);
 struct iio_backend *devm_iio_backend_fwnode_get(struct device *dev,
 						const char *name,
 						struct fwnode_handle *fwnode);
-- 
2.43.0


^ permalink raw reply related

* [PATCH v9 3/3] iio: adc: ad4080: add support for AD4880 dual-channel ADC
From: Antoniu Miclaus @ 2026-04-20 10:12 UTC (permalink / raw)
  To: Lars-Peter Clausen, Michael Hennerich, Antoniu Miclaus,
	Jonathan Cameron, David Lechner, Nuno Sá, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
	devicetree, linux-kernel
In-Reply-To: <20260420101225.4173-1-antoniu.miclaus@analog.com>

Add support for the AD4880, a dual-channel 20-bit 40MSPS SAR ADC with
integrated fully differential amplifiers (FDA).

The AD4880 has two independent ADC channels, each with its own SPI
configuration interface. The driver uses spi_new_ancillary_device() to
create an additional SPI device for the second channel, allowing both
channels to share the same SPI bus with different chip selects.

Reviewed-by: David Lechner <dlechner@baylibre.com>
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
Changes in v9:
  - No changes

 drivers/iio/adc/ad4080.c | 257 +++++++++++++++++++++++++++++----------
 1 file changed, 195 insertions(+), 62 deletions(-)

diff --git a/drivers/iio/adc/ad4080.c b/drivers/iio/adc/ad4080.c
index 204ad198342b..265d85ac171a 100644
--- a/drivers/iio/adc/ad4080.c
+++ b/drivers/iio/adc/ad4080.c
@@ -16,6 +16,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
@@ -134,6 +135,9 @@
 #define AD4086_CHIP_ID						0x0056
 #define AD4087_CHIP_ID						0x0057
 #define AD4088_CHIP_ID						0x0058
+#define AD4880_CHIP_ID						0x0750
+
+#define AD4080_MAX_CHANNELS					2
 
 #define AD4080_LVDS_CNV_CLK_CNT_MAX				7
 
@@ -179,8 +183,9 @@ struct ad4080_chip_info {
 };
 
 struct ad4080_state {
-	struct regmap			*regmap;
-	struct iio_backend		*back;
+	struct spi_device		*spi[AD4080_MAX_CHANNELS];
+	struct regmap			*regmap[AD4080_MAX_CHANNELS];
+	struct iio_backend		*back[AD4080_MAX_CHANNELS];
 	const struct ad4080_chip_info	*info;
 	/*
 	 * Synchronize access to members the of driver state, and ensure
@@ -189,7 +194,7 @@ struct ad4080_state {
 	struct mutex			lock;
 	unsigned int			num_lanes;
 	unsigned long			clk_rate;
-	enum ad4080_filter_type		filter_type;
+	enum ad4080_filter_type		filter_type[AD4080_MAX_CHANNELS];
 	bool				lvds_cnv_en;
 };
 
@@ -206,9 +211,9 @@ static int ad4080_reg_access(struct iio_dev *indio_dev, unsigned int reg,
 	struct ad4080_state *st = iio_priv(indio_dev);
 
 	if (readval)
-		return regmap_read(st->regmap, reg, readval);
+		return regmap_read(st->regmap[0], reg, readval);
 
-	return regmap_write(st->regmap, reg, writeval);
+	return regmap_write(st->regmap[0], reg, writeval);
 }
 
 static int ad4080_get_scale(struct ad4080_state *st, int *val, int *val2)
@@ -229,8 +234,9 @@ static unsigned int ad4080_get_dec_rate(struct iio_dev *dev,
 	struct ad4080_state *st = iio_priv(dev);
 	int ret;
 	unsigned int data;
+	unsigned int ch = chan->channel;
 
-	ret = regmap_read(st->regmap, AD4080_REG_FILTER_CONFIG, &data);
+	ret = regmap_read(st->regmap[ch], AD4080_REG_FILTER_CONFIG, &data);
 	if (ret)
 		return ret;
 
@@ -242,13 +248,14 @@ static int ad4080_set_dec_rate(struct iio_dev *dev,
 			       unsigned int mode)
 {
 	struct ad4080_state *st = iio_priv(dev);
+	unsigned int ch = chan->channel;
 
 	guard(mutex)(&st->lock);
 
-	if ((st->filter_type >= SINC_5 && mode >= 512) || mode < 2)
+	if ((st->filter_type[ch] >= SINC_5 && mode >= 512) || mode < 2)
 		return -EINVAL;
 
-	return regmap_update_bits(st->regmap, AD4080_REG_FILTER_CONFIG,
+	return regmap_update_bits(st->regmap[ch], AD4080_REG_FILTER_CONFIG,
 				  AD4080_FILTER_CONFIG_SINC_DEC_RATE_MSK,
 				  FIELD_PREP(AD4080_FILTER_CONFIG_SINC_DEC_RATE_MSK,
 					     (ilog2(mode) - 1)));
@@ -268,15 +275,15 @@ static int ad4080_read_raw(struct iio_dev *indio_dev,
 		dec_rate = ad4080_get_dec_rate(indio_dev, chan);
 		if (dec_rate < 0)
 			return dec_rate;
-		if (st->filter_type == SINC_5_COMP)
+		if (st->filter_type[chan->channel] == SINC_5_COMP)
 			dec_rate *= 2;
-		if (st->filter_type)
+		if (st->filter_type[chan->channel])
 			*val = DIV_ROUND_CLOSEST(st->clk_rate, dec_rate);
 		else
 			*val = st->clk_rate;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
-		if (st->filter_type == FILTER_NONE) {
+		if (st->filter_type[chan->channel] == FILTER_NONE) {
 			*val = 1;
 		} else {
 			*val = ad4080_get_dec_rate(indio_dev, chan);
@@ -297,7 +304,7 @@ static int ad4080_write_raw(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
-		if (st->filter_type == FILTER_NONE && val > 1)
+		if (st->filter_type[chan->channel] == FILTER_NONE && val > 1)
 			return -EINVAL;
 
 		return ad4080_set_dec_rate(indio_dev, chan, val);
@@ -306,23 +313,23 @@ static int ad4080_write_raw(struct iio_dev *indio_dev,
 	}
 }
 
-static int ad4080_lvds_sync_write(struct ad4080_state *st)
+static int ad4080_lvds_sync_write(struct ad4080_state *st, unsigned int ch)
 {
-	struct device *dev = regmap_get_device(st->regmap);
+	struct device *dev = regmap_get_device(st->regmap[ch]);
 	int ret;
 
-	ret = regmap_set_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A,
+	ret = regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A,
 			      AD4080_ADC_DATA_INTF_CONFIG_A_INTF_CHK_EN);
 	if (ret)
 		return ret;
 
-	ret = iio_backend_interface_data_align(st->back, 10000);
+	ret = iio_backend_interface_data_align(st->back[ch], 10000);
 	if (ret)
 		return dev_err_probe(dev, ret,
 				     "Data alignment process failed\n");
 
 	dev_dbg(dev, "Success: Pattern correct and Locked!\n");
-	return regmap_clear_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A,
+	return regmap_clear_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A,
 				 AD4080_ADC_DATA_INTF_CONFIG_A_INTF_CHK_EN);
 }
 
@@ -331,9 +338,10 @@ static int ad4080_get_filter_type(struct iio_dev *dev,
 {
 	struct ad4080_state *st = iio_priv(dev);
 	unsigned int data;
+	unsigned int ch = chan->channel;
 	int ret;
 
-	ret = regmap_read(st->regmap, AD4080_REG_FILTER_CONFIG, &data);
+	ret = regmap_read(st->regmap[ch], AD4080_REG_FILTER_CONFIG, &data);
 	if (ret)
 		return ret;
 
@@ -345,6 +353,7 @@ static int ad4080_set_filter_type(struct iio_dev *dev,
 				  unsigned int mode)
 {
 	struct ad4080_state *st = iio_priv(dev);
+	unsigned int ch = chan->channel;
 	int dec_rate;
 	int ret;
 
@@ -357,18 +366,18 @@ static int ad4080_set_filter_type(struct iio_dev *dev,
 	if (mode >= SINC_5 && dec_rate >= 512)
 		return -EINVAL;
 
-	ret = iio_backend_filter_type_set(st->back, mode);
+	ret = iio_backend_filter_type_set(st->back[ch], mode);
 	if (ret)
 		return ret;
 
-	ret = regmap_update_bits(st->regmap, AD4080_REG_FILTER_CONFIG,
+	ret = regmap_update_bits(st->regmap[ch], AD4080_REG_FILTER_CONFIG,
 				 AD4080_FILTER_CONFIG_FILTER_SEL_MSK,
 				 FIELD_PREP(AD4080_FILTER_CONFIG_FILTER_SEL_MSK,
 					    mode));
 	if (ret)
 		return ret;
 
-	st->filter_type = mode;
+	st->filter_type[ch] = mode;
 
 	return 0;
 }
@@ -382,14 +391,14 @@ static int ad4080_read_avail(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
-		switch (st->filter_type) {
+		switch (st->filter_type[chan->channel]) {
 		case FILTER_NONE:
 			*vals = ad4080_dec_rate_none;
 			*length = ARRAY_SIZE(ad4080_dec_rate_none);
 			break;
 		default:
 			*vals = ad4080_dec_rate_avail;
-			*length = st->filter_type >= SINC_5 ?
+			*length = st->filter_type[chan->channel] >= SINC_5 ?
 				  (ARRAY_SIZE(ad4080_dec_rate_avail) - 2) :
 				  ARRAY_SIZE(ad4080_dec_rate_avail);
 			break;
@@ -401,6 +410,28 @@ static int ad4080_read_avail(struct iio_dev *indio_dev,
 	}
 }
 
+static int ad4880_update_scan_mode(struct iio_dev *indio_dev,
+				   const unsigned long *scan_mask)
+{
+	struct ad4080_state *st = iio_priv(indio_dev);
+	int ret;
+
+	for (unsigned int ch = 0; ch < st->info->num_channels; ch++) {
+		/*
+		 * Each backend has a single channel (channel 0 from the
+		 * backend's perspective), so always use channel index 0.
+		 */
+		if (test_bit(ch, scan_mask))
+			ret = iio_backend_chan_enable(st->back[ch], 0);
+		else
+			ret = iio_backend_chan_disable(st->back[ch], 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static const struct iio_info ad4080_iio_info = {
 	.debugfs_reg_access = ad4080_reg_access,
 	.read_raw = ad4080_read_raw,
@@ -408,6 +439,19 @@ static const struct iio_info ad4080_iio_info = {
 	.read_avail = ad4080_read_avail,
 };
 
+/*
+ * AD4880 needs update_scan_mode to enable/disable individual backend channels.
+ * Single-channel devices don't need this as their backends may not implement
+ * chan_enable/chan_disable operations.
+ */
+static const struct iio_info ad4880_iio_info = {
+	.debugfs_reg_access = ad4080_reg_access,
+	.read_raw = ad4080_read_raw,
+	.write_raw = ad4080_write_raw,
+	.read_avail = ad4080_read_avail,
+	.update_scan_mode = ad4880_update_scan_mode,
+};
+
 static const struct iio_enum ad4080_filter_type_enum = {
 	.items = ad4080_filter_type_iio_enum,
 	.num_items = ARRAY_SIZE(ad4080_filter_type_iio_enum),
@@ -422,17 +466,28 @@ static struct iio_chan_spec_ext_info ad4080_ext_info[] = {
 	{ }
 };
 
-#define AD4080_CHANNEL_DEFINE(bits, storage) {				\
+/*
+ * AD4880 needs per-channel filter configuration since each channel has
+ * its own independent ADC with separate SPI interface.
+ */
+static struct iio_chan_spec_ext_info ad4880_ext_info[] = {
+	IIO_ENUM("filter_type", IIO_SEPARATE, &ad4080_filter_type_enum),
+	IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE,
+			   &ad4080_filter_type_enum),
+	{ }
+};
+
+#define AD4080_CHANNEL_DEFINE(bits, storage, idx) {			\
 	.type = IIO_VOLTAGE,						\
 	.indexed = 1,							\
-	.channel = 0,							\
+	.channel = (idx),						\
 	.info_mask_separate = BIT(IIO_CHAN_INFO_SCALE),			\
 	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) |	\
 			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),		\
 	.info_mask_shared_by_all_available =				\
 			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),		\
 	.ext_info = ad4080_ext_info,					\
-	.scan_index = 0,						\
+	.scan_index = (idx),						\
 	.scan_type = {							\
 		.sign = 's',						\
 		.realbits = (bits),					\
@@ -440,23 +495,51 @@ static struct iio_chan_spec_ext_info ad4080_ext_info[] = {
 	},								\
 }
 
-static const struct iio_chan_spec ad4080_channel = AD4080_CHANNEL_DEFINE(20, 32);
+/*
+ * AD4880 has per-channel attributes (filter_type, oversampling_ratio,
+ * sampling_frequency) since each channel has its own independent ADC
+ * with separate SPI configuration interface.
+ */
+#define AD4880_CHANNEL_DEFINE(bits, storage, idx) {		\
+	.type = IIO_VOLTAGE,						\
+	.indexed = 1,							\
+	.channel = (idx),						\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) |		\
+			BIT(IIO_CHAN_INFO_SAMP_FREQ) |			\
+			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),		\
+	.info_mask_separate_available =					\
+			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),		\
+	.ext_info = ad4880_ext_info,				\
+	.scan_index = (idx),						\
+	.scan_type = {							\
+		.sign = 's',						\
+		.realbits = (bits),					\
+		.storagebits = (storage),				\
+	},								\
+}
 
-static const struct iio_chan_spec ad4081_channel = AD4080_CHANNEL_DEFINE(20, 32);
+static const struct iio_chan_spec ad4080_channel = AD4080_CHANNEL_DEFINE(20, 32, 0);
 
-static const struct iio_chan_spec ad4082_channel = AD4080_CHANNEL_DEFINE(20, 32);
+static const struct iio_chan_spec ad4081_channel = AD4080_CHANNEL_DEFINE(20, 32, 0);
 
-static const struct iio_chan_spec ad4083_channel = AD4080_CHANNEL_DEFINE(16, 16);
+static const struct iio_chan_spec ad4082_channel = AD4080_CHANNEL_DEFINE(20, 32, 0);
 
-static const struct iio_chan_spec ad4084_channel = AD4080_CHANNEL_DEFINE(16, 16);
+static const struct iio_chan_spec ad4083_channel = AD4080_CHANNEL_DEFINE(16, 16, 0);
 
-static const struct iio_chan_spec ad4085_channel = AD4080_CHANNEL_DEFINE(16, 16);
+static const struct iio_chan_spec ad4084_channel = AD4080_CHANNEL_DEFINE(16, 16, 0);
 
-static const struct iio_chan_spec ad4086_channel = AD4080_CHANNEL_DEFINE(14, 16);
+static const struct iio_chan_spec ad4085_channel = AD4080_CHANNEL_DEFINE(16, 16, 0);
 
-static const struct iio_chan_spec ad4087_channel = AD4080_CHANNEL_DEFINE(14, 16);
+static const struct iio_chan_spec ad4086_channel = AD4080_CHANNEL_DEFINE(14, 16, 0);
 
-static const struct iio_chan_spec ad4088_channel = AD4080_CHANNEL_DEFINE(14, 16);
+static const struct iio_chan_spec ad4087_channel = AD4080_CHANNEL_DEFINE(14, 16, 0);
+
+static const struct iio_chan_spec ad4088_channel = AD4080_CHANNEL_DEFINE(14, 16, 0);
+
+static const struct iio_chan_spec ad4880_channels[] = {
+	AD4880_CHANNEL_DEFINE(20, 32, 0),
+	AD4880_CHANNEL_DEFINE(20, 32, 1),
+};
 
 static const struct ad4080_chip_info ad4080_chip_info = {
 	.name = "ad4080",
@@ -548,25 +631,34 @@ static const struct ad4080_chip_info ad4088_chip_info = {
 	.lvds_cnv_clk_cnt_max = 8,
 };
 
-static int ad4080_setup(struct iio_dev *indio_dev)
+static const struct ad4080_chip_info ad4880_chip_info = {
+	.name = "ad4880",
+	.product_id = AD4880_CHIP_ID,
+	.scale_table = ad4080_scale_table,
+	.num_scales = ARRAY_SIZE(ad4080_scale_table),
+	.num_channels = 2,
+	.channels = ad4880_channels,
+	.lvds_cnv_clk_cnt_max = AD4080_LVDS_CNV_CLK_CNT_MAX,
+};
+
+static int ad4080_setup_channel(struct ad4080_state *st, unsigned int ch)
 {
-	struct ad4080_state *st = iio_priv(indio_dev);
-	struct device *dev = regmap_get_device(st->regmap);
+	struct device *dev = regmap_get_device(st->regmap[ch]);
 	__le16 id_le;
 	u16 id;
 	int ret;
 
-	ret = regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A,
+	ret = regmap_write(st->regmap[ch], AD4080_REG_INTERFACE_CONFIG_A,
 			   AD4080_INTERFACE_CONFIG_A_SW_RESET);
 	if (ret)
 		return ret;
 
-	ret = regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A,
+	ret = regmap_write(st->regmap[ch], AD4080_REG_INTERFACE_CONFIG_A,
 			   AD4080_INTERFACE_CONFIG_A_SDO_ENABLE);
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_read(st->regmap, AD4080_REG_PRODUCT_ID_L, &id_le,
+	ret = regmap_bulk_read(st->regmap[ch], AD4080_REG_PRODUCT_ID_L, &id_le,
 			       sizeof(id_le));
 	if (ret)
 		return ret;
@@ -575,18 +667,18 @@ static int ad4080_setup(struct iio_dev *indio_dev)
 	if (id != st->info->product_id)
 		dev_info(dev, "Unrecognized CHIP_ID 0x%X\n", id);
 
-	ret = regmap_set_bits(st->regmap, AD4080_REG_GPIO_CONFIG_A,
+	ret = regmap_set_bits(st->regmap[ch], AD4080_REG_GPIO_CONFIG_A,
 			      AD4080_GPIO_CONFIG_A_GPO_1_EN);
 	if (ret)
 		return ret;
 
-	ret = regmap_write(st->regmap, AD4080_REG_GPIO_CONFIG_B,
+	ret = regmap_write(st->regmap[ch], AD4080_REG_GPIO_CONFIG_B,
 			   FIELD_PREP(AD4080_GPIO_CONFIG_B_GPIO_1_SEL_MSK,
 				      AD4080_GPIO_CONFIG_B_GPIO_FILTER_RES_RDY));
 	if (ret)
 		return ret;
 
-	ret = iio_backend_num_lanes_set(st->back, st->num_lanes);
+	ret = iio_backend_num_lanes_set(st->back[ch], st->num_lanes);
 	if (ret)
 		return ret;
 
@@ -594,7 +686,7 @@ static int ad4080_setup(struct iio_dev *indio_dev)
 		return 0;
 
 	/* Set maximum LVDS Data Transfer Latency */
-	ret = regmap_update_bits(st->regmap,
+	ret = regmap_update_bits(st->regmap[ch],
 				 AD4080_REG_ADC_DATA_INTF_CONFIG_B,
 				 AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK,
 				 FIELD_PREP(AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK,
@@ -603,24 +695,38 @@ static int ad4080_setup(struct iio_dev *indio_dev)
 		return ret;
 
 	if (st->num_lanes > 1) {
-		ret = regmap_set_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A,
+		ret = regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A,
 				      AD4080_ADC_DATA_INTF_CONFIG_A_SPI_LVDS_LANES);
 		if (ret)
 			return ret;
 	}
 
-	ret = regmap_set_bits(st->regmap,
+	ret = regmap_set_bits(st->regmap[ch],
 			      AD4080_REG_ADC_DATA_INTF_CONFIG_B,
 			      AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_EN);
 	if (ret)
 		return ret;
 
-	return ad4080_lvds_sync_write(st);
+	return ad4080_lvds_sync_write(st, ch);
 }
 
-static int ad4080_properties_parse(struct ad4080_state *st)
+static int ad4080_setup(struct iio_dev *indio_dev)
+{
+	struct ad4080_state *st = iio_priv(indio_dev);
+	int ret;
+
+	for (unsigned int ch = 0; ch < st->info->num_channels; ch++) {
+		ret = ad4080_setup_channel(st, ch);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int ad4080_properties_parse(struct ad4080_state *st,
+				   struct device *dev)
 {
-	struct device *dev = regmap_get_device(st->regmap);
 
 	st->lvds_cnv_en = device_property_read_bool(dev, "adi,lvds-cnv-enable");
 
@@ -655,14 +761,28 @@ static int ad4080_probe(struct spi_device *spi)
 		return dev_err_probe(dev, ret,
 				     "failed to get and enable supplies\n");
 
-	st->regmap = devm_regmap_init_spi(spi, &ad4080_regmap_config);
-	if (IS_ERR(st->regmap))
-		return PTR_ERR(st->regmap);
+	/* Setup primary SPI device (channel 0) */
+	st->spi[0] = spi;
+	st->regmap[0] = devm_regmap_init_spi(spi, &ad4080_regmap_config);
+	if (IS_ERR(st->regmap[0]))
+		return PTR_ERR(st->regmap[0]);
 
 	st->info = spi_get_device_match_data(spi);
 	if (!st->info)
 		return -ENODEV;
 
+	/* Setup ancillary SPI devices for additional channels */
+	for (unsigned int ch = 1; ch < st->info->num_channels; ch++) {
+		st->spi[ch] = devm_spi_new_ancillary_device(spi, spi_get_chipselect(spi, ch));
+		if (IS_ERR(st->spi[ch]))
+			return dev_err_probe(dev, PTR_ERR(st->spi[ch]),
+					     "failed to register ancillary device\n");
+
+		st->regmap[ch] = devm_regmap_init_spi(st->spi[ch], &ad4080_regmap_config);
+		if (IS_ERR(st->regmap[ch]))
+			return PTR_ERR(st->regmap[ch]);
+	}
+
 	ret = devm_mutex_init(dev, &st->lock);
 	if (ret)
 		return ret;
@@ -670,9 +790,10 @@ static int ad4080_probe(struct spi_device *spi)
 	indio_dev->name = st->info->name;
 	indio_dev->channels = st->info->channels;
 	indio_dev->num_channels = st->info->num_channels;
-	indio_dev->info = &ad4080_iio_info;
+	indio_dev->info = st->info->num_channels > 1 ?
+			  &ad4880_iio_info : &ad4080_iio_info;
 
-	ret = ad4080_properties_parse(st);
+	ret = ad4080_properties_parse(st, dev);
 	if (ret)
 		return ret;
 
@@ -682,15 +803,25 @@ static int ad4080_probe(struct spi_device *spi)
 
 	st->clk_rate = clk_get_rate(clk);
 
-	st->back = devm_iio_backend_get(dev, NULL);
-	if (IS_ERR(st->back))
-		return PTR_ERR(st->back);
+	/* Get backends for all channels */
+	for (unsigned int ch = 0; ch < st->info->num_channels; ch++) {
+		st->back[ch] = devm_iio_backend_get_by_index(dev, ch);
+		if (IS_ERR(st->back[ch]))
+			return PTR_ERR(st->back[ch]);
 
-	ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
-	if (ret)
-		return ret;
+		ret = devm_iio_backend_enable(dev, st->back[ch]);
+		if (ret)
+			return ret;
+	}
 
-	ret = devm_iio_backend_enable(dev, st->back);
+	/*
+	 * Request buffer from the first backend only. For multi-channel
+	 * devices (e.g., AD4880), the FPGA uses two axi_ad408x IP instances
+	 * (one per ADC channel) whose outputs are combined by a packer block
+	 * that interleaves all channel data into a single DMA stream routed
+	 * through the first backend's clock domain.
+	 */
+	ret = devm_iio_backend_request_buffer(dev, st->back[0], indio_dev);
 	if (ret)
 		return ret;
 
@@ -711,6 +842,7 @@ static const struct spi_device_id ad4080_id[] = {
 	{ "ad4086", (kernel_ulong_t)&ad4086_chip_info },
 	{ "ad4087", (kernel_ulong_t)&ad4087_chip_info },
 	{ "ad4088", (kernel_ulong_t)&ad4088_chip_info },
+	{ "ad4880", (kernel_ulong_t)&ad4880_chip_info },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, ad4080_id);
@@ -725,6 +857,7 @@ static const struct of_device_id ad4080_of_match[] = {
 	{ .compatible = "adi,ad4086", &ad4086_chip_info },
 	{ .compatible = "adi,ad4087", &ad4087_chip_info },
 	{ .compatible = "adi,ad4088", &ad4088_chip_info },
+	{ .compatible = "adi,ad4880", &ad4880_chip_info },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, ad4080_of_match);
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH 1/2] arm64: dts: qcom: sc8280xp: add several missing pdc map entries
From: Konrad Dybcio @ 2026-04-20 10:21 UTC (permalink / raw)
  To: Pengyu Luo
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <CAH2e8h4bMve_hfW6VXynBh--DgwW2v8=XuVpAzUoS8N_73ZEhg@mail.gmail.com>

On 4/20/26 11:53 AM, Pengyu Luo wrote:
> On Mon, Apr 20, 2026 at 4:32 PM Konrad Dybcio
> <konrad.dybcio@oss.qualcomm.com> wrote:
>>
>> On 4/19/26 7:32 PM, Pengyu Luo wrote:
>>> pdc 215, 256, 257 are missing, but we can find tlmm pin 103, 84, 90
>>> are mapped to them respectively, so add the map entries from pdc to
>>> gic. These entries are reversed from .data section of qcgpio.sys
>>>
>>> Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com>
>>> ---
>>
>> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>
>> Konrad
>>
>> The below change on top will fully align it with the data in the docs
>> (no functional change)
>>
> 
> Glad to know. Could you please help to check the tlmm map too? When I
> was parsing the binary, I found
> 
> tlmm 65535 => pdc 70 => gic 520
> tlmm 65535 => pdc 174 => gic 733
> tlmm 65535 => pdc 175 => gic 734
> tlmm 65535 => pdc 176 => gic 735
> tlmm 65535 => pdc 177 => gic 736
> tlmm 65535 => pdc 178 => gic 737
> tlmm 65535 => pdc 184 => gic 743
> tlmm 65535 => pdc 185 => gic 744
> tlmm 65535 => pdc 186 => gic 745
> tlmm 65535 => pdc 187 => gic 746
> tlmm 65535 => pdc 188 => gic 747
> tlmm 65535 => pdc 194 => gic 753
> tlmm 65535 => pdc 195 => gic 754
> tlmm 65535 => pdc 196 => gic 755
> tlmm 65535 => pdc 197 => gic 756
> tlmm 65535 => pdc 198 => gic 757
> tlmm 65535 => pdc 199 => gic 416
> tlmm 65535 => pdc 204 => gic 462
> tlmm 65535 => pdc 205 => gic 264
> 
> If 65536 means the pin is missing, I will send v2 to remove the tlmm
> map together with the pdc removal.

These seem to be LPASS/SSC GPIOs

There are missing pairs of:

TLMM 151 -> PDC 264 -> GIC 191
TLMM 143 -> PDC 261 -> GIC 402

and very interestingly, GPIO 190 has two mappings:
PDC 70 -> GIC 552
PDC 178 -> GIC 769


Konrad

^ permalink raw reply

* Re: [PATCH] arm64: dts: qcom: qcs6490-rb3gen2: Enable 4-lane DisplayPort Alt Mode
From: Neil Armstrong @ 2026-04-20 10:25 UTC (permalink / raw)
  To: Mahadevan P, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260420-kodiak_4k-v1-1-83dfc66b8f06@oss.qualcomm.com>

On 4/20/26 12:00, Mahadevan P wrote:
> Add the mode-switch property to the QMP combo PHY so that mode-switch
> events are routed to it, allowing the PHY to enter DisplayPort Alternate
> Mode. Expand the DP data-lanes assignment from two to four lanes to make
> use of the full link bandwidth available in this configuration.
> 
> Signed-off-by: Mahadevan P <mahadevan.p@oss.qualcomm.com>
> ---
>   arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
> index e393ccf1884a..0c180e49816f 100644
> --- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
> +++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
> @@ -789,7 +789,7 @@ &mdss_dp {
>   };
>   
>   &mdss_dp_out {
> -	data-lanes = <0 1>;
> +	data-lanes = <0 1 2 3>;

This property should be moved to kodiak.dtsi

>   	remote-endpoint = <&usb_dp_qmpphy_dp_in>;
>   };
>   
> @@ -1391,6 +1391,7 @@ &usb_1_qmpphy {
>   	vdda-phy-supply = <&vreg_l6b_1p2>;
>   	vdda-pll-supply = <&vreg_l1b_0p912>;
>   
> +	mode-switch;
>   	orientation-switch;

Same for those.

Neil

>   
>   	status = "okay";
> 
> ---
> base-commit: 452c3b1ea875276105ac90ba474f72b4cd9b77a2
> change-id: 20260417-kodiak_4k-891ef2221e4b
> 
> Best regards,


^ permalink raw reply

* Re: [PATCH] dts: riscv: spacemit: k3: only keep spacemit,k1-i2c
From: Krzysztof Kozlowski @ 2026-04-20 10:28 UTC (permalink / raw)
  To: Sandie Cao, Yixun Lan
  Cc: Troy Mitchell, Conor Dooley, Rob Herring, Krzysztof Kozlowski,
	Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
	spacemit, linux-riscv, devicetree, linux-kernel,
	kernel test robot
In-Reply-To: <407ce3d77416bb2522b7906b0df3d5adf02c27ee.5595e961.9ee2.4959.8935.9a8f33812b0c@feishu.cn>

On 20/04/2026 11:26, Sandie Cao wrote:
> 
> Please know that, I send patch[1] to add DeepComputing FML13V05 board device tree.  The patch is based on k1/dt-for-next[2]. 
> And it meets dtscheck issue:
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/r/202604140259.eKDaxKua-lkp@intel.com/
> 
> On k1/dt-for-next, it doesn't have spacemit,k3-i2c in Documentation/devicetree/bindings/i2c/spacemit,k1-i2c.yaml.
> Or I use the wrong branch? 
> 
> And what should I do for my patch[1] ?  

Test your patch on linux-next. See also maintainer-soc and
maintainer-soc-clean-dts profiles in kernel.


Best regards,
Krzysztof

^ permalink raw reply

* [PATCH] dt-bindings: iio: dac: mcp47feb02: Fix I2C address in example
From: Ariana Lazar @ 2026-04-20 10:36 UTC (permalink / raw)
  To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Conor Dooley, Jonathan Cameron, linux-iio, devicetree,
	linux-kernel, Ariana Lazar

Change example reg value from 0 to 0x60 in order to use a valid I2C address

Fixes: 4ba12d304175 ("dt-bindings: iio: dac: adding support for Microchip MCP47FEB02")
Link: https://lore.kernel.org/all/dd0dbadb-604b-4f12-8674-268b7db096fd@baylibre.com/
Signed-off-by: Ariana Lazar <ariana.lazar@microchip.com>
---
 .../bindings/iio/dac/microchip,mcp47feb02.yaml     | 32 +++++++++++-----------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
index d2466aa6bda2106a8b695347a0edf38462294d03..95ddc8321eff34ed27dab8ce712210d2cb9ae785 100644
--- a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
@@ -280,23 +280,23 @@ examples:
 
         #address-cells = <1>;
         #size-cells = <0>;
-        dac@0 {
-          compatible = "microchip,mcp47feb02";
-          reg = <0>;
-          vdd-supply = <&vdac_vdd>;
-          vref-supply = <&vref_reg>;
+        dac@60 {
+            compatible = "microchip,mcp47feb02";
+            reg = <0x60>;
+            vdd-supply = <&vdac_vdd>;
+            vref-supply = <&vref_reg>;
 
-          #address-cells = <1>;
-          #size-cells = <0>;
-          channel@0 {
-            reg = <0>;
-            label = "Adjustable_voltage_ch0";
-          };
+            #address-cells = <1>;
+            #size-cells = <0>;
+            channel@0 {
+                reg = <0>;
+                label = "Adjustable_voltage_ch0";
+            };
 
-          channel@1 {
-            reg = <0x1>;
-            label = "Adjustable_voltage_ch1";
-          };
-      };
+            channel@1 {
+                reg = <0x1>;
+                label = "Adjustable_voltage_ch1";
+            };
+        };
     };
 ...

---
base-commit: d2a4ec19d2a2e54c23b5180e939994d3da4a6b91
change-id: 20260417-mcp47feb02-fix6-bd6694d84750

Best regards,
-- 
Ariana Lazar <ariana.lazar@microchip.com>


^ permalink raw reply related

* Re: [PATCH v2 3/3] arm64: dts: qcom: sdm630: assign adsp_mem region to ADSP FastRPC node
From: Ekansh Gupta @ 2026-04-20 10:42 UTC (permalink / raw)
  To: Nickolay Goppen, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, devicetree, linux-kernel,
	~postmarketos/upstreaming, Konrad Dybcio, Dmitry Baryshkov
In-Reply-To: <20260420-qcom-sdm660-cdsp-adsp-fastrpc-dts-fix-v2-3-f6c7ab3c889a@mainlining.org>

On 20-04-2026 15:12, Nickolay Goppen wrote:
> Downstream [1] ADSP FastRPC node has the adsp_mem region assigned, so
> assign it to the ADSP FastRPC node.
> 
> [1]: https://github.com/xiaomi-sdm660/android_kernel_xiaomi_sdm660/blob/11-EAS/arch/arm/boot/dts/qcom/sdm660.dtsi#L1693
> 
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Signed-off-by: Nickolay Goppen <setotau@mainlining.org>
> ---
>  arch/arm64/boot/dts/qcom/sdm630.dtsi | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi
> index 4b47efdb57b2..2dc53814aa55 100644
> --- a/arch/arm64/boot/dts/qcom/sdm630.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi
> @@ -2455,6 +2455,9 @@ fastrpc {
>  					compatible = "qcom,fastrpc";
>  					qcom,glink-channels = "fastrpcglink-apps-dsp";
>  					label = "adsp";
> +					memory-region = <&adsp_mem>;
> +					qcom,vmids = <QCOM_SCM_VMID_LPASS
> +							  QCOM_SCM_VMID_ADSP_HEAP>;
align this line with <
>  					qcom,non-secure-domain;
>  					#address-cells = <1>;
>  					#size-cells = <0>;
> 


^ permalink raw reply

* [PATCH v5 0/9] Add Renesas RZ/G3E GPT support
From: Biju @ 2026-04-20 10:43 UTC (permalink / raw)
  To: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm, Philipp Zabel
  Cc: Biju Das, linux-pwm, devicetree, linux-kernel, linux-renesas-soc,
	Prabhakar Mahadev Lad, Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

This series extends the RZ/G2L GPT PWM driver with RZ/G3E SoC support.

The RZ/G3E GPT has a number of hardware differences compared to RZ/G2L:
it exposes 16 channels (across two GPT instances of 8 channels each),
uses a 4-bit GTCR prescaler field (versus 3-bit on RZ/G2L), and has a
discontinuous prescale sequence with powers-of-2 scaling rather than the
continuous powers-of-4 sequence on RZ/G2L. It also has additional clocks
and resets (bus clock and rst_s).

To accommodate these differences cleanly the series proceeds as follows:

Patches 1-2 add DT binding documentation for the renesas,poegs property
(allowing GPT channels to be linked with POEG for output-disable) and
implement the corresponding driver support. This configures GTINTAD to
route output-disable requests to the correct POEG group and sets GTIOR
to tri-state both output pins on an output-disable event.

Patch 3 is a small cleanup removing an unused parameter from
rzg2l_gpt_calculate_prescale().

Patch 4 migrates the driver from the legacy .get_state/.apply ops to
the new waveform callback interface, introducing struct
rzg2l_gpt_waveform to hold the hardware configuration (gtpr, gtccr,
prescale) for a single channel.

Patches 5-7 introduce struct rzg2l_gpt_info to capture SoC-specific
hardware differences, adding fields for the GTCR prescaler mask
(gtcr_tpcs), the prescaler multiplier (prescale_mult), and a
calculate_prescale() function pointer. This cleanly abstracts the
per-SoC prescaler logic needed for RZ/G3E.

Patch 8 adds DT binding documentation for the RZ/G3E GPT
(renesas,r9a09g047-gpt), covering its 16-channel layout, 64 interrupts,
dual clocks and dual resets.

Patch 9 adds the RZ/G3E driver support itself, wiring up the new
rzg3e_data match entry with its own prescale calculation, prescaler
field mask, and prescale multiplier.

v4->v5:
 * Merged GPT linking POEG patch series here.
 * Dropped suspend/resume patch; will be added later.
 * Updated commit description for patches #2, #4, #5, and #6.
 * Replaced return type of rzg2l_gpt_poeg_init() from void to int and
   probe() check this return value.
 * Added more error checks in rzg2l_gpt_poeg_init().
 * Added a patch to drop the unused rzg2l_gpt_chip parameter from
   rzg2l_gpt_calculate_prescale().
 * Updated rzg2l_gpt_round_waveform_tohw() to initialize gtccr when the
   period of the second channel is smaller.
 * Replaced period_ticks with RZG2L_MAX_TICKS for the duty_ticks maximum
   value check in rzg2l_gpt_round_waveform_tohw().
v3->v4:
 * Added wave form callback conversion back to this patch series.
 * Updated rzg2l_gpt_is_ch_enabled() fit into 80-character limit for
   consistency with other functions.
 * Dropped field_{get,prep} as mainline now support it.
 * Updated commit description for patch#3
 * Retained RZG2L_GTCR_TPCS bit definitons
 * Replaced gtcr_tpcs_mask->gtcr_tpcs
 * Updated commit header and description for patch#4
 * Renamed prescale_pow_of_two_mult_factor->prescale_mult
 * Added RZG3E_GTCR_TPCS bit definition for RZ/G3E and added to
   rzg3e_data.
 * Added error checks on suspend() and device set to operational state
   on failure().
 * Added Rb tag from Geert for SoC dtsi.
 * Added SW_GPIO9_CAN1_STB check to gpt0 node.
v2->v3:
 * Added Rb tag from Rob for bindings patch
 * Dropped wave form callback conversion from this patch series as
   it is covered in another series[1]
 * Added suspend/resume support.
v1->v2:
 * Created separate document for RZ/G3E GPT.
 * Updated commit header and description for binding patch.
 * Added waveform callback conversion to this series.
 * Collected tag.
 * Added link to hardware manual
 * Updated limitation section in driver patch.

Biju Das (9):
  dt-bindings: pwm: rzg2l-gpt: Document renesas,poegs property
  pwm: rzg2l-gpt: Add support for gpt linking with poeg
  pwm: rzg2l-gpt: Drop unused rzg2l_gpt_chip parameter from
    rzg2l_gpt_calculate_prescale()
  pwm: rzg2l-gpt: Convert to waveform callbacks
  pwm: rzg2l-gpt: Add info variable to struct rzg2l_gpt_chip
  pwm: rzg2l-gpt: Add prescale_mult variable to struct rzg2l_gpt_info
  pwm: rzg2l-gpt: Add calculate_prescale() callback to struct
    rzg2l_gpt_info
  dt-bindings: pwm: Document RZ/G3E GPT support
  pwm: rzg2l-gpt: Add RZ/G3E support

 .../bindings/pwm/renesas,rzg2l-gpt.yaml       |  23 ++
 .../bindings/pwm/renesas,rzg3e-gpt.yaml       | 323 ++++++++++++++++
 drivers/pwm/pwm-rzg2l-gpt.c                   | 360 ++++++++++++++----
 3 files changed, 626 insertions(+), 80 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pwm/renesas,rzg3e-gpt.yaml

-- 
2.43.0


^ permalink raw reply

* [PATCH v5 1/9] dt-bindings: pwm: rzg2l-gpt: Document renesas,poegs property
From: Biju @ 2026-04-20 10:43 UTC (permalink / raw)
  To: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm
  Cc: Biju Das, linux-pwm, devicetree, linux-kernel, linux-renesas-soc,
	Prabhakar Mahadev Lad, Biju Das
In-Reply-To: <20260420104332.153640-1-biju.das.jz@bp.renesas.com>

From: Biju Das <biju.das.jz@bp.renesas.com>

RZ/G2L GPT IP supports output pin disable function by dead time
error and detecting short-circuits between output pins.

Add documentation for the optional property renesas,poegs to
link a pair of GPT IOs with POEG.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v5:
 * No change
v24 from [1]:
[1] https://lore.kernel.org/all/20250226144531.176819-1-biju.das.jz@bp.renesas.com/
---
 .../bindings/pwm/renesas,rzg2l-gpt.yaml       | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/Documentation/devicetree/bindings/pwm/renesas,rzg2l-gpt.yaml b/Documentation/devicetree/bindings/pwm/renesas,rzg2l-gpt.yaml
index 13b807765a30..98bcde755fb9 100644
--- a/Documentation/devicetree/bindings/pwm/renesas,rzg2l-gpt.yaml
+++ b/Documentation/devicetree/bindings/pwm/renesas,rzg2l-gpt.yaml
@@ -245,6 +245,28 @@ properties:
   resets:
     maxItems: 1
 
+  renesas,poegs:
+    minItems: 1
+    maxItems: 8
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      items:
+        - description: phandle to POEG instance that serves the output disable
+        - enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ]
+          description: |
+            An index identifying pair of GPT channels.
+              <0> : GPT channels 0 and 1
+              <1> : GPT channels 2 and 3
+              <2> : GPT channels 4 and 5
+              <3> : GPT channels 6 and 7
+              <4> : GPT channels 8 and 9
+              <5> : GPT channels 10 and 11
+              <6> : GPT channels 12 and 13
+              <7> : GPT channels 14 and 15
+    description:
+      A list of phandle and channel index pair tuples to the POEGs that handle the
+      output disable for the GPT channels.
+
 required:
   - compatible
   - reg
@@ -375,4 +397,5 @@ examples:
         power-domains = <&cpg>;
         resets = <&cpg R9A07G044_GPT_RST_C>;
         #pwm-cells = <3>;
+        renesas,poegs = <&poeggd 4>;
     };
-- 
2.43.0


^ permalink raw reply related

* [PATCH v5 8/9] dt-bindings: pwm: Document RZ/G3E GPT support
From: Biju @ 2026-04-20 10:43 UTC (permalink / raw)
  To: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Geert Uytterhoeven, Magnus Damm
  Cc: Biju Das, linux-pwm, devicetree, linux-kernel, linux-renesas-soc,
	Prabhakar Mahadev Lad, Biju Das
In-Reply-To: <20260420104332.153640-1-biju.das.jz@bp.renesas.com>

From: Biju Das <biju.das.jz@bp.renesas.com>

Document support for the GPT found on the Renesas RZ/G3E (R9A09G047)
SoC.

The GPT is a 32-bit timer with 16 hardware channels (GPT0: 8 channel
and GPT1: 8channels). The hardware supports simultaneous control of
all channels. PWM waveforms can be generated by controlling the
up-counter, downcounter, or up- and down-counter.

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v4->v5:
 * No change.
v3->v4:
 * No change.
v2->v3:
 * Added Rb tag from Rob.
v1->v2:
 * Created separate document for RZ/G3E GPT.
 * Updated commit header and description.
---
 .../bindings/pwm/renesas,rzg3e-gpt.yaml       | 323 ++++++++++++++++++
 1 file changed, 323 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/renesas,rzg3e-gpt.yaml

diff --git a/Documentation/devicetree/bindings/pwm/renesas,rzg3e-gpt.yaml b/Documentation/devicetree/bindings/pwm/renesas,rzg3e-gpt.yaml
new file mode 100644
index 000000000000..cb4ffab5f47f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/renesas,rzg3e-gpt.yaml
@@ -0,0 +1,323 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/renesas,rzg3e-gpt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G3E General PWM Timer (GPT)
+
+maintainers:
+  - Biju Das <biju.das.jz@bp.renesas.com>
+
+description: |
+  RZ/G3E General PWM Timer (GPT) composed of 16 channels with 32-bit
+  timer. It supports the following functions
+  * 32 bits x 16 channels.
+  * Up-counting or down-counting (saw waves) or up/down-counting
+    (triangle waves) for each counter.
+  * Clock sources independently selectable for each channel.
+  * Four I/O pins per channel.
+  * Two output compare/input capture registers per channel.
+  * For the two output compare/input capture registers of each channel,
+    four registers are provided as buffer registers and are capable of
+    operating as comparison registers when buffering is not in use.
+  * In output compare operation, buffer switching can be at crests or
+    troughs, enabling the generation of laterally asymmetric PWM waveforms.
+  * Registers for setting up frame cycles in each channel (with capability
+    for generating interrupts at overflow or underflow)
+  * Generation of dead times in PWM operation.
+  * Synchronous starting, stopping and clearing counters for arbitrary
+    channels.
+  * Count start, count stop, count clear, up-count, down-count, or input
+    capture operation in response to a maximum of 8 ELC events.
+  * Count start, count stop, count clear, up-count, down-count, or input
+    capture operation in response to the status of two input pins.
+  * Starting, clearing, stopping and up/down counters in response to a
+    maximum of four external triggers.
+  * Output pin disable function by detected short-circuits between output
+    pins.
+  * A/D converter start triggers can be generated.
+  * Compare match A to F event and overflow/underflow event can be output
+    to the ELC.
+  * Enables the noise filter for input capture.
+  * Logical operation between the channel output.
+
+properties:
+  compatible:
+    items:
+      - const: renesas,r9a09g047-gpt  # RZ/G3E
+
+  reg:
+    maxItems: 1
+
+  '#pwm-cells':
+    const: 3
+
+  interrupts:
+    items:
+      - description: Input capture/compare match of the GTCCRA for channel GPT{0,1}.0
+      - description: Input capture/compare match of the GTCCRB for channel GPT{0,1}.0
+      - description: Compare match with the GTCCRC for channel GPT{0,1}.0
+      - description: Compare match with the GTCCRD for channel GPT{0,1}.0
+      - description: Compare match with the GTCCRE for channel GPT{0,1}.0
+      - description: Compare match with the GTCCRF for channel GPT{0,1}.0
+      - description: A and B both high interrupt for channel GPT{0,1}.0
+      - description: A and B both low interrupt for channel GPT{0,1}.0
+      - description: Input capture/compare match of the GTCCRA for channel GPT{0,1}.1
+      - description: Input capture/compare match of the GTCCRB for channel GPT{0,1}.1
+      - description: Compare match with the GTCCRC for channel GPT{0,1}.1
+      - description: Compare match with the GTCCRD for channel GPT{0,1}.1
+      - description: Compare match with the GTCCRE for channel GPT{0,1}.1
+      - description: Compare match with the GTCCRF for channel GPT{0,1}.1
+      - description: A and B both high interrupt for channel GPT{0,1}.1
+      - description: A and B both low interrupt for channel GPT{0,1}.1
+      - description: Input capture/compare match of the GTCCRA for channel GPT{0,1}.2
+      - description: Input capture/compare match of the GTCCRB for channel GPT{0,1}.2
+      - description: Compare match with the GTCCRC for channel GPT{0,1}.2
+      - description: Compare match with the GTCCRD for channel GPT{0,1}.2
+      - description: Compare match with the GTCCRE for channel GPT{0,1}.2
+      - description: Compare match with the GTCCRF for channel GPT{0,1}.2
+      - description: A and B both high interrupt for channel GPT{0,1}.2
+      - description: A and B both low interrupt for channel GPT{0,1}.2
+      - description: Input capture/compare match of the GTCCRA for channel GPT{0,1}.3
+      - description: Input capture/compare match of the GTCCRB for channel GPT{0,1}.3
+      - description: Compare match with the GTCCRC for channel GPT{0,1}.3
+      - description: Compare match with the GTCCRD for channel GPT{0,1}.3
+      - description: Compare match with the GTCCRE for channel GPT{0,1}.3
+      - description: Compare match with the GTCCRF for channel GPT{0,1}.3
+      - description: A and B both high interrupt for channel GPT{0,1}.3
+      - description: A and B both low interrupt for channel GPT{0,1}.3
+      - description: Input capture/compare match of the GTCCRA for channel GPT{0,1}.4
+      - description: Input capture/compare match of the GTCCRB for channel GPT{0,1}.4
+      - description: Compare match with the GTCCRC for channel GPT{0,1}.4
+      - description: Compare match with the GTCCRD for channel GPT{0,1}.4
+      - description: Compare match with the GTCCRE for channel GPT{0,1}.4
+      - description: Compare match with the GTCCRF for channel GPT{0,1}.4
+      - description: A and B both high interrupt for channel GPT{0,1}.4
+      - description: A and B both low interrupt for channel GPT{0,1}.4
+      - description: Input capture/compare match of the GTCCRA for channel GPT{0,1}.5
+      - description: Input capture/compare match of the GTCCRB for channel GPT{0,1}.5
+      - description: Compare match with the GTCCRC for channel GPT{0,1}.5
+      - description: Compare match with the GTCCRD for channel GPT{0,1}.5
+      - description: Compare match with the GTCCRE for channel GPT{0,1}.5
+      - description: Compare match with the GTCCRF for channel GPT{0,1}.5
+      - description: A and B both high interrupt for channel GPT{0,1}.5
+      - description: A and B both low interrupt for channel GPT{0,1}.5
+      - description: Input capture/compare match of the GTCCRA for channel GPT{0,1}.6
+      - description: Input capture/compare match of the GTCCRB for channel GPT{0,1}.6
+      - description: Compare match with the GTCCRC for channel GPT{0,1}.6
+      - description: Compare match with the GTCCRD for channel GPT{0,1}.6
+      - description: Compare match with the GTCCRE for channel GPT{0,1}.6
+      - description: Compare match with the GTCCRF for channel GPT{0,1}.6
+      - description: A and B both high interrupt for channel GPT{0,1}.6
+      - description: A and B both low interrupt for channel GPT{0,1}.6
+      - description: Input capture/compare match of the GTCCRA for channel GPT{0,1}.7
+      - description: Input capture/compare match of the GTCCRB for channel GPT{0,1}.7
+      - description: Compare match with the GTCCRC for channel GPT{0,1}.7
+      - description: Compare match with the GTCCRD for channel GPT{0,1}.7
+      - description: Compare match with the GTCCRE for channel GPT{0,1}.7
+      - description: Compare match with the GTCCRF for channel GPT{0,1}.7
+      - description: A and B both high interrupt for channel GPT{0,1}.7
+      - description: A and B both low interrupt for channel GPT{0,1}.7
+
+  interrupt-names:
+    items:
+      - const: gtcia0
+      - const: gtcib0
+      - const: gtcic0
+      - const: gtcid0
+      - const: gtcie0
+      - const: gtcif0
+      - const: gtcih0
+      - const: gtcil0
+      - const: gtcia1
+      - const: gtcib1
+      - const: gtcic1
+      - const: gtcid1
+      - const: gtcie1
+      - const: gtcif1
+      - const: gtcih1
+      - const: gtcil1
+      - const: gtcia2
+      - const: gtcib2
+      - const: gtcic2
+      - const: gtcid2
+      - const: gtcie2
+      - const: gtcif2
+      - const: gtcih2
+      - const: gtcil2
+      - const: gtcia3
+      - const: gtcib3
+      - const: gtcic3
+      - const: gtcid3
+      - const: gtcie3
+      - const: gtcif3
+      - const: gtcih3
+      - const: gtcil3
+      - const: gtcia4
+      - const: gtcib4
+      - const: gtcic4
+      - const: gtcid4
+      - const: gtcie4
+      - const: gtcif4
+      - const: gtcih4
+      - const: gtcil4
+      - const: gtcia5
+      - const: gtcib5
+      - const: gtcic5
+      - const: gtcid5
+      - const: gtcie5
+      - const: gtcif5
+      - const: gtcih5
+      - const: gtcil5
+      - const: gtcia6
+      - const: gtcib6
+      - const: gtcic6
+      - const: gtcid6
+      - const: gtcie6
+      - const: gtcif6
+      - const: gtcih6
+      - const: gtcil6
+      - const: gtcia7
+      - const: gtcib7
+      - const: gtcic7
+      - const: gtcid7
+      - const: gtcie7
+      - const: gtcif7
+      - const: gtcih7
+      - const: gtcil7
+
+  clocks:
+    items:
+      - description: Core clock (PCLKD)
+      - description: Bus clock (PCLKA)
+
+  clock-names:
+    items:
+      - const: core
+      - const: bus
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    items:
+      - description: Reset for bus clock (PCLKA/PCLKD)
+      - description: Reset for core clock (PCLKD)
+
+  reset-names:
+    items:
+      - const: rst_p
+      - const: rst_s
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - interrupt-names
+  - clocks
+  - clock-names
+  - power-domains
+  - resets
+  - reset-names
+
+allOf:
+  - $ref: pwm.yaml#
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/renesas,r9a09g047-cpg.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    pwm@13010000 {
+        compatible = "renesas,r9a09g047-gpt";
+        reg = <0x13010000 0x10000>;
+        interrupts = <GIC_SPI 538 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 546 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 554 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 562 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 570 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 586 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 594 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 539 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 547 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 555 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 563 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 571 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 579 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 587 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 595 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 540 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 548 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 556 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 564 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 572 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 580 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 588 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 596 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 541 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 549 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 557 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 565 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 573 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 581 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 589 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 597 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 542 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 550 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 558 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 566 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 574 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 582 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 590 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 598 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 543 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 551 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 559 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 567 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 575 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 583 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 591 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 599 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 544 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 552 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 560 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 568 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 576 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 584 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 592 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 600 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 545 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 553 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 561 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 569 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 577 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 585 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 593 IRQ_TYPE_EDGE_RISING>,
+                     <GIC_SPI 601 IRQ_TYPE_EDGE_RISING>;
+        interrupt-names = "gtcia0", "gtcib0", "gtcic0", "gtcid0",
+                          "gtcie0", "gtcif0", "gtcih0", "gtcil0",
+                          "gtcia1", "gtcib1", "gtcic1", "gtcid1",
+                          "gtcie1", "gtcif1", "gtcih1", "gtcil1",
+                          "gtcia2", "gtcib2", "gtcic2", "gtcid2",
+                          "gtcie2", "gtcif2", "gtcih2", "gtcil2",
+                          "gtcia3", "gtcib3", "gtcic3", "gtcid3",
+                          "gtcie3", "gtcif3", "gtcih3", "gtcil3",
+                          "gtcia4", "gtcib4", "gtcic4", "gtcid4",
+                          "gtcie4", "gtcif4", "gtcih4", "gtcil4",
+                          "gtcia5", "gtcib5", "gtcic5", "gtcid5",
+                          "gtcie5", "gtcif5", "gtcih5", "gtcil5",
+                          "gtcia6", "gtcib6", "gtcic6", "gtcid6",
+                          "gtcie6", "gtcif6", "gtcih6", "gtcil6",
+                          "gtcia7", "gtcib7", "gtcic7", "gtcid7",
+                          "gtcie7", "gtcif7", "gtcih7", "gtcil7";
+        clocks = <&cpg CPG_MOD 0x31>, <&cpg CPG_MOD 0x31>;
+        clock-names = "core", "bus";
+        power-domains = <&cpg>;
+        resets = <&cpg 0x59>, <&cpg 0x5a>;
+        reset-names = "rst_p", "rst_s";
+        #pwm-cells = <3>;
+    };
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v2 1/3] arm64: dts: qcom: sdm660: set cdsp compute-cbs' regs properly
From: Ekansh Gupta @ 2026-04-20 10:43 UTC (permalink / raw)
  To: Nickolay Goppen, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, devicetree, linux-kernel,
	~postmarketos/upstreaming, Konrad Dybcio, Dmitry Baryshkov
In-Reply-To: <20260420-qcom-sdm660-cdsp-adsp-fastrpc-dts-fix-v2-1-f6c7ab3c889a@mainlining.org>

On 20-04-2026 15:12, Nickolay Goppen wrote:
> Changing FastRPC compute-cbs' reg values to matching iommu streams
> solves SMMU translation errors when trying to use FastRPC on CDSP
> so change FastRPC compute-cbs' reg values that way
> 
> Fixes: c0c32a9e3493 ("arm64: dts: qcom: sdm630/660: Add CDSP-related nodes")
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Signed-off-by: Nickolay Goppen <setotau@mainlining.org>
> ---
>  arch/arm64/boot/dts/qcom/sdm660.dtsi | 36 ++++++++++++++++++------------------
>  1 file changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sdm660.dtsi b/arch/arm64/boot/dts/qcom/sdm660.dtsi
> index 3fd6dd82a992..0fca9662c64a 100644
> --- a/arch/arm64/boot/dts/qcom/sdm660.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sdm660.dtsi
> @@ -350,57 +350,57 @@ fastrpc {
>  				#address-cells = <1>;
>  				#size-cells = <0>;
>  
> -				compute-cb@5 {
> +				compute-cb@3 {
>  					compatible = "qcom,fastrpc-compute-cb";
> -					reg = <5>;
> +					reg = <3>;
>  					iommus = <&cdsp_smmu 3>;
>  				};
>  
> -				compute-cb@6 {
> +				compute-cb@4 {
>  					compatible = "qcom,fastrpc-compute-cb";
> -					reg = <6>;
> +					reg = <4>;
>  					iommus = <&cdsp_smmu 4>;
>  				};
Reviewed-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>

^ permalink raw reply

* Re: [PATCH v2 2/3] arm64: dts: qcom: sdm630: set adsp compute-cbs' regs properly
From: Ekansh Gupta @ 2026-04-20 10:44 UTC (permalink / raw)
  To: Nickolay Goppen, Bjorn Andersson, Konrad Dybcio, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-arm-msm, devicetree, linux-kernel,
	~postmarketos/upstreaming, Konrad Dybcio, Dmitry Baryshkov
In-Reply-To: <20260420-qcom-sdm660-cdsp-adsp-fastrpc-dts-fix-v2-2-f6c7ab3c889a@mainlining.org>

On 20-04-2026 15:12, Nickolay Goppen wrote:
> Changing FastRPC compute-cbs' reg values to matching iommu streams
> solves SMMU translation errors when trying to use FastRPC on ADSP
> so change FastRPC compute-cbs' reg values that way
> 
> Fixes: af2ce7296643 ("arm64: dts: qcom: sdm630: Add FastRPC nodes to ADSP")
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Signed-off-by: Nickolay Goppen <setotau@mainlining.org>
> ---
>  arch/arm64/boot/dts/qcom/sdm630.dtsi | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi
> index bef3213165d6..4b47efdb57b2 100644
> --- a/arch/arm64/boot/dts/qcom/sdm630.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi
> @@ -2459,27 +2459,27 @@ fastrpc {
>  					#address-cells = <1>;
>  					#size-cells = <0>;
>  
> -					compute-cb@1 {
> +					compute-cb@3 {
>  						compatible = "qcom,fastrpc-compute-cb";
> -						reg = <1>;
> +						reg = <3>;
>  						iommus = <&lpass_smmu 3>;
>  					};
>  
> -					compute-cb@2 {
> +					compute-cb@7 {
>  						compatible = "qcom,fastrpc-compute-cb";
> -						reg = <2>;
> +						reg = <7>;
>  						iommus = <&lpass_smmu 7>;
>  					};
>  
> -					compute-cb@3 {
> +					compute-cb@8 {
>  						compatible = "qcom,fastrpc-compute-cb";
> -						reg = <3>;
> +						reg = <8>;
>  						iommus = <&lpass_smmu 8>;
>  					};
>  
> -					compute-cb@4 {
> +					compute-cb@9 {
>  						compatible = "qcom,fastrpc-compute-cb";
> -						reg = <4>;
> +						reg = <9>;
>  						iommus = <&lpass_smmu 9>;
>  					};
>  				};
> 
Reviewed-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>

^ permalink raw reply

* Re: [PATCH v3 0/2] Add LT9611C(EX/UXD) DRM bridge driver and device tree
From: Dmitry Baryshkov @ 2026-04-20 10:45 UTC (permalink / raw)
  To: syyang
  Cc: robh, krzk+dt, conor+dt, andrzej.hajda, neil.armstrong,
	maarten.lankhorst, rfoss, mripard, Laurent.pinchart, tzimmermann,
	jonas, jernej.skrabec, devicetree, dri-devel, linux-kernel,
	yangsunyun1993, xmzhu
In-Reply-To: <20260420061644.1251070-1-syyang@lontium.com>

On Mon, 20 Apr 2026 at 09:16, <syyang@lontium.com> wrote:
>
> From: Sunyun Yang <syyang@lontium.com>
>
> This series adds support for the Lontium LT9611C(EX/UXD) MIPI DSI to HDMI
> chip:
>
> -dt-bindings: bridge: This patch adds new content to the lontium,lt9611.yaml
>  binding file.
> -drm/bridge: This patch add new DRM bridge driver for LT9611C(EX/UXD) chip.
>
> Signed-off-by: Sunyun Yang<syyang@lontium.com>

Once again. Your messages are not reaching the dri-devel mailing list.
Please fix your SMTP configuration or start using B4 tool and B4 Web
Relay for sending patches.
Most developers wouldn't even see these emails as they haven't reached
dri-devel.

> ---
> Changes in v3:
> -dt-binding:
>  1. lt9611c(ex/uxd) content merged into lontium,lt9611.yaml
> -drm/bridge:
>  1. Drop the licence text, only use SPDX header
>  2. Sort the headers
>  3. Use library functions for crc8
>  4. Drop i2c_read_byte and i2c_write_byte
>  5. Lowercase all hex values
>  6. Use paged writes as implemented for LT9611C(EX/UXD)
>  7. Drop dev_info, use dev_dbg
>  8. Modify lt9611c_get_edid_block, don't store EDID in the long-term structures
>  9. Use HDMI audio helpers.
>  10.Remove unnecessary flags,Implement proper cleanup path, unwinding resources
>     one by one.
>  11.Replace devm_kzalloc with devm_drm_bridge_alloc.
>  12.Remove extra kthread.
> -Link to v1: https://lore.kernel.org/lkml/20250903123825.1721443-1-syyang@lontium.com/
>
> Changes in v2:
>  1. Forget modify code, operation error, Please disregard this submit.
>
> Changes in v1:
> -dt-binding:
>  1. Submit the first version of the code.
> -drm/bridge:
>  1. Submit the first version of the code.
>
> ---
> Sunyun Yang (2):
>   dt-bindings: bridge: This patch adds new content to the
>     lontium,lt9611.yaml binding file
>   drm/bridge: This patch add new DRM bridge driver for LT9611C chip
>
>  .../display/bridge/lontium,lt9611.yaml        |    8 +-
>  drivers/gpu/drm/bridge/Kconfig                |   18 +
>  drivers/gpu/drm/bridge/Makefile               |    1 +
>  drivers/gpu/drm/bridge/lontium-lt9611c.c      | 1365 +++++++++++++++++
>  4 files changed, 1390 insertions(+), 2 deletions(-)
>  create mode 100755 drivers/gpu/drm/bridge/lontium-lt9611c.c
>
> --
> 2.34.1
>


-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH 1/2] arm64: dts: qcom: sc8280xp: add several missing pdc map entries
From: Pengyu Luo @ 2026-04-20 10:47 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <b9b58923-40c0-4d3d-991f-52471b29a813@oss.qualcomm.com>

On Mon, Apr 20, 2026 at 6:21 PM Konrad Dybcio
<konrad.dybcio@oss.qualcomm.com> wrote:
>
> On 4/20/26 11:53 AM, Pengyu Luo wrote:
> > On Mon, Apr 20, 2026 at 4:32 PM Konrad Dybcio
> > <konrad.dybcio@oss.qualcomm.com> wrote:
> >>
> >> On 4/19/26 7:32 PM, Pengyu Luo wrote:
> >>> pdc 215, 256, 257 are missing, but we can find tlmm pin 103, 84, 90
> >>> are mapped to them respectively, so add the map entries from pdc to
> >>> gic. These entries are reversed from .data section of qcgpio.sys
> >>>
> >>> Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com>
> >>> ---
> >>
> >> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>
> >> Konrad
> >>
> >> The below change on top will fully align it with the data in the docs
> >> (no functional change)
> >>
> >
> > Glad to know. Could you please help to check the tlmm map too? When I
> > was parsing the binary, I found
> >
> > tlmm 65535 => pdc 70 => gic 520
> > tlmm 65535 => pdc 174 => gic 733
> > tlmm 65535 => pdc 175 => gic 734
> > tlmm 65535 => pdc 176 => gic 735
> > tlmm 65535 => pdc 177 => gic 736
> > tlmm 65535 => pdc 178 => gic 737
> > tlmm 65535 => pdc 184 => gic 743
> > tlmm 65535 => pdc 185 => gic 744
> > tlmm 65535 => pdc 186 => gic 745
> > tlmm 65535 => pdc 187 => gic 746
> > tlmm 65535 => pdc 188 => gic 747
> > tlmm 65535 => pdc 194 => gic 753
> > tlmm 65535 => pdc 195 => gic 754
> > tlmm 65535 => pdc 196 => gic 755
> > tlmm 65535 => pdc 197 => gic 756
> > tlmm 65535 => pdc 198 => gic 757
> > tlmm 65535 => pdc 199 => gic 416
> > tlmm 65535 => pdc 204 => gic 462
> > tlmm 65535 => pdc 205 => gic 264
> >
> > If 65536 means the pin is missing, I will send v2 to remove the tlmm
> > map together with the pdc removal.
>
> These seem to be LPASS/SSC GPIOs
>
> There are missing pairs of:
>
> TLMM 151 -> PDC 264 -> GIC 191
> TLMM 143 -> PDC 261 -> GIC 402
>
> and very interestingly, GPIO 190 has two mappings:
> PDC 70 -> GIC 552

PDC 70 is connected to swr2, which is wakeable. Speaking of this, in
qcom,pdc.yaml

Drivers requiring wakeup capabilities of their device interrupts
routed through the PDC, must specify PDC as their interrupt controller
and request the PDC port associated with the GIC interrupt.

But swr2 specifies GIC.

I wonder, when should we use tlmm, when pdc, when gic?

Best wishes,
Pengyu


> PDC 178 -> GIC 769
>
>
> Konrad

^ permalink raw reply

* [PATCH v9 7/7] i3c: hub: p3h2x4x: Add support for NXP P3H2x4x I3C hub functionality
From: Lakshay Piplani @ 2026-04-20 10:52 UTC (permalink / raw)
  To: linux-kernel, linux-i3c, alexandre.belloni, krzk+dt, robh,
	conor+dt, devicetree, broonie, lee, Frank.Li, lgirdwood
  Cc: vikash.bansal, priyanka.jain, aman.kumarpandey, Lakshay Piplani
In-Reply-To: <20260420105222.1562243-1-lakshay.piplani@nxp.com>

From: Aman Kumar Pandey <aman.kumarpandey@nxp.com>

Add I3C hub functionality for the NXP P3H2x4x family of multiport hubs.
These devices support downstream target ports that can be configured
as I3C, I2C, or SMBus.

This driver enables:
- I3C/I2C communication between host and hub
- Transparent communication with downstream devices
- Target port configuration (I3C/I2C/SMBus)
- MCTP device support
- In-band interrupt handling

P3H2440/P3H2441 support 4 target ports.
P3H2840/P3H2841 support 8 target ports.

Signed-off-by: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
Signed-off-by: Vikash Bansal <vikash.bansal@nxp.com>
Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>

---
Changes in v9:
 - Added CONFIG_I2C_SLAVE guards where necessary to avoid build issues
   when I2C slave support is disabled.

Changes in v8:
 - No change

Changes in v7:
 - Remove CONFIG_I2C_SLAVE guards
 - Use Kernel API find_closest instead of custom helper
 - Use devm_regulator_get_enable_optional()
 - Fix kernel-doc warnings

Changes in v6:
 - Remove generic I3C code and keep reg dependent code only.

Changes in v5:
 - Updated supply names.

Changes in v4:
 - Split the driver into three separate patches (mfd, regulator and I3C hub)
 - Added support for NXP P3H2x4x I3C hub functionality
 - Integrated hub driver with its on-die regulator

Changes in v3:
 - Added MFD (Multi-Function Device) support for I3C hub and on-die regulator

Changes in v2:
 - Refined coding style and incorporated review feedback
 - Updated directory structure
 - Revised logic for parsing DTS nodes
---
---
 MAINTAINERS                              |   1 +
 drivers/i3c/Kconfig                      |   1 +
 drivers/i3c/Makefile                     |   1 +
 drivers/i3c/hub/Kconfig                  |  11 +
 drivers/i3c/hub/Makefile                 |   4 +
 drivers/i3c/hub/p3h2840_i3c_hub.h        | 334 ++++++++++++++++++
 drivers/i3c/hub/p3h2840_i3c_hub_common.c | 352 +++++++++++++++++++
 drivers/i3c/hub/p3h2840_i3c_hub_i3c.c    | 132 +++++++
 drivers/i3c/hub/p3h2840_i3c_hub_smbus.c  | 426 +++++++++++++++++++++++
 include/linux/i3c/device.h               |   1 +
 10 files changed, 1263 insertions(+)
 create mode 100644 drivers/i3c/hub/Kconfig
 create mode 100644 drivers/i3c/hub/Makefile
 create mode 100644 drivers/i3c/hub/p3h2840_i3c_hub.h
 create mode 100644 drivers/i3c/hub/p3h2840_i3c_hub_common.c
 create mode 100644 drivers/i3c/hub/p3h2840_i3c_hub_i3c.c
 create mode 100644 drivers/i3c/hub/p3h2840_i3c_hub_smbus.c

diff --git a/MAINTAINERS b/MAINTAINERS
index bb3e8e9674c4..1295c66dacc2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19275,6 +19275,7 @@ L:	linux-i3c-owner@lists.infradead.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
 F:	drivers/i3c/hub.c
+F:	drivers/i3c/hub/*
 F:	drivers/mfd/p3h2840.c
 F:	drivers/regulator/p3h2840_i3c_hub_regulator.c
 F:	include/linux/i3c/hub.h
diff --git a/drivers/i3c/Kconfig b/drivers/i3c/Kconfig
index 65304b416bb4..74727d614492 100644
--- a/drivers/i3c/Kconfig
+++ b/drivers/i3c/Kconfig
@@ -36,6 +36,7 @@ config I3C_HUB
 
 	  Say Y here if your platform includes an I3C hub device
 
+source "drivers/i3c/hub/Kconfig"
 endif # I3C
 
 config I3C_OR_I2C
diff --git a/drivers/i3c/Makefile b/drivers/i3c/Makefile
index 9ddee56a6338..2950820db9ea 100644
--- a/drivers/i3c/Makefile
+++ b/drivers/i3c/Makefile
@@ -3,3 +3,4 @@ i3c-y				:= device.o master.o
 obj-$(CONFIG_I3C)		+= i3c.o
 obj-$(CONFIG_I3C)		+= master/
 obj-$(CONFIG_I3C_HUB)		+= hub.o
+obj-$(CONFIG_I3C_HUB)		+= hub/
diff --git a/drivers/i3c/hub/Kconfig b/drivers/i3c/hub/Kconfig
new file mode 100644
index 000000000000..f725f3e2bfbe
--- /dev/null
+++ b/drivers/i3c/hub/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright 2025 NXP
+config P3H2X4X_I3C_HUB
+    tristate "NXP P3H2X4X I3C HUB support"
+    depends on MFD_P3H2X4X
+    select I3C_HUB
+    help
+      This enables support for NXP P3H244x/P3H284x I3C HUB. These hubs
+      connect to a host via I3C/I2C/SMBus and allow communication with
+      multiple downstream peripherals. The Say Y or M here to use I3C
+      HUB driver to configure I3C HUB device.
diff --git a/drivers/i3c/hub/Makefile b/drivers/i3c/hub/Makefile
new file mode 100644
index 000000000000..9dbd8a7b4184
--- /dev/null
+++ b/drivers/i3c/hub/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright 2025 NXP
+p3h2840_i3c_hub-y := p3h2840_i3c_hub_common.o p3h2840_i3c_hub_i3c.o p3h2840_i3c_hub_smbus.o
+obj-$(CONFIG_P3H2X4X_I3C_HUB)	+= p3h2840_i3c_hub.o
diff --git a/drivers/i3c/hub/p3h2840_i3c_hub.h b/drivers/i3c/hub/p3h2840_i3c_hub.h
new file mode 100644
index 000000000000..f91694c0d71d
--- /dev/null
+++ b/drivers/i3c/hub/p3h2840_i3c_hub.h
@@ -0,0 +1,334 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2025-2026 NXP
+ * This header file contain private device structure definition.
+ */
+
+#ifndef P3H2840_I3C_HUB_H
+#define P3H2840_I3C_HUB_H
+
+#include <linux/bitfield.h>
+#include <linux/i2c.h>
+#include <linux/i3c/device.h>
+#include <linux/i3c/hub.h>
+#include <linux/i3c/master.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regmap.h>
+
+/* I3C HUB REGISTERS */
+
+/* Device Information Registers */
+#define P3H2X4X_DEV_INFO_0					0x00
+#define P3H2X4X_DEV_INFO_1					0x01
+#define P3H2X4X_PID_5						0x02
+#define P3H2X4X_PID_4						0x03
+#define P3H2X4X_PID_3						0x04
+#define P3H2X4X_PID_2						0x05
+#define P3H2X4X_PID_1						0x06
+#define P3H2X4X_PID_0						0x07
+#define P3H2X4X_BCR						0x08
+#define P3H2X4X_DCR						0x09
+#define P3H2X4X_DEV_CAPAB					0x0a
+#define P3H2X4X_DEV_REV						0x0b
+
+/* Device Configuration Registers */
+#define P3H2X4X_CP_CONF						0x11
+#define P3H2X4X_TP_ENABLE					0x12
+
+#define P3H2X4X_DEV_CONF					0x13
+#define P3H2X4X_IO_STRENGTH					0x14
+#define P3H2X4X_TP0145_IO_STRENGTH_MASK				GENMASK(1, 0)
+#define P3H2X4X_TP0145_IO_STRENGTH(x)	\
+		FIELD_PREP(P3H2X4X_TP0145_IO_STRENGTH_MASK, x)
+#define P3H2X4X_TP2367_IO_STRENGTH_MASK				GENMASK(3, 2)
+#define P3H2X4X_TP2367_IO_STRENGTH(x)	\
+		FIELD_PREP(P3H2X4X_TP2367_IO_STRENGTH_MASK, x)
+#define P3H2X4X_CP0_IO_STRENGTH_MASK				GENMASK(5, 4)
+#define P3H2X4X_CP0_IO_STRENGTH(x)	\
+		FIELD_PREP(P3H2X4X_CP0_IO_STRENGTH_MASK, x)
+#define P3H2X4X_CP1_IO_STRENGTH_MASK				GENMASK(7, 6)
+#define P3H2X4X_CP1_IO_STRENGTH(x)	\
+		FIELD_PREP(P3H2X4X_CP1_IO_STRENGTH_MASK, x)
+#define P3H2X4X_IO_STRENGTH_MASK					GENMASK(7, 0)
+
+#define P3H2X4X_TP_IO_MODE_CONF					0x17
+#define P3H2X4X_TP_SMBUS_AGNT_EN				0x18
+
+#define P3H2X4X_LDO_AND_PULLUP_CONF				0x19
+
+#define P3H2X4X_TP0145_PULLUP_CONF_MASK				GENMASK(7, 6)
+#define P3H2X4X_TP0145_PULLUP_CONF(x)	\
+		FIELD_PREP(P3H2X4X_TP0145_PULLUP_CONF_MASK, x)
+#define P3H2X4X_TP2367_PULLUP_CONF_MASK				GENMASK(5, 4)
+#define P3H2X4X_TP2367_PULLUP_CONF(x)	\
+		FIELD_PREP(P3H2X4X_TP2367_PULLUP_CONF_MASK, x)
+#define P3H2X4X_PULLUP_CONF_MASK					GENMASK(7, 4)
+
+#define P3H2X4X_CP_IBI_CONF					0x1a
+
+#define P3H2X4X_TP_SMBUS_AGNT_IBI_CONFIG			0x1b
+
+#define P3H2X4X_IBI_MDB_CUSTOM					0x1c
+#define P3H2X4X_JEDEC_CONTEXT_ID				0x1d
+#define P3H2X4X_TP_GPIO_MODE_EN					0x1e
+
+/* Device Status and IBI Registers */
+#define P3H2X4X_DEV_AND_IBI_STS					0x20
+#define P3H2X4X_TP_SMBUS_AGNT_IBI_STS				0x21
+#define P3H2X4X_SMBUS_AGENT_EVENT_FLAG_STATUS			BIT(4)
+
+/* Controller Port Control/Status Registers */
+#define P3H2X4X_CP_MUX_SET					0x38
+#define P3H2X4X_CONTROLLER_PORT_MUX_REQ				BIT(0)
+#define P3H2X4X_CP_MUX_STS					0x39
+#define P3H2X4X_CONTROLLER_PORT_MUX_CONNECTION_STATUS		BIT(0)
+
+/* Target Ports Control Registers */
+#define P3H2X4X_TP_SMBUS_AGNT_TRANS_START			0x50
+#define P3H2X4X_TP_NET_CON_CONF					0x51
+
+#define P3H2X4X_TP_PULLUP_EN					0x53
+
+#define P3H2X4X_TP_SCL_OUT_EN					0x54
+#define P3H2X4X_TP_SDA_OUT_EN					0x55
+#define P3H2X4X_TP_SCL_OUT_LEVEL				0x56
+#define P3H2X4X_TP_SDA_OUT_LEVEL				0x57
+#define P3H2X4X_TP_IN_DETECT_MODE_CONF				0x58
+#define P3H2X4X_TP_SCL_IN_DETECT_IBI_EN				0x59
+#define P3H2X4X_TP_SDA_IN_DETECT_IBI_EN				0x5a
+
+/* Target Ports Status Registers */
+#define P3H2X4X_TP_SCL_IN_LEVEL_STS				0x60
+#define P3H2X4X_TP_SDA_IN_LEVEL_STS				0x61
+#define P3H2X4X_TP_SCL_IN_DETECT_FLG				0x62
+#define P3H2X4X_TP_SDA_IN_DETECT_FLG				0x63
+
+/* SMBus Agent Configuration and Status Registers */
+#define P3H2X4X_TP0_SMBUS_AGNT_STS				0x64
+#define P3H2X4X_TP1_SMBUS_AGNT_STS				0x65
+#define P3H2X4X_TP2_SMBUS_AGNT_STS				0x66
+#define P3H2X4X_TP3_SMBUS_AGNT_STS				0x67
+#define P3H2X4X_TP4_SMBUS_AGNT_STS				0x68
+#define P3H2X4X_TP5_SMBUS_AGNT_STS				0x69
+#define P3H2X4X_TP6_SMBUS_AGNT_STS				0x6a
+#define P3H2X4X_TP7_SMBUS_AGNT_STS				0x6b
+#define P3H2X4X_ONCHIP_TD_AND_SMBUS_AGNT_CONF			0x6c
+
+/* buf receive flag set */
+#define P3H2X4X_TARGET_BUF_CA_TF				BIT(0)
+#define P3H2X4X_TARGET_BUF_0_RECEIVE				BIT(1)
+#define P3H2X4X_TARGET_BUF_1_RECEIVE				BIT(2)
+#define P3H2X4X_TARGET_BUF_0_1_RECEIVE				GENMASK(2, 1)
+#define P3H2X4X_TARGET_BUF_OVRFL				GENMASK(3, 1)
+#define BUF_RECEIVED_FLAG_MASK					GENMASK(3, 1)
+#define BUF_RECEIVED_FLAG_TF_MASK				GENMASK(3, 0)
+
+#define P3H2X4X_TARGET_AGENT_LOCAL_DEV				0x11
+#define P3H2X4X_TARGET_BUFF_0_PAGE				0x12
+#define P3H2X4X_TARGET_BUFF_1_PAGE				0x13
+
+/* Special Function Registers */
+#define P3H2X4X_LDO_AND_CPSEL_STS				0x79
+#define P3H2X4X_CP_SDA1_LEVEL					BIT(7)
+#define P3H2X4X_CP_SCL1_LEVEL					BIT(6)
+
+#define P3H2X4X_CP_SEL_PIN_INPUT_CODE_MASK			GENMASK(5, 4)
+#define P3H2X4X_CP_SEL_PIN_INPUT_CODE_GET(x)	\
+		(((x) & P3H2X4X_CP_SEL_PIN_INPUT_CODE_MASK) >> 4)
+#define P3H2X4X_CP_SDA1_SCL1_PINS_CODE_MASK			GENMASK(7, 6)
+#define P3H2X4X_CP_SDA1_SCL1_PINS_CODE_GET(x)	\
+		(((x) & P3H2X4X_CP_SDA1_SCL1_PINS_CODE_MASK) >> 6)
+#define P3H2X4X_VCCIO1_PWR_GOOD					BIT(3)
+#define P3H2X4X_VCCIO0_PWR_GOOD					BIT(2)
+#define P3H2X4X_CP1_VCCIO_PWR_GOOD				BIT(1)
+#define P3H2X4X_CP0_VCCIO_PWR_GOOD				BIT(0)
+
+#define P3H2X4X_BUS_RESET_SCL_TIMEOUT				0x7a
+#define P3H2X4X_ONCHIP_TD_PROTO_ERR_FLG				0x7b
+#define P3H2X4X_DEV_CMD						0x7c
+#define P3H2X4X_ONCHIP_TD_STS					0x7d
+#define P3H2X4X_ONCHIP_TD_ADDR_CONF				0x7e
+#define P3H2X4X_PAGE_PTR					0x7f
+
+/* Paged Transaction Registers */
+#define P3H2X4X_CONTROLLER_BUFFER_PAGE				0x10
+#define P3H2X4X_CONTROLLER_AGENT_BUFF				0x80
+#define P3H2X4X_CONTROLLER_AGENT_BUFF_DATA			0x84
+
+#define P3H2X4X_TARGET_BUFF_LENGTH				0x80
+#define P3H2X4X_TARGET_BUFF_ADDRESS				0x81
+#define P3H2X4X_TARGET_BUFF_DATA				0x82
+
+#define P3H2X4X_TP_MAX_COUNT					0x08
+#define P3H2X4X_CP_MAX_COUNT					0x02
+#define P3H2X4X_TP_LOCAL_DEV					0x08
+
+/* LDO Disable/Enable DT settings */
+#define P3H2X4X_LDO_VOLT_1_0V					0x00
+#define P3H2X4X_LDO_VOLT_1_1V					0x01
+#define P3H2X4X_LDO_VOLT_1_2V					0x02
+#define P3H2X4X_LDO_VOLT_1_8V					0x03
+
+#define P3H2X4X_LDO_DISABLED					0x00
+#define P3H2X4X_LDO_ENABLED					0x01
+
+#define P3H2X4X_IBI_DISABLED					0x00
+#define P3H2X4X_IBI_ENABLED					0x01
+
+/* Pullup selection DT settings */
+#define P3H2X4X_TP_PULLUP_250R					0x00
+#define P3H2X4X_TP_PULLUP_500R					0x01
+#define P3H2X4X_TP_PULLUP_1000R					0x02
+#define P3H2X4X_TP_PULLUP_2000R					0x03
+
+#define P3H2X4X_TP_PULLUP_DISABLED				0x00
+#define P3H2X4X_TP_PULLUP_ENABLED				0x01
+
+#define P3H2X4X_IO_STRENGTH_20_OHM				0x00
+#define P3H2X4X_IO_STRENGTH_30_OHM				0x01
+#define P3H2X4X_IO_STRENGTH_40_OHM				0x02
+#define P3H2X4X_IO_STRENGTH_50_OHM				0x03
+
+#define P3H2X4X_TP_MODE_I3C					0x00
+#define P3H2X4X_TP_MODE_SMBUS					0x01
+#define P3H2X4X_TP_MODE_GPIO					0x02
+#define P3H2X4X_TP_MODE_I2C					0x03
+
+#define ONE_BYTE_SIZE						0x01
+
+/* holding SDA low when both SMBus Target Agent received data buffers are full.
+ * This feature can be used as a flow-control mechanism for MCTP applications to
+ * avoid MCTP transmitters on Target Ports time out when the SMBus agent buffers
+ * are not serviced in time by upstream controller and only receives write message
+ * from its downstream ports.
+ * SMBUS_AGENT_TX_RX_LOOPBACK_EN/TARGET_AGENT_BUF_FULL_SDA_LOW_EN
+ */
+
+#define P3H2X4X_TARGET_AGENT_DFT_IBI_CONF			0x20
+#define P3H2X4X_TARGET_AGENT_DFT_IBI_CONF_MASK			0x21
+
+/* Transaction status checking mask */
+
+#define P3H2X4X_SMBUS_TRANSACTION_FINISH_FLAG		1
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_SHIFT		4
+
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_OK		0
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_ADDR_NAK		1
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_DATA_NAK		2
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_WTR_NAK		3
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_SYNC_RCV		4
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_SYNC_RCVCLR	5
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_FAULT		6
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_ARB_LOSS		7
+#define P3H2X4X_SMBUS_CNTRL_STATUS_TXN_SCL_TO		8
+
+#define P3H2X4X_TP_BUFFER_STATUS_MASK				0x0f
+#define P3H2X4X_TP_TRANSACTION_CODE_MASK			0xf0
+
+/* SMBus transaction types fields */
+#define P3H2X4X_SMBUS_400kHz					BIT(2)
+
+/* SMBus polling */
+#define P3H2X4X_POLLING_ROLL_PERIOD_MS				10
+
+/* Hub buffer size */
+#define P3H2X4X_CONTROLLER_BUFFER_SIZE				88
+#define P3H2X4X_TARGET_BUFFER_SIZE				80
+#define P3H2X4X_SMBUS_DESCRIPTOR_SIZE				4
+#define P3H2X4X_SMBUS_PAYLOAD_SIZE	\
+		(P3H2X4X_CONTROLLER_BUFFER_SIZE - P3H2X4X_SMBUS_DESCRIPTOR_SIZE)
+#define P3H2X4X_SMBUS_TARGET_PAYLOAD_SIZE	(P3H2X4X_TARGET_BUFFER_SIZE - 2)
+
+/* Hub SMBus transaction time */
+#define P3H2X4X_SMBUS_400kHz_TRANSFER_TIMEOUT(x)		((20 * (x)) + 80)
+
+#define P3H2X4X_NO_PAGE_PER_TP					4
+
+#define P3H2X4X_MAX_PAYLOAD_LEN					2
+#define P3H2X4X_NUM_SLOTS					6
+
+#define P3H2X4X_HUB_ID						0
+
+#define P3H2X4X_SET_BIT(n)				BIT(n)
+
+enum p3h2x4x_tp {
+	TP_0,
+	TP_1,
+	TP_2,
+	TP_3,
+	TP_4,
+	TP_5,
+	TP_6,
+	TP_7,
+};
+
+enum p3h2x4x_rcv_buf {
+	RCV_BUF_0,
+	RCV_BUF_1,
+	RCV_BUF_OF,
+};
+
+struct tp_configuration {
+	bool pullup_en;
+	bool ibi_en;
+	bool always_enable;
+	int mode;
+};
+
+struct hub_configuration {
+	int tp0145_pullup;
+	int tp2367_pullup;
+	int cp0_io_strength;
+	int cp1_io_strength;
+	int tp0145_io_strength;
+	int tp2367_io_strength;
+	struct tp_configuration tp_config[P3H2X4X_TP_MAX_COUNT];
+};
+
+struct tp_bus {
+	bool is_registered;	    /* bus was registered in the framework. */
+	u8 tp_mask;
+	u8 tp_port;
+	struct mutex port_mutex;      /* per port mutex */
+	struct device_node *of_node;
+	struct i2c_client *tp_smbus_client;
+	struct i2c_adapter *tp_smbus_adapter;
+	struct i3c_hub_controller hub_controller;
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub;
+};
+
+struct p3h2x4x_i3c_hub_dev {
+	struct device *dev;
+	struct regmap *regmap;
+	struct mutex etx_mutex;      /* all port mutex */
+	struct i3c_device *i3cdev;
+	struct i2c_client *i2c_client;
+	struct hub_configuration hub_config;
+	struct tp_bus tp_bus[P3H2X4X_TP_MAX_COUNT];
+	struct i3c_hub *hub;
+};
+
+/**
+ * p3h2x4x_tp_smbus_algo - add i2c adapter for target port configured as SMBus.
+ * @priv: p3h2x4x device structure.
+ * @tp: target port.
+ * Return: 0 in case of success, a negative EINVAL code if the error.
+ */
+int p3h2x4x_tp_smbus_algo(struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub);
+
+/**
+ * p3h2x4x_tp_i3c_algo - register i3c controller for target port configured as I3C.
+ * @priv: p3h2x4x device structure.
+ * @tp: target port.
+ * Return: 0 in case of success, a negative EINVAL code if the error.
+ */
+int p3h2x4x_tp_i3c_algo(struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub);
+
+/**
+ * p3h2x4x_ibi_handler - IBI handler.
+ * @i3cdev: i3c device.
+ * @payload: two byte IBI payload data.
+ */
+void p3h2x4x_ibi_handler(struct i3c_device *i3cdev,
+			 const struct i3c_ibi_payload *payload);
+#endif /* P3H2840_I3C_HUB_H */
diff --git a/drivers/i3c/hub/p3h2840_i3c_hub_common.c b/drivers/i3c/hub/p3h2840_i3c_hub_common.c
new file mode 100644
index 000000000000..cc29cb9b076f
--- /dev/null
+++ b/drivers/i3c/hub/p3h2840_i3c_hub_common.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025-2026 NXP
+ * This P3H2X4X driver file implements functions for Hub probe and DT parsing.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/p3h2840.h>
+#include <linux/util_macros.h>
+
+#include "p3h2840_i3c_hub.h"
+
+/* LDO voltage DT settings */
+#define P3H2X4X_DT_LDO_VOLT_1_0V		1000000
+#define P3H2X4X_DT_LDO_VOLT_1_1V		1100000
+#define P3H2X4X_DT_LDO_VOLT_1_2V		1200000
+#define P3H2X4X_DT_LDO_VOLT_1_8V		1800000
+
+static const int p3h2x4x_pullup_tbl[] = {
+	250, 500, 1000, 2000
+};
+
+static const int p3h2x4x_io_strength_tbl[] = {
+	20, 30, 40, 50
+};
+
+static u8 p3h2x4x_pullup_dt_to_reg(int dt_value)
+{
+	return find_closest(dt_value, p3h2x4x_pullup_tbl,
+			  ARRAY_SIZE(p3h2x4x_pullup_tbl));
+}
+
+static u8 p3h2x4x_io_strength_dt_to_reg(int dt_value)
+{
+	return find_closest(dt_value, p3h2x4x_io_strength_tbl,
+			  ARRAY_SIZE(p3h2x4x_io_strength_tbl));
+}
+
+static int p3h2x4x_configure_pullup(struct device *dev)
+{
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
+	u8 pullup;
+
+	pullup = P3H2X4X_TP0145_PULLUP_CONF(p3h2x4x_pullup_dt_to_reg
+						(p3h2x4x_i3c_hub->hub_config.tp0145_pullup));
+
+	pullup |= P3H2X4X_TP2367_PULLUP_CONF(p3h2x4x_pullup_dt_to_reg
+						(p3h2x4x_i3c_hub->hub_config.tp2367_pullup));
+
+	return regmap_update_bits(p3h2x4x_i3c_hub->regmap, P3H2X4X_LDO_AND_PULLUP_CONF,
+							  P3H2X4X_PULLUP_CONF_MASK, pullup);
+}
+
+static int p3h2x4x_configure_io_strength(struct device *dev)
+{
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
+	u8 io_strength;
+
+	io_strength = P3H2X4X_CP0_IO_STRENGTH(p3h2x4x_io_strength_dt_to_reg
+						(p3h2x4x_i3c_hub->hub_config.cp0_io_strength));
+
+	io_strength |= P3H2X4X_CP1_IO_STRENGTH(p3h2x4x_io_strength_dt_to_reg
+						(p3h2x4x_i3c_hub->hub_config.cp1_io_strength));
+
+	io_strength |= P3H2X4X_TP0145_IO_STRENGTH(p3h2x4x_io_strength_dt_to_reg
+						(p3h2x4x_i3c_hub->hub_config.tp0145_io_strength));
+
+	io_strength |= P3H2X4X_TP2367_IO_STRENGTH(p3h2x4x_io_strength_dt_to_reg
+						(p3h2x4x_i3c_hub->hub_config.tp2367_io_strength));
+
+	return regmap_update_bits(p3h2x4x_i3c_hub->regmap, P3H2X4X_IO_STRENGTH,
+							  P3H2X4X_IO_STRENGTH_MASK, io_strength);
+}
+
+static int p3h2x4x_configure_ldo(struct device *dev)
+{
+	static const char * const supplies[] = {
+		"vcc1",
+		"vcc2",
+		"vcc3",
+		"vcc4"
+	};
+	int ret, i;
+
+	for (i = 0; i < ARRAY_SIZE(supplies); i++) {
+		ret = devm_regulator_get_enable_optional(dev->parent, supplies[i]);
+		if (ret == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		if (ret && ret != -ENODEV)
+			dev_warn(dev, "Failed to enable %s (%d)\n",
+				 supplies[i], ret);
+	}
+
+	/* This delay is required for the regulator to stabilize its output voltage */
+	mdelay(5);
+
+	return 0;
+}
+
+static int p3h2x4x_configure_tp(struct device *dev)
+{
+	struct p3h2x4x_i3c_hub_dev *hub = dev_get_drvdata(dev);
+	u8 mode = 0, smbus = 0, pullup = 0, target_port = 0;
+	int tp, ret;
+
+	for (tp = 0; tp < P3H2X4X_TP_MAX_COUNT; tp++) {
+		pullup |= hub->hub_config.tp_config[tp].pullup_en ? P3H2X4X_SET_BIT(tp) : 0;
+		mode |= (hub->hub_config.tp_config[tp].mode != P3H2X4X_TP_MODE_I3C) ?
+			P3H2X4X_SET_BIT(tp) : 0;
+		smbus |= (hub->hub_config.tp_config[tp].mode == P3H2X4X_TP_MODE_SMBUS) ?
+			 P3H2X4X_SET_BIT(tp) : 0;
+		target_port |= (hub->tp_bus[tp].tp_mask == P3H2X4X_SET_BIT(tp)) ?
+			       hub->tp_bus[tp].tp_mask : 0;
+	}
+
+	ret = regmap_update_bits(hub->regmap, P3H2X4X_TP_PULLUP_EN, pullup, pullup);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(hub->regmap, P3H2X4X_TP_IO_MODE_CONF, mode, mode);
+	if (ret)
+		return ret;
+
+	ret = regmap_update_bits(hub->regmap, P3H2X4X_TP_SMBUS_AGNT_EN, smbus, smbus);
+	if (ret)
+		return ret;
+
+	if (target_port & ~smbus) {
+		ret = regmap_write(hub->regmap, P3H2X4X_CP_MUX_SET,
+				   P3H2X4X_CONTROLLER_PORT_MUX_REQ);
+		if (ret)
+			return ret;
+	}
+
+	return regmap_update_bits(hub->regmap, P3H2X4X_TP_ENABLE, target_port, target_port);
+}
+
+static int p3h2x4x_configure_hw(struct device *dev)
+{
+	int ret;
+
+	ret = p3h2x4x_configure_ldo(dev);
+	if (ret)
+		return ret;
+
+	ret = p3h2x4x_configure_pullup(dev);
+	if (ret)
+		return ret;
+
+	ret = p3h2x4x_configure_io_strength(dev);
+	if (ret)
+		return ret;
+
+	return p3h2x4x_configure_tp(dev);
+}
+
+static void p3h2x4x_get_target_port_dt_conf(struct device *dev,
+					    const struct device_node *node)
+{
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
+	u64 tp_port;
+
+	for_each_available_child_of_node_scoped(node, dev_node) {
+		if (of_property_read_reg(dev_node, 0, &tp_port, NULL))
+			continue;
+
+		if (tp_port < P3H2X4X_TP_MAX_COUNT) {
+			p3h2x4x_i3c_hub->tp_bus[tp_port].of_node = dev_node;
+			p3h2x4x_i3c_hub->tp_bus[tp_port].tp_mask = P3H2X4X_SET_BIT(tp_port);
+			p3h2x4x_i3c_hub->tp_bus[tp_port].p3h2x4x_i3c_hub = p3h2x4x_i3c_hub;
+			p3h2x4x_i3c_hub->tp_bus[tp_port].tp_port = tp_port;
+		}
+	}
+}
+
+static void p3h2x4x_parse_tp_dt_settings(struct device *dev,
+					 const struct device_node *node,
+					 struct tp_configuration tp_config[])
+{
+	u64 id;
+
+	for_each_available_child_of_node_scoped(node, tp_node) {
+		if (of_property_read_reg(tp_node, 0, &id, NULL))
+			continue;
+
+		if (id >= P3H2X4X_TP_MAX_COUNT) {
+			dev_warn(dev, "Invalid target port index found in DT: %lli\n", id);
+			continue;
+		}
+
+		if (strcmp(tp_node->name, "i3c") == 0)
+			tp_config[id].mode = P3H2X4X_TP_MODE_I3C;
+
+		if (strcmp(tp_node->name, "i2c") == 0)
+			tp_config[id].mode = P3H2X4X_TP_MODE_I2C;
+
+		if (strcmp(tp_node->name, "smbus") == 0)
+			tp_config[id].mode = P3H2X4X_TP_MODE_SMBUS;
+
+		tp_config[id].pullup_en =
+			of_property_read_bool(tp_node, "nxp,pullup-enable");
+	}
+}
+
+static void p3h2x4x_get_hub_dt_conf(struct device *dev,
+				    const struct device_node *node)
+{
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
+
+	of_property_read_u32(node, "nxp,tp0145-pullup-ohms",
+			     &p3h2x4x_i3c_hub->hub_config.tp0145_pullup);
+	of_property_read_u32(node, "nxp,tp2367-pullup-ohms",
+			     &p3h2x4x_i3c_hub->hub_config.tp2367_pullup);
+	of_property_read_u32(node, "nxp,cp0-io-strength-ohms",
+			     &p3h2x4x_i3c_hub->hub_config.cp0_io_strength);
+	of_property_read_u32(node, "nxp,cp1-io-strength-ohms",
+			     &p3h2x4x_i3c_hub->hub_config.cp1_io_strength);
+	of_property_read_u32(node, "nxp,tp0145-io-strength-ohms",
+			     &p3h2x4x_i3c_hub->hub_config.tp0145_io_strength);
+	of_property_read_u32(node, "nxp,tp2367-io-strength-ohms",
+			     &p3h2x4x_i3c_hub->hub_config.tp2367_io_strength);
+
+	p3h2x4x_parse_tp_dt_settings(dev, node, p3h2x4x_i3c_hub->hub_config.tp_config);
+}
+
+static void p3h2x4x_default_configuration(struct device *dev)
+{
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = dev_get_drvdata(dev);
+	int tp_count;
+
+	p3h2x4x_i3c_hub->hub_config.tp0145_pullup = P3H2X4X_TP_PULLUP_500R;
+	p3h2x4x_i3c_hub->hub_config.tp2367_pullup = P3H2X4X_TP_PULLUP_500R;
+	p3h2x4x_i3c_hub->hub_config.cp0_io_strength = P3H2X4X_IO_STRENGTH_20_OHM;
+	p3h2x4x_i3c_hub->hub_config.cp1_io_strength = P3H2X4X_IO_STRENGTH_20_OHM;
+	p3h2x4x_i3c_hub->hub_config.tp0145_io_strength = P3H2X4X_IO_STRENGTH_20_OHM;
+	p3h2x4x_i3c_hub->hub_config.tp2367_io_strength = P3H2X4X_IO_STRENGTH_20_OHM;
+
+	for (tp_count = 0; tp_count < P3H2X4X_TP_MAX_COUNT; ++tp_count)
+		p3h2x4x_i3c_hub->hub_config.tp_config[tp_count].mode =  P3H2X4X_TP_MODE_I3C;
+}
+
+static int p3h2x4x_i3c_hub_probe(struct platform_device *pdev)
+{
+	struct p3h2x4x_dev *p3h2x4x = dev_get_drvdata(pdev->dev.parent);
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub;
+	struct device *dev = &pdev->dev;
+	struct device_node *node;
+	int ret, i;
+
+	p3h2x4x_i3c_hub = devm_kzalloc(dev, sizeof(*p3h2x4x_i3c_hub), GFP_KERNEL);
+	if (!p3h2x4x_i3c_hub)
+		return -ENOMEM;
+
+	p3h2x4x_i3c_hub->regmap = p3h2x4x->regmap;
+	p3h2x4x_i3c_hub->dev = dev;
+
+	platform_set_drvdata(pdev, p3h2x4x_i3c_hub);
+
+	p3h2x4x_default_configuration(dev);
+
+	ret = devm_mutex_init(dev, &p3h2x4x_i3c_hub->etx_mutex);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < P3H2X4X_TP_MAX_COUNT; i++) {
+		ret = devm_mutex_init(dev, &p3h2x4x_i3c_hub->tp_bus[i].port_mutex);
+		if (ret)
+			return ret;
+	}
+
+	/* get hub node from DT */
+	node =  dev->parent->of_node;
+	if (!node)
+		return dev_err_probe(dev, -ENODEV, "No Device Tree entry found\n");
+
+	p3h2x4x_get_hub_dt_conf(dev, node);
+	p3h2x4x_get_target_port_dt_conf(dev, node);
+
+	/* Unlock access to protected registers */
+	ret = regmap_write(p3h2x4x_i3c_hub->regmap, P3H2X4X_DEV_REG_PROTECTION_CODE,
+			   P3H2X4X_REGISTERS_UNLOCK_CODE);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to unlock HUB's protected registers\n");
+
+	ret = p3h2x4x_configure_hw(dev);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to configure the HUB\n");
+
+	/* Register logic for native vertual I3C ports */
+	if (p3h2x4x->is_p3h2x4x_in_i3c) {
+		p3h2x4x_i3c_hub->i3cdev = p3h2x4x->i3cdev;
+		i3cdev_set_drvdata(p3h2x4x->i3cdev, p3h2x4x_i3c_hub);
+		ret = p3h2x4x_tp_i3c_algo(p3h2x4x_i3c_hub);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to register i3c bus\n");
+	}
+
+	/* Register logic for native SMBus ports */
+	ret = p3h2x4x_tp_smbus_algo(p3h2x4x_i3c_hub);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add i2c adapter\n");
+
+	/* Lock access to protected registers */
+	ret = regmap_write(p3h2x4x_i3c_hub->regmap, P3H2X4X_DEV_REG_PROTECTION_CODE,
+			   P3H2X4X_REGISTERS_LOCK_CODE);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to lock HUB's protected registers\n");
+
+	return 0;
+}
+
+static void p3h2x4x_i3c_hub_remove(struct platform_device *pdev)
+{
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = platform_get_drvdata(pdev);
+	struct p3h2x4x_dev *p3h2x4x = dev_get_drvdata(pdev->dev.parent);
+	u8 i;
+
+	for (i = 0; i < P3H2X4X_TP_MAX_COUNT; i++) {
+		if (!p3h2x4x_i3c_hub->tp_bus[i].is_registered)
+			continue;
+
+		if (p3h2x4x_i3c_hub->hub_config.tp_config[i].mode == P3H2X4X_TP_MODE_SMBUS)
+			i2c_del_adapter(p3h2x4x_i3c_hub->tp_bus[i].tp_smbus_adapter);
+		else if (p3h2x4x_i3c_hub->hub_config.tp_config[i].mode == P3H2X4X_TP_MODE_I3C)
+			i3c_master_unregister(&p3h2x4x_i3c_hub->tp_bus[i]
+					      .hub_controller.controller);
+	}
+
+	if (p3h2x4x->is_p3h2x4x_in_i3c) {
+		i3c_device_disable_ibi(p3h2x4x->i3cdev);
+		i3c_device_free_ibi(p3h2x4x->i3cdev);
+	}
+}
+
+static struct platform_driver p3h2x4x_i3c_hub_driver = {
+	.driver = {
+		.name = "p3h2x4x-i3c-hub",
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+	.probe = p3h2x4x_i3c_hub_probe,
+	.remove = p3h2x4x_i3c_hub_remove,
+};
+module_platform_driver(p3h2x4x_i3c_hub_driver);
+
+MODULE_AUTHOR("Aman Kumar Pandey <aman.kumarpandey@nxp.com>");
+MODULE_AUTHOR("Vikash Bansal <vikash.bansal@nxp.com>");
+MODULE_AUTHOR("Lakshay Piplani <lakshay.piplani@nxp.com>");
+MODULE_DESCRIPTION("P3H2X4X I3C HUB driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i3c/hub/p3h2840_i3c_hub_i3c.c b/drivers/i3c/hub/p3h2840_i3c_hub_i3c.c
new file mode 100644
index 000000000000..cd336d336b81
--- /dev/null
+++ b/drivers/i3c/hub/p3h2840_i3c_hub_i3c.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025-2026 NXP
+ * This P3H2X4X driver file contain functions for I3C virtual Bus creation, connect/disconnect
+ * hub network and read/write.
+ */
+#include <linux/i3c/hub.h>
+#include <linux/mfd/p3h2840.h>
+#include <linux/regmap.h>
+
+#include "p3h2840_i3c_hub.h"
+
+static const struct i3c_ibi_setup p3h2x4x_ibireq = {
+	.handler = p3h2x4x_ibi_handler,
+	.max_payload_len = P3H2X4X_MAX_PAYLOAD_LEN,
+	.num_slots = P3H2X4X_NUM_SLOTS,
+};
+
+static inline struct tp_bus *
+p3h2x4x_bus_from_controller(struct i3c_master_controller *controller)
+{
+	struct i3c_hub_controller *hub_controller;
+
+	hub_controller = container_of(controller, struct i3c_hub_controller, controller);
+
+	return container_of(hub_controller, struct tp_bus, hub_controller);
+}
+
+static void p3h2x4x_hub_enable_port(struct i3c_master_controller *controller)
+{
+	struct tp_bus *bus = p3h2x4x_bus_from_controller(controller);
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = bus->p3h2x4x_i3c_hub;
+
+	if (p3h2x4x_i3c_hub->hub_config.tp_config[bus->tp_port].always_enable)
+		return;
+
+	regmap_set_bits(p3h2x4x_i3c_hub->regmap, P3H2X4X_TP_NET_CON_CONF, bus->tp_mask);
+}
+
+static void p3h2x4x_hub_disable_port(struct i3c_master_controller *controller)
+{
+	struct tp_bus *bus = p3h2x4x_bus_from_controller(controller);
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = bus->p3h2x4x_i3c_hub;
+
+	if (p3h2x4x_i3c_hub->hub_config.tp_config[bus->tp_port].always_enable)
+		return;
+
+	regmap_clear_bits(p3h2x4x_i3c_hub->regmap, P3H2X4X_TP_NET_CON_CONF, bus->tp_mask);
+}
+
+static const struct i3c_hub_ops p3h2x4x_hub_ops = {
+	.enable_port = p3h2x4x_hub_enable_port,
+	.disable_port = p3h2x4x_hub_disable_port,
+};
+
+static void p3h2x4x_unregister_i3c_master(void *data)
+{
+	struct i3c_master_controller *controller = data;
+
+	i3c_master_unregister(controller);
+}
+
+/**
+ * p3h2x4x_tp_i3c_algo - register i3c master for target port who
+ * configured as i3c.
+ * @p3h2x4x_hub: p3h2x4x device structure.
+ * Return: 0 in case of success, negative error code on failur.
+ */
+int p3h2x4x_tp_i3c_algo(struct p3h2x4x_i3c_hub_dev *p3h2x4x_hub)
+{
+	struct i3c_master_controller *parent = i3c_dev_get_master(p3h2x4x_hub->i3cdev->desc);
+	u8 tp, ntwk_mask = 0;
+	int ret;
+
+	p3h2x4x_hub->hub = i3c_hub_init(parent,
+					&p3h2x4x_hub_ops,
+					p3h2x4x_hub->i3cdev);
+
+	if (IS_ERR(p3h2x4x_hub->hub))
+		return PTR_ERR(p3h2x4x_hub->hub);
+
+	for (tp = 0; tp < P3H2X4X_TP_MAX_COUNT; tp++) {
+		if (!p3h2x4x_hub->tp_bus[tp].of_node ||
+		    p3h2x4x_hub->hub_config.tp_config[tp].mode != P3H2X4X_TP_MODE_I3C)
+			continue;
+
+		/* Assign DT node for this TP */
+		p3h2x4x_hub->dev->of_node = p3h2x4x_hub->tp_bus[tp].of_node;
+
+		struct i3c_hub_controller *hub_controller =
+				&p3h2x4x_hub->tp_bus[tp].hub_controller;
+		struct i3c_master_controller *controller = &hub_controller->controller;
+
+		hub_controller->parent = parent;
+		hub_controller->hub = p3h2x4x_hub->hub;
+
+		dev_set_drvdata(&controller->dev, hub_controller);
+
+		ret = i3c_master_register(controller,
+					  p3h2x4x_hub->dev,
+					  i3c_hub_master_ops(),
+					  false);
+
+		if (ret)
+			return ret;
+
+		ret = devm_add_action_or_reset(p3h2x4x_hub->dev,
+					       p3h2x4x_unregister_i3c_master,
+					       controller);
+		if (ret)
+			return ret;
+
+		/* Perform DAA */
+		ret = i3c_master_do_daa(parent);
+		if (ret)
+			return ret;
+
+		ntwk_mask |= p3h2x4x_hub->tp_bus[tp].tp_mask;
+		p3h2x4x_hub->tp_bus[tp].is_registered = true;
+		p3h2x4x_hub->hub_config.tp_config[tp].always_enable = true;
+	}
+
+	ret = i3c_device_request_ibi(p3h2x4x_hub->i3cdev, &p3h2x4x_ibireq);
+	if (ret)
+		return ret;
+
+	ret = i3c_device_enable_ibi(p3h2x4x_hub->i3cdev);
+	if (ret)
+		return ret;
+
+	return regmap_write(p3h2x4x_hub->regmap, P3H2X4X_TP_NET_CON_CONF, ntwk_mask);
+}
diff --git a/drivers/i3c/hub/p3h2840_i3c_hub_smbus.c b/drivers/i3c/hub/p3h2840_i3c_hub_smbus.c
new file mode 100644
index 000000000000..8707c0fbf5b1
--- /dev/null
+++ b/drivers/i3c/hub/p3h2840_i3c_hub_smbus.c
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025-2026 NXP
+ * This P3H2X4X driver file contain functions for SMBus/I2C virtual Bus creation and read/write.
+ */
+#include <linux/mfd/p3h2840.h>
+#include <linux/regmap.h>
+
+#include "p3h2840_i3c_hub.h"
+
+enum p3h2x4x_smbus_desc_idx {
+	P3H2X4X_DESC_ADDR,
+	P3H2X4X_DESC_TYPE,
+	P3H2X4X_DESC_WRITE_LEN,
+	P3H2X4X_DESC_READ_LEN,
+};
+
+static void p3h2x4x_read_smbus_agent_rx_buf(struct i3c_device *i3cdev, enum p3h2x4x_rcv_buf rfbuf,
+					    enum p3h2x4x_tp tp, bool is_of)
+{
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = i3cdev_get_drvdata(i3cdev);
+	u8 slave_rx_buffer[P3H2X4X_SMBUS_TARGET_PAYLOAD_SIZE] = { 0 };
+	u8 target_buffer_page, flag_clear = 0x0f, temp, i;
+	u32 packet_len, slave_address, ret;
+
+	target_buffer_page = (((rfbuf) ? P3H2X4X_TARGET_BUFF_1_PAGE : P3H2X4X_TARGET_BUFF_0_PAGE)
+				+  (P3H2X4X_NO_PAGE_PER_TP * tp));
+	ret = regmap_write(p3h2x4x_i3c_hub->regmap, P3H2X4X_PAGE_PTR, target_buffer_page);
+	if (ret)
+		goto ibi_err;
+
+	/* read buffer length */
+	ret = regmap_read(p3h2x4x_i3c_hub->regmap, P3H2X4X_TARGET_BUFF_LENGTH, &packet_len);
+	if (ret)
+		goto ibi_err;
+
+	if (packet_len)
+		packet_len = packet_len - 1;
+
+	if (packet_len > P3H2X4X_SMBUS_TARGET_PAYLOAD_SIZE) {
+		dev_err(&i3cdev->dev, "Received message too big for p3h2x4x buffer\n");
+		return;
+	}
+
+	/* read slave  address */
+	ret = regmap_read(p3h2x4x_i3c_hub->regmap, P3H2X4X_TARGET_BUFF_ADDRESS, &slave_address);
+	if (ret)
+		goto ibi_err;
+
+	/* read data */
+	if (packet_len) {
+		ret = regmap_bulk_read(p3h2x4x_i3c_hub->regmap, P3H2X4X_TARGET_BUFF_DATA,
+				       slave_rx_buffer, packet_len);
+		if (ret)
+			goto ibi_err;
+	}
+
+	if (is_of)
+		flag_clear = BUF_RECEIVED_FLAG_TF_MASK;
+	else
+		flag_clear = (((rfbuf == RCV_BUF_0) ? P3H2X4X_TARGET_BUF_0_RECEIVE :
+				P3H2X4X_TARGET_BUF_1_RECEIVE));
+
+	/* notify slave driver about received data */
+	if ((p3h2x4x_i3c_hub->tp_bus[tp].tp_smbus_client->addr & 0x7f) == (slave_address >> 1)) {
+		i2c_slave_event(p3h2x4x_i3c_hub->tp_bus[tp].tp_smbus_client,
+				I2C_SLAVE_WRITE_REQUESTED, (u8 *)&slave_address);
+		for (i = 0; i < packet_len; i++) {
+			temp = slave_rx_buffer[i];
+			i2c_slave_event(p3h2x4x_i3c_hub->tp_bus[tp].tp_smbus_client,
+					I2C_SLAVE_WRITE_RECEIVED, &temp);
+		}
+		i2c_slave_event(p3h2x4x_i3c_hub->tp_bus[tp].tp_smbus_client, I2C_SLAVE_STOP, &temp);
+	}
+
+ibi_err:
+	regmap_write(p3h2x4x_i3c_hub->regmap, P3H2X4X_PAGE_PTR, 0x00);
+	regmap_write(p3h2x4x_i3c_hub->regmap, P3H2X4X_TP0_SMBUS_AGNT_STS + tp, flag_clear);
+}
+
+/**
+ * p3h2x4x_ibi_handler - IBI handler.
+ * @i3cdev: i3c device.
+ * @payload: two byte IBI payload data.
+ *
+ */
+void p3h2x4x_ibi_handler(struct i3c_device *i3cdev,
+			 const struct i3c_ibi_payload *payload)
+{
+	u32 target_port_status, payload_byte_one, payload_byte_two;
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub;
+	u32 ret, i;
+
+	payload_byte_one = (*(int *)payload->data);
+
+	if (!(payload_byte_one & P3H2X4X_SMBUS_AGENT_EVENT_FLAG_STATUS))
+		return;
+
+	p3h2x4x_i3c_hub = i3cdev_get_drvdata(i3cdev);
+
+	if (!p3h2x4x_i3c_hub || !p3h2x4x_i3c_hub->regmap)
+		return;
+
+	payload_byte_two = (*(int *)(payload->data + 4));
+	guard(mutex)(&p3h2x4x_i3c_hub->etx_mutex);
+
+	for (i = 0; i < P3H2X4X_TP_MAX_COUNT; ++i) {
+		if (p3h2x4x_i3c_hub->tp_bus[i].is_registered && (payload_byte_two >> i) & 0x01) {
+			ret = regmap_read(p3h2x4x_i3c_hub->regmap, P3H2X4X_TP0_SMBUS_AGNT_STS + i,
+					  &target_port_status);
+			if (ret) {
+				dev_err(&i3cdev->dev, "target port read status failed %d\n", ret);
+				return;
+			}
+
+			/* process data receive buffer */
+			switch (target_port_status & BUF_RECEIVED_FLAG_MASK) {
+			case P3H2X4X_TARGET_BUF_CA_TF:
+				break;
+			case P3H2X4X_TARGET_BUF_0_RECEIVE:
+				p3h2x4x_read_smbus_agent_rx_buf(i3cdev, RCV_BUF_0, i, false);
+				break;
+			case P3H2X4X_TARGET_BUF_1_RECEIVE:
+				p3h2x4x_read_smbus_agent_rx_buf(i3cdev, RCV_BUF_1, i, false);
+				break;
+			case P3H2X4X_TARGET_BUF_0_1_RECEIVE:
+				p3h2x4x_read_smbus_agent_rx_buf(i3cdev, RCV_BUF_0, i, false);
+				p3h2x4x_read_smbus_agent_rx_buf(i3cdev, RCV_BUF_1, i, false);
+				break;
+			case P3H2X4X_TARGET_BUF_OVRFL:
+				p3h2x4x_read_smbus_agent_rx_buf(i3cdev, RCV_BUF_0, i, false);
+				p3h2x4x_read_smbus_agent_rx_buf(i3cdev, RCV_BUF_1, i, true);
+				dev_err(&i3cdev->dev, "Overflow, reading buffer zero and one\n");
+				break;
+			default:
+				regmap_write(p3h2x4x_i3c_hub->regmap,
+					     P3H2X4X_TP0_SMBUS_AGNT_STS + i,
+					     BUF_RECEIVED_FLAG_TF_MASK);
+				break;
+			}
+		}
+	}
+}
+
+static int p3h2x4x_read_smbus_transaction_status(struct p3h2x4x_i3c_hub_dev *hub,
+						 u8 target_port_status,
+						 u8 data_length)
+{
+	u32 status_read;
+	u8 status;
+	int ret;
+
+	mutex_unlock(&hub->etx_mutex);
+	fsleep(P3H2X4X_SMBUS_400kHz_TRANSFER_TIMEOUT(data_length));
+	mutex_lock(&hub->etx_mutex);
+
+	ret = regmap_read(hub->regmap, target_port_status, &status_read);
+	if (ret)
+		return ret;
+
+	status = (u8)status_read;
+
+	status = (status & P3H2X4X_TP_TRANSACTION_CODE_MASK)
+		  >> P3H2X4X_SMBUS_CNTRL_STATUS_TXN_SHIFT;
+
+	switch (status) {
+	case P3H2X4X_SMBUS_CNTRL_STATUS_TXN_OK:
+		return 0;
+	case P3H2X4X_SMBUS_CNTRL_STATUS_TXN_ADDR_NAK:
+		return -ENXIO;
+	case P3H2X4X_SMBUS_CNTRL_STATUS_TXN_DATA_NAK:
+		return -EIO;
+	case P3H2X4X_SMBUS_CNTRL_STATUS_TXN_SCL_TO:
+		return -ETIMEDOUT;
+	case P3H2X4X_SMBUS_CNTRL_STATUS_TXN_ARB_LOSS:
+		return -EAGAIN;
+	default:
+		return -EIO;
+	}
+}
+
+/*
+ * p3h2x4x_tp_i2c_xfer_msg() - This starts a SMBus write transaction by writing a descriptor
+ * and a message to the p3h2x4x registers. Controller buffer page is determined by multiplying the
+ * target port index by four and adding the base page number to it.
+ */
+static int p3h2x4x_tp_i2c_xfer_msg(struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub,
+				   struct i2c_msg *xfers,
+				   u8 target_port,
+				   u8 nxfers_i, u8 rw)
+{
+	u8 controller_buffer_page = P3H2X4X_CONTROLLER_BUFFER_PAGE + 4 * target_port;
+	u8 target_port_status = P3H2X4X_TP0_SMBUS_AGNT_STS + target_port;
+	u8 desc[P3H2X4X_SMBUS_DESCRIPTOR_SIZE] = { 0 };
+	u8 transaction_type = P3H2X4X_SMBUS_400kHz;
+	int write_length, read_length;
+	u8 addr = xfers[nxfers_i].addr;
+	u8 rw_address = 2 * addr;
+	int ret, ret2;
+
+	if (rw == 2) { /* write and read */
+		write_length = xfers[nxfers_i].len;
+		read_length =  xfers[nxfers_i + 1].len;
+	} else if (rw == 1) {
+		rw_address |= P3H2X4X_SET_BIT(0);
+		write_length = 0;
+		read_length =  xfers[nxfers_i].len;
+	} else {
+		write_length = xfers[nxfers_i].len;
+		read_length = 0;
+	}
+
+	desc[P3H2X4X_DESC_ADDR] = rw_address;
+	if (rw == 2)
+		desc[P3H2X4X_DESC_TYPE] = transaction_type | P3H2X4X_SET_BIT(0);
+	else
+		desc[P3H2X4X_DESC_TYPE] = transaction_type;
+	desc[P3H2X4X_DESC_WRITE_LEN] = write_length;
+	desc[P3H2X4X_DESC_READ_LEN] = read_length;
+
+	ret = regmap_write(p3h2x4x_i3c_hub->regmap, target_port_status,
+			   P3H2X4X_TP_BUFFER_STATUS_MASK);
+	if (ret)
+		goto out;
+
+	ret = regmap_write(p3h2x4x_i3c_hub->regmap, P3H2X4X_PAGE_PTR, controller_buffer_page);
+
+	if (ret)
+		goto out;
+
+	ret = regmap_bulk_write(p3h2x4x_i3c_hub->regmap, P3H2X4X_CONTROLLER_AGENT_BUFF,
+				desc, P3H2X4X_SMBUS_DESCRIPTOR_SIZE);
+
+	if (ret)
+		goto out;
+
+	if (!(rw % 2)) {
+		ret = regmap_bulk_write(p3h2x4x_i3c_hub->regmap,
+					P3H2X4X_CONTROLLER_AGENT_BUFF_DATA,
+					xfers[nxfers_i].buf, xfers[nxfers_i].len);
+		if (ret)
+			goto out;
+	}
+
+	ret = regmap_write(p3h2x4x_i3c_hub->regmap, P3H2X4X_TP_SMBUS_AGNT_TRANS_START,
+			   p3h2x4x_i3c_hub->tp_bus[target_port].tp_mask);
+
+	if (ret)
+		goto out;
+
+	ret = p3h2x4x_read_smbus_transaction_status(p3h2x4x_i3c_hub,
+						    target_port_status,
+						    (write_length + read_length));
+	if (ret)
+		goto out;
+
+	if (rw) {
+		if (rw == 2)
+			nxfers_i += 1;
+
+		ret = regmap_bulk_read(p3h2x4x_i3c_hub->regmap,
+				       P3H2X4X_CONTROLLER_AGENT_BUFF_DATA + write_length,
+				       xfers[nxfers_i].buf, xfers[nxfers_i].len);
+		if (ret)
+			goto out;
+	}
+out:
+	ret2 = regmap_write(p3h2x4x_i3c_hub->regmap,
+			    P3H2X4X_PAGE_PTR, 0x00);
+	if (!ret && ret2)
+		ret = ret2;
+
+	return ret;
+}
+
+/*
+ * This function will be called whenever you call I2C read, write APIs like
+ * i2c_master_send(), i2c_master_recv() etc.
+ */
+static s32 p3h2x4x_tp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+	int ret_sum = 0, ret;
+	u8 msg_count, rw;
+
+	struct tp_bus *bus = i2c_get_adapdata(adap);
+	struct p3h2x4x_i3c_hub_dev *p3h2x4x_i3c_hub = bus->p3h2x4x_i3c_hub;
+
+	guard(mutex)(&p3h2x4x_i3c_hub->etx_mutex);
+	guard(mutex)(&bus->port_mutex);
+
+	for (msg_count = 0; msg_count < num; msg_count++) {
+		if (msgs[msg_count].len > P3H2X4X_SMBUS_PAYLOAD_SIZE) {
+			dev_err(p3h2x4x_i3c_hub->dev,
+				"Message nr. %d not sent - length over %d bytes.\n",
+				msg_count, P3H2X4X_SMBUS_PAYLOAD_SIZE);
+			continue;
+		}
+
+		rw = (msgs[msg_count].flags & I2C_M_RD) ? 1 : 0;
+		if (!rw) {
+			/* If a read message is immediately followed by a write message to
+			 * the same address,  consider combining them into a single transaction.
+			 */
+			if (msg_count + 1 < num &&
+			    msgs[msg_count].addr == msgs[msg_count + 1].addr &&
+			    (msgs[msg_count + 1].flags & I2C_M_RD)) {
+				rw = 2;
+				msg_count += 1;
+				ret_sum += 1;
+			}
+		}
+
+		ret = p3h2x4x_tp_i2c_xfer_msg(p3h2x4x_i3c_hub,
+					      msgs,
+					      bus->tp_port,
+					      (rw == 2) ? (msg_count - 1) : msg_count,
+					       rw);
+		if (ret)
+			return ret;
+
+		ret_sum++;
+	}
+	return ret_sum;
+}
+
+static u32 p3h2x4x_tp_smbus_funcs(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static int p3h2x4x_tp_i2c_reg_slave(struct i2c_client *slave)
+{
+	struct tp_bus *bus = i2c_get_adapdata(slave->adapter);
+
+	if (bus->tp_smbus_client)
+		return -EBUSY;
+
+	bus->tp_smbus_client = slave;
+
+	return 0;
+}
+
+static int p3h2x4x_tp_i2c_unreg_slave(struct i2c_client *slave)
+{
+	struct tp_bus *bus = i2c_get_adapdata(slave->adapter);
+
+	bus->tp_smbus_client = NULL;
+
+	return 0;
+}
+#endif
+
+/*
+ * I2C algorithm Structure
+ */
+static struct i2c_algorithm p3h2x4x_tp_i2c_algorithm = {
+	.master_xfer    = p3h2x4x_tp_i2c_xfer,
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+	.reg_slave = p3h2x4x_tp_i2c_reg_slave,
+	.unreg_slave = p3h2x4x_tp_i2c_unreg_slave,
+#endif
+	.functionality  = p3h2x4x_tp_smbus_funcs,
+};
+
+/**
+ * p3h2x4x_tp_smbus_algo - add i2c adapter for target port who
+ * configured as SMBus.
+ * @hub: p3h2x4x device structure.
+ * Return: 0 in case of success, negative error code on failur.
+ */
+int p3h2x4x_tp_smbus_algo(struct p3h2x4x_i3c_hub_dev *hub)
+{
+	u8 tp, ibi_mask = 0;
+	int ret;
+
+	for (tp = 0; tp < P3H2X4X_TP_MAX_COUNT; tp++) {
+		if (!hub->tp_bus[tp].of_node ||
+		    hub->hub_config.tp_config[tp].mode != P3H2X4X_TP_MODE_SMBUS)
+			continue;
+
+		/* Allocate adapter */
+		struct i2c_adapter *smbus_adapter =
+			devm_kzalloc(hub->dev, sizeof(*smbus_adapter), GFP_KERNEL);
+		if (!smbus_adapter)
+			return -ENOMEM;
+
+		/* Initialize adapter */
+		smbus_adapter->owner = THIS_MODULE;
+		smbus_adapter->class = I2C_CLASS_HWMON;
+		smbus_adapter->algo = &p3h2x4x_tp_i2c_algorithm;
+		smbus_adapter->dev.parent = hub->dev;
+		smbus_adapter->dev.of_node = hub->tp_bus[tp].of_node;
+		snprintf(smbus_adapter->name, sizeof(smbus_adapter->name),
+			 "p3h2x4x-i3c-hub.tp-port-%d", tp);
+
+		i2c_set_adapdata(smbus_adapter, &hub->tp_bus[tp]);
+
+		/* Register adapter */
+		ret = i2c_add_adapter(smbus_adapter);
+		if (ret) {
+			devm_kfree(hub->dev, smbus_adapter);
+			return ret;
+		}
+
+		ibi_mask |= hub->tp_bus[tp].tp_mask;
+		hub->tp_bus[tp].is_registered = true;
+		hub->hub_config.tp_config[tp].ibi_en = true;
+		hub->tp_bus[tp].tp_smbus_adapter = smbus_adapter;
+	}
+
+	/*
+	 * holding SDA low when both SMBus Target Agent received data buffers are full.
+	 * This feature can be used as a flow-control mechanism for MCTP applications to
+	 * avoid MCTP transmitters on Target Ports time out when the SMBus agent buffers
+	 * are not serviced in time by upstream controller and only receives write message
+	 * from its downstream ports.
+	 */
+	ret = regmap_update_bits(hub->regmap, P3H2X4X_ONCHIP_TD_AND_SMBUS_AGNT_CONF,
+				 P3H2X4X_TARGET_AGENT_DFT_IBI_CONF_MASK,
+				 P3H2X4X_TARGET_AGENT_DFT_IBI_CONF);
+	if (ret)
+		return ret;
+
+	return regmap_write(hub->regmap, P3H2X4X_TP_SMBUS_AGNT_IBI_CONFIG, ibi_mask);
+}
diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h
index 971d53349b6f..6188082599dd 100644
--- a/include/linux/i3c/device.h
+++ b/include/linux/i3c/device.h
@@ -85,6 +85,7 @@ struct i3c_xfer {
  */
 enum i3c_dcr {
 	I3C_DCR_GENERIC_DEVICE = 0,
+	I3C_DCR_HUB = 194,
 };
 
 #define I3C_PID_MANUF_ID(pid)		(((pid) & GENMASK_ULL(47, 33)) >> 33)
-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH 1/2] arm64: dts: qcom: sc8280xp: add several missing pdc map entries
From: Konrad Dybcio @ 2026-04-20 10:58 UTC (permalink / raw)
  To: Pengyu Luo
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <CAH2e8h49SxvPtSXB1AWcNNfqC_ZV6-V2YKbN2_rwSemh7G3b6w@mail.gmail.com>

On 4/20/26 12:47 PM, Pengyu Luo wrote:
> On Mon, Apr 20, 2026 at 6:21 PM Konrad Dybcio
> <konrad.dybcio@oss.qualcomm.com> wrote:
>>
>> On 4/20/26 11:53 AM, Pengyu Luo wrote:
>>> On Mon, Apr 20, 2026 at 4:32 PM Konrad Dybcio
>>> <konrad.dybcio@oss.qualcomm.com> wrote:
>>>>
>>>> On 4/19/26 7:32 PM, Pengyu Luo wrote:
>>>>> pdc 215, 256, 257 are missing, but we can find tlmm pin 103, 84, 90
>>>>> are mapped to them respectively, so add the map entries from pdc to
>>>>> gic. These entries are reversed from .data section of qcgpio.sys
>>>>>
>>>>> Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com>
>>>>> ---
>>>>
>>>> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>>
>>>> Konrad
>>>>
>>>> The below change on top will fully align it with the data in the docs
>>>> (no functional change)
>>>>
>>>
>>> Glad to know. Could you please help to check the tlmm map too? When I
>>> was parsing the binary, I found
>>>
>>> tlmm 65535 => pdc 70 => gic 520
>>> tlmm 65535 => pdc 174 => gic 733
>>> tlmm 65535 => pdc 175 => gic 734
>>> tlmm 65535 => pdc 176 => gic 735
>>> tlmm 65535 => pdc 177 => gic 736
>>> tlmm 65535 => pdc 178 => gic 737
>>> tlmm 65535 => pdc 184 => gic 743
>>> tlmm 65535 => pdc 185 => gic 744
>>> tlmm 65535 => pdc 186 => gic 745
>>> tlmm 65535 => pdc 187 => gic 746
>>> tlmm 65535 => pdc 188 => gic 747
>>> tlmm 65535 => pdc 194 => gic 753
>>> tlmm 65535 => pdc 195 => gic 754
>>> tlmm 65535 => pdc 196 => gic 755
>>> tlmm 65535 => pdc 197 => gic 756
>>> tlmm 65535 => pdc 198 => gic 757
>>> tlmm 65535 => pdc 199 => gic 416
>>> tlmm 65535 => pdc 204 => gic 462
>>> tlmm 65535 => pdc 205 => gic 264
>>>
>>> If 65536 means the pin is missing, I will send v2 to remove the tlmm
>>> map together with the pdc removal.
>>
>> These seem to be LPASS/SSC GPIOs
>>
>> There are missing pairs of:
>>
>> TLMM 151 -> PDC 264 -> GIC 191
>> TLMM 143 -> PDC 261 -> GIC 402
>>
>> and very interestingly, GPIO 190 has two mappings:
>> PDC 70 -> GIC 552
> 
> PDC 70 is connected to swr2, which is wakeable. Speaking of this, in
> qcom,pdc.yaml
> 
> Drivers requiring wakeup capabilities of their device interrupts
> routed through the PDC, must specify PDC as their interrupt controller
> and request the PDC port associated with the GIC interrupt.
> 
> But swr2 specifies GIC.
> 
> I wonder, when should we use tlmm, when pdc, when gic?

I would assume "pdc, whenever available"

Konrad

^ permalink raw reply

* Re: [PATCH 05/40] arm64: dts: rockchip: Add frl-enable-gpios to rk3576-luckfox-core3576
From: Cristian Ciocaltea @ 2026-04-20 11:00 UTC (permalink / raw)
  To: Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: kernel, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel
In-Reply-To: <2282688.C4sosBPzcN@phil>

Hi Heiko,

On 4/18/26 2:12 AM, Heiko Stuebner wrote:
> Hi Cristian,
> 
> Am Freitag, 17. April 2026, 18:34:17 Mitteleuropäische Sommerzeit schrieb Cristian Ciocaltea:
>> On 4/17/26 2:32 PM, Heiko Stuebner wrote:
>>> the comments below apply sort of to all patches in that series.
>>>
>>> Am Freitag, 17. April 2026, 11:24:39 Mitteleuropäische Sommerzeit schrieb Cristian Ciocaltea:
>>>> The board exposes the GPIO4_C6 line to control the voltage bias on the
>>>> HDMI data lines.  It must be asserted when operating in HDMI 2.1 FRL
>>>> mode and deasserted for HDMI 1.4/2.0 TMDS mode.
>>>>
>>>> Wire up the HDMI node to the GPIO line using the frl-enable-gpios
>>>> property and drop the line from the vcc_5v0_hdmi regulator to allow
>>>> adjusting the bias when transitioning between TMDS and FRL operating
>>>> modes.

[...]

>>>
>>>
>>>> @@ -231,6 +228,8 @@ &gpu {
>>>>  };
>>>>  
>>>>  &hdmi {
>>>> +	pinctrl-0 = <&hdmi_txm0_pins &hdmi_tx_scl &hdmi_tx_sda &hdmi_frl_en>;
>>>> +	frl-enable-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_LOW>;
>>>
>>> this should be sorted the other way around I think.
>>>
>>> Also please provide a pinctrl-names property too. If for whatever reason
>>> the dw-hdmi aquires a 2nd pinctrl state in the future, this makes sure
>>> board DTs are staying in the "old" compatible mode until they are adapted.
>>
>> Just to make sure I fully understand, the convention is that 
>>
>>   pinctrl-names = "default";
>>
>> should be always provided, even when the node overrides an existing pinctrl-0
>> property?
>>
>> E.g. in rk3576.dtsi we have:
>>
>>   hdmi: hdmi@27da0000 {
>>     ...
>>     pinctrl-names = "default";
>>     pinctrl-0 = <&hdmi_txm0_pins &hdmi_tx_scl &hdmi_tx_sda>;
>>     ...
>>   }
>>
>> Hence I omitted pinctrl-names which doesn't change and just appended
>> &hdmi_frl_en to pinctrl-0's original value.
> 
> correct, please always provide a pinctrl-names entry when setting a new
> pinctrl-0 .
> 
> The background is, imagine you have a base:
> 
> pinctrl-names = "default";
> pinstrl-0 = <....>;
> 
> and override pinctrl-0 in a board.
> 
> Now a newer binding introduces a 2nd pinctrl state "foo". Of course
> we're backwards compatible, and both are valid and the driver checks
> what states are defined.
> 
> So the base sets:
> pinctrl-names = "default", "foo";
> pinctrl-0 = <...>;
> pinctrl-1 = <...>;
> 
> in your (old) board you override pinctrl-0, but the driver still sees
> the new variant with 2 pinctrl states, where it should've stayed with
> the legacy 1-state, until the board-dts might get adapted in the future.
> 
> 
> And I know, we're likely not doing that everywhere, and also in most
> cases it won't really matter, but still it is safer and sets the better
> precedent :-) .

Thanks for the detailed explanation, that clears things up!

There are several other nodes (e.g. i2c, pwm, uart) that also lack
pinctrl-names despite providing pinctrl-0 - I can address those in a
separate patch.

I also noticed an inconsistency in property ordering: some nodes place
pinctrl-names before pinctrl-<n> and others after.  I have always used
the former, but we should probably prefer the latter to stay consistent
with how clocks, resets, phys, etc. are ordered.

Thoughts?

> 
>>>>  	status = "okay";
>>>>  };
>>>>  
>>>> @@ -655,7 +654,7 @@ &pcie0 {
>>>>  
>>>>  &pinctrl {
>>>>  	hdmi {
>>>> -		hdmi_con_en: hdmi-con-en {
>>>> +		hdmi_frl_en: hdmi-frl-en {
>>>
>>> pinctrl names should ideally match the naming in schematics, for example the
>>> "HDMI0_TX_ON_H" for jaguar and tiger. This makes it way easier to> go from DT
>>> to schematics and back.
>>
>> I opted for a more descriptive name that could be used consistently across all
>> boards, given that not all schematics are publicly available.
>>
>> You make a fair point though, we should probably stick with the pretty terrible
>> hdmi[N]_tx_on_h naming instead.
> 
> yep, we're doing that everywhere else already too, and sticking to the
> schematics naming, also prevents any discussions about how something
> should be named ;-) .

Indeed. :)

^ permalink raw reply

* [PATCH v9 1/7] i3c: master: Expose the APIs to support I3C hub
From: Lakshay Piplani @ 2026-04-20 10:52 UTC (permalink / raw)
  To: linux-kernel, linux-i3c, alexandre.belloni, krzk+dt, robh,
	conor+dt, devicetree, broonie, lee, Frank.Li, lgirdwood
  Cc: vikash.bansal, priyanka.jain, aman.kumarpandey, Lakshay Piplani
In-Reply-To: <20260420105222.1562243-1-lakshay.piplani@nxp.com>

From: Aman Kumar Pandey <aman.kumarpandey@nxp.com>

The following APIs were already declared in i3c_internals.h but were
missing EXPORT_SYMBOL_GPL() in their implementation, making them
inaccessible to modular drivers such as the I3C hub driver:

1) i3c_dev_enable_ibi_locked()
2) i3c_dev_disable_ibi_locked()
3) i3c_dev_request_ibi_locked()
4) i3c_dev_free_ibi_locked()

i3c_master_reattach_i3c_dev() is declared in include/linux/i3c/master.h
and exported via EXPORT_SYMBOL_GPL() to make it accessible to the I3C
hub driver.

Signed-off-by: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>

---
Changes in v9:
 - No change

Changes in v8:
 - No change

Changes in v7:
 - Fix kernel-doc warnings for *_locked() APIs
 - Clarify API exposure in commit message

Changes in v6:
 - Split the patch into two parts:
        1) expose the existing API
        2) add new APIs.

Changes in v5:
 - No change

Changes in v4:
 - Updated I3C master to handle hub support
---
---
 drivers/i3c/master.c       | 70 ++++++++++++++++++++++++++++++++++++--
 include/linux/i3c/master.h |  2 ++
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 5cd4e5da2233..d11fe6937ba8 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1652,8 +1652,23 @@ static int i3c_master_attach_i3c_dev(struct i3c_master_controller *master,
 	return 0;
 }
 
-static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
-				       u8 old_dyn_addr)
+/**
+ * i3c_master_reattach_i3c_dev() - reattach an I3C device with a new address
+ * @dev: I3C device descriptor to reattach
+ * @old_dyn_addr: previous dynamic address of the device
+ *
+ * This function reattaches an existing I3C device to the bus when its dynamic
+ * address has changed. It updates the bus address slot status accordingly:
+ * - Marks the new dynamic address as occupied by an I3C device.
+ * - Frees the old dynamic address slot if applicable.
+ *
+ * This function must be called with the bus lock held in write mode.
+ *
+ * Return: 0 on success, or a negative error code if reattachment fails
+ *         (e.g. -EBUSY if the new address slot is not free).
+ */
+int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
+				u8 old_dyn_addr)
 {
 	struct i3c_master_controller *master = i3c_dev_get_master(dev);
 	int ret;
@@ -1677,6 +1692,7 @@ static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(i3c_master_reattach_i3c_dev);
 
 static void i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
 {
@@ -3195,6 +3211,16 @@ int i3c_dev_do_xfers_locked(struct i3c_dev_desc *dev, struct i3c_xfer *xfers,
 	return master->ops->i3c_xfers(dev, xfers, nxfers, mode);
 }
 
+/**
+ * i3c_dev_disable_ibi_locked() - Disable IBIs coming from a specific device
+ * @dev: device on which IBIs should be disabled
+ *
+ * This function disable IBIs coming from a specific device and wait for
+ * all pending IBIs to be processed.
+ *
+ * Context: Must be called with mutex_lock(&dev->desc->ibi_lock) held.
+ * Return: 0 in case of success, a negative error core otherwise.
+ */
 int i3c_dev_disable_ibi_locked(struct i3c_dev_desc *dev)
 {
 	struct i3c_master_controller *master;
@@ -3216,7 +3242,22 @@ int i3c_dev_disable_ibi_locked(struct i3c_dev_desc *dev)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(i3c_dev_disable_ibi_locked);
 
+/**
+ * i3c_dev_enable_ibi_locked() - Enable IBIs from a specific device (lock held)
+ * @dev: device on which IBIs should be enabled
+ *
+ * This function enable IBIs coming from a specific device and wait for
+ * all pending IBIs to be processed. This should be called on a device
+ * where i3c_device_request_ibi() has succeeded.
+ *
+ * Note that IBIs from this device might be received before this function
+ * returns to its caller.
+ *
+ * Context: Must be called with mutex_lock(&dev->desc->ibi_lock) held.
+ * Return: 0 on success, or a negative error code on failure.
+ */
 int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev)
 {
 	struct i3c_master_controller *master = i3c_dev_get_master(dev);
@@ -3231,7 +3272,20 @@ int i3c_dev_enable_ibi_locked(struct i3c_dev_desc *dev)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(i3c_dev_enable_ibi_locked);
 
+/**
+ * i3c_dev_request_ibi_locked() - Request an IBI
+ * @dev: device for which we should enable IBIs
+ * @req: setup requested for this IBI
+ *
+ * This function is responsible for pre-allocating all resources needed to
+ * process IBIs coming from @dev. When this function returns, the IBI is not
+ * enabled until i3c_device_enable_ibi() is called.
+ *
+ * Context: Must be called with mutex_lock(&dev->desc->ibi_lock) held.
+ * Return: 0 in case of success, a negative error core otherwise.
+ */
 int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
 			       const struct i3c_ibi_setup *req)
 {
@@ -3270,7 +3324,18 @@ int i3c_dev_request_ibi_locked(struct i3c_dev_desc *dev,
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(i3c_dev_request_ibi_locked);
 
+/**
+ * i3c_dev_free_ibi_locked() - Free all resources needed for IBI handling
+ * @dev: device on which you want to release IBI resources
+ *
+ * This function is responsible for de-allocating resources previously
+ * allocated by i3c_device_request_ibi(). It should be called after disabling
+ * IBIs with i3c_device_disable_ibi().
+ *
+ * Context: Must be called with mutex_lock(&dev->desc->ibi_lock) held.
+ */
 void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
 {
 	struct i3c_master_controller *master = i3c_dev_get_master(dev);
@@ -3301,6 +3366,7 @@ void i3c_dev_free_ibi_locked(struct i3c_dev_desc *dev)
 	kfree(dev->ibi);
 	dev->ibi = NULL;
 }
+EXPORT_SYMBOL_GPL(i3c_dev_free_ibi_locked);
 
 static int __init i3c_init(void)
 {
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 592b646f6134..aeccec171e64 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -613,6 +613,8 @@ void i3c_master_dma_unmap_single(struct i3c_dma *dma_xfer);
 DEFINE_FREE(i3c_master_dma_unmap_single, void *,
 	    if (_T) i3c_master_dma_unmap_single(_T))
 
+int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
+				u8 old_dyn_addr);
 int i3c_master_set_info(struct i3c_master_controller *master,
 			const struct i3c_device_info *info);
 
-- 
2.25.1


^ permalink raw reply related

* [PATCH v9 4/7] mfd: p3h2x4x: Add driver for NXP P3H2x4x i3c hub and on-die regulator
From: Lakshay Piplani @ 2026-04-20 10:52 UTC (permalink / raw)
  To: linux-kernel, linux-i3c, alexandre.belloni, krzk+dt, robh,
	conor+dt, devicetree, broonie, lee, Frank.Li, lgirdwood
  Cc: vikash.bansal, priyanka.jain, aman.kumarpandey, Lakshay Piplani
In-Reply-To: <20260420105222.1562243-1-lakshay.piplani@nxp.com>

From: Aman Kumar Pandey <aman.kumarpandey@nxp.com>

Add core MFD support for the NXP P3H2x4x (P3H2440/P3H2441/P3H2840/P3H2841)
family of multiport I3C hub devices. These devices connect to a host via
I3C/I2C/SMBus and expose multiple downstream target ports.

Signed-off-by: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
Signed-off-by: Vikash Bansal <vikash.bansal@nxp.com>
Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>

---
Changes in v9:
 - Renamed macros to follow consistent uppercase naming conventions
 - Made REGMAP selects in the P3H2X4X MFD Kconfig conditional,
   to avoid I3C/I2C dependency issues

Changes in v8:
 - No change

Changes in v7:
 - Use new config I3C_OR_I2C

Changes in v6:
 - No change

Changes in v5:
 - Corrected the ordering in the Makefile and Kconfig for MFD_P3H2X4X
 - Updated dev_err_probe() for regmap_init failure.
 - Updated module description

Changes in v4:
 - Split the driver into three separate patches(mfd, regulator and I3C hub)
 - Added support for NXP P3H2x4x MFD functionality
---
---
 MAINTAINERS                 |   2 +
 drivers/mfd/Kconfig         |  13 ++++
 drivers/mfd/Makefile        |   1 +
 drivers/mfd/p3h2840.c       | 124 ++++++++++++++++++++++++++++++++++++
 include/linux/mfd/p3h2840.h |  27 ++++++++
 5 files changed, 167 insertions(+)
 create mode 100644 drivers/mfd/p3h2840.c
 create mode 100644 include/linux/mfd/p3h2840.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 4425816b478b..a2c2f7d944b0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19274,6 +19274,8 @@ L:	linux-kernel@vger.kernel.org
 L:	linux-i3c-owner@lists.infradead.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
+F:	drivers/mfd/p3h2840.c
+F:	include/linux/mfd/p3h2840.h
 
 NXP PF5300/PF5301/PF5302 PMIC REGULATOR DEVICE DRIVER
 M:	Woodrow Douglass <wdouglass@carnegierobotics.com>
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 7192c9d1d268..405b50c3c77b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -617,6 +617,19 @@ config MFD_MX25_TSADC
 	  i.MX25 processors. They consist of a conversion queue for general
 	  purpose ADC and a queue for Touchscreens.
 
+config MFD_P3H2X4X
+	tristate "NXP P3H2X4X I3C Hub Device"
+	depends on I3C_OR_I2C
+	select MFD_CORE
+	select REGMAP_I3C if I3C
+	select REGMAP_I2C if I2C
+	help
+	  Enable Support for NXP P3H244x/P3H284x I3C HUB device using I3C/I2C
+	  communication interface.
+
+	  This driver provides support for I3C hub and regulator, each subdriver
+	  can be enabled independently depending on the required functionality.
+
 config MFD_PF1550
 	tristate "NXP PF1550 PMIC Support"
 	depends on I2C=y && OF
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index e75e8045c28a..a284b22c7b13 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -122,6 +122,7 @@ obj-$(CONFIG_MFD_MC13XXX)	+= mc13xxx-core.o
 obj-$(CONFIG_MFD_MC13XXX_SPI)	+= mc13xxx-spi.o
 obj-$(CONFIG_MFD_MC13XXX_I2C)	+= mc13xxx-i2c.o
 
+obj-$(CONFIG_MFD_P3H2X4X)	+= p3h2840.o
 obj-$(CONFIG_MFD_PF1550)	+= pf1550.o
 
 obj-$(CONFIG_MFD_NCT6694)	+= nct6694.o
diff --git a/drivers/mfd/p3h2840.c b/drivers/mfd/p3h2840.c
new file mode 100644
index 000000000000..14c0b0f142ef
--- /dev/null
+++ b/drivers/mfd/p3h2840.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025-2026 NXP
+ * P3H2X4X i3c hub and regulator device.
+ */
+
+#include <linux/i2c.h>
+#include <linux/i3c/master.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/p3h2840.h>
+#include <linux/regmap.h>
+
+static const struct mfd_cell p3h2x4x_devs[] = {
+	{
+		.name = "p3h2x4x-regulator",
+	},
+	{
+		.name = "p3h2x4x-i3c-hub",
+	},
+};
+
+static const struct regmap_config p3h2x4x_regmap_config = {
+	.reg_bits = P3H2X4X_REG_BITS,
+	.val_bits = P3H2X4X_VAL_BITS,
+	.max_register = 0xFF,
+};
+
+static int p3h2x4x_device_probe_i3c(struct i3c_device *i3cdev)
+{
+	struct p3h2x4x_dev *p3h2x4x;
+	int ret;
+
+	p3h2x4x = devm_kzalloc(&i3cdev->dev, sizeof(*p3h2x4x), GFP_KERNEL);
+	if (!p3h2x4x)
+		return -ENOMEM;
+
+	i3cdev_set_drvdata(i3cdev, p3h2x4x);
+
+	p3h2x4x->regmap = devm_regmap_init_i3c(i3cdev, &p3h2x4x_regmap_config);
+	if (IS_ERR(p3h2x4x->regmap))
+		return dev_err_probe(&i3cdev->dev, PTR_ERR(p3h2x4x->regmap),
+				     "Failed to register HUB regmap\n");
+
+	p3h2x4x->is_p3h2x4x_in_i3c = true;
+	p3h2x4x->i3cdev = i3cdev;
+
+	ret = devm_mfd_add_devices(&i3cdev->dev, PLATFORM_DEVID_AUTO,
+				   p3h2x4x_devs, ARRAY_SIZE(p3h2x4x_devs),
+				   NULL, 0, NULL);
+	if (ret)
+		return dev_err_probe(&i3cdev->dev, ret, "Failed to add sub devices\n");
+
+	return 0;
+}
+
+static int p3h2x4x_device_probe_i2c(struct i2c_client *client)
+{
+	struct p3h2x4x_dev *p3h2x4x;
+	int ret;
+
+	p3h2x4x = devm_kzalloc(&client->dev, sizeof(*p3h2x4x), GFP_KERNEL);
+	if (!p3h2x4x)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, p3h2x4x);
+
+	p3h2x4x->regmap = devm_regmap_init_i2c(client, &p3h2x4x_regmap_config);
+	if (IS_ERR(p3h2x4x->regmap))
+		return dev_err_probe(&client->dev, PTR_ERR(p3h2x4x->regmap),
+				     "Failed to register HUB regmap\n");
+
+	p3h2x4x->is_p3h2x4x_in_i3c = false;
+
+	ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,
+				   p3h2x4x_devs, ARRAY_SIZE(p3h2x4x_devs),
+				   NULL, 0, NULL);
+	if (ret)
+		return dev_err_probe(&client->dev, ret, "Failed to add sub devices\n");
+
+	return 0;
+}
+
+static const struct i3c_device_id p3h2x4x_i3c_ids[] = {
+	I3C_CLASS(I3C_DCR_HUB, NULL),
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(i3c, p3h2x4x_i3c_ids);
+
+static const struct i2c_device_id p3h2x4x_i2c_id_table[] = {
+	{ "nxp-i3c-hub" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, p3h2x4x_i2c_id_table);
+
+static const struct of_device_id p3h2x4x_i2c_of_match[] = {
+	{ .compatible = "nxp,p3h2840", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, p3h2x4x_i2c_of_match);
+
+static struct i3c_driver p3h2x4x_i3c = {
+	.driver = {
+		.name = "p3h2x4x_i3c_drv",
+	},
+	.probe = p3h2x4x_device_probe_i3c,
+	.id_table = p3h2x4x_i3c_ids,
+};
+
+static struct i2c_driver p3h2x4x_i2c = {
+	.driver = {
+		.name = "p3h2x4x_i2c_drv",
+		.of_match_table = p3h2x4x_i2c_of_match,
+	},
+	.probe =  p3h2x4x_device_probe_i2c,
+	.id_table = p3h2x4x_i2c_id_table,
+};
+
+module_i3c_i2c_driver(p3h2x4x_i3c, &p3h2x4x_i2c);
+
+MODULE_AUTHOR("Aman Kumar Pandey <aman.kumarpandey@nxp.com>");
+MODULE_AUTHOR("Vikash Bansal <vikash.bansal@nxp.com>");
+MODULE_AUTHOR("Lakshay Piplani <lakshay.piplani@nxp.com>");
+MODULE_DESCRIPTION("NXP P3H2X4X I3C HUB multi function driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/p3h2840.h b/include/linux/mfd/p3h2840.h
new file mode 100644
index 000000000000..7ffaf1778f71
--- /dev/null
+++ b/include/linux/mfd/p3h2840.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2025-2026 NXP
+ * This header file contain private Reg address and its bit mapping etc.
+ */
+
+#ifndef _LINUX_MFD_P3H2840_H
+#define _LINUX_MFD_P3H2840_H
+
+#include <linux/types.h>
+
+/* Device Configuration Registers */
+#define P3H2X4X_DEV_REG_PROTECTION_CODE				0x10
+#define P3H2X4X_REGISTERS_LOCK_CODE				0x00
+#define P3H2X4X_REGISTERS_UNLOCK_CODE				0x69
+#define P3H2X4X_CP1_REGISTERS_UNLOCK_CODE			0x6a
+
+/* Reg config for Regmap */
+#define P3H2X4X_REG_BITS					8
+#define P3H2X4X_VAL_BITS					8
+
+struct p3h2x4x_dev {
+	struct i3c_device *i3cdev;
+	struct regmap *regmap;
+	bool is_p3h2x4x_in_i3c;
+};
+#endif /* _LINUX_MFD_P3H2840_H */
-- 
2.25.1


^ permalink raw reply related

* [PATCH v9 0/7] Add support for NXP P3H2x4x I3C hub driver
From: Lakshay Piplani @ 2026-04-20 10:52 UTC (permalink / raw)
  To: linux-kernel, linux-i3c, alexandre.belloni, krzk+dt, robh,
	conor+dt, devicetree, broonie, lee, Frank.Li, lgirdwood
  Cc: vikash.bansal, priyanka.jain, aman.kumarpandey, Lakshay Piplani

This series adds a driver for the NXP P3H2x4x family of multiport I3C hub
devices.
 
This is an MFD driver integrating I3C hub and on-die regulators.
 
The series introduces:
- Core I3C master enhancements required for hub support
- Generic I3C hub framework
- MFD and regulator drivers for P3H2x4x
- P3H2x4x I3C hub driver built on top of the generic layer

Changes in v9:
- Renamed macros to follow consistent uppercase naming conventions
- Made REGMAP selects in the P3H2X4X MFD Kconfig conditional, to avoid I3C/I2C dependency issues
- Referenced i3c.yaml and i2c-controller.yaml for child bus nodes
- Dropped unnecessary #address-cells and #size-cells from child nodes
- Added CONFIG_I2C_SLAVE guards where necessary to avoid build errors when I2C slave support is disabled
- Link to v8: https://lore.kernel.org/linux-i3c/20260323062737.886728-1-lakshay.piplani@nxp.com/T/#u

Changes in v8:
- Add compatible in i3c example
- Link to v7: https://lore.kernel.org/linux-i3c/20260319112441.3888957-1-lakshay.piplani@nxp.com/T/#u

Changes in v7:
- Fix kernel-doc warnings across I3C core and hub code
- Rework DT binding schema and examples to pass dt_binding_check
- Update MFD Kconfig to use I3C_OR_I2C
- Convert CONFIG_I3C_HUB to tristate
- Remove unnecessary CONFIG_I2C_SLAVE guards
- Replace custom helpers with find_closest()
- Use devm_regulator_get_enable_optional()
- Link to v6: https://lore.kernel.org/linux-i3c/64c5070c-aa9e-427a-933e-91e168f0510c@kernel.org/T/#u

Changes in v6:
- Update DT binding with vendor-prefixed properties
- Add generic I3C hub support
- Remove generic code from P3H2x4x driver
- Link to v5: https://lore.kernel.org/linux-i3c/20260206120121.856471-1-aman.kumarpandey@nxp.com/T/#u

Changes in v5:
- Update supply naming and descriptions
- Improve MFD Kconfig/Makefile ordering
- Link to v4: https://lore.kernel.org/linux-i3c/20260113114529.1692213-2-aman.kumarpandey@nxp.com/T/#u

Changes in v4:
- Split driver into MFD, regulator and I3C hub parts
- Update I3C master for hub support
- Fix DT binding issues
- Link to v3: https://lore.kernel.org/linux-i3c/20250811-bittern-of-abstract-prestige-aaeda9@kuoka/T/#u

Changes in v3:
- Add MFD support for hub and regulators
- Add regulator integration
- Link to v2: https://lore.kernel.org/linux-i3c/17145d2f-5d07-4939-8381-74e27cde303c@kernel.org/T/#u

Changes in v2:
- Fix DT binding warnings
- Refine DT parsing logic
- Link to v1: https://lore.kernel.org/linux-i3c/822d6dca-b2c6-4439-ade5-219620ebc435@kernel.org/T/#u

Aman Kumar Pandey (6):
  i3c: master: Expose the APIs to support I3C hub
  i3c: master: Add the APIs to support I3C hub
  dt-bindings: i3c: Add NXP P3H2x4x i3c-hub support
  mfd: p3h2x4x: Add driver for NXP P3H2x4x i3c hub and on-die regulator
  regulator: p3h2x4x: Add driver for on-die regulators in NXP P3H2x4x
    i3c hub
  i3c: hub: p3h2x4x: Add support for NXP P3H2x4x I3C hub functionality

Lakshay Piplani (1):
  i3c: hub: Add support for the I3C interface in the I3C hub

 .../devicetree/bindings/i3c/nxp,p3h2840.yaml  | 291 +++++++++++
 MAINTAINERS                                   |  15 +
 drivers/i3c/Kconfig                           |  16 +
 drivers/i3c/Makefile                          |   2 +
 drivers/i3c/hub.c                             | 460 ++++++++++++++++++
 drivers/i3c/hub/Kconfig                       |  11 +
 drivers/i3c/hub/Makefile                      |   4 +
 drivers/i3c/hub/p3h2840_i3c_hub.h             | 334 +++++++++++++
 drivers/i3c/hub/p3h2840_i3c_hub_common.c      | 352 ++++++++++++++
 drivers/i3c/hub/p3h2840_i3c_hub_i3c.c         | 132 +++++
 drivers/i3c/hub/p3h2840_i3c_hub_smbus.c       | 426 ++++++++++++++++
 drivers/i3c/master.c                          | 173 ++++++-
 drivers/mfd/Kconfig                           |  13 +
 drivers/mfd/Makefile                          |   1 +
 drivers/mfd/p3h2840.c                         | 124 +++++
 drivers/regulator/Kconfig                     |  10 +
 drivers/regulator/Makefile                    |   1 +
 drivers/regulator/p3h2840_i3c_hub_regulator.c | 218 +++++++++
 include/linux/i3c/device.h                    |   1 +
 include/linux/i3c/hub.h                       | 107 ++++
 include/linux/i3c/master.h                    |  10 +
 include/linux/mfd/p3h2840.h                   |  27 +
 22 files changed, 2726 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
 create mode 100644 drivers/i3c/hub.c
 create mode 100644 drivers/i3c/hub/Kconfig
 create mode 100644 drivers/i3c/hub/Makefile
 create mode 100644 drivers/i3c/hub/p3h2840_i3c_hub.h
 create mode 100644 drivers/i3c/hub/p3h2840_i3c_hub_common.c
 create mode 100644 drivers/i3c/hub/p3h2840_i3c_hub_i3c.c
 create mode 100644 drivers/i3c/hub/p3h2840_i3c_hub_smbus.c
 create mode 100644 drivers/mfd/p3h2840.c
 create mode 100644 drivers/regulator/p3h2840_i3c_hub_regulator.c
 create mode 100644 include/linux/i3c/hub.h
 create mode 100644 include/linux/mfd/p3h2840.h

-- 
2.25.1


^ permalink raw reply

* [PATCH v9 5/7] regulator: p3h2x4x: Add driver for on-die regulators in NXP P3H2x4x i3c hub
From: Lakshay Piplani @ 2026-04-20 10:52 UTC (permalink / raw)
  To: linux-kernel, linux-i3c, alexandre.belloni, krzk+dt, robh,
	conor+dt, devicetree, broonie, lee, Frank.Li, lgirdwood
  Cc: vikash.bansal, priyanka.jain, aman.kumarpandey, Lakshay Piplani,
	Frank Li
In-Reply-To: <20260420105222.1562243-1-lakshay.piplani@nxp.com>

From: Aman Kumar Pandey <aman.kumarpandey@nxp.com>

The NXP P3H2x4x family integrates on-die regulators alongside I3C hub
functionality. This driver registers the regulators using the MFD
framework and exposes them via the regulator subsystem.

Signed-off-by: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
Signed-off-by: Vikash Bansal <vikash.bansal@nxp.com>
Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>
Reviewed-by: Frank Li <frank.li@nxp.com>

---
Changes in v9:
 - No change

Changes in v8:
 - No change

Changes in v7:
 - No change, added Reviewed-By tag

Changes in v6:
 - Use DEFINE_LOCK_GUARD_1 for reg lock/unlock

Changes in v5:
 - Updated dev_err_probe() for regmap_init failure.
 - Updated module description

Changes in v4:
 - Split the driver into three separate patches (mfd, regulator and I3C hub)
 - Introduced driver for on-die regulators in NXP P3H2x4x I3C hub
---
---
 MAINTAINERS                                   |   1 +
 drivers/regulator/Kconfig                     |  10 +
 drivers/regulator/Makefile                    |   1 +
 drivers/regulator/p3h2840_i3c_hub_regulator.c | 218 ++++++++++++++++++
 4 files changed, 230 insertions(+)
 create mode 100644 drivers/regulator/p3h2840_i3c_hub_regulator.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a2c2f7d944b0..b2119fadef7b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19275,6 +19275,7 @@ L:	linux-i3c-owner@lists.infradead.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
 F:	drivers/mfd/p3h2840.c
+F:	drivers/regulator/p3h2840_i3c_hub_regulator.c
 F:	include/linux/mfd/p3h2840.h
 
 NXP PF5300/PF5301/PF5302 PMIC REGULATOR DEVICE DRIVER
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 10e64e3ffb1f..1c90b3679dbe 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1019,6 +1019,16 @@ config REGULATOR_MTK_DVFSRC
 	  of Mediatek. It allows for voting on regulator state
 	  between multiple users.
 
+config REGULATOR_P3H2X4X
+       tristate "NXP P3H2X4X regulator support"
+       depends on MFD_P3H2X4X
+       help
+         This driver provides support for the voltage regulators of the
+         P3H244x/P3H284x multi-function I3C Hub device.
+
+         Say M here if you want to include support for this regulator as
+         a module. The module will be named "p3h2840_i3c_hub_regulator".
+
 config REGULATOR_PALMAS
 	tristate "TI Palmas PMIC Regulators"
 	depends on MFD_PALMAS
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 35639f3115fd..46f586ccde63 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -128,6 +128,7 @@ obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o
 obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
 obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
 obj-$(CONFIG_REGULATOR_QCOM_USB_VBUS) += qcom_usb_vbus-regulator.o
+obj-$(CONFIG_REGULATOR_P3H2X4X) += p3h2840_i3c_hub_regulator.o
 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
 obj-$(CONFIG_REGULATOR_PCA9450) += pca9450-regulator.o
 obj-$(CONFIG_REGULATOR_PF0900) += pf0900-regulator.o
diff --git a/drivers/regulator/p3h2840_i3c_hub_regulator.c b/drivers/regulator/p3h2840_i3c_hub_regulator.c
new file mode 100644
index 000000000000..4f2514d4d928
--- /dev/null
+++ b/drivers/regulator/p3h2840_i3c_hub_regulator.c
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025-2026 NXP
+ * This P3H2X4X driver file contain functions for enable/disable regulator and voltage set/get.
+ */
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/mfd/p3h2840.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define P3H2X4X_LDO_AND_PULLUP_CONF				0x19
+#define P3H2X4X_LDO_ENABLE_DISABLE_MASK				GENMASK(3, 0)
+#define P3H2X4X_CP0_EN_LDO				        BIT(0)
+#define P3H2X4X_CP1_EN_LDO				        BIT(1)
+#define P3H2X4X_TP0145_EN_LDO					BIT(2)
+#define P3H2X4X_TP2367_EN_LDO					BIT(3)
+
+#define P3H2X4X_NET_OPER_MODE_CONF				0x15
+#define P3H2X4X_VCCIO_LDO_CONF					0x16
+#define P3H2X4X_CP0_VCCIO_LDO_VOLTAGE_MASK			GENMASK(1, 0)
+#define P3H2X4X_CP0_VCCIO_LDO_VOLTAGE(x)	\
+		FIELD_PREP(P3H2X4X_CP0_VCCIO_LDO_VOLTAGE_MASK, x)
+#define P3H2X4X_CP1_VCCIO_LDO_VOLTAGE_MASK			GENMASK(3, 2)
+#define P3H2X4X_CP1_VCCIO_LDO_VOLTAGE(x)	\
+		FIELD_PREP(P3H2X4X_CP1_VCCIO_LDO_VOLTAGE_MASK, x)
+#define P3H2X4X_TP0145_VCCIO_LDO_VOLTAGE_MASK			GENMASK(5, 4)
+#define P3H2X4X_TP0145_VCCIO_LDO_VOLTAGE(x)	\
+		FIELD_PREP(P3H2X4X_TP0145_VCCIO_LDO_VOLTAGE_MASK, x)
+#define P3H2X4X_TP2367_VCCIO_LDO_VOLTAGE_MASK			GENMASK(7, 6)
+#define P3H2X4X_TP2367_VCCIO_LDO_VOLTAGE(x)	\
+		FIELD_PREP(P3H2X4X_TP2367_VCCIO_LDO_VOLTAGE_MASK, x)
+#define P3H2X4X_LDO_COUNT					4
+
+struct p3h2x4x_regulator_dev {
+	struct regulator_dev *rp3h2x4x_dev[P3H2X4X_LDO_COUNT];
+	struct regmap *regmap;
+};
+
+struct p3h2x4x_reg_state {
+	unsigned int orig;
+	bool restore;
+};
+
+static void p3h2x4x_reg_guard_enter(struct regulator_dev *rdev,
+				    struct p3h2x4x_reg_state *state)
+{
+	state->restore = false;
+
+	if (regmap_read(rdev->regmap,
+			P3H2X4X_DEV_REG_PROTECTION_CODE,
+			&state->orig))
+		return;
+
+	if (state->orig != P3H2X4X_REGISTERS_UNLOCK_CODE) {
+		regmap_write(rdev->regmap,
+			     P3H2X4X_DEV_REG_PROTECTION_CODE,
+			     P3H2X4X_REGISTERS_UNLOCK_CODE);
+		state->restore = true;
+	}
+}
+
+static void p3h2x4x_reg_guard_exit(struct regulator_dev *rdev,
+				   struct p3h2x4x_reg_state *state)
+{
+	if (state->restore)
+		regmap_write(rdev->regmap,
+			     P3H2X4X_DEV_REG_PROTECTION_CODE,
+			     state->orig);
+}
+
+DEFINE_LOCK_GUARD_1(p3h2x4x_reg, struct regulator_dev,
+		    p3h2x4x_reg_guard_enter(_T->lock, &_T->state),
+		    p3h2x4x_reg_guard_exit(_T->lock, &_T->state),
+		    struct p3h2x4x_reg_state state);
+
+static int p3h2x4x_regulator_enable(struct regulator_dev *rdev)
+{
+	guard(p3h2x4x_reg)(rdev);
+	return regulator_enable_regmap(rdev);
+}
+
+static int p3h2x4x_regulator_disable(struct regulator_dev *rdev)
+{
+	guard(p3h2x4x_reg)(rdev);
+	return regulator_disable_regmap(rdev);
+}
+
+static int p3h2x4x_regulator_set_voltage_sel(struct regulator_dev *rdev,
+					     unsigned int sel)
+{
+	guard(p3h2x4x_reg)(rdev);
+	return regulator_set_voltage_sel_regmap(rdev, sel);
+}
+
+static const struct regulator_ops p3h2x4x_ldo_ops = {
+	.list_voltage = regulator_list_voltage_table,
+	.map_voltage = regulator_map_voltage_iterate,
+	.set_voltage_sel = p3h2x4x_regulator_set_voltage_sel,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.enable = p3h2x4x_regulator_enable,
+	.disable = p3h2x4x_regulator_disable,
+	.is_enabled = regulator_is_enabled_regmap,
+};
+
+static const unsigned int p3h2x4x_voltage_table[] = {
+	1000000,
+	1100000,
+	1200000,
+	1800000,
+};
+
+static struct regulator_desc p3h2x4x_regulators[] = {
+	{
+		.name = "ldo-cp0",
+		.of_match = of_match_ptr("ldo-cp0"),
+		.regulators_node = of_match_ptr("regulators"),
+		.volt_table = p3h2x4x_voltage_table,
+		.n_voltages = ARRAY_SIZE(p3h2x4x_voltage_table),
+		.ops = &p3h2x4x_ldo_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+		.enable_reg = P3H2X4X_LDO_AND_PULLUP_CONF,
+		.enable_mask = P3H2X4X_CP0_EN_LDO,
+		.vsel_reg = P3H2X4X_VCCIO_LDO_CONF,
+		.vsel_mask = P3H2X4X_CP0_VCCIO_LDO_VOLTAGE_MASK,
+	},
+	{
+		.name = "ldo-cp1",
+		.of_match = of_match_ptr("ldo-cp1"),
+		.regulators_node = of_match_ptr("regulators"),
+		.volt_table = p3h2x4x_voltage_table,
+		.n_voltages = ARRAY_SIZE(p3h2x4x_voltage_table),
+		.ops = &p3h2x4x_ldo_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+		.enable_reg = P3H2X4X_LDO_AND_PULLUP_CONF,
+		.enable_mask = P3H2X4X_CP1_EN_LDO,
+		.vsel_reg = P3H2X4X_VCCIO_LDO_CONF,
+		.vsel_mask = P3H2X4X_CP1_VCCIO_LDO_VOLTAGE_MASK,
+	},
+	{
+		.name = "ldo-tpg0",
+		.of_match = of_match_ptr("ldo-tpg0"),
+		.regulators_node = of_match_ptr("regulators"),
+		.volt_table = p3h2x4x_voltage_table,
+		.n_voltages = ARRAY_SIZE(p3h2x4x_voltage_table),
+		.ops = &p3h2x4x_ldo_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+		.enable_reg = P3H2X4X_LDO_AND_PULLUP_CONF,
+		.enable_mask = P3H2X4X_TP0145_EN_LDO,
+		.vsel_reg = P3H2X4X_VCCIO_LDO_CONF,
+		.vsel_mask = P3H2X4X_TP0145_VCCIO_LDO_VOLTAGE_MASK,
+	},
+	{
+		.name = "ldo-tpg1",
+		.of_match = of_match_ptr("ldo-tpg1"),
+		.regulators_node = of_match_ptr("regulators"),
+		.volt_table = p3h2x4x_voltage_table,
+		.n_voltages = ARRAY_SIZE(p3h2x4x_voltage_table),
+		.ops = &p3h2x4x_ldo_ops,
+		.type = REGULATOR_VOLTAGE,
+		.owner = THIS_MODULE,
+		.enable_reg = P3H2X4X_LDO_AND_PULLUP_CONF,
+		.enable_mask = P3H2X4X_TP2367_EN_LDO,
+		.vsel_reg = P3H2X4X_VCCIO_LDO_CONF,
+		.vsel_mask = P3H2X4X_TP2367_VCCIO_LDO_VOLTAGE_MASK,
+	},
+};
+
+static int p3h2x4x_regulator_probe(struct platform_device *pdev)
+{
+	struct p3h2x4x_dev *p3h2x4x = dev_get_drvdata(pdev->dev.parent);
+	struct p3h2x4x_regulator_dev *p3h2x4x_regulator;
+	struct regulator_config rcfg = { };
+	struct device *dev = &pdev->dev;
+	struct regulator_dev *rdev;
+	int i;
+
+	p3h2x4x_regulator = devm_kzalloc(dev, sizeof(*p3h2x4x_regulator), GFP_KERNEL);
+	if (!p3h2x4x_regulator)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, p3h2x4x_regulator);
+
+	p3h2x4x_regulator->regmap = p3h2x4x->regmap;
+
+	rcfg.dev = dev->parent;
+	rcfg.regmap = p3h2x4x_regulator->regmap;
+	rcfg.driver_data = p3h2x4x_regulator;
+
+	for (i = 0; i < ARRAY_SIZE(p3h2x4x_regulators); i++) {
+		rdev = devm_regulator_register(&pdev->dev, &p3h2x4x_regulators[i], &rcfg);
+		if (IS_ERR(rdev))
+			return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register %s\n",
+					     p3h2x4x_regulators[i].name);
+		p3h2x4x_regulator->rp3h2x4x_dev[i] = rdev;
+	}
+	return 0;
+}
+
+static struct platform_driver p3h2x4x_regulator_driver = {
+	.driver = {
+		.name = "p3h2x4x-regulator",
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+	.probe = p3h2x4x_regulator_probe,
+};
+module_platform_driver(p3h2x4x_regulator_driver);
+
+MODULE_AUTHOR("Aman Kumar Pandey <aman.kumarpandey@nxp.com>");
+MODULE_AUTHOR("Vikash Bansal <vikash.bansal@nxp.com>");
+MODULE_AUTHOR("Lakshay Piplani <lakshay.piplani@nxp.com>");
+MODULE_DESCRIPTION("NXP P3H2X4X I3C HUB Regulator driver");
+MODULE_LICENSE("GPL");
-- 
2.25.1


^ permalink raw reply related

* [PATCH v9 3/7] dt-bindings: i3c: Add NXP P3H2x4x i3c-hub support
From: Lakshay Piplani @ 2026-04-20 10:52 UTC (permalink / raw)
  To: linux-kernel, linux-i3c, alexandre.belloni, krzk+dt, robh,
	conor+dt, devicetree, broonie, lee, Frank.Li, lgirdwood
  Cc: vikash.bansal, priyanka.jain, aman.kumarpandey, Lakshay Piplani
In-Reply-To: <20260420105222.1562243-1-lakshay.piplani@nxp.com>

From: Aman Kumar Pandey <aman.kumarpandey@nxp.com>

Add bindings for the NXP P3H2x4x (P3H2440/P3H2441/P3H2840/P3H2841)
multiport I3C hub family. These devices connect to a host via
I3C/I2C/SMBus and allow communication with multiple downstream
peripherals.

Signed-off-by: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
Signed-off-by: Vikash Bansal <vikash.bansal@nxp.com>
Signed-off-by: Lakshay Piplani <lakshay.piplani@nxp.com>

---
Changes in v9:
 - Referenced i3c.yaml and i2c-controller.yaml for child nodes
 - Dropped unnecessary #address-cells and #size-cells from child nodes

Changes in v8:
 - Add compatible in i3c example

Changes in v7:
 - Fix schema validation issues
 - Adjust required properties
 - Add I2C example

Changes in v6:
 - Use a vendor prefix for the attributes

Changes in v5:
 - Removed SW properties: cp0-ldo-microvolt,cp1-ldo-microvolt,
   tp0145-ldo-microvolt, tp2367-ldo-microvolt
 - Changed supply entries and its descriptions

Changes in v4:
 - Fixed DT binding check warning
 - Removed SW properties: ibi-enable, local-dev, and always-enable

Changes in v3:
 - Added MFD (Multi-Function Device) support for I3C hub and on-die regulator
 - Added Regulator supply node

Changes in v2:
 - Fixed DT binding check warning
 - Revised logic for parsing DTS nodes
---
---
 .../devicetree/bindings/i3c/nxp,p3h2840.yaml  | 291 ++++++++++++++++++
 MAINTAINERS                                   |   9 +
 2 files changed, 300 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml

diff --git a/Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml b/Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
new file mode 100644
index 000000000000..c080eeb0eeaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
@@ -0,0 +1,291 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2025 NXP
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i3c/nxp,p3h2840.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP P3H2X4X I3C HUB
+
+maintainers:
+  - Aman Kumar Pandey <aman.kumarpandey@nxp.com>
+  - Vikash Bansal <vikash.bansal@nxp.com>
+  - Lakshay Piplani <lakshay.piplani@nxp.com>
+
+description: |
+  P3H2x4x (P3H2440/P3H2441/P3H2840/P3H2841) is a family of multiport I3C
+  hub devices that connect to:-
+  1. A host CPU via I3C/I2C/SMBus bus on upstream side and connect to multiple
+     peripheral devices on the downstream  side.
+  2. Have two Controller Ports which can support either
+     I2C/SMBus or I3C buses and connect to a CPU, BMC or SOC.
+  3. P3H2840/ P3H2841 are 8 port I3C hub with eight I3C/I2C Target Port.
+  4. P3H2440/ P3H2441 are 4 port I3C hub with four I3C/I2C Target Port.
+     Target ports can be configured as I2C/SMBus, I3C or GPIO and connect to
+     peripherals.
+
+properties:
+  compatible:
+    const: nxp,p3h2840
+
+  reg:
+    maxItems: 1
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  assigned-address:
+    maximum: 0x7f
+
+  nxp,tp0145-pullup-ohms:
+    description:
+      Selects the pull up resistance for target Port 0/1/4/5, in ohms.
+    enum: [250, 500, 1000, 2000]
+    default: 500
+
+  nxp,tp2367-pullup-ohms:
+    description:
+      Selects the pull up resistance for target Port 2/3/6/7, in ohms.
+    enum: [250, 500, 1000, 2000]
+    default: 500
+
+  nxp,cp0-io-strength-ohms:
+    description:
+      Selects the IO drive strength for controller Port 0, in ohms.
+    enum: [20, 30, 40, 50]
+    default: 20
+
+  nxp,cp1-io-strength-ohms:
+    description:
+      Selects the IO drive strength for controller Port 1, in ohms.
+    enum: [20, 30, 40, 50]
+    default: 20
+
+  nxp,tp0145-io-strength-ohms:
+    description:
+      Selects the IO drive strength for target port 0/1/4/5, in ohms.
+    enum: [20, 30, 40, 50]
+    default: 20
+
+  nxp,tp2367-io-strength-ohms:
+    description:
+      Selects the IO drive strength for target port 2/3/6/7, in ohms.
+    enum: [20, 30, 40, 50]
+    default: 20
+
+  vcc1-supply:
+    description: Controller port 0 power supply.
+
+  vcc2-supply:
+    description: Controller port 1 power supply.
+
+  vcc3-supply:
+    description: Target port 0/1/4/5 power supply.
+
+  vcc4-supply:
+    description: Target port 2/3/6/7 power supply.
+
+  regulators:
+    type: object
+    additionalProperties: false
+
+    properties:
+      ldo-cp0:
+        type: object
+        $ref: /schemas/regulator/regulator.yaml#
+        unevaluatedProperties: false
+
+      ldo-cp1:
+        type: object
+        $ref: /schemas/regulator/regulator.yaml#
+        unevaluatedProperties: false
+
+      ldo-tpg0:
+        type: object
+        $ref: /schemas/regulator/regulator.yaml#
+        unevaluatedProperties: false
+
+      ldo-tpg1:
+        type: object
+        $ref: /schemas/regulator/regulator.yaml#
+        unevaluatedProperties: false
+
+required:
+  - reg
+
+patternProperties:
+  "^i3c@[0-7]$":
+    type: object
+    $ref: /schemas/i3c/i3c.yaml#
+    unevaluatedProperties: false
+
+    properties:
+      reg:
+        description:
+          The I3C HUB Target Port number.
+        maximum: 7
+
+      nxp,pullup-enable:
+        type: boolean
+        description:
+          Enables the on-die pull-up for Target Port.
+
+    required:
+      - reg
+
+  "^(i2c|smbus)@[0-7]$":
+    type: object
+    $ref: /schemas/i2c/i2c-controller.yaml#
+    unevaluatedProperties: false
+
+    properties:
+      reg:
+        description:
+          The I3C HUB Target Port number.
+        maximum: 7
+
+      nxp,pullup-enable:
+        type: boolean
+        description:
+          Enables the on-die pull-up for Target Port.
+
+    required:
+      - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    i3c {
+        #address-cells = <3>;
+        #size-cells = <0>;
+
+        hub@70,236153000c2 {
+            reg = <0x70 0x236 0x3000c2>;
+            compatible = "nxp,p3h2840";
+            #address-cells = <1>;
+            #size-cells = <0>;
+            assigned-address = <0x50>;
+
+            nxp,tp0145-pullup-ohms = <1000>;
+            nxp,tp2367-pullup-ohms = <1000>;
+            nxp,cp0-io-strength-ohms = <50>;
+            nxp,cp1-io-strength-ohms = <50>;
+            nxp,tp0145-io-strength-ohms = <50>;
+            nxp,tp2367-io-strength-ohms = <50>;
+            vcc3-supply = <&reg_tpg0>;
+            vcc4-supply = <&reg_tpg1>;
+
+            regulators {
+                reg_cp0: ldo-cp0 {
+                    regulator-name = "ldo-cp0";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                };
+
+                reg_cp1: ldo-cp1 {
+                    regulator-name = "ldo-cp1";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                };
+
+                reg_tpg0: ldo-tpg0 {
+                    regulator-name = "ldo-tpg0";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                };
+
+                reg_tpg1: ldo-tpg1 {
+                    regulator-name = "ldo-tpg1";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                };
+            };
+
+            smbus@0 {
+                reg = <0x0>;
+                #address-cells = <1>;
+                #size-cells = <0>;
+                nxp,pullup-enable;
+            };
+
+            i2c@1 {
+                reg = <0x1>;
+                #address-cells = <1>;
+                #size-cells = <0>;
+                nxp,pullup-enable;
+            };
+
+            i3c@2 {
+                reg = <0x2>;
+                #address-cells = <3>;
+                #size-cells = <0>;
+                nxp,pullup-enable;
+            };
+        };
+    };
+
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        hub@70 {
+            reg = <0x70>;
+            compatible = "nxp,p3h2840";
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            nxp,tp0145-pullup-ohms = <1000>;
+            nxp,tp2367-pullup-ohms = <1000>;
+            nxp,cp0-io-strength-ohms = <50>;
+            nxp,cp1-io-strength-ohms = <50>;
+            nxp,tp0145-io-strength-ohms = <50>;
+            nxp,tp2367-io-strength-ohms = <50>;
+            vcc3-supply = <&reg_tpg0_i2c>;
+            vcc4-supply = <&reg_tpg1_i2c>;
+
+            regulators {
+                reg_cp0_i2c: ldo-cp0 {
+                    regulator-name = "ldo-cp0";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                };
+
+                reg_cp1_i2c: ldo-cp1 {
+                    regulator-name = "ldo-cp1";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                };
+
+                reg_tpg0_i2c: ldo-tpg0 {
+                    regulator-name = "ldo-tpg0";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                };
+
+                reg_tpg1_i2c: ldo-tpg1 {
+                    regulator-name = "ldo-tpg1";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                };
+            };
+
+            smbus@0 {
+                reg = <0x0>;
+                #address-cells = <1>;
+                #size-cells = <0>;
+                nxp,pullup-enable;
+            };
+
+            i2c@1 {
+                reg = <0x1>;
+                #address-cells = <1>;
+                #size-cells = <0>;
+                nxp,pullup-enable;
+            };
+        };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 76d8291237be..4425816b478b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19266,6 +19266,15 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/ptp/nxp,ptp-netc.yaml
 F:	drivers/ptp/ptp_netc.c
 
+NXP P3H2X4X I3C-HUB DRIVER
+M:	Vikash Bansal <vikash.bansal@nxp.com>
+M:	Aman Kumar Pandey <aman.kumarpandey@nxp.com>
+M:	Lakshay Piplani <lakshay.piplani@nxp.com>
+L:	linux-kernel@vger.kernel.org
+L:	linux-i3c-owner@lists.infradead.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/i3c/nxp,p3h2840.yaml
+
 NXP PF5300/PF5301/PF5302 PMIC REGULATOR DEVICE DRIVER
 M:	Woodrow Douglass <wdouglass@carnegierobotics.com>
 S:	Maintained
-- 
2.25.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox