Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v4 6/8] arm64: dts: amlogic: t7: Add i2c pinctrl node
From: Neil Armstrong @ 2026-04-24 10:00 UTC (permalink / raw)
  To: linux-kernel-dev, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm
In-Reply-To: <20260421-add-mcu-fan-khadas-vim4-v4-6-447114a28f2d@aliel.fr>

On 4/21/26 13:49, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Add the T7 pinctrl used by the Khadas VIM4 for MCU communication.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 10 ++++++++++
>   1 file changed, 10 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> index 7fe72c94ed623..e96fe10b251a0 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> @@ -376,6 +376,16 @@ mux {
>   					};
>   				};
>   
> +				i2c0_ao_d_pins: i2c0-ao-d {
> +					mux {
> +						groups = "i2c0_ao_sck_d",
> +							 "i2c0_ao_sda_d";
> +						function = "i2c0_ao";
> +						bias-disable;
> +						drive-strength-microamp = <3000>;
> +					};
> +				};
> +
>   				pwm_a_pins: pwm-a {
>   					mux {
>   						groups = "pwm_a";
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH v4 5/8] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
From: Neil Armstrong @ 2026-04-24 10:00 UTC (permalink / raw)
  To: linux-kernel-dev, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm
In-Reply-To: <20260421-add-mcu-fan-khadas-vim4-v4-5-447114a28f2d@aliel.fr>

On 4/21/26 13:49, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Replace the hardcoded MAX_LEVEL constant and fan register
> with values read from platform_data (fan_reg, max_level),
> as new MCUs need different values.
> 
> Optionally acquire and enable a "fan" regulator supply
> at probe time and on resume,
> so boards that gate fan power through a regulator are handled.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   drivers/thermal/khadas_mcu_fan.c | 49 +++++++++++++++++++++++++++++++++++-----
>   1 file changed, 43 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
> index d35e5313bea41..24559bf65de46 100644
> --- a/drivers/thermal/khadas_mcu_fan.c
> +++ b/drivers/thermal/khadas_mcu_fan.c
> @@ -13,13 +13,15 @@
>   #include <linux/regmap.h>
>   #include <linux/sysfs.h>
>   #include <linux/thermal.h>
> -
> -#define MAX_LEVEL 3
> +#include <linux/regulator/consumer.h>
>   
>   struct khadas_mcu_fan_ctx {
>   	struct khadas_mcu *mcu;
> +	unsigned int fan_reg;
>   	unsigned int level;
> +	unsigned int max_level;
>   	struct thermal_cooling_device *cdev;
> +	struct regulator *power;
>   };
>   
>   static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
> @@ -27,8 +29,7 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
>   {
>   	int ret;
>   
> -	ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
> -			   level);
> +	ret = regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
>   	if (ret)
>   		return ret;
>   
> @@ -40,7 +41,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
>   static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
>   					unsigned long *state)
>   {
> -	*state = MAX_LEVEL;
> +	struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
> +
> +	*state = ctx->max_level;
>   
>   	return 0;
>   }
> @@ -61,7 +64,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
>   {
>   	struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
>   
> -	if (state > MAX_LEVEL)
> +	if (state > ctx->max_level)
>   		return -EINVAL;
>   
>   	if (state == ctx->level)
> @@ -83,11 +86,32 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)
>   	struct device *dev = &pdev->dev;
>   	struct khadas_mcu_fan_ctx *ctx;
>   	int ret;
> +	const struct khadas_mcu_fan_pdata *pdata = dev_get_platdata(&pdev->dev);

Move this on top to respect reverse christmas ordering.

>   
>   	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
>   	if (!ctx)
>   		return -ENOMEM;
> +
>   	ctx->mcu = mcu;
> +	ctx->fan_reg   = pdata->fan_reg;
> +	ctx->max_level = pdata->max_level;
> +
> +	ctx->power = devm_regulator_get_optional(dev->parent, "fan");
> +	if (IS_ERR(ctx->power)) {
> +		if (PTR_ERR(ctx->power) == -ENODEV)
> +			ctx->power = NULL;
> +		else
> +			return PTR_ERR(ctx->power);
> +	}
> +
> +	if (ctx->power) {
> +		ret = regulator_enable(ctx->power);
> +		if (ret) {
> +			dev_err(dev, "Failed to enable fan power supply: %d\n", ret);
> +			return ret; 
> +		}
> +	}

Or you can request with devm_regulator_get(dev->parent, "fan"); which will
return a dummy regulator, and then you can just call regulator_enable & disable
and remove all those checks.

> +
>   	platform_set_drvdata(pdev, ctx);
>   
>   	cdev = devm_thermal_of_cooling_device_register(dev->parent,
> @@ -124,12 +148,25 @@ static int khadas_mcu_fan_suspend(struct device *dev)
>   
>   	ctx->level = level_save;
>   
> +	if (ctx->power) {
> +		ret = regulator_disable(ctx->power);
> +		if (ret)
> +			return ret;
> +	}

if (ctx->power)
	return regulator_disable(ctx->power);

> +
>   	return 0;
>   }
>   
>   static int khadas_mcu_fan_resume(struct device *dev)
>   {
>   	struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
> +	int ret;
> +
> +	if (ctx->power) {
> +		ret = regulator_enable(ctx->power);
> +		if (ret)
> +			return ret;
> +	}
>   
>   	return khadas_mcu_fan_set_level(ctx, ctx->level);
>   }
> 

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH v4 4/8] mfd: khadas-mcu: Add support for VIM4 MCU variant
From: Neil Armstrong @ 2026-04-24  9:55 UTC (permalink / raw)
  To: linux-kernel-dev, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm
In-Reply-To: <20260421-add-mcu-fan-khadas-vim4-v4-4-447114a28f2d@aliel.fr>

On 4/21/26 13:49, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Refactor probe() to use per-variant khadas_mcu_data
> instead of hardcoded globals.
> 
> Add dedicated regmap configuration and device data for the VIM4 MCU,
> with its own volatile/writeable registers.
> 
> Add the fan control register
> (0–100 levels vs 0–3 for previous supported boards).
> 
> Add a new compatible string "khadas,vim4-mcu".
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   drivers/mfd/khadas-mcu.c | 106 ++++++++++++++++++++++++++++++++++++++++++-----
>   1 file changed, 95 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
> index ba981a7886921..b36b3b3ab73c0 100644
> --- a/drivers/mfd/khadas-mcu.c
> +++ b/drivers/mfd/khadas-mcu.c
> @@ -75,15 +75,91 @@ static const struct regmap_config khadas_mcu_regmap_config = {
>   	.cache_type	= REGCACHE_MAPLE,
>   };
>   
> +static const struct khadas_mcu_fan_pdata khadas_mcu_fan_pdata = {
> +	.fan_reg	= KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
> +	.max_level	= 3,
> +};
> +
>   static struct mfd_cell khadas_mcu_fan_cells[] = {
>   	/* VIM1/2 Rev13+ and VIM3 only */
> -	{ .name = "khadas-mcu-fan-ctrl", },
> +	{
> +		.name = "khadas-mcu-fan-ctrl",
> +		.platform_data = &khadas_mcu_fan_pdata,
> +		.pdata_size    = sizeof(khadas_mcu_fan_pdata),
> +	},
>   };
>   
>   static struct mfd_cell khadas_mcu_cells[] = {
>   	{ .name = "khadas-mcu-user-mem", },
>   };
>   
> +static const struct khadas_mcu_data khadas_mcu_data = {
> +	.regmap_config	= &khadas_mcu_regmap_config,
> +	.cells		= khadas_mcu_cells,
> +	.ncells		= ARRAY_SIZE(khadas_mcu_cells),
> +	.fan_cells	= khadas_mcu_fan_cells,
> +	.nfan_cells	= ARRAY_SIZE(khadas_mcu_fan_cells),
> +};
> +
> +static bool khadas_mcu_vim4_reg_volatile(struct device *dev, unsigned int reg)
> +{
> +	switch (reg) {
> +	case KHADAS_MCU_PWR_OFF_CMD_REG:
> +	case KHADAS_MCU_VIM4_REST_CONF_REG:
> +	case KHADAS_MCU_WOL_INIT_START_REG:
> +	case KHADAS_MCU_VIM4_LED_ON_RAM_REG:
> +	case KHADAS_MCU_VIM4_FAN_CTRL_REG:
> +	case KHADAS_MCU_VIM4_WDT_EN_REG:
> +	case KHADAS_MCU_VIM4_SYS_RST_REG:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool khadas_mcu_vim4_reg_writeable(struct device *dev, unsigned int reg)
> +{
> +	switch (reg) {
> +	case KHADAS_MCU_VERSION_0_REG:
> +	case KHADAS_MCU_VERSION_1_REG:
> +	case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG:
> +		return false;
> +	default:
> +		return true;
> +	}
> +}
> +
> +static const struct regmap_config khadas_mcu_vim4_regmap_config = {
> +	.reg_bits	= 8,
> +	.reg_stride	= 1,
> +	.val_bits	= 8,
> +	.max_register	= KHADAS_MCU_VIM4_SYS_RST_REG,
> +	.volatile_reg	= khadas_mcu_vim4_reg_volatile,
> +	.writeable_reg	= khadas_mcu_vim4_reg_writeable,
> +	.cache_type	= REGCACHE_MAPLE,
> +};
> +
> +static const struct khadas_mcu_fan_pdata khadas_vim4_fan_pdata = {
> +	.fan_reg	= KHADAS_MCU_VIM4_FAN_CTRL_REG,
> +	.max_level	= 0x64,
> +};
> +
> +static const struct mfd_cell khadas_mcu_vim4_cells[] = {
> +	{
> +		.name		= "khadas-mcu-fan-ctrl",
> +		.platform_data	= &khadas_vim4_fan_pdata,
> +		.pdata_size	= sizeof(khadas_vim4_fan_pdata),
> +	},
> +};
> +
> +static const struct khadas_mcu_data khadas_vim4_mcu_data = {
> +	.regmap_config	= &khadas_mcu_vim4_regmap_config,
> +	.cells		= NULL,
> +	.ncells		= 0,
> +	.fan_cells	= khadas_mcu_vim4_cells,
> +	.nfan_cells	= ARRAY_SIZE(khadas_mcu_vim4_cells),
> +};
> +
>   static int khadas_mcu_probe(struct i2c_client *client)
>   {
>   	struct device *dev = &client->dev;
> @@ -94,28 +170,35 @@ static int khadas_mcu_probe(struct i2c_client *client)
>   	if (!ddata)
>   		return -ENOMEM;
>   
> +	ddata->data = i2c_get_match_data(client);
> +	if (!ddata->data)
> +		return -EINVAL;
> +
>   	i2c_set_clientdata(client, ddata);
>   
>   	ddata->dev = dev;
>   
> -	ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config);
> +	ddata->regmap = devm_regmap_init_i2c(client,
> +					     ddata->data->regmap_config);
>   	if (IS_ERR(ddata->regmap)) {
>   		ret = PTR_ERR(ddata->regmap);
>   		dev_err(dev, "Failed to allocate register map: %d\n", ret);
>   		return ret;
>   	}
>   
> -	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
> -				   khadas_mcu_cells,
> -				   ARRAY_SIZE(khadas_mcu_cells),
> -				   NULL, 0, NULL);
> -	if (ret)
> -		return ret;
> +	if (ddata->data->cells && ddata->data->ncells) {
> +		ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
> +					   ddata->data->cells,
> +					   ddata->data->ncells,
> +					   NULL, 0, NULL);
> +		if (ret)
> +			return ret;
> +	}
>   
>   	if (of_property_present(dev->of_node, "#cooling-cells"))
>   		return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
> -					    khadas_mcu_fan_cells,
> -					    ARRAY_SIZE(khadas_mcu_fan_cells),
> +					    ddata->data->fan_cells,
> +					    ddata->data->nfan_cells,
>   					    NULL, 0, NULL);
>   
>   	return 0;
> @@ -123,7 +206,8 @@ static int khadas_mcu_probe(struct i2c_client *client)
>   
>   #ifdef CONFIG_OF
>   static const struct of_device_id khadas_mcu_of_match[] = {
> -	{ .compatible = "khadas,mcu", },
> +	{ .compatible = "khadas,mcu", .data = &khadas_mcu_data },
> +	{ .compatible = "khadas,vim4-mcu", .data = &khadas_vim4_mcu_data },
>   	{},
>   };
>   MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH v4 3/8] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
From: Neil Armstrong @ 2026-04-24  9:55 UTC (permalink / raw)
  To: linux-kernel-dev, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm
In-Reply-To: <20260421-add-mcu-fan-khadas-vim4-v4-3-447114a28f2d@aliel.fr>

On 4/21/26 13:49, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Introduce a per-variant configuration structure (khadas_mcu_data)
> holding the regmap config and MFD cells,
> selected at probe time via the of_device_id match data.
> This makes adding other variants straightforward.
> 
> Also introduce khadas_mcu_fan_pdata to pass fan register address and
> maximum level to the fan sub-driver, removing the hardcoded constants.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   include/linux/mfd/khadas-mcu.h | 39 +++++++++++++++++++++++++++++++++++++--
>   1 file changed, 37 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h
> index a99ba2ed0e4e0..75e275d3fa8d9 100644
> --- a/include/linux/mfd/khadas-mcu.h
> +++ b/include/linux/mfd/khadas-mcu.h
> @@ -70,6 +70,13 @@
>   #define KHADAS_MCU_WOL_INIT_START_REG		0x87 /* WO */
>   #define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG	0x88 /* WO */
>   
> +/* VIM4 specific registers */
> +#define KHADAS_MCU_VIM4_REST_CONF_REG		0x2c /* WO - reset EEPROM */
> +#define KHADAS_MCU_VIM4_LED_ON_RAM_REG		0x89 /* WO - LED volatile */
> +#define KHADAS_MCU_VIM4_FAN_CTRL_REG		0x8a /* WO */
> +#define KHADAS_MCU_VIM4_WDT_EN_REG		0x8b /* WO */
> +#define KHADAS_MCU_VIM4_SYS_RST_REG		0x91 /* WO */
> +
>   enum {
>   	KHADAS_BOARD_VIM1 = 0x1,
>   	KHADAS_BOARD_VIM2,
> @@ -82,10 +89,38 @@ enum {
>    * struct khadas_mcu - Khadas MCU structure
>    * @device:		device reference used for logs
>    * @regmap:		register map
> + * @data:		pointer to variant-specific config
>    */
>   struct khadas_mcu {
> -	struct device *dev;
> -	struct regmap *regmap;
> +	struct device			*dev;
> +	struct regmap			*regmap;
> +	const struct khadas_mcu_data	*data;
> +};
> +
> +/**
> + * struct khadas_mcu_data - per-variant configuration
> + * @regmap_config:	regmap configuration
> + * @cells:		MFD sub-devices
> + * @ncells:		number of sub-devices
> + * @fan_cells:		MFD fan sub-devices
> + * @nfan_cells:		number of fan sub-devices
> + */
> +struct khadas_mcu_data {
> +	const struct regmap_config	*regmap_config;
> +	const struct mfd_cell		*cells;
> +	int				ncells;
> +	const struct mfd_cell		*fan_cells;
> +	int				nfan_cells;
> +};
> +
> +/**
> + * struct khadas_mcu_fan_pdata - fan sub-driver configuration
> + * @fan_reg: register address to write the fan level
> + * @max_level: maximum fan level
> + */
> +struct khadas_mcu_fan_pdata {
> +	unsigned int fan_reg;
> +	unsigned int max_level;
>   };
>   
>   #endif /* MFD_KHADAS_MCU_H */
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH v4 8/8] arm64: dts: amlogic: t7: khadas-vim4: Add fan cooling to thermal zones
From: Neil Armstrong @ 2026-04-24  9:53 UTC (permalink / raw)
  To: linux-kernel-dev, Guillaume La Roque, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl
  Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
	linux-arm-kernel
In-Reply-To: <20260423-add-thermal-t7-vim4-v4-8-d4c1528d5044@aliel.fr>

On 4/23/26 18:07, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Add an active trip at 50°C to all six thermal zones and map it to the
> khadas_mcu fan controller, using cooling states 30 to 100.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   .../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts  | 102 +++++++++++++++++++++
>   1 file changed, 102 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
> index 5d7f5390f3a66..ba9219073dd0a 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
> @@ -157,6 +157,74 @@ wifi32k: wifi32k {
>   	};
>   };
>   
> +&a53_thermal {
> +	trips {
> +		a53_active: a53-active {
> +			temperature = <50000>; /* millicelsius */
> +			hysteresis = <2000>; /* millicelsius */
> +			type = "active";
> +		};
> +	};
> +
> +	cooling-maps {
> +		map {
> +			trip = <&a53_active>;
> +			cooling-device = <&khadas_mcu 30 100>;
> +		};
> +	};
> +};
> +
> +&a73_thermal {
> +	trips {
> +		a73_active: a73-active {
> +			temperature = <50000>; /* millicelsius */
> +			hysteresis = <2000>; /* millicelsius */
> +			type = "active";
> +		};
> +	};
> +
> +	cooling-maps {
> +		map {
> +			trip = <&a73_active>;
> +			cooling-device = <&khadas_mcu 30 100>;
> +		};
> +	};
> +};
> +
> +&gpu_thermal {
> +	trips {
> +		gpu_active: gpu-active {
> +			temperature = <50000>; /* millicelsius */
> +			hysteresis = <2000>; /* millicelsius */
> +			type = "active";
> +		};
> +	};
> +
> +	cooling-maps {
> +		map {
> +			trip = <&gpu_active>;
> +			cooling-device = <&khadas_mcu 30 100>;
> +		};
> +	};
> +};
> +
> +&hevc_thermal {
> +	trips {
> +		hevc_active: hevc-active {
> +			temperature = <50000>; /* millicelsius */
> +			hysteresis = <2000>; /* millicelsius */
> +			type = "active";
> +		};
> +	};
> +
> +	cooling-maps {
> +		map {
> +			trip = <&hevc_active>;
> +			cooling-device = <&khadas_mcu 30 100>;
> +		};
> +	};
> +};
> +
>   &i2c_m_ao_a {
>   	status = "okay";
>   	pinctrl-0 = <&i2c0_ao_d_pins>;
> @@ -170,6 +238,23 @@ khadas_mcu: system-controller@18 {
>   	};
>   };
>   
> +&nna_thermal {
> +	trips {
> +		nna_active: nna-active {
> +			temperature = <50000>; /* millicelsius */
> +			hysteresis = <2000>; /* millicelsius */
> +			type = "active";
> +		};
> +	};
> +
> +	cooling-maps {
> +		map {
> +			trip = <&nna_active>;
> +			cooling-device = <&khadas_mcu 30 100>;
> +		};
> +	};
> +};
> +
>   &pwm_ab {
>   	status = "okay";
>   	pinctrl-0 = <&pwm_a_pins>;
> @@ -266,3 +351,20 @@ &uart_a {
>   	clocks = <&xtal>, <&xtal>, <&xtal>;
>   	clock-names = "xtal", "pclk", "baud";
>   };
> +
> +&vpu_thermal {
> +	trips {
> +		vpu_active: vpu-active {
> +			temperature = <50000>; /* millicelsius */
> +			hysteresis = <2000>; /* millicelsius */
> +			type = "active";
> +		};
> +	};
> +
> +	cooling-maps {
> +		map {
> +			trip = <&vpu_active>;
> +			cooling-device = <&khadas_mcu 30 100>;
> +		};
> +	};
> +};
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH v4 7/8] arm64: dts: amlogic: t7: Add thermal zones
From: Neil Armstrong @ 2026-04-24  9:53 UTC (permalink / raw)
  To: linux-kernel-dev, Guillaume La Roque, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl
  Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
	linux-arm-kernel
In-Reply-To: <20260423-add-thermal-t7-vim4-v4-7-d4c1528d5044@aliel.fr>

On 4/23/26 18:07, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Add thermal zones for all six sensors: a53, a73, gpu, nna, vpu, and hevc.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 179 ++++++++++++++++++++++++++++
>   1 file changed, 179 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> index 62f259b2b17d2..c6ea0f20a879f 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> @@ -9,6 +9,7 @@
>   #include <dt-bindings/clock/amlogic,t7-scmi.h>
>   #include <dt-bindings/clock/amlogic,t7-pll-clkc.h>
>   #include <dt-bindings/clock/amlogic,t7-peripherals-clkc.h>
> +#include <dt-bindings/thermal/thermal.h>
>   
>   / {
>   	interrupt-parent = <&gic>;
> @@ -829,6 +830,184 @@ hevc_tsensor: temperature-sensor@9a000 {
>   				amlogic,secure-monitor = <&sm 5>;
>   			};
>   		};
> +	};
> +
> +	thermal-zones {
> +		a53_thermal: a53-thermal {
> +			polling-delay = <1000>;
> +			polling-delay-passive = <100>;
> +			thermal-sensors = <&a53_tsensor>;
> +
> +			trips {
> +				a53_passive: a53-passive {
> +					temperature = <85000>; /* millicelsius */
> +					hysteresis = <2000>; /* millicelsius */
> +					type = "passive";
> +				};
> +
> +				a53_hot: a53-hot {
> +					temperature = <95000>; /* millicelsius */
> +					hysteresis = <2000>; /* millicelsius */
> +					type = "hot";
> +				};
> +
> +				a53_critical: a53-critical {
> +					temperature = <110000>; /* millicelsius */
> +					hysteresis = <2000>; /* millicelsius */
> +					type = "critical";
> +				};
> +			};
> +
> +			cooling-maps {
> +				map-a53 {
> +					trip = <&a53_passive>;
> +					cooling-device =
> +						<&cpu100 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +						<&cpu101 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +						<&cpu102 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +						<&cpu103 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> +				};
> +			};
> +		};
> +
> +		a73_thermal: a73-thermal {
> +			polling-delay = <1000>;
> +			polling-delay-passive = <100>;
> +			thermal-sensors = <&a73_tsensor>;
> +
> +			trips {
> +				a73_passive: a73-passive {
> +					temperature = <85000>; /* millicelsius */
> +					hysteresis = <2000>; /* millicelsius */
> +					type = "passive";
> +				};
> +
> +				a73_hot: a73-hot {
> +					temperature = <95000>; /* millicelsius */
> +					hysteresis = <2000>; /* millicelsius */
> +					type = "hot";
> +				};
> +
> +				a73_critical: a73-critical {
> +					temperature = <110000>; /* millicelsius */
> +					hysteresis = <2000>; /* millicelsius */
> +					type = "critical";
> +				};
> +			};
> +
> +			cooling-maps {
> +				map-a73 {
> +					trip = <&a73_passive>;
> +					cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +							 <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +							 <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +							 <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> +				};
> +			};
> +		};
> +
> +		gpu_thermal: gpu-thermal {
> +			polling-delay = <1000>;
> +			polling-delay-passive = <100>;
> +			thermal-sensors = <&gpu_tsensor>;
> +
> +			trips {
> +				gpu_passive: gpu-passive {
> +					temperature = <95000>;
> +					hysteresis = <5000>;
> +					type = "passive";
> +				};
> +
> +				gpu_hot: gpu-hot {
> +					temperature = <105000>;
> +					hysteresis = <5000>;
> +					type = "passive";
> +				};
>   
> +				gpu_critical: gpu-critical {
> +					temperature = <115000>;
> +					hysteresis = <1000>;
> +					type = "critical";
> +				};
> +			};
> +		};
> +
> +		hevc_thermal: hevc-thermal {
> +			polling-delay = <1000>;
> +			polling-delay-passive = <100>;
> +			thermal-sensors = <&hevc_tsensor>;
> +
> +			trips {
> +				hevc_passive: hevc-passive {
> +					temperature = <95000>;
> +					hysteresis = <5000>;
> +					type = "passive";
> +				};
> +
> +				hevc_hot: hevc-hot {
> +					temperature = <105000>;
> +					hysteresis = <5000>;
> +					type = "passive";
> +				};
> +
> +				hevc_critical: hevc-critical {
> +					temperature = <115000>;
> +					hysteresis = <1000>;
> +					type = "critical";
> +				};
> +			};
> +		};
> +
> +		nna_thermal: nna-thermal {
> +			polling-delay = <1000>;
> +			polling-delay-passive = <100>;
> +			thermal-sensors = <&nna_tsensor>;
> +
> +			trips {
> +				nna_passive: nna-passive {
> +					temperature = <95000>;
> +					hysteresis = <5000>;
> +					type = "passive";
> +				};
> +
> +				nna_hot: nna-hot {
> +					temperature = <105000>;
> +					hysteresis = <5000>;
> +					type = "passive";
> +				};
> +
> +				nna_critical: nna-critical {
> +					temperature = <115000>;
> +					hysteresis = <1000>;
> +					type = "critical";
> +				};
> +			};
> +		};
> +
> +		vpu_thermal: vpu-thermal {
> +			polling-delay = <1000>;
> +			polling-delay-passive = <100>;
> +			thermal-sensors = <&vpu_tsensor>;
> +
> +			trips {
> +				vpu_passive: vpu-passive {
> +					temperature = <95000>;
> +					hysteresis = <5000>;
> +					type = "passive";
> +				};
> +
> +				vpu_hot: vpu-hot {
> +					temperature = <105000>;
> +					hysteresis = <5000>;
> +					type = "passive";
> +				};
> +
> +				vpu_critical: vpu-critical {
> +					temperature = <115000>;
> +					hysteresis = <1000>;
> +					type = "critical";
> +				};
> +			};
> +		};
>   	};
>   };
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH v4 6/8] arm64: dts: amlogic: t7: Add thermal sensor nodes
From: Neil Armstrong @ 2026-04-24  9:52 UTC (permalink / raw)
  To: linux-kernel-dev, Guillaume La Roque, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl
  Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
	linux-arm-kernel
