2023-07-14 14:05:50

by Naresh Solanki

[permalink] [raw]
Subject: [PATCH v2 1/8] hwmon: (pmbus/mp2975) Fix whitespace error

From: Patrick Rudolph <[email protected]>

Fix whitespace error reported by checkpatch.pl

Signed-off-by: Patrick Rudolph <[email protected]>
Signed-off-by: Naresh Solanki <[email protected]>
---
drivers/hwmon/pmbus/mp2975.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c
index 2109b0458a8b..130cfde52e42 100644
--- a/drivers/hwmon/pmbus/mp2975.c
+++ b/drivers/hwmon/pmbus/mp2975.c
@@ -600,7 +600,7 @@ mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data,
if (ret < 0)
return ret;
thres_dev = ret & MP2975_PRT_THRES_DIV_OV_EN ? MP2975_PROT_DEV_OV_ON :
- MP2975_PROT_DEV_OV_OFF;
+ MP2975_PROT_DEV_OV_OFF;

/* Select the gain of remote sense amplifier. */
ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_SCALE_LOOP);

base-commit: 4dbbaf8fbdbd13adc80731b2452257857e4c2d8b
--
2.41.0



2023-07-14 14:07:36

by Naresh Solanki

[permalink] [raw]
Subject: [PATCH v2 8/8] hwmon: (pmbus/mp2975) Add OCP limit

From: Patrick Rudolph <[email protected]>

Add support for PMBUS_IOUT_OC_FAULT_LIMIT.
Add a helper function to convert the limit to LINEAR11 format
and read data->info.phases[0] on MP2971 and MP2973 as well.

Signed-off-by: Patrick Rudolph <[email protected]>
Signed-off-by: Naresh Solanki <[email protected]>
---
drivers/hwmon/pmbus/mp2975.c | 76 ++++++++++++++++++++++++++++++------
1 file changed, 65 insertions(+), 11 deletions(-)

diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c
index 7684f8667657..0b1983d5998b 100644
--- a/drivers/hwmon/pmbus/mp2975.c
+++ b/drivers/hwmon/pmbus/mp2975.c
@@ -65,6 +65,10 @@
#define MP2973_VID_STEP_SEL_R2 BIT(3)
#define MP2973_IMVP9_EN_R2 BIT(13)

+#define MP2973_MFR_OCP_TOTAL_SET 0x5f
+#define MP2973_OCP_TOTAL_CUR_MASK GENMASK(6, 0)
+#define MP2973_MFR_OCP_LEVEL_RES BIT(15)
+
#define MP2973_MFR_READ_IOUT_PK 0x90
#define MP2973_MFR_READ_POUT_PK 0x91

@@ -153,6 +157,41 @@ mp2975_vid2direct(int vrf, int val)
return 0;
}

