diff --git a/patch/0036-mlxsw-i2c-Fix-chunk-size-setting-in-output-mailbox-b.patch b/patch/0036-mlxsw-i2c-Fix-chunk-size-setting-in-output-mailbox-b.patch deleted file mode 100644 index d6d038b2b..000000000 --- a/patch/0036-mlxsw-i2c-Fix-chunk-size-setting-in-output-mailbox-b.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 4d32fdf801c1938afb7994b6e69543fa59b018a9 Mon Sep 17 00:00:00 2001 -From: Vadim Pasternak -Date: Mon, 14 Aug 2023 10:44:40 +0000 -Subject: [PATH backport v6.1 36/41] mlxsw: i2c: Fix chunk size setting in - output mailbox buffer - -Link: https://github.com/jpirko/linux_mlxsw/commit/2f7618bfe14f09690bd374417e790bbeaf6fb6bf - -The driver reads commands output from the output mailbox. If the size -of the output mailbox is not a multiple of the transaction / -block size, then the driver will not issue enough read transactions -to read the entire output, which can result in driver initialization -errors. - -Fix by determining the number of transactions using DIV_ROUND_UP(). - -Fixes: 3029a693beda ("mlxsw: i2c: Allow flexible setting of I2C transactions size") -Signed-off-by: Vadim Pasternak -Reviewed-by: Ido Schimmel ---- - drivers/net/ethernet/mellanox/mlxsw/i2c.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c -index f5f5f8dc3d19..26e05f129e35 100644 ---- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c -+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c -@@ -444,7 +444,7 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size, - } else { - /* No input mailbox is case of initialization query command. */ - reg_size = MLXSW_I2C_MAX_DATA_SIZE; -- num = reg_size / mlxsw_i2c->block_size; -+ num = DIV_ROUND_UP(reg_size, mlxsw_i2c->block_size); - - if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) { - dev_err(&client->dev, "Could not acquire lock"); --- -2.20.1 - diff --git a/patch/0037-mlxsw-i2c-Limit-single-transaction-buffer-size.patch b/patch/0037-mlxsw-i2c-Limit-single-transaction-buffer-size.patch deleted file mode 100644 index 3fa61239f..000000000 --- a/patch/0037-mlxsw-i2c-Limit-single-transaction-buffer-size.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 1a589f97c28418f9d50b8efa25e6e437dfc700e3 Mon Sep 17 00:00:00 2001 -From: Vadim Pasternak -Date: Mon, 14 Aug 2023 10:44:41 +0000 -Subject: [PATH backport v6.1 37/41] mlxsw: i2c: Limit single transaction - buffer size - -Link: https://github.com/jpirko/linux_mlxsw/commit/162fc0c49b08baf613b1fba211f4d9852845b5b8 - -Maximum size of buffer is obtained from underlying I2C adapter and in -case adapter allows I2C transaction buffer size greater than 100 bytes, -transaction will fail due to firmware limitation. - -As a result driver will fail initialization. - -Limit the maximum size of transaction buffer by 100 bytes to fit to -firmware. - -Remove unnecessary calculation: -max_t(u16, MLXSW_I2C_BLK_DEF, quirk_size). -This condition can not happened. - -Fixes: 3029a693beda ("mlxsw: i2c: Allow flexible setting of I2C transactions size") -Signed-off-by: Vadim Pasternak -Reviewed-by: Petr Machata ---- - drivers/net/ethernet/mellanox/mlxsw/i2c.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c -index 26e05f129e35..d9a71ad9adae 100644 ---- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c -+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c -@@ -48,6 +48,7 @@ - #define MLXSW_I2C_MBOX_SIZE_BITS 12 - #define MLXSW_I2C_ADDR_BUF_SIZE 4 - #define MLXSW_I2C_BLK_DEF 32 -+#define MLXSW_I2C_BLK_MAX 100 - #define MLXSW_I2C_RETRY 5 - #define MLXSW_I2C_TIMEOUT_MSECS 5000 - #define MLXSW_I2C_MAX_DATA_SIZE 256 -@@ -653,9 +654,10 @@ static int mlxsw_i2c_probe(struct i2c_client *client, - return -EOPNOTSUPP; - } - -- mlxsw_i2c->block_size = max_t(u16, MLXSW_I2C_BLK_DEF, -- min_t(u16, quirks->max_read_len, -- quirks->max_write_len)); -+ mlxsw_i2c->block_size = min_t(u16, min_t(u16, quirks->max_read_len, -+ quirks->max_write_len), -+ MLXSW_I2C_BLK_MAX); -+ - } else { - mlxsw_i2c->block_size = MLXSW_I2C_BLK_DEF; - } --- -2.20.1 - diff --git a/patch/0038-mlxsw-core_hwmon-Adjust-module-label-names-based-on-.patch b/patch/0038-mlxsw-core_hwmon-Adjust-module-label-names-based-on-.patch deleted file mode 100644 index 85611880b..000000000 --- a/patch/0038-mlxsw-core_hwmon-Adjust-module-label-names-based-on-.patch +++ /dev/null @@ -1,57 +0,0 @@ -From b5fb1b551d27dc4f66856efececab648058c6097 Mon Sep 17 00:00:00 2001 -From: Vadim Pasternak -Date: Wed, 16 Aug 2023 07:02:38 +0000 -Subject: [PATH backport v6.1 38/41] mlxsw: core_hwmon: Adjust module label - names based on MTCAP sensor counter -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Link: https://github.com/jpirko/linux_mlxsw/commit/0f7d9d1f513b4585a99c49683e637274b3389c4c - -Transceiver module temperature sensors are indexed after ASIC and -platform sensors. The current label printing method does not take this -into account and simply prints the index of the transceiver module -sensor. - -On new systems that have platform sensors this results in incorrect -(shifted) transceiver module labels being printed: - -$ sensors -[...] -front panel 002: +37.0°C (crit = +70.0°C, emerg = +75.0°C) -front panel 003: +47.0°C (crit = +70.0°C, emerg = +75.0°C) -[...] - -Fix by taking the sensor count into account. After the fix: - -$ sensors -[...] -front panel 001: +37.0°C (crit = +70.0°C, emerg = +75.0°C) -front panel 002: +47.0°C (crit = +70.0°C, emerg = +75.0°C) -[...] - -Fixes: a53779de6a0e ("mlxsw: core: Add QSFP module temperature label attribute to hwmon") -Signed-off-by: Vadim Pasternak -Reviewed-by: Ido Schimmel ---- - drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -index 70735068cf29..0fd290d776ff 100644 ---- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c -@@ -405,7 +405,8 @@ mlxsw_hwmon_module_temp_label_show(struct device *dev, - container_of(attr, struct mlxsw_hwmon_attr, dev_attr); - - return sprintf(buf, "front panel %03u\n", -- mlxsw_hwmon_attr->type_index); -+ mlxsw_hwmon_attr->type_index + 1 - -+ mlxsw_hwmon_attr->mlxsw_hwmon_dev->sensor_count); - } - - static ssize_t --- -2.20.1 - diff --git a/patch/0048-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2891-c.patch b/patch/0048-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2891-c.patch index d94e43e2f..928522af5 100644 --- a/patch/0048-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2891-c.patch +++ b/patch/0048-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2891-c.patch @@ -24,14 +24,14 @@ Signed-off-by: Vadim Pasternak Documentation/hwmon/mp2891.rst | 128 ++++++++++ drivers/hwmon/pmbus/Kconfig | 9 + drivers/hwmon/pmbus/Makefile | 1 + - drivers/hwmon/pmbus/mp2891.c | 424 +++++++++++++++++++++++++++++++++ - 4 files changed, 562 insertions(+) + drivers/hwmon/pmbus/mp2891.c | 427 +++++++++++++++++++++++++++++++++ + 4 files changed, 565 insertions(+) create mode 100644 Documentation/hwmon/mp2891.rst create mode 100644 drivers/hwmon/pmbus/mp2891.c diff --git a/Documentation/hwmon/mp2891.rst b/Documentation/hwmon/mp2891.rst new file mode 100644 -index 000000000000..c4bda3d7ee8a +index 000000000..c4bda3d7e --- /dev/null +++ b/Documentation/hwmon/mp2891.rst @@ -0,0 +1,128 @@ @@ -164,7 +164,7 @@ index 000000000000..c4bda3d7ee8a + +**temp1_max_alarm** diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig -index 89668af67206..77d67344cee4 100644 +index 89668af67..77d67344c 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -299,6 +299,15 @@ config SENSORS_MP2888 @@ -184,7 +184,7 @@ index 89668af67206..77d67344cee4 100644 tristate "MPS MP2975" help diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile -index 0002dbe22d52..8e767d7b8c5b 100644 +index 0002dbe22..8e767d7b8 100644 --- a/drivers/hwmon/pmbus/Makefile +++ b/drivers/hwmon/pmbus/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_SENSORS_MAX31785) += max31785.o @@ -197,10 +197,10 @@ index 0002dbe22d52..8e767d7b8c5b 100644 obj-$(CONFIG_SENSORS_PLI1209BC) += pli1209bc.o diff --git a/drivers/hwmon/pmbus/mp2891.c b/drivers/hwmon/pmbus/mp2891.c new file mode 100644 -index 000000000000..1547625fea7e +index 000000000..a4386e8e9 --- /dev/null +++ b/drivers/hwmon/pmbus/mp2891.c -@@ -0,0 +1,424 @@ +@@ -0,0 +1,427 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers(MP2891) @@ -456,7 +456,7 @@ index 000000000000..1547625fea7e + * bit 13 = 0, the vid_step is defined by bits 15:14: + * 00b - 6.25mV/LSB, 01b - 5mV/LSB, 10b - 2mV/LSB, 11b - 1mV + */ -+ if ((ret & MP2891_DAC_2P5MV_MASK) >> MP2891_VID_STEP_POS) { ++ if (ret & MP2891_DAC_2P5MV_MASK) { + data->vid_step[page] = 250; + return mp2891_git_vid_volt_ref(client, data, page); + } @@ -468,6 +468,9 @@ index 000000000000..1547625fea7e + case 2: + data->vid_step[page] = 200; + break; ++ case 3: ++ data->vid_step[page] = 100; ++ break; + default: + data->vid_step[page] = 250; + break; @@ -626,5 +629,5 @@ index 000000000000..1547625fea7e +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(PMBUS); -- -2.20.1 +2.44.0 diff --git a/patch/0091-platform-mellanox-mlxreg-dpu-Add-initial-support-for.patch b/patch/0091-platform-mellanox-mlxreg-dpu-Add-initial-support-for.patch new file mode 100644 index 000000000..a6966cf1f --- /dev/null +++ b/patch/0091-platform-mellanox-mlxreg-dpu-Add-initial-support-for.patch @@ -0,0 +1,703 @@ +From 2f247a7eaf25a3de00d6319f2b6314d0c3bf36f6 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Mon, 17 Jun 2024 00:52:00 +0300 +Subject: [PATCH backport v6.1 1/2] platform/mellanox: mlxreg-dpu: Add initial + support for Nvidia DPU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Provide platform support for Nvidia (DPU) Data Processor Unit for the +Smart Switch SN4280. + +The Smart Switch equipped with: +- Nvidia COME module based on AMD EPYC™ Embedded 3451 CPU. +- Nvidia Spectrum-3 ASIC. +- Four DPUs, each equipped with Nvidia BF3 ARM based processor and + with Lattice LFD2NX-40 FPGA device. +- 28xQSFP-DD external ports. +- Two power supplies. +- Four cooling drawers. + +Drivers provides support for the platform management and monitoring +of DPU components. +It includes support for health events, resets and boot progress +indications logic, implemented by FPGA device. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/mellanox/Kconfig | 12 + + drivers/platform/mellanox/Makefile | 1 + + drivers/platform/mellanox/mlxreg-dpu.c | 625 +++++++++++++++++++++++++ + 3 files changed, 638 insertions(+) + create mode 100644 drivers/platform/mellanox/mlxreg-dpu.c + +diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig +index 6f9cb3a88d68..750c4c0905d7 100644 +--- a/drivers/platform/mellanox/Kconfig ++++ b/drivers/platform/mellanox/Kconfig +@@ -26,6 +26,18 @@ config MLX_PLATFORM + + If you have a Mellanox system, say Y or M here. + ++config MLXREG_DPU ++ tristate "Nvidia Data Processor Unit platform driver support" ++ select REGMAP_I2C ++ help ++ This driver provides support for the Nvidia BF3 Data Processor Units, ++ which are the part of SN4280 Ethernet smart switch systems ++ providing a high performance switching solution for Enterprise Data ++ Centers (EDC) for building Ethernet based clusters, High-Performance ++ Computing (HPC) and embedded environments. ++ ++ If you have a Nvidia smart swicth system, say Y or M here. ++ + config MLXREG_HOTPLUG + tristate "Mellanox platform hotplug driver support" + depends on HWMON +diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile +index ba56485cbe8c..e86723b44c2e 100644 +--- a/drivers/platform/mellanox/Makefile ++++ b/drivers/platform/mellanox/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o + obj-$(CONFIG_MLXBF_BOOTCTL) += mlxbf-bootctl.o + obj-$(CONFIG_MLXBF_PMC) += mlxbf-pmc.o + obj-$(CONFIG_MLXBF_TMFIFO) += mlxbf-tmfifo.o ++obj-$(CONFIG_MLXREG_DPU) += mlxreg-dpu.o + obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o + obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o + obj-$(CONFIG_MLXREG_LC) += mlxreg-lc.o +diff --git a/drivers/platform/mellanox/mlxreg-dpu.c b/drivers/platform/mellanox/mlxreg-dpu.c +new file mode 100644 +index 000000000000..f831d6dd5ece +--- /dev/null ++++ b/drivers/platform/mellanox/mlxreg-dpu.c +@@ -0,0 +1,625 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Nvidia Data Processor Unit platform driver ++ * ++ * Copyright (C) 2024 Nvidia Technologies Ltd. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* I2C bus IO offsets */ ++#define MLXREG_DPU_REG_FPGA1_VER_OFFSET 0x2400 ++#define MLXREG_DPU_REG_FPGA1_PN_OFFSET 0x2404 ++#define MLXREG_DPU_REG_FPGA1_PN1_OFFSET 0x2405 ++#define MLXREG_DPU_REG_PG_OFFSET 0x2414 ++#define MLXREG_DPU_REG_PG_EVENT_OFFSET 0x2415 ++#define MLXREG_DPU_REG_PG_MASK_OFFSET 0x2416 ++#define MLXREG_DPU_REG_RESET_GP1_OFFSET 0x2417 ++#define MLXREG_DPU_REG_RST_CAUSE1_OFFSET 0x241e ++#define MLXREG_DPU_REG_GP0_RO_OFFSET 0x242b ++#define MLXREG_DPU_REG_GP0_OFFSET 0x242e ++#define MLXREG_DPU_REG_GP1_OFFSET 0x242c ++#define MLXREG_DPU_REG_GP4_OFFSET 0x2438 ++#define MLXREG_DPU_REG_AGGRCO_OFFSET 0x2442 ++#define MLXREG_DPU_REG_AGGRCO_MASK_OFFSET 0x2443 ++#define MLXREG_DPU_REG_HEALTH_OFFSET 0x244d ++#define MLXREG_DPU_REG_HEALTH_EVENT_OFFSET 0x244e ++#define MLXREG_DPU_REG_HEALTH_MASK_OFFSET 0x244f ++#define MLXREG_DPU_REG_FPGA1_MVER_OFFSET 0x24de ++#define MLXREG_DPU_REG_CONFIG3_OFFSET 0x24fd ++#define MLXREG_DPU_REG_MAX 0x3fff ++ ++/* Power Good event masks. */ ++#define MLXREG_DPU_PG_VDDIO_MASK BIT(0) ++#define MLXREG_DPU_PG_VDD_CPU_MASK BIT(1) ++#define MLXREG_DPU_PG_VDD_MASK BIT(2) ++#define MLXREG_DPU_PG_1V8_MASK BIT(3) ++#define MLXREG_DPU_PG_COMPARATOR_MASK BIT(4) ++#define MLXREG_DPU_PG_VDDQ_MASK BIT(5) ++#define MLXREG_DPU_PG_HVDD_MASK BIT(6) ++#define MLXREG_DPU_PG_DVDD_MASK BIT(7) ++#define MLXREG_DPU_PG_MASK (MLXREG_DPU_PG_DVDD_MASK | \ ++ MLXREG_DPU_PG_HVDD_MASK | \ ++ MLXREG_DPU_PG_VDDQ_MASK | \ ++ MLXREG_DPU_PG_COMPARATOR_MASK | \ ++ MLXREG_DPU_PG_1V8_MASK | \ ++ MLXREG_DPU_PG_VDD_CPU_MASK | \ ++ MLXREG_DPU_PG_VDD_MASK | \ ++ MLXREG_DPU_PG_VDDIO_MASK) ++ ++/* Health event masks. */ ++#define MLXREG_DPU_HLTH_THERMAL_TRIP_MASK BIT(0) ++#define MLXREG_DPU_HLTH_UFM_UPGRADE_DONE_MASK BIT(1) ++#define MLXREG_DPU_HLTH_VDDQ_HOT_ALERT_MASK BIT(2) ++#define MLXREG_DPU_HLTH_VDD_CPU_HOT_ALERT_MASK BIT(3) ++#define MLXREG_DPU_HLTH_VDDQ_ALERT_MASK BIT(4) ++#define MLXREG_DPU_HLTH_VDD_CPU_ALERT_MASK BIT(5) ++#define MLXREG_DPU_HEALTH_MASK (MLXREG_DPU_HLTH_UFM_UPGRADE_DONE_MASK | \ ++ MLXREG_DPU_HLTH_VDDQ_HOT_ALERT_MASK | \ ++ MLXREG_DPU_HLTH_VDD_CPU_HOT_ALERT_MASK | \ ++ MLXREG_DPU_HLTH_VDDQ_ALERT_MASK | \ ++ MLXREG_DPU_HLTH_VDD_CPU_ALERT_MASK | \ ++ MLXREG_DPU_HLTH_THERMAL_TRIP_MASK) ++ ++/* Hotplug aggregation masks. */ ++#define MLXREG_DPU_HEALTH_AGGR_MASK BIT(0) ++#define MLXREG_DPU_PG_AGGR_MASK BIT(1) ++#define MLXREG_DPU_AGGR_MASK (MLXREG_DPU_HEALTH_AGGR_MASK | \ ++ MLXREG_DPU_PG_AGGR_MASK) ++ ++/* Voltage regulator firmware update status mask. */ ++#define MLXREG_DPU_VOLTREG_UPD_MASK GENMASK(5, 4) ++ ++#define MLXREG_DPU_NR_NONE (-1) ++ ++/* ++ * enum mlxreg_dpu_type - Data Processor Unit types ++ * ++ * @MLXREG_DPU_BF3: DPU equipped with BF3 SoC; ++ */ ++enum mlxreg_dpu_type { ++ MLXREG_DPU_BF3 = 0x0050, ++}; ++ ++/* Default register access data. */ ++static struct mlxreg_core_data mlxreg_dpu_io_data[] = { ++ { ++ .label = "fpga1_version", ++ .reg = MLXREG_DPU_REG_FPGA1_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "fpga1_pn", ++ .reg = MLXREG_DPU_REG_FPGA1_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, ++ }, ++ { ++ .label = "fpga1_version_min", ++ .reg = MLXREG_DPU_REG_FPGA1_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "perst_rst", ++ .reg = MLXREG_DPU_REG_RESET_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0644, ++ }, ++ { ++ .label = "usbphy_rst", ++ .reg = MLXREG_DPU_REG_RESET_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, ++ }, ++ { ++ .label = "phy_rst", ++ .reg = MLXREG_DPU_REG_RESET_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0644, ++ }, ++ { ++ .label = "tpm_rst", ++ .reg = MLXREG_DPU_REG_RESET_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0644, ++ }, ++ { ++ .label = "reset_from_main_board", ++ .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_aux_pwr_or_reload", ++ .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_comex_pwr_fail", ++ .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_dpu_thermal", ++ .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_pwr_off", ++ .reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "dpu_id", ++ .reg = MLXREG_DPU_REG_GP0_RO_OFFSET, ++ .bit = GENMASK(3, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "voltreg_update_status", ++ .reg = MLXREG_DPU_REG_GP0_RO_OFFSET, ++ .mask = MLXREG_DPU_VOLTREG_UPD_MASK, ++ .bit = 5, ++ .mode = 0444, ++ }, ++ { ++ .label = "boot_progress", ++ .reg = MLXREG_DPU_REG_GP1_OFFSET, ++ .bit = GENMASK(3, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "ufm_upgrade", ++ .reg = MLXREG_DPU_REG_GP4_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data mlxreg_dpu_default_regs_io_data = { ++ .data = mlxreg_dpu_io_data, ++ .counter = ARRAY_SIZE(mlxreg_dpu_io_data), ++}; ++ ++/* Default hotplug data. */ ++static struct mlxreg_core_data mlxreg_dpu_power_events_items_data[] = { ++ { ++ .label = "pg_vddio", ++ .reg = MLXREG_DPU_REG_PG_OFFSET, ++ .mask = MLXREG_DPU_PG_VDDIO_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "pg_vdd_cpu", ++ .reg = MLXREG_DPU_REG_PG_OFFSET, ++ .mask = MLXREG_DPU_PG_VDD_CPU_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "pg_vdd", ++ .reg = MLXREG_DPU_REG_PG_OFFSET, ++ .mask = MLXREG_DPU_PG_VDD_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "pg_1v8", ++ .reg = MLXREG_DPU_REG_PG_OFFSET, ++ .mask = MLXREG_DPU_PG_1V8_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "pg_comparator", ++ .reg = MLXREG_DPU_REG_PG_OFFSET, ++ .mask = MLXREG_DPU_PG_COMPARATOR_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "pg_vddq", ++ .reg = MLXREG_DPU_REG_PG_OFFSET, ++ .mask = MLXREG_DPU_PG_VDDQ_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "pg_hvdd", ++ .reg = MLXREG_DPU_REG_PG_OFFSET, ++ .mask = MLXREG_DPU_PG_HVDD_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "pg_dvdd", ++ .reg = MLXREG_DPU_REG_PG_OFFSET, ++ .mask = MLXREG_DPU_PG_DVDD_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++}; ++ ++static struct mlxreg_core_data mlxreg_dpu_health_events_items_data[] = { ++ { ++ .label = "thermal_trip", ++ .reg = MLXREG_DPU_REG_HEALTH_OFFSET, ++ .mask = MLXREG_DPU_HLTH_THERMAL_TRIP_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "ufm_upgrade_done", ++ .reg = MLXREG_DPU_REG_HEALTH_OFFSET, ++ .mask = MLXREG_DPU_HLTH_UFM_UPGRADE_DONE_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "vddq_hot_alert", ++ .reg = MLXREG_DPU_REG_HEALTH_OFFSET, ++ .mask = MLXREG_DPU_HLTH_VDDQ_HOT_ALERT_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "vdd_cpu_hot_alert", ++ .reg = MLXREG_DPU_REG_HEALTH_OFFSET, ++ .mask = MLXREG_DPU_HLTH_VDD_CPU_HOT_ALERT_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "vddq_alert", ++ .reg = MLXREG_DPU_REG_HEALTH_OFFSET, ++ .mask = MLXREG_DPU_HLTH_VDDQ_ALERT_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++ { ++ .label = "vdd_cpu_alert", ++ .reg = MLXREG_DPU_REG_HEALTH_OFFSET, ++ .mask = MLXREG_DPU_HLTH_VDD_CPU_ALERT_MASK, ++ .hpdev.nr = MLXREG_DPU_NR_NONE, ++ }, ++}; ++ ++static struct mlxreg_core_item mlxreg_dpu_hotplug_items[] = { ++ { ++ .data = mlxreg_dpu_power_events_items_data, ++ .aggr_mask = MLXREG_DPU_PG_AGGR_MASK, ++ .reg = MLXREG_DPU_REG_PG_OFFSET, ++ .mask = MLXREG_DPU_PG_MASK, ++ .count = ARRAY_SIZE(mlxreg_dpu_power_events_items_data), ++ .health = false, ++ .inversed = 0, ++ }, ++ { ++ .data = mlxreg_dpu_health_events_items_data, ++ .aggr_mask = MLXREG_DPU_HEALTH_AGGR_MASK, ++ .reg = MLXREG_DPU_REG_HEALTH_OFFSET, ++ .mask = MLXREG_DPU_HEALTH_MASK, ++ .count = ARRAY_SIZE(mlxreg_dpu_health_events_items_data), ++ .health = false, ++ .inversed = 0, ++ }, ++}; ++ ++static ++struct mlxreg_core_hotplug_platform_data mlxreg_dpu_default_hotplug_data = { ++ .items = mlxreg_dpu_hotplug_items, ++ .counter = ARRAY_SIZE(mlxreg_dpu_hotplug_items), ++ .cell = MLXREG_DPU_REG_AGGRCO_OFFSET, ++ .mask = MLXREG_DPU_AGGR_MASK, ++}; ++ ++/* mlxreg_dpu - device private data ++ * @dev: platform device; ++ * @data: pltaform core data; ++ * @io_data: register access platform data; ++ * @io_regs: register access device; ++ * @hotplug_data: hotplug platform data; ++ * @hotplug: hotplug device; ++ */ ++struct mlxreg_dpu { ++ struct device *dev; ++ struct mlxreg_core_data *data; ++ struct mlxreg_core_platform_data *io_data; ++ struct platform_device *io_regs; ++ struct mlxreg_core_hotplug_platform_data *hotplug_data; ++ struct platform_device *hotplug; ++}; ++ ++static bool mlxreg_dpu_writeable_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case MLXREG_DPU_REG_PG_EVENT_OFFSET: ++ case MLXREG_DPU_REG_PG_MASK_OFFSET: ++ case MLXREG_DPU_REG_RESET_GP1_OFFSET: ++ case MLXREG_DPU_REG_GP0_OFFSET: ++ case MLXREG_DPU_REG_GP1_OFFSET: ++ case MLXREG_DPU_REG_GP4_OFFSET: ++ case MLXREG_DPU_REG_AGGRCO_OFFSET: ++ case MLXREG_DPU_REG_AGGRCO_MASK_OFFSET: ++ case MLXREG_DPU_REG_HEALTH_EVENT_OFFSET: ++ case MLXREG_DPU_REG_HEALTH_MASK_OFFSET: ++ return true; ++ } ++ return false; ++} ++ ++static bool mlxreg_dpu_readable_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case MLXREG_DPU_REG_FPGA1_VER_OFFSET: ++ case MLXREG_DPU_REG_FPGA1_PN_OFFSET: ++ case MLXREG_DPU_REG_FPGA1_PN1_OFFSET: ++ case MLXREG_DPU_REG_PG_OFFSET: ++ case MLXREG_DPU_REG_PG_EVENT_OFFSET: ++ case MLXREG_DPU_REG_PG_MASK_OFFSET: ++ case MLXREG_DPU_REG_RESET_GP1_OFFSET: ++ case MLXREG_DPU_REG_RST_CAUSE1_OFFSET: ++ case MLXREG_DPU_REG_GP0_RO_OFFSET: ++ case MLXREG_DPU_REG_GP0_OFFSET: ++ case MLXREG_DPU_REG_GP1_OFFSET: ++ case MLXREG_DPU_REG_GP4_OFFSET: ++ case MLXREG_DPU_REG_AGGRCO_OFFSET: ++ case MLXREG_DPU_REG_AGGRCO_MASK_OFFSET: ++ case MLXREG_DPU_REG_HEALTH_OFFSET: ++ case MLXREG_DPU_REG_HEALTH_EVENT_OFFSET: ++ case MLXREG_DPU_REG_HEALTH_MASK_OFFSET: ++ case MLXREG_DPU_REG_FPGA1_MVER_OFFSET: ++ case MLXREG_DPU_REG_CONFIG3_OFFSET: ++ return true; ++ } ++ return false; ++} ++ ++static bool mlxreg_dpu_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case MLXREG_DPU_REG_FPGA1_VER_OFFSET: ++ case MLXREG_DPU_REG_FPGA1_PN_OFFSET: ++ case MLXREG_DPU_REG_FPGA1_PN1_OFFSET: ++ case MLXREG_DPU_REG_PG_OFFSET: ++ case MLXREG_DPU_REG_PG_EVENT_OFFSET: ++ case MLXREG_DPU_REG_PG_MASK_OFFSET: ++ case MLXREG_DPU_REG_RESET_GP1_OFFSET: ++ case MLXREG_DPU_REG_RST_CAUSE1_OFFSET: ++ case MLXREG_DPU_REG_GP0_RO_OFFSET: ++ case MLXREG_DPU_REG_GP0_OFFSET: ++ case MLXREG_DPU_REG_GP1_OFFSET: ++ case MLXREG_DPU_REG_GP4_OFFSET: ++ case MLXREG_DPU_REG_AGGRCO_OFFSET: ++ case MLXREG_DPU_REG_AGGRCO_MASK_OFFSET: ++ case MLXREG_DPU_REG_HEALTH_OFFSET: ++ case MLXREG_DPU_REG_HEALTH_EVENT_OFFSET: ++ case MLXREG_DPU_REG_HEALTH_MASK_OFFSET: ++ case MLXREG_DPU_REG_FPGA1_MVER_OFFSET: ++ case MLXREG_DPU_REG_CONFIG3_OFFSET: ++ return true; ++ } ++ return false; ++} ++ ++/* Configuration for the register map of a device with 2 bytes address space. */ ++static const struct regmap_config mlxreg_dpu_regmap_conf = { ++ .reg_bits = 16, ++ .val_bits = 8, ++ .max_register = MLXREG_DPU_REG_MAX, ++ .cache_type = REGCACHE_FLAT, ++ .writeable_reg = mlxreg_dpu_writeable_reg, ++ .readable_reg = mlxreg_dpu_readable_reg, ++ .volatile_reg = mlxreg_dpu_volatile_reg, ++}; ++ ++static int mlxreg_dpu_copy_hotplug_data(struct device *dev, struct mlxreg_dpu *mlxreg_dpu, ++ struct mlxreg_core_hotplug_platform_data *hotplug_data) ++{ ++ struct mlxreg_core_item *item; ++ int i; ++ ++ mlxreg_dpu->hotplug_data = devm_kmemdup(dev, hotplug_data, ++ sizeof(*mlxreg_dpu->hotplug_data), GFP_KERNEL); ++ if (!mlxreg_dpu->hotplug_data) ++ return -ENOMEM; ++ ++ mlxreg_dpu->hotplug_data->items = devm_kmemdup(dev, hotplug_data->items, ++ mlxreg_dpu->hotplug_data->counter * ++ sizeof(*hotplug_data->items), ++ GFP_KERNEL); ++ if (!mlxreg_dpu->hotplug_data->items) ++ return -ENOMEM; ++ ++ item = mlxreg_dpu->hotplug_data->items; ++ for (i = 0; i < mlxreg_dpu->hotplug_data->counter; i++, item++) { ++ item = devm_kmemdup(dev, &hotplug_data->items[i], sizeof(*item), GFP_KERNEL); ++ if (!item) ++ return -ENOMEM; ++ item->data = devm_kmemdup(dev, hotplug_data->items[i].data, ++ hotplug_data->items[i].count * sizeof(item->data), ++ GFP_KERNEL); ++ if (!item->data) ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static int mlxreg_dpu_config_init(struct mlxreg_dpu *mlxreg_dpu, void *regmap, ++ struct mlxreg_core_data *data, int irq) ++{ ++ struct device *dev = &data->hpdev.client->dev; ++ u32 regval; ++ int err; ++ ++ /* Validate DPU type. */ ++ err = regmap_read(regmap, MLXREG_DPU_REG_CONFIG3_OFFSET, ®val); ++ if (err) ++ return err; ++ switch (regval) { ++ case MLXREG_DPU_BF3: ++ /* Copy platform specific hotplug data. */ ++ err = mlxreg_dpu_copy_hotplug_data(dev, mlxreg_dpu, ++ &mlxreg_dpu_default_hotplug_data); ++ if (err) ++ return err; ++ ++ mlxreg_dpu->io_data = &mlxreg_dpu_default_regs_io_data; ++ ++ break; ++ default: ++ return -ENODEV; ++ } ++ ++ /* Register IO access driver. */ ++ if (mlxreg_dpu->io_data) { ++ mlxreg_dpu->io_data->regmap = regmap; ++ mlxreg_dpu->io_regs = ++ platform_device_register_resndata(dev, "mlxreg-io", data->slot, NULL, 0, ++ mlxreg_dpu->io_data, ++ sizeof(*mlxreg_dpu->io_data)); ++ if (IS_ERR(mlxreg_dpu->io_regs)) { ++ dev_err(dev, "Failed to create regio for client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, ++ data->hpdev.brdinfo->addr); ++ err = PTR_ERR(mlxreg_dpu->io_regs); ++ goto fail_register_io; ++ } ++ } ++ ++ /* Register hotplug driver. */ ++ if (mlxreg_dpu->hotplug_data && irq) { ++ mlxreg_dpu->hotplug_data->regmap = regmap; ++ mlxreg_dpu->hotplug_data->irq = irq; ++ mlxreg_dpu->hotplug = ++ platform_device_register_resndata(dev, "mlxreg-hotplug", data->slot, NULL, 0, ++ mlxreg_dpu->hotplug_data, ++ sizeof(*mlxreg_dpu->hotplug_data)); ++ if (IS_ERR(mlxreg_dpu->hotplug)) { ++ err = PTR_ERR(mlxreg_dpu->hotplug); ++ goto fail_register_hotplug; ++ } ++ } ++ ++ return 0; ++ ++fail_register_hotplug: ++ platform_device_unregister(mlxreg_dpu->io_regs); ++fail_register_io: ++ ++ return err; ++} ++ ++static void mlxreg_dpu_config_exit(struct mlxreg_dpu *mlxreg_dpu) ++{ ++ /* Unregister hotplug driver. */ ++ platform_device_unregister(mlxreg_dpu->hotplug); ++ /* Unregister IO access driver. */ ++ platform_device_unregister(mlxreg_dpu->io_regs); ++} ++ ++static int mlxreg_dpu_probe(struct platform_device *pdev) ++{ ++ struct mlxreg_core_data *data; ++ struct mlxreg_dpu *mlxreg_dpu; ++ void *regmap; ++ int err; ++ ++ data = dev_get_platdata(&pdev->dev); ++ if (!data || !data->hpdev.brdinfo) ++ return -EINVAL; ++ ++ mlxreg_dpu = devm_kzalloc(&pdev->dev, sizeof(*mlxreg_dpu), GFP_KERNEL); ++ if (!mlxreg_dpu) ++ return -ENOMEM; ++ ++ data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr); ++ if (!data->hpdev.adapter) ++ return -EPROBE_DEFER; ++ ++ /* Create device at the top of DPU I2C tree.*/ ++ data->hpdev.client = i2c_new_client_device(data->hpdev.adapter, ++ data->hpdev.brdinfo); ++ if (IS_ERR(data->hpdev.client)) { ++ dev_err(&pdev->dev, "Failed to create client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr); ++ err = PTR_ERR(data->hpdev.client); ++ goto i2c_new_device_fail; ++ } ++ ++ regmap = devm_regmap_init_i2c(data->hpdev.client, ++ &mlxreg_dpu_regmap_conf); ++ if (IS_ERR(regmap)) { ++ dev_err(&pdev->dev, "Failed to create regmap for client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr); ++ err = PTR_ERR(regmap); ++ goto devm_regmap_init_i2c_fail; ++ } ++ ++ /* Sync registers with hardware. */ ++ regcache_mark_dirty(regmap); ++ err = regcache_sync(regmap); ++ if (err) { ++ dev_err(&pdev->dev, "Failed to sync regmap for client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr); ++ err = PTR_ERR(regmap); ++ goto regcache_sync_fail; ++ } ++ ++ mlxreg_dpu->data = data; ++ mlxreg_dpu->dev = &pdev->dev; ++ platform_set_drvdata(pdev, mlxreg_dpu); ++ ++ /* Configure DPU. */ ++ err = mlxreg_dpu_config_init(mlxreg_dpu, regmap, data, data->hpdev.brdinfo->irq); ++ if (err) ++ goto mlxreg_dpu_config_init_fail; ++ ++ return err; ++ ++mlxreg_dpu_config_init_fail: ++regcache_sync_fail: ++devm_regmap_init_i2c_fail: ++ if (data->hpdev.client) { ++ i2c_unregister_device(data->hpdev.client); ++ data->hpdev.client = NULL; ++ } ++i2c_new_device_fail: ++ i2c_put_adapter(data->hpdev.adapter); ++ data->hpdev.adapter = NULL; ++ return err; ++} ++ ++static int mlxreg_dpu_remove(struct platform_device *pdev) ++{ ++ struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev); ++ struct mlxreg_dpu *mlxreg_dpu = platform_get_drvdata(pdev); ++ ++ mlxreg_dpu_config_exit(mlxreg_dpu); ++ if (data->hpdev.client) { ++ i2c_unregister_device(data->hpdev.client); ++ data->hpdev.client = NULL; ++ i2c_put_adapter(data->hpdev.adapter); ++ data->hpdev.adapter = NULL; ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver mlxreg_dpu_driver = { ++ .probe = mlxreg_dpu_probe, ++ .remove = mlxreg_dpu_remove, ++ .driver = { ++ .name = "mlxreg-dpu", ++ }, ++}; ++ ++module_platform_driver(mlxreg_dpu_driver); ++ ++MODULE_AUTHOR("Vadim Pasternak "); ++MODULE_DESCRIPTION("Nvidia Data Processor Unit platform driver"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_ALIAS("platform:mlxreg-dpu"); ++ +-- +2.34.1 + diff --git a/patch/0092-platform-mellanox-Introduce-support-of-Nvidia-smart-.patch b/patch/0092-platform-mellanox-Introduce-support-of-Nvidia-smart-.patch new file mode 100644 index 000000000..b7435002f --- /dev/null +++ b/patch/0092-platform-mellanox-Introduce-support-of-Nvidia-smart-.patch @@ -0,0 +1,1248 @@ +From 1ffb1c6f0a5d71f35e727ff228dc08b065c084c1 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Thu, 7 Dec 2023 20:43:29 +0000 +Subject: [PATCH v6.1 02/16] platform: mellanox: Introduce support of Nvidia + smart switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Provide platform support for Nvidia Smart Switch SN4280. + +The Smart Switch equipped with: +- Nvidia COME module based on AMD EPYC™ Embedded 3451 CPU. +- Nvidia Spectrum-3 ASIC. +- Four DPUs, each equipped with Nvidia BF3 ARM based processor and + with Lattice LFD2NX-40 FPGA device. +- 28xQSFP-DD external ports. +- Two power supplies. +- Four cooling drawers. + +Introduce configuration structures for the new systems to allow proper +activation of the required platform drivers. + +Signed-off-by: Vadim Pasternak +--- + drivers/platform/mellanox/mlx-platform.c | 927 +++++++++++++++++++++-- + 1 file changed, 860 insertions(+), 67 deletions(-) + +diff --git a/drivers/platform/mellanox/mlx-platform.c b/drivers/platform/mellanox/mlx-platform.c +index cafa4f762..0949f32ad 100644 +--- a/drivers/platform/mellanox/mlx-platform.c ++++ b/drivers/platform/mellanox/mlx-platform.c +@@ -39,6 +39,7 @@ + #define MLXPLAT_CPLD_LPC_REG_CPLD4_PN1_OFFSET 0x0b + #define MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET 0x17 + #define MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET 0x19 ++#define MLXPLAT_CPLD_LPC_REG_RESET_GP3_OFFSET 0x1b + #define MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET 0x1c + #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d + #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e +@@ -54,6 +55,7 @@ + #define MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION 0x2a + #define MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET 0x2b + #define MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET 0x2d ++#define MLXPLAT_CPLD_LPC_REG_GP1_RO_OFFSET 0x2c + #define MLXPLAT_CPLD_LPC_REG_GP0_OFFSET 0x2e + #define MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET 0x2f + #define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET 0x30 +@@ -73,12 +75,14 @@ + #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_GP3_OFFSET 0x46 + #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_GPI_MASK_OFFSET 0x4e + #define MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET 0x50 + #define MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET 0x51 + #define MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET 0x52 +@@ -90,9 +94,11 @@ + #define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58 + #define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET 0x59 + #define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET 0x5a ++#define MLXPLAT_CPLD_LPC_REG_PSU_AC_OFFSET 0x5e + #define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET 0x64 + #define MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET 0x65 + #define MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET 0x66 ++#define MLXPLAT_CPLD_LPC_REG_PSU_ALERT_OFFSET 0x6a + #define MLXPLAT_CPLD_LPC_REG_LC_IN_OFFSET 0x70 + #define MLXPLAT_CPLD_LPC_REG_LC_IN_EVENT_OFFSET 0x71 + #define MLXPLAT_CPLD_LPC_REG_LC_IN_MASK_OFFSET 0x72 +@@ -234,9 +240,15 @@ + #define MLXPLAT_CPLD_AGGR_MASK_NG_DEF 0x04 + #define MLXPLAT_CPLD_AGGR_MASK_COMEX BIT(0) + #define MLXPLAT_CPLD_AGGR_MASK_LC BIT(3) ++#define MLXPLAT_CPLD_AGGR_MASK_DPU_BRD BIT(4) ++#define MLXPLAT_CPLD_AGGR_MASK_DPU_CORE BIT(5) + #define MLXPLAT_CPLD_AGGR_MASK_MODULAR (MLXPLAT_CPLD_AGGR_MASK_NG_DEF | \ + MLXPLAT_CPLD_AGGR_MASK_COMEX | \ + MLXPLAT_CPLD_AGGR_MASK_LC) ++#define MLXPLAT_CPLD_AGGR_MASK_SMART_SW (MLXPLAT_CPLD_AGGR_MASK_COMEX | \ ++ MLXPLAT_CPLD_AGGR_MASK_NG_DEF | \ ++ MLXPLAT_CPLD_AGGR_MASK_DPU_BRD | \ ++ MLXPLAT_CPLD_AGGR_MASK_DPU_CORE) + #define MLXPLAT_CPLD_AGGR_MASK_LC_PRSNT BIT(0) + #define MLXPLAT_CPLD_AGGR_MASK_LC_RDY BIT(1) + #define MLXPLAT_CPLD_AGGR_MASK_LC_PG BIT(2) +@@ -279,6 +291,8 @@ + #define MLXPLAT_CPLD_PSU_CAP_MASK GENMASK(3, 0) + #define MLXPLAT_CPLD_FAN_CAP_MASK GENMASK(7, 0) + #define MLXPLAT_CPLD_ASIC_CAP_MASK GENMASK(7, 0) ++#define MLXPLAT_CPLD_BIOS_STATUS_MASK GENMASK(3, 1) ++#define MLXPLAT_CPLD_DPU_MASK GENMASK(3, 0) + #define MLXPLAT_CPLD_PWR_BUTTON_MASK BIT(0) + #define MLXPLAT_CPLD_LATCH_RST_MASK BIT(6) + #define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3) +@@ -302,6 +316,9 @@ + /* Masks for aggregation for modular systems */ + #define MLXPLAT_CPLD_LPC_LC_MASK GENMASK(7, 0) + ++/* Masks for aggregation for smart switch systems */ ++#define MLXPLAT_CPLD_LPC_SM_SW_MASK GENMASK(7, 0) ++ + #define MLXPLAT_CPLD_HALT_MASK BIT(3) + #define MLXPLAT_CPLD_RESET_MASK GENMASK(7, 1) + +@@ -341,9 +358,11 @@ + #define MLXPLAT_CPLD_FAN4_DEFAULT_NR 14 + #define MLXPLAT_CPLD_NR_ASIC 3 + #define MLXPLAT_CPLD_NR_LC_BASE 34 ++#define MLXPLAT_CPLD_NR_DPU_BASE 18 + + #define MLXPLAT_CPLD_NR_LC_SET(nr) (MLXPLAT_CPLD_NR_LC_BASE + (nr)) + #define MLXPLAT_CPLD_LC_ADDR 0x32 ++#define MLXPLAT_CPLD_DPU_ADDR 0x68 + + /* Masks and default values for watchdogs */ + #define MLXPLAT_CPLD_WD1_CLEAR_MASK GENMASK(7, 1) +@@ -358,6 +377,7 @@ + #define MLXPLAT_CPLD_WD_DFLT_TIMEOUT 30 + #define MLXPLAT_CPLD_WD3_DFLT_TIMEOUT 600 + #define MLXPLAT_CPLD_WD_MAX_DEVS 2 ++#define MLXPLAT_CPLD_DPU_MAX_DEVS 4 + + #define MLXPLAT_CPLD_LPC_SYSIRQ 17 + +@@ -399,6 +419,7 @@ + * @pdev_io_regs - register access platform devices + * @pdev_fan - FAN platform devices + * @pdev_wd - array of watchdog platform devices ++ * pdev_dpu - array of Data Processor Unit platform devices + * @regmap: device register map + * @hotplug_resources: system hotplug resources + * @hotplug_resources_size: size of system hotplug resources +@@ -414,6 +435,7 @@ struct mlxplat_priv { + struct platform_device *pdev_io_regs; + struct platform_device *pdev_fan; + struct platform_device *pdev_wd[MLXPLAT_CPLD_WD_MAX_DEVS]; ++ struct platform_device *pdev_dpu[MLXPLAT_CPLD_DPU_MAX_DEVS]; + void *regmap; + struct resource *hotplug_resources; + unsigned int hotplug_resources_size; +@@ -2941,6 +2963,212 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_rack_switch_data = { + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, + }; + ++/* Platform hotplug for smart switch systems families data */ ++static struct mlxreg_core_data mlxplat_mlxcpld_smart_switch_dpu_ready_data[] = { ++ { ++ .label = "dpu1_ready", ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, ++ .mask = BIT(0), ++ .slot = 1, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "dpu2_ready", ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, ++ .mask = BIT(1), ++ .slot = 2, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "dpu3_ready", ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, ++ .mask = BIT(2), ++ .slot = 3, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "dpu4_ready", ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, ++ .mask = BIT(3), ++ .slot = 4, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++}; ++ ++static struct mlxreg_core_data mlxplat_mlxcpld_smart_switch_dpu_shtdn_ready_data[] = { ++ { ++ .label = "dpu1_shtdn_ready", ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, ++ .mask = BIT(0), ++ .slot = 1, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "dpu2_shtdn_ready", ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, ++ .mask = BIT(1), ++ .slot = 2, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "dpu3_shtdn_ready", ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, ++ .mask = BIT(2), ++ .slot = 3, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "dpu4_shtdn_ready", ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, ++ .mask = BIT(3), ++ .slot = 4, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++}; ++ ++static struct mlxreg_core_item mlxplat_mlxcpld_smart_switch_items[] = { ++ { ++ .data = mlxplat_mlxcpld_xdr_psu_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, ++ .mask = MLXPLAT_CPLD_PSU_XDR_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_PSU_CAP_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_xdr_psu_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_xdr_pwr_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, ++ .mask = MLXPLAT_CPLD_PWR_XDR_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_PSU_I2C_CAP_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_PSU_CAP_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_xdr_pwr_items_data), ++ .inversed = 0, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_xdr_fan_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .mask = MLXPLAT_CPLD_FAN_XDR_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_FAN_CAP_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_xdr_fan_items_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_xdr_asic1_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_XDR_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_ASIC_CAP_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_ASIC_CAP_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_xdr_asic1_items_data), ++ .inversed = 0, ++ .health = true, ++ }, ++ { ++ .data = mlxplat_mlxcpld_smart_switch_dpu_ready_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_DPU_CORE, ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_RD_OFFSET, ++ .mask = MLXPLAT_CPLD_DPU_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_smart_switch_dpu_ready_data), ++ .inversed = 1, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_smart_switch_dpu_shtdn_ready_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_DPU_CORE, ++ .reg = MLXPLAT_CPLD_LPC_REG_LC_SN_OFFSET, ++ .mask = MLXPLAT_CPLD_DPU_MASK, ++ .capability = MLXPLAT_CPLD_LPC_REG_SLOT_QTY_OFFSET, ++ .capability_mask = MLXPLAT_CPLD_DPU_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_smart_switch_dpu_shtdn_ready_data), ++ .inversed = 1, ++ .health = false, ++ }, ++}; ++ ++static ++struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_smart_switch_data = { ++ .items = mlxplat_mlxcpld_smart_switch_items, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_smart_switch_items), ++ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, ++ .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF | MLXPLAT_CPLD_AGGR_MASK_COMEX | ++ MLXPLAT_CPLD_AGGR_MASK_DPU_BRD | MLXPLAT_CPLD_AGGR_MASK_DPU_CORE, ++ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, ++ .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, ++}; ++ ++/* Smart switch data processor units data */ ++static struct i2c_board_info mlxplat_mlxcpld_smart_switch_dpu_devs[] = { ++ { ++ I2C_BOARD_INFO("mlxreg-dpu", MLXPLAT_CPLD_DPU_ADDR), ++ .irq = MLXPLAT_CPLD_LPC_SYSIRQ, ++ }, ++ { ++ I2C_BOARD_INFO("mlxreg-dpu", MLXPLAT_CPLD_DPU_ADDR), ++ .irq = MLXPLAT_CPLD_LPC_SYSIRQ, ++ }, ++ { ++ I2C_BOARD_INFO("mlxreg-dpu", MLXPLAT_CPLD_DPU_ADDR), ++ .irq = MLXPLAT_CPLD_LPC_SYSIRQ, ++ }, ++ { ++ I2C_BOARD_INFO("mlxreg-dpu", MLXPLAT_CPLD_DPU_ADDR), ++ .irq = MLXPLAT_CPLD_LPC_SYSIRQ, ++ }, ++}; ++ ++static struct mlxreg_core_data mlxplat_mlxcpld_smart_switch_dpu_data[] = { ++ { ++ .label = "dpu1", ++ .hpdev.brdinfo = &mlxplat_mlxcpld_smart_switch_dpu_devs[0], ++ .hpdev.nr = MLXPLAT_CPLD_NR_DPU_BASE, ++ .slot = 1, ++ }, ++ { ++ .label = "dpu2", ++ .hpdev.brdinfo = &mlxplat_mlxcpld_smart_switch_dpu_devs[1], ++ .hpdev.nr = MLXPLAT_CPLD_NR_DPU_BASE + 1, ++ .slot = 2, ++ }, ++ { ++ .label = "dpu3", ++ .hpdev.brdinfo = &mlxplat_mlxcpld_smart_switch_dpu_devs[2], ++ .hpdev.nr = MLXPLAT_CPLD_NR_DPU_BASE + 2, ++ .slot = 3, ++ }, ++ { ++ .label = "dpu4", ++ .hpdev.brdinfo = &mlxplat_mlxcpld_smart_switch_dpu_devs[2], ++ .hpdev.nr = MLXPLAT_CPLD_NR_DPU_BASE + 3, ++ .slot = 4, ++ }, ++}; ++ + /* 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, +@@ -5431,99 +5659,573 @@ static struct mlxreg_core_platform_data mlxplat_chassis_blade_regs_io_data = { + .counter = ARRAY_SIZE(mlxplat_mlxcpld_chassis_blade_regs_io_data), + }; + +-/* Platform FAN default */ +-static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { ++/* Platform register access for smart switch systems families data */ ++static struct mlxreg_core_data mlxplat_mlxcpld_smart_switch_regs_io_data[] = { + { +- .label = "pwm1", +- .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET, ++ .label = "cpld1_version", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, + }, + { +- .label = "pwm2", +- .reg = MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET, ++ .label = "cpld2_version", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, + }, + { +- .label = "pwm3", +- .reg = MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET, ++ .label = "cpld3_version", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, + }, + { +- .label = "pwm4", +- .reg = MLXPLAT_CPLD_LPC_REG_PWM4_OFFSET, ++ .label = "cpld1_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, + }, + { +- .label = "tacho1", +- .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET, +- .mask = GENMASK(7, 0), +- .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, +- .bit = BIT(0), +- .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, +- ++ .label = "cpld2_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, + }, + { +- .label = "tacho2", +- .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET, +- .mask = GENMASK(7, 0), +- .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, +- .bit = BIT(1), +- .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .label = "cpld3_pn", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_PN_OFFSET, ++ .bit = GENMASK(15, 0), ++ .mode = 0444, ++ .regnum = 2, + }, + { +- .label = "tacho3", +- .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET, +- .mask = GENMASK(7, 0), +- .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, +- .bit = BIT(2), +- .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .label = "cpld1_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, + }, + { +- .label = "tacho4", +- .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET, +- .mask = GENMASK(7, 0), +- .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, +- .bit = BIT(3), +- .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .label = "cpld2_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, + }, + { +- .label = "tacho5", +- .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET, +- .mask = GENMASK(7, 0), +- .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, +- .bit = BIT(4), +- .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .label = "cpld3_version_min", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD3_MVER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, + }, + { +- .label = "tacho6", +- .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET, +- .mask = GENMASK(7, 0), +- .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, +- .bit = BIT(5), +- .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .label = "kexec_activated", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, + }, + { +- .label = "tacho7", +- .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET, +- .mask = GENMASK(7, 0), +- .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, +- .bit = BIT(6), +- .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .label = "asic_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, + }, + { +- .label = "tacho8", +- .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET, +- .mask = GENMASK(7, 0), +- .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, +- .bit = BIT(7), +- .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .label = "eth_switch_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0644, + }, + { +- .label = "tacho9", +- .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET, +- .mask = GENMASK(7, 0), +- .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, +- .bit = BIT(0), +- .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .label = "dpu1_rst", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP3_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0200, + }, + { +- .label = "tacho10", ++ .label = "dpu2_rst", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP3_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu3_rst", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP3_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu4_rst", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP3_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu1_pwr", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu2_pwr", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu3_pwr", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu4_pwr", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0200, ++ }, ++ { ++ .label = "reset_long_pb", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_short_pb", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_aux_pwr_or_ref", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_swb_dc_dc_pwr_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_swb_wd", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_asic_thermal", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_sw_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_aux_pwr_or_reload", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_comex_pwr_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_platform", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_soc", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_pwr", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_pwr_converter_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_system", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_sw_pwr_off", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_comex_thermal", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_ac_pwr_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "voltreg_update_status", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET, ++ .mask = MLXPLAT_CPLD_VOLTREG_UPD_MASK, ++ .bit = 5, ++ .mode = 0444, ++ }, ++ { ++ .label = "port80", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_RO_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "bios_status", ++ .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, ++ .mask = MLXPLAT_CPLD_BIOS_STATUS_MASK, ++ .bit = 2, ++ .mode = 0444, ++ }, ++ { ++ .label = "bios_start_retry", ++ .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0444, ++ }, ++ { ++ .label = "bios_active_image", ++ .reg = MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "vpd_wp", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0644, ++ }, ++ { ++ .label = "pcie_asic_reset_dis", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0644, ++ }, ++ { ++ .label = "shutdown_unlock", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP0_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0644, ++ }, ++ { ++ .label = "fan_dir", ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "dpu1_rst_en", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu2_rst_en", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu3_rst_en", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu4_rst_en", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0200, ++ }, ++ { ++ .label = "psu1_on", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0200, ++ }, ++ { ++ .label = "psu2_on", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0200, ++ }, ++ { ++ .label = "pwr_cycle", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0200, ++ }, ++ { ++ .label = "pwr_down", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0200, ++ }, ++ { ++ .label = "jtag_cap", ++ .reg = MLXPLAT_CPLD_LPC_REG_FU_CAP_OFFSET, ++ .mask = MLXPLAT_CPLD_FU_CAP_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++ { ++ .label = "jtag_enable", ++ .reg = MLXPLAT_CPLD_LPC_REG_FIELD_UPGRADE, ++ .mask = GENMASK(1, 0), ++ .bit = 1, ++ .mode = 0644, ++ }, ++ { ++ .label = "non_active_bios_select", ++ .reg = MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0644, ++ }, ++ { ++ .label = "bios_upgrade_fail", ++ .reg = MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "bios_image_invert", ++ .reg = MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0644, ++ }, ++ { ++ .label = "me_reboot", ++ .reg = MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0644, ++ }, ++ { ++ .label = "dpu1_pwr_force", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP3_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu2_pwr_force", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP3_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu3_pwr_force", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP3_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0200, ++ }, ++ { ++ .label = "dpu4_pwr_force", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP3_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0200, ++ }, ++ { ++ .label = "ufm_done", ++ .reg = MLXPLAT_CPLD_LPC_REG_GPI_MASK_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "asic_health", ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++ { ++ .label = "psu1_ac_ok", ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_AC_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0644, ++ }, ++ { ++ .label = "psu2_ac_ok", ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_AC_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, ++ }, ++ { ++ .label = "psu1_no_alert", ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_ALERT_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0644, ++ }, ++ { ++ .label = "psu2_no_alert", ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_ALERT_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0644, ++ }, ++ { ++ .label = "asic_pg_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .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, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "config2", ++ .reg = MLXPLAT_CPLD_LPC_REG_CONFIG2_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "config3", ++ .reg = MLXPLAT_CPLD_LPC_REG_CONFIG3_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "ufm_version", ++ .reg = MLXPLAT_CPLD_LPC_REG_UFM_VERSION_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data mlxplat_smart_switch_regs_io_data = { ++ .data = mlxplat_mlxcpld_smart_switch_regs_io_data, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_smart_switch_regs_io_data), ++}; ++ ++/* Platform FAN default */ ++static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { ++ { ++ .label = "pwm1", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET, ++ }, ++ { ++ .label = "pwm2", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM2_OFFSET, ++ }, ++ { ++ .label = "pwm3", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM3_OFFSET, ++ }, ++ { ++ .label = "pwm4", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM4_OFFSET, ++ }, ++ { ++ .label = "tacho1", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET, ++ .mask = GENMASK(7, 0), ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, ++ .bit = BIT(0), ++ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ ++ }, ++ { ++ .label = "tacho2", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET, ++ .mask = GENMASK(7, 0), ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, ++ .bit = BIT(1), ++ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ }, ++ { ++ .label = "tacho3", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET, ++ .mask = GENMASK(7, 0), ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, ++ .bit = BIT(2), ++ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ }, ++ { ++ .label = "tacho4", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET, ++ .mask = GENMASK(7, 0), ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, ++ .bit = BIT(3), ++ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ }, ++ { ++ .label = "tacho5", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET, ++ .mask = GENMASK(7, 0), ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, ++ .bit = BIT(4), ++ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ }, ++ { ++ .label = "tacho6", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET, ++ .mask = GENMASK(7, 0), ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, ++ .bit = BIT(5), ++ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ }, ++ { ++ .label = "tacho7", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET, ++ .mask = GENMASK(7, 0), ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, ++ .bit = BIT(6), ++ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ }, ++ { ++ .label = "tacho8", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET, ++ .mask = GENMASK(7, 0), ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET, ++ .bit = BIT(7), ++ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ }, ++ { ++ .label = "tacho9", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET, ++ .mask = GENMASK(7, 0), ++ .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, ++ .bit = BIT(0), ++ .reg_prsnt = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ }, ++ { ++ .label = "tacho10", + .reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET, + .mask = GENMASK(7, 0), + .capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET, +@@ -5975,6 +6677,8 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + { + switch (reg) { + case MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_RESET_GP3_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: +@@ -5990,6 +6694,7 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP3_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FIELD_UPGRADE: + case MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET: + case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: +@@ -6017,8 +6722,10 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_ASIC4_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_AC_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_ALERT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN2_EVENT_OFFSET: +@@ -6094,6 +6801,8 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD6_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD6_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_RESET_GP3_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: +@@ -6109,12 +6818,14 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION: + case MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP1_RO_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP0_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP3_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FIELD_UPGRADE: + case MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET: + case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: +@@ -6134,6 +6845,7 @@ 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_GPI_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: +@@ -6152,9 +6864,11 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_AC_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_ALERT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: +@@ -6280,6 +6994,8 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_CPLD6_PN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD6_PN1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_GP1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_RESET_GP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_RESET_GP3_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_GP4_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET: +@@ -6295,10 +7011,12 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION: + case MLXPLAT_CPLD_LPC_REG_GP0_RO_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GPCOM0_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP1_RO_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP0_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP_RST_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP3_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FIELD_UPGRADE: + case MLXPLAT_CPLD_LPC_SAFE_BIOS_OFFSET: + case MLXPLAT_CPLD_LPC_SAFE_BIOS_WP_OFFSET: +@@ -6318,6 +7036,7 @@ 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_GPI_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: +@@ -6336,9 +7055,11 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_AC_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_ALERT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: + case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: +@@ -6489,6 +7210,15 @@ static const struct reg_default mlxplat_mlxcpld_regmap_eth_modular[] = { + MLXPLAT_CPLD_AGGR_MASK_LC_LOW }, + }; + ++static const struct reg_default mlxplat_mlxcpld_regmap_smart_switch[] = { ++ { 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 }, ++ { MLXPLAT_CPLD_LPC_REG_AGGRCX_MASK_OFFSET, ++ MLXPLAT_CPLD_LPC_SM_SW_MASK }, ++}; ++ + struct mlxplat_mlxcpld_regmap_context { + void __iomem *base; + }; +@@ -6597,6 +7327,20 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config_eth_modular = { + .reg_write = mlxplat_mlxcpld_reg_write, + }; + ++static const struct regmap_config mlxplat_mlxcpld_regmap_config_smart_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_smart_switch, ++ .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_smart_switch), ++ .reg_read = mlxplat_mlxcpld_reg_read, ++ .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) + { +@@ -6716,6 +7460,7 @@ static struct mlxreg_core_platform_data *mlxplat_regs_io; + static struct mlxreg_core_platform_data *mlxplat_fan; + static struct mlxreg_core_platform_data + *mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS]; ++static struct mlxreg_core_data *mlxplat_dpu_data[MLXPLAT_CPLD_DPU_MAX_DEVS]; + static const struct regmap_config *mlxplat_regmap_config; + static struct pci_dev *lpc_bridge; + static struct pci_dev *i2c_bridge; +@@ -7140,6 +7885,29 @@ static int __init mlxplat_dmi_xdr_matched(const struct dmi_system_id *dmi) + return mlxplat_register_platform_device(); + } + ++static int __init mlxplat_dmi_smart_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_ng800_mux_data); ++ mlxplat_mux_data = mlxplat_ng800_mux_data; ++ mlxplat_hotplug = &mlxplat_mlxcpld_smart_switch_data; ++ mlxplat_hotplug->deferred_nr = ++ mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; ++ mlxplat_led = &mlxplat_xdr_led_data; ++ mlxplat_regs_io = &mlxplat_smart_switch_regs_io_data; ++ mlxplat_fan = &mlxplat_xdr_fan_data; ++ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++) ++ mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i]; ++ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_smart_switch_dpu_data); i++) ++ mlxplat_dpu_data[i] = &mlxplat_mlxcpld_smart_switch_dpu_data[i]; ++ mlxplat_i2c = &mlxplat_mlxcpld_i2c_ng_data; ++ mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config_smart_switch; ++ ++ return mlxplat_register_platform_device(); ++} ++ + static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + { + .callback = mlxplat_dmi_default_wc_matched, +@@ -7246,6 +8014,12 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = { + DMI_MATCH(DMI_BOARD_NAME, "VMOD0018"), + }, + }, ++ { ++ .callback = mlxplat_dmi_smart_switch_matched, ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "VMOD0019"), ++ }, ++ }, + { + .callback = mlxplat_dmi_msn274x_matched, + .matches = { +@@ -7547,7 +8321,7 @@ static void mlxplat_post_exit(void) + + static int mlxplat_post_init(struct mlxplat_priv *priv) + { +- int i = 0, err; ++ int i, j, err; + + /* Add hotplug driver */ + if (mlxplat_hotplug) { +@@ -7624,8 +8398,25 @@ static int mlxplat_post_init(struct mlxplat_priv *priv) + } + } + ++ /* Add DPU drivers. */ ++ for (j = 0; j < MLXPLAT_CPLD_DPU_MAX_DEVS; j++) { ++ if (mlxplat_dpu_data[j]) { ++ priv->pdev_dpu[j] = ++ platform_device_register_resndata(&mlxplat_dev->dev, "mlxreg-dpu", ++ j, NULL, 0, mlxplat_dpu_data[j], ++ sizeof(*mlxplat_dpu_data[j])); ++ if (IS_ERR(priv->pdev_dpu[j])) { ++ err = PTR_ERR(priv->pdev_dpu[j]); ++ goto fail_platform_dpu_register; ++ } ++ } ++ } ++ + return 0; + ++fail_platform_dpu_register: ++ while (--j >= 0) ++ platform_device_unregister(priv->pdev_dpu[j]); + fail_platform_wd_register: + while (--i >= 0) + platform_device_unregister(priv->pdev_wd[i]); +@@ -7646,6 +8437,8 @@ static void mlxplat_pre_exit(struct mlxplat_priv *priv) + { + int i; + ++ for (i = MLXPLAT_CPLD_DPU_MAX_DEVS - 1; i >= 0 ; i--) ++ platform_device_unregister(priv->pdev_dpu[i]); + for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--) + platform_device_unregister(priv->pdev_wd[i]); + if (priv->pdev_fan) +-- +2.44.0 + diff --git a/patch/0094-i2c-asf-Introduce-MCTP-support-over-ASF-controller.patch b/patch/0094-i2c-asf-Introduce-MCTP-support-over-ASF-controller.patch new file mode 100644 index 000000000..454788c06 --- /dev/null +++ b/patch/0094-i2c-asf-Introduce-MCTP-support-over-ASF-controller.patch @@ -0,0 +1,994 @@ +From 4869f448e1c09fff47290505daa231aa5711b134 Mon Sep 17 00:00:00 2001 +From: amlakshm +Date: Tue, 30 Jan 2024 14:18:35 +0530 +Subject: [PATCH backport 6.1 1/1] i2c: asf: Introduce MCTP support over ASF + controller + +Provide driver for AMD ASF controller working as SMBus +master and slave. + +Signed-off-by: Sudheesh Mavila +Signed-off-by: Vadim Pasternak +--- + drivers/i2c/busses/Kconfig | 10 + + drivers/i2c/busses/Makefile | 1 + + drivers/i2c/busses/i2c-asf.c | 934 +++++++++++++++++++++++++++++++++++ + 3 files changed, 945 insertions(+) + create mode 100644 drivers/i2c/busses/i2c-asf.c + +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 9460528c0b1b..d861071755d2 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -95,6 +95,16 @@ config I2C_AMD_MP2 + This driver can also be built as modules. If so, the modules will + be called i2c-amd-mp2-pci and i2c-amd-mp2-plat. + ++config I2C_ASF ++ tristate "AMD ASF controller works as SMBus master and slave" ++ depends on PCI && ACPI ++ help ++ If you say yes to this option, support will be included for the ++ SMBus controller found in the AMD EPIC family. ++ ++ This driver can also be built as modules. If so, the modules will ++ be called i2c-asf. ++ + config I2C_HIX5HD2 + tristate "Hix5hd2 high-speed I2C driver" + depends on ARCH_HISI || ARCH_HIX5HD2 || COMPILE_TEST +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index e73cdb1d2b5a..3f4914c703c2 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -141,6 +141,7 @@ obj-$(CONFIG_I2C_VIPERBOARD) += i2c-viperboard.o + + # Other I2C/SMBus bus drivers + obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o ++obj-$(CONFIG_I2C_ASF) += i2c-asf.o + obj-$(CONFIG_I2C_BCM_KONA) += i2c-bcm-kona.o + obj-$(CONFIG_I2C_BRCMSTB) += i2c-brcmstb.o + obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += i2c-cros-ec-tunnel.o +diff --git a/drivers/i2c/busses/i2c-asf.c b/drivers/i2c/busses/i2c-asf.c +new file mode 100644 +index 000000000000..c3d8ce2b6027 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-asf.c +@@ -0,0 +1,934 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Copyright (c) 1998 - 2002 Frodo Looijaard and ++ * Philip Edelbrock ++ * Copyright (c) 2024 AMD Inc ++ */ ++ ++/* ++ * Supports: ++ * AMD E3K ++ * ++ * Note: we assume there can only be one device, with one or more ++ * SMBus interfaces. ++ * ++ * The driver is written by using i2c-piix4.c as reference. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ASF SMBus address offsets */ ++#define SMBHSTSTS (0 + asf_smba) ++#define SMBHSLVSTS (1 + asf_smba) ++#define SMBHSTCNT (2 + asf_smba) ++#define SMBHSTCMD (3 + asf_smba) ++#define SMBHSTADD (4 + asf_smba) ++#define SMBHSTDAT0 (5 + asf_smba) ++#define SMBHSTDAT1 (6 + asf_smba) ++#define SMBBLKDAT (7 + asf_smba) ++#define ASFINDEX (7 + asf_smba) ++#define ASFLISADDR (9 + asf_smba) ++#define ASFSTA (0xA + asf_smba) ++#define ASFSTAMASK (0xB + asf_smba) ++#define ASFSTAMASK1 (0xC + asf_smba) ++#define ASFSLVSTA (0xD + asf_smba) ++#define ASFDATARDPTR (0x10 + asf_smba) ++#define ASFDATARWPTR (0x11 + asf_smba) ++#define ASFSETDATARDPTR (0x12 + asf_smba) ++#define ASFDATABNKSEL (0x13 + asf_smba) ++#define ASFSLVEN (0x15 + asf_smba) ++ ++/* count for request_region */ ++#define SMBIOSIZE 9 ++ ++/* PCI Address Constants */ ++#define SMBBA 0x090 ++#define SMBHSTCFG 0x0D2 ++#define SMBSLVC 0x0D3 ++#define SMBSHDW1 0x0D4 ++#define SMBSHDW2 0x0D5 ++#define SMBREV 0x0D6 ++ ++/* Other settings */ ++#define MAX_TIMEOUT 500 ++#define ENABLE_INT9 0 ++ ++/* ASF constants */ ++#define ASF_QUICK 0x00 ++#define ASF_BYTE 0x04 ++#define ASF_BYTE_DATA 0x08 ++#define ASF_WORD_DATA 0x0C ++#define ASF_BLOCK_DATA 0x14 ++ ++/* Multi-port constants */ ++#define ASF_MAX_ADAPTERS 1 ++ ++/* SB800 constants */ ++#define SB800_ASF_SMB_IDX 0xcd6 ++#define SB800_ASF_SMB_MAP_SIZE 2 ++ ++#define KERNCZ_IMC_IDX 0x3e ++#define KERNCZ_IMC_DATA 0x3f ++ ++/* ++ * SB800 port is selected by bits 2:1 of the smb_en register (0x2c) ++ * or the smb_sel register (0x2e), depending on bit 0 of register 0x2f. ++ * Hudson-2/Bolton port is always selected by bits 2:1 of register 0x2f. ++ */ ++#define SB800_ASF_PORT_IDX 0x2c ++#define SB800_ASF_PORT_IDX_ALT 0x2e ++#define SB800_ASF_PORT_IDX_SEL 0x2f ++#define SB800_ASF_PORT_IDX_MASK 0x06 ++#define SB800_ASF_PORT_IDX_SHIFT 1 ++ ++/* On kerncz and Hudson2, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */ ++#define SB800_ASF_PORT_IDX_KERNCZ 0x02 ++#define SB800_ASF_PORT_IDX_MASK_KERNCZ 0x18 ++#define SB800_ASF_PORT_IDX_SHIFT_KERNCZ 3 ++ ++#define SB800_ASF_FCH_PM_ADDR 0xFED80300 ++#define SB800_ASF_FCH_PM_SIZE 8 ++ ++static struct pci_driver asf_driver; ++ ++/* ++ * SB800 globals ++ */ ++static u8 asf_port_sel_sb800; ++static u8 asf_port_mask_sb800; ++static u8 asf_port_shift_sb800; ++static const char *asf_main_port_names_sb800[ASF_MAX_ADAPTERS] = { ++ " port 0" ++}; ++ ++struct sb800_mmio_cfg { ++ void __iomem *addr; ++ bool use_mmio; ++}; ++ ++struct i2c_asf_adapdata { ++ unsigned short smba; ++ u8 port; /* Port number, shifted */ ++ struct sb800_mmio_cfg mmio_cfg; ++ struct timer_list slave_timer; ++ struct i2c_client *slave; ++}; ++ ++static spinlock_t asf_spinlock; ++static void __iomem *asf_scl_muxbase; ++static void __iomem *asf_sda_muxbase; ++ ++/* ++ * This gets called whenever an I2C slave interrupt/status change ++ * occurs. ++ */ ++static int asf_slave_process(struct i2c_asf_adapdata *adapdata) ++{ ++ u8 data[72], val = 0, cmd, reg_datab_sel, reg_sta, count; ++ int nextdatabank, databank0status, databank1status; ++ unsigned short asf_smba = adapdata->smba; ++ unsigned long flags; ++ int i = 0; ++ ++ spin_lock_irqsave(&asf_spinlock, flags); ++ reg_sta = inb_p(ASFSTA); ++ if ((reg_sta & 0x40) == 0) { ++ spin_unlock_irqrestore(&asf_spinlock, flags); ++ return 0; ++ } ++ outb_p(reg_sta | 0x40, ASFSTA); ++ ++ while (inb_p(ASFSTA) & 0x80); ++ ++ reg_datab_sel = inb_p(ASFDATABNKSEL); ++ databank0status = (reg_datab_sel & BIT(2)) >> 2; ++ databank1status = (reg_datab_sel & BIT(3)) >> 3; ++ ++ if (databank0status || databank1status) { ++ reg_sta = inb_p(ASFSLVSTA); ++ if (!(reg_sta & 0xE)) { ++ /* no error */ ++ if ((databank0status == 0 && databank1status == 1) || ++ (databank0status == 1 && databank1status == 0)) { ++ if (databank1status == 1) { ++ reg_datab_sel = reg_datab_sel | BIT(4); ++ reg_datab_sel = reg_datab_sel & ~BIT(3); ++ outb_p(reg_datab_sel, ASFDATABNKSEL); ++ while(!(inb_p(ASFDATABNKSEL) & 0x10)); ++ ++ cmd = inb_p(ASFINDEX); ++ count = inb_p(0x11 + asf_smba); ++ for (i = 0; i < count; i++) ++ data[i] = inb_p(ASFINDEX); ++ reg_datab_sel = reg_datab_sel | BIT(3); ++ outb_p(reg_datab_sel, ASFDATABNKSEL); ++ } else { ++ reg_datab_sel = reg_datab_sel & ~BIT(4); ++ reg_datab_sel = reg_datab_sel & ~BIT(2); ++ outb_p(reg_datab_sel, ASFDATABNKSEL); ++ while((inb_p(ASFDATABNKSEL) & 0x10)); ++ ++ cmd = inb_p(ASFINDEX); ++ count = inb_p(0x11 + asf_smba); ++ for (i = 0; i < count; i++) ++ data[i] = inb_p(ASFINDEX); ++ reg_datab_sel = reg_datab_sel | BIT(2); ++ outb_p(reg_datab_sel, ASFDATABNKSEL); ++ } ++ } else if (((databank0status == 1) && (databank1status == 1))) { ++ nextdatabank = reg_datab_sel & 1; ++ if (!nextdatabank) { ++ reg_datab_sel = reg_datab_sel & ~BIT(4); ++ reg_datab_sel = reg_datab_sel & ~BIT(2); ++ outb_p(reg_datab_sel, ASFDATABNKSEL); ++ ++ reg_datab_sel = reg_datab_sel | BIT(2); ++ outb_p(reg_datab_sel, ASFDATABNKSEL); ++ } else { ++ reg_datab_sel = reg_datab_sel | BIT(4); ++ reg_datab_sel = reg_datab_sel & ~BIT(3); ++ outb_p(reg_datab_sel, ASFDATABNKSEL); ++ ++ reg_datab_sel = reg_datab_sel | BIT(3); ++ outb_p(reg_datab_sel, ASFDATABNKSEL); ++ } ++ } ++ } else { ++ reg_datab_sel = reg_datab_sel | (BIT(3) | BIT(2)); ++ outb_p(reg_datab_sel, ASFDATABNKSEL); ++ outb_p(0xF, ASFSLVSTA); ++ } ++ } ++ outb_p(0, 0x12 + asf_smba); ++ outb_p(0xF, ASFSLVSTA); ++ spin_unlock_irqrestore(&asf_spinlock, flags); ++ ++ if ((cmd & 1) == 0) { ++ i2c_slave_event(adapdata->slave, I2C_SLAVE_WRITE_REQUESTED, &val); ++ for (i = 0; i < count; i++) { ++ val = data[i]; ++ i2c_slave_event(adapdata->slave, I2C_SLAVE_WRITE_RECEIVED, &val); ++ } ++ i2c_slave_event(adapdata->slave, I2C_SLAVE_STOP, &val); ++ } ++ return 0; ++} ++ ++static void slave_event_timer(struct timer_list *t) ++{ ++ struct i2c_asf_adapdata *adapdata = from_timer(adapdata, t, slave_timer); ++ ++ asf_slave_process(adapdata); ++ ++ mod_timer(&adapdata->slave_timer, jiffies + msecs_to_jiffies(100)); ++} ++ ++static int asf_sb800_region_request(struct device *dev, ++ struct sb800_mmio_cfg *mmio_cfg) ++{ ++ if (mmio_cfg->use_mmio) { ++ void __iomem *addr; ++ ++ if (!request_mem_region_muxed(SB800_ASF_FCH_PM_ADDR, ++ SB800_ASF_FCH_PM_SIZE, ++ "sb800_asf_smb")) { ++ dev_err(dev, ++ "SMBus base address memory region 0x%x already in use.\n", ++ SB800_ASF_FCH_PM_ADDR); ++ return -EBUSY; ++ } ++ ++ addr = ioremap(SB800_ASF_FCH_PM_ADDR, ++ SB800_ASF_FCH_PM_SIZE); ++ if (!addr) { ++ release_mem_region(SB800_ASF_FCH_PM_ADDR, ++ SB800_ASF_FCH_PM_SIZE); ++ dev_err(dev, "SMBus base address mapping failed.\n"); ++ return -ENOMEM; ++ } ++ ++ mmio_cfg->addr = addr; ++ ++ return 0; ++ } ++ ++ if (!request_muxed_region(SB800_ASF_SMB_IDX, SB800_ASF_SMB_MAP_SIZE, ++ "sb800_asf_smb")) { ++ dev_err(dev, ++ "SMBus base address index region 0x%x already in use.\n", ++ SB800_ASF_SMB_IDX); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static void asf_sb800_region_release(struct device *dev, ++ struct sb800_mmio_cfg *mmio_cfg) ++{ ++ if (mmio_cfg->use_mmio) { ++ iounmap(mmio_cfg->addr); ++ release_mem_region(SB800_ASF_FCH_PM_ADDR, ++ SB800_ASF_FCH_PM_SIZE); ++ return; ++ } ++ ++ release_region(SB800_ASF_SMB_IDX, SB800_ASF_SMB_MAP_SIZE); ++} ++ ++static bool asf_sb800_use_mmio(struct pci_dev *ASF_dev) ++{ ++ /* ++ * cd6h/cd7h port I/O accesses can be disabled on AMD processors ++ * w/ SMBus PCI revision ID 0x51 or greater. MMIO is supported on ++ * the same processors and is the recommended access method. ++ */ ++ return (ASF_dev->vendor == PCI_VENDOR_ID_AMD && ++ ASF_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS && ++ ASF_dev->revision >= 0x51); ++} ++ ++static int ++asf_setup_sb800_smba(struct pci_dev *ASF_dev, u8 smb_en, u8 aux, u8 *smb_en_status, ++ unsigned short *asf_smba) ++{ ++ struct sb800_mmio_cfg mmio_cfg; ++ u8 smba_en_lo, smba_en_hi; ++ int reg, retval; ++ ++ asf_scl_muxbase = ioremap(0xFED80D13, 1); ++ iowrite8(0, asf_scl_muxbase); ++ asf_sda_muxbase = ioremap(0xFED80D14, 1); ++ iowrite8(0, asf_sda_muxbase); ++ ++ mmio_cfg.use_mmio = asf_sb800_use_mmio(ASF_dev); ++ retval = asf_sb800_region_request(&ASF_dev->dev, &mmio_cfg); ++ if (retval) ++ return retval; ++ ++ if (mmio_cfg.use_mmio) { ++ smba_en_lo = ioread8(mmio_cfg.addr); ++ smba_en_hi = ioread8(mmio_cfg.addr + 1); ++ } ++ ++ reg = ioread32(mmio_cfg.addr); ++ reg = reg | BIT(16); ++ iowrite32(reg, mmio_cfg.addr); ++ ++ asf_sb800_region_release(&ASF_dev->dev, &mmio_cfg); ++ ++ *smb_en_status = smba_en_lo & 0x10; ++ *asf_smba = smba_en_hi << 8; ++ ++ if (!*smb_en_status) { ++ dev_err(&ASF_dev->dev, "SMBus Host Controller not enabled!\n"); ++ return -ENODEV; ++ } ++ ++ *asf_smba |= 0x20; ++ ++ return 0; ++} ++ ++static int asf_setup_sb800(struct pci_dev *ASF_dev, const struct pci_device_id *id, u8 aux) ++{ ++ u8 i2ccfg_offset = 0x10, i2ccfg, smb_en, smb_en_status; ++ unsigned short asf_smba; ++ int retval; ++ ++ /* Determine the address of the SMBus areas */ ++ if ((ASF_dev->vendor == PCI_VENDOR_ID_AMD && ++ ASF_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS && ASF_dev->revision >= 0x41) || ++ (ASF_dev->vendor == PCI_VENDOR_ID_AMD && ++ ASF_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS && ASF_dev->revision >= 0x49) || ++ (ASF_dev->vendor == PCI_VENDOR_ID_HYGON && ++ ASF_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS)) ++ smb_en = 0x00; ++ else ++ return -1; ++ ++ retval = asf_setup_sb800_smba(ASF_dev, smb_en, aux, &smb_en_status, &asf_smba); ++ ++ if (retval) ++ return retval; ++ ++ if (acpi_check_region(asf_smba, SMBIOSIZE, asf_driver.name)) ++ return -ENODEV; ++ ++ if (!request_region(asf_smba, SMBIOSIZE, asf_driver.name)) { ++ dev_err(&ASF_dev->dev, "SMBus region 0x%x already in use!\n", asf_smba); ++ return -EBUSY; ++ } ++ ++ /* Request the SMBus I2C bus config region */ ++ if (!request_region(asf_smba + i2ccfg_offset, 1, "i2ccfg")) { ++ dev_err(&ASF_dev->dev, "SMBus I2C bus config region 0x%x already in use!\n", ++ asf_smba + i2ccfg_offset); ++ release_region(asf_smba, SMBIOSIZE); ++ return -EBUSY; ++ } ++ i2ccfg = inb_p(asf_smba + i2ccfg_offset); ++ ++ release_region(asf_smba + i2ccfg_offset, 1); ++ ++ if (i2ccfg & 1) ++ dev_dbg(&ASF_dev->dev, "Using IRQ for SMBus\n"); ++ else ++ dev_dbg(&ASF_dev->dev, "Using SMI# for SMBus\n"); ++ ++ dev_info(&ASF_dev->dev, "SMBus Host Controller at 0x%x, revision %d\n", ++ asf_smba, i2ccfg >> 4); ++ ++ /* Find which register is used for port selection */ ++ if (ASF_dev->vendor == PCI_VENDOR_ID_AMD || ++ ASF_dev->vendor == PCI_VENDOR_ID_HYGON) { ++ if (ASF_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS || ++ (ASF_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS && ++ ASF_dev->revision >= 0x1F)) { ++ asf_port_sel_sb800 = SB800_ASF_PORT_IDX_KERNCZ; ++ asf_port_mask_sb800 = SB800_ASF_PORT_IDX_MASK_KERNCZ; ++ asf_port_shift_sb800 = SB800_ASF_PORT_IDX_SHIFT_KERNCZ; ++ } else { ++ asf_port_sel_sb800 = SB800_ASF_PORT_IDX_ALT; ++ asf_port_mask_sb800 = SB800_ASF_PORT_IDX_MASK; ++ asf_port_shift_sb800 = SB800_ASF_PORT_IDX_SHIFT; ++ } ++ } ++ dev_info(&ASF_dev->dev, "Using register 0x%02x for SMBus port selection\n", ++ (unsigned int)asf_port_sel_sb800); ++ release_region(asf_smba, SMBIOSIZE); ++ return asf_smba; ++} ++ ++static int asf_transaction(struct i2c_adapter *asf_adapter) ++{ ++ struct i2c_asf_adapdata *adapdata = i2c_get_adapdata(asf_adapter); ++ unsigned short asf_smba = adapdata->smba; ++ int result = 0, timeout = 0, temp; ++ ++ dev_dbg(&asf_adapter->dev, "Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", ++ inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), ++ inb_p(SMBHSTDAT1)); ++ ++ /* Make sure the SMBus host is ready to start transmitting */ ++ temp = inb_p(SMBHSTSTS); ++ if (temp) { ++ dev_dbg(&asf_adapter->dev, "SMBus busy (%02x). Resetting...\n", temp); ++ outb_p(temp, SMBHSTSTS); ++ temp = inb_p(SMBHSTSTS); ++ if (temp) { ++ dev_err(&asf_adapter->dev, "Failed! (%02x)\n", temp); ++ return -EBUSY; ++ } ++ dev_dbg(&asf_adapter->dev, "Successful!\n"); ++ } ++ ++ /* start the transaction by setting bit 6 */ ++ outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); ++ ++ /* We will always wait for a fraction of a second! (See ASF docs errata) */ ++ udelay(250); ++ ++ while ((++timeout < MAX_TIMEOUT) && ++ ((temp = inb_p(SMBHSTSTS)) & 0x01)) ++ udelay(250); ++ ++ /* If the SMBus is still busy, we give up */ ++ if (timeout == MAX_TIMEOUT) { ++ dev_err(&asf_adapter->dev, "SMBus Timeout!\n"); ++ result = -ETIMEDOUT; ++ } ++ ++ if (temp & 0x10) { ++ result = -EIO; ++ dev_err(&asf_adapter->dev, "Error: Failed bus transaction\n"); ++ } ++ ++ if (temp & 0x08) { ++ /* Clock stops and slave is stuck in mid-transmission */ ++ result = -EIO; ++ dev_dbg(&asf_adapter->dev, "Bus collision! SMBus may be locked until next hard reset.\n"); ++ } ++ ++ if (temp & 0x04) { ++ result = -ENXIO; ++ dev_dbg(&asf_adapter->dev, "Error: no response!\n"); ++ } ++ ++ if (inb_p(SMBHSTSTS) != 0x00) ++ outb_p(inb(SMBHSTSTS), SMBHSTSTS); ++ ++ temp = inb_p(SMBHSTSTS); ++ if (temp) ++ dev_err(&asf_adapter->dev, "Failed reset at end of transaction (%02x)\n", temp); ++ dev_dbg(&asf_adapter->dev, "Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", ++ inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), ++ inb_p(SMBHSTDAT1)); ++ return result; ++} ++ ++/* Return negative errno on error. */ ++static s32 ++asf_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, ++ int size, union i2c_smbus_data *data) ++{ ++ struct i2c_asf_adapdata *adapdata = i2c_get_adapdata(adap); ++ unsigned short asf_smba = adapdata->smba; ++ int i, len; ++ int status; ++ ++ switch (size) { ++ case I2C_SMBUS_QUICK: ++ outb_p((addr << 1) | read_write, ++ SMBHSTADD); ++ size = ASF_QUICK; ++ break; ++ case I2C_SMBUS_BYTE: ++ outb_p((addr << 1) | read_write, ++ SMBHSTADD); ++ if (read_write == I2C_SMBUS_WRITE) ++ outb_p(command, SMBHSTCMD); ++ size = ASF_BYTE; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ outb_p((addr << 1) | read_write, ++ SMBHSTADD); ++ outb_p(command, SMBHSTCMD); ++ if (read_write == I2C_SMBUS_WRITE) ++ outb_p(data->byte, SMBHSTDAT0); ++ size = ASF_BYTE_DATA; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ outb_p((addr << 1) | read_write, ++ SMBHSTADD); ++ outb_p(command, SMBHSTCMD); ++ if (read_write == I2C_SMBUS_WRITE) { ++ outb_p(data->word & 0xff, SMBHSTDAT0); ++ outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); ++ } ++ size = ASF_WORD_DATA; ++ break; ++ case I2C_SMBUS_BLOCK_DATA: ++ outb_p((addr << 1) | read_write, ++ SMBHSTADD); ++ outb_p(command, SMBHSTCMD); ++ if (read_write == I2C_SMBUS_WRITE) { ++ len = data->block[0]; ++ if (len == 0 || len > 70) ++ return -EINVAL; ++ outb_p(len, SMBHSTDAT0); ++ inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ ++ for (i = 1; i <= len; i++) ++ outb_p(data->block[i], SMBBLKDAT); ++ } ++ size = ASF_BLOCK_DATA; ++ break; ++ default: ++ dev_warn(&adap->dev, "Unsupported transaction %d\n", size); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Enable PEC and PEC append */ ++ outb_p(((size & 0x1C) + (ENABLE_INT9 & 1)) | (BIT(7)) | (BIT(5)), SMBHSTCNT); ++ ++ status = asf_transaction(adap); ++ if (status) ++ return status; ++ ++ if (read_write == I2C_SMBUS_WRITE || size == ASF_QUICK) ++ return 0; ++ ++ switch (size) { ++ case ASF_BYTE: ++ case ASF_BYTE_DATA: ++ data->byte = inb_p(SMBHSTDAT0); ++ break; ++ case ASF_WORD_DATA: ++ data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); ++ break; ++ case ASF_BLOCK_DATA: ++ data->block[0] = inb_p(SMBHSTDAT0); ++ if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX) ++ return -EPROTO; ++ inb_p(SMBHSTCNT); ++ /* Reset SMBBLKDAT */ ++ for (i = 1; i <= data->block[0]; i++) ++ data->block[i] = inb_p(SMBBLKDAT); ++ break; ++ } ++ return 0; ++} ++ ++static int asf_sb800_port_sel(u8 port, struct sb800_mmio_cfg *mmio_cfg) ++{ ++ u8 smba_en_lo, val; ++ ++ if (mmio_cfg->use_mmio) { ++ smba_en_lo = ioread8(mmio_cfg->addr + asf_port_sel_sb800); ++ val = (smba_en_lo & ~asf_port_mask_sb800) | port; ++ if (smba_en_lo != val) ++ iowrite8(val, mmio_cfg->addr + asf_port_sel_sb800); ++ ++ return (smba_en_lo & asf_port_mask_sb800); ++ } ++ ++ outb_p(asf_port_sel_sb800, SB800_ASF_SMB_IDX); ++ smba_en_lo = inb_p(SB800_ASF_SMB_IDX + 1); ++ ++ val = (smba_en_lo & ~asf_port_mask_sb800) | port; ++ if (smba_en_lo != val) ++ outb_p(val, SB800_ASF_SMB_IDX + 1); ++ ++ return (smba_en_lo & asf_port_mask_sb800); ++} ++ ++/* ++ * Handles access to multiple SMBus ports on the SB800. ++ * The port is selected by bits 2:1 of the smb_en register (0x2c). ++ * Returns negative errno on error. ++ * ++ * Note: The selected port must be returned to the initial selection to avoid ++ * problems on certain systems. ++ */ ++static s32 ++asf_access_sb800(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, ++ u8 command, int size, union i2c_smbus_data *data) ++{ ++ struct i2c_asf_adapdata *adapdata = i2c_get_adapdata(adap); ++ unsigned short asf_smba = adapdata->smba; ++ unsigned long lock_flags; ++ int reg, retval; ++ u8 prev_port; ++ ++ retval = asf_sb800_region_request(&adap->dev, &adapdata->mmio_cfg); ++ if (retval) ++ return retval; ++ ++ spin_lock_irqsave(&asf_spinlock, lock_flags); ++ reg = inb_p(ASFSLVEN); ++ reg = reg | (BIT(4)); ++ outb_p(reg, ASFSLVEN); ++ outb_p(0, SMBHSTCMD); ++ outb_p(0, SMBHSTDAT0); ++ outb_p(0, SMBHSTDAT1); ++ outb_p(0, ASFSLVSTA); ++ reg = ioread32(adapdata->mmio_cfg.addr); ++ reg = reg | BIT(16); ++ iowrite32(reg, adapdata->mmio_cfg.addr); ++ prev_port = asf_sb800_port_sel(adapdata->port, &adapdata->mmio_cfg); ++ retval = asf_access(adap, addr, flags, read_write, command, size, data); ++ asf_sb800_port_sel(prev_port, &adapdata->mmio_cfg); ++ ++ /* set asf as slave */ ++ outb_p(0, SMBHSTSTS); ++ outb_p(0, ASFSLVSTA); ++ outb_p(0, ASFSTA); ++ reg = ioread32(adapdata->mmio_cfg.addr); ++ reg = reg & ~BIT(16); ++ reg = reg | BIT(17); ++ iowrite32(reg, adapdata->mmio_cfg.addr); ++ reg = inb(ASFSLVEN); ++ reg = reg & ~BIT(4); ++ outb_p(reg, ASFSLVEN); ++ /* Enable PEC and PEC append */ ++ reg = inb(SMBHSTCNT); ++ reg = reg | BIT(7) | BIT(5); ++ outb_p(reg, SMBHSTCNT); ++ spin_unlock_irqrestore(&asf_spinlock, lock_flags); ++ asf_sb800_region_release(&adap->dev, &adapdata->mmio_cfg); ++ ++ return retval; ++} ++ ++static int asf_access_i2c(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ++{ ++ unsigned short flags = 0; ++ struct i2c_msg *msg; ++ char read_write; ++ int size, ret; ++ u8 command; ++ u16 addr; ++ union i2c_mctp_data { ++ __u8 byte; ++ __u16 word; ++ __u8 block[72 + 2]; /* block[0] is used for length */ ++ } smbus_data; ++ ++ msg = &msgs[0]; ++ if (msgs->flags & I2C_M_RD) { ++ dev_err(&adap->dev, "Read not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (num != 1) { ++ dev_err(&adap->dev, "multiple i2c messages not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (msg->len - 1 > 72) { ++ dev_err(&adap->dev, "max mtu is 68\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ addr = msg->addr; ++ read_write = 0; ++ command = msg[0].buf[0]; ++ size = I2C_SMBUS_BLOCK_DATA; ++ smbus_data.block[0] = msg->len - 1; ++ memcpy(smbus_data.block + 1, msg[0].buf + 1, msg->len - 1); ++ ret = asf_access_sb800(adap, addr, flags, read_write, command, size, ++ (union i2c_smbus_data *)&smbus_data); ++ return ret; ++} ++ ++static int asf_reg_slave(struct i2c_client *slave) ++{ ++ struct i2c_asf_adapdata *adapdata = i2c_get_adapdata(slave->adapter); ++ unsigned short asf_smba = adapdata->smba; ++ int retval, config_reg; ++ unsigned long flags; ++ u8 reg; ++ ++ if (adapdata->slave) ++ return -EBUSY; ++ ++ retval = asf_sb800_region_request(&slave->dev, &adapdata->mmio_cfg); ++ if (retval) ++ return retval; ++ ++ spin_lock_irqsave(&asf_spinlock, flags); ++ ++ reg = (slave->addr << 1) | 1; ++ outb_p(reg, ASFLISADDR); ++ outb_p(0, SMBHSTSTS); ++ outb_p(0, ASFSLVSTA); ++ outb_p(0, ASFSTA); ++ reg = inb_p(ASFSLVEN); ++ reg = reg | BIT(1) | BIT(4); ++ outb_p(reg, ASFSLVEN); ++ reg = reg & ~BIT(4); ++ outb_p(reg, ASFSLVEN); ++ adapdata->slave = slave; ++ reg = inb_p(SMBHSTCNT); ++ reg = reg | BIT(7) | BIT(5); ++ outb_p(reg, SMBHSTCNT); ++ reg = inb_p(ASFDATABNKSEL); ++ reg = reg & ~BIT(7); ++ outb_p(reg, ASFDATABNKSEL); ++ ++ config_reg = ioread32(adapdata->mmio_cfg.addr); ++ config_reg = config_reg & (~BIT(16)); ++ config_reg = config_reg | (BIT(17)); ++ iowrite32(config_reg, adapdata->mmio_cfg.addr); ++ spin_unlock_irqrestore(&asf_spinlock, flags); ++ asf_sb800_region_release(&slave->dev, &adapdata->mmio_cfg); ++ ++ timer_setup(&adapdata->slave_timer, slave_event_timer, 0); ++ mod_timer(&adapdata->slave_timer, jiffies + HZ); ++ ++ return 0; ++} ++ ++static int asf_unreg_slave(struct i2c_client *slave) ++{ ++ struct i2c_asf_adapdata *adapdata = i2c_get_adapdata(slave->adapter); ++ unsigned short asf_smba = adapdata->smba; ++ u8 reg; ++ ++ reg = inb(ASFSLVEN); ++ reg &= ~BIT(1); ++ reg = reg | BIT(4); ++ outb_p(reg, ASFSLVEN); ++ ++ adapdata->slave = NULL; ++ del_timer_sync(&adapdata->slave_timer); ++ return 0; ++} ++ ++static u32 asf_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SLAVE | I2C_FUNC_SMBUS_PEC | ++ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA; ++} ++ ++static const struct i2c_algorithm asf_smbus_algorithm_sb800 = { ++ .smbus_xfer = asf_access_sb800, ++ .master_xfer = asf_access_i2c, ++ .functionality = asf_func, ++ .reg_slave = asf_reg_slave, ++ .unreg_slave = asf_unreg_slave, ++}; ++ ++static const struct pci_device_id asf_ids[] = { ++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) }, ++ { 0, } ++}; ++ ++MODULE_DEVICE_TABLE(pci, asf_ids); ++ ++static struct i2c_adapter *asf_main_adapters[ASF_MAX_ADAPTERS]; ++static struct i2c_adapter *asf_aux_adapter; ++static int asf_adapter_count; ++ ++static int ++asf_add_adapter(struct pci_dev *dev, unsigned short smba, u8 port, u8 hw_port_nr, const char *name, ++ struct i2c_adapter **padap) ++{ ++ struct i2c_asf_adapdata *adapdata; ++ struct i2c_adapter *adap; ++ int retval; ++ ++ adap = kzalloc(sizeof(*adap), GFP_KERNEL); ++ if (!adap) { ++ release_region(smba, SMBIOSIZE); ++ return -ENOMEM; ++ } ++ ++ adap->owner = THIS_MODULE; ++ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ adap->algo = &asf_smbus_algorithm_sb800; ++ ++ adapdata = kzalloc(sizeof(*adapdata), GFP_KERNEL); ++ if (!adapdata) { ++ kfree(adap); ++ release_region(smba, SMBIOSIZE); ++ return -ENOMEM; ++ } ++ ++ adapdata->mmio_cfg.use_mmio = asf_sb800_use_mmio(dev); ++ adapdata->smba = smba; ++ adapdata->port = port << asf_port_shift_sb800; ++ ++ /* set up the sysfs linkage to our parent device */ ++ adap->dev.parent = &dev->dev; ++ ++ if (has_acpi_companion(&dev->dev)) { ++ acpi_preset_companion(&adap->dev, ++ ACPI_COMPANION(&dev->dev), ++ hw_port_nr); ++ } ++ ++ snprintf(adap->name, sizeof(adap->name), "SMBus ASF adapter%s at %04x", name, smba); ++ i2c_set_adapdata(adap, adapdata); ++ retval = i2c_add_adapter(adap); ++ if (retval) { ++ kfree(adapdata); ++ kfree(adap); ++ release_region(smba, SMBIOSIZE); ++ return retval; ++ } ++ ++ *padap = adap; ++ return 0; ++} ++ ++static int asf_add_adapters_sb800(struct pci_dev *dev, unsigned short smba) ++{ ++ struct i2c_asf_adapdata *adapdata; ++ int port; ++ int retval; ++ ++ asf_adapter_count = ASF_MAX_ADAPTERS; ++ ++ for (port = 0; port < asf_adapter_count; port++) { ++ u8 hw_port_nr = port == 0 ? 0 : port + 1; ++ ++ retval = asf_add_adapter(dev, smba, port, hw_port_nr, ++ asf_main_port_names_sb800[port], ++ &asf_main_adapters[port]); ++ if (retval < 0) ++ goto error; ++ } ++ ++ return retval; ++ ++error: ++ dev_err(&dev->dev, "Error setting up SB800 adapters. Unregistering!\n"); ++ while (--port >= 0) { ++ adapdata = i2c_get_adapdata(asf_main_adapters[port]); ++ if (adapdata->smba) { ++ i2c_del_adapter(asf_main_adapters[port]); ++ kfree(adapdata); ++ kfree(asf_main_adapters[port]); ++ asf_main_adapters[port] = NULL; ++ } ++ } ++ ++ return retval; ++} ++ ++static int asf_probe(struct pci_dev *dev, const struct pci_device_id *id) ++{ ++ int retval; ++ ++ if ((dev->vendor == PCI_VENDOR_ID_ATI && dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && ++ dev->revision >= 0x40) || dev->vendor == PCI_VENDOR_ID_AMD) { ++ spin_lock_init(&asf_spinlock); ++ retval = asf_setup_sb800(dev, id, 0); ++ if (retval < 0) ++ return retval; ++ retval = asf_add_adapters_sb800(dev, retval); ++ if (retval < 0) ++ return retval; ++ } ++ ++ return 0; ++} ++ ++static void asf_adap_remove(struct i2c_adapter *adap) ++{ ++ struct i2c_asf_adapdata *adapdata = i2c_get_adapdata(adap); ++ ++ del_timer_sync(&adapdata->slave_timer); ++ ++ if (adapdata->smba) { ++ i2c_del_adapter(adap); ++ if (adapdata->port == (0 << asf_port_shift_sb800)) ++ release_region(adapdata->smba, SMBIOSIZE); ++ kfree(adapdata); ++ kfree(adap); ++ } ++} ++ ++static void asf_remove(struct pci_dev *dev) ++{ ++ int port = asf_adapter_count; ++ ++ while (--port >= 0) { ++ if (asf_main_adapters[port]) { ++ asf_adap_remove(asf_main_adapters[port]); ++ asf_main_adapters[port] = NULL; ++ } ++ } ++ ++ if (asf_aux_adapter) { ++ asf_adap_remove(asf_aux_adapter); ++ asf_aux_adapter = NULL; ++ } ++} ++ ++static struct pci_driver asf_driver = { ++ .name = "asf_smbus", ++ .id_table = asf_ids, ++ .probe = asf_probe, ++ .remove = asf_remove, ++}; ++ ++module_pci_driver(asf_driver); ++ ++MODULE_AUTHOR("dl.amdindia.embedded.ps.linux.all@amd.com"); ++MODULE_DESCRIPTION("ASF SMBus driver"); ++MODULE_LICENSE("GPL"); +-- +2.20.1 + diff --git a/patch/kconfig-inclusions b/patch/kconfig-inclusions index 31240d7fb..e1e471805 100644 --- a/patch/kconfig-inclusions +++ b/patch/kconfig-inclusions @@ -35,6 +35,7 @@ CONFIG_SENSORS_MAX31790=m CONFIG_EEPROM_OPTOE=m ###-> mellanox_amd64-start CONFIG_X86_AMD_PLATFORM_DEVICE=y +CONFIG_MCTP=y CONFIG_DMI_SYSFS=y CONFIG_OF=y CONFIG_EEPROM_AT24=m @@ -49,6 +50,7 @@ CONFIG_I2C_SMBUS=m CONFIG_I2C_I801=m CONFIG_I2C_DESIGNWARE_PCI=m CONFIG_I2C_MLXCPLD=m +CONFIG_I2C_SLAVE=y CONFIG_PINCTRL=y CONFIG_GPIOLIB=y CONFIG_SENSORS_K10TEMP=m @@ -85,15 +87,16 @@ CONFIG_MLXREG_HOTPLUG=m CONFIG_MLXREG_IO=m CONFIG_MLX_WDT=m CONFIG_MLXREG_LC=m +CONFIG_MLXREG_DPU=m CONFIG_SENSORS_MLXREG_FAN=m CONFIG_GPIO_GENERIC=m CONFIG_MAX1363=m CONFIG_SENSORS_TPS53679=m CONFIG_SENSORS_XDPE122=m CONFIG_SENSORS_MP2975=m -#CONFIG_SENSORS_MP2855=m +CONFIG_SENSORS_MP2855=m CONFIG_SENSORS_MP2888=m -#CONFIG_SENSORS_MP2891=m +CONFIG_SENSORS_MP2891=m CONFIG_CPU_THERMAL=y CONFIG_IGB_HWMON=y CONFIG_MFD_CORE=y @@ -113,6 +116,10 @@ CONFIG_SENSORS_LM25066=m CONFIG_SENSORS_UCD9000=m CONFIG_SENSORS_UCD9200=m CONFIG_THERMAL_OF=y +CONFIG_MCTP_FLOWS=y +CONFIG_MCTP_TRANSPORT_I2C=m +CONFIG_I2C_SLAVE_EEPROM=m +CONFIG_I2C_ASF=m CONFIG_SPI_AMD=m CONFIG_PINCTRL_AMD=y CONFIG_EDAC_AMD64=m diff --git a/patch/series b/patch/series index c7f0067cd..b3bbe5570 100755 --- a/patch/series +++ b/patch/series @@ -75,79 +75,79 @@ Support-for-fullcone-nat.patch ###-> mellanox_sdk-end ###-> mellanox_hw_mgmt-start -#0001-platform-mellanox-Introduce-support-for-rack-manager.patch -#0002-platform-mellanox-Change-reset_pwr_converter_fail-at.patch -#0003-platform-mellanox-Cosmetic-changes-rename-to-more-co.patch -#0004-platform-mellanox-Introduce-support-for-next-generat.patch -#0005-platform-mellanox-Introduce-support-of-new-Nvidia-L1.patch -#0006-platform-mellanox-Split-initialization-procedure.patch -#0007-platform-mellanox-Split-logic-in-init-and-exit-flow.patch -#0008-platform-mellanox-Extend-all-systems-with-I2C-notifi.patch -#0009-platform-mellanox-mlx-platform-Add-mux-selection-reg.patch -#0010-platform-mellanox-mlx-platform-Move-bus-shift-assign.patch -#0011-platform-mellanox-mlx-platform-Initialize-shift-vari.patch -#0012-platform-mellanox-Fix-order-in-exit-flow.patch -#0013-platform-mellanox-mlx-platform-Fix-signals-polarity-.patch -#0014-platform-mellanox-mlx-platform-Modify-graceful-shutd.patch -#0015-platform-mellanox-Change-register-offset-addresses.patch -#0016-platform-mellanox-Add-new-attributes.patch -#0017-platform-mellanox-Add-field-upgrade-capability-regis.patch -#0018-platform-mellanox-Modify-reset-causes-description.patch -#0019-platform-mellanox-mlx-platform-Modify-health-and-pow.patch -#0020-platform-mellanox-mlx-platform-Add-reset-cause-attri.patch -#0021-platform-mellanox-mlx-platform-add-support-for-addit.patch -#0022-platform-mellanox-mlx-platform-Modify-power-off-call.patch -#0023-platform-mellanox-Cosmetic-changes.patch -#0024-platform-mellanox-mlx-platform-Add-reset-callback.patch -#0025-platform-mellanox-mlx-platform-Prepare-driver-to-all.patch -#0026-platform-mellanox-mlx-platform-Introduce-ACPI-init-f.patch -#0027-platform-mellanox-mlx-platform-Get-interrupt-line-th.patch -#0028-platform-mellanox-Add-initial-support-for-PCIe-based.patch -#0029-platform-mellanox-mlxreg-hotplug-Extend-condition-fo.patch -#0030-platform-mellanox-nvsw-sn2201-change-fans-i2c-busses.patch -#0032-platform_data-mlxreg-Add-field-with-mapped-resource-.patch -#0033-i2c-mlxcpld-Allow-driver-to-run-on-ARM64-architectur.patch -#0034-i2c-mlxcpld-Add-support-for-extended-transaction-len.patch -#0035-i2c-mlxcpld-Support-PCIe-mapped-register-space.patch -#0036-mlxsw-i2c-Fix-chunk-size-setting-in-output-mailbox-b.patch -#0037-mlxsw-i2c-Limit-single-transaction-buffer-size.patch -#0038-mlxsw-core_hwmon-Adjust-module-label-names-based-on-.patch -#0039-mlxsw-reg-Limit-MTBR-register-payload-to-a-single-da.patch -#0040-mlxsw-core-Extend-allowed-list-of-external-cooling-d.patch -#0041-mlxsw-i2c-Utilize-standard-macros-for-dividing-buffe.patch -#0042-hwmon-mlxreg-fan-Add-support-for-new-flavour-of-capa.patch -#0043-hwmon-mlxreg-fan-Extend-number-of-supporetd-fans.patch -#0044-leds-mlxreg-Add-support-for-new-flavour-of-capabilit.patch -#0045-leds-mlxreg-Remove-code-for-amber-LED-colour.patch -#0046-Extend-driver-to-support-Infineon-Digital-Multi-phas.patch -#0047-dt-bindings-trivial-devices-Add-infineon-xdpe1a2g7.patch -#0048-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2891-c.patch -#0049-dt-bindings-trivial-devices-Add-mps-mp2891.patch -#0050-leds-mlxreg-Skip-setting-LED-color-during-initializa.patch -#0051-platform-mellanox-mlxreg-hotplug-Allow-more-flexible.patch -#0052-i2c-mux-Add-register-map-based-mux-driver.patch -#0053-platform-mellanox-Add-support-for-dynamic-I2C-channe.patch -#0054-platform-mellanox-Introduce-support-for-switches-equ.patch -#0055-mellanox-Relocate-mlx-platform-driver.patch -#0056-Documentation-ABI-Add-new-attribute-for-mlxreg-io-sy.patch -#0057-Documentation-ABI-Add-new-attribute-for-mlxreg-io-sy.patch -#0085-hwmon-mlxreg-fan-Separate-methods-of-fan-setting-com.patch -#0087-platform-mellanox-indicate-deferred-I2C-bus-creation.patch -#0087-platform_data-mlxreg-Add-capability-bit-and-mask-fie.patch -#0088-platform-mellanox-mlxreg-hotplug-Add-support-for-new.patch -#0089-platform-mellanox-mlx-platform-Change-register-name.patch -#0090-platform-mellanox-mlx-platform-Add-support-for-new-X.patch -#0093-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2855-c.patch -#8000-mlxsw-Use-weak-reverse-dependencies-for-firmware-fla.patch -#8003-mlxsw-i2c-SONIC-ISSU-Prevent-transaction-execution-f.patch -#8004-mlxsw-minimal-Downstream-Ignore-error-reading-SPAD-r.patch -#8005-leds-leds-mlxreg-Downstream-Send-udev-event-from-led.patch -#8006-i2c-mlxcpld-Downstream-WA-to-avoid-error-for-SMBUS-r.patch -#8007-hwmon-mlxreg-fan-Downstream-Allow-fan-speed-setting-.patch -#8008-hwmon-emc2305-Downstream-Allow-fan-speed-setting-gra.patch -#8009-hwmon-mlxsw-Downstream-Allow-fan-speed-setting-granu.patch -#8010-mlxsw-i2c-Downstream-Add-retry-mechanism-for-failed-.patch -#8011-mlxsw-minimal-Downstream-Disable-ethtool-interface.patch +0001-platform-mellanox-Introduce-support-for-rack-manager.patch +0002-platform-mellanox-Change-reset_pwr_converter_fail-at.patch +0003-platform-mellanox-Cosmetic-changes-rename-to-more-co.patch +0004-platform-mellanox-Introduce-support-for-next-generat.patch +0005-platform-mellanox-Introduce-support-of-new-Nvidia-L1.patch +0006-platform-mellanox-Split-initialization-procedure.patch +0007-platform-mellanox-Split-logic-in-init-and-exit-flow.patch +0008-platform-mellanox-Extend-all-systems-with-I2C-notifi.patch +0009-platform-mellanox-mlx-platform-Add-mux-selection-reg.patch +0010-platform-mellanox-mlx-platform-Move-bus-shift-assign.patch +0011-platform-mellanox-mlx-platform-Initialize-shift-vari.patch +0012-platform-mellanox-Fix-order-in-exit-flow.patch +0013-platform-mellanox-mlx-platform-Fix-signals-polarity-.patch +0014-platform-mellanox-mlx-platform-Modify-graceful-shutd.patch +0015-platform-mellanox-Change-register-offset-addresses.patch +0016-platform-mellanox-Add-new-attributes.patch +0017-platform-mellanox-Add-field-upgrade-capability-regis.patch +0018-platform-mellanox-Modify-reset-causes-description.patch +0019-platform-mellanox-mlx-platform-Modify-health-and-pow.patch +0020-platform-mellanox-mlx-platform-Add-reset-cause-attri.patch +0021-platform-mellanox-mlx-platform-add-support-for-addit.patch +0022-platform-mellanox-mlx-platform-Modify-power-off-call.patch +0023-platform-mellanox-Cosmetic-changes.patch +0024-platform-mellanox-mlx-platform-Add-reset-callback.patch +0025-platform-mellanox-mlx-platform-Prepare-driver-to-all.patch +0026-platform-mellanox-mlx-platform-Introduce-ACPI-init-f.patch +0027-platform-mellanox-mlx-platform-Get-interrupt-line-th.patch +0028-platform-mellanox-Add-initial-support-for-PCIe-based.patch +0029-platform-mellanox-mlxreg-hotplug-Extend-condition-fo.patch +0030-platform-mellanox-nvsw-sn2201-change-fans-i2c-busses.patch +0032-platform_data-mlxreg-Add-field-with-mapped-resource-.patch +0033-i2c-mlxcpld-Allow-driver-to-run-on-ARM64-architectur.patch +0034-i2c-mlxcpld-Add-support-for-extended-transaction-len.patch +0035-i2c-mlxcpld-Support-PCIe-mapped-register-space.patch +0039-mlxsw-reg-Limit-MTBR-register-payload-to-a-single-da.patch +0040-mlxsw-core-Extend-allowed-list-of-external-cooling-d.patch +0041-mlxsw-i2c-Utilize-standard-macros-for-dividing-buffe.patch +0042-hwmon-mlxreg-fan-Add-support-for-new-flavour-of-capa.patch +0043-hwmon-mlxreg-fan-Extend-number-of-supporetd-fans.patch +0044-leds-mlxreg-Add-support-for-new-flavour-of-capabilit.patch +0045-leds-mlxreg-Remove-code-for-amber-LED-colour.patch +0046-Extend-driver-to-support-Infineon-Digital-Multi-phas.patch +0047-dt-bindings-trivial-devices-Add-infineon-xdpe1a2g7.patch +0048-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2891-c.patch +0049-dt-bindings-trivial-devices-Add-mps-mp2891.patch +0050-leds-mlxreg-Skip-setting-LED-color-during-initializa.patch +0051-platform-mellanox-mlxreg-hotplug-Allow-more-flexible.patch +0052-i2c-mux-Add-register-map-based-mux-driver.patch +0053-platform-mellanox-Add-support-for-dynamic-I2C-channe.patch +0054-platform-mellanox-Introduce-support-for-switches-equ.patch +0055-mellanox-Relocate-mlx-platform-driver.patch +0056-Documentation-ABI-Add-new-attribute-for-mlxreg-io-sy.patch +0057-Documentation-ABI-Add-new-attribute-for-mlxreg-io-sy.patch +0085-hwmon-mlxreg-fan-Separate-methods-of-fan-setting-com.patch +0087-platform-mellanox-indicate-deferred-I2C-bus-creation.patch +0087-platform_data-mlxreg-Add-capability-bit-and-mask-fie.patch +0088-platform-mellanox-mlxreg-hotplug-Add-support-for-new.patch +0089-platform-mellanox-mlx-platform-Change-register-name.patch +0090-platform-mellanox-mlx-platform-Add-support-for-new-X.patch +0091-platform-mellanox-mlxreg-dpu-Add-initial-support-for.patch +0092-platform-mellanox-Introduce-support-of-Nvidia-smart-.patch +0093-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2855-c.patch +0094-i2c-asf-Introduce-MCTP-support-over-ASF-controller.patch +8000-mlxsw-Use-weak-reverse-dependencies-for-firmware-fla.patch +8003-mlxsw-i2c-SONIC-ISSU-Prevent-transaction-execution-f.patch +8004-mlxsw-minimal-Downstream-Ignore-error-reading-SPAD-r.patch +8005-leds-leds-mlxreg-Downstream-Send-udev-event-from-led.patch +8006-i2c-mlxcpld-Downstream-WA-to-avoid-error-for-SMBUS-r.patch +8007-hwmon-mlxreg-fan-Downstream-Allow-fan-speed-setting-.patch +8008-hwmon-emc2305-Downstream-Allow-fan-speed-setting-gra.patch +8009-hwmon-mlxsw-Downstream-Allow-fan-speed-setting-granu.patch +8010-mlxsw-i2c-Downstream-Add-retry-mechanism-for-failed-.patch +8011-mlxsw-minimal-Downstream-Disable-ethtool-interface.patch ###-> mellanox_hw_mgmt-end # Cisco patches for 5.10 kernel