/* * Arbitrary default Rimon value: 1kOhm * This correspond to an overcurrent limit of 55A, close to the specified limit * of un-stacked TPS25990 and makes further calculation easier to setup in * sensor.conf, if necessary
*/ #define TPS25990_DEFAULT_RIMON 1000000000
staticint tps25990_read_word_data(struct i2c_client *client, int page, int phase, int reg)
{ int ret;
switch (reg) { case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_VIN_PEAK); break;
case PMBUS_VIRT_READ_VIN_MIN:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_VIN_MIN); break;
case PMBUS_VIRT_READ_VIN_AVG:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_VIN_AVG); break;
case PMBUS_VIRT_READ_VOUT_MIN:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_VOUT_MIN); break;
case PMBUS_VIRT_READ_VOUT_AVG:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_VOUT_AVG); break;
case PMBUS_VIRT_READ_IIN_AVG:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_IIN_AVG); break;
case PMBUS_VIRT_READ_IIN_MAX:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_IIN_PEAK); break;
case PMBUS_VIRT_READ_TEMP_AVG:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_TEMP_AVG); break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_TEMP_PEAK); break;
case PMBUS_VIRT_READ_PIN_AVG:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_PIN_AVG); break;
case PMBUS_VIRT_READ_PIN_MAX:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_PIN_PEAK); break;
case PMBUS_VIRT_READ_VMON:
ret = pmbus_read_word_data(client, page, phase,
TPS25990_READ_VAUX); break;
case PMBUS_VIN_UV_WARN_LIMIT: case PMBUS_VIN_UV_FAULT_LIMIT: case PMBUS_VIN_OV_WARN_LIMIT: case PMBUS_VOUT_UV_WARN_LIMIT: case PMBUS_IIN_OC_WARN_LIMIT: case PMBUS_OT_WARN_LIMIT: case PMBUS_OT_FAULT_LIMIT: case PMBUS_PIN_OP_WARN_LIMIT: /* * These registers provide an 8 bits value instead of a * 10bits one. Just shifting twice the register value is * enough to make the sensor type conversion work, even * if the datasheet provides different m, b and R for * those.
*/
ret = pmbus_read_word_data(client, page, phase, reg); if (ret < 0) break;
ret <<= TPS25990_8B_SHIFT; break;
case PMBUS_VIN_OV_FAULT_LIMIT:
ret = pmbus_read_word_data(client, page, phase, reg); if (ret < 0) break;
ret = DIV_ROUND_CLOSEST(ret * TPS25990_VIN_OVF_NUM,
TPS25990_VIN_OVF_DIV);
ret += TPS25990_VIN_OVF_OFF; break;
case PMBUS_IIN_OC_FAULT_LIMIT: /* * VIREF directly sets the over-current limit at which the eFuse * will turn the FET off and trigger a fault. Expose it through * this generic property instead of a manufacturer specific one.
*/
ret = pmbus_read_byte_data(client, page, TPS25990_VIREF); if (ret < 0) break;
ret = DIV_ROUND_CLOSEST(ret * TPS25990_IIN_OCF_NUM,
TPS25990_IIN_OCF_DIV);
ret += TPS25990_IIN_OCF_OFF; break;
case PMBUS_VIRT_SAMPLES:
ret = pmbus_read_byte_data(client, page, TPS25990_PK_MIN_AVG); if (ret < 0) break;
ret = 1 << FIELD_GET(PK_MIN_AVG_AVG_CNT, ret); break;
case PMBUS_VIRT_RESET_TEMP_HISTORY: case PMBUS_VIRT_RESET_VIN_HISTORY: case PMBUS_VIRT_RESET_IIN_HISTORY: case PMBUS_VIRT_RESET_PIN_HISTORY: case PMBUS_VIRT_RESET_VOUT_HISTORY:
ret = 0; break;
default:
ret = -ENODATA; break;
}
return ret;
}
staticint tps25990_write_word_data(struct i2c_client *client, int page, int reg, u16 value)
{ int ret;
switch (reg) { case PMBUS_VIN_UV_WARN_LIMIT: case PMBUS_VIN_UV_FAULT_LIMIT: case PMBUS_VIN_OV_WARN_LIMIT: case PMBUS_VOUT_UV_WARN_LIMIT: case PMBUS_IIN_OC_WARN_LIMIT: case PMBUS_OT_WARN_LIMIT: case PMBUS_OT_FAULT_LIMIT: case PMBUS_PIN_OP_WARN_LIMIT:
value >>= TPS25990_8B_SHIFT;
value = clamp_val(value, 0, 0xff);
ret = pmbus_write_word_data(client, page, reg, value); break;
case PMBUS_VIN_OV_FAULT_LIMIT:
value -= TPS25990_VIN_OVF_OFF;
value = DIV_ROUND_CLOSEST(((unsignedint)value) * TPS25990_VIN_OVF_DIV,
TPS25990_VIN_OVF_NUM);
value = clamp_val(value, 0, 0xf);
ret = pmbus_write_word_data(client, page, reg, value); break;
case PMBUS_IIN_OC_FAULT_LIMIT:
value -= TPS25990_IIN_OCF_OFF;
value = DIV_ROUND_CLOSEST(((unsignedint)value) * TPS25990_IIN_OCF_DIV,
TPS25990_IIN_OCF_NUM);
value = clamp_val(value, 0, 0x3f);
ret = pmbus_write_byte_data(client, page, TPS25990_VIREF, value); break;
case PMBUS_VIRT_SAMPLES:
value = clamp_val(value, 1, 1 << PK_MIN_AVG_AVG_CNT);
value = ilog2(value);
ret = pmbus_update_byte_data(client, page, TPS25990_PK_MIN_AVG,
PK_MIN_AVG_AVG_CNT,
FIELD_PREP(PK_MIN_AVG_AVG_CNT, value)); break;
case PMBUS_VIRT_RESET_TEMP_HISTORY: case PMBUS_VIRT_RESET_VIN_HISTORY: case PMBUS_VIRT_RESET_IIN_HISTORY: case PMBUS_VIRT_RESET_PIN_HISTORY: case PMBUS_VIRT_RESET_VOUT_HISTORY: /* * TPS25990 has history resets based on MIN/AVG/PEAK instead of per * sensor type. Exposing this quirk in hwmon is not desirable so * reset MIN, AVG and PEAK together. Even is there effectively only * one reset, which resets everything, expose the 5 entries so * userspace is not required map a sensor type to another to trigger * a reset
*/
ret = pmbus_update_byte_data(client, 0, TPS25990_PK_MIN_AVG,
PK_MIN_AVG_RST_MASK,
PK_MIN_AVG_RST_MASK); break;
default:
ret = -ENODATA; break;
}
return ret;
}
staticint tps25990_read_byte_data(struct i2c_client *client, int page, int reg)
{ int ret;
switch (reg) { case PMBUS_WRITE_PROTECT:
ret = tps25990_mfr_write_protect_get(client); break;
default:
ret = -ENODATA; break;
}
return ret;
}
staticint tps25990_write_byte_data(struct i2c_client *client, int page, int reg, u8 byte)
{ int ret;
switch (reg) { case PMBUS_WRITE_PROTECT:
ret = tps25990_mfr_write_protect_set(client, byte); break;
ret = device_property_read_u32(dev, "ti,rimon-micro-ohms", &rimon); if (ret < 0 && ret != -EINVAL) return dev_err_probe(dev, ret, "failed to get rimon\n");
info = devm_kmemdup(dev, &tps25990_base_info, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM;
/* Adapt the current and power scale for each instance */
tps25990_set_m(&info->m[PSC_CURRENT_IN], rimon);
tps25990_set_m(&info->m[PSC_POWER], rimon);
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.