struct mp2856_data { struct pmbus_driver_info info; int vout_format[MP2856_PAGE_NUM]; int curr_sense_gain[MP2856_PAGE_NUM]; int max_phases[MP2856_PAGE_NUM];
};
/* 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);
}
staticint
mp2856_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg,
u16 mask)
{ int ret = pmbus_read_word_data(client, page, phase, reg);
return (ret > 0) ? ret & mask : ret;
}
staticint
mp2856_read_vout(struct i2c_client *client, struct mp2856_data *data, int page, int phase, u8 reg)
{ int ret;
ret = mp2856_read_word_helper(client, page, phase, reg,
GENMASK(9, 0)); if (ret < 0) return ret;
/* convert vout result to direct format */
ret = (data->vout_format[page] == vid) ?
((ret + 49) * 5) : ((ret * 1000) >> 8);
return ret;
}
staticint
mp2856_read_phase(struct i2c_client *client, struct mp2856_data *data, int page, int phase, u8 reg)
{ int ret; int val;
ret = pmbus_read_word_data(client, page, phase, reg); if (ret < 0) return ret;
if (!((phase + 1) % MP2856_PAGE_NUM))
ret >>= 8;
ret &= 0xff;
/* * Output value is calculated as: (READ_CSx * 12.5mV - 1.23V) / (Kcs * Rcs)
*/
val = (ret * 125) - 12300;
return val2linear11(val);
}
staticint
mp2856_read_phases(struct i2c_client *client, struct mp2856_data *data, int page, int phase)
{ int ret;
if (page == 0) { switch (phase) { case 0 ... 1:
ret = mp2856_read_phase(client, data, page, phase,
MP2856_MFR_READ_CS1_2_R1); break; case 2 ... 3:
ret = mp2856_read_phase(client, data, page, phase,
MP2856_MFR_READ_CS3_4_R1); break; case 4 ... 5:
ret = mp2856_read_phase(client, data, page, phase,
MP2856_MFR_READ_CS5_6_R1); break; case 6 ... 7:
ret = mp2856_read_phase(client, data, page, phase,
MP2856_MFR_READ_CS7_8_R1); break; default: return -ENODATA;
}
} else { switch (phase) { case 0 ... 1:
ret = mp2856_read_phase(client, data, page, phase,
MP2856_MFR_READ_CS1_2_R2); break; case 2 ... 3:
ret = mp2856_read_phase(client, data, page, phase,
MP2856_MFR_READ_CS1_2_R2); break; default: return -ENODATA;
}
} return ret;
}
staticint
mp2856_read_word_data(struct i2c_client *client, int page, int phase, int reg)
{ conststruct pmbus_driver_info *info = pmbus_get_driver_info(client); struct mp2856_data *data = to_mp2856_data(info); int ret;
switch (reg) { case PMBUS_READ_VOUT:
ret = mp2856_read_vout(client, data, page, phase, reg); break; case PMBUS_READ_IOUT: if (phase != 0xff)
ret = mp2856_read_phases(client, data, page, phase); else
ret = pmbus_read_word_data(client, page, phase, reg); break; default: return -ENODATA;
}
return ret;
}
staticint
mp2856_read_byte_data(struct i2c_client *client, int page, int reg)
{ switch (reg) { case PMBUS_VOUT_MODE: /* Enforce VOUT direct format. */ return PB_VOUT_MODE_DIRECT; default: return -ENODATA;
}
}
for (i = 0 ; i < data->info.phases[0]; i++)
data->info.pfunc[i] |= PMBUS_HAVE_IOUT;
return 0;
}
staticint
mp2856_current_sense_gain_get(struct i2c_client *client, struct mp2856_data *data)
{ int i, ret;
/* * Obtain DrMOS current sense gain of power stage from the register * MP2856_MFR_VR_CONFIG1, bits 13-12. The value is selected as below: * 00b - 5µA/A, 01b - 8.5µA/A, 10b - 9.7µA/A, 11b - 10µA/A. Other * values are invalid.
*/ for (i = 0 ; i < data->info.pages; i++) {
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); if (ret < 0) return ret;
ret = i2c_smbus_read_word_data(client,
MP2856_MFR_VR_CONFIG1); if (ret < 0) return ret;
memcpy(&data->info, &mp2856_info, sizeof(*info));
info = &data->info;
/* Identify multiphase configuration. */
ret = mp2856_identify_multiphase_rail1(client, data); if (ret < 0) return ret;
if (mp2856_is_rail2_active(client)) {
ret = mp2856_identify_multiphase_rail2(client, data); if (ret < 0) return ret;
} else { /* rail2 is not active */
info->pages = 1;
}
/* Obtain current sense gain of power stage. */
ret = mp2856_current_sense_gain_get(client, data); if (ret) return ret;
/* Identify vout format. */
ret = mp2856_identify_vout_format(client, data); if (ret) return ret;
/* set the device to page 0 */
i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
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.