In-Reply-To: <20260423-add-thermal-t7-vim4-v4-6-d4c1528d5044@aliel.fr>

On 4/23/26 18:07, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Add six temperature sensor nodes using the amlogic,t7-thermal compatible:
> a73, a53, gpu, nna, vpu, and hevc. Each sensor retrieves its calibration
> data from the secure monitor via the amlogic,secure-monitor phandle with
> the corresponding tsensor_id argument.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 58 +++++++++++++++++++++++++++++
>   1 file changed, 58 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> index 7aec65f036a9c..62f259b2b17d2 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> @@ -656,6 +656,24 @@ sec_ao: ao-secure@10220 {
>   				amlogic,has-chip-id;
>   			};
>   
> +			a73_tsensor: temperature-sensor@20000 {
> +				compatible = "amlogic,t7-thermal";
> +				reg = <0x0 0x20000 0x0 0x50>;
> +				interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&clkc_periphs CLKID_TS>;
> +				#thermal-sensor-cells = <0>;
> +				amlogic,secure-monitor = <&sm 1>;
> +			};
> +
> +			a53_tsensor: temperature-sensor@22000 {
> +				compatible = "amlogic,t7-thermal";
> +				reg = <0x0 0x22000 0x0 0x50>;
> +				interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&clkc_periphs CLKID_TS>;
> +				#thermal-sensor-cells = <0>;
> +				amlogic,secure-monitor = <&sm 2>;
> +			};
> +
>   			pwm_ao_ef: pwm@30000 {
>   				compatible = "amlogic,t7-pwm", "amlogic,meson-s4-pwm";
>   				reg = <0x0 0x30000 0x0 0x24>;
> @@ -770,6 +788,46 @@ sd_emmc_c: mmc@8c000 {
>   				assigned-clock-parents = <&xtal>;
>   				status = "disabled";
>   			};
> +
> +			gpu_tsensor: temperature-sensor@94000 {
> +				compatible = "amlogic,t7-thermal";
> +				reg = <0x0 0x94000 0x0 0x50>;
> +				interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&clkc_periphs CLKID_TS>;
> +				power-domains = <&pwrc PWRC_T7_MALI_TOP_ID>;
> +				#thermal-sensor-cells = <0>;
> +				amlogic,secure-monitor = <&sm 3>;
> +			};
> +
> +			nna_tsensor: temperature-sensor@96000 {
> +				compatible = "amlogic,t7-thermal";
> +				reg = <0x0 0x96000 0x0 0x50>;
> +				interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&clkc_periphs CLKID_TS>;
> +				power-domains = <&pwrc PWRC_T7_NNA_TOP_ID>;
> +				#thermal-sensor-cells = <0>;
> +				amlogic,secure-monitor = <&sm 4>;
> +			};
> +
> +			vpu_tsensor: temperature-sensor@98000 {
> +				compatible = "amlogic,t7-thermal";
> +				reg = <0x0 0x98000 0x0 0x50>;
> +				interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&clkc_periphs CLKID_TS>;
> +				power-domains = <&pwrc PWRC_T7_VPU_HDMI_ID>;
> +				#thermal-sensor-cells = <0>;
> +				amlogic,secure-monitor = <&sm 6>;
> +			};
> +
> +			hevc_tsensor: temperature-sensor@9a000 {
> +				compatible = "amlogic,t7-thermal";
> +				reg = <0x0 0x9a000 0x0 0x50>;
> +				interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
> +				clocks = <&clkc_periphs CLKID_TS>;
> +				power-domains = <&pwrc PWRC_T7_DOS_HEVC_ID>;
> +				#thermal-sensor-cells = <0>;
> +				amlogic,secure-monitor = <&sm 5>;
> +			};
>   		};
>   
>   	};
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH v4 5/8] arm64: dts: amlogic: t7: Add cooling cells to all CPUs
From: Neil Armstrong @ 2026-04-24  9:52 UTC (permalink / raw)
  To: linux-kernel-dev, Guillaume La Roque, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl
  Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
	linux-arm-kernel
In-Reply-To: <20260423-add-thermal-t7-vim4-v4-5-d4c1528d5044@aliel.fr>

On 4/23/26 18:07, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Add #cooling-cells = <2> to all CPU nodes (both little and big cluster)
> to allow them to be used as cooling devices in thermal zone mappings.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 8 ++++++++
>   1 file changed, 8 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> index 560c9dce35266..7aec65f036a9c 100644
> --- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
> @@ -63,6 +63,7 @@ cpu100: cpu@100 {
>   			i-cache-size = <0x8000>;
>   			i-cache-sets = <32>;
>   			next-level-cache = <&l2_cache_l>;
> +			#cooling-cells = <2>;
>   		};
>   
>   		cpu101: cpu@101 {
> @@ -77,6 +78,7 @@ cpu101: cpu@101 {
>   			i-cache-size = <0x8000>;
>   			i-cache-sets = <32>;
>   			next-level-cache = <&l2_cache_l>;
> +			#cooling-cells = <2>;
>   		};
>   
>   		cpu102: cpu@102 {
> @@ -91,6 +93,7 @@ cpu102: cpu@102 {
>   			i-cache-size = <0x8000>;
>   			i-cache-sets = <32>;
>   			next-level-cache = <&l2_cache_l>;
> +			#cooling-cells = <2>;
>   		};
>   
>   		cpu103: cpu@103 {
> @@ -105,6 +108,7 @@ cpu103: cpu@103 {
>   			i-cache-size = <0x8000>;
>   			i-cache-sets = <32>;
>   			next-level-cache = <&l2_cache_l>;
> +			#cooling-cells = <2>;
>   		};
>   
>   		cpu0: cpu@0 {
> @@ -119,6 +123,7 @@ cpu0: cpu@0 {
>   			i-cache-size = <0x10000>;
>   			i-cache-sets = <64>;
>   			next-level-cache = <&l2_cache_b>;
> +			#cooling-cells = <2>;
>   		};
>   
>   		cpu1: cpu@1 {
> @@ -133,6 +138,7 @@ cpu1: cpu@1 {
>   			i-cache-size = <0x10000>;
>   			i-cache-sets = <64>;
>   			next-level-cache = <&l2_cache_b>;
> +			#cooling-cells = <2>;
>   		};
>   
>   		cpu2: cpu@2 {
> @@ -147,6 +153,7 @@ cpu2: cpu@2 {
>   			i-cache-size = <0x10000>;
>   			i-cache-sets = <64>;
>   			next-level-cache = <&l2_cache_b>;
> +			#cooling-cells = <2>;
>   		};
>   
>   		cpu3: cpu@3 {
> @@ -161,6 +168,7 @@ cpu3: cpu@3 {
>   			i-cache-size = <0x10000>;
>   			i-cache-sets = <64>;
>   			next-level-cache = <&l2_cache_b>;
> +			#cooling-cells = <2>;
>   		};
>   
>   		l2_cache_l: l2-cache-cluster0 {
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH v4 3/8] firmware: meson: sm: Add thermal calibration SMC call
From: Neil Armstrong @ 2026-04-24  9:47 UTC (permalink / raw)
  To: linux-kernel-dev, Guillaume La Roque, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl
  Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
	linux-arm-kernel
In-Reply-To: <20260423-add-thermal-t7-vim4-v4-3-d4c1528d5044@aliel.fr>

On 4/23/26 18:07, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Add SM_THERMAL_CALIB_READ at SMC ID 0x82000047 in the command
> table and implement meson_sm_get_thermal_calib(), which forwards the
> tsensor_id argument to the secure monitor and returns the calibration data.
> 
> Also realign the CMD() column to improve readability.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   drivers/firmware/meson/meson_sm.c | 29 ++++++++++++++++++++++++-----
>   1 file changed, 24 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
> index 3ab67aaa9e5da..4e57986724212 100644
> --- a/drivers/firmware/meson/meson_sm.c
> +++ b/drivers/firmware/meson/meson_sm.c
> @@ -41,12 +41,13 @@ static const struct meson_sm_chip gxbb_chip = {
>   	.cmd_shmem_in_base	= 0x82000020,
>   	.cmd_shmem_out_base	= 0x82000021,
>   	.cmd = {
> -		CMD(SM_EFUSE_READ,	0x82000030),
> -		CMD(SM_EFUSE_WRITE,	0x82000031),
> +		CMD(SM_EFUSE_READ,		0x82000030),
> +		CMD(SM_EFUSE_WRITE,		0x82000031),
>   		CMD(SM_EFUSE_USER_MAX,	0x82000033),
> -		CMD(SM_GET_CHIP_ID,	0x82000044),
> -		CMD(SM_A1_PWRC_SET,	0x82000093),
> -		CMD(SM_A1_PWRC_GET,	0x82000095),
> +		CMD(SM_GET_CHIP_ID,		0x82000044),
> +		CMD(SM_THERMAL_CALIB_READ,	0x82000047),
> +		CMD(SM_A1_PWRC_SET,		0x82000093),
> +		CMD(SM_A1_PWRC_GET,		0x82000095),
>   		{ /* sentinel */ },
>   	},
>   };
> @@ -245,6 +246,24 @@ struct meson_sm_firmware *meson_sm_get(struct device_node *sm_node)
>   }
>   EXPORT_SYMBOL_GPL(meson_sm_get);
>   
> +/**
> + *
> + * meson_sm_get_thermal_calib - Read thermal sensor calibration data.
> + * @fw:		Pointer to secure-monitor firmware.
> + * @trim_info:	Pointer to store the returned calibration data.
> + * @tsensor_id:	Sensor index to identify which sensor's calibration data
> + *		to retrieve
> + *
> + * Return: 0 on success, negative error code on failure.
> + */
> +int meson_sm_get_thermal_calib(struct meson_sm_firmware *fw, u32 *trim_info,
> +			       u32 tsensor_id)
> +{
> +	return meson_sm_call(fw, SM_THERMAL_CALIB_READ, trim_info, tsensor_id,
> +			     0, 0, 0, 0);
> +}
> +EXPORT_SYMBOL_GPL(meson_sm_get_thermal_calib);
> +
>   #define SM_CHIP_ID_LENGTH	119
>   #define SM_CHIP_ID_OFFSET	4
>   #define SM_CHIP_ID_SIZE		12
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH v4 2/8] firmware: meson: sm: Thermal calibration read via secure monitor
From: Neil Armstrong @ 2026-04-24  9:47 UTC (permalink / raw)
  To: linux-kernel-dev, Guillaume La Roque, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl
  Cc: linux-pm, linux-amlogic, devicetree, linux-kernel,
	linux-arm-kernel
In-Reply-To: <20260423-add-thermal-t7-vim4-v4-2-d4c1528d5044@aliel.fr>

On 4/23/26 18:07, Ronald Claveau via B4 Relay wrote:
> From: Ronald Claveau <linux-kernel-dev@aliel.fr>
> 
> Add SM_THERMAL_CALIB_READ to the secure monitor command enum and
> introduce meson_sm_get_thermal_calib() to allow drivers to retrieve
> thermal sensor calibration data through the firmware interface.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
> ---
>   include/linux/firmware/meson/meson_sm.h | 3 +++
>   1 file changed, 3 insertions(+)
> 
> diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h
> index 8eaf8922ab020..3ebc2bd9a9760 100644
> --- a/include/linux/firmware/meson/meson_sm.h
> +++ b/include/linux/firmware/meson/meson_sm.h
> @@ -12,6 +12,7 @@ enum {
>   	SM_EFUSE_WRITE,
>   	SM_EFUSE_USER_MAX,
>   	SM_GET_CHIP_ID,
> +	SM_THERMAL_CALIB_READ,
>   	SM_A1_PWRC_SET,
>   	SM_A1_PWRC_GET,
>   };
> @@ -27,5 +28,7 @@ int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
>   		       unsigned int bsize, unsigned int cmd_index, u32 arg0,
>   		       u32 arg1, u32 arg2, u32 arg3, u32 arg4);
>   struct meson_sm_firmware *meson_sm_get(struct device_node *firmware_node);
> +int meson_sm_get_thermal_calib(struct meson_sm_firmware *fw, u32 *trim_info,
> +			       u32 tsensor_id);
>   
>   #endif /* _MESON_SM_FW_H_ */
> 

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil


^ permalink raw reply

* Re: [PATCH] iio: fix header includes across multiple drivers
From: Andy Shevchenko @ 2026-04-24  9:45 UTC (permalink / raw)
  To: David Lechner
  Cc: Caio Morais, jic23, nuno.sa, andy, michal.simek, linux-iio,
	linux-arm-kernel
In-Reply-To: <a9307e04-3754-465e-a610-92c6e83cc3e6@baylibre.com>

On Thu, Apr 23, 2026 at 01:45:12PM -0500, David Lechner wrote:
> On 4/23/26 1:33 PM, Caio Morais wrote:
> > 
> > Remove unnecessary includes and add missing ones as reported by the
> > include-what-you-use (IWYU) tool.
> > 
> > Files changed:
> > - drivers/iio/adc/xilinx-xadc-events.c
> > - drivers/iio/buffer/industrialio-triggered-buffer.c
> > - drivers/iio/common/st_sensors/st_sensors_i2c.c
> > - drivers/iio/common/st_sensors/st_sensors_spi.c
> 
> We'll want to split these up, one patch per file in case they every
> need to be backported as a dependency to a fix.

Per driver actually, as the last two belong to the same driver
(different busses though).

...

> This looks like sorting alphabetically, not actually adding or removing
> any headers as seen by the equal number of insertions and deletions.
> 
> Usually we don't bother with sorting unless we are making other
> changes on top of that.

Right. At bare minimum we expect sorting + IWYU patch series.

...

> >  #include <linux/device.h>
> >  #include <linux/err.h>
> >  #include <linux/i2c.h>
> > +#include <linux/iio/iio.h>
> >  #include <linux/linkage.h>
> >  #include <linux/module.h>
> >  #include <linux/regmap.h>
> > -#include <linux/iio/iio.h>
> 
> On this one, it would be more logical to move the iio header
> down one line to group it with the one below.

Hmm... Personally I consider them different group, I would rather see

linux/*
...blank line...
linux/iio/*
...blank line...
linux/_whatever_driver_specific_

> >  #include <linux/iio/common/st_sensors_i2c.h>

-- 
With Best Regards,
Andy Shevchenko




^ permalink raw reply

* [PATCH v5 2/2] arm64: dts: amlogic: add support for Amediatech X98Q
From: christian.koever-draxl @ 2026-04-24  9:36 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, neil.armstrong, khilman
  Cc: jbrunet, martin.blumenstingl, devicetree, linux-amlogic,
	linux-arm-kernel, linux-kernel,
	Christian Stefan Kövér-Draxl
In-Reply-To: <20260424093633.10734-1-christian.koever-draxl@student.uibk.ac.at>

From: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>

Add dts enabling core hardware for the Amediatech X98Q TV box.

The board features:
- Amlogic S905W2 (Meson S4) SoC
- 1 GiB RAM (2 GiB variants exist)
- eMMC and microSD card slot
- SDIO-based WiFi module (unsupported)
- RMII Ethernet with internal PHY
- IR receiver and UART console
- Status LED

Enabled peripherals:
- eMMC (HS200)
- SD card interface
- SDIO bus (WiFi, no driver yet)
- Ethernet (RMII)
- UART_B
- IR receiver
- PWM-controlled CPU regulator
- PWM and Fixed regulators for core and IO rails

Known limitations:
- No support for the onboard WiFi module
- Missing multimedia (HDMI/audio)

Signed-off-by: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
---
 arch/arm64/boot/dts/amlogic/Makefile          |   1 +
 .../boot/dts/amlogic/meson-s4-s905w2-x98q.dts | 249 ++++++++++++++++++
 2 files changed, 250 insertions(+)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts

diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index 15f9c817e502..c7752684dea6 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -85,6 +85,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxm-ugoos-am3.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-wetek-core2.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-s4-s805x2-aq222.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905w2-x98q.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-s4-s905y4-khadas-vim1s.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air-gbit.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air.dtb
diff --git a/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
index 000000000000..fe84259a20f3
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2026 Christian Stefan Köver-Draxl
+ * Based on meson-s4-s905y4-khadas-vim1s.dts:
+ *  - Copyright (c) 2026 Khadas Technology Co., Ltd.
+ */
+
+/dts-v1/;
+
+#include "meson-s4.dtsi"
+
+/ {
+	model = "Shenzhen Amediatech Technology Co., Ltd X98Q";
+	compatible = "amediatech,x98q", "amlogic,s905w2", "amlogic,s4";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		mmc0 = &emmc; /* eMMC */
+		mmc1 = &sd; /* SD card */
+		mmc2 = &sdio; /* SDIO */
+		serial0 = &uart_b;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x40000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 52 MiB reserved for ARM Trusted Firmware */
+		secmon_reserved: secmon@5000000 {
+			reg = <0x0 0x05000000 0x0 0x3400000>;
+			no-map;
+		};
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio GPIOB_9 GPIO_ACTIVE_LOW>;
+	};
+
+	sdio_32k: sdio-32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+		clocks = <&sdio_32k>;
+		clock-names = "ext_clock";
+	};
+
+	main_5v: regulator-main-5v {
+		compatible = "regulator-fixed";
+		regulator-name = "5V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	sd_3v3: regulator-sd-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "SD_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio GPIOD_4 GPIO_ACTIVE_LOW>;
+		regulator-always-on;
+	};
+
+	vddio_sd: regulator-vddio-sd {
+		compatible = "regulator-gpio";
+		regulator-name = "VDDIO_SD";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		gpios = <&gpio GPIOD_9 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <1800000 1 3300000 0>;
+	};
+
+	vddao_3v3: regulator-vddao-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&main_5v>;
+		regulator-always-on;
+	};
+
+	vddio_ao1v8: regulator-vddio-ao1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_AO1V8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vddao_3v3>;
+		regulator-always-on;
+	};
+
+	/* SY8120B1ABC DC/DC Regulator. */
+	vddcpu: regulator-vddcpu {
+		compatible = "pwm-regulator";
+
+		regulator-name = "VDDCPU";
+		regulator-min-microvolt = <689000>;
+		regulator-max-microvolt = <1049000>;
+
+		vin-supply = <&main_5v>;
+
+		pwms = <&pwm_ij 1 1500 0>;
+		pwm-dutycycle-range = <100 0>;
+
+		regulator-boot-on;
+		regulator-always-on;
+		/* Voltage Duty-Cycle */
+		voltage-table = <1049000 0>,
+				<1039000 3>,
+				<1029000 6>,
+				<1019000 9>,
+				<1009000 12>,
+				<999000 14>,
+				<989000 17>,
+				<979000 20>,
+				<969000 23>,
+				<959000 26>,
+				<949000 29>,
+				<939000 31>,
+				<929000 34>,
+				<919000 37>,
+				<909000 40>,
+				<899000 43>,
+				<889000 45>,
+				<879000 48>,
+				<869000 51>,
+				<859000 54>,
+				<849000 56>,
+				<839000 59>,
+				<829000 62>,
+				<819000 65>,
+				<809000 68>,
+				<799000 70>,
+				<789000 73>,
+				<779000 76>,
+				<769000 79>,
+				<759000 81>,
+				<749000 84>,
+				<739000 87>,
+				<729000 89>,
+				<719000 92>,
+				<709000 95>,
+				<699000 98>,
+				<689000 100>;
+	};
+};
+
+&emmc {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
+	pinctrl-1 = <&emmc_clk_gate_pins>;
+	pinctrl-names = "default", "clk-gate";
+
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_ao1v8>;
+};
+
+&ethmac {
+	status = "okay";
+	phy-handle = <&internal_ephy>;
+	phy-mode = "rmii";
+};
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_pins>;
+	pinctrl-names = "default";
+};
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins1>;
+	pinctrl-names = "default";
+};
+
+&pwm_ij {
+	status = "okay";
+};
+
+&sd {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-1 = <&sdcard_clk_gate_pins>;
+	pinctrl-names = "default", "clk-gate";
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <50000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddao_3v3>;
+};
+
+&sdio {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-1 = <&sdio_clk_gate_pins>;
+	pinctrl-names = "default", "clk-gate";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	bus-width = <4>;
+	cap-sd-highspeed;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+
+	no-sd;
+	no-mmc;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_ao1v8>;
+
+	wifi: wifi@1 {
+		/* Amlogic W150S1 */
+		reg = <1>;
+	};
+};
+
+&uart_b {
+	status = "okay";
+};
-- 
2.54.0



^ permalink raw reply related

* [PATCH v5 0/2] Add support for Amediatech X98Q (Amlogic S905W2)
From: christian.koever-draxl @ 2026-04-24  9:36 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, neil.armstrong, khilman
  Cc: jbrunet, martin.blumenstingl, devicetree, linux-amlogic,
	linux-arm-kernel, linux-kernel,
	Christian Stefan Kövér-Draxl

From: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>

Supported features:
- 1GB RAM (2GB variants exist)
- 10/100 Ethernet (Internal PHY)
- eMMC and SD card storage
- PWM-based CPU voltage regulation
- UART (Serial console)

Notes:
- The console uses uart_b at 921600 baud.
- Verified memory via /proc/device-tree; U-Boot patches the node.
- Tested on the 2GB RAM plus 16GB eMMC variant.

Changes in v5:
- Drop Wireless SDIO Module comment.
- Add generic description of Wireless SDIO Module in dts.

Changes in v4:
- Add/Change hardware description to cover letter and dts patch.

Changes in v3:
- Change position of the entry in the amlogic.yaml.
- Change formatting of the Amlogic W150S1 Wi-Fi module comment.
- Fix several formatting issues.

Changes in v2:
- Split dt-bindings and dts changes into separate patches.
- Updated model string to match documented vendor prefix.
- Put vddio_sd states array in a single line.
- Added a comment for the unsupported Amlogic W150S1 Wi-Fi module. 

Christian Stefan Kövér-Draxl (2):
  dt-bindings: arm: amlogic: add support for Amediatech X98Q
  arm64: dts: amlogic: add support for Amediatech X98Q

 .../devicetree/bindings/arm/amlogic.yaml      |   7 +
 arch/arm64/boot/dts/amlogic/Makefile          |   1 +
 .../boot/dts/amlogic/meson-s4-s905w2-x98q.dts | 249 ++++++++++++++++++
 3 files changed, 257 insertions(+)
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-s4-s905w2-x98q.dts

-- 
2.54.0



^ permalink raw reply

* [PATCH v5 1/2] dt-bindings: arm: amlogic: add support for Amediatech X98Q
From: christian.koever-draxl @ 2026-04-24  9:36 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, neil.armstrong, khilman
  Cc: jbrunet, martin.blumenstingl, devicetree, linux-amlogic,
	linux-arm-kernel, linux-kernel,
	Christian Stefan Kövér-Draxl, Conor Dooley
In-Reply-To: <20260424093633.10734-1-christian.koever-draxl@student.uibk.ac.at>

From: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>

Add the board binding for the Amediatech X98Q TV box.

Signed-off-by: Christian Stefan Kövér-Draxl <christian.koever-draxl@student.uibk.ac.at>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index a885278bc4e2..c0167fbc310a 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -248,6 +248,13 @@ properties:
           - const: amlogic,s805x2
           - const: amlogic,s4
 
+      - description: Boards with the Amlogic Meson S4 S905W2 SoC
+        items:
+          - enum:
+              - amediatech,x98q
+          - const: amlogic,s905w2
+          - const: amlogic,s4
+
       - description: Boards with the Amlogic Meson S4 S905Y4 SoC
         items:
           - enum:
-- 
2.54.0



^ permalink raw reply related

* Re: [REGRESSION] rseq: refactoring in v6.19 broke everyone on arm64 and tcmalloc everywhere
From: Dmitry Vyukov @ 2026-04-24  9:30 UTC (permalink / raw)
  To: Mathias Stearn
  Cc: Thomas Gleixner, Jinjie Ruan, linux-man, Mark Rutland,
	Mathieu Desnoyers, Catalin Marinas, Will Deacon, Boqun Feng,
	Paul E. McKenney, Chris Kennelly, regressions, linux-kernel,
	linux-arm-kernel, Peter Zijlstra, Ingo Molnar, Blake Oler
In-Reply-To: <CAHnCjA1LqbaUGkPe79EeP6Mpaki8QWeR-JBSbrG0z6pTm9CmUg@mail.gmail.com>

