Skip to content

Commit

Permalink
platform: mellanox: Introduce support for rack manager switch
Browse files Browse the repository at this point in the history
The rack switch is designed to provide high bandwidth, low latency
connectivity using optical fiber as the primary interconnect.

System supports 32 OSFP ports, non-blocking switching capacity of
25.6Tbps.
System equipped with:
- 2 replaceable power supplies (AC) with 1+1 redundancy model.
- 7 replaceable fan drawers with 6+1 redundancy model.
- 2 External Root of Trust or EROT (Glacier) devices for securing
  ASICs firmware.

Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Reviewed-by: Michael Shych <michaelsh@nvidia.com>
Link: https://lore.kernel.org/r/20230208063331.15560-2-vadimp@nvidia.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  • Loading branch information
vadimp-nvidia authored and jwrdegoede committed Feb 10, 2023
1 parent 0b8ecad commit f8dacbf
Showing 1 changed file with 261 additions and 0 deletions.
261 changes: 261 additions & 0 deletions drivers/platform/x86/mlx-platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@
#define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88
#define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89
#define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a
#define MLXPLAT_CPLD_LPC_REG_EROT_OFFSET 0x91
#define MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET 0x92
#define MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET 0x93
#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_LC_VR_OFFSET 0x9a
#define MLXPLAT_CPLD_LPC_REG_LC_VR_EVENT_OFFSET 0x9b
#define MLXPLAT_CPLD_LPC_REG_LC_VR_MASK_OFFSET 0x9c
Expand All @@ -109,6 +115,8 @@
#define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa
#define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab
#define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON 0xb2
#define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2
#define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3
#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7
#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET 0xc8
#define MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET 0xc9
Expand Down Expand Up @@ -214,6 +222,7 @@
#define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 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_I2C_CAP_BIT 0x04
#define MLXPLAT_CPLD_I2C_CAP_MASK GENMASK(5, MLXPLAT_CPLD_I2C_CAP_BIT)

Expand Down Expand Up @@ -243,6 +252,7 @@
#define MLXPLAT_CPLD_CH2_ETH_MODULAR 3
#define MLXPLAT_CPLD_CH3_ETH_MODULAR 43
#define MLXPLAT_CPLD_CH4_ETH_MODULAR 51
#define MLXPLAT_CPLD_CH2_RACK_SWITCH 18

/* Number of LPC attached MUX platform devices */
#define MLXPLAT_CPLD_LPC_MUX_DEVS 4
Expand Down Expand Up @@ -280,6 +290,9 @@
/* Minimum power required for turning on Ethernet modular system (WATT) */
#define MLXPLAT_CPLD_ETH_MODULAR_PWR_MIN 50

/* Default value for PWM control register for rack switch system */
#define MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT 0xf4

/* mlxplat_priv - platform private data
* @pdev_i2c - i2c controller platform device
* @pdev_mux - array of mux platform devices
Expand Down Expand Up @@ -460,6 +473,36 @@ static struct i2c_mux_reg_platform_data mlxplat_modular_mux_data[] = {
},
};

/* Platform channels for rack swicth system family */
static const int mlxplat_rack_switch_channels[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
};

/* Platform rack switch mux data */
static struct i2c_mux_reg_platform_data mlxplat_rack_switch_mux_data[] = {
{
.parent = 1,
.base_nr = MLXPLAT_CPLD_CH1,
.write_only = 1,
.reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1,
.reg_size = 1,
.idle_in_use = 1,
.values = mlxplat_rack_switch_channels,
.n_values = ARRAY_SIZE(mlxplat_rack_switch_channels),
},
{
.parent = 1,
.base_nr = MLXPLAT_CPLD_CH2_RACK_SWITCH,
.write_only = 1,
.reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2,
.reg_size = 1,
.idle_in_use = 1,
.values = mlxplat_msn21xx_channels,
.n_values = ARRAY_SIZE(mlxplat_msn21xx_channels),
},

};

