OSDN Git Service

platform: mellanox: Introduce support of new Nvidia L1 switch
authorVadim Pasternak <vadimp@nvidia.com>
Wed, 8 Feb 2023 06:33:22 +0000 (08:33 +0200)
committerHans de Goede <hdegoede@redhat.com>
Fri, 10 Feb 2023 16:43:33 +0000 (17:43 +0100)
Add support for new L1 switch nodes providing L1 connectivity for
multi-node networking chassis.

The purpose is to provide compute server with full management and IO
subsystems with connections to L1 switches.

System contains the following components:
- COMe module based on Intel Coffee Lake CPU
- Switch baseboard with two ASICs, while
  24 ports of each ASICs are connected to one backplane connector
  32 ports of each ASIC are connected to 8 OSFPs
- Integrated 60mm dual-rotor FANs inside L1 node (N+2 redundancy)
- Support 48V or 54V DC input from the external power server.

Add the structures related to the new systems to allow proper activation
of the all required platform driver.

Add poweroff callback to support deep power cycle flow, which should
include special actions against CPLD device for performing graceful
operation.

Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Reviewed-by: Michael Shych <michaelsh@nvidia.com>
Link: https://lore.kernel.org/r/20230208063331.15560-6-vadimp@nvidia.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
drivers/platform/x86/mlx-platform.c

index cd7f6ff..1a07a99 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/platform_data/i2c-mux-reg.h>
 #include <linux/platform_data/mlxreg.h>
+#include <linux/reboot.h>
 #include <linux/regmap.h>
 
 #define MLX_PLAT_DEVICE_NAME           "mlxplat"
 #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET        0x37
 #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET       0x3a
 #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET  0x3b
+#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET       0x3c
+#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET       0x3d
+#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET       0x3e
+#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET       0x3f
 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET     0x40
 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET        0x41
 #define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET     0x42
 #define MLXPLAT_CPLD_LPC_REG_AGGRCO_MASK_OFFSET        0x43
 #define MLXPLAT_CPLD_LPC_REG_AGGRCX_OFFSET     0x44
 #define MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET 0x45
+#define MLXPLAT_CPLD_LPC_REG_BRD_OFFSET                0x47
+#define MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET  0x48
+#define MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET   0x49
 #define MLXPLAT_CPLD_LPC_REG_GWP_OFFSET                0x4a
 #define MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET  0x4b
 #define MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET   0x4c
 #define MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET      0x94
 #define MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET        0x95
 #define MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET 0x96
+#define MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET       0x97
+#define MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET 0x98
+#define MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET  0x99
 #define MLXPLAT_CPLD_LPC_REG_LC_VR_OFFSET      0x9a
 #define MLXPLAT_CPLD_LPC_REG_LC_VR_EVENT_OFFSET        0x9b
 #define MLXPLAT_CPLD_LPC_REG_LC_VR_MASK_OFFSET 0x9c
 #define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET    0xd1
 #define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET  0xd2
 #define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET    0xd3
+#define MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET   0xd9
 #define MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET 0xde
 #define MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET 0xdf
 #define MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET 0xe0
                                         MLXPLAT_CPLD_AGGR_MASK_LC_SDWN)
 #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1
 #define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2       BIT(2)
+#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT     BIT(4)
 #define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6)
 #define MLXPLAT_CPLD_PSU_MASK          GENMASK(1, 0)
 #define MLXPLAT_CPLD_PWR_MASK          GENMASK(1, 0)
 #define MLXPLAT_CPLD_VOLTREG_UPD_MASK  GENMASK(5, 4)
 #define MLXPLAT_CPLD_GWP_MASK          GENMASK(0, 0)
 #define MLXPLAT_CPLD_EROT_MASK         GENMASK(1, 0)
