staticvoid calculate_coef(int *m, int *R, u32 current_lsb, int power_coef)
{
u64 scaled_m; int scale_factor = 0; int scale_coef = 1;
/* * 1000000 from Current_LSB A->uA . * scale_coef is for scaling up to minimize rounding errors, * If there is no decimal information, no need to scale.
*/ if (1000000 % current_lsb) { /* Scaling to keep integer precision */
scale_factor = -3;
scale_coef = 1000;
}
/* * Unit Conversion (Current_LSB A->uA) and use scaling(scale_factor) * to keep integer precision. * Formulae referenced from spec.
*/
scaled_m = div64_u64(1000000 * scale_coef, (u64)current_lsb * power_coef);
/* Maximize while keeping it bounded.*/ while (scaled_m > MAX_M_VAL) {
scaled_m = div_u64(scaled_m, 10);
scale_factor++;
} /* Scale up only if fractional part exists. */ while (scaled_m * 10 < MAX_M_VAL && scale_coef != 1) {
scaled_m *= 10;
scale_factor--;
}
*m = scaled_m;
*R = scale_factor;
}
staticint ina233_read_word_data(struct i2c_client *client, int page, int phase, int reg)
{ int ret;
switch (reg) { case PMBUS_VIRT_READ_VMON:
ret = pmbus_read_word_data(client, 0, 0xff, MFR_READ_VSHUNT);
/* Adjust returned value to match VIN coefficients */ /* VIN: 1.25 mV VSHUNT: 2.5 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 25, 12500); break; default:
ret = -ENODATA; break;
} return ret;
}
/* If INA233 skips current/power, shunt-resistor and current-lsb aren't needed. */ /* read rshunt value (uOhm) */
ret = device_property_read_u32(dev, "shunt-resistor", &rshunt); if (ret) { if (ret != -EINVAL) return dev_err_probe(dev, ret, "Shunt resistor property read fail.\n");
rshunt = INA233_RSHUNT_DEFAULT;
} if (!rshunt) return dev_err_probe(dev, -EINVAL, "Shunt resistor cannot be zero.\n");
/* read Maximum expected current value (uA) */
ret = device_property_read_u32(dev, "ti,maximum-expected-current-microamp", &max_current); if (ret) { if (ret != -EINVAL) return dev_err_probe(dev, ret, "Maximum expected current property read fail.\n");
max_current = INA233_MAX_CURRENT_DEFAULT;
} if (max_current < 32768) return dev_err_probe(dev, -EINVAL, "Maximum expected current cannot less then 32768.\n");
/* Calculate Current_LSB according to the spec formula */
current_lsb = max_current / 32768;
/* calculate current coefficient */
calculate_coef(&m, &R, current_lsb, 1);
info->m[PSC_CURRENT_OUT] = m;
info->R[PSC_CURRENT_OUT] = R;
/* calculate power coefficient */
calculate_coef(&m, &R, current_lsb, 25);
info->m[PSC_POWER] = m;
info->R[PSC_POWER] = R;
/* write MFR_CALIBRATION register, Apply formula from spec with unit scaling. */
calibration = div64_u64(5120000000ULL, (u64)rshunt * current_lsb); if (calibration > 0x7FFF) return dev_err_probe(dev, -EINVAL, "Product of Current_LSB %u and shunt resistor %u too small, MFR_CALIBRATION reg exceeds 0x7FFF.\n",
current_lsb, rshunt);
ret = i2c_smbus_write_word_data(client, MFR_CALIBRATION, calibration); if (ret < 0) return dev_err_probe(dev, ret, "Unable to write calibration.\n");
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.