sonic-buildimage/platform/mellanox/non-upstream-patches/patches/0054-platform-mellanox-Introduce-support-for-switches-equ.patch

313 lines
11 KiB
Diff
Raw Normal View History

From 3e4ff8f2195a3dc7b04bb5a1b9fd6b655f78a75e Mon Sep 17 00:00:00 2001
From: Vadim Pasternak <vadimp@nvidia.com>
Date: Mon, 24 Jul 2023 11:10:50 +0000
Subject: [PATH backport v6.1 54/54] platform: mellanox: Introduce support for
switches equipped with new FPGA device
Add support for Nvidia MQM97xx and MSN47xx family switches equipped with
new FPGA device.
These switches are based on previous generation of MQM97xx and MSN47xx
switches, but COMe module uses new FPGA device.
Platform configuration for new switches is based on the new VMOD0016
class. Configuration is extended to support new register map with
callbacks supporting indirect addressing for PCIe-to-LPC bridge.
This bridge provides interface between FPGA at COMe board (directly
connected to CPU PCIe root complex) to CPLDs on switch board (which
cannot be connected directly to PCIe root complex).
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Reviewed-by: Michael Shych <michaelsh@nvidia.com>
---
drivers/platform/x86/mlx-platform.c | 196 ++++++++++++++++++++++++++++
1 file changed, 196 insertions(+)
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 9021597b5446..46958810e972 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -183,6 +183,9 @@
#define MLXPLAT_CPLD_LPC_REG_CONFIG1_OFFSET 0xfb
#define MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET 0xfc
#define MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET 0xfd
+#define MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET 0x100
+#define MLXPLAT_CPLD_LPC_REG_EXT_MID_OFFSET 0x195
+#define MLXPLAT_CPLD_LPC_REG_EXT_MAX_OFFSET 0x1ff
#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
#define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL
@@ -277,6 +280,7 @@
/* Maximum number of possible physical buses equipped on system */
#define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16
#define MLXPLAT_CPLD_MAX_PHYS_EXT_ADAPTER_NUM 24
+#define MLXPLAT_CPLD_DEFAULT_MUX_HOTPLUG_VECTOR 0
/* Number of channels in group */
#define MLXPLAT_CPLD_GRP_CHNL_NUM 8
@@ -338,6 +342,21 @@
#define PCI_DEVICE_ID_LATTICE_I2C_BRIDGE 0x9c2f
#define PCI_DEVICE_ID_LATTICE_JTAG_BRIDGE 0x9c30
#define PCI_DEVICE_ID_LATTICE_LPC_BRIDGE 0x9c32
+#define MLXPLAT_FPGA_PCI_BAR0_SIZE 0x4000
+#define MLXPLAT_FPGA_PCI_BASE_OFFSET 0x00000000
+#define MLXPLAT_FPGA_PCI_MSB_ADDR 0x25
+#define MLXPLAT_FPGA_PCI_MSB_EXT_ADDR 0x20
+#define MLXPLAT_FPGA_PCI_LSB_ADDR_OFFSET MLXPLAT_FPGA_PCI_BASE_OFFSET
+#define MLXPLAT_FPGA_PCI_MSB_ADDR_OFFSET (MLXPLAT_FPGA_PCI_BASE_OFFSET + 0x01)
+#define MLXPLAT_FPGA_PCI_DATA_OUT_OFFSET (MLXPLAT_FPGA_PCI_BASE_OFFSET + 0x02)
+#define MLXPLAT_FPGA_PCI_DATA_IN_OFFSET (MLXPLAT_FPGA_PCI_BASE_OFFSET + 0x03)
+#define MLXPLAT_FPGA_PCI_CTRL_OFFSET (MLXPLAT_FPGA_PCI_BASE_OFFSET + 0x04)
+#define MLXPLAT_FPGA_PCI_STAT_OFFSET (MLXPLAT_FPGA_PCI_BASE_OFFSET + 0x05)
+
+#define MLXPLAT_FPGA_PCI_CTRL_READ BIT(0)
+#define MLXPLAT_FPGA_PCI_CTRL_WRITE BIT(1)
+#define MLXPLAT_FPGA_PCI_COMPLETED GENMASK(1, 0)
+#define MLXPLAT_FPGA_PCI_TO 50 /* usec */
/* mlxplat_priv - platform private data
* @pdev_i2c - i2c controller platform device
@@ -453,6 +472,28 @@ static struct i2c_mux_reg_platform_data mlxplat_default_mux_data[] = {
};
+/* Default channels vector for regmap mux. */
+static int mlxplat_default_regmap_mux_chan[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+/* Platform regmap mux data */
+static struct i2c_mux_regmap_platform_data mlxplat_default_regmap_mux_data[] = {
+ {
+ .parent = 1,
+ .chan_ids = mlxplat_default_regmap_mux_chan,
+ .num_adaps = ARRAY_SIZE(mlxplat_default_regmap_mux_chan),
+ .sel_reg_addr = MLXPLAT_CPLD_LPC_REG_I2C_CH1_OFFSET,
+ .reg_size = 1,
+ },
+ {
+ .parent = 1,
+ .chan_ids = mlxplat_default_regmap_mux_chan,
+ .num_adaps = ARRAY_SIZE(mlxplat_default_regmap_mux_chan),
+ .sel_reg_addr = MLXPLAT_CPLD_LPC_REG_I2C_CH2_OFFSET,
+ .reg_size = 1,
+ },
+
+};
+
/* Platform mux configuration variables */
static int mlxplat_max_adap_num;
static int mlxplat_mux_num;
@@ -3540,6 +3581,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
.mask = GENMASK(7, 0) & ~BIT(2),
.mode = 0200,
},
+ {
+ .label = "kexec_activated",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(1),
+ .mode = 0644,
+ },
{
.label = "erot1_reset",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET,
@@ -5065,6 +5112,7 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PWM4_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET ... MLXPLAT_CPLD_LPC_REG_EXT_MAX_OFFSET:
return true;
}
return false;
@@ -5230,6 +5278,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET ... MLXPLAT_CPLD_LPC_REG_EXT_MAX_OFFSET:
return true;
}
return false;
@@ -5387,6 +5436,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET ... MLXPLAT_CPLD_LPC_REG_EXT_MAX_OFFSET:
return true;
}
return false;
@@ -5417,6 +5467,14 @@ 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_bf3[] = {
+ { MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, 0xc1 },
+ { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 },
+ { 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_rack_switch[] = {
{ MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT },
{ MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET, 0x00 },
@@ -5545,6 +5603,114 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config_eth_modular = {
.reg_write = mlxplat_mlxcpld_reg_write,
};
+/* Wait completion routine for indirect access for register map */
+static int mlxplat_fpga_completion_wait(struct mlxplat_mlxcpld_regmap_context *ctx)
+{
+ unsigned long end;
+ u8 status;
+
+ end = jiffies + msecs_to_jiffies(MLXPLAT_FPGA_PCI_TO);
+ do {
+ status = ioread8(ctx->base + MLXPLAT_FPGA_PCI_STAT_OFFSET);
+ if (!(status & MLXPLAT_FPGA_PCI_COMPLETED))
+ return 0;
+ cond_resched();
+ } while (time_before(jiffies, end));
+
+ return -EIO;
+}
+
+/* Read callback for indirect register map access */
+static int mlxplat_fpga_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct mlxplat_mlxcpld_regmap_context *ctx = context;
+ unsigned int msb_off = MLXPLAT_FPGA_PCI_MSB_ADDR;
+ int err;
+
+ if (reg >= MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET) {
+ if (reg <= MLXPLAT_CPLD_LPC_REG_EXT_MID_OFFSET) {
+ /* Access to 2-nd FPGA bank */
+ *val = ioread8(i2c_bridge_addr + reg -
+ MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET);
+ return 0;
+ }
+ /* Access to 3-rd FPGA bank */
+ reg -= MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET;
+ msb_off = MLXPLAT_FPGA_PCI_MSB_EXT_ADDR;
+ }
+
+ /* Verify there is no pending transactions */
+ err = mlxplat_fpga_completion_wait(ctx);
+ if (err)
+ return err;
+
+ /* Set address in register space */
+ iowrite8(msb_off, ctx->base + MLXPLAT_FPGA_PCI_MSB_ADDR_OFFSET);
+ iowrite8(reg, ctx->base + MLXPLAT_FPGA_PCI_LSB_ADDR_OFFSET);
+ /* Activate read operation */
+ iowrite8(MLXPLAT_FPGA_PCI_CTRL_READ, ctx->base + MLXPLAT_FPGA_PCI_CTRL_OFFSET);
+ /* Verify transaction completion */
+ err = mlxplat_fpga_completion_wait(ctx);
+ if (err)
+ return err;
+
+ /* Read data */
+ *val = ioread8(ctx->base + MLXPLAT_FPGA_PCI_DATA_IN_OFFSET);
+
+ return 0;
+}
+
+/* Write callback for indirect register map access */
+static int mlxplat_fpga_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct mlxplat_mlxcpld_regmap_context *ctx = context;
+ unsigned int msb_off = MLXPLAT_FPGA_PCI_MSB_ADDR;
+ int err;
+
+ if (reg >= MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET) {
+ if (reg <= MLXPLAT_CPLD_LPC_REG_EXT_MID_OFFSET) {
+ /* Access to 2-nd FPGA bank */
+ iowrite8(val, i2c_bridge_addr + reg - MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET);
+ /* Flush modification */
+ wmb();
+ return 0;
+ }
+
+ /* Access to 3-rd FPGA bank */
+ reg -= MLXPLAT_CPLD_LPC_REG_EXT_MIN_OFFSET;
+ msb_off = MLXPLAT_FPGA_PCI_MSB_EXT_ADDR;
+ }
+
+ /* Verify there is no pending transactions */
+ err = mlxplat_fpga_completion_wait(ctx);
+ if (err)
+ return err;
+
+ /* Set address in register space */
+ iowrite8(msb_off, ctx->base + MLXPLAT_FPGA_PCI_MSB_ADDR_OFFSET);
+ iowrite8(reg, ctx->base + MLXPLAT_FPGA_PCI_LSB_ADDR_OFFSET);
+ /* Set data to be written */
+ iowrite8(val, ctx->base + MLXPLAT_FPGA_PCI_DATA_OUT_OFFSET);
+ /* Activate write operation */
+ iowrite8(MLXPLAT_FPGA_PCI_CTRL_WRITE, ctx->base + MLXPLAT_FPGA_PCI_CTRL_OFFSET);
+
+ return mlxplat_fpga_completion_wait(ctx);
+}
+
+static const struct regmap_config mlxplat_fpga_regmap_config_bf3_comex_default = {
+ .reg_bits = 9,
+ .val_bits = 8,
+ .max_register = 511,
+ .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_bf3,
+ .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_bf3),
+ .reg_read = mlxplat_fpga_reg_read,
+ .reg_write = mlxplat_fpga_reg_write,
+};
+
static struct resource mlxplat_mlxcpld_resources[] = {
[0] = DEFINE_RES_IRQ_NAMED(MLXPLAT_CPLD_LPC_SYSIRQ, "mlxreg-hotplug"),
};
@@ -5927,6 +6093,30 @@ static int __init mlxplat_dmi_l1_switch_matched(const struct dmi_system_id *dmi)
return mlxplat_register_platform_device();
}
+static int __init mlxplat_dmi_bf3_comex_default_matched(const struct dmi_system_id *dmi)
+{
+ int i;
+
+ mlxplat_max_adap_num = MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM;
+ mlxplat_mux_hotplug_num = MLXPLAT_CPLD_DEFAULT_MUX_HOTPLUG_VECTOR;
+ mlxplat_mux_num = ARRAY_SIZE(mlxplat_default_regmap_mux_data);
+ mlxplat_mux_regmap_data = mlxplat_default_regmap_mux_data;
+ mlxplat_hotplug = &mlxplat_mlxcpld_ext_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_fpga_regmap_config_bf3_comex_default;
+ mlxplat_reboot_nb = &mlxplat_reboot_default_nb;
+ pm_power_off = mlxplat_poweroff;
+
+ return 1;
+}
+
static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
{
.callback = mlxplat_dmi_default_wc_matched,
@@ -6015,6 +6205,12 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0015"),
},
},
+ {
+ .callback = mlxplat_dmi_bf3_comex_default_matched,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0016"),
+ },
+ },
{
.callback = mlxplat_dmi_l1_switch_matched,
.matches = {
--
2.20.1