@@ -11,6 +11,7 @@
#include <linux/gcd.h>
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
+#include <linux/math.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -21,17 +22,16 @@ struct rescale;
struct rescale_cfg {
enum iio_chan_type type;
- int (*props)(struct device *dev, struct rescale *rescale);
+ int (*props)(struct device *dev, struct s32_fract *fract);
};
struct rescale {
+ struct s32_fract fract;
const struct rescale_cfg *cfg;
struct iio_channel *source;
struct iio_chan_spec chan;
struct iio_chan_spec_ext_info *ext_info;
bool chan_processed;
- s32 numerator;
- s32 denominator;
};
static int rescale_read_raw(struct iio_dev *indio_dev,
@@ -39,6 +39,7 @@ static int rescale_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct rescale *rescale = iio_priv(indio_dev);
+ struct s32_fract *fract = &rescale->fract;
unsigned long long tmp;
int ret;
@@ -67,19 +68,19 @@ static int rescale_read_raw(struct iio_dev *indio_dev,
}
switch (ret) {
case IIO_VAL_FRACTIONAL:
- *val *= rescale->numerator;
- *val2 *= rescale->denominator;
+ *val *= fract->numerator;
+ *val2 *= fract->denominator;
return ret;
case IIO_VAL_INT:
- *val *= rescale->numerator;
- if (rescale->denominator == 1)
+ *val *= fract->numerator;
+ if (fract->denominator == 1)
return ret;
- *val2 = rescale->denominator;
+ *val2 = fract->denominator;
return IIO_VAL_FRACTIONAL;
case IIO_VAL_FRACTIONAL_LOG2:
tmp = *val * 1000000000LL;
- do_div(tmp, rescale->denominator);
- tmp *= rescale->numerator;
+ do_div(tmp, fract->denominator);
+ tmp *= fract->numerator;
do_div(tmp, 1000000000LL);
*val = tmp;
return ret;
@@ -175,7 +176,7 @@ static int rescale_configure_channel(struct device *dev,
}
static int rescale_current_sense_amplifier_props(struct device *dev,
- struct rescale *rescale)
+ struct s32_fract *fract)
{
u32 sense;
u32 gain_mult = 1;
@@ -199,22 +200,22 @@ static int rescale_current_sense_amplifier_props(struct device *dev,
* numerator/denominator from overflowing.
*/
factor = gcd(sense, 1000000);
- rescale->numerator = 1000000 / factor;
- rescale->denominator = sense / factor;
+ fract->numerator = 1000000 / factor;
+ fract->denominator = sense / factor;
- factor = gcd(rescale->numerator, gain_mult);
- rescale->numerator /= factor;
- rescale->denominator *= gain_mult / factor;
+ factor = gcd(fract->numerator, gain_mult);
+ fract->numerator /= factor;
+ fract->denominator *= gain_mult / factor;
- factor = gcd(rescale->denominator, gain_div);
- rescale->numerator *= gain_div / factor;
- rescale->denominator /= factor;
+ factor = gcd(fract->denominator, gain_div);
+ fract->numerator *= gain_div / factor;
+ fract->denominator /= factor;
return 0;
}
static int rescale_current_sense_shunt_props(struct device *dev,
- struct rescale *rescale)
+ struct s32_fract *fract)
{
u32 shunt;
u32 factor;
@@ -228,35 +229,33 @@ static int rescale_current_sense_shunt_props(struct device *dev,
}
factor = gcd(shunt, 1000000);
- rescale->numerator = 1000000 / factor;
- rescale->denominator = shunt / factor;
+ fract->numerator = 1000000 / factor;
+ fract->denominator = shunt / factor;
return 0;
}
static int rescale_voltage_divider_props(struct device *dev,
- struct rescale *rescale)
+ struct s32_fract *fract)
{
int ret;
u32 factor;
- ret = device_property_read_u32(dev, "output-ohms",
- &rescale->denominator);
+ ret = device_property_read_u32(dev, "output-ohms", &fract->denominator);
if (ret) {
dev_err(dev, "failed to read output-ohms: %d\n", ret);
return ret;
}
- ret = device_property_read_u32(dev, "full-ohms",
- &rescale->numerator);
+ ret = device_property_read_u32(dev, "full-ohms", &fract->numerator);
if (ret) {
dev_err(dev, "failed to read full-ohms: %d\n", ret);
return ret;
}
- factor = gcd(rescale->numerator, rescale->denominator);
- rescale->numerator /= factor;
- rescale->denominator /= factor;
+ factor = gcd(fract->numerator, fract->denominator);
+ fract->numerator /= factor;
+ fract->denominator /= factor;
return 0;
}
@@ -299,6 +298,7 @@ static int rescale_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct iio_channel *source;
struct rescale *rescale;
+ struct s32_fract *fract;
int sizeof_ext_info;
int sizeof_priv;
int i;
@@ -324,14 +324,16 @@ static int rescale_probe(struct platform_device *pdev)
rescale = iio_priv(indio_dev);
rescale->source = source;
rescale->cfg = of_device_get_match_data(dev);
- rescale->numerator = 1;
- rescale->denominator = 1;
- ret = rescale->cfg->props(dev, rescale);
+ fract = &rescale->fract;
+ fract->numerator = 1;
+ fract->denominator = 1;
+
+ ret = rescale->cfg->props(dev, fract);
if (ret)
return ret;
- if (!rescale->numerator || !rescale->denominator) {
+ if (!fract->numerator || !fract->denominator) {
dev_err(dev, "invalid scaling factor.\n");
return -EINVAL;
}
Instead of custom data type re-use generic struct s32_fract. No changes intended. The new member is put to be the first one to avoid additional pointer arithmetic. Besides that one may switch to use fract member to perform container_of(), which will be no-op in this case, to get struct rescale. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> --- v3: split out assignment reshuffling (Jonathan) drivers/iio/afe/iio-rescale.c | 70 ++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 34 deletions(-)