+#define MAX_LIN_MANTISSA (1023 * 1000)
+#define MIN_LIN_MANTISSA (511 * 1000)
+
+/* Converts a milli-unit DIRECT value to LINEAR11 format */
+static u16 mp2975_data2reg_linear11(s64 val)
+{
+ s16 exponent = 0, mantissa;
+ bool negative = false;
+
+ /* simple case */
+ if (val == 0)
+ return 0;
+
+ /* Reduce large mantissa until it fits into 10 bit */
+ while (val >= MAX_LIN_MANTISSA && exponent < 15) {
+ exponent++;
+ val >>= 1;
+ }
+ /* Increase small mantissa to improve precision */
+ while (val < MIN_LIN_MANTISSA && exponent > -15) {
+ exponent--;
+ val <<= 1;
+ }
+
+ /* Convert mantissa from milli-units to units */
+ mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff);
+
+ /* restore sign */
+ if (negative)
+ mantissa = -mantissa;
+
+ /* Convert to 5 bit exponent, 11 bit mantissa */
+ return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
+}
+
static int
mp2975_read_phase(struct i2c_client *client, struct mp2975_data *data,
int page, int phase, u8 reg)
@@ -297,6 +336,20 @@ static int mp2973_read_word_data(struct i2c_client *client, int page,
ret = pmbus_read_word_data(client, page, phase,
MP2973_MFR_READ_IOUT_PK);
break;
+ case PMBUS_IOUT_OC_FAULT_LIMIT:
+ ret = mp2975_read_word_helper(client, page, phase,
+ MP2973_MFR_OCP_TOTAL_SET,
+ GENMASK(15, 0));
+ if (ret < 0)
+ return ret;
+
+ if (ret & MP2973_MFR_OCP_LEVEL_RES)
+ ret = 2 * (ret & MP2973_OCP_TOTAL_CUR_MASK);
+ else
+ ret = ret & MP2973_OCP_TOTAL_CUR_MASK;
+
+ ret = mp2975_data2reg_linear11(ret * info->phases[page] * 1000);
+ break;
case PMBUS_UT_WARN_LIMIT:
case PMBUS_UT_FAULT_LIMIT:
case PMBUS_VIN_UV_WARN_LIMIT:
@@ -307,7 +360,6 @@ static int mp2973_read_word_data(struct i2c_client *client, int page,
case PMBUS_IIN_OC_FAULT_LIMIT:
case PMBUS_IOUT_OC_LV_FAULT_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:
@@ -481,11 +533,13 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data,
if (info->phases[0] > data->max_phases[0])
return -EINVAL;

- mp2975_set_phase_rail1(info);
- num_phases2 = min(data->max_phases[0] - info->phases[0],
- data->max_phases[1]);
- if (info->phases[1] && info->phases[1] <= num_phases2)
- mp2975_set_phase_rail2(info, num_phases2);
+ if (data->chip_id == mp2975) {
+ mp2975_set_phase_rail1(info);
+ num_phases2 = min(data->max_phases[0] - info->phases[0],
+ data->max_phases[1]);
+ if (info->phases[1] && info->phases[1] <= num_phases2)
+ mp2975_set_phase_rail2(info, num_phases2);
+ }

return 0;
}
@@ -878,12 +932,12 @@ static int mp2975_probe(struct i2c_client *client)
data->info.num_regulators = MP2975_PAGE_NUM;
}

