platform: mellanox: nvsw-sn2200: Add support for new system flavour
authorVadim Pasternak <vadimp@nvidia.com>
Sun, 4 May 2025 16:55:06 +0000 (19:55 +0300)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Thu, 8 May 2025 13:03:48 +0000 (16:03 +0300)
Add support for SN2201 system flavour, which is fitting OCP rack
form-factor and feeded from external power source through the rack
standard busbar interface.

Validate system type through DMI decode.
For new system flavour:
- Skip internal power supply configuration.
- Attach power hotswap device.

Reviewed-by: Michael Shych <michaelsh@nvidia.com>
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Link: https://lore.kernel.org/r/20250504165507.9003-2-vadimp@nvidia.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/platform/mellanox/nvsw-sn2201.c

index d0e5a18..8c31189 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/dmi.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
        | NVSW_SN2201_CPLD_AGGR_PSU_MASK_DEF \
        | NVSW_SN2201_CPLD_AGGR_PWR_MASK_DEF \
        | NVSW_SN2201_CPLD_AGGR_FAN_MASK_DEF)
+#define NVSW_SN2201_CPLD_AGGR_BUSBAR_MASK_DEF \
+       (NVSW_SN2201_CPLD_AGGR_ASIC_MASK_DEF \
+       | NVSW_SN2201_CPLD_AGGR_FAN_MASK_DEF)
 
 #define NVSW_SN2201_CPLD_ASIC_MASK             GENMASK(3, 1)
 #define NVSW_SN2201_CPLD_PSU_MASK              GENMASK(1, 0)
  * @cpld_devs: I2C devices for cpld;
  * @cpld_devs_num: number of I2C devices for cpld;
  * @main_mux_deferred_nr: I2C adapter number must be exist prior creating devices execution;
