From: Wenliang Yan Date: Tue, 6 May 2025 05:37:40 +0000 (-0400) Subject: hwmon: (ina238) Modify the calculation formula to adapt to different chips X-Git-Tag: v6.16-rc1~66^2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d9f596b1fe3445040c05d0fa3842224fc77810b;p=thirdparty%2Fkernel%2Flinux.git hwmon: (ina238) Modify the calculation formula to adapt to different chips Modify the calculation formula to adapt to different chips. Signed-off-by: Wenliang Yan Link: https://lore.kernel.org/r/20250506053741.4837-4-wenliang202407@163.com [groeck: Fixed checkpatch issue (space before and after arithmetic operators)] Signed-off-by: Guenter Roeck --- diff --git a/drivers/hwmon/ina238.c b/drivers/hwmon/ina238.c index 48b61328eb35f..a4a41742786bd 100644 --- a/drivers/hwmon/ina238.c +++ b/drivers/hwmon/ina238.c @@ -270,10 +270,10 @@ static int ina238_read_in(struct device *dev, u32 attr, int channel, regval = (s16)regval; if (channel == 0) /* gain of 1 -> LSB / 4 */ - *val = (regval * INA238_SHUNT_VOLTAGE_LSB) / - (1000 * (4 - data->gain + 1)); + *val = (regval * INA238_SHUNT_VOLTAGE_LSB) * + data->gain / (1000 * 4); else - *val = (regval * INA238_BUS_VOLTAGE_LSB) / 1000; + *val = (regval * data->config->bus_voltage_lsb) / 1000; break; case hwmon_in_max_alarm: case hwmon_in_min_alarm: @@ -298,8 +298,8 @@ static int ina238_write_in(struct device *dev, u32 attr, int channel, case 0: /* signed value, clamp to max range +/-163 mV */ regval = clamp_val(val, -163, 163); - regval = (regval * 1000 * (4 - data->gain + 1)) / - INA238_SHUNT_VOLTAGE_LSB; + regval = (regval * 1000 * 4) / + (INA238_SHUNT_VOLTAGE_LSB * data->gain); regval = clamp_val(regval, S16_MIN, S16_MAX); switch (attr) { @@ -315,7 +315,7 @@ static int ina238_write_in(struct device *dev, u32 attr, int channel, case 1: /* signed value, positive values only. Clamp to max 102.396 V */ regval = clamp_val(val, 0, 102396); - regval = (regval * 1000) / INA238_BUS_VOLTAGE_LSB; + regval = (regval * 1000) / data->config->bus_voltage_lsb; regval = clamp_val(regval, 0, S16_MAX); switch (attr) { @@ -370,8 +370,8 @@ static int ina238_read_power(struct device *dev, u32 attr, long *val) return err; /* Fixed 1mA lsb, scaled by 1000000 to have result in uW */ - power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT * - data->gain, 20 * data->rshunt); + 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; @@ -381,8 +381,8 @@ static int ina238_read_power(struct device *dev, u32 attr, long *val) return err; /* Fixed 1mA lsb, scaled by 1000000 to have result in uW */ - power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT * - data->gain, 20 * data->rshunt); + 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; @@ -395,8 +395,8 @@ static int ina238_read_power(struct device *dev, u32 attr, long *val) * Truncated 24-bit compare register, lower 8-bits are * truncated. Same conversion to/from uW as POWER register. */ - power = div_u64((regval << 8) * 1000ULL * INA238_FIXED_SHUNT * - data->gain, 20 * data->rshunt); + 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; @@ -428,8 +428,8 @@ static int ina238_write_power(struct device *dev, u32 attr, long val) * register. */ regval = clamp_val(val, 0, LONG_MAX); - regval = div_u64(val * 20ULL * data->rshunt, - 1000ULL * INA238_FIXED_SHUNT * data->gain); + regval = div_u64(val * 4 * 100 * data->rshunt, data->config->power_calculate_factor * + 1000ULL * INA238_FIXED_SHUNT * data->gain); regval = clamp_val(regval >> 8, 0, U16_MAX); return regmap_write(data->regmap, INA238_POWER_LIMIT, regval); @@ -446,17 +446,17 @@ static int ina238_read_temp(struct device *dev, u32 attr, long *val) err = regmap_read(data->regmap, INA238_DIE_TEMP, ®val); if (err) return err; - - /* Signed, bits 15-4 of register, result in mC */ - *val = ((s16)regval >> 4) * INA238_DIE_TEMP_LSB; + /* Signed, result in mC */ + *val = div_s64(((s64)((s16)regval) >> data->config->temp_shift) * + (s64)data->config->temp_lsb, 10000); break; case hwmon_temp_max: err = regmap_read(data->regmap, INA238_TEMP_LIMIT, ®val); if (err) return err; - - /* Signed, bits 15-4 of register, result in mC */ - *val = ((s16)regval >> 4) * INA238_DIE_TEMP_LSB; + /* Signed, result in mC */ + *val = div_s64(((s64)((s16)regval) >> data->config->temp_shift) * + (s64)data->config->temp_lsb, 10000); break; case hwmon_temp_max_alarm: err = regmap_read(data->regmap, INA238_DIAG_ALERT, ®val); @@ -480,9 +480,10 @@ static int ina238_write_temp(struct device *dev, u32 attr, long val) if (attr != hwmon_temp_max) return -EOPNOTSUPP; - /* Signed, bits 15-4 of register */ - regval = (val / INA238_DIE_TEMP_LSB) << 4; - regval = clamp_val(regval, S16_MIN, S16_MAX) & 0xfff0; + /* Signed */ + regval = clamp_val(val, -40000, 125000); + regval = div_s64(val * 10000, data->config->temp_lsb) << data->config->temp_shift; + regval = clamp_val(regval, S16_MIN, S16_MAX) & (0xffff << data->config->temp_shift); return regmap_write(data->regmap, INA238_TEMP_LIMIT, regval); }