/* Platform hotplug devices */
static struct i2c_board_info mlxplat_mlxcpld_pwr[] = {
{
Expand Down Expand Up @@ -2064,6 +2107,97 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_nvlink_blade_data = {
.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
};

/* Platform hotplug for switch systems family data */
static struct mlxreg_core_data mlxplat_mlxcpld_erot_ap_items_data[] = {
{
.label = "erot1_ap",
.reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET,
.mask = BIT(0),
.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
},
{
.label = "erot2_ap",
.reg = MLXPLAT_CPLD_LPC_REG_EROT_OFFSET,
.mask = BIT(1),
.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
},
};

static struct mlxreg_core_data mlxplat_mlxcpld_erot_error_items_data[] = {
{
.label = "erot1_error",
.reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET,
.mask = BIT(0),
.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
},
{
.label = "erot2_error",
.reg = MLXPLAT_CPLD_LPC_REG_EROTE_OFFSET,
.mask = BIT(1),
.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
},
};

static struct mlxreg_core_item mlxplat_mlxcpld_rack_switch_items[] = {
{
.data = mlxplat_mlxcpld_ext_psu_items_data,
.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
.mask = MLXPLAT_CPLD_PSU_EXT_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET,
.count = ARRAY_SIZE(mlxplat_mlxcpld_ext_psu_items_data),
.inversed = 1,
.health = false,
},
{
.data = mlxplat_mlxcpld_ext_pwr_items_data,
.aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
.mask = MLXPLAT_CPLD_PWR_EXT_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET,
.count = ARRAY_SIZE(mlxplat_mlxcpld_ext_pwr_items_data),
.inversed = 0,
.health = false,
},
{
.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,
},
};

static
struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_rack_switch_data = {
.items = mlxplat_mlxcpld_rack_switch_items,
.counter = ARRAY_SIZE(mlxplat_mlxcpld_rack_switch_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,
};

/* Platform led default data */
static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
{
Expand Down Expand Up @@ -2947,6 +3081,44 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
.mask = GENMASK(7, 0) & ~BIT(2),
.mode = 0200,
},
{
.label = "erot1_reset",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(6),
.mode = 0644,
},
{
.label = "erot2_reset",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(7),
.mode = 0644,
},
{
.label = "erot1_recovery",
.reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(6),
.mode = 0644,
},
{
.label = "erot2_recovery",
.reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(7),
.mode = 0644,
},
{
.label = "erot1_wp",
.reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(4),
.mode = 0644,
.secured = 1,
},
{
.label = "erot2_wp",
.reg = MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(5),
.mode = 0644,
.secured = 1,
},
{
.label = "reset_long_pb",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
Expand Down Expand Up @@ -3142,6 +3314,25 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
.mask = GENMASK(7, 0) & ~BIT(4),
.mode = 0644,
},
{
.label = "erot1_ap_reset",
.reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(0),
.mode = 0444,
},
{
.label = "erot2_ap_reset",
.reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET,
.mask = GENMASK(7, 0) & ~BIT(1),
.mode = 0444,
},
{
.label = "spi_chnl_select",
.reg = MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT,
.mask = GENMASK(7, 0),
.bit = 1,
.mode = 0644,
},
{
.label = "config1",
.reg = MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET,
Expand Down Expand Up @@ -4257,6 +4448,10 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET:
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_AGGRLC_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET:
Expand All @@ -4274,6 +4469,7 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON:
case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT:
case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET:
Expand Down Expand Up @@ -4358,6 +4554,12 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_EROT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET:
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_AGGRLC_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET:
Expand All @@ -4382,6 +4584,8 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON:
case MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET:
case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT:
case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET:
Expand Down Expand Up @@ -4492,6 +4696,12 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_EROT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_EROT_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_EROT_MASK_OFFSET:
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_AGGRLC_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLC_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET:
Expand All @@ -4516,6 +4726,8 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LC_PWR_ON:
case MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET:
case MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT:
case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
Expand Down Expand Up @@ -4583,6 +4795,13 @@ static const struct reg_default mlxplat_mlxcpld_regmap_ng400[] = {
{ MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, 0x00 },
};

static const struct reg_default mlxplat_mlxcpld_regmap_rack_switch[] = {
{ MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT },
{ MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET, 0x00 },
{ MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET, 0x00 },
{ MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET, 0x00 },
};

static const struct reg_default mlxplat_mlxcpld_regmap_eth_modular[] = {
{ MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, 0x61 },
{ MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 },
Expand Down Expand Up @@ -4676,6 +4895,20 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config_ng400 = {
.reg_write = mlxplat_mlxcpld_reg_write,
};

static const struct regmap_config mlxplat_mlxcpld_regmap_config_rack_switch = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 255,
.cache_type = REGCACHE_FLAT,
.writeable_reg = mlxplat_mlxcpld_writeable_reg,
.readable_reg = mlxplat_mlxcpld_readable_reg,
.volatile_reg = mlxplat_mlxcpld_volatile_reg,
.reg_defaults = mlxplat_mlxcpld_regmap_rack_switch,
.num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_rack_switch),
.reg_read = mlxplat_mlxcpld_reg_read,
.reg_write = mlxplat_mlxcpld_reg_write,
};

static const struct regmap_config mlxplat_mlxcpld_regmap_config_eth_modular = {
.reg_bits = 8,
.val_bits = 8,
Expand Down Expand Up @@ -4957,6 +5190,27 @@ static int __init mlxplat_dmi_nvlink_blade_matched(const struct dmi_system_id *d
return 1;
}

static int __init mlxplat_dmi_rack_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_rack_switch_data;
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_default_ng_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;

return 1;
}

static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
{
.callback = mlxplat_dmi_default_wc_matched,
Expand Down Expand Up @@ -5014,6 +5268,13 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0009"),
},
},
{
.callback = mlxplat_dmi_rack_switch_matched,
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0010"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "HI142"),
},
},
{
.callback = mlxplat_dmi_ng400_matched,
.matches = {
Expand Down

0 comments on commit f8dacbf

Please sign in to comment.