diff --git a/patch/0071-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch b/patch/0071-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch new file mode 100644 index 000000000..7db10fa2e --- /dev/null +++ b/patch/0071-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch @@ -0,0 +1,64 @@ +From 3ce235145dfc28ac3e937b55581cdeaaf47a9929 Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 3 Jun 2020 11:09:47 +0300 +Subject: [backport bugfix] platform/x86: mlx-platform: Remove PSU EEPROM + configuration + +Remove PSU EEPROM configuration for systems class equipped with +Mellanox chip Spectrume-2. Till now all the systems from this class +used few types of power units, all equipped with EEPROM device with +address space two bytes. Thus, all these devices have been handled by +EEPROM driver "24c32". +There is a new requirement is to support power unit replacement by "off +the shelf" device, matching electrical required parameters. Such device +could be equpped with different EEPROM type, which could be one byte +address space adressing or even could be not equipped with EEPROM. +In such case "24c32" will not work. + +Fixes: 1bd42d94ccab ("platform/x86: mlx-platform: Add support for new 200G IB and Ethernet systems") +Signed-off-by: Vadim Pasternak +--- + drivers/platform/x86/mlx-platform.c | 15 ++------------- + 1 file changed, 2 insertions(+), 13 deletions(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index 208f4a476229..d6c87fb88507 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -329,15 +329,6 @@ static struct i2c_board_info mlxplat_mlxcpld_psu[] = { + }, + }; + +-static struct i2c_board_info mlxplat_mlxcpld_ng_psu[] = { +- { +- I2C_BOARD_INFO("24c32", 0x51), +- }, +- { +- I2C_BOARD_INFO("24c32", 0x50), +- }, +-}; +- + static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { + { + I2C_BOARD_INFO("dps460", 0x59), +@@ -762,15 +753,13 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = { + .label = "psu1", + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(0), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[0], +- .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "psu2", + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(1), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[1], +- .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + }; + +-- +2.11.0 + diff --git a/patch/0072-thermal-Fix-deadlock-in-thermal-thermal_zone_device_.patch b/patch/0072-thermal-Fix-deadlock-in-thermal-thermal_zone_device_.patch new file mode 100644 index 000000000..76d023cc1 --- /dev/null +++ b/patch/0072-thermal-Fix-deadlock-in-thermal-thermal_zone_device_.patch @@ -0,0 +1,83 @@ +From 163b00cde7cf2206e248789d2780121ad5e6a70b Mon Sep 17 00:00:00 2001 +From: Wei Wang +Date: Tue, 12 Nov 2019 12:42:23 -0800 +Subject: [PATCH] thermal: Fix deadlock in thermal thermal_zone_device_check + +1851799e1d29 ("thermal: Fix use-after-free when unregistering thermal zone +device") changed cancel_delayed_work to cancel_delayed_work_sync to avoid +a use-after-free issue. However, cancel_delayed_work_sync could be called +insides the WQ causing deadlock. + +[54109.642398] c0 1162 kworker/u17:1 D 0 11030 2 0x00000000 +[54109.642437] c0 1162 Workqueue: thermal_passive_wq thermal_zone_device_check +[54109.642447] c0 1162 Call trace: +[54109.642456] c0 1162 __switch_to+0x138/0x158 +[54109.642467] c0 1162 __schedule+0xba4/0x1434 +[54109.642480] c0 1162 schedule_timeout+0xa0/0xb28 +[54109.642492] c0 1162 wait_for_common+0x138/0x2e8 +[54109.642511] c0 1162 flush_work+0x348/0x40c +[54109.642522] c0 1162 __cancel_work_timer+0x180/0x218 +[54109.642544] c0 1162 handle_thermal_trip+0x2c4/0x5a4 +[54109.642553] c0 1162 thermal_zone_device_update+0x1b4/0x25c +[54109.642563] c0 1162 thermal_zone_device_check+0x18/0x24 +[54109.642574] c0 1162 process_one_work+0x3cc/0x69c +[54109.642583] c0 1162 worker_thread+0x49c/0x7c0 +[54109.642593] c0 1162 kthread+0x17c/0x1b0 +[54109.642602] c0 1162 ret_from_fork+0x10/0x18 +[54109.643051] c0 1162 kworker/u17:2 D 0 16245 2 0x00000000 +[54109.643067] c0 1162 Workqueue: thermal_passive_wq thermal_zone_device_check +[54109.643077] c0 1162 Call trace: +[54109.643085] c0 1162 __switch_to+0x138/0x158 +[54109.643095] c0 1162 __schedule+0xba4/0x1434 +[54109.643104] c0 1162 schedule_timeout+0xa0/0xb28 +[54109.643114] c0 1162 wait_for_common+0x138/0x2e8 +[54109.643122] c0 1162 flush_work+0x348/0x40c +[54109.643131] c0 1162 __cancel_work_timer+0x180/0x218 +[54109.643141] c0 1162 handle_thermal_trip+0x2c4/0x5a4 +[54109.643150] c0 1162 thermal_zone_device_update+0x1b4/0x25c +[54109.643159] c0 1162 thermal_zone_device_check+0x18/0x24 +[54109.643167] c0 1162 process_one_work+0x3cc/0x69c +[54109.643177] c0 1162 worker_thread+0x49c/0x7c0 +[54109.643186] c0 1162 kthread+0x17c/0x1b0 +[54109.643195] c0 1162 ret_from_fork+0x10/0x18 +[54109.644500] c0 1162 cat D 0 7766 1 0x00000001 +[54109.644515] c0 1162 Call trace: +[54109.644524] c0 1162 __switch_to+0x138/0x158 +[54109.644536] c0 1162 __schedule+0xba4/0x1434 +[54109.644546] c0 1162 schedule_preempt_disabled+0x80/0xb0 +[54109.644555] c0 1162 __mutex_lock+0x3a8/0x7f0 +[54109.644563] c0 1162 __mutex_lock_slowpath+0x14/0x20 +[54109.644575] c0 1162 thermal_zone_get_temp+0x84/0x360 +[54109.644586] c0 1162 temp_show+0x30/0x78 +[54109.644609] c0 1162 dev_attr_show+0x5c/0xf0 +[54109.644628] c0 1162 sysfs_kf_seq_show+0xcc/0x1a4 +[54109.644636] c0 1162 kernfs_seq_show+0x48/0x88 +[54109.644656] c0 1162 seq_read+0x1f4/0x73c +[54109.644664] c0 1162 kernfs_fop_read+0x84/0x318 +[54109.644683] c0 1162 __vfs_read+0x50/0x1bc +[54109.644692] c0 1162 vfs_read+0xa4/0x140 +[54109.644701] c0 1162 SyS_read+0xbc/0x144 +[54109.644708] c0 1162 el0_svc_naked+0x34/0x38 +[54109.845800] c0 1162 D 720.000s 1->7766->7766 cat [panic] + +Fixes: 1851799e1d29 ("thermal: Fix use-after-free when unregistering thermal zone device") +Cc: stable@vger.kernel.org +Signed-off-by: Wei Wang +Signed-off-by: Zhang Rui +--- + drivers/thermal/thermal_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index cf18034..90c033b 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -402,7 +402,7 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, + mod_delayed_work(system_freezable_wq, &tz->poll_queue, + msecs_to_jiffies(delay)); + else +- cancel_delayed_work_sync(&tz->poll_queue); ++ cancel_delayed_work(&tz->poll_queue); + } + + static void monitor_thermal_zone(struct thermal_zone_device *tz) diff --git a/patch/0073-mlxsw-core-Fix-memory-leak-on-module-removal.patch b/patch/0073-mlxsw-core-Fix-memory-leak-on-module-removal.patch new file mode 100644 index 000000000..743f1e410 --- /dev/null +++ b/patch/0073-mlxsw-core-Fix-memory-leak-on-module-removal.patch @@ -0,0 +1,53 @@ +From ad4710e1334390817da14b8080e415e1075f0a1a Mon Sep 17 00:00:00 2001 +From: Oleksandr Shamray +Date: Mon, 19 Oct 2020 14:47:54 +0300 +Subject: [PATCH] mlxsw: core: Fix memory leak on module removal + +Free the devlink instance during the teardown sequence in the non-reload case to avoid the following memory leak. + +unreferenced object 0xffff888232895000 (size 2048): + comm "modprobe", pid 1073, jiffies 4295568857 (age 164.871s) + hex dump (first 32 bytes): + 00 01 00 00 00 00 ad de 22 01 00 00 00 00 ad de ........"....... + 10 50 89 32 82 88 ff ff 10 50 89 32 82 88 ff ff .P.2.....P.2.... + backtrace: + [<00000000c704e9a6>] __kmalloc+0x13a/0x2a0 + [<00000000ee30129d>] devlink_alloc+0xff/0x760 + [<0000000092ab3e5d>] 0xffffffffa042e5b0 + [<000000004f3f8a31>] 0xffffffffa042f6ad + [<0000000092800b4b>] 0xffffffffa0491df3 + [<00000000c4843903>] local_pci_probe+0xcb/0x170 + [<000000006993ded7>] pci_device_probe+0x2c2/0x4e0 + [<00000000a8e0de75>] really_probe+0x2c5/0xf90 + [<00000000d42ba75d>] driver_probe_device+0x1eb/0x340 + [<00000000bcc95e05>] device_driver_attach+0x294/0x300 + [<000000000e2bc177>] __driver_attach+0x167/0x2f0 + [<000000007d44cd6e>] bus_for_each_dev+0x148/0x1f0 + [<000000003cd5a91e>] driver_attach+0x45/0x60 + [<000000000041ce51>] bus_add_driver+0x3b8/0x720 + [<00000000f5215476>] driver_register+0x230/0x4e0 + [<00000000d79356f5>] __pci_register_driver+0x190/0x200 + +Fixes: a22712a96291 ("mlxsw: core: Fix devlink unregister flow") +Signed-off-by: Ido Schimmel +Reported-by: Vadim Pasternak +--- + drivers/net/ethernet/mellanox/mlxsw/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c +index a127e0b..40a1272 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c +@@ -1062,6 +1062,8 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, + kfree(mlxsw_core->lag.mapping); + mlxsw_ports_fini(mlxsw_core); + mlxsw_core->bus->fini(mlxsw_core->bus_priv); ++ if (!reload) ++ devlink_free(devlink); + + return; + +-- +2.8.4 + diff --git a/patch/0074-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch b/patch/0074-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch new file mode 100644 index 000000000..751138df8 --- /dev/null +++ b/patch/0074-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch @@ -0,0 +1,49 @@ +From 198e605329d5202aec72bf89c291eb7da360dd33 Mon Sep 17 00:00:00 2001 +From: Oleksandr Shamray +Date: Wed, 21 Oct 2020 13:57:35 +0300 +Subject: [PATCH 1/2] platform/x86: mlx-platform: Remove PSU EEPROM + configuration + +Remove PSU EEPROM configuration for systems class equipped with +Mellanox chip Spectrum and Celeron CPU. Till now all the systems from this class +used few types of power units, all equipped with EEPROM device with +address space two bytes. Thus, all these devices have been handled by +EEPROM driver "24c02". +There is a new requirement is to support power unit replacement by "off +the shelf" device, matching electrical required parameters. Such device +could be equpped with different EEPROM type, which could be one byte +address space adressing or even could be not equipped with EEPROM. +In such case "24c02" will not work. + +Fixes: c6acad68e ("platform/mellanox: mlxreg-hotplug: Modify to use a regmap interface") +Fixes: ba814fdd0 ("platform/x86: mlx-platform: Use defines for bus assignment") +Signed-off-by: Oleksandr Shamray +--- + drivers/platform/x86/mlx-platform.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index d6c87fb..6400f1d 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -375,15 +375,13 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = { + .label = "psu1", + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(0), +- .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0], +- .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "psu2", + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(1), +- .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1], +- .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + }; + +-- +2.8.4 + diff --git a/patch/0075-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch b/patch/0075-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch new file mode 100644 index 000000000..d538a7729 --- /dev/null +++ b/patch/0075-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch @@ -0,0 +1,48 @@ +From 6a826ae7e734054d610f0d3a9daad88339ee35e7 Mon Sep 17 00:00:00 2001 +From: Oleksandr Shamray +Date: Wed, 21 Oct 2020 15:10:48 +0300 +Subject: [PATCH 2/2] platform/x86: mlx-platform: Remove PSU EEPROM + configuration + +Remove PSU EEPROM configuration for systems class equipped with +Mellanox chip Spectrum and Mellanox Broadwell Comex. Till now all the systems from this class +used few types of power units, all equipped with EEPROM device with +address space two bytes. Thus, all these devices have been handled by +EEPROM driver "24c02". +There is a new requirement is to support power unit replacement by "off +the shelf" device, matching electrical required parameters. Such device +could be equpped with different EEPROM type, which could be one byte +address space adressing or even could be not equipped with EEPROM. +In such case "24c02" will not work. + +Fixes: ef08e14a3 ("platform/x86: mlx-platform: Add support for new msn274x system type") +Signed-ff-by: Oleksandr Shamray +--- + drivers/platform/x86/mlx-platform.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index 6400f1d..c1d1a78 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -593,15 +593,13 @@ static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_psu_items_data[] = { + .label = "psu1", + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(0), +- .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0], +- .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "psu2", + .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(1), +- .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1], +- .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + }; + +-- +2.8.4 + diff --git a/patch/0076-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2975-c.patch b/patch/0076-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2975-c.patch new file mode 100644 index 000000000..e9d4c235b --- /dev/null +++ b/patch/0076-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2975-c.patch @@ -0,0 +1,874 @@ +From 4218cfb886d2de82677a3fe1aeb44858c38f81bd Mon Sep 17 00:00:00 2001 +From: Oleksandr Shamray +Date: Thu, 12 Nov 2020 16:16:50 +0200 +Subject: [PATCH 1/4] hwmon: (pmbus) Add support for MPS Multi-phase mp2975 + controller + +Add support for mp295 device from Monolithic Power Systems, Inc. (MPS) +vendor. This is a dual-loop, digital, multi-phase controller. +This device: +- Supports two power rail. +- Provides 8 pulse-width modulations (PWMs), and can be configured up + to 8-phase operation for rail 1 and up to 4-phase operation for rail + 2. +- Supports two pages 0 and 1 for telemetry and also pages 2 and 3 for + configuration. +- Can configured VOUT readout in direct or VID format and allows + setting of different formats on rails 1 and 2. For VID the following + protocols are available: VR13 mode with 5-mV DAC; VR13 mode with + 10-mV DAC, IMVP9 mode with 5-mV DAC. + +Signed-off-by: Vadim Pasternak +--- + drivers/hwmon/pmbus/Kconfig | 10 + + drivers/hwmon/pmbus/Makefile | 1 + + drivers/hwmon/pmbus/mp2975.c | 804 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 815 insertions(+) + create mode 100644 drivers/hwmon/pmbus/mp2975.c + +diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig +index 14c0572..fbf326e 100644 +--- a/drivers/hwmon/pmbus/Kconfig ++++ b/drivers/hwmon/pmbus/Kconfig +@@ -145,6 +145,16 @@ config SENSORS_MAX8688 + This driver can also be built as a module. If so, the module will + be called max8688. + ++config SENSORS_MP2975 ++ tristate "MPS MP2975" ++ default n ++ help ++ If you say yes here you get hardware monitoring support for MPS ++ MP2975 Dual Loop Digital Multi-Phase Controller. ++ ++ This driver can also be built as a module. If so, the module will ++ be called mp2975. ++ + config SENSORS_TPS40422 + tristate "TI TPS40422" + default n +diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile +index e7272e2..c7b5096 100644 +--- a/drivers/hwmon/pmbus/Makefile ++++ b/drivers/hwmon/pmbus/Makefile +@@ -13,6 +13,7 @@ obj-$(CONFIG_SENSORS_MAX20751) += max20751.o + obj-$(CONFIG_SENSORS_MAX34440) += max34440.o + obj-$(CONFIG_SENSORS_DNI_DPS460) += dni_dps460.o + obj-$(CONFIG_SENSORS_MAX8688) += max8688.o ++obj-$(CONFIG_SENSORS_MP2975) += mp2975.o + obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o + obj-$(CONFIG_SENSORS_TPS53679) += tps53679.o + obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o +diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c +new file mode 100644 +index 0000000..a0c2bcf +--- /dev/null ++++ b/drivers/hwmon/pmbus/mp2975.c +@@ -0,0 +1,804 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers ++ * ++ * Copyright (c) 2020 Nvidia Technologies. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "pmbus.h" ++ ++/* Vendor specific registers. */ ++#define MP2975_MFR_APS_HYS_R2 0x0d ++#define MP2975_MFR_SLOPE_TRIM3 0x1d ++#define MP2975_MFR_VR_MULTI_CONFIG_R1 0x0d ++#define MP2975_MFR_VR_MULTI_CONFIG_R2 0x1d ++#define MP2975_MFR_APS_DECAY_ADV 0x56 ++#define MP2975_MFR_DC_LOOP_CTRL 0x59 ++#define MP2975_MFR_OCP_UCP_PHASE_SET 0x65 ++#define MP2975_MFR_VR_CONFIG1 0x68 ++#define MP2975_MFR_READ_CS1_2 0x82 ++#define MP2975_MFR_READ_CS3_4 0x83 ++#define MP2975_MFR_READ_CS5_6 0x84 ++#define MP2975_MFR_READ_CS7_8 0x85 ++#define MP2975_MFR_READ_CS9_10 0x86 ++#define MP2975_MFR_READ_CS11_12 0x87 ++#define MP2975_MFR_READ_IOUT_PK 0x90 ++#define MP2975_MFR_READ_POUT_PK 0x91 ++#define MP2975_MFR_READ_VREF_R1 0xa1 ++#define MP2975_MFR_READ_VREF_R2 0xa3 ++#define MP2975_MFR_OVP_TH_SET 0xe5 ++#define MP2975_MFR_UVP_SET 0xe6 ++ ++#define MP2975_VOUT_FORMAT BIT(15) ++#define MP2975_VID_STEP_SEL_R1 BIT(4) ++#define MP2975_IMVP9_EN_R1 BIT(13) ++#define MP2975_VID_STEP_SEL_R2 BIT(3) ++#define MP2975_IMVP9_EN_R2 BIT(12) ++#define MP2975_PRT_THRES_DIV_OV_EN BIT(14) ++#define MP2975_DRMOS_KCS GENMASK(13, 12) ++#define MP2975_PROT_DEV_OV_OFF 10 ++#define MP2975_PROT_DEV_OV_ON 5 ++#define MP2975_SENSE_AMPL BIT(11) ++#define MP2975_SENSE_AMPL_UNIT 1 ++#define MP2975_SENSE_AMPL_HALF 2 ++#define MP2975_VIN_UV_LIMIT_UNIT 8 ++ ++#define MP2975_PSC_VOLTAGE_OUT 0x40 ++#define MP2975_MAX_PHASE_RAIL1 8 ++#define MP2975_MAX_PHASE_RAIL2 4 ++#define MP2975_PAGE_NUM 2 ++ ++#define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \ ++ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT) ++ ++struct mp2975_data { ++ struct pmbus_driver_info info; ++ int vout_scale; ++ int vid_step[MP2975_PAGE_NUM]; ++ int vref[MP2975_PAGE_NUM]; ++ int vref_off[MP2975_PAGE_NUM]; ++ int vout_max[MP2975_PAGE_NUM]; ++ int vout_ov_fixed[MP2975_PAGE_NUM]; ++ int vout_format[MP2975_PAGE_NUM]; ++ int curr_sense_gain[MP2975_PAGE_NUM]; ++}; ++ ++#define to_mp2975_data(x) container_of(x, struct mp2975_data, info) ++ ++static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg) ++{ ++ switch (reg) { ++ case PMBUS_VOUT_MODE: ++ /* ++ * Enforce VOUT direct format, since device allows to set the ++ * different formats for the different rails. Conversion from ++ * VID to direct provided by driver internally, in case it is ++ * necessary. ++ */ ++ return MP2975_PSC_VOLTAGE_OUT; ++ default: ++ return -ENODATA; ++ } ++} ++ ++static int ++mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg, ++ u16 mask) ++{ ++ int ret = pmbus_read_word_data(client, page, reg); ++ ++ return (ret > 0) ? ret & mask : ret; ++} ++ ++static int ++mp2975_vid2direct(int vrf, int val) ++{ ++ switch (vrf) { ++ case vr12: ++ if (val >= 0x01) ++ return 250 + (val - 1) * 5; ++ break; ++ case vr13: ++ if (val >= 0x01) ++ return 500 + (val - 1) * 10; ++ break; ++ case imvp9: ++ if (val >= 0x01) ++ return 200 + (val - 1) * 10; ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int ++mp2975_read_phase(struct i2c_client *client, struct mp2975_data *data, ++ int page, int phase, u8 reg) ++{ ++ u16 mask; ++ int shift = 0, ret; ++ ++ if ((phase + 1) % MP2975_PAGE_NUM) { ++ mask = GENMASK(7, 0); ++ } else { ++ mask = GENMASK(15, 8); ++ shift = 8; ++ } ++ ++ ret = mp2975_read_word_helper(client, page, phase, reg, mask); ++ if (ret < 0) ++ return ret; ++ ++ ret >>= shift; ++ ++ /* ++ * Output value is calculated as: (READ_CSx / 80 – 1.23) / (Kcs * Rcs) ++ * where: ++ * - Kcs is the DrMOS current sense gain of power stage, which is ++ * obtained from the register MP2975_MFR_VR_CONFIG1, bits 13-12 with ++ * the following selection of DrMOS (data->curr_sense_gain[page]): ++ * 00b - 5µA/A, 01b - 8.5µA/A, 10b - 9.7µA/A, 11b - 10µA/A. ++ * - Rcs is the internal phase current sense resistor which is constant ++ * value 1kΩ. ++ */ ++ return DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(ret * 100 - 9840, 100) * ++ 100, data->curr_sense_gain[page]); ++} ++ ++static int ++mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data, ++ int page, int phase) ++{ ++ int ret; ++ ++ if (page) { ++ switch (phase) { ++ case 0 ... 1: ++ ret = mp2975_read_phase(client, data, page, phase, ++ MP2975_MFR_READ_CS7_8); ++ break; ++ case 2 ... 3: ++ ret = mp2975_read_phase(client, data, page, phase, ++ MP2975_MFR_READ_CS9_10); ++ break; ++ case 4 ... 5: ++ ret = mp2975_read_phase(client, data, page, phase, ++ MP2975_MFR_READ_CS11_12); ++ break; ++ default: ++ return -ENODATA; ++ } ++ } else { ++ switch (phase) { ++ case 0 ... 1: ++ ret = mp2975_read_phase(client, data, page, phase, ++ MP2975_MFR_READ_CS1_2); ++ break; ++ case 2 ... 3: ++ ret = mp2975_read_phase(client, data, page, phase, ++ MP2975_MFR_READ_CS3_4); ++ break; ++ case 4 ... 5: ++ ret = mp2975_read_phase(client, data, page, phase, ++ MP2975_MFR_READ_CS5_6); ++ break; ++ case 6 ... 7: ++ ret = mp2975_read_phase(client, data, page, phase, ++ MP2975_MFR_READ_CS7_8); ++ break; ++ case 8 ... 9: ++ ret = mp2975_read_phase(client, data, page, phase, ++ MP2975_MFR_READ_CS9_10); ++ break; ++ case 10 ... 11: ++ ret = mp2975_read_phase(client, data, page, phase, ++ MP2975_MFR_READ_CS11_12); ++ break; ++ default: ++ return -ENODATA; ++ } ++ } ++ return ret; ++} ++ ++static int mp2975_read_word_data(struct i2c_client *client, int page, ++ int reg) ++{ ++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client); ++ struct mp2975_data *data = to_mp2975_data(info); ++ int phase = 255; ++ int ret; ++ ++ switch (reg) { ++ case PMBUS_OT_FAULT_LIMIT: ++ ret = mp2975_read_word_helper(client, page, phase, reg, ++ GENMASK(7, 0)); ++ break; ++ case PMBUS_VIN_OV_FAULT_LIMIT: ++ ret = mp2975_read_word_helper(client, page, phase, reg, ++ GENMASK(7, 0)); ++ if (ret < 0) ++ return ret; ++ ++ ret = DIV_ROUND_CLOSEST(ret, MP2975_VIN_UV_LIMIT_UNIT); ++ break; ++ case PMBUS_VOUT_OV_FAULT_LIMIT: ++ /* ++ * Register provides two values for over-voltage protection ++ * threshold for fixed (ovp2) and tracking (ovp1) modes. The ++ * minimum of these two values is provided as over-voltage ++ * fault alarm. ++ */ ++ ret = mp2975_read_word_helper(client, page, phase, ++ MP2975_MFR_OVP_TH_SET, ++ GENMASK(2, 0)); ++ if (ret < 0) ++ return ret; ++ ++ ret = min_t(int, data->vout_max[page] + 50 * (ret + 1), ++ data->vout_ov_fixed[page]); ++ break; ++ case PMBUS_VOUT_UV_FAULT_LIMIT: ++ ret = mp2975_read_word_helper(client, page, phase, ++ MP2975_MFR_UVP_SET, ++ GENMASK(2, 0)); ++ if (ret < 0) ++ return ret; ++ ++ ret = DIV_ROUND_CLOSEST(data->vref[page] * 10 - 50 * ++ (ret + 1) * data->vout_scale, 10); ++ break; ++ case PMBUS_READ_VOUT: ++ ret = mp2975_read_word_helper(client, page, phase, reg, ++ GENMASK(11, 0)); ++ if (ret < 0) ++ return ret; ++ ++ /* ++ * READ_VOUT can be provided in VID or direct format. The ++ * format type is specified by bit 15 of the register ++ * MP2975_MFR_DC_LOOP_CTRL. The driver enforces VOUT direct ++ * format, since device allows to set the different formats for ++ * the different rails and also all VOUT limits registers are ++ * provided in a direct format. In case format is VID - convert ++ * to direct. ++ */ ++ if (data->vout_format[page] == vid) ++ ret = mp2975_vid2direct(info->vrm_version[page], ret); ++ break; ++ case PMBUS_VIRT_READ_POUT_MAX: ++ ret = mp2975_read_word_helper(client, page, phase, ++ MP2975_MFR_READ_POUT_PK, ++ GENMASK(12, 0)); ++ if (ret < 0) ++ return ret; ++ ++ ret = DIV_ROUND_CLOSEST(ret, 4); ++ break; ++ case PMBUS_VIRT_READ_IOUT_MAX: ++ ret = mp2975_read_word_helper(client, page, phase, ++ MP2975_MFR_READ_IOUT_PK, ++ GENMASK(12, 0)); ++ if (ret < 0) ++ return ret; ++ ++ ret = DIV_ROUND_CLOSEST(ret, 4); ++ break; ++ case PMBUS_READ_IOUT: ++ ret = mp2975_read_phases(client, data, page, phase); ++ if (ret < 0) ++ return ret; ++ ++ break; ++ case PMBUS_UT_WARN_LIMIT: ++ case PMBUS_UT_FAULT_LIMIT: ++ case PMBUS_VIN_UV_WARN_LIMIT: ++ case PMBUS_VIN_UV_FAULT_LIMIT: ++ case PMBUS_VOUT_UV_WARN_LIMIT: ++ case PMBUS_VOUT_OV_WARN_LIMIT: ++ case PMBUS_VIN_OV_WARN_LIMIT: ++ case PMBUS_IIN_OC_FAULT_LIMIT: ++ case PMBUS_IOUT_OC_LV_FAULT_LIMIT: ++ case PMBUS_IIN_OC_WARN_LIMIT: ++ case PMBUS_IOUT_OC_WARN_LIMIT: ++ case PMBUS_IOUT_OC_FAULT_LIMIT: ++ case PMBUS_IOUT_UC_FAULT_LIMIT: ++ case PMBUS_POUT_OP_FAULT_LIMIT: ++ case PMBUS_POUT_OP_WARN_LIMIT: ++ case PMBUS_PIN_OP_WARN_LIMIT: ++ return -ENXIO; ++ default: ++ return -ENODATA; ++ } ++ ++ return ret; ++} ++ ++static int mp2975_identify_multiphase_rail2(struct i2c_client *client) ++{ ++ int ret; ++ ++ /* ++ * Identify multiphase for rail 2 - could be from 0 to 4. ++ * In case phase number is zero – only page zero is supported ++ */ ++ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); ++ if (ret < 0) ++ return ret; ++ ++ /* Identify multiphase for rail 2 - could be from 0 to 4. */ ++ ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R2); ++ if (ret < 0) ++ return ret; ++ ++ ret &= GENMASK(2, 0); ++ return (ret >= 4) ? 4 : ret; ++} ++#if 0 ++static void mp2975_set_phase_rail1(struct pmbus_driver_info *info) ++{ ++ int i; ++ ++ for (i = 0 ; i < info->phases[0]; i++) ++ info->pfunc[i] = PMBUS_HAVE_IOUT; ++} ++ ++static void mp2975_set_phase_rail2(struct pmbus_driver_info *info) ++{ ++ int max_rail, i; ++ ++ /* Set phases for rail 2 from upper to lower. */ ++ max_rail = info->phases[1] % (MP2975_MAX_PHASE_RAIL2 - 1); ++ for (i = 1 ; i <= max_rail; i++) ++ info->pfunc[MP2975_MAX_PHASE_RAIL1 - i] = PMBUS_HAVE_IOUT; ++} ++ ++static int mp2975_set_multiphase_rail2(struct pmbus_driver_info *info) ++{ ++ switch (info->phases[1]) { ++ case 1 ... 7: ++ mp2975_set_phase_rail2(info); ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ++mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, ++ struct pmbus_driver_info *info) ++{ ++ int ret; ++ ++ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); ++ if (ret < 0) ++ return ret; ++ ++ /* Identify multiphase for rail 1 - could be from 1 to 8. */ ++ ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R1); ++ if (ret > 0) ++ info->phases[0] = ret & GENMASK(3, 0); ++ else ++ return (ret) ? ret : -EINVAL; ++ ++ /* ++ * The device provides a total of 8 PWM pins, and can be configured ++ * to different phase count applications for rail 1 and rail 2. ++ * Rail 1 can be set to 8 phases, while rail 2 can only be set to 4 ++ * phases at most. When rail 1’s phase count is configured as 0, rail ++ * 1 operates with 1-phase DCM. When rail 2 phase count is configured ++ * as 0, rail 2 is disabled. ++ */ ++ switch (info->phases[0]) { ++ case 1 ... 4: ++ mp2975_set_phase_rail1(info); ++ return mp2975_set_multiphase_rail2(info); ++ case 5: ++ mp2975_set_phase_rail1(info); ++ switch (info->phases[1]) { ++ case 1 ... 3: ++ return mp2975_set_multiphase_rail2(info); ++ default: ++ return 0; ++ } ++ case 6: ++ mp2975_set_phase_rail1(info); ++ switch (info->phases[1]) { ++ case 1 ... 2: ++ return mp2975_set_multiphase_rail2(info); ++ default: ++ return 0; ++ } ++ case 7: ++ mp2975_set_phase_rail1(info); ++ switch (info->phases[1]) { ++ case 1: ++ return mp2975_set_multiphase_rail2(info); ++ default: ++ return 0; ++ } ++ case 8: ++ mp2975_set_phase_rail1(info); ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++#endif ++static int ++mp2975_identify_vid(struct i2c_client *client, struct mp2975_data *data, ++ struct pmbus_driver_info *info, u32 reg, int page, ++ u32 imvp_bit, u32 vr_bit) ++{ ++ int ret; ++ ++ /* Identify VID mode and step selection. */ ++ ret = i2c_smbus_read_word_data(client, reg); ++ if (ret < 0) ++ return ret; ++ ++ if (ret & imvp_bit) { ++ info->vrm_version[page] = imvp9; ++ data->vid_step[page] = MP2975_PROT_DEV_OV_OFF; ++ } else if (ret & vr_bit) { ++ info->vrm_version[page] = vr12; ++ data->vid_step[page] = MP2975_PROT_DEV_OV_ON; ++ } else { ++ info->vrm_version[page] = vr13; ++ data->vid_step[page] = MP2975_PROT_DEV_OV_OFF; ++ } ++ ++ return 0; ++} ++ ++static int ++mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data, ++ struct pmbus_driver_info *info) ++{ ++ int ret; ++ ++ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); ++ if (ret < 0) ++ return ret; ++ ++ /* Identify VID mode for rail 1. */ ++ ret = mp2975_identify_vid(client, data, info, ++ MP2975_MFR_VR_MULTI_CONFIG_R1, 0, ++ MP2975_IMVP9_EN_R1, MP2975_VID_STEP_SEL_R1); ++ if (ret < 0) ++ return ret; ++ ++ /* Identify VID mode for rail 2, if connected. */ ++ if (info->pages == MP2975_PAGE_NUM) ++ ret = mp2975_identify_vid(client, data, info, ++ MP2975_MFR_VR_MULTI_CONFIG_R2, 1, ++ MP2975_IMVP9_EN_R2, ++ MP2975_VID_STEP_SEL_R2); ++ return ret; ++} ++ ++static int ++mp2975_current_sense_gain_get(struct i2c_client *client, ++ struct mp2975_data *data) ++{ ++ int i, ret; ++ ++ /* ++ * Obtain DrMOS current sense gain of power stage from the register ++ * MP2975_MFR_VR_CONFIG1, bits 13-12. The value is selected as below: ++ * 00b - 5µA/A, 01b - 8.5µA/A, 10b - 9.7µA/A, 11b - 10µA/A. Other ++ * values are invalid. ++ */ ++ for (i = 0 ; i < data->info.pages; i++) { ++ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); ++ if (ret < 0) ++ return ret; ++ ret = i2c_smbus_read_word_data(client, ++ MP2975_MFR_VR_CONFIG1); ++ if (ret < 0) ++ return ret; ++ ++ switch ((ret & MP2975_DRMOS_KCS) >> 12) { ++ case 0: ++ data->curr_sense_gain[i] = 50; ++ break; ++ case 1: ++ data->curr_sense_gain[i] = 85; ++ break; ++ case 2: ++ data->curr_sense_gain[i] = 97; ++ break; ++ default: ++ data->curr_sense_gain[i] = 100; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++mp2975_vref_get(struct i2c_client *client, struct mp2975_data *data, ++ struct pmbus_driver_info *info) ++{ ++ int ret; ++ ++ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 3); ++ if (ret < 0) ++ return ret; ++ ++ /* Get voltage reference value for rail 1. */ ++ ret = i2c_smbus_read_word_data(client, MP2975_MFR_READ_VREF_R1); ++ if (ret < 0) ++ return ret; ++ ++ data->vref[0] = ret * data->vid_step[0]; ++ ++ /* Get voltage reference value for rail 2, if connected. */ ++ if (data->info.pages == MP2975_PAGE_NUM) { ++ ret = i2c_smbus_read_word_data(client, MP2975_MFR_READ_VREF_R2); ++ if (ret < 0) ++ return ret; ++ ++ data->vref[1] = ret * data->vid_step[1]; ++ } ++ return 0; ++} ++ ++static int ++mp2975_vref_offset_get(struct i2c_client *client, struct mp2975_data *data, ++ int page) ++{ ++ int ret; ++ ++ ret = i2c_smbus_read_word_data(client, MP2975_MFR_OVP_TH_SET); ++ if (ret < 0) ++ return ret; ++ ++ switch ((ret & GENMASK(5, 3)) >> 3) { ++ case 1: ++ data->vref_off[page] = 140; ++ break; ++ case 2: ++ data->vref_off[page] = 220; ++ break; ++ case 4: ++ data->vref_off[page] = 400; ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int ++mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, ++ struct pmbus_driver_info *info, int page) ++{ ++ int ret; ++ ++ /* Get maximum reference voltage of VID-DAC in VID format. */ ++ ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_MAX); ++ if (ret < 0) ++ return ret; ++ ++ data->vout_max[page] = mp2975_vid2direct(info->vrm_version[page], ret & ++ GENMASK(8, 0)); ++ return 0; ++} ++ ++static int ++mp2975_identify_vout_format(struct i2c_client *client, ++ struct mp2975_data *data, int page) ++{ ++ int ret; ++ ++ ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL); ++ if (ret < 0) ++ return ret; ++ ++ if (ret & MP2975_VOUT_FORMAT) ++ data->vout_format[page] = vid; ++ else ++ data->vout_format[page] = direct; ++ return 0; ++} ++ ++static int ++mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data, ++ struct pmbus_driver_info *info) ++{ ++ int thres_dev, sense_ampl, ret; ++ ++ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0); ++ if (ret < 0) ++ return ret; ++ ++ /* ++ * Get divider for over- and under-voltage protection thresholds ++ * configuration from the Advanced Options of Auto Phase Shedding and ++ * decay register. ++ */ ++ ret = i2c_smbus_read_word_data(client, MP2975_MFR_APS_DECAY_ADV); ++ if (ret < 0) ++ return ret; ++ thres_dev = ret & MP2975_PRT_THRES_DIV_OV_EN ? MP2975_PROT_DEV_OV_ON : ++ MP2975_PROT_DEV_OV_OFF; ++ ++ /* Select the gain of remote sense amplifier. */ ++ ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_SCALE_LOOP); ++ if (ret < 0) ++ return ret; ++ sense_ampl = ret & MP2975_SENSE_AMPL ? MP2975_SENSE_AMPL_HALF : ++ MP2975_SENSE_AMPL_UNIT; ++ ++ data->vout_scale = sense_ampl * thres_dev; ++ ++ return 0; ++} ++ ++static int ++mp2975_vout_per_rail_config_get(struct i2c_client *client, ++ struct mp2975_data *data, ++ struct pmbus_driver_info *info) ++{ ++ int i, ret; ++ ++ for (i = 0; i < data->info.pages; i++) { ++ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); ++ if (ret < 0) ++ return ret; ++ ++ /* Obtain voltage reference offsets. */ ++ ret = mp2975_vref_offset_get(client, data, i); ++ if (ret < 0) ++ return ret; ++ ++ /* Obtain maximum voltage values. */ ++ ret = mp2975_vout_max_get(client, data, info, i); ++ if (ret < 0) ++ return ret; ++ ++ /* ++ * Get VOUT format for READ_VOUT command : VID or direct. ++ * Pages on same device can be configured with different ++ * formats. ++ */ ++ ret = mp2975_identify_vout_format(client, data, i); ++ if (ret < 0) ++ return ret; ++ ++ /* ++ * Set over-voltage fixed value. Thresholds are provided as ++ * fixed value, and tracking value. The minimum of them are ++ * exposed as over-voltage critical threshold. ++ */ ++ data->vout_ov_fixed[i] = data->vref[i] + ++ DIV_ROUND_CLOSEST(data->vref_off[i] * ++ data->vout_scale, ++ 10); ++ } ++ ++ return 0; ++} ++ ++static struct pmbus_driver_info mp2975_info = { ++ .pages = 1, ++ .format[PSC_VOLTAGE_IN] = linear, ++ .format[PSC_VOLTAGE_OUT] = direct, ++ .format[PSC_TEMPERATURE] = direct, ++ .format[PSC_CURRENT_IN] = linear, ++ .format[PSC_CURRENT_OUT] = direct, ++ .format[PSC_POWER] = direct, ++ .m[PSC_TEMPERATURE] = 1, ++ .m[PSC_VOLTAGE_OUT] = 1, ++ .R[PSC_VOLTAGE_OUT] = 3, ++ .m[PSC_CURRENT_OUT] = 1, ++ .m[PSC_POWER] = 1, ++ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ++ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | ++ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT | ++ PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT, ++ .read_byte_data = mp2975_read_byte_data, ++ .read_word_data = mp2975_read_word_data, ++}; ++ ++static int mp2975_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pmbus_driver_info *info; ++ struct mp2975_data *data; ++ int ret; ++ ++ data = devm_kzalloc(&client->dev, sizeof(struct mp2975_data), ++ GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ memcpy(&data->info, &mp2975_info, sizeof(*info)); ++ info = &data->info; ++ ++ /* Identify multiphase configuration for rail 2. */ ++ ret = mp2975_identify_multiphase_rail2(client); ++ if (ret < 0) ++ return ret; ++ ++ if (ret) ++ data->info.pages = MP2975_PAGE_NUM; ++ ++ if (ret) { ++ /* Two rails are connected. */ ++ data->info.pages = MP2975_PAGE_NUM; ++#if 0 ++ data->info.phases[1] = ret; ++#endif ++ data->info.func[1] = MP2975_RAIL2_FUNC; ++ } ++#if 0 ++ /* Identify multiphase configuration. */ ++ ret = mp2975_identify_multiphase(client, data, info); ++ if (ret) ++ return ret; ++#endif ++ /* Identify VID setting per rail. */ ++ ret = mp2975_identify_rails_vid(client, data, info); ++ if (ret < 0) ++ return ret; ++ ++ /* Obtain current sense gain of power stage. */ ++ ret = mp2975_current_sense_gain_get(client, data); ++ if (ret) ++ return ret; ++ ++ /* Obtain voltage reference values. */ ++ ret = mp2975_vref_get(client, data, info); ++ if (ret) ++ return ret; ++ ++ /* Obtain vout over-voltage scales. */ ++ ret = mp2975_vout_ov_scale_get(client, data, info); ++ if (ret < 0) ++ return ret; ++ ++ /* Obtain offsets, maximum and format for vout. */ ++ ret = mp2975_vout_per_rail_config_get(client, data, info); ++ if (ret) ++ return ret; ++ ++ return pmbus_do_probe(client, id, info); ++} ++ ++static const struct i2c_device_id mp2975_id[] = { ++ {"mp2975", 0}, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(i2c, mp2975_id); ++ ++static const struct of_device_id __maybe_unused mp2975_of_match[] = { ++ {.compatible = "mps,mp2975"}, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, mp2975_of_match); ++ ++static struct i2c_driver mp2975_driver = { ++ .driver = { ++ .name = "mp2975", ++ .of_match_table = of_match_ptr(mp2975_of_match), ++ }, ++ .probe = mp2975_probe, ++ .remove = pmbus_do_remove, ++ .id_table = mp2975_id, ++}; ++ ++module_i2c_driver(mp2975_driver); ++ ++MODULE_AUTHOR("Vadim Pasternak "); ++MODULE_DESCRIPTION("PMBus driver for MPS MP2975 device"); ++MODULE_LICENSE("GPL"); +-- +2.8.4 + diff --git a/patch/0070-mlxsw-core-Increase-critical-threshold-for-ASIC-ther.patch b/patch/0077-mlxsw-core-Increase-critical-threshold-for-ASIC-ther.patch similarity index 100% rename from patch/0070-mlxsw-core-Increase-critical-threshold-for-ASIC-ther.patch rename to patch/0077-mlxsw-core-Increase-critical-threshold-for-ASIC-ther.patch diff --git a/patch/0071-mlxsw-core-Add-validation-of-transceiver-temperature.patch b/patch/0078-mlxsw-core-Add-validation-of-transceiver-temperature.patch similarity index 100% rename from patch/0071-mlxsw-core-Add-validation-of-transceiver-temperature.patch rename to patch/0078-mlxsw-core-Add-validation-of-transceiver-temperature.patch diff --git a/patch/0072-mlxsw-core-Remove-critical-trip-point-from-thermal-z.patch b/patch/0079-mlxsw-core-Remove-critical-trip-point-from-thermal-z.patch similarity index 100% rename from patch/0072-mlxsw-core-Remove-critical-trip-point-from-thermal-z.patch rename to patch/0079-mlxsw-core-Remove-critical-trip-point-from-thermal-z.patch diff --git a/patch/config-sensor-mp2975.patch b/patch/config-sensor-mp2975.patch new file mode 100644 index 000000000..882b590f6 --- /dev/null +++ b/patch/config-sensor-mp2975.patch @@ -0,0 +1,12 @@ +diff --git a/debian/build/build_amd64_none_amd64/.config b/debian/build/build_amd64_none_amd64/.config +index 286b750..718ae95 100644 +--- a/debian/build/build_amd64_none_amd64/.config ++++ b/debian/build/build_amd64_none_amd64/.config +@@ -3971,6 +3971,7 @@ CONFIG_SENSORS_TPS53679=m + CONFIG_SENSORS_UCD9000=m + CONFIG_SENSORS_UCD9200=m + CONFIG_SENSORS_XDPE122=m ++CONFIG_SENSORS_MP2975=m + # CONFIG_SENSORS_ZL6100 is not set + CONFIG_SENSORS_DPS1900=m + # CONFIG_SENSORS_SHT15 is not set diff --git a/patch/series b/patch/series index 223cb3341..ee116af27 100755 --- a/patch/series +++ b/patch/series @@ -105,9 +105,15 @@ linux-4.13-thermal-intel_pch_thermal-Fix-enable-check-on.patch 0067-Add-support-for-new-transceivers-types-QSFP-DD-and-Q.patch 0068-mlxsw-core-thermal-Separate-temperature-trend-read-c.patch 0069-watchdog-mlx-wdt-support-new-watchdog-type-with-long.patch -0070-mlxsw-core-Increase-critical-threshold-for-ASIC-ther.patch -0071-mlxsw-core-Add-validation-of-transceiver-temperature.patch -0072-mlxsw-core-Remove-critical-trip-point-from-thermal-z.patch +0071-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch +0072-thermal-Fix-deadlock-in-thermal-thermal_zone_device_.patch +0073-mlxsw-core-Fix-memory-leak-on-module-removal.patch +0074-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch +0075-platform-x86-mlx-platform-Remove-PSU-EEPROM-configur.patch +0076-hwmon-pmbus-Add-support-for-MPS-Multi-phase-mp2975-c.patch +0077-mlxsw-core-Increase-critical-threshold-for-ASIC-ther.patch +0078-mlxsw-core-Add-validation-of-transceiver-temperature.patch +0079-mlxsw-core-Remove-critical-trip-point-from-thermal-z.patch linux-4.16-firmware-dmi-handle-missing-DMI-data-gracefully.patch mellanox-backport-introduce-psample-a-new-genetlink-channel.patch mellanox-backport-introduce-tc-sample-action.patch @@ -120,6 +126,7 @@ Support-for-fullcone-nat.patch driver-ixgbe-external-phy.patch fix_ismt_alignment_issue.patch net-psample-module-unload.patch +config-sensor-mp2975.patch # # This series applies on GIT commit 1451b36b2b0d62178e42f648d8a18131af18f7d8 # Tkernel-sched-core-fix-cgroup-fork-race.patch