- if (data->chip_id == mp2975) {
- /* Identify multiphase configuration. */
- ret = mp2975_identify_multiphase(client, data, info);
- if (ret)
- return ret;
+ /* Identify multiphase configuration. */
+ ret = mp2975_identify_multiphase(client, data, info);
+ if (ret)
+ return ret;

+ if (data->chip_id == mp2975) {
/* Identify VID setting per rail. */
ret = mp2975_identify_rails_vid(client, data, info);
if (ret < 0)
--
2.41.0


2023-07-14 14:09:54

by Naresh Solanki

[permalink] [raw]
Subject: [PATCH v2 7/8] hwmon: (pmbus/mp2975) Add regulator support

From: Patrick Rudolph <[email protected]>

Add support to expose the PMBUS regulator.

Tested on MP2973 and MP2971.

Signed-off-by: Patrick Rudolph <[email protected]>
Signed-off-by: Naresh Solanki <[email protected]>
---
Changes in V2:
- Use IS_ENABLED for configs in if statement.
---
drivers/hwmon/pmbus/Kconfig | 7 +++++++
drivers/hwmon/pmbus/mp2975.c | 15 +++++++++++++++
2 files changed, 22 insertions(+)

diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 270b6336b76d..b4e93bd5835e 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -317,6 +317,13 @@ config SENSORS_MP2975
This driver can also be built as a module. If so, the module will
be called mp2975.

+config SENSORS_MP2975_REGULATOR
+ depends on SENSORS_MP2975 && REGULATOR
+ bool "Regulator support for MPS MP2975"
+ help
+ If you say yes here you get regulator support for MPS MP2975
+ Dual Loop Digital Multi-Phase Controller.
+
config SENSORS_MP5023
tristate "MPS MP5023"
help
diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c
index 4d72ed18cc8c..7684f8667657 100644
--- a/drivers/hwmon/pmbus/mp2975.c
+++ b/drivers/hwmon/pmbus/mp2975.c
@@ -115,6 +115,11 @@ static const struct i2c_device_id mp2975_id[] = {

MODULE_DEVICE_TABLE(i2c, mp2975_id);

+static const struct regulator_desc __maybe_unused mp2975_reg_desc[] = {
+ PMBUS_REGULATOR("vout", 0),
+ PMBUS_REGULATOR("vout", 1),
+};
+
#define to_mp2975_data(x) container_of(x, struct mp2975_data, info)

static int
@@ -806,6 +811,10 @@ static struct pmbus_driver_info mp2975_info = {
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL,
.read_word_data = mp2975_read_word_data,
+#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)
+ .num_regulators = 1,
+ .reg_desc = mp2975_reg_desc,
+#endif
};

static struct pmbus_driver_info mp2973_info = {
@@ -823,6 +832,10 @@ static struct pmbus_driver_info mp2973_info = {
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
.read_word_data = mp2973_read_word_data,
+#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)
+ .num_regulators = 1,
+ .reg_desc = mp2975_reg_desc,
+#endif
};

static int mp2975_probe(struct i2c_client *client)
@@ -861,6 +874,8 @@ static int mp2975_probe(struct i2c_client *client)
data->info.pages = MP2975_PAGE_NUM;
data->info.phases[1] = ret;
data->info.func[1] = MP2975_RAIL2_FUNC;
+ if (IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR))
+ data->info.num_regulators = MP2975_PAGE_NUM;
}

if (data->chip_id == mp2975) {
--
2.41.0


2023-07-14 14:16:50

by Naresh Solanki

[permalink] [raw]
Subject: [PATCH v2 5/8] hwmon: (pmbus/mp2975) Make phase count variable

From: Patrick Rudolph <[email protected]>

In order to add support for MP2973 and MP2971 replace hardcoded
phase count for both channels by a variable.

Signed-off-by: Patrick Rudolph <[email protected]>
Signed-off-by: Naresh Solanki <[email protected]>
---
drivers/hwmon/pmbus/mp2975.c | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c
index 0dca4c24fe5a..a4453b9284fa 100644
--- a/drivers/hwmon/pmbus/mp2975.c
+++ b/drivers/hwmon/pmbus/mp2975.c
@@ -61,10 +61,15 @@ enum chips {
mp2975
};

+static const int mp2975_max_phases[][MP2975_PAGE_NUM] = {
+ [mp2975] = { MP2975_MAX_PHASE_RAIL1, MP2975_MAX_PHASE_RAIL2 },
+};
+
struct mp2975_data {
struct pmbus_driver_info info;
enum chips chip_id;
int vout_scale;
+ int max_phases[MP2975_PAGE_NUM];
int vid_step[MP2975_PAGE_NUM];
int vref[MP2975_PAGE_NUM];
int vref_off[MP2975_PAGE_NUM];
@@ -304,25 +309,25 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
return ret;
}

-static int mp2975_identify_multiphase_rail2(struct i2c_client *client)
+static int mp2975_identify_multiphase_rail2(struct i2c_client *client,
+ struct mp2975_data *data)
{
int ret;

/*
- * Identify multiphase for rail 2 - could be from 0 to 4.
+ * Identify multiphase for rail 2 - could be from 0 to data->max_phases[1].
* 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;
+ return (ret >= data->max_phases[1]) ? data->max_phases[1] : ret;
}

static void mp2975_set_phase_rail1(struct pmbus_driver_info *info)
@@ -353,7 +358,7 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data,
if (ret < 0)
return ret;

- /* Identify multiphase for rail 1 - could be from 1 to 8. */
+ /* Identify multiphase for rail 1 - could be from 1 to data->max_phases[0]. */
ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R1);
if (ret <= 0)
return ret;
@@ -361,19 +366,19 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data,
info->phases[0] = ret & GENMASK(3, 0);

/*
- * The device provides a total of 8 PWM pins, and can be configured
+ * The device provides a total of $n 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
+ * Rail 1 can be set to $n phases, while rail 2 can be set to less than
+ * that. 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.
*/
- if (info->phases[0] > MP2975_MAX_PHASE_RAIL1)
+ if (info->phases[0] > data->max_phases[0])
return -EINVAL;

mp2975_set_phase_rail1(info);
- num_phases2 = min(MP2975_MAX_PHASE_RAIL1 - info->phases[0],
- MP2975_MAX_PHASE_RAIL2);
+ num_phases2 = min(data->max_phases[0] - info->phases[0],
+ data->max_phases[1]);
if (info->phases[1] && info->phases[1] <= num_phases2)
mp2975_set_phase_rail2(info, num_phases2);

@@ -669,11 +674,13 @@ static int mp2975_probe(struct i2c_client *client)
else
data->chip_id = i2c_match_id(mp2975_id, client)->driver_data;

- memcpy(&data->info, &mp2975_info, sizeof(*info));
+ memcpy(data->max_phases, mp2975_max_phases[data->chip_id],
+ sizeof(data->max_phases));
+
info = &data->info;

/* Identify multiphase configuration for rail 2. */
- ret = mp2975_identify_multiphase_rail2(client);
+ ret = mp2975_identify_multiphase_rail2(client, data);
if (ret < 0)
return ret;

--
2.41.0


2023-07-19 03:26:22

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 1/8] hwmon: (pmbus/mp2975) Fix whitespace error

On Fri, Jul 14, 2023 at 03:51:09PM +0200, Naresh Solanki wrote:
> From: Patrick Rudolph <[email protected]>
>
> Fix whitespace error reported by checkpatch.pl
>
> Signed-off-by: Patrick Rudolph <[email protected]>
> Signed-off-by: Naresh Solanki <[email protected]>

Applied.

Thanks,
Guenter

2023-07-19 03:26:32

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 8/8] hwmon: (pmbus/mp2975) Add OCP limit

On Fri, Jul 14, 2023 at 03:51:16PM +0200, Naresh Solanki wrote:
> From: Patrick Rudolph <[email protected]>
>
> Add support for PMBUS_IOUT_OC_FAULT_LIMIT.
> Add a helper function to convert the limit to LINEAR11 format
> and read data->info.phases[0] on MP2971 and MP2973 as well.
>
> Signed-off-by: Patrick Rudolph <[email protected]>
> Signed-off-by: Naresh Solanki <[email protected]>

Applied.

Thanks,
Guenter

2023-07-19 03:27:23

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 5/8] hwmon: (pmbus/mp2975) Make phase count variable

On Fri, Jul 14, 2023 at 03:51:13PM +0200, Naresh Solanki wrote:
> From: Patrick Rudolph <[email protected]>
>
> In order to add support for MP2973 and MP2971 replace hardcoded
> phase count for both channels by a variable.
>
> Signed-off-by: Patrick Rudolph <[email protected]>
> Signed-off-by: Naresh Solanki <[email protected]>

Applied.

Thanks,
Guenter

2023-07-19 04:24:10

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 7/8] hwmon: (pmbus/mp2975) Add regulator support

On Fri, Jul 14, 2023 at 03:51:15PM +0200, Naresh Solanki wrote:
> From: Patrick Rudolph <[email protected]>
>
> Add support to expose the PMBUS regulator.
>
> Tested on MP2973 and MP2971.
>
> Signed-off-by: Patrick Rudolph <[email protected]>
> Signed-off-by: Naresh Solanki <[email protected]>

Applied.

Thanks,
Guenter