/* * Vender specific registers. The MFR_ICC_MAX(0x02) is used to * config the iin scale. The MFR_RESO_SET(0xC7) is used to * config the vout format. The MFR_VR_MULTI_CONFIG_R1(0x0D) is * used to identify the vout vid step.
*/ #define MFR_ICC_MAX 0x02 #define MFR_RESO_SET 0xC7 #define MFR_VR_MULTI_CONFIG_R1 0x0D
staticint mp9941_set_vout_format(struct i2c_client *client)
{ int ret;
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0); if (ret < 0) return ret;
ret = i2c_smbus_read_word_data(client, MFR_RESO_SET); if (ret < 0) return ret;
/* * page = 0, MFR_RESO_SET[7:6] defines the vout format * 2'b11 set the vout format as direct
*/
ret = (ret & ~GENMASK(7, 6)) | FIELD_PREP(GENMASK(7, 6), 3);
/* * page = 2, MFR_VR_MULTI_CONFIG_R1[4:4] defines rail1 vid step value * 1'b0 represents the vid step value is 10mV * 1'b1 represents the vid step value is 5mV
*/
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); if (ret < 0) return ret;
ret = i2c_smbus_read_word_data(client, MFR_VR_MULTI_CONFIG_R1); if (ret < 0) return ret;
staticint mp9941_identify_iin_scale(struct i2c_client *client)
{ int ret;
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0); if (ret < 0) return ret;
ret = i2c_smbus_read_word_data(client, MFR_RESO_SET); if (ret < 0) return ret;
ret = (ret & ~GENMASK(3, 2)) | FIELD_PREP(GENMASK(3, 2), 0);
ret = i2c_smbus_write_word_data(client, MFR_RESO_SET, ret); if (ret < 0) return ret;
/* * page = 2, MFR_ICC_MAX[15:13] defines the iin scale * 3'b000 set the iout scale as 0.5A/Lsb
*/
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); if (ret < 0) return ret;
ret = i2c_smbus_read_word_data(client, MFR_ICC_MAX); if (ret < 0) return ret;
ret = (ret & ~GENMASK(15, 13)) | FIELD_PREP(GENMASK(15, 13), 0);
staticint mp9941_identify(struct i2c_client *client, struct pmbus_driver_info *info)
{ int ret;
ret = mp9941_identify_iin_scale(client); if (ret < 0) return ret;
ret = mp9941_identify_vid_resolution(client, info); if (ret < 0) return ret;
return mp9941_set_vout_format(client);
}
staticint mp9941_read_word_data(struct i2c_client *client, int page, int phase, int reg)
{ conststruct pmbus_driver_info *info = pmbus_get_driver_info(client); struct mp9941_data *data = to_mp9941_data(info); int ret;
switch (reg) { case PMBUS_READ_VIN: /* The MP9941 vin scale is (1/32V)/Lsb */
ret = pmbus_read_word_data(client, page, phase, reg); if (ret < 0) return ret;
ret = DIV_ROUND_CLOSEST((ret & GENMASK(9, 0)) * MP9941_READ_VIN_UINT,
MP9941_READ_VIN_DIV); break; case PMBUS_READ_IIN:
ret = pmbus_read_word_data(client, page, phase, reg); if (ret < 0) return ret;
ret = ret & GENMASK(10, 0); break; case PMBUS_VIN_OV_FAULT_LIMIT: /* The MP9941 vin ov limit scale is (1/8V)/Lsb */
ret = pmbus_read_word_data(client, page, phase, reg); if (ret < 0) return ret;
ret = DIV_ROUND_CLOSEST((ret & GENMASK(7, 0)) * MP9941_VIN_LIMIT_UINT,
MP9941_VIN_LIMIT_DIV); break; case PMBUS_IIN_OC_WARN_LIMIT:
ret = pmbus_read_word_data(client, page, phase, reg); if (ret < 0) return ret;
ret = ret & GENMASK(7, 0); break; case PMBUS_VOUT_UV_FAULT_LIMIT: case PMBUS_MFR_VOUT_MIN: case PMBUS_MFR_VOUT_MAX: /* * The vout scale is set to 1mV/Lsb(using r/m/b scale). * But the vout uv limit and vout max/min scale is 1VID/Lsb, * so the vout uv limit and vout max/min value should be * multiplied by vid resolution.
*/
ret = pmbus_read_word_data(client, page, phase, reg); if (ret < 0) return ret;
ret = ret * data->vid_resolution; break; case PMBUS_READ_IOUT: case PMBUS_READ_POUT: case PMBUS_READ_TEMPERATURE_1: case PMBUS_READ_VOUT: case PMBUS_READ_PIN: case PMBUS_OT_FAULT_LIMIT: case PMBUS_OT_WARN_LIMIT:
ret = -ENODATA; break; default:
ret = -EINVAL; break;
}
return ret;
}
staticint mp9941_write_word_data(struct i2c_client *client, int page, int reg,
u16 word)
{ conststruct pmbus_driver_info *info = pmbus_get_driver_info(client); struct mp9941_data *data = to_mp9941_data(info); int ret;
switch (reg) { case PMBUS_VIN_OV_FAULT_LIMIT: /* The MP9941 vin ov limit scale is (1/8V)/Lsb */
ret = pmbus_write_word_data(client, page, reg,
DIV_ROUND_CLOSEST(word * MP9941_VIN_LIMIT_DIV,
MP9941_VIN_LIMIT_UINT)); break; case PMBUS_VOUT_UV_FAULT_LIMIT: case PMBUS_MFR_VOUT_MIN: case PMBUS_MFR_VOUT_MAX:
ret = pmbus_write_word_data(client, page, reg,
DIV_ROUND_CLOSEST(word, data->vid_resolution)); break; case PMBUS_IIN_OC_WARN_LIMIT: case PMBUS_OT_FAULT_LIMIT: case PMBUS_OT_WARN_LIMIT:
ret = -ENODATA; break; default:
ret = -EINVAL; break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.