On Fri, 24 Apr 2026 at 10:32, Mathias Stearn <mathias@mongodb.com> wrote:
>
> On Fri, Apr 24, 2026 at 9:57 AM Dmitry Vyukov <dvyukov@google.com> wrote:
> > > So if the code only requires to know when it got rescheduled to another
> > > CPU then it still should work, no?
> >
> > This was my first thought too:
> > https://lore.kernel.org/lkml/CACT4Y+a9GnOh3wHKSRwzoKF6_OSksQ8qehnHfpCgkQSt_OOmYg@mail.gmail.com/
> > The only problem is with membarrier (it used to force write to
> > __rseq_abi.cpu_id_start for all threads, but now it does not).
> > Otherwise the caching scheme works.
>
> I almost wrote a message last night saying that we didn't need
> cpu_id_start invalidation on preemption. However, I remembered that
> the Grow() function[1] does a load outside of a critical section then
> stores a derived value inside the critical section, guarded only by
> the cpu_id_start invalidation check in StoreCurrentCpu[2]. It really
> should be doing a compare against the original value inside the
> critical section (or just do the whole thing inside), but it doesn't.
> I haven't reasoned end-to-end through this fully to prove corruption
> is possible, but I suspect that it is if another thread same-cpu
> preempts between the loads and the store and updates the header before
> the original thread resumes and writes its original intended header
> value. Ditto for signals, which sometimes allocate even though they
> shouldn't.
>
> I was really hoping that we would only need to do the "redundant"
> cpu_id_start writes would only be needed on membarrier_rseq IPIs where
> it really is a pay-for-what-you-use functionality, I think existing
> binaries depend on invalidation on preemption. Luckily that should be
> cheap enough to be ~free.

I've prototyped this idea too:
https://github.com/dvyukov/linux/commit/1284e3723047cb5afd247f75c53de43efc18db82



> [1] https://github.com/google/tcmalloc/blob/8e98046ec5639bffbe70a53770a2699dd355b26d/tcmalloc/internal/percpu_tcmalloc.h#L964-L980
> [2] https://github.com/google/tcmalloc/blob/8e98046ec5639bffbe70a53770a2699dd355b26d/tcmalloc/internal/percpu_tcmalloc.h#L551-L605


^ permalink raw reply

* [PATCH v4 2/2] ARM: dts: aspeed: ventura2: Add Meta ventura2 BMC
From: Kyle Hsieh @ 2026-04-24  9:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
	Kyle Hsieh
In-Reply-To: <20260424-ventura2_initial_dts-v4-0-806b00ea4314@gmail.com>

Add linux device tree entry related to the Meta(Facebook) rmc-node.
The system use an AT2600 BMC.
This node is named "ventura2".

Signed-off-by: Kyle Hsieh <kylehsieh1995@gmail.com>
---
 arch/arm/boot/dts/aspeed/Makefile                  |    1 +
 .../dts/aspeed/aspeed-bmc-facebook-ventura2.dts    | 2925 ++++++++++++++++++++
 2 files changed, 2926 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index 9adf9278dc94..6b96997629d4 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -32,6 +32,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
 	aspeed-bmc-facebook-minipack.dtb \
 	aspeed-bmc-facebook-santabarbara.dtb \
 	aspeed-bmc-facebook-tiogapass.dtb \
+	aspeed-bmc-facebook-ventura2.dtb \
 	aspeed-bmc-facebook-wedge40.dtb \
 	aspeed-bmc-facebook-wedge100.dtb \
 	aspeed-bmc-facebook-wedge400-data64.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura2.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura2.dts
