hwmon: (pmbus/mp2975) Fix whitespace error
Subsystems (2)
PATCH 1/8 hwmon: (pmbus/mp2975) Fix whitespace error
From: Patrick Rudolph <[email protected]>
Fix whitespace error reported by checkpatch.pl
--- drivers/hwmon/pmbus/mp2975.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/pmbus/mp2975.c +1 -1
@@ -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
Signature · 1 line
2.41.0
PATCH 2/8 dt-bindings: trivial-devices: Add MPS MP2971 and MP2973
From: Patrick Rudolph <[email protected]>
Add Monolithic Power Systems MP2971 & MP2973 to trivial devices.
--- Documentation/devicetree/bindings/trivial-devices.yaml | 4 ++++ 1 file changed, 4 insertions(+)
Documentation/devicetree/bindings/trivial-devices.yaml +4 -0
@@ -119,6 +119,10 @@ properties: - fsl,mpr121 # Monolithic Power Systems Inc. multi-phase controller mp2888 - mps,mp2888 + # Monolithic Power Systems Inc. multi-phase controller mp2971 + - mps,mp2971 + # Monolithic Power Systems Inc. multi-phase controller mp2973 + - mps,mp2973 # Monolithic Power Systems Inc. multi-phase controller mp2975 - mps,mp2975 # Honeywell Humidicon HIH-6130 humidity/temperature sensor
Signature · 1 line
2.41.0
Re: [PATCH 2/8] dt-bindings: trivial-devices: Add MPS MP2971 and MP2973
Quoted 6 lines · Naresh Solanki
From: Patrick Rudolph <[email protected]>
Add Monolithic Power Systems MP2971 & MP2973 to trivial devices.
Signed-off-by Patrick Rudolph <[email protected]>Signed-off-by Naresh Solanki <[email protected]>
Best regards,
Krzysztof
PATCH 3/8 hwmon: (pmbus/mp2975) Prepare for MP2973 and MP2971
In reply to Naresh SolankiFrom: Patrick Rudolph <[email protected]>
Add support for differntiating between the chips. The following commits will make use of this mechanism.
--- drivers/hwmon/pmbus/mp2975.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
drivers/hwmon/pmbus/mp2975.c +19 -8
@@ -10,6 +10,7 @@#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of_device.h> #include "pmbus.h" /* Vendor specific registers. */
@@ -56,8 +57,13 @@ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \ PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL) +enum chips { + mp2975 +}; +struct mp2975_data {struct pmbus_driver_info info; +enum chips chip_id;int vout_scale;int vid_step[MP2975_PAGE_NUM ];int vref[MP2975_PAGE_NUM ];
@@ -68,6 +74,13 @@ struct mp2975_data {int curr_sense_gain[MP2975_PAGE_NUM ]; }; +static const struct i2c_device_id mp2975_id[] = { + {"mp2975" , mp2975}, + {} +}; + +MODULE_DEVICE_TABLE (i2c, mp2975_id); +#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)
@@ -691,6 +704,11 @@ static int mp2975_probe(struct i2c_client *client)if (!data)return -ENOMEM ; +if (client->dev.of_node) + data->chip_id = (enum chips )of_device_get_match_data (&client->dev); +else + data->chip_id =i2c_match_id (mp2975_id, client)->driver_data; +memcpy (&data->info, &mp2975_info,sizeof (*info)); info = &data->info;
@@ -739,15 +757,8 @@ static int mp2975_probe(struct i2c_client *client)return pmbus_do_probe (client, 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" }, + {.compatible ="mps,mp2975" , .data = (void *)mp2975}, {} };MODULE_DEVICE_TABLE (of, mp2975_of_match);
Signature · 1 line
2.41.0
PATCH 4/8 hwmon: (pmbus/mp2975) Simplify VOUT code
In reply to Naresh SolankiFrom: Patrick Rudolph <[email protected]>
In order to upstream MP2973/MP2971 simplify the code by removing support for various VOUT formats. The MP2973 and MP2971 supports all PMBUS supported formats for VOUT, while the MP2975 only support DIRECT and VID for VOUT.
In DIRECT mode all chips report the voltage in 1mV/LSB.
Configure the chip to use DIRECT format for VOUT and drop the code conversion code for other formats. The to be added chips MP2973/MP2971 will be configured to also report VOUT in DIRECT format.
The maximum voltage that can be reported in DIRECT format is 32768mV. This is sufficient as the maximum output voltage for VR12/VR13 is 3040 mV.
--- drivers/hwmon/pmbus/mp2975.c | 54 ++++++------------------------------ 1 file changed, 8 insertions(+), 46 deletions(-)
drivers/hwmon/pmbus/mp2975.c +8 -46
@@ -70,7 +70,6 @@ struct mp2975_data {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 ]; };
@@ -83,22 +82,6 @@ MODULE_DEVICE_TABLE(i2c, mp2975_id);#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 PB_VOUT_MODE_DIRECT ; -default : -return -ENODATA ; - } -} -static int mp2975_read_word_helper (struct i2c_client *client,int page,int phase,u8 reg,u16 mask)
@@ -273,24 +256,6 @@ static int mp2975_read_word_data(struct i2c_client *client, int page, 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,
@@ -578,20 +543,18 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_identify_vout_format (struct i2c_client *client, -struct mp2975_data *data,int page) +mp2975_set_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 ; +/* Enable DIRECT VOUT format 1mV/LSB */ + ret &= ~MP2975_VOUT_FORMAT ; + ret =i2c_smbus_write_word_data (client,MP2975_MFR_DC_LOOP_CTRL , ret); +return ret; } static int
@@ -650,11 +613,11 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,return ret;/* -* Get VOUT format for READ_VOUT command : VID or direct. +* Set VOUT format for READ_VOUT command : direct. * Pages on same device can be configured with different * formats. */ - ret =mp2975_identify_vout_format (client, data, i); + ret =mp2975_set_vout_format (client, data, i);if (ret <0 )return ret;
@@ -689,7 +652,6 @@ static struct pmbus_driver_info mp2975_info = {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 | PMBUS_PHASE_VIRTUAL, - .read_byte_data = mp2975_read_byte_data, .read_word_data = mp2975_read_word_data, };
Signature · 1 line
2.41.0
Guenter Roeck
maintainerRe: [PATCH 4/8] hwmon: (pmbus/mp2975) Simplify VOUT code
Quoted 96 lines · Naresh Solanki
From: Patrick Rudolph <[email protected]>
In order to upstream MP2973/MP2971 simplify the code by removing support for various VOUT formats. The MP2973 and MP2971 supports all PMBUS supported formats for VOUT, while the MP2975 only support DIRECT and VID for VOUT.
In DIRECT mode all chips report the voltage in 1mV/LSB.
Configure the chip to use DIRECT format for VOUT and drop the code conversion code for other formats. The to be added chips MP2973/MP2971 will be configured to also report VOUT in DIRECT format.
The maximum voltage that can be reported in DIRECT format is 32768mV. This is sufficient as the maximum output voltage for VR12/VR13 is 3040 mV.
Signed-off-by Patrick Rudolph <[email protected]>Signed-off-by Naresh Solanki <[email protected]>--- drivers/hwmon/pmbus/mp2975.c | 54 ++++++------------------------------ 1 file changed, 8 insertions(+), 46 deletions(-)drivers/hwmon/pmbus/mp2975.c +2
-37@@ -70,7 +70,6 @@ struct mp2975_data {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 ]; };@@ -83,22 +82,6 @@ MODULE_DEVICE_TABLE(i2c, mp2975_id);#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 PB_VOUT_MODE_DIRECT ; -default : -return -ENODATA ; - } -} -static int mp2975_read_word_helper (struct i2c_client *client,int page,int phase,u8 reg,u16 mask)@@ -273,24 +256,6 @@ static int mp2975_read_word_data(struct i2c_client *client, int page, 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,@@ -578,20 +543,18 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_identify_vout_format (struct i2c_client *client, -struct mp2975_data *data,int page) +mp2975_set_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 )
drivers/hwmon/pmbus/mp2975.c mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, · line 556
Quoted 10 lines
drivers/hwmon/pmbus/mp2975.c +3
-6return ret; - -if (ret &MP2975_VOUT_FORMAT ) - data->vout_format[page] = vid; -else - data->vout_format[page] = direct; -return 0 ; +/* Enable DIRECT VOUT format 1mV/LSB */ + ret &= ~MP2975_VOUT_FORMAT ; + ret =i2c_smbus_write_word_data (client,MP2975_MFR_DC_LOOP_CTRL , ret);
Writing this back is only needed if MP2975_VOUT_FORMAT was not already cleared.
drivers/hwmon/pmbus/mp2975.c mp2975_vout_per_rail_config_get(struct i2c_client *client, · line 618
Quoted 12 lines
drivers/hwmon/pmbus/mp2975.c +2
-1+return ret; } static int@@ -650,11 +613,11 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,return ret;/* -* Get VOUT format for READ_VOUT command : VID or direct. +* Set VOUT format for READ_VOUT command : direct. * Pages on same device can be configured with different * formats.
Not sure if this comment still makes sense.
Quoted 14 lines
drivers/hwmon/pmbus/mp2975.c +1
-2*/ - ret =mp2975_identify_vout_format (client, data, i); + ret =mp2975_set_vout_format (client, data, i);if (ret <0 )return ret;@@ -689,7 +652,6 @@ static struct pmbus_driver_info mp2975_info = {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 | PMBUS_PHASE_VIRTUAL, - .read_byte_data = mp2975_read_byte_data, .read_word_data = mp2975_read_word_data, };
Re: [PATCH 4/8] hwmon: (pmbus/mp2975) Simplify VOUT code
Hi Guenter,
Quoted 96 lines · Guenter Roeck
Quoted 94 lines · Naresh Solanki
From: Patrick Rudolph <[email protected]>
In order to upstream MP2973/MP2971 simplify the code by removing support for various VOUT formats. The MP2973 and MP2971 supports all PMBUS supported formats for VOUT, while the MP2975 only support DIRECT and VID for VOUT.
In DIRECT mode all chips report the voltage in 1mV/LSB.
Configure the chip to use DIRECT format for VOUT and drop the code conversion code for other formats. The to be added chips MP2973/MP2971 will be configured to also report VOUT in DIRECT format.
The maximum voltage that can be reported in DIRECT format is 32768mV. This is sufficient as the maximum output voltage for VR12/VR13 is 3040 mV.
Signed-off-by Patrick Rudolph <[email protected]>Signed-off-by Naresh Solanki <[email protected]>--- drivers/hwmon/pmbus/mp2975.c | 54 ++++++------------------------------ 1 file changed, 8 insertions(+), 46 deletions(-)drivers/hwmon/pmbus/mp2975.c +2
-37@@ -70,7 +70,6 @@ struct mp2975_data {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 ]; };@@ -83,22 +82,6 @@ MODULE_DEVICE_TABLE(i2c, mp2975_id);#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 PB_VOUT_MODE_DIRECT ; -default : -return -ENODATA ; - } -} -static int mp2975_read_word_helper (struct i2c_client *client,int page,int phase,u8 reg,u16 mask)@@ -273,24 +256,6 @@ static int mp2975_read_word_data(struct i2c_client *client, int page, 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,@@ -578,20 +543,18 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_identify_vout_format (struct i2c_client *client, -struct mp2975_data *data,int page) +mp2975_set_vout_format (struct i2c_client *client, +struct mp2975_data *data,int page) {int ret;
Quoted 14 lines
drivers/hwmon/pmbus/mp2975.c mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, · line 556
Quoted 12 lines
drivers/hwmon/pmbus/mp2975.c +3
-6ret =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 ; +/* Enable DIRECT VOUT format 1mV/LSB */ + ret &= ~MP2975_VOUT_FORMAT ; + ret =i2c_smbus_write_word_data (client,MP2975_MFR_DC_LOOP_CTRL , ret);Writing this back is only needed if
MP2975_VOUT_FORMATwas not already cleared.
Yes. Will optimize it as:
if (ret & MP2975_VOUT_FORMAT) {
ret &= ~MP2975_VOUT_FORMAT;
ret = i2c_smbus_write_word_data(client, MP2975_MFR_DC_LOOP_CTRL, ret); }
Quoted 8 lines
Quoted 8 lines
drivers/hwmon/pmbus/mp2975.c +1
-0+return ret; } static int@@ -650,11 +613,11 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,return ret;
Quoted 7 lines
drivers/hwmon/pmbus/mp2975.c mp2975_vout_per_rail_config_get(struct i2c_client *client, · line 618
Quoted 5 lines
drivers/hwmon/pmbus/mp2975.c +1
-1/* -* Get VOUT format for READ_VOUT command : VID or direct. +* Set VOUT format for READ_VOUT command : direct. * Pages on same device can be configured with different * formats. Not sure if this comment still makes sense.
Yes. Updated the comment as below:
/* Set VOUT format for READ_VOUT command : direct. */ ret = mp2975_set_vout_format(....
Quoted 7 lines
Quoted 7 lines
drivers/hwmon/pmbus/mp2975.c +1
-1*/ - ret =mp2975_identify_vout_format (client, data, i); + ret =mp2975_set_vout_format (client, data, i);if (ret <0 )return ret;
Quoted 9 lines
drivers/hwmon/pmbus/mp2975.c static struct pmbus_driver_info mp2975_info = { · line 657
Quoted 8 lines
drivers/hwmon/pmbus/mp2975.c +0
-1@@ -689,7 +652,6 @@ static struct pmbus_driver_info mp2975_info = {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 | PMBUS_PHASE_VIRTUAL, - .read_byte_data = mp2975_read_byte_data, .read_word_data = mp2975_read_word_data, };
Regards,
Naresh Solanki
PATCH 5/8 hwmon: (pmbus/mp2975) Make phase count variable
In reply to Naresh SolankiFrom: Patrick Rudolph <[email protected]>
In order to add support for MP2973 and MP2971 replace hardcoded phase count for both channels by a variable.
--- drivers/hwmon/pmbus/mp2975.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-)
drivers/hwmon/pmbus/mp2975.c +20 -13
@@ -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);
@@ -671,11 +676,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;
Signature · 1 line
2.41.0
PATCH 6/8 hwmon: (pmbus/mp2975) Add support for MP2971 and MP2973
In reply to Naresh SolankiFrom: Patrick Rudolph <[email protected]>
Add support for MP2971 and MP2973, the successor of MP2975.
The major differences are:
- On MP2973 and MP2971 the Vref cannot be read and thus most of the OVP/current calculations won't work.
- MP2973 and MP2971 also support LINEAR format for VOUT
- MP2973 and MP2971 do not support OVP2
- On MP2973 and MP2971 most registers are in LINEAR format
- The IMVP9_EN bit has a different position
- Per phase current sense haven't been implemented.
As on MP2975 most of the FAULT_LIMIT and WARN_LIMIT registers have been redefined and doesn't provide the functionality as defined in PMBUS spec.
Tested on MP2973 and MP2971.
--- drivers/hwmon/pmbus/mp2975.c | 262 +++++++++++++++++++++++++++++------ 1 file changed, 221 insertions(+), 41 deletions(-)
drivers/hwmon/pmbus/mp2975.c +221 -41
@@ -35,6 +35,8 @@#define MP2975_MFR_OVP_TH_SET 0xe5#define MP2975_MFR_UVP_SET 0xe6 +#define MP2973_MFR_RESO_SET 0xc7 +#define MP2975_VOUT_FORMAT BIT(15)#define MP2975_VID_STEP_SEL_R1 BIT(4)#define MP2975_IMVP9_EN_R1 BIT(13)
@@ -49,8 +51,32 @@#define MP2975_SENSE_AMPL_HALF 2#define MP2975_VIN_UV_LIMIT_UNIT 8 +#define MP2973_VOUT_FORMAT_R1 GENMASK(7, 6) +#define MP2973_VOUT_FORMAT_R2 GENMASK(4, 3) +#define MP2973_VOUT_FORMAT_DIRECT_R1 BIT(7) +#define MP2973_VOUT_FORMAT_LINEAR_R1 BIT(6) +#define MP2973_VOUT_FORMAT_DIRECT_R2 BIT(4) +#define MP2973_VOUT_FORMAT_LINEAR_R2 BIT(3) + +#define MP2973_MFR_VR_MULTI_CONFIG_R1 0x0d +#define MP2973_MFR_VR_MULTI_CONFIG_R2 0x1d +#define MP2973_VID_STEP_SEL_R1 BIT(4) +#define MP2973_IMVP9_EN_R1 BIT(14) +#define MP2973_VID_STEP_SEL_R2 BIT(3) +#define MP2973_IMVP9_EN_R2 BIT(13) + +#define MP2973_MFR_READ_IOUT_PK 0x90 +#define MP2973_MFR_READ_POUT_PK 0x91 +#define MP2975_MAX_PHASE_RAIL1 8#define MP2975_MAX_PHASE_RAIL2 4 + +#define MP2973_MAX_PHASE_RAIL1 14 +#define MP2973_MAX_PHASE_RAIL2 6 + +#define MP2971_MAX_PHASE_RAIL1 8 +#define MP2971_MAX_PHASE_RAIL2 3 +#define MP2975_PAGE_NUM 2#define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \
@@ -58,11 +84,13 @@ PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL)enum chips { - mp2975 + mp2971, mp2973, mp2975 };static const int mp2975_max_phases[][MP2975_PAGE_NUM ] = { [mp2975] = {MP2975_MAX_PHASE_RAIL1 ,MP2975_MAX_PHASE_RAIL2 }, + [mp2973] = {MP2973_MAX_PHASE_RAIL1 ,MP2973_MAX_PHASE_RAIL2 }, + [mp2971] = {MP2971_MAX_PHASE_RAIL1 ,MP2971_MAX_PHASE_RAIL2 }, };struct mp2975_data {
@@ -79,6 +107,8 @@ struct mp2975_data { };static const struct i2c_device_id mp2975_id[] = { + {"mp2971" , mp2971}, + {"mp2973" , mp2973}, {"mp2975" , mp2975}, {} };
@@ -215,6 +245,76 @@ mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data,return ret; } +static int mp2973_read_word_data (struct i2c_client *client,int page, +int phase,int reg) +{ +const struct pmbus_driver_info *info =pmbus_get_driver_info (client); +struct mp2975_data *data =to_mp2975_data (info); +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 : +/* +* MP2971 and mp2973 only supports tracking (ovp1) mode. +*/ + ret =mp2975_read_word_helper (client, page, phase, +MP2975_MFR_OVP_TH_SET , +GENMASK (2 ,0 )); +if (ret <0 ) +return ret; + + ret = data->vout_max[page] +50 * (ret +1 ); +break ; +case PMBUS_VOUT_UV_FAULT_LIMIT : + ret =mp2975_read_word_helper (client, page, phase, reg, +GENMASK (8 ,0 )); +if (ret <0 ) +return ret; + ret =mp2975_vid2direct (info->vrm_version[page], ret); +break ; +case PMBUS_VIRT_READ_POUT_MAX : + ret =pmbus_read_word_data (client, page, phase, +MP2973_MFR_READ_POUT_PK ); +break ; +case PMBUS_VIRT_READ_IOUT_MAX : + ret =pmbus_read_word_data (client, page, phase, +MP2973_MFR_READ_IOUT_PK ); +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_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_read_word_data (struct i2c_client *client,int page,int phase,int reg) {
@@ -386,7 +486,7 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_identify_vid (struct i2c_client *client,struct mp2975_data *data, +mp297x_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) {
@@ -422,7 +522,7 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,return ret;/* Identify VID mode for rail 1. */ - ret =mp2975_identify_vid (client, data, info, + ret =mp297x_identify_vid (client, data, info,MP2975_MFR_VR_MULTI_CONFIG_R1 ,0 ,MP2975_IMVP9_EN_R1 ,MP2975_VID_STEP_SEL_R1 );if (ret <0 )
@@ -430,10 +530,39 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,/* Identify VID mode for rail 2, if connected. */ if (info->phases[1 ]) - ret =mp2975_identify_vid (client, data, info, + ret =mp297x_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 +mp2973_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 =mp297x_identify_vid (client, data, info, +MP2973_MFR_VR_MULTI_CONFIG_R1 ,0 , +MP2973_IMVP9_EN_R1 ,MP2973_VID_STEP_SEL_R1 ); + +if (ret <0 ) +return ret; + +/* Identify VID mode for rail 2, if connected. */ +if (info->phases[1 ]) + ret =mp297x_identify_vid (client, data, info, +MP2973_MFR_VR_MULTI_CONFIG_R2 ,1 , +MP2973_IMVP9_EN_R2 , +MP2973_VID_STEP_SEL_R2 ); +return ret; }
@@ -532,7 +661,7 @@ mp2975_vref_offset_get(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_vout_max_get (struct i2c_client *client,struct mp2975_data *data, +mp297x_vout_max_get (struct i2c_client *client,struct mp2975_data *data,struct pmbus_driver_info *info,int page) {int ret;
@@ -548,17 +677,33 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_set_vout_format (struct i2c_client *client, +mp297x_set_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;/* Enable DIRECT VOUT format 1mV/LSB */ - ret &= ~MP2975_VOUT_FORMAT ; - ret =i2c_smbus_write_word_data (client,MP2975_MFR_DC_LOOP_CTRL , ret); +if (data->chip_id == mp2975) { + ret =i2c_smbus_read_word_data (client,MP2975_MFR_DC_LOOP_CTRL ); +if (ret <0 ) +return ret; + ret &= ~MP2975_VOUT_FORMAT ; + ret =i2c_smbus_write_word_data (client,MP2975_MFR_DC_LOOP_CTRL , ret); + }else { + ret =i2c_smbus_read_word_data (client,MP2973_MFR_RESO_SET ); +if (ret <0 ) +return ret; + +if (page ==0 ) { + ret &= ~MP2973_VOUT_FORMAT_R1 ; + ret |=MP2973_VOUT_FORMAT_DIRECT_R1 ; + }else { + ret &= ~MP2973_VOUT_FORMAT_R2 ; + ret |=MP2973_VOUT_FORMAT_DIRECT_R2 ; + } + + ret =i2c_smbus_write_word_data (client,MP2973_MFR_RESO_SET , ret); + }return ret; }
@@ -605,24 +750,28 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,for (i =0 ; i < data->info.pages; i++) { ret =i2c_smbus_write_byte_data (client,PMBUS_PAGE , i);if (ret <0 ) -return ret; +continue ; -/* Obtain voltage reference offsets. */ - ret =mp2975_vref_offset_get (client, data, i); +/* +* Set VOUT format for READ_VOUT command : direct. +* Pages on same device can be configured with different +* formats. +*/ + ret =mp297x_set_vout_format (client, data, i);if (ret <0 )return ret;/* Obtain maximum voltage values. */ - ret =mp2975_vout_max_get (client, data, info, i); + ret =mp297x_vout_max_get (client, data, info, i);if (ret <0 )return ret; -/* -* Set VOUT format for READ_VOUT command : direct. -* Pages on same device can be configured with different -* formats. -*/ - ret =mp2975_set_vout_format (client, data, i); +/* Skip if reading Vref is unsupported */ +if (data->chip_id != mp2975) +continue ; + +/* Obtain voltage reference offsets. */ + ret =mp2975_vref_offset_get (client, data, i);if (ret <0 )return ret;
@@ -660,6 +809,23 @@ static struct pmbus_driver_info mp2975_info = { .read_word_data = mp2975_read_word_data, }; +static struct pmbus_driver_info mp2973_info = { + .pages =1 , + .format[PSC_VOLTAGE_IN ] = linear, + .format[PSC_VOLTAGE_OUT ] = direct, + .format[PSC_TEMPERATURE ] = linear, + .format[PSC_CURRENT_IN ] = linear, + .format[PSC_CURRENT_OUT ] = linear, + .format[PSC_POWER ] = linear, + .m[PSC_VOLTAGE_OUT ] =1 , + .R[PSC_VOLTAGE_OUT ] =3 , + .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_word_data = mp2973_read_word_data, +}; +static int mp2975_probe (struct i2c_client *client) {struct pmbus_driver_info *info;
@@ -679,6 +845,11 @@ static int mp2975_probe(struct i2c_client *client)memcpy (data->max_phases, mp2975_max_phases[data->chip_id],sizeof (data->max_phases)); +if (data->chip_id == mp2975) +memcpy (&data->info, &mp2975_info,sizeof (*info)); +else +memcpy (&data->info, &mp2973_info,sizeof (*info)); + info = &data->info;/* Identify multiphase configuration for rail 2. */
@@ -693,30 +864,37 @@ static int mp2975_probe(struct i2c_client *client) data->info.func[1 ] =MP2975_RAIL2_FUNC ; } -/* Identify multiphase configuration. */ - ret =mp2975_identify_multiphase (client, data, info); -if (ret) -return ret; +if (data->chip_id == mp2975) { +/* Identify multiphase configuration. */ + ret =mp2975_identify_multiphase (client, data, info); +if (ret) +return ret; -/* Identify VID setting per rail. */ - ret =mp2975_identify_rails_vid (client, data, info); -if (ret <0 ) -return ret; +/* 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 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 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 vout over-voltage scales. */ + ret =mp2975_vout_ov_scale_get (client, data, info); +if (ret <0 ) +return ret; + }else { +/* Identify VID setting per rail. */ + ret =mp2973_identify_rails_vid (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);
@@ -727,6 +905,8 @@ static int mp2975_probe(struct i2c_client *client) }static const struct of_device_id __maybe_unused mp2975_of_match[] = { + {.compatible ="mps,mp2971" , .data = (void *)mp2971}, + {.compatible ="mps,mp2973" , .data = (void *)mp2973}, {.compatible ="mps,mp2975" , .data = (void *)mp2975}, {} };
Signature · 1 line
2.41.0
Guenter Roeck
maintainerRe: [PATCH 6/8] hwmon: (pmbus/mp2975) Add support for MP2971 and MP2973
Quoted 173 lines · Naresh Solanki
From: Patrick Rudolph <[email protected]>
Add support for MP2971 and MP2973, the successor of MP2975.
The major differences are:
- On MP2973 and MP2971 the Vref cannot be read and thus most of the OVP/current calculations won't work.
- MP2973 and MP2971 also support LINEAR format for VOUT
- MP2973 and MP2971 do not support OVP2
- On MP2973 and MP2971 most registers are in LINEAR format
- TheIMVP9_ENbit has a different position
- Per phase current sense haven't been implemented.As on MP2975 most of the
FAULT_LIMITandWARN_LIMITregisters have been redefined and doesn't provide the functionality as defined in PMBUS spec.Tested on MP2973 and MP2971.
Signed-off-by Patrick Rudolph <[email protected]>Signed-off-by Naresh Solanki <[email protected]>--- drivers/hwmon/pmbus/mp2975.c | 262 +++++++++++++++++++++++++++++------ 1 file changed, 221 insertions(+), 41 deletions(-)drivers/hwmon/pmbus/mp2975.c +101
-1@@ -35,6 +35,8 @@#define MP2975_MFR_OVP_TH_SET 0xe5#define MP2975_MFR_UVP_SET 0xe6 +#define MP2973_MFR_RESO_SET 0xc7 +#define MP2975_VOUT_FORMAT BIT(15)#define MP2975_VID_STEP_SEL_R1 BIT(4)#define MP2975_IMVP9_EN_R1 BIT(13)@@ -49,8 +51,32 @@#define MP2975_SENSE_AMPL_HALF 2#define MP2975_VIN_UV_LIMIT_UNIT 8 +#define MP2973_VOUT_FORMAT_R1 GENMASK(7, 6) +#define MP2973_VOUT_FORMAT_R2 GENMASK(4, 3) +#define MP2973_VOUT_FORMAT_DIRECT_R1 BIT(7) +#define MP2973_VOUT_FORMAT_LINEAR_R1 BIT(6) +#define MP2973_VOUT_FORMAT_DIRECT_R2 BIT(4) +#define MP2973_VOUT_FORMAT_LINEAR_R2 BIT(3) + +#define MP2973_MFR_VR_MULTI_CONFIG_R1 0x0d +#define MP2973_MFR_VR_MULTI_CONFIG_R2 0x1d +#define MP2973_VID_STEP_SEL_R1 BIT(4) +#define MP2973_IMVP9_EN_R1 BIT(14) +#define MP2973_VID_STEP_SEL_R2 BIT(3) +#define MP2973_IMVP9_EN_R2 BIT(13) + +#define MP2973_MFR_READ_IOUT_PK 0x90 +#define MP2973_MFR_READ_POUT_PK 0x91 +#define MP2975_MAX_PHASE_RAIL1 8#define MP2975_MAX_PHASE_RAIL2 4 + +#define MP2973_MAX_PHASE_RAIL1 14 +#define MP2973_MAX_PHASE_RAIL2 6 + +#define MP2971_MAX_PHASE_RAIL1 8 +#define MP2971_MAX_PHASE_RAIL2 3 +#define MP2975_PAGE_NUM 2#define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \@@ -58,11 +84,13 @@ PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL)enum chips { - mp2975 + mp2971, mp2973, mp2975 };static const int mp2975_max_phases[][MP2975_PAGE_NUM ] = { [mp2975] = {MP2975_MAX_PHASE_RAIL1 ,MP2975_MAX_PHASE_RAIL2 }, + [mp2973] = {MP2973_MAX_PHASE_RAIL1 ,MP2973_MAX_PHASE_RAIL2 }, + [mp2971] = {MP2971_MAX_PHASE_RAIL1 ,MP2971_MAX_PHASE_RAIL2 }, };struct mp2975_data {@@ -79,6 +107,8 @@ struct mp2975_data { };static const struct i2c_device_id mp2975_id[] = { + {"mp2971" , mp2971}, + {"mp2973" , mp2973}, {"mp2975" , mp2975}, {} };@@ -215,6 +245,76 @@ mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data,return ret; } +static int mp2973_read_word_data (struct i2c_client *client,int page, +int phase,int reg) +{ +const struct pmbus_driver_info *info =pmbus_get_driver_info (client); +struct mp2975_data *data =to_mp2975_data (info); +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 : +/* +* MP2971 and mp2973 only supports tracking (ovp1) mode. +*/ + ret =mp2975_read_word_helper (client, page, phase, +MP2975_MFR_OVP_TH_SET , +GENMASK (2 ,0 )); +if (ret <0 ) +return ret; + + ret = data->vout_max[page] +50 * (ret +1 ); +break ; +case PMBUS_VOUT_UV_FAULT_LIMIT : + ret =mp2975_read_word_helper (client, page, phase, reg, +GENMASK (8 ,0 )); +if (ret <0 ) +return ret; + ret =mp2975_vid2direct (info->vrm_version[page], ret); +break ; +case PMBUS_VIRT_READ_POUT_MAX : + ret =pmbus_read_word_data (client, page, phase, +MP2973_MFR_READ_POUT_PK ); +break ; +case PMBUS_VIRT_READ_IOUT_MAX : + ret =pmbus_read_word_data (client, page, phase, +MP2973_MFR_READ_IOUT_PK ); +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_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_read_word_data (struct i2c_client *client,int page,int phase,int reg) {
drivers/hwmon/pmbus/mp2975.c mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, · line 489
Quoted 5 lines
drivers/hwmon/pmbus/mp2975.c +1
-1@@ -386,7 +486,7 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, } static int -mp2975_identify_vid(struct i2c_client *client, struct mp2975_data *data, +mp297x_identify_vid(struct i2c_client *client, struct mp2975_data *data,
Please refrain from such cosmetic changes. It is perfectly fine to keep calling the function mp2975_identify_vid() even if it is called for other chips.
Those changes only make it more difficult to review your patch and, on top of that, are not really related to introducing support for the new chips.
Quoted 88 lines
drivers/hwmon/pmbus/mp2975.c +43
-9struct pmbus_driver_info *info, u32 reg, int page, u32 imvp_bit, u32 vr_bit) {@@ -422,7 +522,7 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,return ret;/* Identify VID mode for rail 1. */ - ret =mp2975_identify_vid (client, data, info, + ret =mp297x_identify_vid (client, data, info,MP2975_MFR_VR_MULTI_CONFIG_R1 ,0 ,MP2975_IMVP9_EN_R1 ,MP2975_VID_STEP_SEL_R1 );if (ret <0 )@@ -430,10 +530,39 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,/* Identify VID mode for rail 2, if connected. */ if (info->phases[1 ]) - ret =mp2975_identify_vid (client, data, info, + ret =mp297x_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 +mp2973_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 =mp297x_identify_vid (client, data, info, +MP2973_MFR_VR_MULTI_CONFIG_R1 ,0 , +MP2973_IMVP9_EN_R1 ,MP2973_VID_STEP_SEL_R1 ); + +if (ret <0 ) +return ret; + +/* Identify VID mode for rail 2, if connected. */ +if (info->phases[1 ]) + ret =mp297x_identify_vid (client, data, info, +MP2973_MFR_VR_MULTI_CONFIG_R2 ,1 , +MP2973_IMVP9_EN_R2 , +MP2973_VID_STEP_SEL_R2 ); +return ret; }@@ -532,7 +661,7 @@ mp2975_vref_offset_get(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_vout_max_get (struct i2c_client *client,struct mp2975_data *data, +mp297x_vout_max_get (struct i2c_client *client,struct mp2975_data *data,struct pmbus_driver_info *info,int page) {int ret;@@ -548,17 +677,33 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_set_vout_format (struct i2c_client *client, +mp297x_set_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;/* Enable DIRECT VOUT format 1mV/LSB */ - ret &= ~MP2975_VOUT_FORMAT ; - ret =i2c_smbus_write_word_data (client,MP2975_MFR_DC_LOOP_CTRL , ret); +if (data->chip_id == mp2975) { + ret =i2c_smbus_read_word_data (client,MP2975_MFR_DC_LOOP_CTRL ); +if (ret <0 ) +return ret; + ret &= ~MP2975_VOUT_FORMAT ; + ret =i2c_smbus_write_word_data (client,MP2975_MFR_DC_LOOP_CTRL , ret); + }else { + ret =i2c_smbus_read_word_data (client,MP2973_MFR_RESO_SET ); +if (ret <0 ) +return ret;
drivers/hwmon/pmbus/mp2975.c mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, · line 705
Quoted 10 lines
drivers/hwmon/pmbus/mp2975.c +10
-0+ +if (page ==0 ) { + ret &= ~MP2973_VOUT_FORMAT_R1 ; + ret |=MP2973_VOUT_FORMAT_DIRECT_R1 ; + }else { + ret &= ~MP2973_VOUT_FORMAT_R2 ; + ret |=MP2973_VOUT_FORMAT_DIRECT_R2 ; + } + + ret =i2c_smbus_write_word_data (client,MP2973_MFR_RESO_SET , ret);
Same as with the previous patch: The value only needs to be written back if it differs from the value already configured in the chip.
Quoted 146 lines
drivers/hwmon/pmbus/mp2975.c +66
-30+ }return ret; }@@ -605,24 +750,28 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,for (i =0 ; i < data->info.pages; i++) { ret =i2c_smbus_write_byte_data (client,PMBUS_PAGE , i);if (ret <0 ) -return ret; +continue ; -/* Obtain voltage reference offsets. */ - ret =mp2975_vref_offset_get (client, data, i); +/* +* Set VOUT format for READ_VOUT command : direct. +* Pages on same device can be configured with different +* formats. +*/ + ret =mp297x_set_vout_format (client, data, i);if (ret <0 )return ret;/* Obtain maximum voltage values. */ - ret =mp2975_vout_max_get (client, data, info, i); + ret =mp297x_vout_max_get (client, data, info, i);if (ret <0 )return ret; -/* -* Set VOUT format for READ_VOUT command : direct. -* Pages on same device can be configured with different -* formats. -*/ - ret =mp2975_set_vout_format (client, data, i); +/* Skip if reading Vref is unsupported */ +if (data->chip_id != mp2975) +continue ; + +/* Obtain voltage reference offsets. */ + ret =mp2975_vref_offset_get (client, data, i);if (ret <0 )return ret;@@ -660,6 +809,23 @@ static struct pmbus_driver_info mp2975_info = { .read_word_data = mp2975_read_word_data, }; +static struct pmbus_driver_info mp2973_info = { + .pages =1 , + .format[PSC_VOLTAGE_IN ] = linear, + .format[PSC_VOLTAGE_OUT ] = direct, + .format[PSC_TEMPERATURE ] = linear, + .format[PSC_CURRENT_IN ] = linear, + .format[PSC_CURRENT_OUT ] = linear, + .format[PSC_POWER ] = linear, + .m[PSC_VOLTAGE_OUT ] =1 , + .R[PSC_VOLTAGE_OUT ] =3 , + .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_word_data = mp2973_read_word_data, +}; +static int mp2975_probe (struct i2c_client *client) {struct pmbus_driver_info *info;@@ -679,6 +845,11 @@ static int mp2975_probe(struct i2c_client *client)memcpy (data->max_phases, mp2975_max_phases[data->chip_id],sizeof (data->max_phases)); +if (data->chip_id == mp2975) +memcpy (&data->info, &mp2975_info,sizeof (*info)); +else +memcpy (&data->info, &mp2973_info,sizeof (*info)); + info = &data->info;/* Identify multiphase configuration for rail 2. */ @@ -693,30 +864,37 @@ static int mp2975_probe(struct i2c_client *client) data->info.func[1 ] =MP2975_RAIL2_FUNC ; } -/* Identify multiphase configuration. */ - ret =mp2975_identify_multiphase (client, data, info); -if (ret) -return ret; +if (data->chip_id == mp2975) { +/* Identify multiphase configuration. */ + ret =mp2975_identify_multiphase (client, data, info); +if (ret) +return ret; -/* Identify VID setting per rail. */ - ret =mp2975_identify_rails_vid (client, data, info); -if (ret <0 ) -return ret; +/* 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 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 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 vout over-voltage scales. */ + ret =mp2975_vout_ov_scale_get (client, data, info); +if (ret <0 ) +return ret; + }else { +/* Identify VID setting per rail. */ + ret =mp2973_identify_rails_vid (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);@@ -727,6 +905,8 @@ static int mp2975_probe(struct i2c_client *client) }static const struct of_device_id __maybe_unused mp2975_of_match[] = { + {.compatible ="mps,mp2971" , .data = (void *)mp2971}, + {.compatible ="mps,mp2973" , .data = (void *)mp2973}, {.compatible ="mps,mp2975" , .data = (void *)mp2975}, {} };
Re: [PATCH 6/8] hwmon: (pmbus/mp2975) Add support for MP2971 and MP2973
Hi Guenter,
Quoted 185 lines · Guenter Roeck
Quoted 173 lines · Naresh Solanki
From: Patrick Rudolph <[email protected]>
Add support for MP2971 and MP2973, the successor of MP2975.
The major differences are:
- On MP2973 and MP2971 the Vref cannot be read and thus most of the OVP/current calculations won't work.
- MP2973 and MP2971 also support LINEAR format for VOUT
- MP2973 and MP2971 do not support OVP2
- On MP2973 and MP2971 most registers are in LINEAR format
- TheIMVP9_ENbit has a different position
- Per phase current sense haven't been implemented.As on MP2975 most of the
FAULT_LIMITandWARN_LIMITregisters have been redefined and doesn't provide the functionality as defined in PMBUS spec.Tested on MP2973 and MP2971.
Signed-off-by Patrick Rudolph <[email protected]>Signed-off-by Naresh Solanki <[email protected]>--- drivers/hwmon/pmbus/mp2975.c | 262 +++++++++++++++++++++++++++++------ 1 file changed, 221 insertions(+), 41 deletions(-)drivers/hwmon/pmbus/mp2975.c +101
-1@@ -35,6 +35,8 @@#define MP2975_MFR_OVP_TH_SET 0xe5#define MP2975_MFR_UVP_SET 0xe6 +#define MP2973_MFR_RESO_SET 0xc7 +#define MP2975_VOUT_FORMAT BIT(15)#define MP2975_VID_STEP_SEL_R1 BIT(4)#define MP2975_IMVP9_EN_R1 BIT(13)@@ -49,8 +51,32 @@#define MP2975_SENSE_AMPL_HALF 2#define MP2975_VIN_UV_LIMIT_UNIT 8 +#define MP2973_VOUT_FORMAT_R1 GENMASK(7, 6) +#define MP2973_VOUT_FORMAT_R2 GENMASK(4, 3) +#define MP2973_VOUT_FORMAT_DIRECT_R1 BIT(7) +#define MP2973_VOUT_FORMAT_LINEAR_R1 BIT(6) +#define MP2973_VOUT_FORMAT_DIRECT_R2 BIT(4) +#define MP2973_VOUT_FORMAT_LINEAR_R2 BIT(3) + +#define MP2973_MFR_VR_MULTI_CONFIG_R1 0x0d +#define MP2973_MFR_VR_MULTI_CONFIG_R2 0x1d +#define MP2973_VID_STEP_SEL_R1 BIT(4) +#define MP2973_IMVP9_EN_R1 BIT(14) +#define MP2973_VID_STEP_SEL_R2 BIT(3) +#define MP2973_IMVP9_EN_R2 BIT(13) + +#define MP2973_MFR_READ_IOUT_PK 0x90 +#define MP2973_MFR_READ_POUT_PK 0x91 +#define MP2975_MAX_PHASE_RAIL1 8#define MP2975_MAX_PHASE_RAIL2 4 + +#define MP2973_MAX_PHASE_RAIL1 14 +#define MP2973_MAX_PHASE_RAIL2 6 + +#define MP2971_MAX_PHASE_RAIL1 8 +#define MP2971_MAX_PHASE_RAIL2 3 +#define MP2975_PAGE_NUM 2#define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \@@ -58,11 +84,13 @@ PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL)enum chips { - mp2975 + mp2971, mp2973, mp2975 };static const int mp2975_max_phases[][MP2975_PAGE_NUM ] = { [mp2975] = {MP2975_MAX_PHASE_RAIL1 ,MP2975_MAX_PHASE_RAIL2 }, + [mp2973] = {MP2973_MAX_PHASE_RAIL1 ,MP2973_MAX_PHASE_RAIL2 }, + [mp2971] = {MP2971_MAX_PHASE_RAIL1 ,MP2971_MAX_PHASE_RAIL2 }, };struct mp2975_data {@@ -79,6 +107,8 @@ struct mp2975_data { };static const struct i2c_device_id mp2975_id[] = { + {"mp2971" , mp2971}, + {"mp2973" , mp2973}, {"mp2975" , mp2975}, {} };@@ -215,6 +245,76 @@ mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data,return ret; } +static int mp2973_read_word_data (struct i2c_client *client,int page, +int phase,int reg) +{ +const struct pmbus_driver_info *info =pmbus_get_driver_info (client); +struct mp2975_data *data =to_mp2975_data (info); +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 : +/* +* MP2971 and mp2973 only supports tracking (ovp1) mode. +*/ + ret =mp2975_read_word_helper (client, page, phase, +MP2975_MFR_OVP_TH_SET , +GENMASK (2 ,0 )); +if (ret <0 ) +return ret; + + ret = data->vout_max[page] +50 * (ret +1 ); +break ; +case PMBUS_VOUT_UV_FAULT_LIMIT : + ret =mp2975_read_word_helper (client, page, phase, reg, +GENMASK (8 ,0 )); +if (ret <0 ) +return ret; + ret =mp2975_vid2direct (info->vrm_version[page], ret); +break ; +case PMBUS_VIRT_READ_POUT_MAX : + ret =pmbus_read_word_data (client, page, phase, +MP2973_MFR_READ_POUT_PK ); +break ; +case PMBUS_VIRT_READ_IOUT_MAX : + ret =pmbus_read_word_data (client, page, phase, +MP2973_MFR_READ_IOUT_PK ); +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_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_read_word_data (struct i2c_client *client,int page,int phase,int reg) {drivers/hwmon/pmbus/mp2975.c mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, · line 489
Quoted 5 lines
drivers/hwmon/pmbus/mp2975.c +1
-1@@ -386,7 +486,7 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, } static int -mp2975_identify_vid(struct i2c_client *client, struct mp2975_data *data, +mp297x_identify_vid(struct i2c_client *client, struct mp2975_data *data,Please refrain from such cosmetic changes. It is perfectly fine to keep calling the function
mp2975_identify_vid()even if it is called for other chips.
Quoted 3 lines
Those changes only make it more difficult to review your patch and, on top of that, are not really related to introducing support for the new chips.
Yes. I agree with you.
I've removed cosmetic changes & diff looks better now. Will follow this way for future patch. Thanks.
Quoted 94 lines
Quoted 94 lines
drivers/hwmon/pmbus/mp2975.c +48
-9struct pmbus_driver_info *info, u32 reg, int page, u32 imvp_bit, u32 vr_bit) {@@ -422,7 +522,7 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,return ret;/* Identify VID mode for rail 1. */ - ret =mp2975_identify_vid (client, data, info, + ret =mp297x_identify_vid (client, data, info,MP2975_MFR_VR_MULTI_CONFIG_R1 ,0 ,MP2975_IMVP9_EN_R1 ,MP2975_VID_STEP_SEL_R1 );if (ret <0 )@@ -430,10 +530,39 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,/* Identify VID mode for rail 2, if connected. */ if (info->phases[1 ]) - ret =mp2975_identify_vid (client, data, info, + ret =mp297x_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 +mp2973_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 =mp297x_identify_vid (client, data, info, +MP2973_MFR_VR_MULTI_CONFIG_R1 ,0 , +MP2973_IMVP9_EN_R1 ,MP2973_VID_STEP_SEL_R1 ); + +if (ret <0 ) +return ret; + +/* Identify VID mode for rail 2, if connected. */ +if (info->phases[1 ]) + ret =mp297x_identify_vid (client, data, info, +MP2973_MFR_VR_MULTI_CONFIG_R2 ,1 , +MP2973_IMVP9_EN_R2 , +MP2973_VID_STEP_SEL_R2 ); +return ret; }@@ -532,7 +661,7 @@ mp2975_vref_offset_get(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_vout_max_get (struct i2c_client *client,struct mp2975_data *data, +mp297x_vout_max_get (struct i2c_client *client,struct mp2975_data *data,struct pmbus_driver_info *info,int page) {int ret;@@ -548,17 +677,33 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, }static int -mp2975_set_vout_format (struct i2c_client *client, +mp297x_set_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;/* Enable DIRECT VOUT format 1mV/LSB */ - ret &= ~MP2975_VOUT_FORMAT ; - ret =i2c_smbus_write_word_data (client,MP2975_MFR_DC_LOOP_CTRL , ret); +if (data->chip_id == mp2975) { + ret =i2c_smbus_read_word_data (client,MP2975_MFR_DC_LOOP_CTRL ); +if (ret <0 ) +return ret; + ret &= ~MP2975_VOUT_FORMAT ; + ret =i2c_smbus_write_word_data (client,MP2975_MFR_DC_LOOP_CTRL , ret); + }else { + ret =i2c_smbus_read_word_data (client,MP2973_MFR_RESO_SET ); +if (ret <0 ) +return ret; + +if (page ==0 ) { + ret &= ~MP2973_VOUT_FORMAT_R1 ; + ret |=MP2973_VOUT_FORMAT_DIRECT_R1 ; + }else {
Quoted 8 lines
drivers/hwmon/pmbus/mp2975.c mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, · line 705
Quoted 5 lines
drivers/hwmon/pmbus/mp2975.c +5
-0+ ret &= ~MP2973_VOUT_FORMAT_R2 ; + ret |=MP2973_VOUT_FORMAT_DIRECT_R2 ; + } + + ret =i2c_smbus_write_word_data (client,MP2973_MFR_RESO_SET , ret);Same as with the previous patch: The value only needs to be written back if it differs from the value already configured in the chip.
Yes. I that's efficient approach.
Will introduce a variable 'i' & check for difference at the end & do i2c write if needed.
Quoted 148 lines
Quoted 147 lines
drivers/hwmon/pmbus/mp2975.c +66
-30+ }return ret; }@@ -605,24 +750,28 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,for (i =0 ; i < data->info.pages; i++) { ret =i2c_smbus_write_byte_data (client,PMBUS_PAGE , i);if (ret <0 ) -return ret; +continue ; -/* Obtain voltage reference offsets. */ - ret =mp2975_vref_offset_get (client, data, i); +/* +* Set VOUT format for READ_VOUT command : direct. +* Pages on same device can be configured with different +* formats. +*/ + ret =mp297x_set_vout_format (client, data, i);if (ret <0 )return ret;/* Obtain maximum voltage values. */ - ret =mp2975_vout_max_get (client, data, info, i); + ret =mp297x_vout_max_get (client, data, info, i);if (ret <0 )return ret; -/* -* Set VOUT format for READ_VOUT command : direct. -* Pages on same device can be configured with different -* formats. -*/ - ret =mp2975_set_vout_format (client, data, i); +/* Skip if reading Vref is unsupported */ +if (data->chip_id != mp2975) +continue ; + +/* Obtain voltage reference offsets. */ + ret =mp2975_vref_offset_get (client, data, i);if (ret <0 )return ret;@@ -660,6 +809,23 @@ static struct pmbus_driver_info mp2975_info = { .read_word_data = mp2975_read_word_data, }; +static struct pmbus_driver_info mp2973_info = { + .pages =1 , + .format[PSC_VOLTAGE_IN ] = linear, + .format[PSC_VOLTAGE_OUT ] = direct, + .format[PSC_TEMPERATURE ] = linear, + .format[PSC_CURRENT_IN ] = linear, + .format[PSC_CURRENT_OUT ] = linear, + .format[PSC_POWER ] = linear, + .m[PSC_VOLTAGE_OUT ] =1 , + .R[PSC_VOLTAGE_OUT ] =3 , + .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_word_data = mp2973_read_word_data, +}; +static int mp2975_probe (struct i2c_client *client) {struct pmbus_driver_info *info;@@ -679,6 +845,11 @@ static int mp2975_probe(struct i2c_client *client)memcpy (data->max_phases, mp2975_max_phases[data->chip_id],sizeof (data->max_phases)); +if (data->chip_id == mp2975) +memcpy (&data->info, &mp2975_info,sizeof (*info)); +else +memcpy (&data->info, &mp2973_info,sizeof (*info)); + info = &data->info;/* Identify multiphase configuration for rail 2. */ @@ -693,30 +864,37 @@ static int mp2975_probe(struct i2c_client *client) data->info.func[1 ] =MP2975_RAIL2_FUNC ; } -/* Identify multiphase configuration. */ - ret =mp2975_identify_multiphase (client, data, info); -if (ret) -return ret; +if (data->chip_id == mp2975) { +/* Identify multiphase configuration. */ + ret =mp2975_identify_multiphase (client, data, info); +if (ret) +return ret; -/* Identify VID setting per rail. */ - ret =mp2975_identify_rails_vid (client, data, info); -if (ret <0 ) -return ret; +/* 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 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 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 vout over-voltage scales. */ + ret =mp2975_vout_ov_scale_get (client, data, info); +if (ret <0 ) +return ret; + }else { +/* Identify VID setting per rail. */ + ret =mp2973_identify_rails_vid (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);@@ -727,6 +905,8 @@ static int mp2975_probe(struct i2c_client *client) }static const struct of_device_id __maybe_unused mp2975_of_match[] = { + {.compatible ="mps,mp2971" , .data = (void *)mp2971}, + {.compatible ="mps,mp2973" , .data = (void *)mp2973}, {.compatible ="mps,mp2975" , .data = (void *)mp2975}, {} };
PATCH 7/8 hwmon: (pmbus/mp2975) Add regulator support
In reply to Naresh SolankiFrom: Patrick Rudolph <[email protected]>
Add support to expose the PMBUS regulator.
Tested on MP2973 and MP2971.
--- drivers/hwmon/pmbus/Kconfig | 7 +++++++ drivers/hwmon/pmbus/mp2975.c | 15 +++++++++++++++ 2 files changed, 22 insertions(+)
drivers/hwmon/pmbus/Kconfig +7 -0
@@ -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
drivers/hwmon/pmbus/mp2975.c +15 -0
@@ -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
@@ -807,6 +812,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 = {
@@ -824,6 +833,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)
@@ -862,6 +875,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 (CONFIG_SENSORS_MP2975_REGULATOR ) + data->info.num_regulators =MP2975_PAGE_NUM ; }if (data->chip_id == mp2975) {
Signature · 1 line
2.41.0
PATCH 8/8 hwmon: (pmbus/mp2975) Add OCP limit
In reply to Naresh SolankiFrom: 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.
--- drivers/hwmon/pmbus/mp2975.c | 76 ++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 11 deletions(-)
drivers/hwmon/pmbus/mp2975.c +65 -11
@@ -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 ; }
@@ -879,12 +933,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 )
Signature · 1 line
2.41.0