787dd7221d
Why I did it Add platform support for Debian 12 (Bookworm) on Mellanox Platform How I did it Update hw-management to v7.0030.2008 Deprecate the sfp_count == module_count approach in favour of asic init completion Ref: Mellanox/hw-mgmt@bf4f593 Add xxd package to base image which is required by hw-management scripts Add the non-upstream flag into linux kernel cache options Update the thermalctl logic based on new sysfs attributes Fix the integrate-mlnx-hw-mgmt script to not populate the arm64 Kconfig How to verify it Build kernel and run platform tests Signed-off-by: Vivek Reddy <vkarri@nvidia.com> Co-authored-by: Junchao-Mellanox <junchao@nvidia.com> Co-authored-by: Junchao-Mellanox <57339448+Junchao-Mellanox@users.noreply.github.com>
564 lines
15 KiB
Diff
564 lines
15 KiB
Diff
From c8a04a4c79a9fb99215e93884ff76b89e9947275 Mon Sep 17 00:00:00 2001
|
||
From: Vadim Pasternak <vadimp@nvidia.com>
|
||
Date: Thu, 13 Jul 2023 06:16:53 +0000
|
||
Subject: [PATCH backport 6.1.42 48/85] hwmon: (pmbus) Add support for MPS
|
||
Multi-phase mp2891 controller
|
||
MIME-Version: 1.0
|
||
Content-Type: text/plain; charset=UTF-8
|
||
Content-Transfer-Encoding: 8bit
|
||
|
||
Introduce driver for dual-loop, digital, multi-phase controller MP2891 from
|
||
Monolithic Power Systems, Inc. (MPS) vendor.
|
||
|
||
The MP2891 can work with MPS’s Intelli-PhaseTM products to complete the
|
||
multi-phase voltage regulator (VR) solution with minimal external
|
||
components.
|
||
|
||
This device supports:
|
||
- Two power rails.
|
||
- Programmable Multi-Phase up to 16 Phases on rail 1, and a maximum of 8
|
||
phases on rail 2.
|
||
|
||
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
|
||
---
|
||
Documentation/hwmon/mp2891.rst | 128 ++++++++++++
|
||
drivers/hwmon/pmbus/Kconfig | 9 +
|
||
drivers/hwmon/pmbus/Makefile | 1 +
|
||
drivers/hwmon/pmbus/mp2891.c | 357 +++++++++++++++++++++++++++++++++
|
||
4 files changed, 495 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
|
||
--- /dev/null
|
||
+++ b/Documentation/hwmon/mp2891.rst
|
||
@@ -0,0 +1,128 @@
|
||
+.. SPDX-License-Identifier: GPL-2.0
|
||
+
|
||
+Kernel driver mp2891
|
||
+====================
|
||
+
|
||
+Supported chips:
|
||
+
|
||
+ * MPS MP2891
|
||
+
|
||
+ Prefix: 'mp2891'
|
||
+
|
||
+Author:
|
||
+
|
||
+ Vadim Pasternak <vadimp@nvidia.com>
|
||
+
|
||
+Description
|
||
+-----------
|
||
+
|
||
+This driver implements support for Monolithic Power Systems, Inc. (MPS)
|
||
+vendor dual-loop, digital, multi-phase controller MP2891.
|
||
+The MP2891 can work with MPS’s Intelli-PhaseTM products to complete the
|
||
+multi-phase voltage regulator (VR) solution with minimal external components.
|
||
+
|
||
+MP2891 is available in a QFN-56 (7mmx7mm) package.
|
||
+
|
||
+This device supports:
|
||
+
|
||
+- Two power rails.
|
||
+- Programmable Multi-Phase up to 16 Phases on rail 1, and a maximum of 8 phases
|
||
+ on rail 2.
|
||
+- PWM-VID Interface.
|
||
+- Two pages for telemetry.
|
||
+- Programmable pins for PMBus Address.
|
||
+- Ability to store and restore device configurations.
|
||
+- 200kHz to 3MHz Switching Frequency.
|
||
+- Automatic Loop Compensation.
|
||
+- Couple Inductor Mode.
|
||
+- Supports Multi-Configuration for 6 Different Applications.
|
||
+- Flexible Pulse-Width Modulation (PWM) Assignment for 2 Rails.
|
||
+- Automatic Phase-Shedding (APS) to Improve Overall Efficiency.
|
||
+- Phase-to-Phase Active Current Balancing with Configurable Offsets for Thermal
|
||
+ Balance.
|
||
+- Digital Load-Line Regulation.
|
||
+- Overclocking Mode by Adding Offset to VOUT.
|
||
+
|
||
+Device complaint with:
|
||
+
|
||
+- PMBus rev 1.3 interface.
|
||
+
|
||
+Device supports direct format for reading output current, output voltage,
|
||
+input and output power and temperature.
|
||
+Device supports linear format for reading input voltage and input power.
|
||
+
|
||
+The driver provides the next attributes for the current:
|
||
+
|
||
+- for current out input and maximum alarm;
|
||
+- for phase current: input and label.
|
||
+
|
||
+The driver exports the following attributes via the 'sysfs' files, where:
|
||
+
|
||
+- 'n' is number of configured phases (from 1 to 10);
|
||
+- index 1 for "iout";
|
||
+- indexes 2 ... 1 + n for phases.
|
||
+
|
||
+**curr[1-{1+n}]_input**
|
||
+
|
||
+**curr[1-{1+n}]_label**
|
||
+
|
||
+**curr1_max**
|
||
+
|
||
+**curr1_max_alarm**
|
||
+
|
||
+The driver provides the next attributes for the voltage:
|
||
+
|
||
+- for voltage in: input, low and high critical thresholds, low and high
|
||
+ critical alarms;
|
||
+- for voltage out: input and high alarm;
|
||
+
|
||
+The driver exports the following attributes via the 'sysfs' files, where
|
||
+
|
||
+**in1_crit**
|
||
+
|
||
+**in1_crit_alarm**
|
||
+
|
||
+**in1_input**
|
||
+
|
||
+**in1_label**
|
||
+
|
||
+**in1_min**
|
||
+
|
||
+**in1_min_alarm**
|
||
+
|
||
+**in2_alarm**
|
||
+
|
||
+**in2_input**
|
||
+
|
||
+**in2_label**
|
||
+
|
||
+The driver provides the next attributes for the power:
|
||
+
|
||
+- for power in alarm and input.
|
||
+- for power out: cap, cap alarm an input.
|
||
+
|
||
+The driver exports the following attributes via the 'sysfs' files, where
|
||
+- indexes 1 for "pin";
|
||
+- indexes 2 for "pout";
|
||
+
|
||
+**power1_alarm**
|
||
+
|
||
+**power1_input**
|
||
+
|
||
+**power1_label**
|
||
+
|
||
+**power2_input**
|
||
+
|
||
+**power2_label**
|
||
+
|
||
+**power2_max**
|
||
+
|
||
+**power2_max_alarm**
|
||
+
|
||
+The driver provides the next attributes for the temperature:
|
||
+
|
||
+**temp1_input**
|
||
+
|
||
+**temp1_max**
|
||
+
|
||
+**temp1_max_alarm**
|
||
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
|
||
index 89668af67206..77d67344cee4 100644
|
||
--- a/drivers/hwmon/pmbus/Kconfig
|
||
+++ b/drivers/hwmon/pmbus/Kconfig
|
||
@@ -299,6 +299,15 @@ config SENSORS_MP2888
|
||
This driver can also be built as a module. If so, the module will
|
||
be called mp2888.
|
||
|
||
+config SENSORS_MP2891
|
||
+ tristate "MPS MP2891"
|
||
+ help
|
||
+ If you say yes here you get hardware monitoring support for MPS
|
||
+ MP2891 Dual Loop Digital Multi-Phase Controller.
|
||
+
|
||
+ This driver can also be built as a module. If so, the module will
|
||
+ be called mp2891.
|
||
+
|
||
config SENSORS_MP2975
|
||
tristate "MPS MP2975"
|
||
help
|
||
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
|
||
index 0002dbe22d52..8e767d7b8c5b 100644
|
||
--- a/drivers/hwmon/pmbus/Makefile
|
||
+++ b/drivers/hwmon/pmbus/Makefile
|
||
@@ -32,6 +32,7 @@ obj-$(CONFIG_SENSORS_MAX31785) += max31785.o
|
||
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
|
||
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
|
||
obj-$(CONFIG_SENSORS_MP2888) += mp2888.o
|
||
+obj-$(CONFIG_SENSORS_MP2891) += mp2891.o
|
||
obj-$(CONFIG_SENSORS_MP2975) += mp2975.o
|
||
obj-$(CONFIG_SENSORS_MP5023) += mp5023.o
|
||
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..e9e82844ee2a
|
||
--- /dev/null
|
||
+++ b/drivers/hwmon/pmbus/mp2891.c
|
||
@@ -0,0 +1,357 @@
|
||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||
+/*
|
||
+ * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers(MP2891)
|
||
+ *
|
||
+ * Copyright (C) 2023 Nvidia
|
||
+ */
|
||
+
|
||
+#include <linux/err.h>
|
||
+#include <linux/i2c.h>
|
||
+#include <linux/init.h>
|
||
+#include <linux/kernel.h>
|
||
+#include <linux/module.h>
|
||
+#include "pmbus.h"
|
||
+
|
||
+/* Vendor specific registers. */
|
||
+/*
|
||
+ * MP2891_MFR_SVI3_IOUT_PRT:
|
||
+ * bits 15:5 - reserved zeros;
|
||
+ * bits 4:3 - set SVI3 Vout digital filter
|
||
+ * b00: 5kHz
|
||
+ * b01: 2kHz
|
||
+ * b10: 1kHz
|
||
+ * b11: no filter
|
||
+ * bits 2:0 - define output current scaling selection of rail1.
|
||
+ * b000: 1 A/LSB
|
||
+ * b001: (1/32) A/LSB
|
||
+ * b010: (1/16) A/LSB
|
||
+ * b011: (1/8) A/LSB
|
||
+ * b100: (1/4) A/LSB
|
||
+ * b101: (1/2) A/LSB
|
||
+ * b110: 1 A/LSB
|
||
+ * b111: 2 A/LSB
|
||
+ */
|
||
+#define MP2891_MFR_SVI3_IOUT_PRT 0x65
|
||
+/*
|
||
+ * MP2891_MFR_VOUT_LOOP_CTRL:
|
||
+ * bits 15:14 define the VID step.
|
||
+ * b00: 6.25mV
|
||
+ * b01: 5mV
|
||
+ * b10: 2mV
|
||
+ * b11: 1mV
|
||
+ * bit 13 enable bit of 2.5mV resolution.
|
||
+ * b0: disable
|
||
+ * b1: enable
|
||
+ * bits 12:11 reserved zeros
|
||
+ * bit 10 defines rail remote sense amplifier gain:
|
||
+ * b0: 1
|
||
+ * b1: 0.5
|
||
+ * bit 9 DC reference_select
|
||
+ * b0: Comp EA uses Vfb and Vref
|
||
+ * b1: Comp EA uses Vdiff and Vref
|
||
+ * bit 8 enables DC loop calibration at DCM.
|
||
+ * b0: disable
|
||
+ * b1: enable
|
||
+ * bit 7 enables DC loop calibration both at DCM and CCM operation.
|
||
+ * b0: disable
|
||
+ * b1: enable
|
||
+ * bit 6 - holds DC loop when the PWM time interval meets PWM switching period condition
|
||
+ * set with PMBus command MFR_VR_CONFIG1 (B7h), bit [3:2].
|
||
+ * b0: disable hold DC loop when PWM switching period condition meets
|
||
+ * b1: hold DC loop when PWM switching period condition meets
|
||
+ * bit 5 hold DC loop when phase count is changed.
|
||
+ * b0: disable hold DC loop when phase number change
|
||
+ * b1: hold the DC loop when phase number change.
|
||
+ * bit 4 hold DC loop regulation when a load transient event is detected.
|
||
+ * b0: disable hold DC loop when meets VFB+/- window condition
|
||
+ * b1: hold DC loop when meets VFB+/- window condition
|
||
+ * bits 3:0 set the DC loop minimal holding time in direct format.
|
||
+ */
|
||
+#define MP2891_MFR_VOUT_LOOP_CTRL 0xbd
|
||
+
|
||
+#define MP2891_VID_STEP_POS 14
|
||
+#define MP2891_VID_STEP_MASK GENMASK(MP2891_VID_STEP_POS + 1, MP2891_VID_STEP_POS)
|
||
+#define MP2891_DAC_2P5MV_MASK BIT(13)
|
||
+#define MP2891_IOUT_SCALE_MASK GENMASK(2, 0)
|
||
+
|
||
+#define MP2891_PAGE_NUM 2
|
||
+#define MP2891_RAIL1_FUNC (PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | \
|
||
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | \
|
||
+ PMBUS_PHASE_VIRTUAL)
|
||
+
|
||
+#define MP2891_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP | \
|
||
+ PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL)
|
||
+
|
||
+struct mp2891_data {
|
||
+ struct pmbus_driver_info info;
|
||
+ int vid_step[MP2891_PAGE_NUM];
|
||
+ int iout_scale[MP2891_PAGE_NUM];
|
||
+};
|
||
+
|
||
+#define to_mp2891_data(x) container_of(x, struct mp2891_data, info)
|
||
+
|
||
+static int mp2891_read_vout(struct i2c_client *client, int page, int phase, int reg)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||
+ struct mp2891_data *data = to_mp2891_data(info);
|
||
+
|
||
+ ret = pmbus_read_word_data(client, page, phase, reg);
|
||
+
|
||
+ return ret < 0 ? ret : ret * data->vid_step[page] / 100;
|
||
+}
|
||
+
|
||
+static int mp2891_read_iout(struct i2c_client *client, int page, int phase, int reg)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||
+ struct mp2891_data *data = to_mp2891_data(info);
|
||
+
|
||
+ ret = pmbus_read_word_data(client, page, phase, reg);
|
||
+
|
||
+ return ret < 0 ? ret : ret * data->iout_scale[page];
|
||
+}
|
||
+
|
||
+static int mp2891_read_byte_data(struct i2c_client *client, int page, int reg)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ 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.
|
||
+ */
|
||
+ ret = PB_VOUT_MODE_DIRECT;
|
||
+ break;
|
||
+ default:
|
||
+ ret = -EINVAL;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+static int mp2891_read_word_data(struct i2c_client *client, int page, int phase, int reg)
|
||
+{
|
||
+ switch (reg) {
|
||
+ case PMBUS_READ_VOUT:
|
||
+ return mp2891_read_vout(client, page, phase, reg);
|
||
+ case PMBUS_READ_IOUT:
|
||
+ return mp2891_read_iout(client, page, phase, reg);
|
||
+ case PMBUS_OT_WARN_LIMIT:
|
||
+ case PMBUS_OT_FAULT_LIMIT:
|
||
+ case PMBUS_UT_WARN_LIMIT:
|
||
+ case PMBUS_UT_FAULT_LIMIT:
|
||
+ case PMBUS_VOUT_OV_WARN_LIMIT:
|
||
+ case PMBUS_VIN_OV_WARN_LIMIT:
|
||
+ case PMBUS_POUT_MAX:
|
||
+ case PMBUS_POUT_OP_FAULT_LIMIT:
|
||
+ case PMBUS_MFR_VIN_MIN:
|
||
+ case PMBUS_MFR_VOUT_MIN:
|
||
+ case PMBUS_MFR_VIN_MAX:
|
||
+ case PMBUS_MFR_VOUT_MAX:
|
||
+ case PMBUS_MFR_IIN_MAX:
|
||
+ case PMBUS_MFR_IOUT_MAX:
|
||
+ case PMBUS_MFR_PIN_MAX:
|
||
+ case PMBUS_MFR_POUT_MAX:
|
||
+ case PMBUS_MFR_MAX_TEMP_1:
|
||
+ return -ENXIO;
|
||
+ default:
|
||
+ return -EINVAL;
|
||
+ }
|
||
+}
|
||
+
|
||
+static int mp2891_identify_vid(struct i2c_client *client, struct mp2891_data *data, u32 reg,
|
||
+ int page)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
|
||
+ if (ret < 0)
|
||
+ return ret;
|
||
+
|
||
+ ret = i2c_smbus_read_word_data(client, reg);
|
||
+ if (ret < 0)
|
||
+ return ret;
|
||
+
|
||
+ /*
|
||
+ * Obtain vid_step from MP2891_MFR_VOUT_LOOP_CTRL register:
|
||
+ * bit 13 = 1, the vid_step is below 2.5mV/LSB;
|
||
+ * 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) {
|
||
+ data->vid_step[page] = 250;
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ switch ((ret & MP2891_VID_STEP_MASK) >> MP2891_VID_STEP_POS) {
|
||
+ case 0:
|
||
+ data->vid_step[page] = 625;
|
||
+ break;
|
||
+ case 1:
|
||
+ data->vid_step[page] = 500;
|
||
+ break;
|
||
+ case 2:
|
||
+ data->vid_step[page] = 200;
|
||
+ break;
|
||
+ default:
|
||
+ data->vid_step[page] = 100;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int mp2891_identify_rails_vid(struct i2c_client *client, struct mp2891_data *data)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ /* Identify vid_step for rail 1. */
|
||
+ ret = mp2891_identify_vid(client, data, MP2891_MFR_VOUT_LOOP_CTRL, 0);
|
||
+ if (ret < 0)
|
||
+ return ret;
|
||
+
|
||
+ /* Identify vid_step for rail 2. */
|
||
+ return mp2891_identify_vid(client, data, MP2891_MFR_VOUT_LOOP_CTRL, 1);
|
||
+}
|
||
+
|
||
+static int
|
||
+mp2891_iout_scale_get(struct i2c_client *client, struct mp2891_data *data, u32 reg, int page)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
|
||
+ if (ret < 0)
|
||
+ return ret;
|
||
+
|
||
+ ret = i2c_smbus_read_word_data(client, reg);
|
||
+ if (ret < 0)
|
||
+ return ret;
|
||
+
|
||
+ /*
|
||
+ * Obtain iout_scale from the register MP2891_MFR_SVI3_IOUT_PRT, bits 2-0.
|
||
+ * The value is selected as below:
|
||
+ * 000b - 1A/LSB, 001b - (1/32)A/LSB, 010b - (1/16)A/LSB,
|
||
+ * 011b - (1/8)A/LSB, 100b - (1/4)A/LSB, 101b - (1/2)A/LSB
|
||
+ * 110b - 1A/LSB, 111b - 2A/LSB
|
||
+ */
|
||
+ switch (ret & MP2891_IOUT_SCALE_MASK) {
|
||
+ case 0:
|
||
+ case 6:
|
||
+ data->iout_scale[page] = 32;
|
||
+ return 0;
|
||
+ case 1:
|
||
+ data->iout_scale[page] = 1;
|
||
+ return 0;
|
||
+ case 2:
|
||
+ data->iout_scale[page] = 2;
|
||
+ return 0;
|
||
+ case 3:
|
||
+ data->iout_scale[page] = 4;
|
||
+ return 0;
|
||
+ case 4:
|
||
+ data->iout_scale[page] = 8;
|
||
+ return 0;
|
||
+ case 5:
|
||
+ data->iout_scale[page] = 16;
|
||
+ return 0;
|
||
+ default:
|
||
+ data->iout_scale[page] = 64;
|
||
+ return 0;
|
||
+ }
|
||
+}
|
||
+
|
||
+static int mp2891_rails_iout_scale_get(struct i2c_client *client, struct mp2891_data *data)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ /* Get iout_scale for rail 1. */
|
||
+ ret = mp2891_iout_scale_get(client, data, MP2891_MFR_SVI3_IOUT_PRT, 0);
|
||
+ /* Get iout_scale for rail 2. */
|
||
+ return ret < 0 ? ret : mp2891_iout_scale_get(client, data, MP2891_MFR_SVI3_IOUT_PRT, 1);
|
||
+}
|
||
+
|
||
+static struct pmbus_driver_info mp2891_info = {
|
||
+ .pages = MP2891_PAGE_NUM,
|
||
+ .format[PSC_VOLTAGE_IN] = direct,
|
||
+ .format[PSC_VOLTAGE_OUT] = direct,
|
||
+ .format[PSC_CURRENT_OUT] = direct,
|
||
+ .format[PSC_TEMPERATURE] = direct,
|
||
+ .format[PSC_POWER] = linear,
|
||
+ .m[PSC_VOLTAGE_IN] = 1,
|
||
+ .m[PSC_VOLTAGE_OUT] = 1,
|
||
+ .m[PSC_CURRENT_OUT] = 32,
|
||
+ .m[PSC_TEMPERATURE] = 1,
|
||
+ .R[PSC_VOLTAGE_IN] = 3,
|
||
+ .R[PSC_VOLTAGE_OUT] = 3,
|
||
+ .R[PSC_CURRENT_OUT] = 0,
|
||
+ .R[PSC_TEMPERATURE] = 0,
|
||
+ .b[PSC_VOLTAGE_IN] = 0,
|
||
+ .b[PSC_VOLTAGE_OUT] = 0,
|
||
+ .b[PSC_CURRENT_OUT] = 0,
|
||
+ .b[PSC_TEMPERATURE] = 0,
|
||
+ .func[0] = MP2891_RAIL1_FUNC,
|
||
+ .func[1] = MP2891_RAIL2_FUNC,
|
||
+ .read_word_data = mp2891_read_word_data,
|
||
+ .read_byte_data = mp2891_read_byte_data,
|
||
+};
|
||
+
|
||
+static int mp2891_probe(struct i2c_client *client)
|
||
+{
|
||
+ struct pmbus_driver_info *info;
|
||
+ struct mp2891_data *data;
|
||
+ int ret;
|
||
+
|
||
+ data = devm_kzalloc(&client->dev, sizeof(struct mp2891_data), GFP_KERNEL);
|
||
+
|
||
+ if (!data)
|
||
+ return -ENOMEM;
|
||
+
|
||
+ memcpy(&data->info, &mp2891_info, sizeof(*info));
|
||
+ info = &data->info;
|
||
+
|
||
+ /* Identify VID setting per rail - obtain the vid_step of output voltage. */
|
||
+ ret = mp2891_identify_rails_vid(client, data);
|
||
+ if (ret < 0)
|
||
+ return ret;
|
||
+
|
||
+ /* Get iout scale per rail - obtain current scale. */
|
||
+ ret = mp2891_rails_iout_scale_get(client, data);
|
||
+ if (ret < 0)
|
||
+ return ret;
|
||
+
|
||
+ return pmbus_do_probe(client, info);
|
||
+}
|
||
+
|
||
+static const struct i2c_device_id mp2891_id[] = {
|
||
+ {"mp2891", 0},
|
||
+ {}
|
||
+};
|
||
+MODULE_DEVICE_TABLE(i2c, mp2891_id);
|
||
+
|
||
+static const struct of_device_id __maybe_unused mp2891_of_match[] = {
|
||
+ {.compatible = "mps,mp2891"},
|
||
+ {}
|
||
+};
|
||
+MODULE_DEVICE_TABLE(of, mp2891_of_match);
|
||
+
|
||
+static struct i2c_driver mp2891_driver = {
|
||
+ .driver = {
|
||
+ .name = "mp2891",
|
||
+ .of_match_table = mp2891_of_match,
|
||
+ },
|
||
+ .probe_new = mp2891_probe,
|
||
+ .id_table = mp2891_id,
|
||
+};
|
||
+
|
||
+module_i2c_driver(mp2891_driver);
|
||
+
|
||
+MODULE_DESCRIPTION("PMBus driver for MPS MP2891 device");
|
||
+MODULE_LICENSE("GPL");
|
||
+MODULE_IMPORT_NS(PMBUS);
|
||
--
|
||
2.20.1
|
||
|