new file mode 100644
index 000000000000..8d4ddb473862
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-ventura2.dts
@@ -0,0 +1,2925 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2023 Facebook Inc.
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/i2c/i2c.h>
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+/ {
+	model = "Facebook Ventura2 RMC";
+	compatible = "facebook,ventura2-rmc", "aspeed,ast2600";
+	aliases {
+		serial2 = &uart3;
+		serial4 = &uart5;
+
+		/*
+		 * i2c switch 0-0077, pca9548, 8 child channels assigned
+		 * with bus number 16-23.
+		 */
+		i2c16 = &i2c0mux0ch0;
+		i2c17 = &i2c0mux0ch1;
+		i2c18 = &i2c0mux0ch2;
+		i2c19 = &i2c0mux0ch3;
+		i2c20 = &i2c0mux0ch4;
+		i2c21 = &i2c0mux0ch5;
+		i2c22 = &i2c0mux0ch6;
+		i2c23 = &i2c0mux0ch7;
+
+		/*
+		 * i2c switch 1-0077, pca9548, 8 child channels assigned
+		 * with bus number 24-31.
+		 */
+		i2c24 = &i2c1mux0ch0;
+		i2c25 = &i2c1mux0ch1;
+		i2c26 = &i2c1mux0ch2;
+		i2c27 = &i2c1mux0ch3;
+		i2c28 = &i2c1mux0ch4;
+		i2c29 = &i2c1mux0ch5;
+		i2c30 = &i2c1mux0ch6;
+		i2c31 = &i2c1mux0ch7;
+
+		/*
+		 * i2c switch 4-0077, pca9548, 8 child channels assigned
+		 * with bus number 32-39.
+		 */
+		i2c32 = &i2c4mux0ch0;
+		i2c33 = &i2c4mux0ch1;
+		i2c34 = &i2c4mux0ch2;
+		i2c35 = &i2c4mux0ch3;
+		i2c36 = &i2c4mux0ch4;
+		i2c37 = &i2c4mux0ch5;
+		i2c38 = &i2c4mux0ch6;
+		i2c39 = &i2c4mux0ch7;
+
+		/*
+		 * i2c switch 5-0077, pca9548, 8 child channels assigned
+		 * with bus number 40-47.
+		 */
+		i2c40 = &i2c5mux0ch0;
+		i2c41 = &i2c5mux0ch1;
+		i2c42 = &i2c5mux0ch2;
+		i2c43 = &i2c5mux0ch3;
+		i2c44 = &i2c5mux0ch4;
+		i2c45 = &i2c5mux0ch5;
+		i2c46 = &i2c5mux0ch6;
+		i2c47 = &i2c5mux0ch7;
+
+		/*
+		 * i2c switch 8-0077, pca9548, 8 child channels assigned
+		 * with bus number 48-55.
+		 */
+		i2c48 = &i2c8mux0ch0;
+		i2c49 = &i2c8mux0ch1;
+		i2c50 = &i2c8mux0ch2;
+		i2c51 = &i2c8mux0ch3;
+		i2c52 = &i2c8mux0ch4;
+		i2c53 = &i2c8mux0ch5;
+		i2c54 = &i2c8mux0ch6;
+		i2c55 = &i2c8mux0ch7;
+
+		/*
+		 * i2c switch 11-0077, pca9548, 8 child channels assigned
+		 * with bus number 56-63.
+		 */
+		i2c56 = &i2c11mux0ch0;
+		i2c57 = &i2c11mux0ch1;
+		i2c58 = &i2c11mux0ch2;
+		i2c59 = &i2c11mux0ch3;
+		i2c60 = &i2c11mux0ch4;
+		i2c61 = &i2c11mux0ch5;
+		i2c62 = &i2c11mux0ch6;
+		i2c63 = &i2c11mux0ch7;
+
+		/*
+		 * i2c switch 13-0077, pca9548, 8 child channels assigned
+		 * with bus number 64-71.
+		 */
+		i2c64 = &i2c13mux0ch0;
+		i2c65 = &i2c13mux0ch1;
+		i2c66 = &i2c13mux0ch2;
+		i2c67 = &i2c13mux0ch3;
+		i2c68 = &i2c13mux0ch4;
+		i2c69 = &i2c13mux0ch5;
+		i2c70 = &i2c13mux0ch6;
+		i2c71 = &i2c13mux0ch7;
+
+		/*
+		 * i2c switch 15-0077, pca9548, 8 child channels assigned
+		 * with bus number 72-79.
+		 */
+		i2c72 = &i2c15mux0ch0;
+		i2c73 = &i2c15mux0ch1;
+		i2c74 = &i2c15mux0ch2;
+		i2c75 = &i2c15mux0ch3;
+		i2c76 = &i2c15mux0ch4;
+		i2c77 = &i2c15mux0ch5;
+		i2c78 = &i2c15mux0ch6;
+		i2c79 = &i2c15mux0ch7;
+	};
+
+	chosen {
+		stdout-path = "serial4:57600n8";
+	};
+
+	fan_leds {
+		compatible = "gpio-leds";
+
+		led-0 {
+			label = "fcb0fan0_ledd1_blue";
+			default-state = "off";
+			gpios = <&fan_io_expander0 0 GPIO_ACTIVE_LOW>;
+		};
+
+		led-1 {
+			label = "fcb0fan1_ledd2_blue";
+			default-state = "off";
+			gpios = <&fan_io_expander0 1 GPIO_ACTIVE_LOW>;
+		};
+
+		led-2 {
+			label = "fcb0fan2_ledd3_blue";
+			default-state = "off";
+			gpios = <&fan_io_expander1 0 GPIO_ACTIVE_LOW>;
+		};
+
+		led-3 {
+			label = "fcb0fan3_ledd4_blue";
+			default-state = "off";
+			gpios = <&fan_io_expander1 1 GPIO_ACTIVE_LOW>;
+		};
+
+		led-4 {
+			label = "fcb0fan0_ledd1_amber";
+			default-state = "off";
+			gpios = <&fan_io_expander0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		led-5 {
+			label = "fcb0fan1_ledd2_amber";
+			default-state = "off";
+			gpios = <&fan_io_expander0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		led-6 {
+			label = "fcb0fan2_ledd3_amber";
+			default-state = "off";
+			gpios = <&fan_io_expander1 4 GPIO_ACTIVE_LOW>;
+		};
+
+		led-7 {
+			label = "fcb0fan3_ledd4_amber";
+			default-state = "off";
+			gpios = <&fan_io_expander1 5 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	iio-hwmon {
+		compatible = "iio-hwmon";
+		io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>,
+		<&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>,
+		<&adc1 2>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led-0 {
+			label = "bmc_heartbeat_amber";
+			gpios = <&gpio0 ASPEED_GPIO(P, 7) GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led-1 {
+			label = "fp_id_amber";
+			default-state = "off";
+			gpios = <&gpio0 ASPEED_GPIO(B, 5) GPIO_ACTIVE_HIGH>;
+		};
+
+		led-2 {
+			label = "bmc_ready_noled";
+			default-state = "on";
+			gpios = <&gpio0 ASPEED_GPIO(B, 3) (GPIO_ACTIVE_HIGH|GPIO_TRANSITORY)>;
+		};
+
+		led-3 {
+			label = "power_blue";
+			default-state = "off";
+			gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x80000000>;
+	};
+
+	p1v8_bmc_aux: regulator-p1v8-bmc-aux {
+		compatible = "regulator-fixed";
+		regulator-name = "p1v8_bmc_aux";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	p2v5_bmc_aux: regulator-p2v5-bmc-aux {
+		compatible = "regulator-fixed";
+		regulator-name = "p2v5_bmc_aux";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-always-on;
+	};
+
+	p5v_dac_aux: regulator-p5v-bmc-aux {
+		compatible = "regulator-fixed";
+		regulator-name = "p5v_dac_aux";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	spi1_gpio: spi {
+		compatible = "spi-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sck-gpios = <&gpio0 ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>;
+		mosi-gpios = <&gpio0 ASPEED_GPIO(Z, 4) GPIO_ACTIVE_HIGH>;
+		miso-gpios = <&gpio0 ASPEED_GPIO(Z, 5) GPIO_ACTIVE_HIGH>;
+		cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>;
+		num-chipselects = <1>;
+
+		tpm@0 {
+			compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
+			spi-max-frequency = <33000000>;
+			reg = <0>;
+		};
+	};
+};
+
+&adc0 {
+	vref-supply = <&p1v8_bmc_aux>;
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default
+	&pinctrl_adc2_default &pinctrl_adc3_default
+	&pinctrl_adc4_default &pinctrl_adc5_default
+	&pinctrl_adc6_default &pinctrl_adc7_default>;
+};
+
+&adc1 {
+	vref-supply = <&p2v5_bmc_aux>;
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_adc8_default &pinctrl_adc10_default>;
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&fmc {
+	status = "okay";
+	flash@0 {
+		status = "okay";
+		m25p,fast-read;
+		label = "bmc";
+		spi-max-frequency = <50000000>;
+		#include "openbmc-flash-layout-128.dtsi"
+	};
+	flash@1 {
+		status = "okay";
+		m25p,fast-read;
+		label = "alt-bmc";
+		spi-max-frequency = <50000000>;
+	};
+};
+
+&peci0 {
+	status = "okay";
+};
+
+&gpio0 {
+	gpio-line-names =
+	/*A0-A7*/	"","","","","","","","",
+	/*B0-B7*/	"BATTERY_DETECT","","","BMC_READY_R",
+			"","FM_ID_LED","","",
+	/*C0-C7*/	"","","","","","","","",
+	/*D0-D7*/	"","","","","","","","",
+	/*E0-E7*/	"","","","","","","","",
+	/*F0-F7*/	"","","","","","","","",
+	/*G0-G7*/	"FM_MUX1_SEL_R","","","",
+			"","","","",
+	/*H0-H7*/	"","","","","","","","",
+	/*I0-I7*/	"","","","","","","","",
+	/*J0-J7*/	"","","","","","","","",
+	/*K0-K7*/	"","","","","","","","",
+	/*L0-L7*/	"","","","","","","","",
+	/*M0-M7*/	"","","","","STBY_POWER_PG_3V3","","","",
+	/*N0-N7*/	"LED_POSTCODE_0","LED_POSTCODE_1",
+			"LED_POSTCODE_2","LED_POSTCODE_3",
+			"LED_POSTCODE_4","LED_POSTCODE_5",
+			"LED_POSTCODE_6","LED_POSTCODE_7",
+	/*O0-O7*/	"","","","","","","","debug-card-mux",
+	/*P0-P7*/	"PWR_BTN_BMC_BUF_N","","ID_RST_BTN_BMC_N","",
+			"PWR_LED","","","BMC_HEARTBEAT_N",
+	/*Q0-Q7*/	"","","","","","","","",
+	/*R0-R7*/	"","","","","","","","",
+	/*S0-S7*/	"","","SYS_BMC_PWRBTN_R_N","","","","","",
+	/*T0-T7*/	"","","","","","","","",
+	/*U0-U7*/	"","","","","","","","",
+	/*V0-V7*/	"","","","","","","","",
+	/*W0-W7*/	"","","","","","","","",
+	/*X0-X7*/	"","","","","","","","",
+	/*Y0-Y7*/	"","","","","","","","",
+	/*Z0-Z7*/	"","","","","","","","";
+};
+
+&gpio1 {
+	gpio-line-names =
+	/*18A0-18A7*/	"","","","","","","","",
+	/*18B0-18B7*/	"","","","",
+			"FM_BOARD_BMC_REV_ID0","FM_BOARD_BMC_REV_ID1",
+			"FM_BOARD_BMC_REV_ID2","",
+	/*18C0-18C7*/	"SPI_BMC_BIOS_ROM_IRQ0_R_N","","","","","","","",
+	/*18D0-18D7*/	"","","","","","","","",
+	/*18E0-18E3*/	"FM_BMC_PROT_LS_EN","AC_PWR_BMC_BTN_R_N","","";
+};
+
+&i2c0 {
+	status = "okay";
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c0mux0ch0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			temp-sensor@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+		};
+
+		i2c0mux0ch1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			temp-sensor@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+		};
+
+		i2c0mux0ch2: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		i2c0mux0ch3: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c0mux0ch4: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c0mux0ch5: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+
+			eeprom@56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+		};
+
+		i2c0mux0ch6: i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+
+			eeprom@56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+
+			fan_io_expander0: gpio@20 {
+				compatible = "nxp,pca9555";
+				reg = <0x20>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			fan_io_expander1: gpio@21 {
+				compatible = "nxp,pca9555";
+				reg = <0x21>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			adc@1d {
+				compatible = "ti,adc128d818";
+				reg = <0x1d>;
+				ti,mode = /bits/ 8 <1>;
+			};
+
+			adc@35 {
+				compatible = "maxim,max11617";
+				reg = <0x35>;
+			};
+		};
+
+		i2c0mux0ch7: i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+
+			fanctl0: fan-controller@20 {
+				compatible = "maxim,max31790";
+				reg = <0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				channel@2 {
+					reg = <2>;
+					sensor-type = "TACH";
+				};
+				channel@5 {
+					reg = <5>;
+					sensor-type = "TACH";
+				};
+			};
+
+			fanctl1: fan-controller@23 {
+				compatible = "nuvoton,nct7363";
+				reg = <0x23>;
+				#pwm-cells = <2>;
+
+				fan-9 {
+					pwms = <&fanctl1 0 20000>;
+					tach-ch = /bits/ 8 <0x09>;
+				};
+
+				fan-11 {
+					pwms = <&fanctl1 0 20000>;
+					tach-ch = /bits/ 8 <0x0B>;
+				};
+
+				fan-10 {
+					pwms = <&fanctl1 4 20000>;
+					tach-ch = /bits/ 8 <0x0A>;
+				};
+
+				fan-13 {
+					pwms = <&fanctl1 4 20000>;
+					tach-ch = /bits/ 8 <0x0D>;
+				};
+
+				fan-15 {
+					pwms = <&fanctl1 6 20000>;
+					tach-ch = /bits/ 8 <0x0F>;
+				};
+
+				fan-1 {
+					pwms = <&fanctl1 6 20000>;
+					tach-ch = /bits/ 8 <0x01>;
+				};
+
+				fan-0 {
+					pwms = <&fanctl1 10 20000>;
+					tach-ch = /bits/ 8 <0x00>;
+				};
+
+				fan-3 {
+					pwms = <&fanctl1 10 20000>;
+					tach-ch = /bits/ 8 <0x03>;
+				};
+			};
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c1mux0ch0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			status = "okay";
+		};
+
+		i2c1mux0ch1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			status = "okay";
+		};
+
+		i2c1mux0ch2: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			status = "okay";
+		};
+
+		i2c1mux0ch3: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c1mux0ch4: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c1mux0ch5: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+		};
+
+		i2c1mux0ch6: i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			status = "okay";
+		};
+
+		i2c1mux0ch7: i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c2 {
+	status = "okay";
+	bus-frequency = <400000>;
+};
+
+&i2c3 {
+	status = "okay";
+	bus-frequency = <400000>;
+
+	dac@c {
+		reg = <0x0c>;
+		compatible = "adi,ad5612";
+		vcc-supply = <&p5v_dac_aux>;
+	};
+
+	dac@e {
+		reg = <0x0e>;
+		compatible = "adi,ad5612";
+		vcc-supply = <&p5v_dac_aux>;
+	};
+
+	dac@f {
+		reg = <0x0f>;
+		compatible = "adi,ad5612";
+		vcc-supply = <&p5v_dac_aux>;
+	};
+
+	io_expander6: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&io_expander7>;
+		interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	prsnt_io_expander0: gpio@40 {
+		compatible = "nxp,pca9698";
+		reg = <0x40>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <48 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN1_TRAY1_PRSNT", "CAN1_TRAY2_PRSNT",
+			"CAN1_TRAY3_PRSNT", "CAN1_TRAY4_PRSNT",
+			"CAN1_TRAY5_PRSNT", "CAN1_TRAY6_PRSNT",
+			"CAN1_TRAY7_PRSNT", "CAN1_TRAY8_PRSNT",
+			"CAN1_TRAY9_PRSNT", "CAN1_TRAY10_PRSNT",
+			"CAN1_TRAY11_PRSNT", "CAN1_TRAY12_PRSNT",
+			"CAN1_TRAY13_PRSNT", "CAN1_TRAY14_PRSNT",
+			"CAN1_TRAY15_PRSNT", "CAN1_TRAY16_PRSNT",
+			"CAN1_TRAY17_PRSNT", "CAN1_TRAY18_PRSNT",
+			"CAN1_TRAY19_PRSNT", "CAN1_TRAY20_PRSNT",
+			"CAN1_TRAY21_PRSNT", "CAN1_TRAY22_PRSNT",
+			"CAN1_TRAY23_PRSNT", "CAN1_TRAY24_PRSNT",
+			"CAN1_TRAY25_PRSNT", "CAN1_TRAY26_PRSNT",
+			"CAN1_TRAY27_PRSNT", "CAN1_TRAY28_PRSNT",
+			"CAN1_TRAY29_PRSNT", "CAN1_TRAY30_PRSNT",
+			"CAN1_TRAY31_PRSNT", "CAN1_TRAY32_PRSNT",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	prsnt_io_expander1: gpio@41 {
+		compatible = "nxp,pca9698";
+		reg = <0x41>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <56 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN2_TRAY1_PRSNT", "CAN2_TRAY2_PRSNT",
+			"CAN2_TRAY3_PRSNT", "CAN2_TRAY4_PRSNT",
+			"CAN2_TRAY5_PRSNT", "CAN2_TRAY6_PRSNT",
+			"CAN2_TRAY7_PRSNT", "CAN2_TRAY8_PRSNT",
+			"CAN2_TRAY9_PRSNT", "CAN2_TRAY10_PRSNT",
+			"CAN2_TRAY11_PRSNT", "CAN2_TRAY12_PRSNT",
+			"CAN2_TRAY13_PRSNT", "CAN2_TRAY14_PRSNT",
+			"CAN2_TRAY15_PRSNT", "CAN2_TRAY16_PRSNT",
+			"CAN2_TRAY17_PRSNT", "CAN2_TRAY18_PRSNT",
+			"CAN2_TRAY19_PRSNT", "CAN2_TRAY20_PRSNT",
+			"CAN2_TRAY21_PRSNT", "CAN2_TRAY22_PRSNT",
+			"CAN2_TRAY23_PRSNT", "CAN2_TRAY24_PRSNT",
+			"CAN2_TRAY25_PRSNT", "CAN2_TRAY26_PRSNT",
+			"CAN2_TRAY27_PRSNT", "CAN2_TRAY28_PRSNT",
+			"CAN2_TRAY29_PRSNT", "CAN2_TRAY30_PRSNT",
+			"CAN2_TRAY31_PRSNT", "CAN2_TRAY32_PRSNT",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	prsnt_io_expander2: gpio@42 {
+		compatible = "nxp,pca9698";
+		reg = <0x42>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <64 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN3_TRAY1_PRSNT", "CAN3_TRAY2_PRSNT",
+			"CAN3_TRAY3_PRSNT", "CAN3_TRAY4_PRSNT",
+			"CAN3_TRAY5_PRSNT", "CAN3_TRAY6_PRSNT",
+			"CAN3_TRAY7_PRSNT", "CAN3_TRAY8_PRSNT",
+			"CAN3_TRAY9_PRSNT", "CAN3_TRAY10_PRSNT",
+			"CAN3_TRAY11_PRSNT", "CAN3_TRAY12_PRSNT",
+			"CAN3_TRAY13_PRSNT", "CAN3_TRAY14_PRSNT",
+			"CAN3_TRAY15_PRSNT", "CAN3_TRAY16_PRSNT",
+			"CAN3_TRAY17_PRSNT", "CAN3_TRAY18_PRSNT",
+			"CAN3_TRAY19_PRSNT", "CAN3_TRAY20_PRSNT",
+			"CAN3_TRAY21_PRSNT", "CAN3_TRAY22_PRSNT",
+			"CAN3_TRAY23_PRSNT", "CAN3_TRAY24_PRSNT",
+			"CAN3_TRAY25_PRSNT", "CAN3_TRAY26_PRSNT",
+			"CAN3_TRAY27_PRSNT", "CAN3_TRAY28_PRSNT",
+			"CAN3_TRAY29_PRSNT", "CAN3_TRAY30_PRSNT",
+			"CAN3_TRAY31_PRSNT", "CAN3_TRAY32_PRSNT",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	prsnt_io_expander3: gpio@43 {
+		compatible = "nxp,pca9698";
+		reg = <0x43>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <72 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN4_TRAY1_PRSNT", "CAN4_TRAY2_PRSNT",
+			"CAN4_TRAY3_PRSNT", "CAN4_TRAY4_PRSNT",
+			"CAN4_TRAY5_PRSNT", "CAN4_TRAY6_PRSNT",
+			"CAN4_TRAY7_PRSNT", "CAN4_TRAY8_PRSNT",
+			"CAN4_TRAY9_PRSNT", "CAN4_TRAY10_PRSNT",
+			"CAN4_TRAY11_PRSNT", "CAN4_TRAY12_PRSNT",
+			"CAN4_TRAY13_PRSNT", "CAN4_TRAY14_PRSNT",
+			"CAN4_TRAY15_PRSNT", "CAN4_TRAY16_PRSNT",
+			"CAN4_TRAY17_PRSNT", "CAN4_TRAY18_PRSNT",
+			"CAN4_TRAY19_PRSNT", "CAN4_TRAY20_PRSNT",
+			"CAN4_TRAY21_PRSNT", "CAN4_TRAY22_PRSNT",
+			"CAN4_TRAY23_PRSNT", "CAN4_TRAY24_PRSNT",
+			"CAN4_TRAY25_PRSNT", "CAN4_TRAY26_PRSNT",
+			"CAN4_TRAY27_PRSNT", "CAN4_TRAY28_PRSNT",
+			"CAN4_TRAY29_PRSNT", "CAN4_TRAY30_PRSNT",
+			"CAN4_TRAY31_PRSNT", "CAN4_TRAY32_PRSNT",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	prsnt_io_expander4: gpio@44 {
+		compatible = "nxp,pca9698";
+		reg = <0x44>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <80 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN5_TRAY1_PRSNT", "CAN5_TRAY2_PRSNT",
+			"CAN5_TRAY3_PRSNT", "CAN5_TRAY4_PRSNT",
+			"CAN5_TRAY5_PRSNT", "CAN5_TRAY6_PRSNT",
+			"CAN5_TRAY7_PRSNT", "CAN5_TRAY8_PRSNT",
+			"CAN5_TRAY9_PRSNT", "CAN5_TRAY10_PRSNT",
+			"CAN5_TRAY11_PRSNT", "CAN5_TRAY12_PRSNT",
+			"CAN5_TRAY13_PRSNT", "CAN5_TRAY14_PRSNT",
+			"CAN5_TRAY15_PRSNT", "CAN5_TRAY16_PRSNT",
+			"CAN5_TRAY17_PRSNT", "CAN5_TRAY18_PRSNT",
+			"CAN5_TRAY19_PRSNT", "CAN5_TRAY20_PRSNT",
+			"CAN5_TRAY21_PRSNT", "CAN5_TRAY22_PRSNT",
+			"CAN5_TRAY23_PRSNT", "CAN5_TRAY24_PRSNT",
+			"CAN5_TRAY25_PRSNT", "CAN5_TRAY26_PRSNT",
+			"CAN5_TRAY27_PRSNT", "CAN5_TRAY28_PRSNT",
+			"CAN5_TRAY29_PRSNT", "CAN5_TRAY30_PRSNT",
+			"CAN5_TRAY31_PRSNT", "CAN5_TRAY32_PRSNT",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	prsnt_io_expander5: gpio@45 {
+		compatible = "nxp,pca9698";
+		reg = <0x45>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <88 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN6_TRAY1_PRSNT", "CAN6_TRAY2_PRSNT",
+			"CAN6_TRAY3_PRSNT", "CAN6_TRAY4_PRSNT",
+			"CAN6_TRAY5_PRSNT", "CAN6_TRAY6_PRSNT",
+			"CAN6_TRAY7_PRSNT", "CAN6_TRAY8_PRSNT",
+			"CAN6_TRAY9_PRSNT", "CAN6_TRAY10_PRSNT",
+			"CAN6_TRAY11_PRSNT", "CAN6_TRAY12_PRSNT",
+			"CAN6_TRAY13_PRSNT", "CAN6_TRAY14_PRSNT",
+			"CAN6_TRAY15_PRSNT", "CAN6_TRAY16_PRSNT",
+			"CAN6_TRAY17_PRSNT", "CAN6_TRAY18_PRSNT",
+			"CAN6_TRAY19_PRSNT", "CAN6_TRAY20_PRSNT",
+			"CAN6_TRAY21_PRSNT", "CAN6_TRAY22_PRSNT",
+			"CAN6_TRAY23_PRSNT", "CAN6_TRAY24_PRSNT",
+			"CAN6_TRAY25_PRSNT", "CAN6_TRAY26_PRSNT",
+			"CAN6_TRAY27_PRSNT", "CAN6_TRAY28_PRSNT",
+			"CAN6_TRAY29_PRSNT", "CAN6_TRAY30_PRSNT",
+			"CAN6_TRAY31_PRSNT", "CAN6_TRAY32_PRSNT",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	prsnt_io_expander6: gpio@46 {
+		compatible = "nxp,pca9698";
+		reg = <0x46>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <96 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN7_TRAY1_PRSNT", "CAN7_TRAY2_PRSNT",
+			"CAN7_TRAY3_PRSNT", "CAN7_TRAY4_PRSNT",
+			"CAN7_TRAY5_PRSNT", "CAN7_TRAY6_PRSNT",
+			"CAN7_TRAY7_PRSNT", "CAN7_TRAY8_PRSNT",
+			"CAN7_TRAY9_PRSNT", "CAN7_TRAY10_PRSNT",
+			"CAN7_TRAY11_PRSNT", "CAN7_TRAY12_PRSNT",
+			"CAN7_TRAY13_PRSNT", "CAN7_TRAY14_PRSNT",
+			"CAN7_TRAY15_PRSNT", "CAN7_TRAY16_PRSNT",
+			"CAN7_TRAY17_PRSNT", "CAN7_TRAY18_PRSNT",
+			"CAN7_TRAY19_PRSNT", "CAN7_TRAY20_PRSNT",
+			"CAN7_TRAY21_PRSNT", "CAN7_TRAY22_PRSNT",
+			"CAN7_TRAY23_PRSNT", "CAN7_TRAY24_PRSNT",
+			"CAN7_TRAY25_PRSNT", "CAN7_TRAY26_PRSNT",
+			"CAN7_TRAY27_PRSNT", "CAN7_TRAY28_PRSNT",
+			"CAN7_TRAY29_PRSNT", "CAN7_TRAY30_PRSNT",
+			"CAN7_TRAY31_PRSNT", "CAN7_TRAY32_PRSNT",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	prsnt_io_expander7: gpio@47 {
+		compatible = "nxp,pca9698";
+		reg = <0x47>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <104 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN8_TRAY1_PRSNT", "CAN8_TRAY2_PRSNT",
+			"CAN8_TRAY3_PRSNT", "CAN8_TRAY4_PRSNT",
+			"CAN8_TRAY5_PRSNT", "CAN8_TRAY6_PRSNT",
+			"CAN8_TRAY7_PRSNT", "CAN8_TRAY8_PRSNT",
+			"CAN8_TRAY9_PRSNT", "CAN8_TRAY10_PRSNT",
+			"CAN8_TRAY11_PRSNT", "CAN8_TRAY12_PRSNT",
+			"CAN8_TRAY13_PRSNT", "CAN8_TRAY14_PRSNT",
+			"CAN8_TRAY15_PRSNT", "CAN8_TRAY16_PRSNT",
+			"CAN8_TRAY17_PRSNT", "CAN8_TRAY18_PRSNT",
+			"CAN8_TRAY19_PRSNT", "CAN8_TRAY20_PRSNT",
+			"CAN8_TRAY21_PRSNT", "CAN8_TRAY22_PRSNT",
+			"CAN8_TRAY23_PRSNT", "CAN8_TRAY24_PRSNT",
+			"CAN8_TRAY25_PRSNT", "CAN8_TRAY26_PRSNT",
+			"CAN8_TRAY27_PRSNT", "CAN8_TRAY28_PRSNT",
+			"CAN8_TRAY29_PRSNT", "CAN8_TRAY30_PRSNT",
+			"CAN8_TRAY31_PRSNT", "CAN8_TRAY32_PRSNT",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	pwrgd_io_expander0: gpio@48 {
+		compatible = "nxp,pca9698";
+		reg = <0x48>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <50 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN1_TRAY1_PWRGD", "CAN1_TRAY2_PWRGD",
+			"CAN1_TRAY3_PWRGD", "CAN1_TRAY4_PWRGD",
+			"CAN1_TRAY5_PWRGD", "CAN1_TRAY6_PWRGD",
+			"CAN1_TRAY7_PWRGD", "CAN1_TRAY8_PWRGD",
+			"CAN1_TRAY9_PWRGD", "CAN1_TRAY10_PWRGD",
+			"CAN1_TRAY11_PWRGD", "CAN1_TRAY12_PWRGD",
+			"CAN1_TRAY13_PWRGD", "CAN1_TRAY14_PWRGD",
+			"CAN1_TRAY15_PWRGD", "CAN1_TRAY16_PWRGD",
+			"CAN1_TRAY17_PWRGD", "CAN1_TRAY18_PWRGD",
+			"CAN1_TRAY19_PWRGD", "CAN1_TRAY20_PWRGD",
+			"CAN1_TRAY21_PWRGD", "CAN1_TRAY22_PWRGD",
+			"CAN1_TRAY23_PWRGD", "CAN1_TRAY24_PWRGD",
+			"CAN1_TRAY25_PWRGD", "CAN1_TRAY26_PWRGD",
+			"CAN1_TRAY27_PWRGD", "CAN1_TRAY28_PWRGD",
+			"CAN1_TRAY29_PWRGD", "CAN1_TRAY30_PWRGD",
+			"CAN1_TRAY31_PWRGD", "CAN1_TRAY32_PWRGD",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	pwrgd_io_expander1: gpio@49 {
+		compatible = "nxp,pca9698";
+		reg = <0x49>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <58 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN2_TRAY1_PWRGD", "CAN2_TRAY2_PWRGD",
+			"CAN2_TRAY3_PWRGD", "CAN2_TRAY4_PWRGD",
+			"CAN2_TRAY5_PWRGD", "CAN2_TRAY6_PWRGD",
+			"CAN2_TRAY7_PWRGD", "CAN2_TRAY8_PWRGD",
+			"CAN2_TRAY9_PWRGD", "CAN2_TRAY10_PWRGD",
+			"CAN2_TRAY11_PWRGD", "CAN2_TRAY12_PWRGD",
+			"CAN2_TRAY13_PWRGD", "CAN2_TRAY14_PWRGD",
+			"CAN2_TRAY15_PWRGD", "CAN2_TRAY16_PWRGD",
+			"CAN2_TRAY17_PWRGD", "CAN2_TRAY18_PWRGD",
+			"CAN2_TRAY19_PWRGD", "CAN2_TRAY20_PWRGD",
+			"CAN2_TRAY21_PWRGD", "CAN2_TRAY22_PWRGD",
+			"CAN2_TRAY23_PWRGD", "CAN2_TRAY24_PWRGD",
+			"CAN2_TRAY25_PWRGD", "CAN2_TRAY26_PWRGD",
+			"CAN2_TRAY27_PWRGD", "CAN2_TRAY28_PWRGD",
+			"CAN2_TRAY29_PWRGD", "CAN2_TRAY30_PWRGD",
+			"CAN2_TRAY31_PWRGD", "CAN2_TRAY32_PWRGD",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	pwrgd_io_expander2: gpio@4a {
+		compatible = "nxp,pca9698";
+		reg = <0x4a>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <66 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN3_TRAY1_PWRGD", "CAN3_TRAY2_PWRGD",
+			"CAN3_TRAY3_PWRGD", "CAN3_TRAY4_PWRGD",
+			"CAN3_TRAY5_PWRGD", "CAN3_TRAY6_PWRGD",
+			"CAN3_TRAY7_PWRGD", "CAN3_TRAY8_PWRGD",
+			"CAN3_TRAY9_PWRGD", "CAN3_TRAY10_PWRGD",
+			"CAN3_TRAY11_PWRGD", "CAN3_TRAY12_PWRGD",
+			"CAN3_TRAY13_PWRGD", "CAN3_TRAY14_PWRGD",
+			"CAN3_TRAY15_PWRGD", "CAN3_TRAY16_PWRGD",
+			"CAN3_TRAY17_PWRGD", "CAN3_TRAY18_PWRGD",
+			"CAN3_TRAY19_PWRGD", "CAN3_TRAY20_PWRGD",
+			"CAN3_TRAY21_PWRGD", "CAN3_TRAY22_PWRGD",
+			"CAN3_TRAY23_PWRGD", "CAN3_TRAY24_PWRGD",
+			"CAN3_TRAY25_PWRGD", "CAN3_TRAY26_PWRGD",
+			"CAN3_TRAY27_PWRGD", "CAN3_TRAY28_PWRGD",
+			"CAN3_TRAY29_PWRGD", "CAN3_TRAY30_PWRGD",
+			"CAN3_TRAY31_PWRGD", "CAN3_TRAY32_PWRGD",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	pwrgd_io_expander3: gpio@4b {
+		compatible = "nxp,pca9698";
+		reg = <0x4b>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <74 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN4_TRAY1_PWRGD", "CAN4_TRAY2_PWRGD",
+			"CAN4_TRAY3_PWRGD", "CAN4_TRAY4_PWRGD",
+			"CAN4_TRAY5_PWRGD", "CAN4_TRAY6_PWRGD",
+			"CAN4_TRAY7_PWRGD", "CAN4_TRAY8_PWRGD",
+			"CAN4_TRAY9_PWRGD", "CAN4_TRAY10_PWRGD",
+			"CAN4_TRAY11_PWRGD", "CAN4_TRAY12_PWRGD",
+			"CAN4_TRAY13_PWRGD", "CAN4_TRAY14_PWRGD",
+			"CAN4_TRAY15_PWRGD", "CAN4_TRAY16_PWRGD",
+			"CAN4_TRAY17_PWRGD", "CAN4_TRAY18_PWRGD",
+			"CAN4_TRAY19_PWRGD", "CAN4_TRAY20_PWRGD",
+			"CAN4_TRAY21_PWRGD", "CAN4_TRAY22_PWRGD",
+			"CAN4_TRAY23_PWRGD", "CAN4_TRAY24_PWRGD",
+			"CAN4_TRAY25_PWRGD", "CAN4_TRAY26_PWRGD",
+			"CAN4_TRAY27_PWRGD", "CAN4_TRAY28_PWRGD",
+			"CAN4_TRAY29_PWRGD", "CAN4_TRAY30_PWRGD",
+			"CAN4_TRAY31_PWRGD", "CAN4_TRAY32_PWRGD",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	pwrgd_io_expander4: gpio@4c {
+		compatible = "nxp,pca9698";
+		reg = <0x4c>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <82 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN5_TRAY1_PWRGD", "CAN5_TRAY2_PWRGD",
+			"CAN5_TRAY3_PWRGD", "CAN5_TRAY4_PWRGD",
+			"CAN5_TRAY5_PWRGD", "CAN5_TRAY6_PWRGD",
+			"CAN5_TRAY7_PWRGD", "CAN5_TRAY8_PWRGD",
+			"CAN5_TRAY9_PWRGD", "CAN5_TRAY10_PWRGD",
+			"CAN5_TRAY11_PWRGD", "CAN5_TRAY12_PWRGD",
+			"CAN5_TRAY13_PWRGD", "CAN5_TRAY14_PWRGD",
+			"CAN5_TRAY15_PWRGD", "CAN5_TRAY16_PWRGD",
+			"CAN5_TRAY17_PWRGD", "CAN5_TRAY18_PWRGD",
+			"CAN5_TRAY19_PWRGD", "CAN5_TRAY20_PWRGD",
+			"CAN5_TRAY21_PWRGD", "CAN5_TRAY22_PWRGD",
+			"CAN5_TRAY23_PWRGD", "CAN5_TRAY24_PWRGD",
+			"CAN5_TRAY25_PWRGD", "CAN5_TRAY26_PWRGD",
+			"CAN5_TRAY27_PWRGD", "CAN5_TRAY28_PWRGD",
+			"CAN5_TRAY29_PWRGD", "CAN5_TRAY30_PWRGD",
+			"CAN5_TRAY31_PWRGD", "CAN5_TRAY32_PWRGD",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	pwrgd_io_expander5: gpio@4d {
+		compatible = "nxp,pca9698";
+		reg = <0x4d>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <90 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN6_TRAY1_PWRGD", "CAN6_TRAY2_PWRGD",
+			"CAN6_TRAY3_PWRGD", "CAN6_TRAY4_PWRGD",
+			"CAN6_TRAY5_PWRGD", "CAN6_TRAY6_PWRGD",
+			"CAN6_TRAY7_PWRGD", "CAN6_TRAY8_PWRGD",
+			"CAN6_TRAY9_PWRGD", "CAN6_TRAY10_PWRGD",
+			"CAN6_TRAY11_PWRGD", "CAN6_TRAY12_PWRGD",
+			"CAN6_TRAY13_PWRGD", "CAN6_TRAY14_PWRGD",
+			"CAN6_TRAY15_PWRGD", "CAN6_TRAY16_PWRGD",
+			"CAN6_TRAY17_PWRGD", "CAN6_TRAY18_PWRGD",
+			"CAN6_TRAY19_PWRGD", "CAN6_TRAY20_PWRGD",
+			"CAN6_TRAY21_PWRGD", "CAN6_TRAY22_PWRGD",
+			"CAN6_TRAY23_PWRGD", "CAN6_TRAY24_PWRGD",
+			"CAN6_TRAY25_PWRGD", "CAN6_TRAY26_PWRGD",
+			"CAN6_TRAY27_PWRGD", "CAN6_TRAY28_PWRGD",
+			"CAN6_TRAY29_PWRGD", "CAN6_TRAY30_PWRGD",
+			"CAN6_TRAY31_PWRGD", "CAN6_TRAY32_PWRGD",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	pwrgd_io_expander6: gpio@4e {
+		compatible = "nxp,pca9698";
+		reg = <0x4e>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <98 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN7_TRAY1_PWRGD", "CAN7_TRAY2_PWRGD",
+			"CAN7_TRAY3_PWRGD", "CAN7_TRAY4_PWRGD",
+			"CAN7_TRAY5_PWRGD", "CAN7_TRAY6_PWRGD",
+			"CAN7_TRAY7_PWRGD", "CAN7_TRAY8_PWRGD",
+			"CAN7_TRAY9_PWRGD", "CAN7_TRAY10_PWRGD",
+			"CAN7_TRAY11_PWRGD", "CAN7_TRAY12_PWRGD",
+			"CAN7_TRAY13_PWRGD", "CAN7_TRAY14_PWRGD",
+			"CAN7_TRAY15_PWRGD", "CAN7_TRAY16_PWRGD",
+			"CAN7_TRAY17_PWRGD", "CAN7_TRAY18_PWRGD",
+			"CAN7_TRAY19_PWRGD", "CAN7_TRAY20_PWRGD",
+			"CAN7_TRAY21_PWRGD", "CAN7_TRAY22_PWRGD",
+			"CAN7_TRAY23_PWRGD", "CAN7_TRAY24_PWRGD",
+			"CAN7_TRAY25_PWRGD", "CAN7_TRAY26_PWRGD",
+			"CAN7_TRAY27_PWRGD", "CAN7_TRAY28_PWRGD",
+			"CAN7_TRAY29_PWRGD", "CAN7_TRAY30_PWRGD",
+			"CAN7_TRAY31_PWRGD", "CAN7_TRAY32_PWRGD",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	pwrgd_io_expander7: gpio@4f {
+		compatible = "nxp,pca9698";
+		reg = <0x4f>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <106 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN8_TRAY1_PWRGD", "CAN8_TRAY2_PWRGD",
+			"CAN8_TRAY3_PWRGD", "CAN8_TRAY4_PWRGD",
+			"CAN8_TRAY5_PWRGD", "CAN8_TRAY6_PWRGD",
+			"CAN8_TRAY7_PWRGD", "CAN8_TRAY8_PWRGD",
+			"CAN8_TRAY9_PWRGD", "CAN8_TRAY10_PWRGD",
+			"CAN8_TRAY11_PWRGD", "CAN8_TRAY12_PWRGD",
+			"CAN8_TRAY13_PWRGD", "CAN8_TRAY14_PWRGD",
+			"CAN8_TRAY15_PWRGD", "CAN8_TRAY16_PWRGD",
+			"CAN8_TRAY17_PWRGD", "CAN8_TRAY18_PWRGD",
+			"CAN8_TRAY19_PWRGD", "CAN8_TRAY20_PWRGD",
+			"CAN8_TRAY21_PWRGD", "CAN8_TRAY22_PWRGD",
+			"CAN8_TRAY23_PWRGD", "CAN8_TRAY24_PWRGD",
+			"CAN8_TRAY25_PWRGD", "CAN8_TRAY26_PWRGD",
+			"CAN8_TRAY27_PWRGD", "CAN8_TRAY28_PWRGD",
+			"CAN8_TRAY29_PWRGD", "CAN8_TRAY30_PWRGD",
+			"CAN8_TRAY31_PWRGD", "CAN8_TRAY32_PWRGD",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	large_leak_io_expander0: gpio@50 {
+		compatible = "nxp,pca9698";
+		reg = <0x50>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <54 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN1_TRAY1_LARGE_LEAK", "CAN1_TRAY2_LARGE_LEAK",
+			"CAN1_TRAY3_LARGE_LEAK", "CAN1_TRAY4_LARGE_LEAK",
+			"CAN1_TRAY5_LARGE_LEAK", "CAN1_TRAY6_LARGE_LEAK",
+			"CAN1_TRAY7_LARGE_LEAK", "CAN1_TRAY8_LARGE_LEAK",
+			"CAN1_TRAY9_LARGE_LEAK", "CAN1_TRAY10_LARGE_LEAK",
+			"CAN1_TRAY11_LARGE_LEAK", "CAN1_TRAY12_LARGE_LEAK",
+			"CAN1_TRAY13_LARGE_LEAK", "CAN1_TRAY14_LARGE_LEAK",
+			"CAN1_TRAY15_LARGE_LEAK", "CAN1_TRAY16_LARGE_LEAK",
+			"CAN1_TRAY17_LARGE_LEAK", "CAN1_TRAY18_LARGE_LEAK",
+			"CAN1_TRAY19_LARGE_LEAK", "CAN1_TRAY20_LARGE_LEAK",
+			"CAN1_TRAY21_LARGE_LEAK", "CAN1_TRAY22_LARGE_LEAK",
+			"CAN1_TRAY23_LARGE_LEAK", "CAN1_TRAY24_LARGE_LEAK",
+			"CAN1_TRAY25_LARGE_LEAK", "CAN1_TRAY26_LARGE_LEAK",
+			"CAN1_TRAY27_LARGE_LEAK", "CAN1_TRAY28_LARGE_LEAK",
+			"CAN1_TRAY29_LARGE_LEAK", "CAN1_TRAY30_LARGE_LEAK",
+			"CAN1_TRAY31_LARGE_LEAK", "CAN1_TRAY32_LARGE_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	large_leak_io_expander1: gpio@51 {
+		compatible = "nxp,pca9698";
+		reg = <0x51>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <62 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN2_TRAY1_LARGE_LEAK", "CAN2_TRAY2_LARGE_LEAK",
+			"CAN2_TRAY3_LARGE_LEAK", "CAN2_TRAY4_LARGE_LEAK",
+			"CAN2_TRAY5_LARGE_LEAK", "CAN2_TRAY6_LARGE_LEAK",
+			"CAN2_TRAY7_LARGE_LEAK", "CAN2_TRAY8_LARGE_LEAK",
+			"CAN2_TRAY9_LARGE_LEAK", "CAN2_TRAY10_LARGE_LEAK",
+			"CAN2_TRAY11_LARGE_LEAK", "CAN2_TRAY12_LARGE_LEAK",
+			"CAN2_TRAY13_LARGE_LEAK", "CAN2_TRAY14_LARGE_LEAK",
+			"CAN2_TRAY15_LARGE_LEAK", "CAN2_TRAY16_LARGE_LEAK",
+			"CAN2_TRAY17_LARGE_LEAK", "CAN2_TRAY18_LARGE_LEAK",
+			"CAN2_TRAY19_LARGE_LEAK", "CAN2_TRAY20_LARGE_LEAK",
+			"CAN2_TRAY21_LARGE_LEAK", "CAN2_TRAY22_LARGE_LEAK",
+			"CAN2_TRAY23_LARGE_LEAK", "CAN2_TRAY24_LARGE_LEAK",
+			"CAN2_TRAY25_LARGE_LEAK", "CAN2_TRAY26_LARGE_LEAK",
+			"CAN2_TRAY27_LARGE_LEAK", "CAN2_TRAY28_LARGE_LEAK",
+			"CAN2_TRAY29_LARGE_LEAK", "CAN2_TRAY30_LARGE_LEAK",
+			"CAN2_TRAY31_LARGE_LEAK", "CAN2_TRAY32_LARGE_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	large_leak_io_expander2: gpio@52 {
+		compatible = "nxp,pca9698";
+		reg = <0x52>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <70 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN3_TRAY1_LARGE_LEAK", "CAN3_TRAY2_LARGE_LEAK",
+			"CAN3_TRAY3_LARGE_LEAK", "CAN3_TRAY4_LARGE_LEAK",
+			"CAN3_TRAY5_LARGE_LEAK", "CAN3_TRAY6_LARGE_LEAK",
+			"CAN3_TRAY7_LARGE_LEAK", "CAN3_TRAY8_LARGE_LEAK",
+			"CAN3_TRAY9_LARGE_LEAK", "CAN3_TRAY10_LARGE_LEAK",
+			"CAN3_TRAY11_LARGE_LEAK", "CAN3_TRAY12_LARGE_LEAK",
+			"CAN3_TRAY13_LARGE_LEAK", "CAN3_TRAY14_LARGE_LEAK",
+			"CAN3_TRAY15_LARGE_LEAK", "CAN3_TRAY16_LARGE_LEAK",
+			"CAN3_TRAY17_LARGE_LEAK", "CAN3_TRAY18_LARGE_LEAK",
+			"CAN3_TRAY19_LARGE_LEAK", "CAN3_TRAY20_LARGE_LEAK",
+			"CAN3_TRAY21_LARGE_LEAK", "CAN3_TRAY22_LARGE_LEAK",
+			"CAN3_TRAY23_LARGE_LEAK", "CAN3_TRAY24_LARGE_LEAK",
+			"CAN3_TRAY25_LARGE_LEAK", "CAN3_TRAY26_LARGE_LEAK",
+			"CAN3_TRAY27_LARGE_LEAK", "CAN3_TRAY28_LARGE_LEAK",
+			"CAN3_TRAY29_LARGE_LEAK", "CAN3_TRAY30_LARGE_LEAK",
+			"CAN3_TRAY31_LARGE_LEAK", "CAN3_TRAY32_LARGE_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	large_leak_io_expander3: gpio@53 {
+		compatible = "nxp,pca9698";
+		reg = <0x53>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <78 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN4_TRAY1_LARGE_LEAK", "CAN4_TRAY2_LARGE_LEAK",
+			"CAN4_TRAY3_LARGE_LEAK", "CAN4_TRAY4_LARGE_LEAK",
+			"CAN4_TRAY5_LARGE_LEAK", "CAN4_TRAY6_LARGE_LEAK",
+			"CAN4_TRAY7_LARGE_LEAK", "CAN4_TRAY8_LARGE_LEAK",
+			"CAN4_TRAY9_LARGE_LEAK", "CAN4_TRAY10_LARGE_LEAK",
+			"CAN4_TRAY11_LARGE_LEAK", "CAN4_TRAY12_LARGE_LEAK",
+			"CAN4_TRAY13_LARGE_LEAK", "CAN4_TRAY14_LARGE_LEAK",
+			"CAN4_TRAY15_LARGE_LEAK", "CAN4_TRAY16_LARGE_LEAK",
+			"CAN4_TRAY17_LARGE_LEAK", "CAN4_TRAY18_LARGE_LEAK",
+			"CAN4_TRAY19_LARGE_LEAK", "CAN4_TRAY20_LARGE_LEAK",
+			"CAN4_TRAY21_LARGE_LEAK", "CAN4_TRAY22_LARGE_LEAK",
+			"CAN4_TRAY23_LARGE_LEAK", "CAN4_TRAY24_LARGE_LEAK",
+			"CAN4_TRAY25_LARGE_LEAK", "CAN4_TRAY26_LARGE_LEAK",
+			"CAN4_TRAY27_LARGE_LEAK", "CAN4_TRAY28_LARGE_LEAK",
+			"CAN4_TRAY29_LARGE_LEAK", "CAN4_TRAY30_LARGE_LEAK",
+			"CAN4_TRAY31_LARGE_LEAK", "CAN4_TRAY32_LARGE_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	large_leak_io_expander4: gpio@54 {
+		compatible = "nxp,pca9698";
+		reg = <0x54>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <86 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN5_TRAY1_LARGE_LEAK", "CAN5_TRAY2_LARGE_LEAK",
+			"CAN5_TRAY3_LARGE_LEAK", "CAN5_TRAY4_LARGE_LEAK",
+			"CAN5_TRAY5_LARGE_LEAK", "CAN5_TRAY6_LARGE_LEAK",
+			"CAN5_TRAY7_LARGE_LEAK", "CAN5_TRAY8_LARGE_LEAK",
+			"CAN5_TRAY9_LARGE_LEAK", "CAN5_TRAY10_LARGE_LEAK",
+			"CAN5_TRAY11_LARGE_LEAK", "CAN5_TRAY12_LARGE_LEAK",
+			"CAN5_TRAY13_LARGE_LEAK", "CAN5_TRAY14_LARGE_LEAK",
+			"CAN5_TRAY15_LARGE_LEAK", "CAN5_TRAY16_LARGE_LEAK",
+			"CAN5_TRAY17_LARGE_LEAK", "CAN5_TRAY18_LARGE_LEAK",
+			"CAN5_TRAY19_LARGE_LEAK", "CAN5_TRAY20_LARGE_LEAK",
+			"CAN5_TRAY21_LARGE_LEAK", "CAN5_TRAY22_LARGE_LEAK",
+			"CAN5_TRAY23_LARGE_LEAK", "CAN5_TRAY24_LARGE_LEAK",
+			"CAN5_TRAY25_LARGE_LEAK", "CAN5_TRAY26_LARGE_LEAK",
+			"CAN5_TRAY27_LARGE_LEAK", "CAN5_TRAY28_LARGE_LEAK",
+			"CAN5_TRAY29_LARGE_LEAK", "CAN5_TRAY30_LARGE_LEAK",
+			"CAN5_TRAY31_LARGE_LEAK", "CAN5_TRAY32_LARGE_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	large_leak_io_expander5: gpio@55 {
+		compatible = "nxp,pca9698";
+		reg = <0x55>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <94 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN6_TRAY1_LARGE_LEAK", "CAN6_TRAY2_LARGE_LEAK",
+			"CAN6_TRAY3_LARGE_LEAK", "CAN6_TRAY4_LARGE_LEAK",
+			"CAN6_TRAY5_LARGE_LEAK", "CAN6_TRAY6_LARGE_LEAK",
+			"CAN6_TRAY7_LARGE_LEAK", "CAN6_TRAY8_LARGE_LEAK",
+			"CAN6_TRAY9_LARGE_LEAK", "CAN6_TRAY10_LARGE_LEAK",
+			"CAN6_TRAY11_LARGE_LEAK", "CAN6_TRAY12_LARGE_LEAK",
+			"CAN6_TRAY13_LARGE_LEAK", "CAN6_TRAY14_LARGE_LEAK",
+			"CAN6_TRAY15_LARGE_LEAK", "CAN6_TRAY16_LARGE_LEAK",
+			"CAN6_TRAY17_LARGE_LEAK", "CAN6_TRAY18_LARGE_LEAK",
+			"CAN6_TRAY19_LARGE_LEAK", "CAN6_TRAY20_LARGE_LEAK",
+			"CAN6_TRAY21_LARGE_LEAK", "CAN6_TRAY22_LARGE_LEAK",
+			"CAN6_TRAY23_LARGE_LEAK", "CAN6_TRAY24_LARGE_LEAK",
+			"CAN6_TRAY25_LARGE_LEAK", "CAN6_TRAY26_LARGE_LEAK",
+			"CAN6_TRAY27_LARGE_LEAK", "CAN6_TRAY28_LARGE_LEAK",
+			"CAN6_TRAY29_LARGE_LEAK", "CAN6_TRAY30_LARGE_LEAK",
+			"CAN6_TRAY31_LARGE_LEAK", "CAN6_TRAY32_LARGE_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	large_leak_io_expander6: gpio@56 {
+		compatible = "nxp,pca9698";
+		reg = <0x56>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <102 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN7_TRAY1_LARGE_LEAK", "CAN7_TRAY2_LARGE_LEAK",
+			"CAN7_TRAY3_LARGE_LEAK", "CAN7_TRAY4_LARGE_LEAK",
+			"CAN7_TRAY5_LARGE_LEAK", "CAN7_TRAY6_LARGE_LEAK",
+			"CAN7_TRAY7_LARGE_LEAK", "CAN7_TRAY8_LARGE_LEAK",
+			"CAN7_TRAY9_LARGE_LEAK", "CAN7_TRAY10_LARGE_LEAK",
+			"CAN7_TRAY11_LARGE_LEAK", "CAN7_TRAY12_LARGE_LEAK",
+			"CAN7_TRAY13_LARGE_LEAK", "CAN7_TRAY14_LARGE_LEAK",
+			"CAN7_TRAY15_LARGE_LEAK", "CAN7_TRAY16_LARGE_LEAK",
+			"CAN7_TRAY17_LARGE_LEAK", "CAN7_TRAY18_LARGE_LEAK",
+			"CAN7_TRAY19_LARGE_LEAK", "CAN7_TRAY20_LARGE_LEAK",
+			"CAN7_TRAY21_LARGE_LEAK", "CAN7_TRAY22_LARGE_LEAK",
+			"CAN7_TRAY23_LARGE_LEAK", "CAN7_TRAY24_LARGE_LEAK",
+			"CAN7_TRAY25_LARGE_LEAK", "CAN7_TRAY26_LARGE_LEAK",
+			"CAN7_TRAY27_LARGE_LEAK", "CAN7_TRAY28_LARGE_LEAK",
+			"CAN7_TRAY29_LARGE_LEAK", "CAN7_TRAY30_LARGE_LEAK",
+			"CAN7_TRAY31_LARGE_LEAK", "CAN7_TRAY32_LARGE_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	large_leak_io_expander7: gpio@57 {
+		compatible = "nxp,pca9698";
+		reg = <0x57>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <110 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN8_TRAY1_LARGE_LEAK", "CAN8_TRAY2_LARGE_LEAK",
+			"CAN8_TRAY3_LARGE_LEAK", "CAN8_TRAY4_LARGE_LEAK",
+			"CAN8_TRAY5_LARGE_LEAK", "CAN8_TRAY6_LARGE_LEAK",
+			"CAN8_TRAY7_LARGE_LEAK", "CAN8_TRAY8_LARGE_LEAK",
+			"CAN8_TRAY9_LARGE_LEAK", "CAN8_TRAY10_LARGE_LEAK",
+			"CAN8_TRAY11_LARGE_LEAK", "CAN8_TRAY12_LARGE_LEAK",
+			"CAN8_TRAY13_LARGE_LEAK", "CAN8_TRAY14_LARGE_LEAK",
+			"CAN8_TRAY15_LARGE_LEAK", "CAN8_TRAY16_LARGE_LEAK",
+			"CAN8_TRAY17_LARGE_LEAK", "CAN8_TRAY18_LARGE_LEAK",
+			"CAN8_TRAY19_LARGE_LEAK", "CAN8_TRAY20_LARGE_LEAK",
+			"CAN8_TRAY21_LARGE_LEAK", "CAN8_TRAY22_LARGE_LEAK",
+			"CAN8_TRAY23_LARGE_LEAK", "CAN8_TRAY24_LARGE_LEAK",
+			"CAN8_TRAY25_LARGE_LEAK", "CAN8_TRAY26_LARGE_LEAK",
+			"CAN8_TRAY27_LARGE_LEAK", "CAN8_TRAY28_LARGE_LEAK",
+			"CAN8_TRAY29_LARGE_LEAK", "CAN8_TRAY30_LARGE_LEAK",
+			"CAN8_TRAY31_LARGE_LEAK", "CAN8_TRAY32_LARGE_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	small_leak_io_expander0: gpio@58 {
+		compatible = "nxp,pca9698";
+		reg = <0x58>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <52 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN1_TRAY1_SMALL_LEAK", "CAN1_TRAY2_SMALL_LEAK",
+			"CAN1_TRAY3_SMALL_LEAK", "CAN1_TRAY4_SMALL_LEAK",
+			"CAN1_TRAY5_SMALL_LEAK", "CAN1_TRAY6_SMALL_LEAK",
+			"CAN1_TRAY7_SMALL_LEAK", "CAN1_TRAY8_SMALL_LEAK",
+			"CAN1_TRAY9_SMALL_LEAK", "CAN1_TRAY10_SMALL_LEAK",
+			"CAN1_TRAY11_SMALL_LEAK", "CAN1_TRAY12_SMALL_LEAK",
+			"CAN1_TRAY13_SMALL_LEAK", "CAN1_TRAY14_SMALL_LEAK",
+			"CAN1_TRAY15_SMALL_LEAK", "CAN1_TRAY16_SMALL_LEAK",
+			"CAN1_TRAY17_SMALL_LEAK", "CAN1_TRAY18_SMALL_LEAK",
+			"CAN1_TRAY19_SMALL_LEAK", "CAN1_TRAY20_SMALL_LEAK",
+			"CAN1_TRAY21_SMALL_LEAK", "CAN1_TRAY22_SMALL_LEAK",
+			"CAN1_TRAY23_SMALL_LEAK", "CAN1_TRAY24_SMALL_LEAK",
+			"CAN1_TRAY25_SMALL_LEAK", "CAN1_TRAY26_SMALL_LEAK",
+			"CAN1_TRAY27_SMALL_LEAK", "CAN1_TRAY28_SMALL_LEAK",
+			"CAN1_TRAY29_SMALL_LEAK", "CAN1_TRAY30_SMALL_LEAK",
+			"CAN1_TRAY31_SMALL_LEAK", "CAN1_TRAY32_SMALL_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	small_leak_io_expander1: gpio@59 {
+		compatible = "nxp,pca9698";
+		reg = <0x59>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <60 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN2_TRAY1_SMALL_LEAK", "CAN2_TRAY2_SMALL_LEAK",
+			"CAN2_TRAY3_SMALL_LEAK", "CAN2_TRAY4_SMALL_LEAK",
+			"CAN2_TRAY5_SMALL_LEAK", "CAN2_TRAY6_SMALL_LEAK",
+			"CAN2_TRAY7_SMALL_LEAK", "CAN2_TRAY8_SMALL_LEAK",
+			"CAN2_TRAY9_SMALL_LEAK", "CAN2_TRAY10_SMALL_LEAK",
+			"CAN2_TRAY11_SMALL_LEAK", "CAN2_TRAY12_SMALL_LEAK",
+			"CAN2_TRAY13_SMALL_LEAK", "CAN2_TRAY14_SMALL_LEAK",
+			"CAN2_TRAY15_SMALL_LEAK", "CAN2_TRAY16_SMALL_LEAK",
+			"CAN2_TRAY17_SMALL_LEAK", "CAN2_TRAY18_SMALL_LEAK",
+			"CAN2_TRAY19_SMALL_LEAK", "CAN2_TRAY20_SMALL_LEAK",
+			"CAN2_TRAY21_SMALL_LEAK", "CAN2_TRAY22_SMALL_LEAK",
+			"CAN2_TRAY23_SMALL_LEAK", "CAN2_TRAY24_SMALL_LEAK",
+			"CAN2_TRAY25_SMALL_LEAK", "CAN2_TRAY26_SMALL_LEAK",
+			"CAN2_TRAY27_SMALL_LEAK", "CAN2_TRAY28_SMALL_LEAK",
+			"CAN2_TRAY29_SMALL_LEAK", "CAN2_TRAY30_SMALL_LEAK",
+			"CAN2_TRAY31_SMALL_LEAK", "CAN2_TRAY32_SMALL_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	small_leak_io_expander2: gpio@5a {
+		compatible = "nxp,pca9698";
+		reg = <0x5a>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <68 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN3_TRAY1_SMALL_LEAK", "CAN3_TRAY2_SMALL_LEAK",
+			"CAN3_TRAY3_SMALL_LEAK", "CAN3_TRAY4_SMALL_LEAK",
+			"CAN3_TRAY5_SMALL_LEAK", "CAN3_TRAY6_SMALL_LEAK",
+			"CAN3_TRAY7_SMALL_LEAK", "CAN3_TRAY8_SMALL_LEAK",
+			"CAN3_TRAY9_SMALL_LEAK", "CAN3_TRAY10_SMALL_LEAK",
+			"CAN3_TRAY11_SMALL_LEAK", "CAN3_TRAY12_SMALL_LEAK",
+			"CAN3_TRAY13_SMALL_LEAK", "CAN3_TRAY14_SMALL_LEAK",
+			"CAN3_TRAY15_SMALL_LEAK", "CAN3_TRAY16_SMALL_LEAK",
+			"CAN3_TRAY17_SMALL_LEAK", "CAN3_TRAY18_SMALL_LEAK",
+			"CAN3_TRAY19_SMALL_LEAK", "CAN3_TRAY20_SMALL_LEAK",
+			"CAN3_TRAY21_SMALL_LEAK", "CAN3_TRAY22_SMALL_LEAK",
+			"CAN3_TRAY23_SMALL_LEAK", "CAN3_TRAY24_SMALL_LEAK",
+			"CAN3_TRAY25_SMALL_LEAK", "CAN3_TRAY26_SMALL_LEAK",
+			"CAN3_TRAY27_SMALL_LEAK", "CAN3_TRAY28_SMALL_LEAK",
+			"CAN3_TRAY29_SMALL_LEAK", "CAN3_TRAY30_SMALL_LEAK",
+			"CAN3_TRAY31_SMALL_LEAK", "CAN3_TRAY32_SMALL_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	small_leak_io_expander3: gpio@5b {
+		compatible = "nxp,pca9698";
+		reg = <0x5b>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <76 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN4_TRAY1_SMALL_LEAK", "CAN4_TRAY2_SMALL_LEAK",
+			"CAN4_TRAY3_SMALL_LEAK", "CAN4_TRAY4_SMALL_LEAK",
+			"CAN4_TRAY5_SMALL_LEAK", "CAN4_TRAY6_SMALL_LEAK",
+			"CAN4_TRAY7_SMALL_LEAK", "CAN4_TRAY8_SMALL_LEAK",
+			"CAN4_TRAY9_SMALL_LEAK", "CAN4_TRAY10_SMALL_LEAK",
+			"CAN4_TRAY11_SMALL_LEAK", "CAN4_TRAY12_SMALL_LEAK",
+			"CAN4_TRAY13_SMALL_LEAK", "CAN4_TRAY14_SMALL_LEAK",
+			"CAN4_TRAY15_SMALL_LEAK", "CAN4_TRAY16_SMALL_LEAK",
+			"CAN4_TRAY17_SMALL_LEAK", "CAN4_TRAY18_SMALL_LEAK",
+			"CAN4_TRAY19_SMALL_LEAK", "CAN4_TRAY20_SMALL_LEAK",
+			"CAN4_TRAY21_SMALL_LEAK", "CAN4_TRAY22_SMALL_LEAK",
+			"CAN4_TRAY23_SMALL_LEAK", "CAN4_TRAY24_SMALL_LEAK",
+			"CAN4_TRAY25_SMALL_LEAK", "CAN4_TRAY26_SMALL_LEAK",
+			"CAN4_TRAY27_SMALL_LEAK", "CAN4_TRAY28_SMALL_LEAK",
+			"CAN4_TRAY29_SMALL_LEAK", "CAN4_TRAY30_SMALL_LEAK",
+			"CAN4_TRAY31_SMALL_LEAK", "CAN4_TRAY32_SMALL_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	small_leak_io_expander4: gpio@5c {
+		compatible = "nxp,pca9698";
+		reg = <0x5c>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <84 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN5_TRAY1_SMALL_LEAK", "CAN5_TRAY2_SMALL_LEAK",
+			"CAN5_TRAY3_SMALL_LEAK", "CAN5_TRAY4_SMALL_LEAK",
+			"CAN5_TRAY5_SMALL_LEAK", "CAN5_TRAY6_SMALL_LEAK",
+			"CAN5_TRAY7_SMALL_LEAK", "CAN5_TRAY8_SMALL_LEAK",
+			"CAN5_TRAY9_SMALL_LEAK", "CAN5_TRAY10_SMALL_LEAK",
+			"CAN5_TRAY11_SMALL_LEAK", "CAN5_TRAY12_SMALL_LEAK",
+			"CAN5_TRAY13_SMALL_LEAK", "CAN5_TRAY14_SMALL_LEAK",
+			"CAN5_TRAY15_SMALL_LEAK", "CAN5_TRAY16_SMALL_LEAK",
+			"CAN5_TRAY17_SMALL_LEAK", "CAN5_TRAY18_SMALL_LEAK",
+			"CAN5_TRAY19_SMALL_LEAK", "CAN5_TRAY20_SMALL_LEAK",
+			"CAN5_TRAY21_SMALL_LEAK", "CAN5_TRAY22_SMALL_LEAK",
+			"CAN5_TRAY23_SMALL_LEAK", "CAN5_TRAY24_SMALL_LEAK",
+			"CAN5_TRAY25_SMALL_LEAK", "CAN5_TRAY26_SMALL_LEAK",
+			"CAN5_TRAY27_SMALL_LEAK", "CAN5_TRAY28_SMALL_LEAK",
+			"CAN5_TRAY29_SMALL_LEAK", "CAN5_TRAY30_SMALL_LEAK",
+			"CAN5_TRAY31_SMALL_LEAK", "CAN5_TRAY32_SMALL_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	small_leak_io_expander5: gpio@5d {
+		compatible = "nxp,pca9698";
+		reg = <0x5d>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <92 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN6_TRAY1_SMALL_LEAK", "CAN6_TRAY2_SMALL_LEAK",
+			"CAN6_TRAY3_SMALL_LEAK", "CAN6_TRAY4_SMALL_LEAK",
+			"CAN6_TRAY5_SMALL_LEAK", "CAN6_TRAY6_SMALL_LEAK",
+			"CAN6_TRAY7_SMALL_LEAK", "CAN6_TRAY8_SMALL_LEAK",
+			"CAN6_TRAY9_SMALL_LEAK", "CAN6_TRAY10_SMALL_LEAK",
+			"CAN6_TRAY11_SMALL_LEAK", "CAN6_TRAY12_SMALL_LEAK",
+			"CAN6_TRAY13_SMALL_LEAK", "CAN6_TRAY14_SMALL_LEAK",
+			"CAN6_TRAY15_SMALL_LEAK", "CAN6_TRAY16_SMALL_LEAK",
+			"CAN6_TRAY17_SMALL_LEAK", "CAN6_TRAY18_SMALL_LEAK",
+			"CAN6_TRAY19_SMALL_LEAK", "CAN6_TRAY20_SMALL_LEAK",
+			"CAN6_TRAY21_SMALL_LEAK", "CAN6_TRAY22_SMALL_LEAK",
+			"CAN6_TRAY23_SMALL_LEAK", "CAN6_TRAY24_SMALL_LEAK",
+			"CAN6_TRAY25_SMALL_LEAK", "CAN6_TRAY26_SMALL_LEAK",
+			"CAN6_TRAY27_SMALL_LEAK", "CAN6_TRAY28_SMALL_LEAK",
+			"CAN6_TRAY29_SMALL_LEAK", "CAN6_TRAY30_SMALL_LEAK",
+			"CAN6_TRAY31_SMALL_LEAK", "CAN6_TRAY32_SMALL_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	small_leak_io_expander6: gpio@5e {
+		compatible = "nxp,pca9698";
+		reg = <0x5e>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <100 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN7_TRAY1_SMALL_LEAK", "CAN7_TRAY2_SMALL_LEAK",
+			"CAN7_TRAY3_SMALL_LEAK", "CAN7_TRAY4_SMALL_LEAK",
+			"CAN7_TRAY5_SMALL_LEAK", "CAN7_TRAY6_SMALL_LEAK",
+			"CAN7_TRAY7_SMALL_LEAK", "CAN7_TRAY8_SMALL_LEAK",
+			"CAN7_TRAY9_SMALL_LEAK", "CAN7_TRAY10_SMALL_LEAK",
+			"CAN7_TRAY11_SMALL_LEAK", "CAN7_TRAY12_SMALL_LEAK",
+			"CAN7_TRAY13_SMALL_LEAK", "CAN7_TRAY14_SMALL_LEAK",
+			"CAN7_TRAY15_SMALL_LEAK", "CAN7_TRAY16_SMALL_LEAK",
+			"CAN7_TRAY17_SMALL_LEAK", "CAN7_TRAY18_SMALL_LEAK",
+			"CAN7_TRAY19_SMALL_LEAK", "CAN7_TRAY20_SMALL_LEAK",
+			"CAN7_TRAY21_SMALL_LEAK", "CAN7_TRAY22_SMALL_LEAK",
+			"CAN7_TRAY23_SMALL_LEAK", "CAN7_TRAY24_SMALL_LEAK",
+			"CAN7_TRAY25_SMALL_LEAK", "CAN7_TRAY26_SMALL_LEAK",
+			"CAN7_TRAY27_SMALL_LEAK", "CAN7_TRAY28_SMALL_LEAK",
+			"CAN7_TRAY29_SMALL_LEAK", "CAN7_TRAY30_SMALL_LEAK",
+			"CAN7_TRAY31_SMALL_LEAK", "CAN7_TRAY32_SMALL_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	small_leak_io_expander7: gpio@5f {
+		compatible = "nxp,pca9698";
+		reg = <0x5f>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <108 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"CAN8_TRAY1_SMALL_LEAK", "CAN8_TRAY2_SMALL_LEAK",
+			"CAN8_TRAY3_SMALL_LEAK", "CAN8_TRAY4_SMALL_LEAK",
+			"CAN8_TRAY5_SMALL_LEAK", "CAN8_TRAY6_SMALL_LEAK",
+			"CAN8_TRAY7_SMALL_LEAK", "CAN8_TRAY8_SMALL_LEAK",
+			"CAN8_TRAY9_SMALL_LEAK", "CAN8_TRAY10_SMALL_LEAK",
+			"CAN8_TRAY11_SMALL_LEAK", "CAN8_TRAY12_SMALL_LEAK",
+			"CAN8_TRAY13_SMALL_LEAK", "CAN8_TRAY14_SMALL_LEAK",
+			"CAN8_TRAY15_SMALL_LEAK", "CAN8_TRAY16_SMALL_LEAK",
+			"CAN8_TRAY17_SMALL_LEAK", "CAN8_TRAY18_SMALL_LEAK",
+			"CAN8_TRAY19_SMALL_LEAK", "CAN8_TRAY20_SMALL_LEAK",
+			"CAN8_TRAY21_SMALL_LEAK", "CAN8_TRAY22_SMALL_LEAK",
+			"CAN8_TRAY23_SMALL_LEAK", "CAN8_TRAY24_SMALL_LEAK",
+			"CAN8_TRAY25_SMALL_LEAK", "CAN8_TRAY26_SMALL_LEAK",
+			"CAN8_TRAY27_SMALL_LEAK", "CAN8_TRAY28_SMALL_LEAK",
+			"CAN8_TRAY29_SMALL_LEAK", "CAN8_TRAY30_SMALL_LEAK",
+			"CAN8_TRAY31_SMALL_LEAK", "CAN8_TRAY32_SMALL_LEAK",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+};
+
+&i2c4 {
+	status = "okay";
+	multi-master;
+	mctp-controller;
+	mctp0: mctp@10 {
+		compatible = "mctp-i2c-controller";
+		reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+	};
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c4mux0ch0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			io_expander3: gpio@23 {
+				compatible = "nxp,pca9555";
+				reg = <0x23>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-parent = <&io_expander7>;
+				interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+				gpio-line-names =
+					"", "",
+					"", "RST_I2CRST_MUX1_N",
+					"RST_I2CRST_MUX2_N", "RST_I2CRST_MUX3_N",
+					"RST_I2CRST_MUX4_N", "RST_I2CRST_MUX5_N",
+					"RST_I2CRST_MUX6_N", "RST_I2CRST_MUX7_N",
+					"RST_I2CRST_MUX8_N", "",
+					"TRAY30_PWRGD_BUF_R", "TRAY31_PWRGD_BUF_R",
+					"TRAY32_PWRGD_BUF_R", "TRAY37_PWRGD_BUF_R";
+			};
+		};
+
+		i2c4mux0ch1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			temp-sensor@48 {
+				compatible = "ti,tmp75";
+				reg = <0x48>;
+			};
+
+			temp-sensor@4a {
+				compatible = "ti,tmp75";
+				reg = <0x4a>;
+			};
+
+			eeprom@56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+		};
+
+		i2c4mux0ch2: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+
+			power-monitor@11 {
+				compatible = "infineon,tda38640";
+				reg = <0x11>;
+			};
+
+			power-monitor@22 {
+				compatible = "infineon,tda38640";
+				reg = <0x22>;
+			};
+
+			power-monitor@45 {
+				compatible = "infineon,tda38640";
+				reg = <0x45>;
+			};
+
+			power-monitor@66 {
+				compatible = "infineon,tda38640";
+				reg = <0x66>;
+			};
+		};
+
+		i2c4mux0ch3: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c4mux0ch4: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c4mux0ch5: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+		};
+
+		i2c4mux0ch6: i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			mctp-controller;
+		};
+
+		i2c4mux0ch7: i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c5 {
+	status = "okay";
+
+	io_expander4: gpio@22 {
+		compatible = "nxp,pca9555";
+		reg = <0x22>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&io_expander7>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"R_COME_THERMTRIP_L", "R_PWRGD_PCH_PWROK",
+			"", "",
+			"", "",
+			"", "",
+			"", "",
+			"", "",
+			"", "TRAY38_PWRGD_BUF_R",
+			"TRAY39_PWRGD_BUF_R", "TRAY40_PWRGD_BUF_R";
+	};
+
+	io_expander5: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&io_expander7>;
+		interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"PWRGD_P5V_AUX_R2", "",
+			"PWRGD_P1V5_AUX_R", "PWRGD_P1V05_AUX_R",
+			"PWRGD_P52V_HSC_PWROK_R", "PWRGD_P24V_AUX_2_R",
+			"PWRGD_P24V_AUX_R", "PWRGD_P12V_AUX_R2",
+			"PWRGD_P12V_SCM_R", "P24V_AUX_INA230_ALERT_N_R",
+			"", "PRSNT_CAN1_MCIO_N",
+			"PRSNT_CAN2_MCIO_N", "PRSNT_AALC_MCIO_N",
+			"PRSNT_RACKMON_MCIO_N", "PRSNT_RIO_RACKMON_N";
+	};
+
+	temp-sensor@4f {
+		compatible = "ti,tmp75";
+		reg = <0x4f>;
+	};
+
+	eeprom@54 {
+		compatible = "atmel,24c128";
+		reg = <0x54>;
+	};
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c5mux0ch0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		i2c5mux0ch1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		i2c5mux0ch2: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+
+			eeprom@56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+		};
+
+		i2c5mux0ch3: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+
+			eeprom@56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+		};
+
+		i2c5mux0ch4: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+
+			eeprom@56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+		};
+
+		i2c5mux0ch5: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+
+			eeprom@56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+		};
+
+		i2c5mux0ch6: i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+
+			eeprom@56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+		};
+
+		i2c5mux0ch7: i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+
+			eeprom@56 {
+				compatible = "atmel,24c128";
+				reg = <0x56>;
+			};
+		};
+	};
+};
+
+&i2c6 {
+	status = "okay";
+
+	dac@0c {
+		reg = <0x0c>;
+		compatible = "adi,ad5612";
+		vcc-supply = <&p5v_dac_aux>;
+	};
+
+	dac@0e {
+		reg = <0x0e>;
+		compatible = "adi,ad5612";
+		vcc-supply = <&p5v_dac_aux>;
+	};
+
+	dac@0f {
+		reg = <0x0f>;
+		compatible = "adi,ad5612";
+		vcc-supply = <&p5v_dac_aux>;
+	};
+
+	io_expander0: gpio@20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&io_expander7>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"", "",
+			"", "",
+			"", "PRSNT_FANBP_0_PWR_N",
+			"PRSNT_FANBP_0_SIG_N", "PRSNT_POE_PWR_N",
+			"PRSNT_POE_SIG_N", "",
+			"PWRGD_P3V3_ISO_POE_BMC_R", "",
+			"", "",
+			"DEV_DIS_N", "PCI_DIS_N";
+	};
+
+	io_expander1: gpio@21 {
+		compatible = "nxp,pca9555";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&io_expander7>;
+		interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"PWRGD_CPU_LVC3_BMC", "R_FM_BIOS_POST_CMPLT_BMC",
+			"", "",
+			"", "",
+			"", "",
+			"", "",
+			"", "PCIE_SSD1_PRSNT_N",
+			"", "TRAY23_PWRGD_BUF_R",
+			"TRAY24_PWRGD_BUF_R", "TRAY29_PWRGD_BUF_R";
+	};
+
+	io_expander2: gpio@22 {
+		compatible = "nxp,pca9555";
+		reg = <0x22>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&io_expander7>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"BOARD_ID_0", "BOARD_ID_1",
+			"BOARD_ID_2", "BOARD_ID_3",
+			"SKU_ID_3", "SKU_ID_2",
+			"SKU_ID_1", "SKU_ID_0",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	io_expander7: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <32 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"IOEXP1_INT_N", "IOEXP2_INT_N",
+			"IOEXP3_INT_N", "IOEXP4_INT_N",
+			"IOEXP5_INT_N", "IOEXP6_INT_N",
+			"IOEXP7_INT_N", "",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	io_expander8: gpio@24 {
+		compatible = "nxp,pca9555";
+		reg = <0x24>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&io_expander7>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"PRSNT_MGMT_J54_N", "PRSNT_RACKMON_J47_N",
+			"PRSNT_MGMT_DEBUG_J53_N", "PRSNT_MINISAS_TOP_J49_N",
+			"PRSNT_MINISAS_TOP_J50_N", "PRSNT_MINISAS_BOT_J51_N",
+			"PRSNT_MINISAS_BOT_J52_N", "JTAG_PLD_JTAGEN",
+			"PU_PLD_CONFIG_N", "",
+			"", "",
+			"", "",
+			"", "";
+};
+
+	// Marvell 88E6393X EEPROM
+	eeprom@50 {
+		compatible = "atmel,24c64";
+		reg = <0x50>;
+	};
+
+	rtc@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+&i2c7 {
+	status = "okay";
+	bus-frequency = <100000>;
+	multi-master;
+	aspeed,hw-timeout-ms = <1000>;
+
+	ipmb@10 {
+		compatible = "ipmb-dev";
+		reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+		i2c-protocol;
+	};
+};
+
+&i2c8 {
+	status = "okay";
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c8mux0ch0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			status = "okay";
+		};
+
+		i2c8mux0ch1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			status = "okay";
+		};
+
+		i2c8mux0ch2: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			status = "okay";
+		};
+
+		i2c8mux0ch3: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c8mux0ch4: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c8mux0ch5: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+		};
+
+		i2c8mux0ch6: i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			status = "okay";
+		};
+
+		i2c8mux0ch7: i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c9 {
+	status = "okay";
+
+	temperature-sensor@4b {
+		compatible = "ti,tmp75";
+		reg = <0x4b>;
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c128";
+		reg = <0x50>;
+	};
+
+	eeprom@51 {
+		compatible = "atmel,24c128";
+		reg = <0x51>;
+	};
+
+	eeprom@56 {
+		compatible = "atmel,24c64";
+		reg = <0x56>;
+	};
+};
+
+&i2c10 {
+	status = "okay";
+
+	legacy_prsnt_io_expander0: gpio@11 {
+		compatible = "nxp,pca9555";
+		reg = <0x11>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <40 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_PRSNT1_N_BUF_R", "TRAY_PRSNT2_N_BUF_R",
+			"TRAY_PRSNT3_N_BUF_R", "TRAY_PRSNT4_N_BUF_R",
+			"TRAY_PRSNT5_N_BUF_R", "TRAY_PRSNT6_N_BUF_R",
+			"TRAY_PRSNT7_N_BUF_R", "TRAY_PRSNT8_N_BUF_R",
+			"TRAY_PRSNT9_N_BUF_R", "TRAY_PRSNT10_N_BUF_R",
+			"TRAY_PRSNT11_N_BUF_R", "TRAY_PRSNT12_N_BUF_R",
+			"TRAY_PRSNT13_N_BUF_R", "TRAY_PRSNT14_N_BUF_R",
+			"TRAY_PRSNT15_N_BUF_R", "TRAY_PRSNT16_N_BUF_R";
+	};
+
+	legacy_prsnt_io_expander1: gpio@12 {
+		compatible = "nxp,pca9555";
+		reg = <0x12>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <40 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_PRSNT17_N_BUF_R", "TRAY_PRSNT18_N_BUF_R",
+			"TRAY_PRSNT19_N_BUF_R", "TRAY_PRSNT20_N_BUF_R",
+			"TRAY_PRSNT21_N_BUF_R", "TRAY_PRSNT22_N_BUF_R",
+			"TRAY_PRSNT23_N_BUF_R", "TRAY_PRSNT24_N_BUF_R",
+			"TRAY_PRSNT25_N_BUF_R", "TRAY_PRSNT26_N_BUF_R",
+			"TRAY_PRSNT27_N_BUF_R", "TRAY_PRSNT28_N_BUF_R",
+			"TRAY_PRSNT29_N_BUF_R", "TRAY_PRSNT30_N_BUF_R",
+			"TRAY_PRSNT31_N_BUF_R", "TRAY_PRSNT32_N_BUF_R";
+	};
+
+	legacy_prsnt_io_expander2: gpio@13 {
+		compatible = "nxp,pca9555";
+		reg = <0x13>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <40 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_PRSNT33_N_BUF_R", "TRAY_PRSNT34_N_BUF_R",
+			"TRAY_PRSNT35_N_BUF_R", "TRAY_PRSNT36_N_BUF_R",
+			"TRAY_PRSNT37_N_BUF_R", "TRAY_PRSNT38_N_BUF_R",
+			"TRAY_PRSNT39_N_BUF_R", "TRAY_PRSNT40_N_BUF_R",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	power-monitor@14 {
+		compatible = "infineon,xdp710";
+		reg = <0x14>;
+	};
+
+	legacy_pwrgd_io_expander1: gpio@15 {
+		compatible = "nxp,pca9555";
+		reg = <0x15>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_PWRGD17_N_BUF_R", "TRAY_PWRGD18_N_BUF_R",
+			"TRAY_PWRGD19_N_BUF_R", "TRAY_PWRGD20_N_BUF_R",
+			"TRAY_PWRGD21_N_BUF_R", "TRAY_PWRGD22_N_BUF_R",
+			"TRAY_PWRGD23_N_BUF_R", "TRAY_PWRGD24_N_BUF_R",
+			"TRAY_PWRGD25_N_BUF_R", "TRAY_PWRGD26_N_BUF_R",
+			"TRAY_PWRGD27_N_BUF_R", "TRAY_PWRGD28_N_BUF_R",
+			"TRAY_PWRGD29_N_BUF_R", "TRAY_PWRGD30_N_BUF_R",
+			"TRAY_PWRGD31_N_BUF_R", "TRAY_PWRGD32_N_BUF_R";
+	};
+
+	legacy_pwrgd_io_expander2: gpio@16 {
+		compatible = "nxp,pca9555";
+		reg = <0x16>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_PWRGD33_N_BUF_R", "TRAY_PWRGD34_N_BUF_R",
+			"TRAY_PWRGD35_N_BUF_R", "TRAY_PWRGD36_N_BUF_R",
+			"TRAY_PWRGD37_N_BUF_R", "TRAY_PWRGD38_N_BUF_R",
+			"TRAY_PWRGD39_N_BUF_R", "TRAY_PWRGD40_N_BUF_R",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	legacy_leak_io_expander0: gpio@17 {
+		compatible = "nxp,pca9555";
+		reg = <0x17>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <46 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_LEAK_DETECT1_N_BUF_R", "TRAY_LEAK_DETECT2_N_BUF_R",
+			"TRAY_LEAK_DETECT3_N_BUF_R", "TRAY_LEAK_DETECT4_N_BUF_R",
+			"TRAY_LEAK_DETECT5_N_BUF_R", "TRAY_LEAK_DETECT6_N_BUF_R",
+			"TRAY_LEAK_DETECT7_N_BUF_R", "TRAY_LEAK_DETECT8_N_BUF_R",
+			"TRAY_LEAK_DETECT9_N_BUF_R", "TRAY_LEAK_DETECT10_N_BUF_R",
+			"TRAY_LEAK_DETECT11_N_BUF_R", "TRAY_LEAK_DETECT12_N_BUF_R",
+			"TRAY_LEAK_DETECT13_N_BUF_R", "TRAY_LEAK_DETECT14_N_BUF_R",
+			"TRAY_LEAK_DETECT15_N_BUF_R", "TRAY_LEAK_DETECT16_N_BUF_R";
+	};
+
+	legacy_leak_io_expander1: gpio@18 {
+		compatible = "nxp,pca9555";
+		reg = <0x18>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <46 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_LEAK_DETECT17_N_BUF_R", "TRAY_LEAK_DETECT18_N_BUF_R",
+			"TRAY_LEAK_DETECT19_N_BUF_R", "TRAY_LEAK_DETECT20_N_BUF_R",
+			"TRAY_LEAK_DETECT21_N_BUF_R", "TRAY_LEAK_DETECT22_N_BUF_R",
+			"TRAY_LEAK_DETECT23_N_BUF_R", "TRAY_LEAK_DETECT24_N_BUF_R",
+			"TRAY_LEAK_DETECT25_N_BUF_R", "TRAY_LEAK_DETECT26_N_BUF_R",
+			"TRAY_LEAK_DETECT27_N_BUF_R", "TRAY_LEAK_DETECT28_N_BUF_R",
+			"TRAY_LEAK_DETECT29_N_BUF_R", "TRAY_LEAK_DETECT30_N_BUF_R",
+			"TRAY_LEAK_DETECT31_N_BUF_R", "TRAY_LEAK_DETECT32_N_BUF_R";
+	};
+
+	legacy_leak_io_expander2: gpio@19 {
+		compatible = "nxp,pca9555";
+		reg = <0x19>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <46 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_LEAK_DETECT33_N_BUF_R", "TRAY_LEAK_DETECT34_N_BUF_R",
+			"TRAY_LEAK_DETECT35_N_BUF_R", "TRAY_LEAK_DETECT36_N_BUF_R",
+			"TRAY_LEAK_DETECT37_N_BUF_R", "TRAY_LEAK_DETECT38_N_BUF_R",
+			"TRAY_LEAK_DETECT39_N_BUF_R", "TRAY_LEAK_DETECT40_N_BUF_R",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	legacy_small_leak_io_expander0: gpio@1a {
+		compatible = "nxp,pca9555";
+		reg = <0x1a>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <44 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_SMALL_LEAK1_N_BUF_R", "TRAY_SMALL_LEAK2_N_BUF_R",
+			"TRAY_SMALL_LEAK3_N_BUF_R", "TRAY_SMALL_LEAK4_N_BUF_R",
+			"TRAY_SMALL_LEAK5_N_BUF_R", "TRAY_SMALL_LEAK6_N_BUF_R",
+			"TRAY_SMALL_LEAK7_N_BUF_R", "TRAY_SMALL_LEAK8_N_BUF_R",
+			"TRAY_SMALL_LEAK9_N_BUF_R", "TRAY_SMALL_LEAK10_N_BUF_R",
+			"TRAY_SMALL_LEAK11_N_BUF_R", "TRAY_SMALL_LEAK12_N_BUF_R",
+			"TRAY_SMALL_LEAK13_N_BUF_R", "TRAY_SMALL_LEAK14_N_BUF_R",
+			"TRAY_SMALL_LEAK15_N_BUF_R", "TRAY_SMALL_LEAK16_N_BUF_R";
+	};
+
+	legacy_small_leak_io_expander1: gpio@1b {
+		compatible = "nxp,pca9555";
+		reg = <0x1b>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <44 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_SMALL_LEAK17_N_BUF_R", "TRAY_SMALL_LEAK18_N_BUF_R",
+			"TRAY_SMALL_LEAK19_N_BUF_R", "TRAY_SMALL_LEAK20_N_BUF_R",
+			"TRAY_SMALL_LEAK21_N_BUF_R", "TRAY_SMALL_LEAK22_N_BUF_R",
+			"TRAY_SMALL_LEAK23_N_BUF_R", "TRAY_SMALL_LEAK24_N_BUF_R",
+			"TRAY_SMALL_LEAK25_N_BUF_R", "TRAY_SMALL_LEAK26_N_BUF_R",
+			"TRAY_SMALL_LEAK27_N_BUF_R", "TRAY_SMALL_LEAK28_N_BUF_R",
+			"TRAY_SMALL_LEAK29_N_BUF_R", "TRAY_SMALL_LEAK30_N_BUF_R",
+			"TRAY_SMALL_LEAK31_N_BUF_R", "TRAY_SMALL_LEAK32_N_BUF_R";
+	};
+
+	legacy_small_leak_io_expander2: gpio@1c {
+		compatible = "nxp,pca9555";
+		reg = <0x1c>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <44 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_SMALL_LEAK33_N_BUF_R", "TRAY_SMALL_LEAK34_N_BUF_R",
+			"TRAY_SMALL_LEAK35_N_BUF_R", "TRAY_SMALL_LEAK36_N_BUF_R",
+			"TRAY_SMALL_LEAK37_N_BUF_R", "TRAY_SMALL_LEAK38_N_BUF_R",
+			"TRAY_SMALL_LEAK39_N_BUF_R", "TRAY_SMALL_LEAK40_N_BUF_R",
+			"", "",
+			"", "",
+			"", "",
+			"", "";
+	};
+
+	legacy_pwrgd_io_expander0: gpio@28 {
+		compatible = "nxp,pca9555";
+		reg = <0x28>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&sgpiom0>;
+		interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
+
+		gpio-line-names =
+			"TRAY_PWRGD1_N_BUF_R", "TRAY_PWRGD2_N_BUF_R",
+			"TRAY_PWRGD3_N_BUF_R", "TRAY_PWRGD4_N_BUF_R",
+			"TRAY_PWRGD5_N_BUF_R", "TRAY_PWRGD6_N_BUF_R",
+			"TRAY_PWRGD7_N_BUF_R", "TRAY_PWRGD8_N_BUF_R",
+			"TRAY_PWRGD9_N_BUF_R", "TRAY_PWRGD10_N_BUF_R",
+			"TRAY_PWRGD11_N_BUF_R", "TRAY_PWRGD12_N_BUF_R",
+			"TRAY_PWRGD13_N_BUF_R", "TRAY_PWRGD14_N_BUF_R",
+			"TRAY_PWRGD15_N_BUF_R", "TRAY_PWRGD16_N_BUF_R";
+	};
+
+	adc@35 {
+		compatible = "maxim,max11617";
+		reg = <0x35>;
+	};
+
+	power-monitor@40 {
+		compatible = "ti,ina230";
+		reg = <0x40>;
+		shunt-resistor = <1000>;
+	};
+
+	power-sensor@41 {
+		compatible = "ti,ina238";
+		reg = <0x41>;
+		shunt-resistor = <20000>;
+	};
+
+	power-sensor@43 {
+		compatible = "ti,ina238";
+		reg = <0x43>;
+		shunt-resistor = <20000>;
+	};
+
+	power-monitor@44 {
+		compatible = "lltc,ltc4287";
+		reg = <0x44>;
+		shunt-resistor-micro-ohms = <500>;
+	};
+
+	power-monitor@45 {
+		compatible = "ti,ina230";
+		reg = <0x45>;
+		shunt-resistor = <1000>;
+	};
+
+	adc@48 {
+		compatible = "ti,ads1015";
+		reg = <0x48>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	temp-sensor@4c {
+		compatible = "ti,tmp75";
+		reg = <0x4c>;
+	};
+
+	temp-sensor@4d {
+		compatible = "ti,tmp75";
+		reg = <0x4d>;
+	};
+
+	temp-sensor@4e {
+		compatible = "ti,tmp75";
+		reg = <0x4e>;
+	};
+
+	power-monitor@4f {
+		compatible = "ti,ina230";
+		reg = <0x4f>;
+		shunt-resistor = <1000>;
+	};
+
+	power-monitor@69 {
+		compatible = "pmbus";
+		reg = <0x69>;
+	};
+
+	fpga_io_expander64: gpio@64 {
+		compatible = "nxp,pca9555";
+		reg = <0x64>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		gpio-line-names =
+			"", "",
+			"", "",
+			"", "",
+			"LEAK_CONFIG0", "LEAK_CONFIG1",
+			"FPGA_PWRGD_P24V_AUX_R", "FPGA_PWRGD_P24V_AUX_2_R",
+			"FPGA_PWRGD_P12V_SCM_R", "FPGA_PWRGD_P12V_AUX_R2",
+			"FPGA_PRSNT_FANBP_0_SIG_R_PLD_N", "FPGA_PRSNT_FANBP_0_PWR_R_PLD_N",
+			"FPGA_P24V_AUX_INA230_ALERT_N_R", "FPGA_SMB_TMC75_TEMP_ALERT_N_R";
+	};
+
+	fpga_io_expander65: gpio@65 {
+		compatible = "nxp,pca9555";
+		reg = <0x65>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		gpio-line-names =
+			"FPGA_PCI_DIS_N", "FPGA_DEV_DIS_N",
+			"FPGA_PWRGD_P3V3_AUX_R", "FPGA_PWRGD_P5V_AUX_R2",
+			"FPGA_PWRGD_P1V05_AUX_R", "FPGA_P48V_HSC_ALERT_N",
+			"FPGA_PWRGD_P1V5_AUX_R", "FPGA_PWRGD_P52V_HSC_PWROK_R",
+			"FPGA_R_COME_THERMTRIP_L", "FPGA_PRSNT_POE_SIG_PLD_N",
+			"FPGA_PRSNT_POE_PWR_PLD_N", "FPGA_PRSNT_RIO_RACKMON_N",
+			"FPGA_PRSNT_CAN2_MCIO_N", "FPGA_PRSNT_CAN1_MCIO_N",
+			"FPGA_PRSNT_RACKMON_MCIO_N", "FPGA_PRSNT_AALC_MCIO_N";
+	};
+
+	fpga_io_expander66: gpio@66 {
+		compatible = "nxp,pca9555";
+		reg = <0x66>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		gpio-line-names =
+			"FPGA_R_FM_CPU_ERR0_LVT3_L", "FPGA_FPGA_R_FM_PCHHOT_L",
+			"FPGA_R_FM_BIOS_POST_CMPLT_L", "FPGA_R_FM_SOC_BMC_RST_L",
+			"FPGA_R_CPU_MSMI_CATERR_N", "FPGA_R_H_MEMHOT_OUT_FET_L",
+			"FPGA_R_PWRGD_P3V3_STBY", "FPGA_R_PWRGD_PCH_PWROK",
+			"FPGA_TRAY23_PWRGD_BUF_R", "FPGA_TRAY24_PWRGD_BUF_R",
+			"FPGA_P24V_AUX_2_INA230_ALERT_N_R", "FPGA_R_IRQ_BMC_PCH_SMI_N",
+			"FPGA_R_FM_CPU_DIMM_EVENT_COD_BUF", "FPGA_R_BIOS_MSG_DIS_L",
+			"FPGA_R_ISO_FM_USB_OC0_L", "FPGA_SPI_LVC_EN";
+	};
+
+	fpga_io_expander67: gpio@67 {
+		compatible = "nxp,pca9555";
+		reg = <0x67>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		gpio-line-names =
+			"FPGA_TRAY29_PWRGD_BUF_R", "FPGA_TRAY30_PWRGD_BUF_R",
+			"FPGA_TRAY31_PWRGD_BUF_R", "FPGA_TRAY32_PWRGD_BUF_R",
+			"FPGA_TRAY37_PWRGD_BUF_R", "FPGA_TRAY38_PWRGD_BUF_R",
+			"FPGA_TRAY39_PWRGD_BUF_R", "FPGA_TRAY40_PWRGD_BUF_R",
+			"FPGA_ISO_CARRIER_BOARD_PWR_OK", "FPGA_UART_MUX_SEL",
+			"", "",
+			"", "",
+			"", "";
+	};
+};
+
+&i2c11 {
+	status = "okay";
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c11mux0ch0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			status = "okay";
+		};
+
+		i2c11mux0ch1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			status = "okay";
+		};
+
+		i2c11mux0ch2: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			status = "okay";
+		};
+
+		i2c11mux0ch3: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c11mux0ch4: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c11mux0ch5: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+		};
+
+		i2c11mux0ch6: i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			status = "okay";
+		};
+
+		i2c11mux0ch7: i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c12 {
+	status = "okay";
+	bus-frequency = <400000>;
+};
+
+&i2c13 {
+	status = "okay";
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c13mux0ch0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			status = "okay";
+		};
+
+		i2c13mux0ch1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			status = "okay";
+		};
+
+		i2c13mux0ch2: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			status = "okay";
+		};
+
+		i2c13mux0ch3: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c13mux0ch4: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c13mux0ch5: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+		};
+
+		i2c13mux0ch6: i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			status = "okay";
+		};
+
+		i2c13mux0ch7: i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c14 {
+	status = "okay";
+};
+
+&i2c15 {
+	status = "okay";
+
+	i2c-mux@77 {
+		compatible = "nxp,pca9548";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c15mux0ch0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			status = "okay";
+		};
+
+		i2c15mux0ch1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			status = "okay";
+		};
+
+		i2c15mux0ch2: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			status = "okay";
+		};
+
+		i2c15mux0ch3: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			status = "okay";
+		};
+
+		i2c15mux0ch4: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			status = "okay";
+		};
+
+		i2c15mux0ch5: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			status = "okay";
+		};
+
+		i2c15mux0ch6: i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			status = "okay";
+		};
+
+		i2c15mux0ch7: i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			status = "okay";
+		};
+	};
+};
+
+&lpc_ctrl {
+	status = "okay";
+};
+
+&kcs3 {
+	aspeed,lpc-io-reg = <0xca2>;
+	status = "okay";
+};
+
+&mac2 {
+	status = "okay";
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_rmii3_default>;
+
+	/*
+	 * The Marvell 88E6393X is initialized at boot via EEPROM
+	 * configuration and hardware straps.
+	 * The BMC connects via an RMII fixed-link; link parameters are fixed
+	 * by board design.
+	 */
+	fixed-link {
+		speed = <100>;
+		full-duplex;
+	};
+};
+
+&mac3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_rmii4_default>;
+	use-ncsi;
+};
+
+&mdio0 {
+	status = "okay";
+};
+
+&peci0 {
+	status = "okay";
+};
+
+&sgpiom0 {
+	status = "okay";
+	ngpios = <128>;
+	bus-frequency = <200000>;
+	gpio-line-names =
+		/*"input pin","output pin"*/
+		/*A0 - A7*/
+		"power-chassis-good","FM_PLD_HEARTBEAT_LVC3_R",
+		"host0-ready","R_BMC_PTH_RST_BTN_L",
+		"CONTROL_VT2_SUPPLY1_CLOSE","FM_MDIO_SW_SEL_PLD",
+		"CONTROL_VT2_SUPPLY2_CLOSE","FM_88E6393X_BIN_UPDATE_EN_N",
+		"CONTROL_VT2_SUPPLY3_CLOSE","Sequence_TransFR_Alert",
+		"RETURN_CNTL1_FB","WATER_VALVE1_OPEN",
+		"RETURN_CNTL2_FB","WATER_VALVE2_OPEN",
+		"RETURN_CNTL3_FB","WATER_VALVE3_OPEN",
+		/*B0 - B7*/
+		"IT_STOP_PUMP_R_CPLD","WATER_VALVE1_CLOSE",
+		"IT_STOP_PUMP_SPARE_R_CPLD","WATER_VALVE2_CLOSE",
+		"IT_STOP_PUMP_2_R_CPLD","WATER_VALVE3_CLOSE",
+		"IT_STOP_PUMP_SPARE_2_R_CPLD","REPORT_VT2_SUPPLY1_CLOSE",
+		"RPU_2_READY_SPARE_PLD_R","REPORT_VT2_SUPPLY2_CLOSE",
+		"RPU_2_READY_PLD_R","REPORT_VT2_SUPPLY3_CLOSE",
+		"RPU_READY_SPARE_PLD_R","PCIE_SSD1_PRSNT_N",
+		"RPU_READY_PLD_R","",
+		/*C0 - C7*/
+		"IOEXP8_INT_N","",
+		"SUPPLY_CNTL1_FB","",
+		"SUPPLY_CNTL2_FB","",
+		"SUPPLY_CNTL3_FB","",
+		"PRSNT_TRAY1_TO_40_R_BUF_N","",
+		"PWRGD_TRAY1_TO_40_R_BUF","",
+		"SMALL_LEAK_TRAY1_TO_40_R_BUF_N","",
+		"LEAK_DETECT_TRAY1_TO_40_R_BUF_N","",
+		/*D0 - D7*/
+		"PRSNT_CANBUSP1_TRAY1_TO_32_N","",
+		"PWRGD_CANBUSP1_TRAY1_TO_32_PWROK","",
+		"SMALL_LEAK_CANBUSP1_TRAY1_TO_32_N","",
+		"LEAK_DETECT_CANBUSP1_TRAY1_TO_32_N","",
+		"PRSNT_CANBUSP2_TRAY1_TO_32_N","",
+		"PWRGD_CANBUSP2_TRAY1_TO_32_PWROK","",
+		"SMALL_LEAK_CANBUSP2_TRAY1_TO_32_N","",
+		"LEAK_DETECT_CANBUSP2_TRAY1_TO_32_N","",
+		/*E0 - E7*/
+		"PRSNT_CANBUSP3_TRAY1_TO_32_N","",
+		"PWRGD_CANBUSP3_TRAY1_TO_32_PWROK","",
+		"SMALL_LEAK_CANBUSP3_TRAY1_TO_32_N","",
+		"LEAK_DETECT_CANBUSP3_TRAY1_TO_32_N","",
+		"PRSNT_CANBUSP4_TRAY1_TO_32_N","",
+		"PWRGD_CANBUSP4_TRAY1_TO_32_PWROK","",
+		"SMALL_LEAK_CANBUSP4_TRAY1_TO_32_N","",
+		"LEAK_DETECT_CANBUSP4_TRAY1_TO_32_N","",
+		/*F0 - F7*/
+		"PRSNT_CANBUSP5_TRAY1_TO_32_N","",
+		"PWRGD_CANBUSP5_TRAY1_TO_32_PWROK","",
+		"SMALL_LEAK_CANBUSP5_TRAY1_TO_32_N","",
+		"LEAK_DETECT_CANBUSP5_TRAY1_TO_32_N","",
+		"PRSNT_CANBUSP6_TRAY1_TO_32_N","",
+		"PWRGD_CANBUSP6_TRAY1_TO_32_PWROK","",
+		"SMALL_LEAK_CANBUSP6_TRAY1_TO_32_N","",
+		"LEAK_DETECT_CANBUSP6_TRAY1_TO_32_N","",
+		/*G0 - G7*/
+		"PRSNT_CANBUSP7_TRAY1_TO_32_N","",
+		"PWRGD_CANBUSP7_TRAY1_TO_32_PWROK","",
+		"SMALL_LEAK_CANBUSP7_TRAY1_TO_32_N","",
+		"LEAK_DETECT_CANBUSP7_TRAY1_TO_32_N","",
+		"PRSNT_CANBUSP8_TRAY1_TO_32_N","",
+		"PWRGD_CANBUSP8_TRAY1_TO_32_PWROK","",
+		"SMALL_LEAK_CANBUSP8_TRAY1_TO_32_N","",
+		"LEAK_DETECT_CANBUSP8_TRAY1_TO_32_N","",
+		/*H0 - H7*/
+		"CHASSIS0_LEAK_Q_N_R","",
+		"CHASSIS1_LEAK_Q_N_R","",
+		"CHASSIS2_LEAK_Q_N_R","",
+		"CHASSIS3_LEAK_Q_N_R","",
+		"CHASSIS4_LEAK_Q_N_R","",
+		"CHASSIS5_LEAK_Q_N_R","",
+		"CHASSIS6_LEAK_Q_N_R","",
+		"CHASSIS7_LEAK_Q_N_R","",
+		/*I0 - I7*/
+		"CHASSIS8_LEAK_Q_N_R","",
+		"CHASSIS9_LEAK_Q_N_R","",
+		"CHASSIS10_LEAK_Q_N_R","",
+		"CHASSIS11_LEAK_Q_N_R","",
+		"AALC_RPU_READY","",
+		"","",
+		"","",
+		"","",
+		/*J0 - J7*/
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		/*K0 - K7*/
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		"","",
+		/*L0 - L7*/
+		"IT_GEAR_RPU_2_LINK_PRSNT_SPARE_N_R","",
+		"IT_GEAR_RPU_2_LINK_PRSNT_N_R","",
+		"IT_GEAR_RPU_LINK_PRSNT_SPARE_N_R","",
+		"IT_GEAR_RPU_LINK_PRSNT_N_R","",
+		"","",
+		"","",
+		"","",
+		"","",
+		/*M0 - M7*/
+		"","",
+		"","",
+		"PRSNT_SENSOR_N","",
+		"PRSNT3_VT2_PLD_N","",
+		"PRSNT2_VT2_PLD_N","",
+		"PRSNT1_VT2_PLD_N","",
+		"PRSNT3_RETURN_PLD_N","",
+		"PRSNT2_RETURN_PLD_N","",
+		/*N0 - N7*/
+		"PRSNT1_RETURN_PLD_N","",
+		"PRSNT3_SUPPLY_PLD_N","",
+		"PRSNT2_SUPPLY_PLD_N","",
+		"PRSNT1_SUPPLY_PLD_N","",
+		"PRSNT_LEAK11_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK10_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK9_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK8_SENSOR_R_PLD_N","",
+		/*O0 - O7*/
+		"PRSNT_LEAK7_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK6_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK5_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK4_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK3_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK2_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK1_SENSOR_R_PLD_N","",
+		"PRSNT_LEAK0_SENSOR_R_PLD_N","",
+		/*P0 - P7*/
+		"","",
+		"","",
+		"","",
+		"","",
+		"","SGPIO_REG_VALID_0",
+		"","SGPIO_REG_VALID_1",
+		"","SGPIO_REG_VALID_2",
+		"","SGPIO_REG_VALID_3";
+};
+
+&spi2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spi2_default>;
+
+	flash@0 {
+		status = "okay";
+		m25p,fast-read;
+		label = "pnor";
+		spi-max-frequency = <12000000>;
+		spi-tx-bus-width = <2>;
+		spi-rx-bus-width = <2>;
+	};
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&wdt1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdtrst1_default>;
+	aspeed,reset-type = "soc";
+	aspeed,external-signal;
+	aspeed,ext-push-pull;
+	aspeed,ext-active-high;
+	aspeed,ext-pulse-duration = <256>;
+};
+

