From: Jonathan Cameron <Jonathan.Cameron@xxxxxxxxxx> With some high resolution sensors such as the ad7746 the build up of error when multiplying the _raw and _scale values together can be significant. Reduce this affect by providing additional resolution in both calculation and formatting of result. Signed-off-by: Jonathan Cameron <Jonathan.Cameron@xxxxxxxxxx> --- drivers/iio/industrialio-core.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 2f48e9a97274..d831835770da 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -683,14 +683,21 @@ static ssize_t __iio_format_value(char *buf, size_t offset, unsigned int type, else return sysfs_emit_at(buf, offset, "%d.%09u", tmp0, abs(tmp1)); - case IIO_VAL_FRACTIONAL_LOG2: - tmp2 = shift_right((s64)vals[0] * 1000000000LL, vals[1]); - tmp0 = (int)div_s64_rem(tmp2, 1000000000LL, &tmp1); - if (tmp0 == 0 && tmp2 < 0) - return sysfs_emit_at(buf, offset, "-0.%09u", abs(tmp1)); - else - return sysfs_emit_at(buf, offset, "%d.%09u", tmp0, - abs(tmp1)); + case IIO_VAL_FRACTIONAL_LOG2: { + u64 t1, t2; + int integer; + bool neg = vals[0] < 0; + + t1 = shift_right((u64)abs(vals[0]) * 1000000000000ULL, vals[1]); + integer = (int)div64_u64_rem(t1, 1000000000000ULL, &t2); + if (integer == 0 && neg) + return sysfs_emit_at(buf, offset, "-0.%012llu", abs(t2)); + if (neg) + integer *= -1; + return sysfs_emit_at(buf, offset, "%d.%012llu", integer, + abs(t2)); + } + } case IIO_VAL_INT_MULTIPLE: { int i; -- 2.35.3