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@xxxxxxxxxx> Reviewed-by: Michael Shych <michaelsh@xxxxxxxxxx> --- drivers/platform/x86/mlx-platform.c | 261 ++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 2fac05a17a5c..3e4adeb20a7e 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -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 @@ -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 @@ -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) @@ -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 @@ -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 @@ -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[] = { { @@ -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[] = { { @@ -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, @@ -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, @@ -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: @@ -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: @@ -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: @@ -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: @@ -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: @@ -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: @@ -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 }, @@ -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, @@ -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, @@ -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 = { -- 2.20.1