-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 1/2] dt-bindings: arm: aspeed: add Meta ventura2 board
From: Kyle Hsieh @ 2026-04-24  9:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
	Kyle Hsieh, Krzysztof Kozlowski
In-Reply-To: <20260424-ventura2_initial_dts-v4-0-806b00ea4314@gmail.com>

Document the new compatibles used on Facebook ventura2.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Kyle Hsieh <kylehsieh1995@gmail.com>
---
 Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 9298c1a75dd1..d48607c86e8e 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -92,6 +92,7 @@ properties:
               - facebook,harma-bmc
               - facebook,minerva-cmc
               - facebook,santabarbara-bmc
+              - facebook,ventura2-rmc
               - facebook,yosemite4-bmc
               - facebook,yosemite5-bmc
               - ibm,balcones-bmc

-- 
2.34.1



^ permalink raw reply related

* [PATCH v4 0/2] Add Meta(Facebook) ventura2 BMC(AST2600)
From: Kyle Hsieh @ 2026-04-24  9:30 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel,
	Kyle Hsieh, Krzysztof Kozlowski

Summary:
Add linux device tree entry related to Meta(Facebook) ventura2.
specific devices connected to BMC(AST2600) SoC.

Signed-off-by: Kyle Hsieh <kylehsieh1995@gmail.com>
---
Changes in v4:
- Fixed capitalization: "ventura2" -> "Ventura2".
- Reordered I2C child nodes in ascending order of unit addresses.
- Enable PECI, LPC control, and KCS3 interfaces for host communication.
- Configure MCTP controller on I2C4 and enable MCTP support for specific mux channels.
- Add Infineon TDA38640 and TI INA230 power monitor nodes.
- GPIO and Pinmux cleanup for PVT:
    - Aligned gpio-line-names as requested.
    - Remove unused or non-existent GPIO line names to align with Ventura2 PVT.
    - Update specific GPIO pins to empty strings where signals were removed or consolidated.