+#define MLXPLAT_CPLD_PWR_BUTTON_MASK   BIT(0)
+#define MLXPLAT_CPLD_LATCH_RST_MASK    BIT(5)
+#define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3)
+#define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4)
+#define MLXPLAT_CPLD_INTRUSION_MASK    BIT(6)
+#define MLXPLAT_CPLD_PWM_PG_MASK       BIT(7)
+#define MLXPLAT_CPLD_L1_CHA_HEALTH_MASK (MLXPLAT_CPLD_THERMAL1_PDB_MASK | \
+                                        MLXPLAT_CPLD_THERMAL2_PDB_MASK | \
+                                        MLXPLAT_CPLD_INTRUSION_MASK |\
+                                        MLXPLAT_CPLD_PWM_PG_MASK)
 #define MLXPLAT_CPLD_I2C_CAP_BIT       0x04
 #define MLXPLAT_CPLD_I2C_CAP_MASK      GENMASK(5, MLXPLAT_CPLD_I2C_CAP_BIT)
 
 /* Masks for aggregation for modular systems */
 #define MLXPLAT_CPLD_LPC_LC_MASK       GENMASK(7, 0)
 
+#define MLXPLAT_CPLD_HALT_MASK         BIT(3)
+
 /* Default I2C parent bus number */
 #define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR       1
 
@@ -315,6 +340,8 @@ struct mlxplat_priv {
        void *regmap;
 };
 