+ * @ext_pwr_source: true if system powered by external power supply; false - by internal;
  */
 struct nvsw_sn2201 {
        struct device *dev;
@@ -152,6 +157,7 @@ struct nvsw_sn2201 {
        struct mlxreg_hotplug_device *cpld_devs;
        int cpld_devs_num;
        int main_mux_deferred_nr;
+       bool ext_pwr_source;
 };
 
 static bool nvsw_sn2201_writeable_reg(struct device *dev, unsigned int reg)
@@ -522,6 +528,35 @@ struct mlxreg_core_hotplug_platform_data nvsw_sn2201_hotplug = {
        .mask = NVSW_SN2201_CPLD_AGGR_MASK_DEF,
 };
 
+static struct mlxreg_core_item nvsw_sn2201_busbar_items[] = {
+       {
+               .data = nvsw_sn2201_fan_items_data,
+               .aggr_mask = NVSW_SN2201_CPLD_AGGR_FAN_MASK_DEF,
+               .reg = NVSW_SN2201_FAN_PRSNT_STATUS_OFFSET,
+               .mask = NVSW_SN2201_CPLD_FAN_MASK,
+               .count = ARRAY_SIZE(nvsw_sn2201_fan_items_data),
+               .inversed = 1,
+               .health = false,
+       },
+       {
+               .data = nvsw_sn2201_sys_items_data,
+               .aggr_mask = NVSW_SN2201_CPLD_AGGR_ASIC_MASK_DEF,
+               .reg = NVSW_SN2201_ASIC_STATUS_OFFSET,
+               .mask = NVSW_SN2201_CPLD_ASIC_MASK,
+               .count = ARRAY_SIZE(nvsw_sn2201_sys_items_data),
+               .inversed = 1,
+               .health = false,
+       },
+};
+
+static
+struct mlxreg_core_hotplug_platform_data nvsw_sn2201_busbar_hotplug = {
+       .items = nvsw_sn2201_items,
+       .count = ARRAY_SIZE(nvsw_sn2201_busbar_items),
+       .cell = NVSW_SN2201_SYS_INT_STATUS_OFFSET,
+       .mask = NVSW_SN2201_CPLD_AGGR_BUSBAR_MASK_DEF,
+};
+
 /* SN2201 static devices. */
 static struct i2c_board_info nvsw_sn2201_static_devices[] = {
        {
@@ -557,6 +592,9 @@ static struct i2c_board_info nvsw_sn2201_static_devices[] = {
        {
                I2C_BOARD_INFO("pmbus", 0x40),
        },
+       {
+               I2C_BOARD_INFO("lm5066i", 0x15),
+       },
 };
 
 /* SN2201 default static board info. */
@@ -607,6 +645,58 @@ static struct mlxreg_hotplug_device nvsw_sn2201_static_brdinfo[] = {
        },
 };
 
+/* SN2201 default busbar static board info. */
+static struct mlxreg_hotplug_device nvsw_sn2201_busbar_static_brdinfo[] = {
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[0],
+               .nr = NVSW_SN2201_MAIN_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[1],
+               .nr = NVSW_SN2201_MAIN_MUX_CH0_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[2],
+               .nr = NVSW_SN2201_MAIN_MUX_CH0_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[3],
+               .nr = NVSW_SN2201_MAIN_MUX_CH0_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[4],
+               .nr = NVSW_SN2201_MAIN_MUX_CH3_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[5],
+               .nr = NVSW_SN2201_MAIN_MUX_CH5_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[6],
+               .nr = NVSW_SN2201_MAIN_MUX_CH5_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[7],
+               .nr = NVSW_SN2201_MAIN_MUX_CH5_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[8],
+               .nr = NVSW_SN2201_MAIN_MUX_CH6_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[9],
+               .nr = NVSW_SN2201_MAIN_MUX_CH6_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[10],
+               .nr = NVSW_SN2201_MAIN_MUX_CH7_NR,
+       },
+       {
+               .brdinfo = &nvsw_sn2201_static_devices[11],
+               .nr = NVSW_SN2201_MAIN_MUX_CH1_NR,
+       },
+};
+
 /* LED default data. */
 static struct mlxreg_core_data nvsw_sn2201_led_data[] = {
        {
@@ -981,7 +1071,10 @@ static int nvsw_sn2201_config_init(struct nvsw_sn2201 *nvsw_sn2201, void *regmap
        nvsw_sn2201->io_data = &nvsw_sn2201_regs_io;
        nvsw_sn2201->led_data = &nvsw_sn2201_led;
        nvsw_sn2201->wd_data = &nvsw_sn2201_wd;
-       nvsw_sn2201->hotplug_data = &nvsw_sn2201_hotplug;
+       if (nvsw_sn2201->ext_pwr_source)
+               nvsw_sn2201->hotplug_data = &nvsw_sn2201_busbar_hotplug;
+       else
+               nvsw_sn2201->hotplug_data = &nvsw_sn2201_hotplug;
 
        /* Register IO access driver. */
        if (nvsw_sn2201->io_data) {
@@ -1198,12 +1291,18 @@ static int nvsw_sn2201_config_pre_init(struct nvsw_sn2201 *nvsw_sn2201)
 static int nvsw_sn2201_probe(struct platform_device *pdev)
 {
        struct nvsw_sn2201 *nvsw_sn2201;
+       const char *sku;
        int ret;
 
        nvsw_sn2201 = devm_kzalloc(&pdev->dev, sizeof(*nvsw_sn2201), GFP_KERNEL);
        if (!nvsw_sn2201)
                return -ENOMEM;
 
+       /* Validate system powering type - only HI168 SKU supports external power. */
+       sku = dmi_get_system_info(DMI_PRODUCT_SKU);
+       if (sku && !strcmp(sku, "HI168"))
+               nvsw_sn2201->ext_pwr_source = true;
+
        nvsw_sn2201->dev = &pdev->dev;
        platform_set_drvdata(pdev, nvsw_sn2201);
        ret = platform_device_add_resources(pdev, nvsw_sn2201_lpc_io_resources,
@@ -1214,8 +1313,13 @@ static int nvsw_sn2201_probe(struct platform_device *pdev)
        nvsw_sn2201->main_mux_deferred_nr = NVSW_SN2201_MAIN_MUX_DEFER_NR;
        nvsw_sn2201->main_mux_devs = nvsw_sn2201_main_mux_brdinfo;
        nvsw_sn2201->cpld_devs = nvsw_sn2201_cpld_brdinfo;
-       nvsw_sn2201->sn2201_devs = nvsw_sn2201_static_brdinfo;
-       nvsw_sn2201->sn2201_devs_num = ARRAY_SIZE(nvsw_sn2201_static_brdinfo);
+       if (nvsw_sn2201->ext_pwr_source) {
+               nvsw_sn2201->sn2201_devs = nvsw_sn2201_busbar_static_brdinfo;
+               nvsw_sn2201->sn2201_devs_num = ARRAY_SIZE(nvsw_sn2201_busbar_static_brdinfo);
+       } else {
+               nvsw_sn2201->sn2201_devs = nvsw_sn2201_static_brdinfo;
+               nvsw_sn2201->sn2201_devs_num = ARRAY_SIZE(nvsw_sn2201_static_brdinfo);
+       }
 
        return nvsw_sn2201_config_pre_init(nvsw_sn2201);
 }