- Adjust SGPIOM frequency to 200kHz and update signal line names.
- Enable UART3 and add serial2 alias.
- Link to v3: https://lore.kernel.org/r/20260113-ventura2_initial_dts-v3-0-2dbfda6a5b47@gmail.com

Changes in v3:
- Add annotation for marvel 88e6393x
- Modify the gpio-line-name
- Modify the node order alphabetically
- Modify dt-bindings document for rmc instead of bmc
- Move the gpio-line-names to original node
- Link to v2: https://lore.kernel.org/r/20251224-ventura2_initial_dts-v2-0-f193ba5d4073@gmail.com

Changes in v2:
- Remove unused mdio
- Link to v1: https://lore.kernel.org/r/20251222-ventura2_initial_dts-v1-0-1f06166c78a3@gmail.com

---
Kyle Hsieh (2):
      dt-bindings: arm: aspeed: add Meta ventura2 board
      ARM: dts: aspeed: ventura2: Add Meta ventura2 BMC

 .../devicetree/bindings/arm/aspeed/aspeed.yaml     |    1 +
 arch/arm/boot/dts/aspeed/Makefile                  |    1 +
 .../dts/aspeed/aspeed-bmc-facebook-ventura2.dts    | 2925 ++++++++++++++++++++
 3 files changed, 2927 insertions(+)