+static struct platform_device *mlxplat_dev;
+
 /* Regions for LPC I2C controller and LPC base register space */
 static const struct resource mlxplat_lpc_resources[] = {
        [0] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_I2C_BASE_ADRR,
@@ -2307,6 +2334,156 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_rack_switch_data = {
        .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
 };
 
+/* Callback performs graceful shutdown after notification about power button event */
+static int
+mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_kind kind,
+                                            u8 action)
+{
+       dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button");
+       kernel_halt();
+       return 0;
+}
+
+static struct mlxreg_core_hotplug_notifier mlxplat_mlxcpld_l1_switch_pwr_events_notifier = {
+       .user_handler = mlxplat_mlxcpld_l1_switch_pwr_events_handler,
+};
+
+/* Platform hotplug for l1 switch systems family data  */
+static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_pwr_events_items_data[] = {
+       {
+               .label = "power_button",
+               .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET,
+               .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK,
+               .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
+               .hpdev.notifier = &mlxplat_mlxcpld_l1_switch_pwr_events_notifier,
+       },
+};
+
+/* Callback activates latch reset flow after notification about intrusion event */
+static int
+mlxplat_mlxcpld_l1_switch_intrusion_events_handler(void *handle, enum mlxreg_hotplug_kind kind,
+                                                  u8 action)
+{
+       struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
+       u32 regval;
+       int err;
+
+       err = regmap_read(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, &regval);
+       if (err)
+               goto fail_regmap_read;
+
+       if (action) {
+               dev_info(&mlxplat_dev->dev, "Detected intrusion - system latch is opened");
+               err = regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+                                  regval | MLXPLAT_CPLD_LATCH_RST_MASK);
+       } else {
+               dev_info(&mlxplat_dev->dev, "System latch is properly closed");
+               err = regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+                                  regval & ~MLXPLAT_CPLD_LATCH_RST_MASK);
+       }
+
+       if (err)
+               goto fail_regmap_write;
+
+       return 0;
+
+fail_regmap_read:
+fail_regmap_write:
+       dev_err(&mlxplat_dev->dev, "Register access failed");
+       return err;
+}
+
+static struct mlxreg_core_hotplug_notifier mlxplat_mlxcpld_l1_switch_intrusion_events_notifier = {
+       .user_handler = mlxplat_mlxcpld_l1_switch_intrusion_events_handler,
+};
+
+static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_health_events_items_data[] = {
+       {
+               .label = "thermal1_pdb",
+               .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET,
+               .mask = MLXPLAT_CPLD_THERMAL1_PDB_MASK,
+               .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
+       },
+       {
+               .label = "thermal2_pdb",
+               .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET,
+               .mask = MLXPLAT_CPLD_THERMAL2_PDB_MASK,
+               .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
+       },
+       {
+               .label = "intrusion",
+               .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET,
+               .mask = MLXPLAT_CPLD_INTRUSION_MASK,
+               .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
+               .hpdev.notifier = &mlxplat_mlxcpld_l1_switch_intrusion_events_notifier,
+       },
+       {
+               .label = "pwm_pg",
+               .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET,
+               .mask = MLXPLAT_CPLD_PWM_PG_MASK,
+               .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
+       },
+};
+
+static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = {
+       {
+               .data = mlxplat_mlxcpld_default_ng_fan_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
+               .mask = MLXPLAT_CPLD_FAN_NG_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data),
+               .inversed = 1,
+               .health = false,
+       },
+       {
+               .data = mlxplat_mlxcpld_erot_ap_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET,
+               .mask = MLXPLAT_CPLD_EROT_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_ap_items_data),
+               .inversed = 1,
+               .health = false,
+       },
+       {
+               .data = mlxplat_mlxcpld_erot_error_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET,
+               .mask = MLXPLAT_CPLD_EROT_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_erot_error_items_data),
+               .inversed = 1,
+               .health = false,
+       },
+       {
+               .data = mlxplat_mlxcpld_l1_switch_pwr_events_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET,
+               .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data),
+               .inversed = 0,
+               .health = false,
+       },
+       {
+               .data = mlxplat_mlxcpld_l1_switch_health_events_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET,
+               .mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data),
+               .inversed = 0,
+               .health = false,
+               .ind = 8,
+       },
+};
+
+static
+struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_l1_switch_data = {
+       .items = mlxplat_mlxcpld_l1_switch_events_items,
+       .counter = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_events_items),
+       .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
+       .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX,
+       .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
+       .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW | MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT,
+};
+
 /* Platform led default data */
 static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
        {
@@ -2836,6 +3013,114 @@ static struct mlxreg_core_platform_data mlxplat_modular_led_data = {
                .counter = ARRAY_SIZE(mlxplat_mlxcpld_modular_led_data),
 };
 
+/* Platform led data for chassis system */
+static struct mlxreg_core_data mlxplat_mlxcpld_l1_switch_led_data[] = {
+       {
+               .label = "status:green",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+       },
+       {
+               .label = "status:orange",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
+       },
+       {
+               .label = "fan1:green",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(0),
+       },
+       {
+               .label = "fan1:orange",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(0),
+       },
+       {
+               .label = "fan2:green",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(1),
+       },
+       {
+               .label = "fan2:orange",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(1),
+       },
+       {
+               .label = "fan3:green",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(2),
+       },
+       {
+               .label = "fan3:orange",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(2),
+       },
+       {
+               .label = "fan4:green",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(3),
+       },
+       {
+               .label = "fan4:orange",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(3),
+       },
+       {
+               .label = "fan5:green",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(4),
+       },
+       {
+               .label = "fan5:orange",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(4),
+       },
+       {
+               .label = "fan6:green",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(5),
+       },
+       {
+               .label = "fan6:orange",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+               .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
+               .bit = BIT(5),
+       },
+       {
+               .label = "uid:blue",
+               .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
+               .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+       },
+};
+
+static struct mlxreg_core_platform_data mlxplat_l1_switch_led_data = {
+               .data = mlxplat_mlxcpld_l1_switch_led_data,
+               .counter = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_led_data),
+};
+
 /* Platform register access default */
 static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
        {
@@ -3368,12 +3653,48 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
                .mode = 0200,
        },
        {
+               .label = "deep_pwr_cycle",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(5),
+               .mode = 0200,
+       },
+       {
+               .label = "latch_reset",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(5),
+               .mode = 0200,
+       },
+       {
                .label = "jtag_enable",
                .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET,
                .mask = GENMASK(7, 0) & ~BIT(4),
                .mode = 0644,
        },
        {
+               .label = "dbg1",
+               .reg = MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET,
+               .bit = GENMASK(7, 0),
+               .mode = 0644,
+       },
+       {
+               .label = "dbg2",
+               .reg = MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET,
+               .bit = GENMASK(7, 0),
+               .mode = 0644,
+       },
+       {
+               .label = "dbg3",
+               .reg = MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET,
+               .bit = GENMASK(7, 0),
+               .mode = 0644,
+       },
+       {
+               .label = "dbg4",
+               .reg = MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET,
+               .bit = GENMASK(7, 0),
+               .mode = 0644,
+       },
+       {
                .label = "asic_health",
                .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
                .mask = MLXPLAT_CPLD_ASIC_MASK,
@@ -4586,11 +4907,18 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET:
        case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRCO_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_BRD_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_ASIC2_EVENT_OFFSET:
@@ -4605,6 +4933,8 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET:
@@ -4633,6 +4963,7 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET:
@@ -4683,6 +5014,10 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET:
@@ -4692,6 +5027,9 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_GWP_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_BRD_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
@@ -4713,6 +5051,9 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET:
@@ -4749,6 +5090,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET:
@@ -4825,6 +5167,10 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET:
@@ -4834,6 +5180,9 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_GWP_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_GWP_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_GWP_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_BRD_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_BRD_EVENT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_BRD_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
@@ -4855,6 +5204,9 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_EROTE_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_EROTE_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWRB_EVENT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWRB_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLC_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET:
@@ -4885,6 +5237,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_DBG_CTRL_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET:
@@ -5080,7 +5433,6 @@ static struct resource mlxplat_mlxcpld_resources[] = {
        [0] = DEFINE_RES_IRQ_NAMED(MLXPLAT_CPLD_LPC_SYSIRQ, "mlxreg-hotplug"),
 };
 
-static struct platform_device *mlxplat_dev;
 static struct mlxreg_core_hotplug_platform_data *mlxplat_i2c;
 static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
 static struct mlxreg_core_platform_data *mlxplat_led;
@@ -5090,6 +5442,14 @@ static struct mlxreg_core_platform_data
        *mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS];
 static const struct regmap_config *mlxplat_regmap_config;
 
