From decca450dcf35b64c7a0faaac61bccc6aa92fe71 Mon Sep 17 00:00:00 2001 From: Stephen Sun Date: Thu, 5 Feb 2026 13:20:32 +0000 Subject: [PATCH] Integrate HW-MGMT 7.0050.3519 Changes ## Patch List * 0054-1-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch : * 0056-hwmon-pmbus-mp2845-Add-support-for-MP2845-device.patch : * 0057-hwmon-pmbus-mp5926-Add-support-for-MP5926-device.patch : Signed-off-by: sw-r2d2-bot Signed-off-by: Stephen Sun --- config.local/amd64/config.sonic | 5 + ...support-for-MPS-Multi-phase-mp2855-c.patch | 2 +- ...x-nvsw-bmc-Add-system-control-and-mo.patch | 1950 ++++++++++++++++- ...-Downstream-Add-support-for-new-Nvi.patch} | 26 +- ...x-Downstream-Add-support-DGX-flavor-.patch | 10 +- ...mp2845-Add-support-for-MP2845-device.patch | 554 +++++ ...mp5926-Add-support-for-MP5926-device.patch | 252 +++ ...tform-Downstream-Add-SPI-path-for-ra.patch | 92 - patches-sonic/series | 5 +- 9 files changed, 2758 insertions(+), 138 deletions(-) rename patches-sonic/{9000-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch => 0054-1-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch} (94%) create mode 100644 patches-sonic/0056-hwmon-pmbus-mp2845-Add-support-for-MP2845-device.patch create mode 100644 patches-sonic/0057-hwmon-pmbus-mp5926-Add-support-for-MP5926-device.patch delete mode 100644 patches-sonic/8001-platform-mlx-platform-Downstream-Add-SPI-path-for-ra.patch diff --git a/config.local/amd64/config.sonic b/config.local/amd64/config.sonic index 23bf715f2..ab39a7e1a 100644 --- a/config.local/amd64/config.sonic +++ b/config.local/amd64/config.sonic @@ -101,6 +101,8 @@ CONFIG_SENSORS_MP2888=m CONFIG_SENSORS_MP2891=m CONFIG_SENSORS_MP2869=m CONFIG_SENSORS_MP29502=m +CONFIG_SENSORS_MP2845=m +CONFIG_SENSORS_MP5926=m CONFIG_GPIO_ICH=m CONFIG_CPU_THERMAL=y CONFIG_IGB_HWMON=y @@ -110,6 +112,9 @@ CONFIG_TI_ADS1015=m CONFIG_PINCTRL_INTEL=y CONFIG_PINCTRL_CANNONLAKE=m CONFIG_PINCTRL_DENVERTON=m +CONFIG_NVSW_HOST_L1=m +CONFIG_NVSW_HOST_SPC5=m +CONFIG_NVSW_HOST_SPC6=m CONFIG_NVSW_SN2201=m CONFIG_I2C_DESIGNWARE_PLATFORM=m CONFIG_I2C_DESIGNWARE_BAYTRAIL=y diff --git a/patches-sonic/0043-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2855-c.patch b/patches-sonic/0043-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2855-c.patch index d09ca494e..54f32f8f0 100644 --- a/patches-sonic/0043-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2855-c.patch +++ b/patches-sonic/0043-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2855-c.patch @@ -102,7 +102,7 @@ index 00000000..3cffd09 + PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_VOUT | \ + PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT | \ + PMBUS_HAVE_STATUS_TEMP) -+ ++ +#define MP2855_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_IOUT | \ + PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT | \ + PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP) diff --git a/patches-sonic/0046-platform-mellanox-nvsw-bmc-Add-system-control-and-mo.patch b/patches-sonic/0046-platform-mellanox-nvsw-bmc-Add-system-control-and-mo.patch index ef97c02fc..ecb6389e2 100644 --- a/patches-sonic/0046-platform-mellanox-nvsw-bmc-Add-system-control-and-mo.patch +++ b/patches-sonic/0046-platform-mellanox-nvsw-bmc-Add-system-control-and-mo.patch @@ -1,7 +1,7 @@ -From 9b36f571a51a32214316a7a4afc3c902b9059f48 Mon Sep 17 00:00:00 2001 +From 14c5add67eda8b7ce73de25302734b22d1777579 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 4 Jul 2024 23:50:27 +0300 -Subject: [PATCH 46/78] platform/mellanox: nvsw-bmc: Add system control and +Subject: [PATCH] platform/mellanox: nvsw-bmc: Add system control and monitoring driver for Nvidia BMC The driver allows system control and monitoring of Nvidia switches @@ -18,21 +18,25 @@ This control includes: Signed-off-by: Vadim Pasternak --- - .../devicetree/bindings/trivial-devices.yaml | 5 + - drivers/platform/mellanox/Kconfig | 18 + - drivers/platform/mellanox/Makefile | 2 + - drivers/platform/mellanox/nvsw-bmc-hid162.c | 2773 ++++++++++++++++++++ - drivers/platform/mellanox/nvsw-core.c | 625 +++++ - drivers/platform/mellanox/nvsw-host-l1.c | 745 ++++++ - drivers/platform/mellanox/nvsw.h | 260 ++ - 7 files changed, 4428 insertions(+) + .../devicetree/bindings/trivial-devices.yaml | 5 + + drivers/platform/mellanox/Kconfig | 38 + + drivers/platform/mellanox/Makefile | 4 + + drivers/platform/mellanox/nvsw-bmc-hid162.c | 2773 +++++++++++++++++ + drivers/platform/mellanox/nvsw-core.c | 694 +++++ + drivers/platform/mellanox/nvsw-host-l1.c | 744 +++++ + drivers/platform/mellanox/nvsw-host-spc5.c | 937 ++++++ + drivers/platform/mellanox/nvsw-host-spc6.c | 821 +++++ + drivers/platform/mellanox/nvsw.h | 296 ++ + 9 files changed, 6312 insertions(+) create mode 100644 drivers/platform/mellanox/nvsw-bmc-hid162.c create mode 100644 drivers/platform/mellanox/nvsw-core.c create mode 100644 drivers/platform/mellanox/nvsw-host-l1.c + create mode 100644 drivers/platform/mellanox/nvsw-host-spc5.c + create mode 100644 drivers/platform/mellanox/nvsw-host-spc6.c create mode 100644 drivers/platform/mellanox/nvsw.h diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml -index a190c56..14568bd 100644 +index a190c5676..14568bd0f 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -307,6 +307,11 @@ properties: @@ -48,10 +52,10 @@ index a190c56..14568bd 100644 - nuvoton,w83773g # OKI ML86V7667 video decoder diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig -index e3afbe6..dd6b576 100644 +index e3afbe62c..6cbda147a 100644 --- a/drivers/platform/mellanox/Kconfig +++ b/drivers/platform/mellanox/Kconfig -@@ -105,6 +105,24 @@ config MLXBF_PMC +@@ -105,6 +105,44 @@ config MLXBF_PMC to performance monitoring counters within various blocks in the Mellanox BlueField SoC via a sysfs interface. @@ -65,31 +69,53 @@ index e3afbe6..dd6b576 100644 + will be called nvsw-bmc-hid162. + +config NVSW_HOST_L1 -+ tristate "Nvidia host CPLD/FPGA Hardware Control and Monitoring" ++ tristate "Nvidia L1 host CPLD/FPGA Hardware Control and Monitoring" + depends on REGMAP_I2C && OF && REGMAP && HWMON + help + Say Y here to include support for the FPGA/CPLD logic by host CPU -+ equipped on Nvidia switches. ++ equipped on Nvidia L1 switches. + This driver can also be built as a module. If so the module + will be called nvsw-host-l1. ++ ++config NVSW_HOST_SPC5 ++ tristate "Nvidia SPC5 host CPLD/FPGA Hardware Control and Monitoring" ++ depends on HWMON ++ select REGMAP_I2C ++ help ++ Say Y here to include support for the FPGA/CPLD logic by host CPU ++ equipped on Nvidia SPC5 ethernet switches. ++ This driver can also be built as a module. If so the module ++ will be called nvsw-host-spc5. ++ ++config NVSW_HOST_SPC6 ++ tristate "Nvidia SPC6 host CPLD/FPGA Hardware Control and Monitoring" ++ depends on HWMON ++ select REGMAP_I2C ++ help ++ Say Y here to include support for the FPGA/CPLD logic by host CPU ++ equipped on Nvidia SPC6 ethernet switches. ++ This driver can also be built as a module. If so the module ++ will be called nvsw-host-spc6. + config NVSW_SN2201 tristate "Nvidia SN2201 platform driver support" depends on HWMON && I2C diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile -index e86723b..4c1aec1 100644 +index e86723b44..123edaa99 100644 --- a/drivers/platform/mellanox/Makefile +++ b/drivers/platform/mellanox/Makefile -@@ -11,4 +11,6 @@ obj-$(CONFIG_MLXREG_DPU) += mlxreg-dpu.o +@@ -11,4 +11,8 @@ obj-$(CONFIG_MLXREG_DPU) += mlxreg-dpu.o obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o obj-$(CONFIG_MLXREG_LC) += mlxreg-lc.o +obj-$(CONFIG_NVSW_BMC_HID162) += nvsw-bmc-hid162.o nvsw-core.o +obj-$(CONFIG_NVSW_HOST_L1) += nvsw-host-l1.o nvsw-core.o ++obj-$(CONFIG_NVSW_HOST_SPC5) += nvsw-host-spc5.o nvsw-core.o ++obj-$(CONFIG_NVSW_HOST_SPC6) += nvsw-host-spc6.o nvsw-core.o obj-$(CONFIG_NVSW_SN2201) += nvsw-sn2201.o diff --git a/drivers/platform/mellanox/nvsw-bmc-hid162.c b/drivers/platform/mellanox/nvsw-bmc-hid162.c new file mode 100644 -index 00000000..fbc7382 +index 000000000..fbc738231 --- /dev/null +++ b/drivers/platform/mellanox/nvsw-bmc-hid162.c @@ -0,0 +1,2773 @@ @@ -2868,10 +2894,10 @@ index 00000000..fbc7382 +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/platform/mellanox/nvsw-core.c b/drivers/platform/mellanox/nvsw-core.c new file mode 100644 -index 00000000..bfe56ab +index 000000000..4f91c9862 --- /dev/null +++ b/drivers/platform/mellanox/nvsw-core.c -@@ -0,0 +1,625 @@ +@@ -0,0 +1,694 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Nvidia BMC platform driver @@ -2900,6 +2926,7 @@ index 00000000..bfe56ab + case NVSW_REG_PG3_EVENT_OFFSET: + case NVSW_REG_PG3_MASK_OFFSET: + case NVSW_REG_PG4_EVENT_OFFSET: ++ case NVSW_REG_PG4_MASK_OFFSET: + case NVSW_REG_RESET_GP1_OFFSET: + case NVSW_REG_FIELD_UPGRADE: + case NVSW_REG_GP0_OFFSET: @@ -2934,6 +2961,8 @@ index 00000000..bfe56ab + case NVSW_REG_VR1_ALERT_MASK_OFFSET: + case NVSW_REG_VR2_ALERT_EVENT_OFFSET: + case NVSW_REG_VR2_ALERT_MASK_OFFSET: ++ case NVSW_REG_PS_DC_OK_EVENT_OFFSET: ++ case NVSW_REG_PS_DC_OK_MASK_OFFSET: + case NVSW_REG_FAN_EVENT_OFFSET: + case NVSW_REG_FAN_MASK_OFFSET: + case NVSW_REG_PWRB_EVENT_OFFSET: @@ -2977,6 +3006,7 @@ index 00000000..bfe56ab + case NVSW_REG_CPLD4_VER_OFFSET: + case NVSW_REG_CPLD4_PN_OFFSET: + case NVSW_REG_CPLD4_PN1_OFFSET: ++ case NVSW_REG_CPLD7_VER_OFFSET: + case NVSW_REG_PG1_OFFSET: + case NVSW_REG_PG1_EVENT_OFFSET: + case NVSW_REG_PG1_MASK_OFFSET: @@ -2989,6 +3019,12 @@ index 00000000..bfe56ab + case NVSW_REG_PG4_OFFSET: + case NVSW_REG_PG4_EVENT_OFFSET: + case NVSW_REG_PG4_MASK_OFFSET: ++ case NVSW_REG_CPLD6_VER_OFFSET: ++ case NVSW_REG_CPLD6_PN_OFFSET: ++ case NVSW_REG_CPLD6_PN1_OFFSET: ++ case NVSW_REG_CPLD9_VER_OFFSET: ++ case NVSW_REG_CPLD10_PN_OFFSET: ++ case NVSW_REG_CPLD10_PN1_OFFSET: + case NVSW_REG_RESET_GP1_OFFSET: + case NVSW_REG_FIELD_UPGRADE: + case NVSW_REG_SAFE_BIOS_OFFSET: @@ -2999,10 +3035,13 @@ index 00000000..bfe56ab + case NVSW_REG_LED5_OFFSET: + case NVSW_REG_LED6_OFFSET: + case NVSW_REG_LED7_OFFSET: ++ case NVSW_REG_CPLD7_PN_OFFSET: ++ case NVSW_REG_CPLD7_PN1_OFFSET: + case NVSW_REG_RESET_GP2_OFFSET: + case NVSW_REG_GP0_RO_OFFSET: + case NVSW_REG_GP1_RO_OFFSET: + case NVSW_REG_GP4_RO_OFFSET: ++ case NVSW_REG_GP5_RO_OFFSET: + case NVSW_REG_GPCOM0_OFFSET: + case NVSW_REG_GP0_OFFSET: + case NVSW_REG_GP1_OFFSET: @@ -3042,9 +3081,18 @@ index 00000000..bfe56ab + case NVSW_REG_VR2_ALERT_OFFSET: + case NVSW_REG_VR2_ALERT_EVENT_OFFSET: + case NVSW_REG_VR2_ALERT_MASK_OFFSET: ++ case NVSW_REG_PS_DC_OK_OFFSET: ++ case NVSW_REG_PS_DC_OK_EVENT_OFFSET: ++ case NVSW_REG_PS_DC_OK_MASK_OFFSET: ++ case NVSW_REG_CPLD8_PN_OFFSET: ++ case NVSW_REG_CPLD8_PN1_OFFSET: ++ case NVSW_REG_CPLD8_VER_OFFSET: + case NVSW_REG_FAN_OFFSET: + case NVSW_REG_FAN_EVENT_OFFSET: + case NVSW_REG_FAN_MASK_OFFSET: ++ case NVSW_REG_CPLD5_VER_OFFSET: ++ case NVSW_REG_CPLD5_PN_OFFSET: ++ case NVSW_REG_CPLD5_PN1_OFFSET: + case NVSW_REG_EROT_OFFSET: + case NVSW_REG_EROT_EVENT_OFFSET: + case NVSW_REG_EROT_MASK_OFFSET: @@ -3084,16 +3132,26 @@ index 00000000..bfe56ab + case NVSW_REG_CONFIG2_OFFSET: + case NVSW_REG_CONFIG3_OFFSET: + case NVSW_REG_SPI_CHNL_SELECT: ++ case NVSW_REG_CPLD5_MVER_OFFSET: ++ case NVSW_REG_CPLD9_PN_OFFSET: ++ case NVSW_REG_CPLD9_PN1_OFFSET: ++ case NVSW_REG_CPLD10_VER_OFFSET: + case NVSW_REG_WD2_TMR_OFFSET: + case NVSW_REG_WD2_TLEFT_OFFSET: + case NVSW_REG_WD2_ACT_OFFSET: + case NVSW_REG_WD3_TMR_OFFSET: + case NVSW_REG_WD3_TLEFT_OFFSET: + case NVSW_REG_WD3_ACT_OFFSET: ++ case NVSW_REG_CPLD7_MVER_OFFSET: ++ case NVSW_REG_CPLD8_MVER_OFFSET: ++ case NVSW_REG_CPLD9_MVER_OFFSET: ++ case NVSW_REG_CPLD10_MVER_OFFSET: ++ case NVSW_REG_CPLD6_MVER_OFFSET: + case NVSW_REG_MUX0_OFFSET: + case NVSW_REG_MUX1_OFFSET: + case NVSW_REG_MUX2_OFFSET: + case NVSW_REG_UFM_VERSION_OFFSET: ++ case NVSW_REG_PSU_I2C_CAP_OFFSET: + return true; + } + return false; @@ -3114,6 +3172,7 @@ index 00000000..bfe56ab + case NVSW_REG_CPLD4_VER_OFFSET: + case NVSW_REG_CPLD4_PN_OFFSET: + case NVSW_REG_CPLD4_PN1_OFFSET: ++ case NVSW_REG_CPLD7_VER_OFFSET: + case NVSW_REG_PG1_OFFSET: + case NVSW_REG_PG1_EVENT_OFFSET: + case NVSW_REG_PG1_MASK_OFFSET: @@ -3126,6 +3185,12 @@ index 00000000..bfe56ab + case NVSW_REG_PG4_OFFSET: + case NVSW_REG_PG4_EVENT_OFFSET: + case NVSW_REG_PG4_MASK_OFFSET: ++ case NVSW_REG_CPLD6_VER_OFFSET: ++ case NVSW_REG_CPLD6_PN_OFFSET: ++ case NVSW_REG_CPLD6_PN1_OFFSET: ++ case NVSW_REG_CPLD9_VER_OFFSET: ++ case NVSW_REG_CPLD10_PN_OFFSET: ++ case NVSW_REG_CPLD10_PN1_OFFSET: + case NVSW_REG_RESET_GP1_OFFSET: + case NVSW_REG_FIELD_UPGRADE: + case NVSW_REG_SAFE_BIOS_OFFSET: @@ -3136,6 +3201,8 @@ index 00000000..bfe56ab + case NVSW_REG_LED5_OFFSET: + case NVSW_REG_LED6_OFFSET: + case NVSW_REG_LED7_OFFSET: ++ case NVSW_REG_CPLD7_PN_OFFSET: ++ case NVSW_REG_CPLD7_PN1_OFFSET: + case NVSW_REG_RESET_GP2_OFFSET: + case NVSW_REG_GP0_RO_OFFSET: + case NVSW_REG_GP1_RO_OFFSET: @@ -3178,9 +3245,18 @@ index 00000000..bfe56ab + case NVSW_REG_VR2_ALERT_OFFSET: + case NVSW_REG_VR2_ALERT_EVENT_OFFSET: + case NVSW_REG_VR2_ALERT_MASK_OFFSET: ++ case NVSW_REG_PS_DC_OK_OFFSET: ++ case NVSW_REG_PS_DC_OK_EVENT_OFFSET: ++ case NVSW_REG_PS_DC_OK_MASK_OFFSET: ++ case NVSW_REG_CPLD8_PN_OFFSET: ++ case NVSW_REG_CPLD8_PN1_OFFSET: ++ case NVSW_REG_CPLD8_VER_OFFSET: + case NVSW_REG_FAN_OFFSET: + case NVSW_REG_FAN_EVENT_OFFSET: + case NVSW_REG_FAN_MASK_OFFSET: ++ case NVSW_REG_CPLD5_VER_OFFSET: ++ case NVSW_REG_CPLD5_PN_OFFSET: ++ case NVSW_REG_CPLD5_PN1_OFFSET: + case NVSW_REG_EROT_OFFSET: + case NVSW_REG_EROT_EVENT_OFFSET: + case NVSW_REG_EROT_MASK_OFFSET: @@ -3197,6 +3273,7 @@ index 00000000..bfe56ab + case NVSW_REG_LEAK_EVENT_OFFSET: + case NVSW_REG_LEAK_MASK_OFFSET: + case NVSW_REG_GP4_RO_OFFSET: ++ case NVSW_REG_GP5_RO_OFFSET: + case NVSW_REG_CPLD1_MVER_OFFSET: + case NVSW_REG_CPLD2_MVER_OFFSET: + case NVSW_REG_CPLD3_MVER_OFFSET: @@ -3221,9 +3298,18 @@ index 00000000..bfe56ab + case NVSW_REG_CONFIG2_OFFSET: + case NVSW_REG_CONFIG3_OFFSET: + case NVSW_REG_SPI_CHNL_SELECT: ++ case NVSW_REG_CPLD5_MVER_OFFSET: ++ case NVSW_REG_CPLD9_PN_OFFSET: ++ case NVSW_REG_CPLD9_PN1_OFFSET: ++ case NVSW_REG_CPLD10_VER_OFFSET: + case NVSW_REG_WD2_TMR_OFFSET: + case NVSW_REG_WD2_TLEFT_OFFSET: + case NVSW_REG_WD2_ACT_OFFSET: ++ case NVSW_REG_CPLD7_MVER_OFFSET: ++ case NVSW_REG_CPLD8_MVER_OFFSET: ++ case NVSW_REG_CPLD9_MVER_OFFSET: ++ case NVSW_REG_CPLD10_MVER_OFFSET: ++ case NVSW_REG_CPLD6_MVER_OFFSET: + case NVSW_REG_WD3_TMR_OFFSET: + case NVSW_REG_WD3_TLEFT_OFFSET: + case NVSW_REG_WD3_ACT_OFFSET: @@ -3231,6 +3317,7 @@ index 00000000..bfe56ab + case NVSW_REG_MUX1_OFFSET: + case NVSW_REG_MUX2_OFFSET: + case NVSW_REG_UFM_VERSION_OFFSET: ++ case NVSW_REG_PSU_I2C_CAP_OFFSET: + return true; + } + return false; @@ -3311,6 +3398,7 @@ index 00000000..bfe56ab + sizeof(*nvsw_core->regio_data)); + if (IS_ERR(nvsw_core->regio)) { + err = PTR_ERR(nvsw_core->regio); ++ dev_err(nvsw_core->dev, "Failed to register mlxreg-io driver\n"); + goto fail_platform_io_register; + } + } @@ -3337,6 +3425,7 @@ index 00000000..bfe56ab + sizeof(*nvsw_core->led_data)); + if (IS_ERR(nvsw_core->led)) { + err = PTR_ERR(nvsw_core->led); ++ dev_err(nvsw_core->dev, "Failed to register leds-mlxreg driver\n"); + goto fail_platform_leds_register; + } + } @@ -3366,6 +3455,7 @@ index 00000000..bfe56ab + sizeof(*nvsw_core->wd_data[i])); + if (IS_ERR(nvsw_core->wd[i])) { + err = PTR_ERR(nvsw_core->wd[i]); ++ dev_err(nvsw_core->dev, "Failed to register mlx-wdt driver\n"); + goto fail_platform_wd_register; + } + } @@ -3422,6 +3512,11 @@ index 00000000..bfe56ab + switch (nvsw_core->regmap_type) { + case REGMAP_I2C: + nvsw_core->regmap = devm_regmap_init_i2c(nvsw_core->client, &nvsw_regmap_i2c_conf); ++ if (IS_ERR(nvsw_core->regmap)) { ++ dev_err(nvsw_core->dev, "Failed to create I2C regmap\n"); ++ err = PTR_ERR(nvsw_core->regmap); ++ return err; ++ } + break; + case REGMAP_IO: + if (nvsw_core->port_map) { @@ -3499,10 +3594,10 @@ index 00000000..bfe56ab +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/platform/mellanox/nvsw-host-l1.c b/drivers/platform/mellanox/nvsw-host-l1.c new file mode 100644 -index 00000000..ffe248b +index 000000000..46022cb99 --- /dev/null +++ b/drivers/platform/mellanox/nvsw-host-l1.c -@@ -0,0 +1,745 @@ +@@ -0,0 +1,744 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Nvidia BMC platform driver @@ -4247,13 +4342,1782 @@ index 00000000..ffe248b +MODULE_AUTHOR("Vadim Pasternak "); +MODULE_DESCRIPTION("Nvidia platform driver"); +MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/platform/mellanox/nvsw-host-spc5.c b/drivers/platform/mellanox/nvsw-host-spc5.c +new file mode 100644 +index 000000000..6d1c71cf4 +--- /dev/null ++++ b/drivers/platform/mellanox/nvsw-host-spc5.c +@@ -0,0 +1,937 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Nvidia BMC platform driver ++ * ++ * Copyright (C) 2025 Nvidia Technologies Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "nvsw.h" ++ ++#define NVSW_HOST_DEVICE_NAME "mlxplat" ++ ++/* LPC bus IO offsets */ ++#define NVSW_I2C_BASE_ADRR 0x2000 ++#define NVSW_REG_BASE_ADRR 0x2500 ++#define NVSW_LPC_IO_RANGE 0x100 ++#define NVSW_LPC_PIO_OFFSET 0x10000UL ++#define NVSW_REG_MUX1 (NVSW_REG_MUX1_OFFSET | NVSW_LPC_PIO_OFFSET) ++#define NVSW_REG_MUX2 (NVSW_REG_MUX0_OFFSET | NVSW_LPC_PIO_OFFSET) ++ ++/* Default I2C parent bus number */ ++#define NVSW_CPLD_PHYS_ADAPTER_DEF_NR 5 ++ ++/* Start channel numbers */ ++#define NVSW_PARENT_CH NVSW_CPLD_PHYS_ADAPTER_DEF_NR ++#define NVSW_MUX1_CH NVSW_CPLD_PHYS_ADAPTER_DEF_NR + 1 ++#define NVSW_MUX2_CH 64 ++ ++ ++/* Regions for LPC I2C controller and LPC base register space */ ++static const struct resource nvsw_host_io_resources[] = { ++ [0] = DEFINE_RES_NAMED(NVSW_I2C_BASE_ADRR, NVSW_LPC_IO_RANGE, ++ "nvsw_cpld_lpc_i2c_ctrl", IORESOURCE_IO), ++ [1] = DEFINE_RES_NAMED(NVSW_REG_BASE_ADRR, NVSW_LPC_IO_RANGE, ++ "nvsw_cpld_lpc_regs", IORESOURCE_IO), ++}; ++ ++/* SPC5 platform mgmt board mux channels */ ++static const int nvsw_host_spc5_mgmt_channels[] = { ++ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, ++ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ++ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, ++ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58 ++}; ++ ++/* SPC5 platform ComEx board mux channels */ ++static const int nvsw_host_spc5_comex_channels[] = { ++ 1, 2, 3, 4, 5, 6, 7, 8 ++}; ++ ++/* SPC5 platform mux data */ ++static struct i2c_mux_reg_platform_data nvsw_host_spc5_mux_data[] = { ++ { ++ .parent = NVSW_PARENT_CH, ++ .base_nr = NVSW_MUX1_CH, ++ .write_only = 1, ++ .reg = (void __iomem *)NVSW_REG_MUX1, ++ .reg_size = 1, ++ .idle_in_use = 1, ++ .values = nvsw_host_spc5_mgmt_channels, ++ .n_values = ARRAY_SIZE(nvsw_host_spc5_mgmt_channels), ++ }, ++ { ++ .parent = NVSW_PARENT_CH, ++ .base_nr = NVSW_MUX2_CH, ++ .write_only = 1, ++ .reg = (void __iomem *)NVSW_REG_MUX2, ++ .reg_size = 1, ++ .idle_in_use = 1, ++ .values = nvsw_host_spc5_comex_channels, ++ .n_values = ARRAY_SIZE(nvsw_host_spc5_comex_channels), ++ }, ++}; ++ ++/* SPC5 platform i2c frequency data */ ++static struct mlxreg_core_data nvsw_mlxcpld_i2c_items_data[] = { ++ { ++ .reg = NVSW_REG_PSU_I2C_CAP_OFFSET, ++ .mask = NVSW_I2C_CAP_MASK, ++ .bit = NVSW_I2C_CAP_BIT, ++ }, ++}; ++ ++static struct mlxreg_core_item nvsw_mlxcpld_i2c_items[] = { ++ { ++ .data = nvsw_mlxcpld_i2c_items_data, ++ }, ++}; ++ ++/* SPC5 platform i2c data */ ++static struct mlxreg_core_hotplug_platform_data nvsw_mlxcpld_i2c_data = { ++ .items = nvsw_mlxcpld_i2c_items, ++ .cell = NVSW_REG_AGGR_OFFSET, ++ .mask = NVSW_AGGR_MASK_COMEX, ++ .cell_low = NVSW_REG_AGGRCO_OFFSET, ++ .mask_low = NVSW_LOW_AGGR_MASK_I2C, ++}; ++ ++static struct platform_device *nvsw_host_dev; ++static struct platform_device *nvsw_i2c_dev; ++static struct i2c_mux_reg_platform_data *nvsw_host_mux_data[NVSW_MUX_MAX]; ++static struct mlxreg_core_platform_data *nvsw_led_data; ++static struct mlxreg_core_platform_data *nvsw_regs_io_data; ++static struct mlxreg_core_hotplug_platform_data *nvsw_i2c_data; ++static struct mlxreg_core_platform_data *nvsw_wd_data[NVSW_WD_MAX]; ++static int mux_num; ++static enum nvsw_core_hid_type nvsw_host_hid; ++ ++/* Platform register access for SPC5 systems families data */ ++static struct mlxreg_core_data nvsw_host_spc5_regs_io_data[] = { ++ { ++ .label = "cpld1_version", ++ .reg = NVSW_REG_CPLD1_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld2_version", ++ .reg = NVSW_REG_CPLD2_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld3_version", ++ .reg = NVSW_REG_CPLD3_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld4_version", ++ .reg = NVSW_REG_CPLD4_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld5_version", ++ .reg = NVSW_REG_CPLD5_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld6_version", ++ .reg = NVSW_REG_CPLD6_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld7_version", ++ .reg = NVSW_REG_CPLD7_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld8_version", ++ .reg = NVSW_REG_CPLD8_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld9_version", ++ .reg = NVSW_REG_CPLD9_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld10_version", ++ .reg = NVSW_REG_CPLD10_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld1_pn", ++ .reg = NVSW_REG_CPLD1_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld2_pn", ++ .reg = NVSW_REG_CPLD2_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld3_pn", ++ .reg = NVSW_REG_CPLD3_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld4_pn", ++ .reg = NVSW_REG_CPLD4_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld5_pn", ++ .reg = NVSW_REG_CPLD5_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld6_pn", ++ .reg = NVSW_REG_CPLD6_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld7_pn", ++ .reg = NVSW_REG_CPLD7_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld8_pn", ++ .reg = NVSW_REG_CPLD8_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld9_pn", ++ .reg = NVSW_REG_CPLD9_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld10_pn", ++ .reg = NVSW_REG_CPLD10_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld1_version_min", ++ .reg = NVSW_REG_CPLD1_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld2_version_min", ++ .reg = NVSW_REG_CPLD2_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld3_version_min", ++ .reg = NVSW_REG_CPLD3_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld4_version_min", ++ .reg = NVSW_REG_CPLD4_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld5_version_min", ++ .reg = NVSW_REG_CPLD5_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld6_version_min", ++ .reg = NVSW_REG_CPLD6_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld7_version_min", ++ .reg = NVSW_REG_CPLD7_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld8_version_min", ++ .reg = NVSW_REG_CPLD8_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld9_version_min", ++ .reg = NVSW_REG_CPLD9_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld10_version_min", ++ .reg = NVSW_REG_CPLD10_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "pwr_converter_prog_en", ++ .reg = NVSW_REG_GP7_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0644, ++ }, ++ { ++ .label = "graceful_pwr_off", ++ .reg = NVSW_REG_GP7_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, ++ }, ++ { ++ .label = "cpu_mctp_ready", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, ++ }, ++ { ++ .label = "cpu_shutdown_req", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "vpd_wp", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, ++ .secured = 1, ++ }, ++ { ++ .label = "pcie_asic_reset_dis", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0644, ++ }, ++ { ++ .label = "shutdown_unlock", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0644, ++ }, ++ { ++ .label = "cpu_power_off_ready", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0644, ++ }, ++ { ++ .label = "pwr_cycle", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0244, ++ }, ++ { ++ .label = "pwr_down", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0200, ++ }, ++ { ++ .label = "aux_pwr_cycle", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0200, ++ }, ++ { ++ .label = "bmc_to_cpu_ctrl", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0644, ++ }, ++ { ++ .label = "uart_sel", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = NVSW_UART_SEL_MASK, ++ .bit = 7, ++ .mode = 0644, ++ }, ++ { ++ .label = "leakage1", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "leakage2", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "leakage3", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "leakage4", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "leakage5", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0444, ++ }, ++ { ++ .label = "asic_reset", ++ .reg = NVSW_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, ++ }, ++ { ++ .label = "asic1_reset", ++ .reg = NVSW_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0644, ++ }, ++ { ++ .label = "asic2_reset", ++ .reg = NVSW_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0644, ++ }, ++ { ++ .label = "asic3_reset", ++ .reg = NVSW_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0644, ++ }, ++ { ++ .label = "asic4_reset", ++ .reg = NVSW_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0644, ++ }, ++ { ++ .label = "sgmii_phy_reset", ++ .reg = NVSW_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0644, ++ }, ++ { ++ .label = "reset_long_pb", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_short_pb", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_aux_pwr_or_reload", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_swb_dc_dc_pwr_fail", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_platform", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_swb_wd", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_asic_thermal", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_comex_pwr_fail", ++ .reg = NVSW_REG_RESET_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_soc", ++ .reg = NVSW_REG_RESET_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_system", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_sw_pwr_off", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_comex_thermal", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_pwr_converter_fail", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_main_51v", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_mgmt_pwr", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "port80", ++ .reg = NVSW_REG_GP1_RO_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "jtag_cap", ++ .reg = NVSW_REG_FU_CAP_OFFSET, ++ .mask = NVSW_FU_CAP_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++ { ++ .label = "jtag_enable", ++ .reg = NVSW_REG_FIELD_UPGRADE, ++ .mask = GENMASK(1, 0), ++ .bit = 1, ++ .mode = 0644, ++ }, ++ { ++ .label = "asic_health", ++ .reg = NVSW_REG_ASIC1_HEALTH_OFFSET, ++ .mask = NVSW_ASIC_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++ { ++ .label = "asic2_health", ++ .reg = NVSW_REG_ASIC1_HEALTH_OFFSET, ++ .mask = NVSW_ASIC2_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++ { ++ .label = "asic3_health", ++ .reg = NVSW_REG_ASIC1_HEALTH_OFFSET, ++ .mask = NVSW_ASIC3_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++ { ++ .label = "asic4_health", ++ .reg = NVSW_REG_ASIC1_HEALTH_OFFSET, ++ .mask = NVSW_ASIC4_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++ { ++ .label = "asic1_pg_fail", ++ .reg = NVSW_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "asic2_pg_fail", ++ .reg = NVSW_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "asic3_pg_fail", ++ .reg = NVSW_REG_GP5_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "asic4_pg_fail", ++ .reg = NVSW_REG_GP5_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "spi_chnl_select", ++ .reg = NVSW_REG_SPI_CHNL_SELECT, ++ .mask = GENMASK(7, 0), ++ .bit = 1, ++ .mode = 0644, ++ }, ++ { ++ .label = "pdb1_pwr_status", ++ .reg = NVSW_REG_GP0_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0644, ++ }, ++ { ++ .label = "pdb2_pwr_status", ++ .reg = NVSW_REG_GP0_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, ++ }, ++ { ++ .label = "pdb3_pwr_status", ++ .reg = NVSW_REG_GP0_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0644, ++ }, ++ { ++ .label = "pdb4_pwr_status", ++ .reg = NVSW_REG_GP0_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data nvsw_host_spc5_regs_io = { ++ .data = nvsw_host_spc5_regs_io_data, ++ .counter = ARRAY_SIZE(nvsw_host_spc5_regs_io_data), ++}; ++ ++/* SPC5 platform led data */ ++static struct mlxreg_core_data nvsw_host_spc5_led_data[] = { ++ { ++ .label = "status:green", ++ .reg = NVSW_REG_LED1_OFFSET, ++ .mask = NVSW_LED_LO_NIBBLE_MASK ++ }, ++ { ++ .label = "status:amber", ++ .reg = NVSW_REG_LED1_OFFSET, ++ .mask = NVSW_LED_LO_NIBBLE_MASK ++ }, ++ { ++ .label = "power:green", ++ .mode = 0444, ++ .reg = NVSW_REG_LED1_OFFSET, ++ .mask = NVSW_LED_HI_NIBBLE_MASK, ++ }, ++ { ++ .label = "power:amber", ++ .reg = NVSW_REG_LED1_OFFSET, ++ .mask = NVSW_LED_HI_NIBBLE_MASK, ++ }, ++ { ++ .label = "uid:blue", ++ .reg = NVSW_REG_LED5_OFFSET, ++ .mask = NVSW_LED_LO_NIBBLE_MASK, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data nvsw_host_spc5_led = { ++ .data = nvsw_host_spc5_led_data, ++ .counter = ARRAY_SIZE(nvsw_host_spc5_led_data), ++}; ++ ++/* Watchdog type3 platform data */ ++static struct mlxreg_core_data nvsw_host_wd_main_regs_type3[] = { ++ { ++ .label = "action", ++ .reg = NVSW_REG_WD2_ACT_OFFSET, ++ .mask = NVSW_WD_RESET_ACT_MASK, ++ .bit = 0, ++ }, ++ { ++ .label = "timeout", ++ .reg = NVSW_REG_WD2_TMR_OFFSET, ++ .mask = NVSW_WD_TYPE2_TO_MASK, ++ .health_cntr = NVSW_WD3_DFLT_TIMEOUT, ++ }, ++ { ++ .label = "timeleft", ++ .reg = NVSW_REG_WD2_TMR_OFFSET, ++ .mask = NVSW_WD_TYPE2_TO_MASK, ++ }, ++ { ++ .label = "ping", ++ .reg = NVSW_REG_WD2_ACT_OFFSET, ++ .mask = NVSW_WD_RESET_ACT_MASK, ++ .bit = 0, ++ }, ++ { ++ .label = "reset", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .bit = 6, ++ }, ++}; ++ ++static struct mlxreg_core_data nvsw_host_wd_aux_regs_type3[] = { ++ { ++ .label = "action", ++ .reg = NVSW_REG_WD3_ACT_OFFSET, ++ .mask = NVSW_WD_FAN_ACT_MASK, ++ .bit = 4, ++ }, ++ { ++ .label = "timeout", ++ .reg = NVSW_REG_WD3_TMR_OFFSET, ++ .mask = NVSW_WD_TYPE2_TO_MASK, ++ .health_cntr = NVSW_WD3_DFLT_TIMEOUT, ++ }, ++ { ++ .label = "timeleft", ++ .reg = NVSW_REG_WD3_TMR_OFFSET, ++ .mask = NVSW_WD_TYPE2_TO_MASK, ++ }, ++ { ++ .label = "ping", ++ .reg = NVSW_REG_WD3_ACT_OFFSET, ++ .mask = NVSW_WD_FAN_ACT_MASK, ++ .bit = 4, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data nvsw_host_wd_set_type3[] = { ++ { ++ .data = nvsw_host_wd_main_regs_type3, ++ .counter = ARRAY_SIZE(nvsw_host_wd_main_regs_type3), ++ .version = MLX_WDT_TYPE3, ++ .identity = "mlx-wdt-main", ++ }, ++ { ++ .data = nvsw_host_wd_aux_regs_type3, ++ .counter = ARRAY_SIZE(nvsw_host_wd_aux_regs_type3), ++ .version = MLX_WDT_TYPE3, ++ .identity = "mlx-wdt-aux", ++ }, ++}; ++ ++/* IO port mapping callback. */ ++static void __iomem *nvsw_host_spc5_port_map(struct nvsw_core *nvsw_core) ++{ ++ return devm_ioport_map(nvsw_core->dev, nvsw_host_io_resources[1].start, 1); ++} ++ ++/* Mux init/exit callbacks. */ ++static int nvsw_host_spc5_mux_topology_init(struct nvsw_core *nvsw_core) ++{ ++ int i, err; ++ ++ if (!nvsw_i2c_data) ++ return 0; ++ ++ /* Create i2c infrastructure. */ ++ nvsw_i2c_data->regmap = nvsw_core->regmap; ++ nvsw_i2c_data->handle = nvsw_core; ++ ++ nvsw_i2c_dev = platform_device_register_resndata(nvsw_core->dev, "i2c_mlxcpld", ++ NVSW_CPLD_PHYS_ADAPTER_DEF_NR, NULL, 0, ++ nvsw_i2c_data, sizeof(*nvsw_i2c_data)); ++ if (IS_ERR(nvsw_i2c_dev)) { ++ err = PTR_ERR(nvsw_i2c_dev); ++ return err; ++ } ++ ++ /* Create mux infrastructure. */ ++ for (i = 0; i < nvsw_core->mux_num; i++) { ++ nvsw_core->mux[i] = ++ platform_device_register_resndata(nvsw_core->dev, "i2c-mux-reg", i, NULL, ++ 0, nvsw_host_mux_data[i], ++ sizeof(*nvsw_host_mux_data[i])); ++ if (IS_ERR(nvsw_core->mux[i])) { ++ dev_err(nvsw_core->dev, "Failed to create mux infra\n"); ++ err = PTR_ERR(nvsw_core->mux[i]); ++ goto fail_platform_mux_register; ++ } ++ } ++ ++ return 0; ++fail_platform_mux_register: ++ while (--i >= 0) ++ platform_device_unregister(nvsw_core->mux[i]); ++ return err; ++} ++ ++static void nvsw_host_spc5_mux_topology_exit(struct nvsw_core *nvsw_core) ++{ ++ int i; ++ ++ for (i = 0; i < nvsw_core->mux_num; i++) { ++ if (nvsw_core->mux[i]) ++ platform_device_unregister(nvsw_core->mux[i]); ++ } ++ ++ if (nvsw_i2c_dev) ++ platform_device_unregister(nvsw_i2c_dev); ++} ++ ++static int __init nvsw_host_register_platform_device(void) ++{ ++ nvsw_host_dev = platform_device_register_simple(NVSW_HOST_DEVICE_NAME, -1, ++ nvsw_host_io_resources, ++ ARRAY_SIZE(nvsw_host_io_resources)); ++ if (IS_ERR(nvsw_host_dev)) ++ return PTR_ERR(nvsw_host_dev); ++ return 1; ++} ++ ++static int __init nvsw_host_dmi_spc5_switch_matched(const struct dmi_system_id *dmi) ++{ ++ int i; ++ ++ /* Set system configuration. */ ++ nvsw_host_hid = HID181; ++ mux_num = ARRAY_SIZE(nvsw_host_spc5_mux_data); ++ for (i = 0; i < mux_num; i++) ++ nvsw_host_mux_data[i] = &nvsw_host_spc5_mux_data[i]; ++ nvsw_led_data = &nvsw_host_spc5_led; ++ nvsw_regs_io_data = &nvsw_host_spc5_regs_io; ++ for (i = 0; i < ARRAY_SIZE(nvsw_host_wd_set_type3); i++) ++ nvsw_wd_data[i] = &nvsw_host_wd_set_type3[i]; ++ nvsw_i2c_data = &nvsw_mlxcpld_i2c_data; ++ ++ return nvsw_host_register_platform_device(); ++} ++ ++static const struct dmi_system_id nvsw_host_dmi_table[] __initconst = { ++ { ++ .callback = nvsw_host_dmi_spc5_switch_matched, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "VMOD0024"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "HI181"), ++ }, ++ }, ++ { ++ .callback = nvsw_host_dmi_spc5_switch_matched, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "VMOD0024"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "HI182"), ++ }, ++ }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(dmi, nvsw_host_dmi_table); ++ ++static int nvsw_host_probe(struct platform_device *pdev) ++{ ++ struct nvsw_core *nvsw_core; ++ int i; ++ ++ nvsw_core = devm_kzalloc(&nvsw_host_dev->dev, sizeof(*nvsw_core), GFP_KERNEL); ++ if (!nvsw_core) ++ return -ENOMEM; ++ ++ /* Set system configuration. */ ++ nvsw_core->dev = &nvsw_host_dev->dev; ++ nvsw_core->hid = nvsw_host_hid; ++ nvsw_core->regmap_type = REGMAP_IO; ++ nvsw_core->mux_num = mux_num; ++ for (i = 0; i < ARRAY_SIZE(nvsw_wd_data); i++) ++ nvsw_core->wd_data[i] = nvsw_wd_data[i]; ++ nvsw_core->regio_data = nvsw_regs_io_data; ++ nvsw_core->led_data = nvsw_led_data; ++ nvsw_core->port_map = nvsw_host_spc5_port_map; ++ nvsw_core->mux_init = nvsw_host_spc5_mux_topology_init; ++ nvsw_core->mux_exit = nvsw_host_spc5_mux_topology_exit; ++ platform_set_drvdata(nvsw_host_dev, nvsw_core); ++ ++ return nvsw_core_init(nvsw_core); ++} ++ ++static void nvsw_host_remove(struct platform_device *pdev) ++{ ++ struct nvsw_core *nvsw_core = platform_get_drvdata(nvsw_host_dev); ++ ++ nvsw_core_exit(nvsw_core); ++} ++ ++static struct platform_driver nvsw_host_driver = { ++ .driver = { ++ .name = NVSW_HOST_DEVICE_NAME, ++ .probe_type = PROBE_FORCE_SYNCHRONOUS, ++ }, ++ .probe = nvsw_host_probe, ++ .remove = nvsw_host_remove, ++}; ++ ++static int __init nvsw_host_init(void) ++{ ++ if (!dmi_check_system(nvsw_host_dmi_table)) ++ return -ENODEV; ++ ++ return platform_driver_register(&nvsw_host_driver); ++} ++module_init(nvsw_host_init); ++ ++static void __exit nvsw_host_exit(void) ++{ ++ if (nvsw_host_dev) ++ platform_device_unregister(nvsw_host_dev); ++ ++ platform_driver_unregister(&nvsw_host_driver); ++} ++module_exit(nvsw_host_exit); ++ ++MODULE_AUTHOR("Vadim Pasternak "); ++MODULE_DESCRIPTION("Nvidia platform driver"); ++MODULE_LICENSE("Dual BSD/GPL"); ++ +diff --git a/drivers/platform/mellanox/nvsw-host-spc6.c b/drivers/platform/mellanox/nvsw-host-spc6.c +new file mode 100644 +index 000000000..958943778 +--- /dev/null ++++ b/drivers/platform/mellanox/nvsw-host-spc6.c +@@ -0,0 +1,821 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Nvidia SPC6 host platform driver ++ * ++ * Copyright (C) 2025 Nvidia Technologies Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "nvsw.h" ++ ++#define NVSW_HOST_DEVICE_NAME "mlxplat" ++ ++/* Bus number of mux device */ ++#define NVSW_I2C_MUX_BUS_NR 2 ++ ++/* Platform mux channels */ ++static int nvsw_host_spc6_mux_channels[] = { ++ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, ++ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ++ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, ++ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, ++ 63, 64, 65, 66, 67, ++}; ++ ++/* Platform mux data */ ++static struct mlxcpld_mux_plat_data nvsw_host_spc6_mux_data[] = { ++ { ++ .chan_ids = nvsw_host_spc6_mux_channels, ++ .num_adaps = ARRAY_SIZE(nvsw_host_spc6_mux_channels), ++ .sel_reg_addr = NVSW_REG_MUX1_OFFSET, ++ .reg_size = 2, ++ }, ++}; ++ ++/* Platform mux board info */ ++static struct i2c_board_info nvsw_host_spc6_mux_brdinfo = { ++ I2C_BOARD_INFO("i2c-mux-mlxcpld", 0x33), ++}; ++ ++static struct i2c_adapter *nvsw_host_mux_i2c_adapter; ++static struct i2c_client *nvsw_host_mux_i2c_client; ++static struct mlxcpld_mux_plat_data *nvsw_host_mux_data[NVSW_MUX_MAX]; ++static struct i2c_board_info *nvsw_host_mux_brdinfo; ++static struct mlxreg_core_platform_data *nvsw_led_data; ++static struct mlxreg_core_platform_data *nvsw_regs_io_data; ++static struct mlxreg_core_platform_data *nvsw_wd_data[NVSW_WD_MAX]; ++static int mux_num; ++static enum nvsw_core_hid_type nvsw_host_hid; ++static struct platform_device *nvsw_host_pdev; ++ ++/* Platform register access data */ ++static struct mlxreg_core_data nvsw_host_spc6_regs_io_data[] = { ++ { ++ .label = "cpld1_version", ++ .reg = NVSW_REG_CPLD1_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld2_version", ++ .reg = NVSW_REG_CPLD2_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld3_version", ++ .reg = NVSW_REG_CPLD3_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld4_version", ++ .reg = NVSW_REG_CPLD4_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld5_version", ++ .reg = NVSW_REG_CPLD5_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld6_version", ++ .reg = NVSW_REG_CPLD6_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld7_version", ++ .reg = NVSW_REG_CPLD7_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld8_version", ++ .reg = NVSW_REG_CPLD8_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld9_version", ++ .reg = NVSW_REG_CPLD9_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld10_version", ++ .reg = NVSW_REG_CPLD10_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld1_pn", ++ .reg = NVSW_REG_CPLD1_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld2_pn", ++ .reg = NVSW_REG_CPLD2_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld3_pn", ++ .reg = NVSW_REG_CPLD3_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld4_pn", ++ .reg = NVSW_REG_CPLD4_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld5_pn", ++ .reg = NVSW_REG_CPLD5_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld6_pn", ++ .reg = NVSW_REG_CPLD6_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld7_pn", ++ .reg = NVSW_REG_CPLD7_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld8_pn", ++ .reg = NVSW_REG_CPLD8_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld9_pn", ++ .reg = NVSW_REG_CPLD9_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld10_pn", ++ .reg = NVSW_REG_CPLD10_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "cpld1_version_min", ++ .reg = NVSW_REG_CPLD1_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld2_version_min", ++ .reg = NVSW_REG_CPLD2_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld3_version_min", ++ .reg = NVSW_REG_CPLD3_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld4_version_min", ++ .reg = NVSW_REG_CPLD4_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld5_version_min", ++ .reg = NVSW_REG_CPLD5_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld6_version_min", ++ .reg = NVSW_REG_CPLD6_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld7_version_min", ++ .reg = NVSW_REG_CPLD7_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld8_version_min", ++ .reg = NVSW_REG_CPLD8_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld9_version_min", ++ .reg = NVSW_REG_CPLD9_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld10_version_min", ++ .reg = NVSW_REG_CPLD10_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "pwr_converter_prog_en", ++ .reg = NVSW_REG_GP7_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0644, ++ }, ++ { ++ .label = "graceful_pwr_off", ++ .reg = NVSW_REG_GP7_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, ++ }, ++ { ++ .label = "cpu_mctp_ready", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, ++ }, ++ { ++ .label = "cpu_shutdown_req", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "vpd_wp", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, ++ .secured = 1, ++ }, ++ { ++ .label = "pcie_asic_reset_dis", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0644, ++ }, ++ { ++ .label = "shutdown_unlock", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0644, ++ }, ++ { ++ .label = "cpu_power_off_ready", ++ .reg = NVSW_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0644, ++ }, ++ { ++ .label = "pwr_cycle", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0244, ++ }, ++ { ++ .label = "pwr_down", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0200, ++ }, ++ { ++ .label = "aux_pwr_cycle", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0200, ++ }, ++ { ++ .label = "bmc_to_cpu_ctrl", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0644, ++ }, ++ { ++ .label = "uart_sel", ++ .reg = NVSW_REG_GP1_OFFSET, ++ .mask = NVSW_UART_SEL_MASK, ++ .bit = 7, ++ .mode = 0644, ++ }, ++ { ++ .label = "leakage1", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "leakage2", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "leakage3", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "leakage4", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "leakage5", ++ .reg = NVSW_REG_LEAK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0444, ++ }, ++ { ++ .label = "asic_reset", ++ .reg = NVSW_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, ++ }, ++ { ++ .label = "reset_long_pb", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_short_pb", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_aux_pwr_or_reload", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_swb_dc_dc_pwr_fail", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_platform", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_swb_wd", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_asic_thermal", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_soc", ++ .reg = NVSW_REG_RESET_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_system", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_sw_pwr_off", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_cpu_thermal", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_pwr_converter_fail", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_main_51v", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_mgmt_pwr", ++ .reg = NVSW_REG_RESET_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "jtag_cap", ++ .reg = NVSW_REG_FU_CAP_OFFSET, ++ .mask = NVSW_FU_CAP_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++ { ++ .label = "jtag_enable", ++ .reg = NVSW_REG_FIELD_UPGRADE, ++ .mask = GENMASK(1, 0), ++ .bit = 1, ++ .mode = 0644, ++ }, ++ { ++ .label = "asic_health", ++ .reg = NVSW_REG_ASIC1_HEALTH_OFFSET, ++ .mask = NVSW_ASIC_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++ { ++ .label = "asic_pg_fail", ++ .reg = NVSW_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "spi_chnl_select", ++ .reg = NVSW_REG_SPI_CHNL_SELECT, ++ .mask = GENMASK(7, 0), ++ .bit = 1, ++ .mode = 0644, ++ }, ++ { ++ .label = "pdb1_pwr_status", ++ .reg = NVSW_REG_PS_DC_OK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0644, ++ }, ++ { ++ .label = "pdb2_pwr_status", ++ .reg = NVSW_REG_PS_DC_OK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, ++ }, ++ { ++ .label = "pdb3_pwr_status", ++ .reg = NVSW_REG_PS_DC_OK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0644, ++ }, ++ { ++ .label = "pdb4_pwr_status", ++ .reg = NVSW_REG_PS_DC_OK_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data nvsw_host_spc6_regs_io = { ++ .data = nvsw_host_spc6_regs_io_data, ++ .counter = ARRAY_SIZE(nvsw_host_spc6_regs_io_data), ++}; ++ ++/* Platform led data */ ++static struct mlxreg_core_data nvsw_host_spc6_lc_led_data[] = { ++ { ++ .label = "status:green", ++ .reg = NVSW_REG_LED1_OFFSET, ++ .mask = NVSW_LED_LO_NIBBLE_MASK ++ }, ++ { ++ .label = "status:amber", ++ .reg = NVSW_REG_LED1_OFFSET, ++ .mask = NVSW_LED_LO_NIBBLE_MASK ++ }, ++ { ++ .label = "power:green", ++ .mode = 0444, ++ .reg = NVSW_REG_LED1_OFFSET, ++ .mask = NVSW_LED_HI_NIBBLE_MASK, ++ }, ++ { ++ .label = "power:amber", ++ .reg = NVSW_REG_LED1_OFFSET, ++ .mask = NVSW_LED_HI_NIBBLE_MASK, ++ }, ++ { ++ .label = "uid:blue", ++ .reg = NVSW_REG_LED5_OFFSET, ++ .mask = NVSW_LED_LO_NIBBLE_MASK, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data nvsw_host_spc6_lc_led = { ++ .data = nvsw_host_spc6_lc_led_data, ++ .counter = ARRAY_SIZE(nvsw_host_spc6_lc_led_data), ++}; ++ ++/* Watchdog type3 platform data */ ++static struct mlxreg_core_data nvsw_host_wd_main_regs_type3[] = { ++ { ++ .label = "action", ++ .reg = NVSW_REG_WD2_ACT_OFFSET, ++ .mask = NVSW_WD_RESET_ACT_MASK, ++ .bit = 0, ++ }, ++ { ++ .label = "timeout", ++ .reg = NVSW_REG_WD2_TMR_OFFSET, ++ .mask = NVSW_WD_TYPE2_TO_MASK, ++ .health_cntr = NVSW_WD3_DFLT_TIMEOUT, ++ }, ++ { ++ .label = "timeleft", ++ .reg = NVSW_REG_WD2_TMR_OFFSET, ++ .mask = NVSW_WD_TYPE2_TO_MASK, ++ }, ++ { ++ .label = "ping", ++ .reg = NVSW_REG_WD2_ACT_OFFSET, ++ .mask = NVSW_WD_RESET_ACT_MASK, ++ .bit = 0, ++ }, ++ { ++ .label = "reset", ++ .reg = NVSW_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .bit = 6, ++ }, ++}; ++ ++static struct mlxreg_core_data nvsw_host_wd_aux_regs_type3[] = { ++ { ++ .label = "action", ++ .reg = NVSW_REG_WD3_ACT_OFFSET, ++ .mask = NVSW_WD_FAN_ACT_MASK, ++ .bit = 4, ++ }, ++ { ++ .label = "timeout", ++ .reg = NVSW_REG_WD3_TMR_OFFSET, ++ .mask = NVSW_WD_TYPE2_TO_MASK, ++ .health_cntr = NVSW_WD3_DFLT_TIMEOUT, ++ }, ++ { ++ .label = "timeleft", ++ .reg = NVSW_REG_WD3_TMR_OFFSET, ++ .mask = NVSW_WD_TYPE2_TO_MASK, ++ }, ++ { ++ .label = "ping", ++ .reg = NVSW_REG_WD3_ACT_OFFSET, ++ .mask = NVSW_WD_FAN_ACT_MASK, ++ .bit = 4, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data nvsw_host_wd_set_type3[] = { ++ { ++ .data = nvsw_host_wd_main_regs_type3, ++ .counter = ARRAY_SIZE(nvsw_host_wd_main_regs_type3), ++ .version = MLX_WDT_TYPE3, ++ .identity = "mlx-wdt-main", ++ }, ++ { ++ .data = nvsw_host_wd_aux_regs_type3, ++ .counter = ARRAY_SIZE(nvsw_host_wd_aux_regs_type3), ++ .version = MLX_WDT_TYPE3, ++ .identity = "mlx-wdt-aux", ++ }, ++}; ++ ++/* Callback is used to indicate that all adapter devices have been created. */ ++static int ++nvsw_host_spc6_completion_notify(void *handle, struct i2c_adapter *parent, ++ struct i2c_adapter *adapters[]) ++{ ++ return 0; ++} ++ ++/* Mux init/exit callbacks. */ ++static int nvsw_host_spc6_mux_topology_init(struct nvsw_core *nvsw_core) ++{ ++ int i, err; ++ ++ /* Create mux infrastructure. */ ++ for (i = 0; i < nvsw_core->mux_num; i++) { ++ nvsw_host_mux_data[i]->handle = nvsw_core; ++ nvsw_host_mux_data[i]->completion_notify = ++ nvsw_host_spc6_completion_notify; ++ nvsw_core->mux[i] = ++ platform_device_register_resndata(&nvsw_host_mux_i2c_client->dev, ++ "i2c-mux-mlxcpld", i, NULL, ++ 0, nvsw_host_mux_data[i], ++ sizeof(*nvsw_host_mux_data[i])); ++ if (IS_ERR(nvsw_core->mux[i])) { ++ dev_err(nvsw_core->dev, "Failed to create mux infra\n"); ++ err = PTR_ERR(nvsw_core->mux[i]); ++ goto platform_mux_register_fail; ++ } ++ } ++ ++ return 0; ++ ++platform_mux_register_fail: ++ while (--i >= 0) ++ platform_device_unregister(nvsw_core->mux[i]); ++ i2c_unregister_device(nvsw_host_mux_i2c_client); ++ nvsw_host_mux_i2c_client = NULL; ++ ++ return err; ++} ++ ++static void nvsw_host_spc6_mux_topology_exit(struct nvsw_core *nvsw_core) ++{ ++ int i; ++ ++ for (i = 0; i < nvsw_core->mux_num; i++) { ++ if (nvsw_core->mux[i]) ++ platform_device_unregister(nvsw_core->mux[i]); ++ } ++ ++ if (nvsw_core->client) { ++ i2c_unregister_device(nvsw_core->client); ++ nvsw_host_mux_i2c_client = NULL; ++ i2c_put_adapter(nvsw_host_mux_i2c_adapter); ++ nvsw_host_mux_i2c_adapter = NULL; ++ } ++} ++ ++static int __init nvsw_host_dmi_spc6_switch_matched(const struct dmi_system_id *dmi) ++{ ++ int i, err; ++ ++ /* Allocate the platform device structure */ ++ nvsw_host_pdev = ++ platform_device_alloc(NVSW_HOST_DEVICE_NAME, PLATFORM_DEVID_NONE); ++ if (!nvsw_host_pdev) ++ return -ENOMEM; ++ ++ /* Register the device with the platform bus */ ++ err = platform_device_add(nvsw_host_pdev); ++ if (err) { ++ platform_device_put(nvsw_host_pdev); ++ return err; ++ } ++ ++ /* Set system configuration. */ ++ nvsw_host_hid = HID193; ++ mux_num = ARRAY_SIZE(nvsw_host_spc6_mux_data); ++ for (i = 0; i < mux_num; i++) ++ nvsw_host_mux_data[i] = &nvsw_host_spc6_mux_data[i]; ++ nvsw_host_mux_brdinfo = &nvsw_host_spc6_mux_brdinfo; ++ nvsw_led_data = &nvsw_host_spc6_lc_led; ++ nvsw_regs_io_data = &nvsw_host_spc6_regs_io; ++ for (i = 0; i < ARRAY_SIZE(nvsw_host_wd_set_type3); i++) ++ nvsw_wd_data[i] = &nvsw_host_wd_set_type3[i]; ++ ++ return 0; ++} ++ ++static const struct dmi_system_id nvsw_host_dmi_table[] __initconst = { ++ { ++ .callback = nvsw_host_dmi_spc6_switch_matched, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "VMOD0025"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "HI193"), ++ }, ++ }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(dmi, nvsw_host_dmi_table); ++ ++static int nvsw_host_probe(struct platform_device *pdev) ++{ ++ struct nvsw_core *nvsw_core; ++ int i, err; ++ ++ /* Get I2C adapter at the top of host I2C tree */ ++ nvsw_host_mux_i2c_adapter = i2c_get_adapter(NVSW_I2C_MUX_BUS_NR); ++ if (!nvsw_host_mux_i2c_adapter) { ++ dev_info(&pdev->dev, ++ "I2C adapter for bus %d is not ready, deferring probe\n", ++ NVSW_I2C_MUX_BUS_NR); ++ return -EPROBE_DEFER; ++ } ++ ++ /* Create device at the top of host I2C tree */ ++ nvsw_host_mux_brdinfo->platform_data = nvsw_host_mux_data; ++ nvsw_host_mux_i2c_client = i2c_new_client_device(nvsw_host_mux_i2c_adapter, ++ nvsw_host_mux_brdinfo); ++ if (IS_ERR(nvsw_host_mux_i2c_client)) { ++ dev_err(&pdev->dev, ++ "Failed to create client %s at bus %d at addr 0x%02x\n", ++ nvsw_host_mux_brdinfo->type, NVSW_I2C_MUX_BUS_NR, ++ nvsw_host_mux_brdinfo->addr); ++ err = PTR_ERR(nvsw_host_mux_i2c_client); ++ i2c_put_adapter(nvsw_host_mux_i2c_adapter); ++ nvsw_host_mux_i2c_adapter = NULL; ++ return err; ++ } ++ ++ nvsw_core = devm_kzalloc(&pdev->dev, sizeof(*nvsw_core), GFP_KERNEL); ++ if (!nvsw_core) ++ return -ENOMEM; ++ ++ /* Set system configuration. */ ++ nvsw_core->dev = &pdev->dev; ++ nvsw_core->hid = nvsw_host_hid; ++ nvsw_core->regmap_type = REGMAP_I2C; ++ nvsw_core->client = nvsw_host_mux_i2c_client; ++ nvsw_core->mux_num = mux_num; ++ for (i = 0; i < ARRAY_SIZE(nvsw_wd_data); i++) ++ nvsw_core->wd_data[i] = nvsw_wd_data[i]; ++ nvsw_core->regio_data = nvsw_regs_io_data; ++ nvsw_core->led_data = nvsw_led_data; ++ nvsw_core->mux_init = nvsw_host_spc6_mux_topology_init; ++ nvsw_core->mux_exit = nvsw_host_spc6_mux_topology_exit; ++ platform_set_drvdata(pdev, nvsw_core); ++ ++ return nvsw_core_init(nvsw_core); ++} ++ ++static void nvsw_host_remove(struct platform_device *pdev) ++{ ++ struct nvsw_core *nvsw_core = platform_get_drvdata(pdev); ++ ++ nvsw_core_exit(nvsw_core); ++} ++ ++static struct platform_driver nvsw_host_driver = { ++ .driver = { ++ .name = NVSW_HOST_DEVICE_NAME, ++ .probe_type = PROBE_FORCE_SYNCHRONOUS, ++ }, ++ .probe = nvsw_host_probe, ++ .remove = nvsw_host_remove, ++}; ++ ++static int __init nvsw_host_init(void) ++{ ++ int err; ++ ++ if (!dmi_check_system(nvsw_host_dmi_table)) ++ return -ENODEV; ++ ++ err = platform_driver_register(&nvsw_host_driver); ++ if (err) { ++ if (nvsw_host_pdev) ++ platform_device_unregister(nvsw_host_pdev); ++ } ++ ++ return err; ++} ++module_init(nvsw_host_init); ++ ++static void __exit nvsw_host_exit(void) ++{ ++ platform_driver_unregister(&nvsw_host_driver); ++} ++module_exit(nvsw_host_exit); ++ ++MODULE_AUTHOR("Vadim Pasternak "); ++MODULE_DESCRIPTION("Nvidia platform driver"); ++MODULE_LICENSE("Dual BSD/GPL"); + diff --git a/drivers/platform/mellanox/nvsw.h b/drivers/platform/mellanox/nvsw.h new file mode 100644 -index 00000000..b1ae4db +index 000000000..2e9b505f7 --- /dev/null +++ b/drivers/platform/mellanox/nvsw.h -@@ -0,0 +1,260 @@ +@@ -0,0 +1,296 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Nvidia BMC platform driver @@ -4277,6 +6141,7 @@ index 00000000..b1ae4db +#define NVSW_REG_CPLD3_PN1_OFFSET 0x2509 +#define NVSW_REG_CPLD4_PN_OFFSET 0x250a +#define NVSW_REG_CPLD4_PN1_OFFSET 0x250b ++#define NVSW_REG_CPLD7_VER_OFFSET 0x2510 +#define NVSW_REG_PG1_OFFSET 0x2511 +#define NVSW_REG_PG1_EVENT_OFFSET 0x2512 +#define NVSW_REG_PG1_MASK_OFFSET 0x2513 @@ -4292,6 +6157,8 @@ index 00000000..b1ae4db +#define NVSW_REG_LED5_OFFSET 0x2524 +#define NVSW_REG_LED6_OFFSET 0x2525 +#define NVSW_REG_LED7_OFFSET 0x2526 ++#define NVSW_REG_CPLD7_PN_OFFSET 0x2528 ++#define NVSW_REG_CPLD7_PN1_OFFSET 0x2529 +#define NVSW_REG_GP0_RO_OFFSET 0x252a +#define NVSW_REG_GP1_RO_OFFSET 0x252c +#define NVSW_REG_GPCOM0_OFFSET 0x252d @@ -4299,6 +6166,7 @@ index 00000000..b1ae4db +#define NVSW_REG_GP7_OFFSET 0x252f +#define NVSW_REG_GP1_OFFSET 0x2530 +#define NVSW_REG_GP4_OFFSET 0x2532 ++#define NVSW_REG_GP5_RO_OFFSET 0x2533 +#define NVSW_REG_FIELD_UPGRADE 0x2534 +#define NVSW_REG_SAFE_BIOS_OFFSET 0x2535 +#define NVSW_REG_PWM_CONTROL_OFFSET 0x2537 @@ -4332,18 +6200,33 @@ index 00000000..b1ae4db +#define NVSW_REG_VR2_ALERT_OFFSET 0x255e +#define NVSW_REG_VR2_ALERT_EVENT_OFFSET 0x255f +#define NVSW_REG_VR2_ALERT_MASK_OFFSET 0x2560 ++#define NVSW_REG_PS_DC_OK_OFFSET 0x2567 ++#define NVSW_REG_PS_DC_OK_EVENT_OFFSET 0x2568 ++#define NVSW_REG_PS_DC_OK_MASK_OFFSET 0x2569 ++#define NVSW_REG_CPLD8_PN_OFFSET 0x2573 ++#define NVSW_REG_CPLD8_PN1_OFFSET 0x2574 ++#define NVSW_REG_CPLD6_VER_OFFSET 0x2575 +#define NVSW_REG_PG3_OFFSET 0x2576 +#define NVSW_REG_PG3_EVENT_OFFSET 0x2577 +#define NVSW_REG_PG3_MASK_OFFSET 0x2578 +#define NVSW_REG_PG4_OFFSET 0x2579 +#define NVSW_REG_PG4_EVENT_OFFSET 0x257a +#define NVSW_REG_PG4_MASK_OFFSET 0x257b ++#define NVSW_REG_CPLD6_PN_OFFSET 0x257c ++#define NVSW_REG_CPLD6_PN1_OFFSET 0x257d ++#define NVSW_REG_CPLD9_PN_OFFSET 0x257e ++#define NVSW_REG_CPLD9_PN1_OFFSET 0x257f ++#define NVSW_REG_CPLD10_PN_OFFSET 0x2580 ++#define NVSW_REG_CPLD10_PN1_OFFSET 0x2581 +#define NVSW_REG_ASIC3_HEALTH_OFFSET 0x2582 +#define NVSW_REG_ASIC3_EVENT_OFFSET 0x2583 +#define NVSW_REG_ASIC3_MASK_OFFSET 0x2584 +#define NVSW_REG_FAN_OFFSET 0x2588 +#define NVSW_REG_FAN_EVENT_OFFSET 0x2589 +#define NVSW_REG_FAN_MASK_OFFSET 0x258a ++#define NVSW_REG_CPLD5_VER_OFFSET 0x258e ++#define NVSW_REG_CPLD5_PN_OFFSET 0x258f ++#define NVSW_REG_CPLD5_PN1_OFFSET 0x2590 +#define NVSW_REG_EROT_OFFSET 0x2591 +#define NVSW_REG_EROT_EVENT_OFFSET 0x2592 +#define NVSW_REG_EROT_MASK_OFFSET 0x2593 @@ -4361,12 +6244,21 @@ index 00000000..b1ae4db +#define NVSW_REG_LEAK_MASK_OFFSET 0x25b1 +#define NVSW_REG_GP4_RO_OFFSET 0x25c2 +#define NVSW_REG_SPI_CHNL_SELECT 0x25c3 ++#define NVSW_REG_CPLD5_MVER_OFFSET 0x25c4 ++#define NVSW_REG_CPLD8_VER_OFFSET 0x25c8 ++#define NVSW_REG_CPLD9_VER_OFFSET 0x25c9 ++#define NVSW_REG_CPLD10_VER_OFFSET 0x25ca +#define NVSW_REG_WD2_TMR_OFFSET 0x25cd +#define NVSW_REG_WD2_TLEFT_OFFSET 0x25ce +#define NVSW_REG_WD2_ACT_OFFSET 0x25cf +#define NVSW_REG_WD3_TMR_OFFSET 0x25d1 +#define NVSW_REG_WD3_TLEFT_OFFSET 0x25d2 +#define NVSW_REG_WD3_ACT_OFFSET 0x25d3 ++#define NVSW_REG_CPLD7_MVER_OFFSET 0x25d5 ++#define NVSW_REG_CPLD8_MVER_OFFSET 0x25d6 ++#define NVSW_REG_CPLD9_MVER_OFFSET 0x25d7 ++#define NVSW_REG_CPLD10_MVER_OFFSET 0x25d8 ++#define NVSW_REG_CPLD6_MVER_OFFSET 0x25d9 +#define NVSW_REG_MUX0_OFFSET 0x25da +#define NVSW_REG_MUX1_OFFSET 0x25db +#define NVSW_REG_MUX2_OFFSET 0x25dc @@ -4391,6 +6283,7 @@ index 00000000..b1ae4db +#define NVSW_REG_FAN_CAP1_OFFSET 0x25f5 +#define NVSW_REG_FAN_DRW_CAP_OFFSET 0x25f7 +#define NVSW_REG_TACHO_SPEED_OFFSET 0x25f8 ++#define NVSW_REG_PSU_I2C_CAP_OFFSET 0x25f9 +#define NVSW_REG_CONFIG1_OFFSET 0x25fb +#define NVSW_REG_CONFIG2_OFFSET 0x25fc +#define NVSW_REG_CONFIG3_OFFSET 0x25fd @@ -4398,6 +6291,7 @@ index 00000000..b1ae4db +#define NVSW_REG_MAX 0x26ff + +#define NVSW_AGGR_MASK_COMEX BIT(0) ++#define NVSW_LOW_AGGR_MASK_I2C BIT(6) +#define NVSW_AGGR_MASK BIT(2) +#define NVSW_LOW_AGGR_MASK_LOW 0xe0 +#define NVSW_REG_FRU1_MASK GENMASK(3, 0) @@ -4435,11 +6329,14 @@ index 00000000..b1ae4db +#define NVSW_UART_SEL_MASK GENMASK(7, 6) +#define NVSW_BIOS_STATUS_MASK GENMASK(3, 1) +#define NVSW_REG_RESET_MASK BIT(1) ++#define NVSW_MASTER_MASK BIT(5) +#define NVSW_FU_CAP_MASK GENMASK(1, 0) +#define NVSW_WD_RESET_ACT_MASK GENMASK(7, 1) +#define NVSW_WD_FAN_ACT_MASK (GENMASK(7, 0) & ~BIT(4)) +#define NVSW_WD_TYPE2_TO_MASK 0 +#define NVSW_WD3_DFLT_TIMEOUT 600 ++#define NVSW_I2C_CAP_BIT 0x04 ++#define NVSW_I2C_CAP_MASK GENMASK(5, NVSW_I2C_CAP_BIT) + +#define NVSW_NR_NONE -1 +#define NVSW_MUX_MAX 2 @@ -4451,6 +6348,9 @@ index 00000000..b1ae4db + HID176, + HID177, + HID180, ++ HID181, ++ HID182, ++ HID193, +}; + + /* The system register map type. */ @@ -4515,5 +6415,5 @@ index 00000000..b1ae4db +#endif /* !defined(__NVSW_H__) */ + -- -2.8.4 +2.34.1 diff --git a/patches-sonic/9000-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch b/patches-sonic/0054-1-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch similarity index 94% rename from patches-sonic/9000-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch rename to patches-sonic/0054-1-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch index 7f058ea7b..7abef897d 100644 --- a/patches-sonic/9000-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch +++ b/patches-sonic/0054-1-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch @@ -1,7 +1,7 @@ -From a209121e8dc093705e0f3fcc3aad27d4c28d949d Mon Sep 17 00:00:00 2001 +From e9caf9cf3e69dff922c98c0e5e0ffe7a2fd0a7c7 Mon Sep 17 00:00:00 2001 From: Oleksandr Shamray Date: Mon, 9 Dec 2024 11:42:37 +0200 -Subject: [PATCH 69/78] platform: mellanox: Downstream: Add support for new +Subject: [PATCH 17/40] platform: mellanox: Downstream: Add support for new Nvidia IB DGX system based on class VMOD0010 This system is based on Nvidia QM9700 64x400G QTM-2 IB switch, with the @@ -18,15 +18,15 @@ Reviewed-by: Vadim Pasternak 1 file changed, 454 insertions(+) diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c -index 9203ed8..710c21d 100644 +index b2ea7e8..4c1073b 100644 --- a/drivers/platform/mellanox/mlx-platform.c +++ b/drivers/platform/mellanox/mlx-platform.c -@@ -825,6 +825,16 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = { +@@ -824,6 +824,16 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = { }, }; +/* Platform hotplug dgx data */ -+static struct mlxreg_core_data mlxplat_mlxcpld_dgx_psu_items_data[] = { ++static struct mlxreg_core_data mlxplat_mlxcpld_dgx_pdb_items_data[] = { + { + .label = "pdb1", + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, @@ -38,7 +38,7 @@ index 9203ed8..710c21d 100644 static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = { { .label = "pwr1", -@@ -874,6 +884,15 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_ng800_items_data[] = +@@ -873,6 +883,15 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_ng800_items_data[] = }, }; @@ -54,17 +54,17 @@ index 9203ed8..710c21d 100644 static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = { { .label = "fan1", -@@ -1497,6 +1516,45 @@ static struct mlxreg_core_item mlxplat_mlxcpld_ext_items[] = { +@@ -1496,6 +1515,45 @@ static struct mlxreg_core_item mlxplat_mlxcpld_ext_items[] = { } }; +static struct mlxreg_core_item mlxplat_mlxcpld_ext_dgx_items[] = { + { -+ .data = mlxplat_mlxcpld_dgx_psu_items_data, ++ .data = mlxplat_mlxcpld_dgx_pdb_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF, + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = MLXPLAT_CPLD_PSU_MASK, -+ .count = ARRAY_SIZE(mlxplat_mlxcpld_dgx_psu_items_data), ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_dgx_pdb_items_data), + .inversed = 1, + .health = false, + }, @@ -100,7 +100,7 @@ index 9203ed8..710c21d 100644 static struct mlxreg_core_item mlxplat_mlxcpld_ng800_items[] = { { .data = mlxplat_mlxcpld_default_ng_psu_items_data, -@@ -1549,6 +1607,16 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ext_data = { +@@ -1548,6 +1606,16 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ext_data = { }; static @@ -117,7 +117,7 @@ index 9203ed8..710c21d 100644 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_ng800_data = { .items = mlxplat_mlxcpld_ng800_items, .count = ARRAY_SIZE(mlxplat_mlxcpld_ng800_items), -@@ -5048,6 +5116,359 @@ static struct mlxreg_core_platform_data mlxplat_default_ng_regs_io_data = { +@@ -5037,6 +5105,359 @@ static struct mlxreg_core_platform_data mlxplat_default_ng_regs_io_data = { .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_regs_io_data), }; @@ -477,7 +477,7 @@ index 9203ed8..710c21d 100644 /* Platform register access for modular systems families data */ static struct mlxreg_core_data mlxplat_mlxcpld_modular_regs_io_data[] = { { -@@ -7799,6 +8220,32 @@ static int __init mlxplat_dmi_ng400_matched(const struct dmi_system_id *dmi) +@@ -7787,6 +8208,32 @@ static int __init mlxplat_dmi_ng400_matched(const struct dmi_system_id *dmi) return mlxplat_register_platform_device(); } @@ -510,7 +510,7 @@ index 9203ed8..710c21d 100644 static int __init mlxplat_dmi_modular_matched(const struct dmi_system_id *dmi) { int i; -@@ -8095,6 +8542,13 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { +@@ -8060,6 +8507,13 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { }, }, { diff --git a/patches-sonic/0055-platform-mellanox-Downstream-Add-support-DGX-flavor-.patch b/patches-sonic/0055-platform-mellanox-Downstream-Add-support-DGX-flavor-.patch index 4a3c62055..5774a87da 100644 --- a/patches-sonic/0055-platform-mellanox-Downstream-Add-support-DGX-flavor-.patch +++ b/patches-sonic/0055-platform-mellanox-Downstream-Add-support-DGX-flavor-.patch @@ -1,7 +1,7 @@ -From 817b5cfab9f1eef11a244020caf1987bb37f682e Mon Sep 17 00:00:00 2001 +From a6c422c8a1a6416e34590988537f993b4b36e0ea Mon Sep 17 00:00:00 2001 From: Oleksandr Shamray Date: Mon, 9 Dec 2024 13:38:05 +0200 -Subject: [PATCH 55/78] platform: mellanox: Downstream: Add support DGX flavor +Subject: [PATCH 18/40] platform: mellanox: Downstream: Add support DGX flavor of next-generation 800GB/s ethernet switch. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -20,10 +20,10 @@ Signed-off-by: Oleksandr Shamray 1 file changed, 28 insertions(+) diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c -index de3dbaf..3472c99 100644 +index 4c1073b..54f52d7 100644 --- a/drivers/platform/mellanox/mlx-platform.c +++ b/drivers/platform/mellanox/mlx-platform.c -@@ -7871,6 +7871,27 @@ static int __init mlxplat_dmi_ng800_matched(const struct dmi_system_id *dmi) +@@ -8318,6 +8318,27 @@ static int __init mlxplat_dmi_ng800_matched(const struct dmi_system_id *dmi) return mlxplat_register_platform_device(); } @@ -51,7 +51,7 @@ index de3dbaf..3472c99 100644 static int __init mlxplat_dmi_l1_switch_matched(const struct dmi_system_id *dmi) { int i; -@@ -8072,6 +8093,13 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { +@@ -8526,6 +8547,13 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { }, }, { diff --git a/patches-sonic/0056-hwmon-pmbus-mp2845-Add-support-for-MP2845-device.patch b/patches-sonic/0056-hwmon-pmbus-mp2845-Add-support-for-MP2845-device.patch new file mode 100644 index 000000000..460aadee5 --- /dev/null +++ b/patches-sonic/0056-hwmon-pmbus-mp2845-Add-support-for-MP2845-device.patch @@ -0,0 +1,554 @@ +From 5ba8fda8e39bd295fe065d2c84e60b59e94c2760 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 3 Dec 2025 17:07:17 +0200 +Subject: [PATCH 1/2] hwmon: (pmbus/mp2845): Add support for MP2845 device + +Add support for MPS device MP2845 - Digital Multi-Phase Power +Controller. + +The MP2845 is a Digital, Multi-Phase PWM Controller with PMBus and +PWM-VID manufactured by Monolithic Power Systems (MPS) designed for +efficient power management in high-performance computing applications. + +Signed-off-by: Vadim Pasternak +--- + drivers/hwmon/pmbus/Kconfig | 9 + + drivers/hwmon/pmbus/Makefile | 1 + + drivers/hwmon/pmbus/mp2845.c | 493 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 503 insertions(+) + create mode 100644 drivers/hwmon/pmbus/mp2845.c + +diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig +index 369e409..946613e 100644 +--- a/drivers/hwmon/pmbus/Kconfig ++++ b/drivers/hwmon/pmbus/Kconfig +@@ -319,6 +319,15 @@ config SENSORS_MAX8688 + This driver can also be built as a module. If so, the module will + be called max8688. + ++config SENSORS_MP2845 ++ tristate "MPS MP2845" ++ help ++ If you say yes here you get hardware monitoring support for MPS ++ MP2845 Digital Multi-Phase Power Controller. ++ ++ This driver can also be built as a module. If so, the module will ++ be called mp2845. ++ + config SENSORS_MP2855 + tristate "MPS MP2855" + help +diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile +index a95fc50..c716461 100644 +--- a/drivers/hwmon/pmbus/Makefile ++++ b/drivers/hwmon/pmbus/Makefile +@@ -34,6 +34,7 @@ obj-$(CONFIG_SENSORS_MAX20751) += max20751.o + obj-$(CONFIG_SENSORS_MAX31785) += max31785.o + obj-$(CONFIG_SENSORS_MAX34440) += max34440.o + obj-$(CONFIG_SENSORS_MAX8688) += max8688.o ++obj-$(CONFIG_SENSORS_MP2845) += mp2845.o + obj-$(CONFIG_SENSORS_MP2855) += mp2855.o + obj-$(CONFIG_SENSORS_MP2856) += mp2856.o + obj-$(CONFIG_SENSORS_MP2869) += mp2869.o +diff --git a/drivers/hwmon/pmbus/mp2845.c b/drivers/hwmon/pmbus/mp2845.c +new file mode 100644 +index 00000000..96d3dc5 +--- /dev/null ++++ b/drivers/hwmon/pmbus/mp2845.c +@@ -0,0 +1,493 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Hardware monitoring driver for MPS Digital Controller(MP2845) ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MP2845_IOUT_SCALE_MASK1 GENMASK(5, 3) ++#define MP2845_IOUT_SCALE_MASK2 GENMASK(13, 11) ++ ++#define MFR_VIN_OV_UV_SET 0x71 ++#define MFR_OVUV_OCWARN_THRES 0x75 ++#define MFR_TOTAL_OCP_SET 0x76 ++#define MFR_PROTECT_STATUS1 0x80 ++#define MFR_PROTECT_STATUS2 0x81 ++ ++#define MP2845_VIN_LIMIT_UINT 125 ++#define MP2845_READ_VIN_UINT 3125 ++#define MP2845_READ_VIN_DIV 100 ++#define MP2845_READ_IOUT_UINT 3125 ++#define MP2845_READ_IOUT_DIV 100 ++#define MP2845_READ_VOUT_UINT 5 ++#define MP2845_TEMP_UINT 1000 ++ ++#define MFR_READ_VIN 0xA6 ++#define MFR_READ_VOUT 0xA7 ++#define MFR_READ_IOUT 0xA8 ++#define MFR_READ_TEMP 0xA9 ++#define MFR_MFG_ID_SCALE_VI1 0x77 ++#define MFR_MFG_ID_SCALE_VI2 0x78 ++ ++struct mp2845_data { ++ struct i2c_client *client; ++ int iout_gain[4]; ++ /* lock for preventing concurrency issue */ ++ struct mutex lock; ++}; ++ ++static umode_t mp2845_is_visible(const void *data, enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ switch (type) { ++ case hwmon_temp: ++ case hwmon_in: ++ case hwmon_curr: ++ return 0444; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int mp2845_read_string(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, const char **str) ++{ ++ struct mp2845_data *data; ++ int ret = 0; ++ ++ data = dev_get_drvdata(dev); ++ ++ mutex_lock(&data->lock); ++ ++ switch (type) { ++ case hwmon_in: ++ if (channel == 0) ++ *str = "vin"; ++ else if (channel == 1) ++ *str = "vout1"; ++ else if (channel == 2) ++ *str = "vout2"; ++ else if (channel == 3) ++ *str = "vout3"; ++ else ++ *str = "vout4"; ++ break; ++ case hwmon_curr: ++ if (channel == 0) ++ *str = "iout1"; ++ else if (channel == 1) ++ *str = "iout2"; ++ else if (channel == 2) ++ *str = "iout3"; ++ else ++ *str = "iout4"; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ mutex_unlock(&data->lock); ++ ++ return ret; ++} ++ ++static int mp2845_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *val) ++{ ++ int ret; ++ struct mp2845_data *data; ++ ++ data = dev_get_drvdata(dev); ++ if (!data) ++ return -ENOMEM; ++ ++ mutex_lock(&data->lock); ++ ++ switch (type) { ++ case hwmon_in: ++ if (channel == 0) { ++ if (attr == hwmon_in_input) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, 0); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_READ_VIN); ++ if (ret < 0) ++ break; ++ ++ *val = DIV_ROUND_CLOSEST((ret & GENMASK(9, 0)) * ++ MP2845_READ_VIN_UINT, ++ MP2845_READ_VIN_DIV); ++ } else if (attr == hwmon_in_crit) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, 0); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_VIN_OV_UV_SET); ++ if (ret < 0) ++ break; ++ ++ *val = FIELD_GET(GENMASK(15, 8), ret) * MP2845_VIN_LIMIT_UINT; ++ } else if (attr == hwmon_in_min) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, 0); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_VIN_OV_UV_SET); ++ if (ret < 0) ++ break; ++ ++ *val = FIELD_GET(GENMASK(7, 0), ret) * MP2845_VIN_LIMIT_UINT; ++ } else if (attr == hwmon_in_crit_alarm) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, 0); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_PROTECT_STATUS2); ++ if (ret < 0) ++ break; ++ ++ *val = FIELD_GET(GENMASK(5, 5), ret); ++ } else { ++ ret = i2c_smbus_write_byte_data(data->client, 0, 0); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_PROTECT_STATUS2); ++ if (ret < 0) ++ break; ++ ++ *val = FIELD_GET(GENMASK(4, 4), ret); ++ } ++ } else { ++ if (attr == hwmon_in_input) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, channel - 1); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_READ_VOUT); ++ if (ret < 0) ++ break; ++ ++ *val = (ret & GENMASK(9, 0)) * MP2845_READ_VOUT_UINT; ++ } else if (attr == hwmon_in_crit_alarm) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, 0); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_PROTECT_STATUS1); ++ if (ret < 0) ++ break; ++ ++ if (channel == 1) ++ *val = FIELD_GET(GENMASK(10, 10), ret); ++ else if (channel == 2) ++ *val = FIELD_GET(GENMASK(7, 7), ret); ++ else if (channel == 3) ++ *val = FIELD_GET(GENMASK(4, 4), ret); ++ else ++ *val = FIELD_GET(GENMASK(1, 1), ret); ++ } else { ++ ret = i2c_smbus_write_byte_data(data->client, 0, 0); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_PROTECT_STATUS1); ++ if (ret < 0) ++ break; ++ ++ if (channel == 1) ++ *val = FIELD_GET(GENMASK(11, 11), ret); ++ else if (channel == 2) ++ *val = FIELD_GET(GENMASK(8, 8), ret); ++ else if (channel == 3) ++ *val = FIELD_GET(GENMASK(5, 5), ret); ++ else ++ *val = FIELD_GET(GENMASK(2, 2), ret); ++ } ++ } ++ break; ++ case hwmon_temp: ++ if (attr == hwmon_temp_input) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, channel); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_READ_TEMP); ++ if (ret < 0) ++ break; ++ ++ *val = ((ret & GENMASK(7, 0)) - 40) * MP2845_TEMP_UINT; ++ } else { ++ ret = i2c_smbus_write_byte_data(data->client, 0, 0); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_PROTECT_STATUS1); ++ if (ret < 0) ++ break; ++ ++ if (channel == 0) { ++ *val = FIELD_GET(GENMASK(12, 12), ret); ++ } else if (channel == 1) { ++ *val = FIELD_GET(GENMASK(14, 14), ret); ++ } else if (channel == 2) { ++ ret = i2c_smbus_read_word_data(data->client, MFR_PROTECT_STATUS2); ++ if (ret < 0) ++ break; ++ ++ *val = FIELD_GET(GENMASK(0, 0), ret); ++ } else { ++ ret = i2c_smbus_read_word_data(data->client, MFR_PROTECT_STATUS2); ++ if (ret < 0) ++ break; ++ ++ *val = FIELD_GET(GENMASK(2, 2), ret); ++ } ++ } ++ break; ++ case hwmon_curr: ++ if (attr == hwmon_curr_input) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, channel); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_READ_IOUT); ++ if (ret < 0) ++ break; ++ ++ *val = DIV_ROUND_CLOSEST((ret & GENMASK(9, 0)) * data->iout_gain[channel] * ++ MP2845_READ_IOUT_UINT, MP2845_READ_IOUT_DIV); ++ } else if (attr == hwmon_curr_max) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, channel); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_OVUV_OCWARN_THRES); ++ if (ret < 0) ++ break; ++ ++ *val = DIV_ROUND_CLOSEST(FIELD_GET(GENMASK(15, 8), ret) * ++ data->iout_gain[channel] * MP2845_READ_IOUT_UINT * ++ 4 * 2, MP2845_READ_IOUT_DIV); ++ } else if (attr == hwmon_curr_crit) { ++ ret = i2c_smbus_write_byte_data(data->client, 0, channel); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_TOTAL_OCP_SET); ++ if (ret < 0) ++ break; ++ ++ *val = DIV_ROUND_CLOSEST(FIELD_GET(GENMASK(15, 8), ret) * ++ data->iout_gain[channel] * MP2845_READ_IOUT_UINT * ++ 4 * 2, MP2845_READ_IOUT_DIV); ++ } else { ++ ret = i2c_smbus_write_byte_data(data->client, 0, 0); ++ if (ret < 0) ++ break; ++ ++ ret = i2c_smbus_read_word_data(data->client, MFR_PROTECT_STATUS1); ++ if (ret < 0) ++ break; ++ ++ if (channel == 0) ++ *val = FIELD_GET(GENMASK(9, 9), ret); ++ else if (channel == 2) ++ *val = FIELD_GET(GENMASK(6, 6), ret); ++ else if (channel == 3) ++ *val = FIELD_GET(GENMASK(3, 3), ret); ++ else ++ *val = FIELD_GET(GENMASK(0, 0), ret); ++ } ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ mutex_unlock(&data->lock); ++ ++ return ret; ++} ++ ++static int ++mp2845_identify_iout_scale(struct mp2845_data *data, int page) ++{ ++ int gain; ++ int ret; ++ ++ ret = i2c_smbus_write_byte_data(data->client, 0x00, page); ++ if (ret < 0) ++ return ret; ++ ++ ret = i2c_smbus_read_word_data(data->client, page == 0 ? MFR_MFG_ID_SCALE_VI2 : ++ MFR_MFG_ID_SCALE_VI1); ++ if (ret < 0) ++ return ret; ++ ++ gain = page == 0 ? FIELD_GET(MP2845_IOUT_SCALE_MASK1, ret) : ++ FIELD_GET(MP2845_IOUT_SCALE_MASK2, ret); ++ switch (gain) { ++ case 1: ++ data->iout_gain[page] = 1; ++ break; ++ case 2: ++ data->iout_gain[page] = 2; ++ break; ++ case 3: ++ data->iout_gain[page] = 4; ++ break; ++ case 4: ++ data->iout_gain[page] = 8; ++ break; ++ case 5: ++ data->iout_gain[page] = 16; ++ break; ++ case 6: ++ data->iout_gain[page] = 32; ++ break; ++ case 7: ++ data->iout_gain[page] = 64; ++ break; ++ default: ++ data->iout_gain[page] = 1; ++ break; ++ } ++ ++ return 0; ++} ++ ++static const struct hwmon_channel_info *mp2845_info[] = { ++ HWMON_CHANNEL_INFO(in, ++ HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_CRIT | HWMON_I_CRIT_ALARM | ++ HWMON_I_LCRIT_ALARM | HWMON_I_LABEL, ++ HWMON_I_INPUT | HWMON_I_CRIT_ALARM | HWMON_I_LCRIT_ALARM | ++ HWMON_I_LABEL, ++ HWMON_I_INPUT | HWMON_I_CRIT_ALARM | HWMON_I_LCRIT_ALARM | ++ HWMON_I_LABEL, ++ HWMON_I_INPUT | HWMON_I_CRIT_ALARM | HWMON_I_LCRIT_ALARM | ++ HWMON_I_LABEL, ++ HWMON_I_INPUT | HWMON_I_CRIT_ALARM | HWMON_I_LCRIT_ALARM | ++ HWMON_I_LABEL), ++ HWMON_CHANNEL_INFO(temp, ++ HWMON_T_INPUT | HWMON_T_CRIT_ALARM, ++ HWMON_T_INPUT | HWMON_T_CRIT_ALARM, ++ HWMON_T_INPUT | HWMON_T_CRIT_ALARM, ++ HWMON_T_INPUT | HWMON_T_CRIT_ALARM), ++ HWMON_CHANNEL_INFO(curr, ++ HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM | HWMON_C_MAX | ++ HWMON_C_LABEL, ++ HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM | HWMON_C_MAX | ++ HWMON_C_LABEL, ++ HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM | HWMON_C_MAX | ++ HWMON_C_LABEL, ++ HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM | HWMON_C_MAX | ++ HWMON_C_LABEL), ++ NULL ++}; ++ ++static const struct hwmon_ops mp2845_hwmon_ops = { ++ .is_visible = mp2845_is_visible, ++ .read = mp2845_read, ++ .read_string = mp2845_read_string, ++}; ++ ++static const struct hwmon_chip_info mp2845_chip_info = { ++ .ops = &mp2845_hwmon_ops, ++ .info = mp2845_info, ++}; ++ ++static int mp2845_probe(struct i2c_client *client) ++{ ++ struct device *dev = &client->dev; ++ struct device *hwmon_dev; ++ struct mp2845_data *data; ++ int ret; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA)) { ++ dev_err(dev, "check failed, smbus byte and/or word data not supported!\n"); ++ return -ENODEV; ++ } ++ ++ data = devm_kzalloc(dev, sizeof(struct mp2845_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ mutex_init(&data->lock); ++ data->client = client; ++ ++ ret = mp2845_identify_iout_scale(data, 0); ++ if (ret < 0) { ++ dev_err(dev, "unable to identify rail1 iout scale, errno = %d\n", ret); ++ return ret; ++ } ++ ++ ret = mp2845_identify_iout_scale(data, 1); ++ if (ret < 0) { ++ dev_err(dev, "unable to identify rail2 iout scale, errno = %d\n", ret); ++ return ret; ++ } ++ ++ ret = mp2845_identify_iout_scale(data, 2); ++ if (ret < 0) { ++ dev_err(dev, "unable to identify rail3 iout scale, errno = %d\n", ret); ++ return ret; ++ } ++ ++ ret = mp2845_identify_iout_scale(data, 3); ++ if (ret < 0) { ++ dev_err(dev, "unable to identify rail4 iout scale, errno = %d\n", ret); ++ return ret; ++ } ++ ++ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, ++ data, &mp2845_chip_info, ++ NULL); ++ if (IS_ERR(hwmon_dev)) { ++ dev_err(dev, "unable to register mp2845 hwmon device\n"); ++ return PTR_ERR(hwmon_dev); ++ } ++ ++ dev_info(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), client->name); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id mp2845_ids[] = { ++ {"mp2845", 0}, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, mp2845_ids); ++ ++static const struct of_device_id __maybe_unused mp2845_of_match[] = { ++ {.compatible = "mps,mp2845"}, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, mp2845_of_match); ++ ++static struct i2c_driver mp2845_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "mp2845", ++ .of_match_table = mp2845_of_match, ++ }, ++ .probe = mp2845_probe, ++ .id_table = mp2845_ids, ++}; ++module_i2c_driver(mp2845_driver); ++ ++MODULE_AUTHOR("Noah Wang "); ++MODULE_DESCRIPTION("MP2845 driver"); ++MODULE_LICENSE("GPL"); +-- +2.8.4 + diff --git a/patches-sonic/0057-hwmon-pmbus-mp5926-Add-support-for-MP5926-device.patch b/patches-sonic/0057-hwmon-pmbus-mp5926-Add-support-for-MP5926-device.patch new file mode 100644 index 000000000..64caa7736 --- /dev/null +++ b/patches-sonic/0057-hwmon-pmbus-mp5926-Add-support-for-MP5926-device.patch @@ -0,0 +1,252 @@ +From e5d678169c052940009201338af7832fdc672ca2 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 3 Dec 2025 19:18:38 +0200 +Subject: [PATCH 2/2] hwmon: (pmbus/mp5926): Add support for device MP5926 + +Add support for MPS device MP5926. + +The MP5926 is a high voltage hot-swap controller capable of operating +with supplies 8V to 80V. The MP5926 provides a controlled soft start +during hot insertion to ensure a controlled output voltage ramp occurs. + +Signed-off-by: Vadim Pasternak +--- + drivers/hwmon/pmbus/Kconfig | 9 ++ + drivers/hwmon/pmbus/Makefile | 1 + + drivers/hwmon/pmbus/mp5926.c | 192 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 202 insertions(+) + create mode 100644 drivers/hwmon/pmbus/mp5926.c + +diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig +index 946613e..08c9e7b 100644 +--- a/drivers/hwmon/pmbus/Kconfig ++++ b/drivers/hwmon/pmbus/Kconfig +@@ -426,6 +426,15 @@ config SENSORS_MP5920 + This driver can also be built as a module. If so, the module will + be called mp5920. + ++config SENSORS_MP5926 ++ tristate "MPS MP5926" ++ help ++ If you say yes here you get hardware monitoring support for MPS ++ MP5926 Controller. ++ ++ This driver can also be built as a module. If so, the module will ++ be called mp5926. ++ + config SENSORS_MP5990 + tristate "MPS MP5990" + help +diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile +index c716461..1a641d9 100644 +--- a/drivers/hwmon/pmbus/Makefile ++++ b/drivers/hwmon/pmbus/Makefile +@@ -45,6 +45,7 @@ obj-$(CONFIG_SENSORS_MP2975) += mp2975.o + obj-$(CONFIG_SENSORS_MP2993) += mp2993.o + obj-$(CONFIG_SENSORS_MP5023) += mp5023.o + obj-$(CONFIG_SENSORS_MP5920) += mp5920.o ++obj-$(CONFIG_SENSORS_MP5926) += mp5926.o + obj-$(CONFIG_SENSORS_MP5990) += mp5990.o + obj-$(CONFIG_SENSORS_MP9941) += mp9941.o + obj-$(CONFIG_SENSORS_MPQ7932) += mpq7932.o +diff --git a/drivers/hwmon/pmbus/mp5926.c b/drivers/hwmon/pmbus/mp5926.c +new file mode 100644 +index 00000000..626d945 +--- /dev/null ++++ b/drivers/hwmon/pmbus/mp5926.c +@@ -0,0 +1,192 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++// ++// mp5926.c - pmbus driver for mps mp5926 ++// ++// Copyright 2025 Monolithic Power Systems, Inc ++// ++// Author: Yuxi Wang ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pmbus.h" ++ ++/*Common Register*/ ++#define PAGE 0x01 ++#define EFUSE_CFG 0xCF ++#define I_SCALE_SEL 0xC6 ++#define MP5926_FUNC (PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | \ ++ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP | \ ++ PMBUS_HAVE_STATUS_VOUT) ++ ++static int mp5926_read_word_data(struct i2c_client *client, int page, int phase, int reg) ++{ ++ int ret; ++ s16 exponent; ++ s32 mantissa; ++ s64 val; ++ ++ switch (reg) { ++ case PMBUS_READ_VIN...PMBUS_READ_VCAP: ++ case PMBUS_READ_IOUT...PMBUS_READ_TEMPERATURE_1: ++ case PMBUS_READ_PIN: ++ case PMBUS_STATUS_WORD: ++ ret = -ENODATA; ++ break; ++ case PMBUS_READ_VOUT: ++ /* The Vout format used by the chip is linear11 and not linear16. ++ * So we transform the value into the direct format defined by PMBus. ++ */ ++ ret = i2c_smbus_read_word_data(client, EFUSE_CFG); ++ if (ret < 0) ++ return ret; ++ if (ret & BIT(12)) { ++ ret = i2c_smbus_read_word_data(client, PMBUS_READ_VOUT); ++ if (ret < 0) ++ return ret; ++ exponent = ((s16)ret) >> 11; ++ mantissa = ((s16)((ret & 0x7ff) << 5)) >> 5; ++ val = mantissa * 1000; ++ if (exponent >= 0) ++ val <<= exponent; ++ else ++ val >>= -exponent; ++ return div_s64(val * 10 + 313L, 625L); ++ } ++ ret = -ENODATA; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++static int mp5926_read_byte_data(struct i2c_client *client, int page, int reg) ++{ ++ int ret; ++ ++ switch (reg) { ++ case PMBUS_STATUS_BYTE: ++ case PMBUS_STATUS_VOUT: ++ case PMBUS_STATUS_INPUT: ++ case PMBUS_STATUS_TEMPERATURE: ++ case PMBUS_STATUS_CML: ++ case PMBUS_STATUS_MFR_SPECIFIC: ++ ret = -ENODATA; ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ return ret; ++} ++ ++static struct pmbus_driver_info mp5926_info_linear = { ++ .pages = PAGE, ++ .format[PSC_VOLTAGE_IN] = linear, ++ .format[PSC_CURRENT_IN] = linear, ++ .format[PSC_VOLTAGE_OUT] = direct, ++ .format[PSC_TEMPERATURE] = linear, ++ .format[PSC_POWER] = linear, ++ ++ .m[PSC_VOLTAGE_OUT] = 16, ++ .b[PSC_VOLTAGE_OUT] = 0, ++ .R[PSC_VOLTAGE_OUT] = 0, ++ ++ .read_word_data = mp5926_read_word_data, ++ .read_byte_data = mp5926_read_byte_data, ++ .func[0] = MP5926_FUNC, ++}; ++ ++static struct pmbus_driver_info mp5926_info_direct = { ++ .pages = PAGE, ++ .format[PSC_VOLTAGE_IN] = direct, ++ .format[PSC_CURRENT_IN] = direct, ++ .format[PSC_VOLTAGE_OUT] = direct, ++ .format[PSC_TEMPERATURE] = direct, ++ .format[PSC_POWER] = direct, ++ ++ .m[PSC_VOLTAGE_IN] = 16, ++ .b[PSC_VOLTAGE_IN] = 0, ++ .R[PSC_VOLTAGE_IN] = 0, ++ ++ .m[PSC_CURRENT_IN] = 16, ++ .b[PSC_CURRENT_IN] = 0, ++ .R[PSC_CURRENT_IN] = 0, ++ ++ .m[PSC_VOLTAGE_OUT] = 16, ++ .b[PSC_VOLTAGE_OUT] = 0, ++ .R[PSC_VOLTAGE_OUT] = 0, ++ ++ .m[PSC_TEMPERATURE] = 4, ++ .b[PSC_TEMPERATURE] = 0, ++ .R[PSC_TEMPERATURE] = 3, ++ ++ .m[PSC_POWER] = 25, ++ .b[PSC_POWER] = 0, ++ .R[PSC_POWER] = -2, ++ ++ .read_word_data = mp5926_read_word_data, ++ .read_byte_data = mp5926_read_byte_data, ++ .func[0] = MP5926_FUNC, ++}; ++ ++static int mp5926_probe(struct i2c_client *client) ++{ ++ int ret; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA | ++ I2C_FUNC_SMBUS_BLOCK_DATA)) ++ return -ENODEV; ++ ++ ret = i2c_smbus_read_word_data(client, EFUSE_CFG); ++ ++ if (ret < 0) ++ return ret; ++ ++ if (ret & BIT(12)) { ++ ret = pmbus_do_probe(client, &mp5926_info_linear); ++ } else { ++ ret = i2c_smbus_read_word_data(client, I_SCALE_SEL); ++ if (ret < 0) ++ return ret; ++ if (ret & BIT(6)) ++ mp5926_info_direct.m[PSC_CURRENT_IN] = 4; ++ ret = pmbus_do_probe(client, &mp5926_info_direct); ++ } ++ if (!ret) ++ dev_info(&client->dev, "%s chip found\n", client->name); ++ return ret; ++} ++ ++static const struct i2c_device_id mp5926_id[] = { ++ { "mp5926", 0 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, mp5926_id); ++ ++static const struct of_device_id mp5926_of_match[] = { ++ { .compatible = "mps,mp5926" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, mp5926_of_match); ++ ++static struct i2c_driver mp5926_driver = { ++ .probe = mp5926_probe, ++ .driver = { ++ .name = "mp5926", ++ .of_match_table = mp5926_of_match, ++ }, ++ .id_table = mp5926_id, ++}; ++ ++module_i2c_driver(mp5926_driver); ++MODULE_AUTHOR("Yuxi Wang "); ++MODULE_DESCRIPTION("MPS MP5926 HWMON driver"); ++MODULE_LICENSE("GPL"); ++MODULE_IMPORT_NS(PMBUS); +-- +2.8.4 + diff --git a/patches-sonic/8001-platform-mlx-platform-Downstream-Add-SPI-path-for-ra.patch b/patches-sonic/8001-platform-mlx-platform-Downstream-Add-SPI-path-for-ra.patch deleted file mode 100644 index 94bab3943..000000000 --- a/patches-sonic/8001-platform-mlx-platform-Downstream-Add-SPI-path-for-ra.patch +++ /dev/null @@ -1,92 +0,0 @@ -From e598aed4536365af75ab5543364c79123d243104 Mon Sep 17 00:00:00 2001 -From: Vadim Pasternak -Date: Wed, 2 Aug 2023 07:58:51 +0000 -Subject: [PATCH 57/78] platform: mlx-platform: Downstream: Add SPI path for - rack switch for EROT access - -Create spidev for OOB access to External Root of Trusts devices. - -Signed-off-by: Vadim Pasternak ---- - drivers/platform/mellanox/mlx-platform.c | 17 +++++++++++++++++ - drivers/spi/spi.c | 1 + - 2 files changed, 18 insertions(+) - -diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c -index 3472c99..9203ed8 100644 ---- a/drivers/platform/mellanox/mlx-platform.c -+++ b/drivers/platform/mellanox/mlx-platform.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #define MLX_PLAT_DEVICE_NAME "mlxplat" - -@@ -3336,6 +3337,16 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_l1_switch_data = { - .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT, - }; - -+static struct spi_board_info rack_switch_switch_spi_board_info[] = { -+ { -+ .modalias = "spidev", -+ .irq = -1, -+ .max_speed_hz = 20000000, -+ .bus_num = 0, -+ .chip_select = 0, -+ }, -+}; -+ - /* Platform hotplug for 800G systems family data */ - static struct mlxreg_core_item mlxplat_mlxcpld_ng800_hi171_items[] = { - { -@@ -7524,6 +7535,7 @@ static struct mlxreg_core_platform_data - *mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS]; - static struct mlxreg_core_data *mlxplat_dpu_data[MLXPLAT_CPLD_DPU_MAX_DEVS]; - static const struct regmap_config *mlxplat_regmap_config; -+static struct spi_board_info *mlxplat_spi; - static struct pci_dev *lpc_bridge; - static struct pci_dev *i2c_bridge; - static struct pci_dev *jtag_bridge; -@@ -7846,6 +7858,7 @@ static int __init mlxplat_dmi_rack_switch_matched(const struct dmi_system_id *dm - mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; - mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_rack_switch; -+ mlxplat_spi = rack_switch_switch_spi_board_info; - - return mlxplat_register_platform_device(); - } -@@ -7911,6 +7924,7 @@ static int __init mlxplat_dmi_l1_switch_matched(const struct dmi_system_id *dmi) - mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_rack_switch; - pm_power_off = mlxplat_poweroff; - mlxplat_reboot_nb = &mlxplat_reboot_default_nb; -+ mlxplat_spi = rack_switch_switch_spi_board_info; - - return mlxplat_register_platform_device(); - } -@@ -8511,6 +8525,9 @@ static int mlxplat_platdevs_init(struct mlxplat_priv *priv) - } - } - -+ if (mlxplat_spi) -+ spi_register_board_info(mlxplat_spi, 1); -+ - /* Add WD drivers. */ - err = mlxplat_mlxcpld_check_wd_capability(priv->regmap); - if (err) -diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c -index 0f3e6e2..1e35969 100644 ---- a/drivers/spi/spi.c -+++ b/drivers/spi/spi.c -@@ -952,6 +952,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) - - return 0; - } -+EXPORT_SYMBOL(spi_register_board_info); - - /*-------------------------------------------------------------------------*/ - --- -2.8.4 - diff --git a/patches-sonic/series b/patches-sonic/series index bd5992a7e..7e1e96dac 100644 --- a/patches-sonic/series +++ b/patches-sonic/series @@ -110,9 +110,11 @@ driver-net-tg3-change-dma-mask-for-57766.patch 0052-platform-mellanox-Introduce-support-for-switches-equ.patch 0053-platform-mellanox-mlx-platform-Add-support-for-new-X.patch 0054-i2c-asf-Introduce-MCTP-support-over-ASF-controller.patch +0054-1-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch 0055-platform-mellanox-Downstream-Add-support-DGX-flavor-.patch +0056-hwmon-pmbus-mp2845-Add-support-for-MP2845-device.patch +0057-hwmon-pmbus-mp5926-Add-support-for-MP5926-device.patch 8000-mlxsw-Use-weak-reverse-dependencies-for-firmware-fla.patch -8001-platform-mlx-platform-Downstream-Add-SPI-path-for-ra.patch 8002-mlxsw-i2c-SONIC-ISSU-Prevent-transaction-execution-f.patch 8003-mlxsw-minimal-Downstream-Ignore-error-reading-SPAD-r.patch 8004-leds-leds-mlxreg-Downstream-Send-udev-event-from-led.patch @@ -124,7 +126,6 @@ driver-net-tg3-change-dma-mask-for-57766.patch 8010-mlxsw-minimal-Downstream-Disable-ethtool-interface.patch 8011-hwmon-pmbus-Downstream-Workaround-for-psu-attributes.patch 8013-hwmon-pmbus-mp2975-Clear-interrupts-at-probe.patch -9000-platform-mellanox-Downstream-Add-support-for-new-Nvi.patch ###-> mellanox_hw_mgmt-end # Cisco patches for 5.10 kernel