---
base-commit: 9448598b22c50c8a5bb77a9103e2d49f134c9578
change-id: 20251222-ventura2_initial_dts-909b3277d665

Best regards,
-- 
Kyle Hsieh <kylehsieh1995@gmail.com>



^ permalink raw reply

* Re: [PATCH 1/4] arm64: signal: Preserve POR_EL0 if poe_context is missing
From: Kevin Brodsky @ 2026-04-24  9:24 UTC (permalink / raw)
  To: Will Deacon
  Cc: linux-arm-kernel, linux-kernel, Catalin Marinas, Joey Gouly,
	Mark Brown, Shuah Khan, linux-kselftest
In-Reply-To: <aeoTX_6nK6oHw5OE@willie-the-truck>

On 23/04/2026 14:41, Will Deacon wrote:
> On Wed, Apr 22, 2026 at 04:55:05PM +0200, Kevin Brodsky wrote:
>> On 22/04/2026 14:19, Will Deacon wrote:
>>>> @@ -74,8 +76,12 @@ struct rt_sigframe_user_layout {
>>>>   * This state needs to be carefully managed to ensure that it doesn't cause
>>>>   * uaccess to fail when setting up the signal frame, and the signal handler
>>>>   * itself also expects a well-defined state when entered.
>>>> + *
>>>> + * The valid_fields member is a bitfield (see UA_STATE_HAS_*), specifying which
>>>> + * of the remaining fields is valid (has been set to a value).
>>>>   */
>>>>  struct user_access_state {
>>>> +	unsigned int valid_fields;
>>>>  	u64 por_el0;
>>>>  };
>>> Do you think it would be worth adding some accessors to make it easier
>>> to keep the flags in sync? For example:
>>>
>>> /* Stores por_el0 into uas->por_el0 and sets UA_STATE_HAS_POR_EL0 */
>>> void set_ua_state_por_el0(struct user_access_state *uas, u64 por_el0);
>>>
>>> /*
>>>  * If UA_STATE_HAS_POR_EL0, *por_el0 = uas->por_el0 and return 0.
>>>  * Otherwise, return -ENOENT.
>>>  */
>>> int get_ua_state_por_el0(struct user_access_state *uas, u64 *por_el0);
>>>
>>> WDYT?
>> I did get a feeling having helpers would be a good idea. I wonder if
>> getters/setters aren't a bit overkill though, as they make accesses to
>> the struct more cumbersome and we'd need a pair for every member (unless
>> we use some macro magic).
> We only have one struct member, so it's probably fine for now, and we
> could group related members together in sub-structures to help in future.
> But it's up to you -- I don't feel strongly about it, but requiring the
> caller to update the flag manually is going to be a bug magnet.
>
>> Maybe it would be sufficient to have say
>> ua_state_has_field(POR_EL0) to check if the bit is set, and
>> ua_state_set_field_valid(POR_EL0) to set the bit?
> I don't think that really helps with my concern. I'd like to avoid callers
> having to remember to deal with the flags when they update the data.

Got it. I can't think of a better way to do this so I'll just go ahead
with your suggestion, and prefix all members of the struct with __ to
make it clear they shouldn't be accessed directly. The macro magic can
wait until we have more than one struct member ;)

I've also reconsidered setup_sigframe() and realised using valid_fields
there is not a great idea, because the record is allocated in
setup_sigframe_layout() based on system_supports_poe(), and leaving a
record uninitialised would be bad™. I'll remove that change and I'll
have preserve_poe_context() fail with a WARN_ON() if
get_ua_state_por_el0() somehow returns an error.

- Kevin


^ permalink raw reply

* Re: [PATCH v3 1/4] kernel: param: initialize module_kset on-demand
From: Shashank Balaji @ 2026-04-24  9:16 UTC (permalink / raw)
  To: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
	Maxime Coquelin, Alexandre Torgue, Greg Kroah-Hartman,
	Rafael J. Wysocki, Danilo Krummrich, Miguel Ojeda, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Alice Ryhl, Trevor Gross, Richard Cochran, Jonathan Corbet,
	Shuah Khan
  Cc: Rahul Bukte, linux-kernel, coresight, linux-arm-kernel,
	driver-core, rust-for-linux, linux-doc, Daniel Palmer, Tim Bird
In-Reply-To: <20260422-acpi_mod_name-v3-1-a184eff9ff6f@sony.com>

On Wed, Apr 22, 2026 at 06:49:03PM +0900, Shashank Balaji wrote:
> module_kset is initialized in param_sysfs_init(), a subsys_initcall. A number
> of platform drivers register themselves prior to subsys_initcalls. With an
> upcoming patch ("driver core: platform: set mod_name in driver registration")
> that sets their mod_name in struct device_driver, lookup_or_create_module()
> will be called for those drivers, which calls kset_find_object(module_kset, mod_name).
> This fails because module_kset isn't alive yet.
> 
> Fix this by initializing module_kset on-demand in lookup_or_create_module().
> Retain the param_sysfs_init() subsys_initcall to ensure that module_kset is
> live after subsys_initcalls (assuming no OOM) for any users who may need it,
> on the off chance that it wasn't init'd on-demand because of no
> pre-subsys_initcall drivers.
> 
> This on-demand path can trigger before subsys_initcall. kset_create_and_add()
> be should safe in those contexts because the allocator is up and running by then,
> no userspace to start uevent helper or listen to a uevent socket.
> 
> Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
> Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
> Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
> 
> ---
> 
> Patch 3 depends on this patch.
> ---
>  kernel/params.c | 41 +++++++++++++++++++++++++----------------
>  1 file changed, 25 insertions(+), 16 deletions(-)
> 
> diff --git a/kernel/params.c b/kernel/params.c
> index 74d620bc2521..f25d6fda159c 100644
> --- a/kernel/params.c
> +++ b/kernel/params.c
> @@ -745,6 +745,26 @@ void module_param_sysfs_remove(struct module *mod)
>  }
>  #endif
>  
> +static int uevent_filter(const struct kobject *kobj)
> +{
> +	const struct kobj_type *ktype = get_ktype(kobj);
> +
> +	if (ktype == &module_ktype)
> +		return 1;
> +	return 0;
> +}
> +
> +static const struct kset_uevent_ops module_uevent_ops = {
> +	.filter = uevent_filter,
> +};
> +
> +static struct kset *__init_or_module ensure_module_kset(void)
> +{
> +	if (!module_kset)
> +		module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
> +	return module_kset;
> +}

Sashiko's review [1]:

	Could this cause a race condition if multiple threads try to initialize
	module_kset concurrently?

	If asynchronous driver registration triggers this path concurrently before
	subsys_initcalls, is it possible for both threads to see module_kset as NULL:

	Thread 1
	    if (!module_kset)
		module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
		/* Succeeds and assigns a valid kset */

	Thread 2
	    if (!module_kset)
		module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
		/* Fails due to duplicate name and returns NULL */

	If Thread 2 overwrites module_kset with NULL after Thread 1 succeeds, wouldn't
	this orphan the kset created by Thread 1 and cause all subsequent callers to
	fail? Does this initialization need synchronization to prevent this?

While all pre-subsys_initcall platform driver registration happens
synchronously now, on the boot cpu, asynchronous registration may be
introduced in the future which would silently break this patch. Either
way, it would be better to be safe with a mutex.

I also noticed another problem with this patch: kset_create_and_add() is
called as long as module_kset is not set. So in the case of OOM, init
will be attempted as long as it succeeds, even beyond subsys_initcall.
While the current behaviour is to init only in subsys_initcall.

Both of these can be fixed with a DO_ONCE_SLEEPABLE-based
initialization.

[1] https://sashiko.dev/#/patchset/20260422-acpi_mod_name-v3-0-a184eff9ff6f@sony.com?part=1


^ permalink raw reply

* [PATCH net] net: airoha: Do not read uninitialized fragment address in airoha_dev_xmit()
From: Lorenzo Bianconi @ 2026-04-24  9:00 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: Simon Horman, linux-arm-kernel, linux-mediatek, netdev,
	Lorenzo Bianconi

The transmit loop in airoha_dev_xmit() reads fragment address and length
during its final iteration, when the loop index equals
skb_shinfo(skb)->nr_frags, at which point the fragment data is
uninitialized. While these values are never consumed, the read itself is
unsafe and may trigger a page fault. Fix this by avoiding the fragment
read on the last iteration.
Additionally, move the skb pointer from the first to the last used packet
descriptor, so that airoha_qdma_tx_napi_poll() defers freeing the skb
until the final descriptor is processed.

Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/ethernet/airoha/airoha_eth.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 2bb0a3ff9810..d3a841908c82 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -1997,8 +1997,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
 	struct netdev_queue *txq;
 	struct airoha_queue *q;
 	LIST_HEAD(tx_list);
+	int i = 0, qid;
 	void *data;
-	int i, qid;
 	u16 index;
 	u8 fport;
 
@@ -2057,7 +2057,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
 			     list);
 	index = e - q->entry;
 
