diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..2295e1ca9 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,87 @@ +# Copilot Instructions for sonic-linux-kernel + +## Project Overview + +sonic-linux-kernel contains the build scripts, patches, and kernel configuration for the SONiC Linux kernel. SONiC uses a single shared kernel across all platforms, preferring out-of-tree kernel modules for platform-specific hardware support. This repo manages kernel patches, configuration options, and the Debian kernel package build. + +## Architecture + +``` +sonic-linux-kernel/ +├── Makefile # Top-level build — produces Debian kernel packages +├── patch/ # Kernel configuration and patch management +│ ├── kconfig-exclusions # Kernel options to remove (reduce build time) +│ ├── kconfig-inclusions # Kernel options to add +│ └── series # Patch application order +├── patches-sonic/ # SONiC-specific kernel patches +├── patches-debian/ # Debian-specific kernel patches +├── config.local # Local kernel config overrides +├── manage-config # Script to manage kernel configuration +├── .azure-pipelines/ # Azure DevOps CI +└── azure-pipelines.yml # CI pipeline +``` + +### Key Concepts +- **Single kernel for all platforms**: All SONiC platforms share the same kernel image +- **Out-of-tree modules**: Platform-specific drivers should be built as external modules +- **kconfig management**: Options excluded via `kconfig-exclusions`, included via `kconfig-inclusions` +- **Patch layers**: `patches-sonic/` for SONiC-specific, `patches-debian/` for Debian-derived patches + +## Language & Style + +- **Primary languages**: Shell scripts, Makefiles, C (kernel patches) +- **Kernel patches**: Must pass `checkpatch.pl` validation +- **Patch format**: Standard kernel patch format with upstream commit reference when applicable +- **Commit messages**: Include original upstream commit ID and message for backported patches + +## Build Instructions + +```bash +# Build kernel Debian packages +make DEST= + +# If DEST is not set, packages stay in current directory +make +``` + +## Kernel Configuration Changes + +### Excluding Options (speed up builds) +Add to `patch/kconfig-exclusions`: +``` +CONFIG_REISERFS_FS +CONFIG_JFS_FS +CONFIG_XFS_FS +``` + +### Including Options +Add to `patch/kconfig-inclusions` with the desired value: +``` +CONFIG_MY_DRIVER=m +``` + +## Patch Acceptance Criteria + +Kernel patches are accepted under these conditions: +1. **Enable existing modules**: Enabling built-in kernel modules for SONiC use +2. **Upstream patches**: Backported patches that are already accepted upstream (include upstream commit ID) +3. **Common platform modules**: New modules needed by all/most platforms +4. **Platform-specific (exception)**: Only when impossible or very difficult to build out-of-tree + +## PR Guidelines + +- **Signed-off-by**: Required on all commits +- **CLA**: Sign Linux Foundation EasyCLA +- **checkpatch.pl**: All kernel patches MUST pass `checkpatch.pl` +- **Upstream first**: Prefer upstream patches — include the original commit hash +- **Justification**: Explain why a patch is needed and why it can't be done out-of-tree +- **CI**: Azure pipeline checks must pass + +## Gotchas + +- **Build time**: Full kernel build is slow — use kconfig-exclusions to remove unnecessary drivers +- **All platforms affected**: Kernel changes impact every SONiC platform +- **ABI stability**: Kernel ABI changes can break out-of-tree platform modules +- **Patch rebasing**: During kernel version upgrades, all patches must be ported — minimize the patch set +- **Config conflicts**: `kconfig-exclusions` and `kconfig-inclusions` can conflict — exclusions take priority +- **Out-of-tree preference**: Reviewers will push back on patches that could be out-of-tree modules diff --git a/config.local/amd64/config.sonic b/config.local/amd64/config.sonic index 23bf715f2..c09b6652f 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 diff --git a/config.local/arm64/config.sonic-aspeed b/config.local/arm64/config.sonic-aspeed index 1323634ef..aa3e11f0d 100644 --- a/config.local/arm64/config.sonic-aspeed +++ b/config.local/arm64/config.sonic-aspeed @@ -22,7 +22,8 @@ CONFIG_MDIO_ASPEED=m CONFIG_ASPEED_KCS_IPMI_BMC=m CONFIG_ASPEED_BT_IPMI_BMC=m CONFIG_SPI_ASPEED_SMC=m -CONFIG_I2C_ASPEED=m +# CONFIG_I2C_ASPEED is not set +CONFIG_I2C_AST2600=m CONFIG_SPI_ASPEED_TXRX=y CONFIG_PINCTRL_ASPEED=y CONFIG_PINCTRL_ASPEED_G7=y @@ -31,6 +32,7 @@ CONFIG_GPIO_ASPEED_SGPIO=y CONFIG_GPIO_ASPEED_LTPI=y CONFIG_SENSORS_ASPEED=y CONFIG_SENSORS_ASPEED_G6=m +CONFIG_SENSORS_ASPEED_CHASSIS=m CONFIG_ASPEED_WATCHDOG=y CONFIG_MEDIA_SUPPORT=m CONFIG_VIDEO_DEV=m 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..8f6711267 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 e1efc50e70baeffd64fb6f233fc0b929a530b59e 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,23 @@ 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 | 28 + + drivers/platform/mellanox/Makefile | 3 + + drivers/platform/mellanox/nvsw-bmc-hid162.c | 2773 +++++++++++++++++ + drivers/platform/mellanox/nvsw-core.c | 685 ++++ + drivers/platform/mellanox/nvsw-host-l1.c | 744 +++++ + drivers/platform/mellanox/nvsw-host-spc5.c | 943 ++++++ + drivers/platform/mellanox/nvsw.h | 292 ++ + 8 files changed, 5473 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.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 +50,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..521423f4b 100644 --- a/drivers/platform/mellanox/Kconfig +++ b/drivers/platform/mellanox/Kconfig -@@ -105,6 +105,24 @@ config MLXBF_PMC +@@ -105,6 +105,34 @@ config MLXBF_PMC to performance monitoring counters within various blocks in the Mellanox BlueField SoC via a sysfs interface. @@ -65,31 +67,42 @@ 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_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..a7c15b0aa 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,7 @@ 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_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 +2881,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..1012da6a6 --- /dev/null +++ b/drivers/platform/mellanox/nvsw-core.c -@@ -0,0 +1,625 @@ +@@ -0,0 +1,685 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Nvidia BMC platform driver @@ -2900,6 +2913,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: @@ -2977,6 +2991,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 +3004,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 +3020,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 +3066,15 @@ 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_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 +3114,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 +3154,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 +3167,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 +3183,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 +3227,15 @@ 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_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 +3252,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 +3277,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 +3296,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 +3377,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; + } + } @@ -3322,8 +3389,9 @@ index 00000000..bfe56ab + PLATFORM_DEVID_NONE, NULL, 0, + nvsw_core->fan_data, + sizeof(*nvsw_core->fan_data)); -+ if (IS_ERR(nvsw_core->fan_data)) { -+ err = PTR_ERR(nvsw_core->fan_data); ++ if (IS_ERR(nvsw_core->fan)) { ++ err = PTR_ERR(nvsw_core->fan); ++ dev_err(nvsw_core->dev, "Failed to register mlxreg-fan driver\n"); + goto fail_platform_fan_register; + } + } @@ -3337,6 +3405,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; + } + } @@ -3353,6 +3422,7 @@ index 00000000..bfe56ab + sizeof(*nvsw_core->hotplug_data)); + if (IS_ERR(nvsw_core->hotplug)) { + err = PTR_ERR(nvsw_core->hotplug); ++ dev_err(nvsw_core->dev, "Failed to register mlxreg-hotplug driver\n"); + goto fail_platform_hotplug_register; + } + } @@ -3366,6 +3436,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; + } + } @@ -3376,6 +3447,8 @@ index 00000000..bfe56ab +fail_platform_wd_register: + while (i--) + platform_device_unregister(nvsw_core->wd[i]); ++ if (nvsw_core->hotplug_data) ++ platform_device_unregister(nvsw_core->hotplug); +fail_platform_hotplug_register: + if (nvsw_core->led_data) + platform_device_unregister(nvsw_core->led); @@ -3437,7 +3510,7 @@ index 00000000..bfe56ab + } + + if (IS_ERR(nvsw_core->regmap)) { -+ dev_err(nvsw_core->dev, "Failed to create regmap"); ++ dev_err(nvsw_core->dev, "Failed to create regmap\n"); + return PTR_ERR(nvsw_core->regmap); + } + @@ -3445,7 +3518,7 @@ index 00000000..bfe56ab + regcache_mark_dirty(nvsw_core->regmap); + err = regcache_sync(nvsw_core->regmap); + if (err) { -+ dev_err(nvsw_core->dev, "Failed to sync regmap"); ++ dev_err(nvsw_core->dev, "Failed to sync regmap\n"); + return err; + } + @@ -3453,7 +3526,7 @@ index 00000000..bfe56ab + if (nvsw_core->set_reg_default) { + err = nvsw_core->set_reg_default(nvsw_core->regmap); + if (err) { -+ dev_err(nvsw_core->dev, "Failed to set default regmap"); ++ dev_err(nvsw_core->dev, "Failed to set default regmap\n"); + return err; + } + } @@ -3499,10 +3572,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 +4320,961 @@ 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..e54bd4109 +--- /dev/null ++++ b/drivers/platform/mellanox/nvsw-host-spc5.c +@@ -0,0 +1,943 @@ ++// 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 = "bios_active_image", ++ .reg = NVSW_REG_GPCOM0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .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.h b/drivers/platform/mellanox/nvsw.h new file mode 100644 -index 00000000..b1ae4db +index 000000000..9a0b48409 --- /dev/null +++ b/drivers/platform/mellanox/nvsw.h -@@ -0,0 +1,260 @@ +@@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * Nvidia BMC platform driver @@ -4277,6 +5298,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 +5314,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 +5323,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 +5357,30 @@ 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_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 +5398,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 +5437,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 +5445,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 +5483,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 +5502,8 @@ index 00000000..b1ae4db + HID176, + HID177, + HID180, ++ HID181, ++ HID182, +}; + + /* The system register map type. */ @@ -4515,5 +5568,5 @@ index 00000000..b1ae4db +#endif /* !defined(__NVSW_H__) */ + -- -2.8.4 +2.34.1 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/nexthop-b27-dts.patch b/patches-sonic/nexthop-b27-dts.patch new file mode 100644 index 000000000..f0c25b2da --- /dev/null +++ b/patches-sonic/nexthop-b27-dts.patch @@ -0,0 +1,971 @@ +From 9b8f9f3eed5b8732aca6533ddfde184332e254b7 Mon Sep 17 00:00:00 2001 +From: NextHop Build System +Date: Tue, 13 Jan 2026 16:28:15 +0000 +Subject: [PATCH] Add NextHop AST2700 R0 device tree + +This adds nexthop-b27-r0.dts for NextHop AST2700 based B27 R0 hardware. + +Hardware differences from ast2700-evb: +- MAC0: Fixed-link (1000Mbps) instead of PHY - direct RGMII to BCM switch +- MAC1: Disabled (not connected) +- MDIO0/MDIO1: Disabled (no PHY chips) + +The device tree is based on ast2700-evb.dts with modifications for +production hardware that does not have PHY chips. +--- + arch/arm64/boot/dts/aspeed/Makefile | 1 + + arch/arm64/boot/dts/aspeed/nexthop-b27-r0.dts | 930 +++++++++++++++++++ + 2 files changed, 931 insertions(+) + create mode 100644 arch/arm64/boot/dts/aspeed/nexthop-b27-r0.dts + +diff --git a/arch/arm64/boot/dts/aspeed/Makefile b/arch/arm64/boot/dts/aspeed/Makefile +index 4458a1b..486146e 100644 +--- a/arch/arm64/boot/dts/aspeed/Makefile ++++ b/arch/arm64/boot/dts/aspeed/Makefile +@@ -2,6 +2,7 @@ + + dtb-$(CONFIG_ARCH_ASPEED) += \ + ast2700-evb.dtb \ ++ nexthop-b27-r0.dtb \ + ast2700-raw.dtb \ + ast2700-evb-s0.dtb \ + ast2700-evb-s1.dtb \ +diff --git a/arch/arm64/boot/dts/aspeed/nexthop-b27-r0.dts b/arch/arm64/boot/dts/aspeed/nexthop-b27-r0.dts +new file mode 100644 +index 0000000..3ca87d4 +--- /dev/null ++++ b/arch/arm64/boot/dts/aspeed/nexthop-b27-r0.dts +@@ -0,0 +1,930 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++// ++// NextHop AST2700 based B27 R0 Device Tree ++// Based on ast2700-evb.dts with modifications for NextHop B27 card ++ ++/dts-v1/; ++ ++#include "aspeed-g7.dtsi" ++#include ++#include ++ ++#define PCIE0_EP 0 // 1: EP, 0: RC ++#define PCIE1_EP 0 // 1: EP, 0: RC ++#define PCIE2_RC 0 // 1: RC, 0: SGMII ++ ++/ { ++ model = "NextHop B27 R0"; ++ compatible = "nexthop,nexthop-b27-r0", "aspeed,ast2700-evb", "aspeed,ast2700"; ++ ++ chosen { ++ stdout-path = &uart12; ++ }; ++ ++ firmware { ++ optee: optee { ++ compatible = "linaro,optee-tz"; ++ method = "smc"; ++ }; ++ }; ++ ++ memory@400000000 { ++ device_type = "memory"; ++ reg = <0x4 0x00000000 0x0 0x40000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ #include "ast2700-reserved-mem.dtsi" ++#if 0 ++ video_engine_memory0: video0 { ++ size = <0x0 0x02c00000>; ++ alignment = <0x0 0x00100000>; ++ compatible = "shared-dma-pool"; ++ reusable; ++ }; ++ ++ video_engine_memory1: video1{ ++ size = <0x0 0x02c00000>; ++ alignment = <0x0 0x00100000>; ++ compatible = "shared-dma-pool"; ++ reusable; ++ }; ++#endif ++ gfx_memory: framebuffer { ++ size = <0x0 0x01000000>; ++ alignment = <0x0 0x01000000>; ++ compatible = "shared-dma-pool"; ++ reusable; ++ }; ++ ++ xdma_memory0: xdma0 { ++ size = <0x0 0x01000000>; ++ alignment = <0x0 0x01000000>; ++ compatible = "shared-dma-pool"; ++ no-map; ++ }; ++ ++ xdma_memory1: xdma1 { ++ size = <0x0 0x01000000>; ++ alignment = <0x0 0x01000000>; ++ compatible = "shared-dma-pool"; ++ no-map; ++ }; ++ }; ++#if 0 ++ fan0: pwm-fan0 { ++ compatible = "pwm-fan"; ++ pwms = <&pwm_tach 0 40000 0>; /* Target freq:25 kHz */ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <0 15 128 255>; ++ }; ++ ++ fan1: pwm-fan1 { ++ compatible = "pwm-fan"; ++ pwms = <&pwm_tach 1 40000 0>; /* Target freq:25 kHz */ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <0 15 128 255>; ++ }; ++ ++ fan2: pwm-fan2 { ++ compatible = "pwm-fan"; ++ pwms = <&pwm_tach 2 40000 0>; /* Target freq:25 kHz */ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <0 15 128 255>; ++ }; ++ ++ fan3: pwm-fan3 { ++ compatible = "pwm-fan"; ++ pwms = <&pwm_tach 3 40000 0>; /* Target freq:25 kHz */ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <0 15 128 255>; ++ }; ++ ++ fan4: pwm-fan4 { ++ compatible = "pwm-fan"; ++ pwms = <&pwm_tach 4 40000 0>; /* Target freq:25 kHz */ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <0 15 128 255>; ++ }; ++ ++ fan5: pwm-fan5 { ++ compatible = "pwm-fan"; ++ pwms = <&pwm_tach 5 40000 0>; /* Target freq:25 kHz */ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <0 15 128 255>; ++ }; ++ ++ fan6: pwm-fan6 { ++ compatible = "pwm-fan"; ++ pwms = <&pwm_tach 6 40000 0>; /* Target freq:25 kHz */ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <0 15 128 255>; ++ }; ++ ++ fan7: pwm-fan7 { ++ compatible = "pwm-fan"; ++ pwms = <&pwm_tach 7 40000 0>; /* Target freq:25 kHz */ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <0 15 128 255>; ++ }; ++ ++ fan8: pwm-fan8 { ++ compatible = "pwm-fan"; ++ pwms = <&pwm_tach 8 40000 0>; /* Target freq:25 kHz */ ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ #cooling-cells = <2>; ++ cooling-levels = <0 15 128 255>; ++ }; ++#endif ++ iio-hwmon { ++ compatible = "iio-hwmon"; ++ status = "okay"; ++ io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>, ++ <&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>, ++ <&adc1 0>, <&adc1 1>, <&adc1 2>, <&adc1 3>, ++ <&adc1 4>, <&adc1 5>, <&adc1 6>, <&adc1 7>; ++ }; ++}; ++ ++#if 0 ++&pwm_tach { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default ++ &pinctrl_pwm2_default &pinctrl_pwm3_default ++ &pinctrl_pwm4_default &pinctrl_pwm5_default ++ &pinctrl_pwm6_default &pinctrl_pwm7_default ++ &pinctrl_pwm8_default ++ &pinctrl_tach0_default &pinctrl_tach1_default ++ &pinctrl_tach2_default &pinctrl_tach3_default ++ &pinctrl_tach4_default &pinctrl_tach5_default ++ &pinctrl_tach6_default &pinctrl_tach7_default ++ &pinctrl_tach8_default &pinctrl_tach9_default ++ &pinctrl_tach10_default &pinctrl_tach11_default ++ &pinctrl_tach12_default &pinctrl_tach13_default ++ &pinctrl_tach14_default &pinctrl_tach15_default>; ++ fan-0 { ++ tach-ch = /bits/ 8 <0x0>; ++ }; ++ fan-1 { ++ tach-ch = /bits/ 8 <0x1>; ++ }; ++ fan-2 { ++ tach-ch = /bits/ 8 <0x2>; ++ }; ++ fan-3 { ++ tach-ch = /bits/ 8 <0x3>; ++ }; ++ fan-4 { ++ tach-ch = /bits/ 8 <0x4>; ++ }; ++ fan-5 { ++ tach-ch = /bits/ 8 <0x5>; ++ }; ++ fan-6 { ++ tach-ch = /bits/ 8 <0x6>; ++ }; ++ fan-7 { ++ tach-ch = /bits/ 8 <0x7>; ++ }; ++ fan-8 { ++ tach-ch = /bits/ 8 <0x8>; ++ }; ++ fan-9 { ++ tach-ch = /bits/ 8 <0x9>; ++ }; ++ fan-10 { ++ tach-ch = /bits/ 8 <0xA>; ++ }; ++ fan-11 { ++ tach-ch = /bits/ 8 <0xB>; ++ }; ++ fan-12 { ++ tach-ch = /bits/ 8 <0xC>; ++ }; ++ fan-13 { ++ tach-ch = /bits/ 8 <0xD>; ++ }; ++ fan-14 { ++ tach-ch = /bits/ 8 <0xE>; ++ }; ++ fan-15 { ++ tach-ch = /bits/ 8 <0xF>; ++ }; ++}; ++#endif ++&edac { ++ status = "okay"; ++}; ++ ++&mctp0 { ++ status = "okay"; ++ memory-region = <&mctp0_reserved>; ++}; ++ ++&mctp1 { ++ status = "okay"; ++ memory-region = <&mctp1_reserved>; ++}; ++ ++&mctp2 { ++ status = "okay"; ++ memory-region = <&mctp2_reserved>; ++}; ++ ++#if 0 ++&sgpiom0 { ++ status = "okay"; ++}; ++ ++&sgpiom1 { ++ status = "okay"; ++}; ++#endif ++ ++&jtag1 { ++ status = "okay"; ++}; ++ ++#if 0 ++&adc0 { ++ aspeed,int-vref-microvolt = <2500000>; ++ status = "okay"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default ++ &pinctrl_adc2_default &pinctrl_adc3_default ++ &pinctrl_adc4_default &pinctrl_adc5_default ++ &pinctrl_adc6_default &pinctrl_adc7_default>; ++}; ++ ++&adc1 { ++ aspeed,int-vref-microvolt = <2500000>; ++ status = "okay"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_adc8_default &pinctrl_adc9_default ++ &pinctrl_adc10_default &pinctrl_adc11_default ++ &pinctrl_adc12_default &pinctrl_adc13_default ++ &pinctrl_adc14_default &pinctrl_adc15_default>; ++}; ++#endif ++ ++&pinctrl0 { ++ pinctrl_emmcclk_driving: emmcclk-driving { ++ pins = "AC14"; ++ drive-strength = <2>; ++ }; ++ ++ pinctrl_emmccmd_driving: emmccmd-driving { ++ pins = "AE15"; ++ drive-strength = <1>; ++ }; ++ pinctrl_emmcdat_driving: emmcdat-driving { ++ pins = "AD14", "AE14", "AF14", "AB13"; ++ drive-strength = <1>; ++ }; ++}; ++ ++&pinctrl1 { ++ pinctrl_i3c0_3_hv_voltage: i3chv-voltage { ++ pins = "U25"; ++ power-source = <1800>; ++ }; ++ ++ pinctrl_i3c0_driving: i3c0-driving { ++ pins = "U25", "U26"; ++ drive-strength = <2>; ++ }; ++ ++ pinctrl_i3c1_driving: i3c1-driving { ++ pins = "Y26", "AA24"; ++ drive-strength = <2>; ++ }; ++ ++ pinctrl_i3c2_driving: i3c2-driving { ++ pins = "R25", "AA26"; ++ drive-strength = <2>; ++ }; ++ ++ pinctrl_i3c3_driving: i3c3-driving { ++ pins = "R26", "Y25"; ++ drive-strength = <2>; ++ }; ++ ++ pinctrl_i3c12_15_hv_voltage: i3chv-voltage { ++ pins = "W25"; ++ power-source = <1800>; ++ }; ++ ++ pinctrl_i3c12_driving: i3c12-driving { ++ pins = "W25", "Y23"; ++ drive-strength = <2>; ++ }; ++ ++ pinctrl_i3c13_driving: i3c13-driving { ++ pins = "Y24", "W21"; ++ drive-strength = <2>; ++ }; ++ ++ pinctrl_i3c14_driving: i3c14-driving { ++ pins = "AA23", "AC22"; ++ drive-strength = <2>; ++ }; ++ ++ pinctrl_i3c15_driving: i3c15-driving { ++ pins = "AB22", "Y21"; ++ drive-strength = <2>; ++ }; ++ ++ pinctrl_rgmii0_driving: rgmii0-driving { ++ pins = "C20", "C19", "A8", "R14", "A7", "P14", ++ "D20", "A6", "B6", "N14", "B7", "B8"; ++ drive-strength = <1>; ++ }; ++ ++ pinctrl_rgmii1_driving: rgmii1-driving { ++ pins = "D19", "C19", "D15", "B12", "B10", "P13", ++ "C18", "C6", "C7", "D7", "N13", "C8"; ++ drive-strength = <1>; ++ }; ++}; ++ ++&gpio1 { ++ pinctrl-0 = <&pinctrl_i3c0_3_hv_voltage &pinctrl_i3c12_15_hv_voltage ++ &pinctrl_i3c0_driving &pinctrl_i3c1_driving ++ &pinctrl_i3c2_driving &pinctrl_i3c3_driving ++ &pinctrl_i3c12_driving &pinctrl_i3c13_driving ++ &pinctrl_i3c14_driving &pinctrl_i3c15_driving>; ++ pinctrl-names = "default"; ++}; ++ ++#if 0 ++&i3c0 { ++ initial-role = "target"; ++ pid = <0x000007ec 0x06010000>; ++ dcr = /bits/ 8 <0xcc>; ++ status = "okay"; ++}; ++ ++&i3c1 { ++ initial-role = "primary"; ++ status = "okay"; ++}; ++ ++&i3c2 { ++ initial-role = "target"; ++ pid = <0x000007ec 0x06012000>; ++ dcr = /bits/ 8 <0xcc>; ++ status = "okay"; ++}; ++ ++&i3c3 { ++ initial-role = "primary"; ++ status = "okay"; ++}; ++ ++&i3c4 { ++ initial-role = "target"; ++ pid = <0x000007ec 0x06014000>; ++ dcr = /bits/ 8 <0xcc>; ++ status = "okay"; ++}; ++ ++&i3c5 { ++ initial-role = "primary"; ++ status = "okay"; ++}; ++ ++&i3c6 { ++ initial-role = "target"; ++ pid = <0x000007ec 0x06016000>; ++ dcr = /bits/ 8 <0xcc>; ++ status = "okay"; ++}; ++ ++&i3c7 { ++ initial-role = "primary"; ++ status = "okay"; ++}; ++ ++&i3c8 { ++ initial-role = "target"; ++ pid = <0x000007ec 0x06018000>; ++ dcr = /bits/ 8 <0xcc>; ++ status = "okay"; ++}; ++ ++&i3c9 { ++ initial-role = "primary"; ++ status = "okay"; ++}; ++ ++&i3c10 { ++ initial-role = "target"; ++ pid = <0x000007ec 0x0601A000>; ++ dcr = /bits/ 8 <0xcc>; ++ status = "okay"; ++}; ++ ++&i3c11 { ++ initial-role = "primary"; ++ status = "okay"; ++}; ++ ++&i3c12 { ++ initial-role = "target"; ++ pid = <0x000007ec 0x0601C000>; ++ dcr = /bits/ 8 <0xcc>; ++ status = "okay"; ++}; ++ ++&i3c13 { ++ initial-role = "primary"; ++ status = "okay"; ++}; ++ ++&i3c14 { ++ initial-role = "target"; ++ pid = <0x000007ec 0x0601E000>; ++ dcr = /bits/ 8 <0xcc>; ++ status = "okay"; ++}; ++ ++&i3c15 { ++ initial-role = "primary"; ++ status = "okay"; ++}; ++#endif ++ ++&uart1 { ++ status = "okay"; ++}; ++&uart12 { ++ status = "okay"; ++}; ++ ++&fmc { ++ status = "okay"; ++ pinctrl-0 = <&pinctrl_fwspi_quad_default>; ++ pinctrl-names = "default"; ++ ++ flash@0 { ++ status = "okay"; ++ m25p,fast-read; ++ label = "bmc"; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++#include "aspeed-evb-flash-layout-128.dtsi" ++ }; ++ ++ flash@1 { ++ status = "okay"; ++ m25p,fast-read; ++ label = "fmc0:1"; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++ }; ++ ++ flash@2 { ++ status = "disabled"; ++ m25p,fast-read; ++ label = "fmc0:2"; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <4>; ++ spi-rx-bus-width = <4>; ++ }; ++}; ++ ++&spi0 { ++ status = "okay"; ++ pinctrl-0 = <&pinctrl_spi0_default &pinctrl_spi0_cs1_default>; ++ pinctrl-names = "default"; ++ ++ flash@0 { ++ status = "okay"; ++ m25p,fast-read; ++ label = "spi0:0"; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <2>; ++ spi-rx-bus-width = <2>; ++ }; ++ ++ flash@1 { ++ status = "disabled"; ++ m25p,fast-read; ++ label = "spi0:1"; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <2>; ++ spi-rx-bus-width = <2>; ++ }; ++}; ++ ++#if 0 ++&spi1 { ++ status = "okay"; ++ pinctrl-0 = <&pinctrl_spi1_default &pinctrl_spi1_cs1_default>; ++ pinctrl-names = "default"; ++ ++ flash@0 { ++ status = "okay"; ++ m25p,fast-read; ++ label = "spi1:0"; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <2>; ++ spi-rx-bus-width = <2>; ++ }; ++ ++ flash@1 { ++ status = "disabled"; ++ m25p,fast-read; ++ label = "spi1:1"; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <2>; ++ spi-rx-bus-width = <2>; ++ }; ++}; ++#endif ++ ++#if 1 ++&spi2 { ++ compatible = "aspeed,ast2700-spi-txrx"; ++ pinctrl-0 = <&pinctrl_spi2_default>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ spi-aspeed-full-duplex; ++ ++ tpm0: tpmdev@0 { ++ compatible = "tcg,tpm_tis-spi"; ++ spi-max-frequency = <25000000>; ++ reg = <0>; ++ status = "okay"; ++ }; ++}; ++#else ++&spi2 { ++ compatible = "aspeed,ast2700-spi"; ++ pinctrl-0 = <&pinctrl_spi2_default &pinctrl_spi2_cs1_default>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ flash@0 { ++ status = "okay"; ++ reg = < 0 >; ++ compatible = "jedec,spi-nor"; ++ m25p,fast-read; ++ label = "spi2:0"; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <2>; ++ spi-rx-bus-width = <2>; ++ }; ++ ++ flash@1 { ++ status = "okay"; ++ reg = < 1 >; ++ compatible = "jedec,spi-nor"; ++ m25p,fast-read; ++ label = "spi2:1"; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <2>; ++ spi-rx-bus-width = <2>; ++ }; ++}; ++#endif ++ ++#if 0 ++&can0 { ++ status = "okay"; ++}; ++#endif ++ ++&emmc_controller { ++ status = "okay"; ++ mmc-hs200-1_8v; ++}; ++ ++&emmc { ++ status = "okay"; ++#if 1 ++ bus-width = <4>; ++#else ++ bus-width = <8>; ++ pinctrl-0 = <&pinctrl_emmc_default ++ &pinctrl_emmcg8_default>; ++#endif ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_emmc_default &pinctrl_emmcclk_driving &pinctrl_emmccmd_driving &pinctrl_emmcdat_driving>; ++ ++ non-removable; ++ max-frequency = <200000000>; ++}; ++ ++#if 0 ++&ufs_controller { ++ status = "okay"; ++}; ++ ++&ufs { ++ status = "okay"; ++ lanes-per-direction = <2>; ++ ref-clk-freq = <26000000>; ++}; ++#endif ++ ++&chassis { ++ status = "okay"; ++}; ++ ++&mac0 { ++ status = "okay"; ++ /*compatible = "brcm,bcm53134";*/ ++ phy-mode = "rgmii-id"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_rgmii0_default &pinctrl_rgmii0_driving>; ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ pause; ++ }; ++}; ++ ++&mdio0 { ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ switch@1e { ++ compatible = "brcm,bcm53134"; ++ reg = <0x1e>; ++ ++ dsa,member = <0 0>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* Port 0 - External RJ45 with internal PHY */ ++ port@0 { ++ reg = <0>; ++ label = "rj45"; ++ phy-handle = <&switch0phy0>; ++ }; ++ ++ /* Port 5 - x86 with internal PHY */ ++ port@5 { ++ reg = <5>; ++ label = "x86"; ++ phy-handle = <&switch0phy5>; ++ }; ++ ++ /* Port 8 - IMP to AST2700 MAC0 */ ++ port@8 { ++ reg = <8>; ++ label = "cpu"; ++ ethernet = <&mac0>; ++ phy-mode = "rgmii-id"; ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ pause; ++ }; ++ }; ++ }; ++ ++ /* BCM53134 internal MDIO bus for internal PHYs */ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ switch0phy0: ethernet-phy@0 { ++ reg = <0>; ++ }; ++ ++ switch0phy5: ethernet-phy@5 { ++ reg = <5>; ++ }; ++ }; ++ }; ++}; ++ ++ ++&syscon1 { ++ assigned-clocks = <&syscon1 SCU1_CLK_MACHCLK>, ++ <&syscon1 SCU1_CLK_RGMII>, ++ <&syscon1 SCU1_CLK_RMII>; ++ assigned-clock-rates = <200000000>, <125000000>, <50000000>; ++}; ++ ++&espi0 { ++ status = "okay"; ++ perif-dma-mode; ++ perif-mmbi-enable; ++ perif-mmbi-src-addr = <0x0 0xa8000000>; ++ perif-mmbi-tgt-memory = <&espi0_mmbi_memory>; ++ perif-mmbi-instance-num = <0x1>; ++ perif-mcyc-enable; ++ perif-mcyc-src-addr = <0x0 0x98000000>; ++ perif-mcyc-size = <0x0 0x10000>; ++ perif-rtc-enable; ++ oob-dma-mode; ++ flash-dma-mode; ++#if 0 // if support eDAF MIX mode, open this if case to use sample code ++ flash-edaf-mode = <0x0>; ++ flash-edaf-tgt-addr = <&edaf0>; ++ flash-edaf-size = <0x0 0x4000000>; ++#endif ++}; ++ ++&rtc_over_espi0 { ++ status = "okay"; ++}; ++ ++#if 0 ++&lpc0_kcs0 { ++ status = "okay"; ++ kcs-io-addr = <0xca0>; ++ kcs-channel = <0>; ++}; ++ ++&lpc0_kcs1 { ++ status = "okay"; ++ kcs-io-addr = <0xca8>; ++ kcs-channel = <1>; ++}; ++ ++&lpc0_kcs2 { ++ status = "okay"; ++ kcs-io-addr = <0xca2>; ++ kcs-channel = <2>; ++}; ++ ++&lpc0_kcs3 { ++ status = "okay"; ++ kcs-io-addr = <0xca4>; ++ kcs-channel = <3>; ++}; ++#endif ++ ++&rtc { ++ status = "okay"; ++}; ++ ++ ++&jtag0 { ++ status = "okay"; ++}; ++ ++&sdio_controller { ++ status = "disabled"; ++ mmc-hs200-1_8v; ++ ++ vcc_sdhci0: regulator-vcc-sdhci0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "SDHCI0 Vcc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpios = <&gpio1 ASPEED_GPIO(G, 6) GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vccq_sdhci0: regulator-vccq-sdhci0 { ++ compatible = "regulator-gpio"; ++ regulator-name = "SDHCI0 VccQ"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ gpios = <&gpio1 ASPEED_GPIO(G, 7) GPIO_ACTIVE_HIGH>; ++ gpios-states = <1>; ++ states = <3300000 1>, ++ <1800000 0>; ++ }; ++ ++}; ++ ++&sdhci { ++ status = "disabled"; ++ bus-width = <4>; ++ max-frequency = <100000000>; ++ /* DDR50 bits in CAPA2 are not supported */ ++ sdhci-caps-mask = <0x6 0x0>; ++ sdhci-drive-type = /bits/ 8 <3>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_sd_default>; ++ vmmc-supply = <&vcc_sdhci0>; ++ vqmmc-supply = <&vccq_sdhci0>; ++ sd-uhs-sdr104; /* enable sdr104 to execute tuning */ ++}; ++ ++#if 1 ++&i2c0 { ++ status = "okay"; ++}; ++ ++&i2c1 { ++ status = "okay"; ++}; ++ ++&i2c2 { ++ status = "okay"; ++}; ++ ++&i2c3 { ++ status = "okay"; ++}; ++ ++&i2c4 { ++ status = "okay"; ++}; ++ ++&i2c5 { ++ status = "disabled"; ++}; ++ ++&i2c6 { ++ status = "okay"; ++}; ++ ++&i2c7 { ++ status = "okay"; ++}; ++ ++&i2c8 { ++ status = "okay"; ++}; ++ ++&i2c9 { ++ status = "okay"; ++}; ++ ++&i2c10 { ++ status = "okay"; ++}; ++ ++&i2c11 { ++ status = "okay"; ++}; ++ ++&i2c12 { ++ status = "okay"; ++}; ++ ++&i2c13 { ++ status = "disabled"; ++}; ++#endif ++ ++#if 0 ++&ehci0 { ++ status = "okay"; ++}; ++#endif ++ ++&vhubb0 { ++ status = "disabled"; ++}; ++ ++&vhubb1 { ++ status = "okay"; ++ pinctrl-0 = <&pinctrl_usb2bd1_default>; ++}; ++ ++#if 0 ++&vhuba0 { ++ status = "okay"; ++ pinctrl-0 = <&pinctrl_usb2ahpd0_default>; ++}; ++#endif ++&wdt0 { ++ status = "okay"; ++}; ++ ++&wdt1 { ++ status = "okay"; ++}; ++ ++&otp { ++ status = "okay"; ++}; ++ +-- +2.34.1 + diff --git a/patches-sonic/series b/patches-sonic/series index bd5992a7e..f086e61a6 100644 --- a/patches-sonic/series +++ b/patches-sonic/series @@ -111,6 +111,8 @@ driver-net-tg3-change-dma-mask-for-57766.patch 0053-platform-mellanox-mlx-platform-Add-support-for-new-X.patch 0054-i2c-asf-Introduce-MCTP-support-over-ASF-controller.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 @@ -220,6 +222,7 @@ cisco-npu-disable-other-bars.patch ###-> aspeed aspeed-ast2700-support.patch +nexthop-b27-dts.patch ###-> aspeed-end #