struct ina238_config { bool has_20bit_voltage_current; /* vshunt, vbus and current are 20-bit fields */ bool has_power_highest; /* chip detection power peak */ bool has_energy; /* chip detection energy */
u8 temp_shift; /* fixed parameters for temp calculate */
u32 power_calculate_factor; /* fixed parameters for power calculate */
u16 config_default; /* Power-on default state */ int bus_voltage_lsb; /* use for temperature calculate, uV/lsb */ int temp_lsb; /* use for temperature calculate */
};
err = ina238_read_reg24(client, reg, ®val); if (err) return err;
/* bits 3-0 Reserved, always zero */
regval >>= 4;
*val = sign_extend32(regval, 19);
return0;
}
staticint ina228_read_shunt_voltage(struct device *dev, u32 attr, int channel, long *val)
{ struct ina238_data *data = dev_get_drvdata(dev); int regval; int err;
err = ina238_read_field_s20(data->client, INA238_SHUNT_VOLTAGE, ®val); if (err) return err;
staticint ina228_read_bus_voltage(struct device *dev, u32 attr, int channel, long *val)
{ struct ina238_data *data = dev_get_drvdata(dev); int regval; int err;
err = ina238_read_field_s20(data->client, INA238_BUS_VOLTAGE, ®val); if (err) return err;
staticint ina238_read_in(struct device *dev, u32 attr, int channel, long *val)
{ struct ina238_data *data = dev_get_drvdata(dev); int reg, mask; int regval; int err;
switch (channel) { case0: switch (attr) { case hwmon_in_input: if (data->config->has_20bit_voltage_current) return ina228_read_shunt_voltage(dev, attr, channel, val);
reg = INA238_SHUNT_VOLTAGE; break; case hwmon_in_max:
reg = INA238_SHUNT_OVER_VOLTAGE; break; case hwmon_in_min:
reg = INA238_SHUNT_UNDER_VOLTAGE; break; case hwmon_in_max_alarm:
reg = INA238_DIAG_ALERT;
mask = INA238_DIAG_ALERT_SHNTOL; break; case hwmon_in_min_alarm:
reg = INA238_DIAG_ALERT;
mask = INA238_DIAG_ALERT_SHNTUL; break; default: return -EOPNOTSUPP;
} break; case1: switch (attr) { case hwmon_in_input: if (data->config->has_20bit_voltage_current) return ina228_read_bus_voltage(dev, attr, channel, val);
reg = INA238_BUS_VOLTAGE; break; case hwmon_in_max:
reg = INA238_BUS_OVER_VOLTAGE; break; case hwmon_in_min:
reg = INA238_BUS_UNDER_VOLTAGE; break; case hwmon_in_max_alarm:
reg = INA238_DIAG_ALERT;
mask = INA238_DIAG_ALERT_BUSOL; break; case hwmon_in_min_alarm:
reg = INA238_DIAG_ALERT;
mask = INA238_DIAG_ALERT_BUSUL; break; default: return -EOPNOTSUPP;
} break; default: return -EOPNOTSUPP;
}
staticint ina238_read_current(struct device *dev, u32 attr, long *val)
{ struct ina238_data *data = dev_get_drvdata(dev); int regval; int err;
switch (attr) { case hwmon_curr_input: if (data->config->has_20bit_voltage_current) {
err = ina238_read_field_s20(data->client, INA238_CURRENT, ®val); if (err) return err;
} else {
err = regmap_read(data->regmap, INA238_CURRENT, ®val); if (err < 0) return err; /* sign-extend */
regval = (s16)regval;
}
/* Signed register, fixed 1mA current lsb. result in mA */
*val = div_s64((s64)regval * INA238_FIXED_SHUNT * data->gain,
data->rshunt * 4);
/* Account for 4 bit offset */ if (data->config->has_20bit_voltage_current)
*val /= 16; break; default: return -EOPNOTSUPP;
}
return0;
}
staticint ina238_read_power(struct device *dev, u32 attr, long *val)
{ struct ina238_data *data = dev_get_drvdata(dev); longlong power; int regval; int err;
switch (attr) { case hwmon_power_input:
err = ina238_read_reg24(data->client, INA238_POWER, ®val); if (err) return err;
/* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT * data->gain *
data->config->power_calculate_factor, 4 * 100 * data->rshunt); /* Clamp value to maximum value of long */
*val = clamp_val(power, 0, LONG_MAX); break; case hwmon_power_input_highest:
err = ina238_read_reg24(data->client, SQ52206_POWER_PEAK, ®val); if (err) return err;
/* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT * data->gain *
data->config->power_calculate_factor, 4 * 100 * data->rshunt); /* Clamp value to maximum value of long */
*val = clamp_val(power, 0, LONG_MAX); break; case hwmon_power_max:
err = regmap_read(data->regmap, INA238_POWER_LIMIT, ®val); if (err) return err;
/* *Truncated24-bitcompareregister,lower8-bitsare *truncated.Sameconversionto/fromuWasPOWERregister.
*/
power = div_u64((regval << 8) * 1000ULL * INA238_FIXED_SHUNT * data->gain *
data->config->power_calculate_factor, 4 * 100 * data->rshunt); /* Clamp value to maximum value of long */
*val = clamp_val(power, 0, LONG_MAX); break; case hwmon_power_max_alarm:
err = regmap_read(data->regmap, INA238_DIAG_ALERT, ®val); if (err) return err;
switch (type) { case hwmon_in: switch (attr) { case hwmon_in_input: case hwmon_in_max_alarm: case hwmon_in_min_alarm: return0444; case hwmon_in_max: case hwmon_in_min: return0644; default: return0;
} case hwmon_curr: switch (attr) { case hwmon_curr_input: return0444; default: return0;
} case hwmon_power: switch (attr) { case hwmon_power_input: case hwmon_power_max_alarm: return0444; case hwmon_power_max: return0644; case hwmon_power_input_highest: if (has_power_highest) return0444; return0; default: return0;
} case hwmon_temp: switch (attr) { case hwmon_temp_input: case hwmon_temp_max_alarm: return0444; case hwmon_temp_max: return0644; default: return0;
} default: return0;
}
}
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.