-	for (i = 0; i < nr_frags; i++) {
+	while (true) {
 		struct airoha_qdma_desc *desc = &q->desc[index];
 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 		dma_addr_t addr;
@@ -2069,7 +2069,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
 			goto error_unmap;
 
 		list_move_tail(&e->list, &tx_list);
-		e->skb = i ? NULL : skb;
+		e->skb = i == nr_frags - 1 ? skb : NULL;
 		e->dma_addr = addr;
 		e->dma_len = len;
 
@@ -2088,6 +2088,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
 		WRITE_ONCE(desc->msg1, cpu_to_le32(msg1));
 		WRITE_ONCE(desc->msg2, cpu_to_le32(0xffff));
 
+		if (++i == nr_frags)
+			break;
+
 		data = skb_frag_address(frag);
 		len = skb_frag_size(frag);
 	}

---
base-commit: e728258debd553c95d2e70f9cd97c9fde27c7130
change-id: 20260423-airoha-xmit-fix-read-frag-dc6aa001ca4b

Best regards,
-- 
Lorenzo Bianconi <lorenzo@kernel.org>



^ permalink raw reply related

* Re: [PATCH RFC] iommu: Enable per-device SSID space for SVA
From: Joonwon Kang @ 2026-04-24  8:57 UTC (permalink / raw)
  To: joonwonkang
  Cc: Alexander.Grest, amhetre, baolu.lu, iommu, jgg, joro, kees,
	linux-arm-kernel, linux-kernel, nicolinc, praan, robin.murphy,
	smostafa, will
In-Reply-To: <20260424085011.3502295-1-joonwonkang@google.com>

> For SVA, the IOMMU core always allocates PASID from the global PASID
> space. The use of this global PASID space comes from the limitation of
> the ENQCMD instruction in Intel CPUs that it fetches its PASID operand
> from IA32_PASID, which is per-task.
> 
> Due to this nature, SVA with ARM SMMU v3 has been found not working in
> our environment when other modules/devices compete for PASID. The
> environment looks as follows:
> 
> - The device is not a PCIe device.
> - The device is to use SVA.
> - The supported SSID/PASID space is very small for the device; only 1 to
>   3 SSIDs are supported.
> - There is a custom way of transmitting the SSID from the kernel to the
>   device.
> 
> With this setup, when other modules have allocated all the PASIDs that
> our device is expected to use from the global PASID space via APIs like
> iommu_alloc_global_pasid() or iommu_sva_bind_device(), SVA binding to
> our device fails due to the lack of available PASIDs.
> 
> Since SSID/PASID is supported per-SID in ARM SMMU v3, this commit
> leverages the fact and lifts the use of the global PASID space if
> possible. What it does includes:
> 
> - Introduce a new IOMMU capability IOMMU_CAP_PER_DEV_PASID_SPACE, which
>   represents whether the IOMMU supports an independent PASID space per-
>   device, not shared across devices. ARM SMMU v3 is the case.
> - Open a new API iommu_attach_device_pasid_any() to allocate any
>   available PASID and attach an IOMMU domain to it.
> - Opt out the use of the global PASID space for SVA if the IOMMU has
>   that capability, and use the new API to allocate a PASID in that case.
> 
> Signed-off-by: Joonwon Kang <joonwonkang@google.com>

Please disregard this RFC as I have sent a new one with more recipients.

Thanks,
Joonwon Kang


^ permalink raw reply

* Re: [PATCH v5 8/8] ARM: defconfig: Add a zx29 defconfig file
From: Arnd Bergmann @ 2026-04-24  8:54 UTC (permalink / raw)
  To: Linus Walleij, Stefan Dösinger
  Cc: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Krzysztof Kozlowski,
	Alexandre Belloni, Drew Fustini, Greg Kroah-Hartman, Jiri Slaby,
	linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
	linux-serial
In-Reply-To: <CAD++jL=_eDY_mG_QBreSrZiho0hUrDSciedq=vrxXaTiMwrSyg@mail.gmail.com>

On Fri, Apr 24, 2026, at 09:13, Linus Walleij wrote:
> On Tue, Apr 21, 2026 at 10:24 PM Stefan Dösinger
> <stefandoesinger@gmail.com> wrote:
>
>> This enables existing drivers that already are (UART) or will be (USB,
>> GPIO) necessary to operate this board even if they aren't declared in
>> the DTS yet.
>>
>> Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
>
> *I* personally (as SoC maintainer) think that having a few more defconfigs
> is fine, even helpful.
>
> But I would defer this to the more senior SoC maintainers because I think
> their stance is something like:
>
> - We have multi_v7_defconfig for compile testing
>
> - We know that binary gets way to big for your system: it's for build
>   testing and perhaps booting in QEMU or systems with many MB of
>   RAM, not for actually running it on products.
>
> - You are encouraged to keep your own defconfig out-of-tree.

Right, we clearly need to do something better than what we are with
the general defconfigs, as I'm sure many of the existing ones are
never actually used for booting a machine, and are horribly out of
date with the Kconfig options.

I wouldn't object to adding another defconfig for a new (or revived)
soc family, but I don't want to have more per-board ones.
Overall, we have about 70 defconfigs and 55 soc families that have their
own mach-* directory (plus a few without code), and the number of
defconfigs alone makes it hard to keep them up to date. 

> However I even challenged this myself by adding a defconfig for memory
> constrained Broadcoms a while back (NACKed/ignored ;) so if it was all
> up to me I would merge this.

I don't even remember that discussion ;-)

One idea might be to have a tiny base defconfig, plus platform
specific fragments that add drivers. The problem is agreeing
what bits are essential enough to still get enabled in the
tiny config.

       Arnd


^ permalink raw reply

* [PATCH RFC] iommu: Enable per-device SSID space for SVA
From: Joonwon Kang @ 2026-04-24  8:53 UTC (permalink / raw)
  To: will, robin.murphy, joro, jpb
  Cc: jgg, nicolinc, praan, kees, amhetre, Alexander.Grest, baolu.lu,
	smostafa, linux-arm-kernel, iommu, linux-kernel, Joonwon Kang

For SVA, the IOMMU core always allocates PASID from the global PASID
space. The use of this global PASID space comes from the limitation of
the ENQCMD instruction in Intel CPUs that it fetches its PASID operand
from IA32_PASID, which is per-task.

Due to this nature, SVA with ARM SMMU v3 has been found not working in
our environment when other modules/devices compete for PASID. The
environment looks as follows:

- The device is not a PCIe device.
- The device is to use SVA.
- The supported SSID/PASID space is very small for the device; only 1 to
  3 SSIDs are supported.
- There is a custom way of transmitting the SSID from the kernel to the
  device.

With this setup, when other modules have allocated all the PASIDs that
our device is expected to use from the global PASID space via APIs like
iommu_alloc_global_pasid() or iommu_sva_bind_device(), SVA binding to
our device fails due to the lack of available PASIDs.

Since SSID/PASID is supported per-SID in ARM SMMU v3, this commit
leverages the fact and lifts the use of the global PASID space if
possible. What it does includes:

- Introduce a new IOMMU capability IOMMU_CAP_PER_DEV_PASID_SPACE, which
  represents whether the IOMMU supports an independent PASID space per-
  device, not shared across devices. ARM SMMU v3 is the case.
- Open a new API iommu_attach_device_pasid_any() to allocate any
  available PASID and attach an IOMMU domain to it.
- Opt out the use of the global PASID space for SVA if the IOMMU has
  that capability, and use the new API to allocate a PASID in that case.

Signed-off-by: Joonwon Kang <joonwonkang@google.com>
---
v1: Request comments for this approach, other possible approaches and/or
  other aspects to consider more. Code is not sanitized and commits are
  not separated appropriately in this version.

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |  2 +
 drivers/iommu/iommu-sva.c                   | 44 +++++++----
 drivers/iommu/iommu.c                       | 85 ++++++++++++++++++++-
 include/linux/iommu.h                       |  5 ++
 4 files changed, 121 insertions(+), 15 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 4d00d796f078..3a700ab0b5c7 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2494,6 +2494,8 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
 		return true;
 	case IOMMU_CAP_DIRTY_TRACKING:
 		return arm_smmu_dbm_capable(master->smmu);
+	case IOMMU_CAP_PER_DEV_PASID_SPACE:
+		return true;
 	default:
 		return false;
 	}
diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index 07d64908a05f..637d8fd29cbf 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -21,6 +21,7 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
 {
 	struct iommu_mm_data *iommu_mm;
 	ioasid_t pasid;
+	const struct iommu_ops *ops = dev_iommu_ops(dev);
 
 	lockdep_assert_held(&iommu_sva_lock);
 
@@ -39,11 +40,18 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
 	if (!iommu_mm)
 		return ERR_PTR(-ENOMEM);
 
-	pasid = iommu_alloc_global_pasid(dev);
-	if (pasid == IOMMU_PASID_INVALID) {
-		kfree(iommu_mm);
-		return ERR_PTR(-ENOSPC);
+	if (ops->capable && ops->capable(dev, IOMMU_CAP_PER_DEV_PASID_SPACE)) {
+		pasid = IOMMU_NO_PASID;
+		iommu_mm->pasid_global = false;
+	} else {
+		pasid = iommu_alloc_global_pasid(dev);
+		if (pasid == IOMMU_PASID_INVALID) {
+			kfree(iommu_mm);
+			return ERR_PTR(-ENOSPC);
+		}
+		iommu_mm->pasid_global = true;
 	}
+
 	iommu_mm->pasid = pasid;
 	iommu_mm->mm = mm;
 	INIT_LIST_HEAD(&iommu_mm->sva_domains);
@@ -114,13 +122,15 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
 		goto out_unlock;
 	}
 
-	/* Search for an existing domain. */
-	list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
-		ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
-						&handle->handle);
-		if (!ret) {
-			domain->users++;
-			goto out;
+	if (iommu_mm->pasid != IOMMU_NO_PASID) {
+		/* Search for an existing domain. */
+		list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
+			ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
+							&handle->handle);
+			if (!ret) {
+				domain->users++;
+				goto out;
+			}
 		}
 	}
 
@@ -131,8 +141,13 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
 		goto out_free_handle;
 	}
 
-	ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
-					&handle->handle);
+	if (iommu_mm->pasid != IOMMU_NO_PASID) {
+		ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
+						&handle->handle);
+	} else {
+		ret = iommu_attach_device_pasid_any(domain, dev, &iommu_mm->pasid,
+						    &handle->handle);
+	}
 	if (ret)
 		goto out_free_domain;
 	domain->users = 1;
@@ -211,7 +226,8 @@ void mm_pasid_drop(struct mm_struct *mm)
 	if (!iommu_mm)
 		return;
 
-	iommu_free_global_pasid(iommu_mm->pasid);
+	if (iommu_mm->pasid_global)
+		iommu_free_global_pasid(iommu_mm->pasid);
 	kfree(iommu_mm);
 }
 
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 35db51780954..b882ecad7f57 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1061,7 +1061,7 @@ struct iommu_group *iommu_group_alloc(void)
 	mutex_init(&group->mutex);
 	INIT_LIST_HEAD(&group->devices);
 	INIT_LIST_HEAD(&group->entry);
-	xa_init(&group->pasid_array);
+	xa_init_flags(&group->pasid_array, XA_FLAGS_ALLOC);
 
 	ret = ida_alloc(&iommu_group_ida, GFP_KERNEL);
 	if (ret < 0) {
@@ -3619,6 +3619,89 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
 }
 EXPORT_SYMBOL_GPL(iommu_attach_device_pasid);
 
+/**
+ * iommu_attach_device_pasid_any() - Allocate a pasid of device and attach a
+ * domain to it
+ * @domain: the iommu domain.
+ * @dev: the attached device.
+ * @pasid: pointer to the pasid of the device to be allocated.
+ * @handle: the attach handle.
+ *
+ * Caller should always provide a new handle to avoid race with the paths
+ * that have lockless reference to handle if it intends to pass a valid handle.
+ *
+ * Return: 0 on success, or an error.
+ */
+int iommu_attach_device_pasid_any(struct iommu_domain *domain,
+				  struct device *dev,
+				  ioasid_t *pasid,
+				  struct iommu_attach_handle *handle)
+{
+	/* Caller must be a probed driver on dev */
+	struct iommu_group *group = dev->iommu_group;
+	const struct iommu_ops *ops;
+	void *entry;
+	u32 new_pasid;
+	int ret;
+
+	if (!group)
+		return -ENODEV;
+
+	ops = dev_iommu_ops(dev);
+
+	if (!domain->ops->set_dev_pasid ||
+	    !ops->blocked_domain ||
+	    !ops->blocked_domain->ops->set_dev_pasid)
+		return -EOPNOTSUPP;
+
+	if (!domain_iommu_ops_compatible(ops, domain) || !pasid)
+		return -EINVAL;
+
+	mutex_lock(&group->mutex);
+
+	/*
+	 * This is a concurrent attach during a device reset. Reject it until
+	 * pci_dev_reset_iommu_done() attaches the device to group->domain.
+	 */
+	if (group->resetting_domain) {
+		ret = -EBUSY;
+		goto out_unlock;
+	}
+
+	entry = iommu_make_pasid_array_entry(domain, handle);
+
+	struct xa_limit limit = {
+		.min = IOMMU_FIRST_GLOBAL_PASID,
+		.max = dev->iommu->max_pasids - 1,
+	};
+
+	ret = xa_alloc(&group->pasid_array, &new_pasid, XA_ZERO_ENTRY, limit, GFP_KERNEL);
+	if (ret)
+		goto out_unlock;
+
+	ret = __iommu_set_group_pasid(domain, group, new_pasid, NULL);
+	if (ret) {
+		xa_release(&group->pasid_array, new_pasid);
+		goto out_unlock;
+	}
+
+	/*
+	 * The xa_insert() above reserved the memory, and the group->mutex is
+	 * held, this cannot fail. The new domain cannot be visible until the
+	 * operation succeeds as we cannot tolerate PRIs becoming concurrently
+	 * queued and then failing attach.
+	 */
+	WARN_ON(xa_is_err(xa_store(&group->pasid_array,
+				   new_pasid, entry, GFP_KERNEL)));
+
+	*pasid = new_pasid;
+
+out_unlock:
+	mutex_unlock(&group->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_attach_device_pasid_any);
+
 /**
  * iommu_replace_device_pasid - Replace the domain that a specific pasid
  *                              of the device is attached to
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 54b8b48c762e..1665f9fe1d8a 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -271,6 +271,7 @@ enum iommu_cap {
 	 */
 	IOMMU_CAP_DEFERRED_FLUSH,
 	IOMMU_CAP_DIRTY_TRACKING,	/* IOMMU supports dirty tracking */
+	IOMMU_CAP_PER_DEV_PASID_SPACE,	/* IOMMU supports per-device PASID space */
 };
 
 /* These are the possible reserved region types */
@@ -1136,6 +1137,7 @@ struct iommu_sva {
 
 struct iommu_mm_data {
 	u32			pasid;
+	bool			pasid_global;
 	struct mm_struct	*mm;
 	struct list_head	sva_domains;
 	struct list_head	mm_list_elm;
@@ -1184,6 +1186,9 @@ void iommu_device_release_dma_owner(struct device *dev);
 int iommu_attach_device_pasid(struct iommu_domain *domain,
 			      struct device *dev, ioasid_t pasid,
 			      struct iommu_attach_handle *handle);
+int iommu_attach_device_pasid_any(struct iommu_domain *domain,
+				  struct device *dev, ioasid_t *pasid,
+				  struct iommu_attach_handle *handle);
 void iommu_detach_device_pasid(struct iommu_domain *domain,
 			       struct device *dev, ioasid_t pasid);
 ioasid_t iommu_alloc_global_pasid(struct device *dev);
-- 
2.54.0.545.g6539524ca2-goog



^ permalink raw reply related

* [PATCH RFC] iommu: Enable per-device SSID space for SVA
From: Joonwon Kang @ 2026-04-24  8:50 UTC (permalink / raw)
  To: will, robin.murphy, joro
  Cc: jgg, nicolinc, praan, kees, amhetre, Alexander.Grest, baolu.lu,
	smostafa, linux-arm-kernel, iommu, linux-kernel, Joonwon Kang

For SVA, the IOMMU core always allocates PASID from the global PASID
space. The use of this global PASID space comes from the limitation of
the ENQCMD instruction in Intel CPUs that it fetches its PASID operand
from IA32_PASID, which is per-task.

Due to this nature, SVA with ARM SMMU v3 has been found not working in
our environment when other modules/devices compete for PASID. The
environment looks as follows:

- The device is not a PCIe device.
- The device is to use SVA.
- The supported SSID/PASID space is very small for the device; only 1 to
  3 SSIDs are supported.
- There is a custom way of transmitting the SSID from the kernel to the
  device.

With this setup, when other modules have allocated all the PASIDs that
our device is expected to use from the global PASID space via APIs like
iommu_alloc_global_pasid() or iommu_sva_bind_device(), SVA binding to
our device fails due to the lack of available PASIDs.

Since SSID/PASID is supported per-SID in ARM SMMU v3, this commit
leverages the fact and lifts the use of the global PASID space if
possible. What it does includes:

- Introduce a new IOMMU capability IOMMU_CAP_PER_DEV_PASID_SPACE, which
  represents whether the IOMMU supports an independent PASID space per-
  device, not shared across devices. ARM SMMU v3 is the case.
- Open a new API iommu_attach_device_pasid_any() to allocate any
  available PASID and attach an IOMMU domain to it.
- Opt out the use of the global PASID space for SVA if the IOMMU has
  that capability, and use the new API to allocate a PASID in that case.

Signed-off-by: Joonwon Kang <joonwonkang@google.com>
---
v1: Request comments for this approach, other possible approaches and/or
  other aspects to consider more. Code is not sanitized and commits are
  not separated appropriately in this version.

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |  2 +
 drivers/iommu/iommu-sva.c                   | 44 +++++++----
 drivers/iommu/iommu.c                       | 85 ++++++++++++++++++++-
 include/linux/iommu.h                       |  5 ++
 4 files changed, 121 insertions(+), 15 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 4d00d796f078..3a700ab0b5c7 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2494,6 +2494,8 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
 		return true;
 	case IOMMU_CAP_DIRTY_TRACKING:
 		return arm_smmu_dbm_capable(master->smmu);
+	case IOMMU_CAP_PER_DEV_PASID_SPACE:
+		return true;
 	default:
 		return false;
 	}
diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index 07d64908a05f..637d8fd29cbf 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -21,6 +21,7 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
 {
 	struct iommu_mm_data *iommu_mm;
 	ioasid_t pasid;
+	const struct iommu_ops *ops = dev_iommu_ops(dev);
 
 	lockdep_assert_held(&iommu_sva_lock);
 
@@ -39,11 +40,18 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
 	if (!iommu_mm)
 		return ERR_PTR(-ENOMEM);
 
-	pasid = iommu_alloc_global_pasid(dev);
-	if (pasid == IOMMU_PASID_INVALID) {
-		kfree(iommu_mm);
-		return ERR_PTR(-ENOSPC);
+	if (ops->capable && ops->capable(dev, IOMMU_CAP_PER_DEV_PASID_SPACE)) {
+		pasid = IOMMU_NO_PASID;
+		iommu_mm->pasid_global = false;
+	} else {
+		pasid = iommu_alloc_global_pasid(dev);
+		if (pasid == IOMMU_PASID_INVALID) {
+			kfree(iommu_mm);
+			return ERR_PTR(-ENOSPC);
+		}
+		iommu_mm->pasid_global = true;
 	}
+
 	iommu_mm->pasid = pasid;
 	iommu_mm->mm = mm;
 	INIT_LIST_HEAD(&iommu_mm->sva_domains);
@@ -114,13 +122,15 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
 		goto out_unlock;
 	}
 
-	/* Search for an existing domain. */
-	list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
-		ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
-						&handle->handle);
-		if (!ret) {
-			domain->users++;
-			goto out;
+	if (iommu_mm->pasid != IOMMU_NO_PASID) {
+		/* Search for an existing domain. */
+		list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
+			ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
+							&handle->handle);
+			if (!ret) {
+				domain->users++;
+				goto out;
+			}
 		}
 	}
 
@@ -131,8 +141,13 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
 		goto out_free_handle;
 	}
 
-	ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
-					&handle->handle);
+	if (iommu_mm->pasid != IOMMU_NO_PASID) {
+		ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid,
+						&handle->handle);
+	} else {
+		ret = iommu_attach_device_pasid_any(domain, dev, &iommu_mm->pasid,
+						    &handle->handle);
+	}
 	if (ret)
 		goto out_free_domain;
 	domain->users = 1;
@@ -211,7 +226,8 @@ void mm_pasid_drop(struct mm_struct *mm)
 	if (!iommu_mm)
 		return;
 
-	iommu_free_global_pasid(iommu_mm->pasid);
+	if (iommu_mm->pasid_global)
+		iommu_free_global_pasid(iommu_mm->pasid);
 	kfree(iommu_mm);
 }
 
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 35db51780954..b882ecad7f57 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1061,7 +1061,7 @@ struct iommu_group *iommu_group_alloc(void)
 	mutex_init(&group->mutex);
 	INIT_LIST_HEAD(&group->devices);
 	INIT_LIST_HEAD(&group->entry);
-	xa_init(&group->pasid_array);
+	xa_init_flags(&group->pasid_array, XA_FLAGS_ALLOC);
 
 	ret = ida_alloc(&iommu_group_ida, GFP_KERNEL);
 	if (ret < 0) {
@@ -3619,6 +3619,89 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
 }
 EXPORT_SYMBOL_GPL(iommu_attach_device_pasid);
 
+/**
+ * iommu_attach_device_pasid_any() - Allocate a pasid of device and attach a
+ * domain to it
+ * @domain: the iommu domain.
+ * @dev: the attached device.
+ * @pasid: pointer to the pasid of the device to be allocated.
+ * @handle: the attach handle.
+ *
+ * Caller should always provide a new handle to avoid race with the paths
+ * that have lockless reference to handle if it intends to pass a valid handle.
+ *
+ * Return: 0 on success, or an error.
+ */
+int iommu_attach_device_pasid_any(struct iommu_domain *domain,
+				  struct device *dev,
+				  ioasid_t *pasid,
+				  struct iommu_attach_handle *handle)
+{
+	/* Caller must be a probed driver on dev */
+	struct iommu_group *group = dev->iommu_group;
+	const struct iommu_ops *ops;
+	void *entry;
+	u32 new_pasid;
+	int ret;
+
+	if (!group)
+		return -ENODEV;
+
+	ops = dev_iommu_ops(dev);
+
+	if (!domain->ops->set_dev_pasid ||
+	    !ops->blocked_domain ||
+	    !ops->blocked_domain->ops->set_dev_pasid)
+		return -EOPNOTSUPP;
+
+	if (!domain_iommu_ops_compatible(ops, domain) || !pasid)
+		return -EINVAL;
+
+	mutex_lock(&group->mutex);
+
+	/*
+	 * This is a concurrent attach during a device reset. Reject it until
+	 * pci_dev_reset_iommu_done() attaches the device to group->domain.
+	 */
+	if (group->resetting_domain) {
+		ret = -EBUSY;
+		goto out_unlock;
+	}
+
+	entry = iommu_make_pasid_array_entry(domain, handle);
+
+	struct xa_limit limit = {
+		.min = IOMMU_FIRST_GLOBAL_PASID,
+		.max = dev->iommu->max_pasids - 1,
+	};
+
+	ret = xa_alloc(&group->pasid_array, &new_pasid, XA_ZERO_ENTRY, limit, GFP_KERNEL);
+	if (ret)
+		goto out_unlock;
+
+	ret = __iommu_set_group_pasid(domain, group, new_pasid, NULL);
+	if (ret) {
+		xa_release(&group->pasid_array, new_pasid);
+		goto out_unlock;
+	}
+
+	/*
+	 * The xa_insert() above reserved the memory, and the group->mutex is
+	 * held, this cannot fail. The new domain cannot be visible until the
+	 * operation succeeds as we cannot tolerate PRIs becoming concurrently
+	 * queued and then failing attach.
+	 */
+	WARN_ON(xa_is_err(xa_store(&group->pasid_array,
+				   new_pasid, entry, GFP_KERNEL)));
+
+	*pasid = new_pasid;
+
+out_unlock:
+	mutex_unlock(&group->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_attach_device_pasid_any);
+
 /**
  * iommu_replace_device_pasid - Replace the domain that a specific pasid
  *                              of the device is attached to
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 54b8b48c762e..1665f9fe1d8a 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -271,6 +271,7 @@ enum iommu_cap {
 	 */
 	IOMMU_CAP_DEFERRED_FLUSH,
 	IOMMU_CAP_DIRTY_TRACKING,	/* IOMMU supports dirty tracking */
+	IOMMU_CAP_PER_DEV_PASID_SPACE,	/* IOMMU supports per-device PASID space */
 };
 
 /* These are the possible reserved region types */
@@ -1136,6 +1137,7 @@ struct iommu_sva {
 
 struct iommu_mm_data {
 	u32			pasid;
+	bool			pasid_global;
 	struct mm_struct	*mm;
 	struct list_head	sva_domains;
 	struct list_head	mm_list_elm;
@@ -1184,6 +1186,9 @@ void iommu_device_release_dma_owner(struct device *dev);
 int iommu_attach_device_pasid(struct iommu_domain *domain,
 			      struct device *dev, ioasid_t pasid,
 			      struct iommu_attach_handle *handle);
+int iommu_attach_device_pasid_any(struct iommu_domain *domain,
+				  struct device *dev, ioasid_t *pasid,
+				  struct iommu_attach_handle *handle);
 void iommu_detach_device_pasid(struct iommu_domain *domain,
 			       struct device *dev, ioasid_t pasid);
 ioasid_t iommu_alloc_global_pasid(struct device *dev);
-- 
2.54.0.545.g6539524ca2-goog



^ 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