On Mon, 20 Apr 2020 22:40:22 +0200 Linus Walleij <linus.walleij@xxxxxxxxxx> wrote: > The manual for the HSCDTD008A gives us a scaling for the > three axis as +/- 2.4mT (24 Gauss) per axis. > > The manual for the AMI305 and AMI306 gives us a scaling > for the three axis as +/- 12 Gauss per axis. > > Tests with the HSCDTD008A sensor, cat the raw values: > $ cat in_magn_*_raw > raw > 45 > 189 > -19 > > The scaling factor in in_magn_*_scale is 0.001464843, > which gives: > 0.065 Gauss > 0.277 Gauss > -0.027 Gauss > > The earths magnetic field is in the range of 0.25 to 0.65 > Gauss on the surface according to Wikipedia, so these > seem like reasonable values. > > Again we are guessing that the AK8974 has a 12 bit ADC, > based on the similarity with AMI305 and AMI306. > > Cc: Nick Reitemeyer <nick.reitemeyer@xxxxxx> > Cc: Stephan Gerhold <stephan@xxxxxxxxxxx> > Cc: Michał Mirosław <mirq-linux@xxxxxxxxxxxx> > Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx> Applied, but they'll sit in my testing branch for a while yet most likely so can rebase (add tags / drop them etc) if others still wish to comment. Thanks, Jonathan > --- > ChangeLog v3->v4: > - Do not multiply the range with 2, instead divide by > two in divisor and dividend. (Thus it becomes 2^11 > and 2^14 respectively.) > - Use the IIO_VAL_FRACTIONAL_LOG2 trick and pass 2^11 > or 2^14 as range. > ChangeLog v2->v3: > - Scale the 2.4mT/24Gauss to 15 bits for the HSCDTD008A. > - Scale the 12 Gauss to 12 bits for the AMI305/AMI306 > - Use 12 bits for the other variants. > - Return directly in the raw read function. > ChangeLog v1->v2: > - Split out the measurement refactoring. > --- > drivers/iio/magnetometer/ak8974.c | 45 ++++++++++++++++++++++++++++++- > 1 file changed, 44 insertions(+), 1 deletion(-) > > diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c > index fb6d84b79a7a..2d500be9da40 100644 > --- a/drivers/iio/magnetometer/ak8974.c > +++ b/drivers/iio/magnetometer/ak8974.c > @@ -606,6 +606,48 @@ static int ak8974_read_raw(struct iio_dev *indio_dev, > if (ret) > return ret; > return IIO_VAL_INT; > + case IIO_CHAN_INFO_SCALE: > + switch (ak8974->variant) { > + case AK8974_WHOAMI_VALUE_AMI306: > + case AK8974_WHOAMI_VALUE_AMI305: > + /* > + * The datasheet for AMI305 and AMI306, page 6 > + * specifies the range of the sensor to be > + * +/- 12 Gauss. > + */ > + *val = 12; > + /* > + * 12 bits are used, +/- 2^11 > + * [ -2048 .. 2047 ] (manual page 20) > + * [ 0xf800 .. 0x07ff ] > + */ > + *val2 = 11; > + return IIO_VAL_FRACTIONAL_LOG2; > + case AK8974_WHOAMI_VALUE_HSCDTD008A: > + /* > + * The datasheet for HSCDTF008A, page 3 specifies the > + * range of the sensor as +/- 2.4 mT per axis, which > + * corresponds to +/- 2400 uT = +/- 24 Gauss. > + */ > + *val = 24; > + /* > + * 15 bits are used (set up in CTRL4), +/- 2^14 > + * [ -16384 .. 16383 ] (manual page 24) > + * [ 0xc000 .. 0x3fff ] > + */ > + *val2 = 14; > + return IIO_VAL_FRACTIONAL_LOG2; > + default: > + /* GUESSING +/- 12 Gauss */ > + *val = 12; > + /* GUESSING 12 bits ADC +/- 2^11 */ > + *val2 = 11; > + return IIO_VAL_FRACTIONAL_LOG2; > + } > + break; > + default: > + /* Unknown request */ > + break; > } > > return -EINVAL; > @@ -670,7 +712,8 @@ static const struct iio_chan_spec_ext_info ak8974_ext_info[] = { > .type = IIO_MAGN, \ > .modified = 1, \ > .channel2 = IIO_MOD_##axis, \ > - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ > + BIT(IIO_CHAN_INFO_SCALE), \ > .ext_info = ak8974_ext_info, \ > .address = index, \ > .scan_index = index, \