+/* Platform default poweroff function */
+static void mlxplat_poweroff(void)
+{
+       struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
+
+       regmap_write(priv->regmap, MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, MLXPLAT_CPLD_HALT_MASK);
+}
+
 static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
 {
        int i;
@@ -5385,6 +5745,28 @@ static int __init mlxplat_dmi_ng800_matched(const struct dmi_system_id *dmi)
        return 1;
 }
 
+static int __init mlxplat_dmi_l1_switch_matched(const struct dmi_system_id *dmi)
+{
+       int i;
+
+       mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM;
+       mlxplat_mux_num = ARRAY_SIZE(mlxplat_rack_switch_mux_data);
+       mlxplat_mux_data = mlxplat_rack_switch_mux_data;
+       mlxplat_hotplug = &mlxplat_mlxcpld_l1_switch_data;
+       mlxplat_hotplug->deferred_nr =
+               mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
+       mlxplat_led = &mlxplat_l1_switch_led_data;
+       mlxplat_regs_io = &mlxplat_default_ng_regs_io_data;
+       mlxplat_fan = &mlxplat_default_fan_data;
+       for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++)
+               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;
+       pm_power_off = mlxplat_poweroff;
+
+       return 1;
+}
+
 static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
        {
                .callback = mlxplat_dmi_default_wc_matched,
@@ -5474,6 +5856,12 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
                },
        },
        {
+               .callback = mlxplat_dmi_l1_switch_matched,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "VMOD0017"),
+               },
+       },
+       {
                .callback = mlxplat_dmi_msn274x_matched,
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
@@ -5802,6 +6190,8 @@ static void __exit mlxplat_exit(void)
        struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
        int i;
 
+       if (pm_power_off)
+               pm_power_off = NULL;
        for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--)
                platform_device_unregister(priv->pdev_wd[i]);
        if (priv->pdev_fan)