lkml.org 
[lkml]   [2023]   [Sep]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH v2 2/3] iio: pressure: Support ROHM BU1390
On 9/18/23 15:56, Matti Vaittinen wrote:
> On 9/17/23 13:35, Jonathan Cameron wrote:
>> On Fri, 15 Sep 2023 09:56:19 +0300
>> Matti Vaittinen <mazziesaccount@gmail.com> wrote:
>>
>>> Support for the ROHM BM1390 pressure sensor. The BM1390GLV-Z can measure
>>> pressures ranging from 300 hPa to 1300 hPa with configurable measurement
>>> averaging and internal FIFO. The sensor does also provide temperature
>>> measurements.
>>>
>>> Sensor does also contain IIR filter implemented in HW. The data-sheet
>>> says the IIR filter can be configured to be "weak", "middle" or
>>> "strong". Some RMS noise figures are provided in data sheet but no
>>> accurate maths for the filter configurations is provided. Hence, the IIR
>>> filter configuration is not supported by this driver and the filter is
>>> configured to the "middle" setting (at least not for now).
>>>
>>> The FIFO measurement mode is only measuring the pressure and not the
>>> temperature. The driver measures temperature when FIFO is flushed and
>>> simply uses the same measured temperature value to all reported
>>> temperatures. This should not be a problem when temperature is not
>>> changing very rapidly (several degrees C / second) but allows users to
>>> get the temperature measurements from sensor without any additional
>>> logic.
>>>
>>> This driver allows the sensor to be used in two muitually exclusive
>>> ways,
>>>
>>> 1. With trigger (data-ready IRQ).
>>> In this case the FIFO is not used as we get data ready for each
>>> collected
>>> sample. Instead, for each data-ready IRQ we read the sample from sensor
>>> and push it to the IIO buffer.
>>>
>>> 2. With hardware FIFO and watermark IRQ.
>>> In this case the data-ready is not used but we enable watermark IRQ. At
>>> each watermark IRQ we go and read all samples in FIFO and push them
>>> to the
>>> IIO buffer.
>>>
>>> Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>

...

>>> +
>>> +static const unsigned long bm1390_scan_masks[] = {
>>> +    BIT(BM1390_CHAN_PRESSURE) | BIT(BM1390_CHAN_TEMP), 0
>> Why?  Doesn't look hard to support just one or the other?
>> Normally we only do this sort of limitation when there is a heavily
>> optimized read routine for a set of channels and it is better
>> to grab them all and throw away the ones we don't care about.
>> That doesn't seem to be true here. So if the fifo grabbed both
>> temp and pressure it would makes sense here, but doesn't seem
>> like it does.
>
> I have a feeling I have misunderstood how this mask works. I have
> assumed all the channels with corresponding mask bit _can_ be enabled
> simultaneously, but I have not understood they _must_ all be enabled. I
> think I must go back studying this, but if all channels really _must_ be
> enabled, then you are correct. It actually makes a lot of sense to
> support the pressure values alone, as, according to the data-sheet, the
> HW is doing a "MEMS temperature compensation" to the pressure values.
> So, my assuimption is the temperature data may not be required to be
> captured.
>
> This also means I should revise the scan masks for the BU27008, BU27010
> and BU27034 light sensors as I don't think all the users want all the
> channels enabled. I wonder how I have not noticed any problems when I
> tested those things - did I really always enable all the channels...? @_@
>
> Anyways, Thanks.

Hi Jonathan,

There's something in IIO scan_masks / buffer demuxing that I don't quite
understand. I noticed following things:

1) Strict available scan mask check seems to be in use only for
INDIO_BUFFER_HARDWARE stuff.

https://elixir.bootlin.com/linux/v6.6-rc2/source/drivers/iio/industrialio-buffer.c#L881

So, the:

>>> +static const unsigned long bm1390_scan_masks[] = {
>>> + BIT(BM1390_CHAN_PRESSURE) | BIT(BM1390_CHAN_TEMP), 0

is not exclusive for BM1390 as long as it is not setting the
INDIO_BUFFER_HARDWARE.

My test seems to agree with the code:

// Only enable the temperature:
root@arm:/sys/bus/iio/devices/iio:device0# echo 1 >
scan_elements/in_temp_en

// Run the geneeric buffer without -a:
root@arm:/sys/bus/iio/devices/iio:device0# /iio_generic_buffer -c 20 -N
0 -t bm1390data-rdy-dev0
iio device number being used is 0
iio trigger number being used is 0
/sys/bus/iio/devices/iio:device0 bm1390data-rdy-dev0
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
22968.750000
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
23000.000000
23031.250000
23000.000000
23000.000000
root@arm:/sys/bus/iio/devices/iio:device0#

In above case the temperature values and only the temperature values
were shown. I must admit I did not spend enough time with the
iio_generic_buffer.c or IIO demuxing code to really understand all the
details (I got headache very quickly ;) ). I still believe the
iio_generic_buffer expects to see only the enabled channel data in the
buffer - so, it seems to me the kernel is also only adding the enabled
channel data to the buffer. Also, judging the values, the demuxing is
correctly extracting the temperature data from data the driver pushes here:

iio_push_to_buffers_with_timestamp(idev, &data->buf, data->timestamp);

The bm1390 driver as sent in v2 does not do demuxing but always pushes
whole chunk of data and trusts IIO to do demuxing.

2) I noticed the 'available_scan_masks' was marked as an optional field.
So, I think that if there is no restrictions to which of the channels
can be enabled, then we can omit setting it. This is what I tried.

It appears that when we do not populate the 'available_scan_masks' with the:
>>> +static const unsigned long bm1390_scan_masks[] = {
>>> + BIT(BM1390_CHAN_PRESSURE) | BIT(BM1390_CHAN_TEMP), 0

things change. When I tested enabling only temperature and ran the
iio_generic_buffer -c 20 -N 0 -t bm1390data-rdy-dev0 - the reported
values seemed completely random.

When I initialized the pressure data in driver:
data->buf.pressure = 1;
before doing the:
iio_push_to_buffers_with_timestamp(idev, &data->buf, data->timestamp);

I saw following:

root@arm:/# cd /sys/bus/iio/devices/iio\:device0
root@arm:/sys/bus/iio/devices/iio:device0# echo 1 >
scan_elements/in_temp_en
root@arm:/sys/bus/iio/devices/iio:device0# /iio_generic_buffer -c 20 -N
0 -t bm1390data-rdy-dev0
iio device number being used is 0
iio trigger number being used is 0
/sys/bus/iio/devices/iio:device0 bm1390data-rdy-dev0
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
8000.000000
root@arm:/sys/bus/iio/devices/iio:device0# cat in_temp_scale
31.250000

If we calculate 8000/31.250000 we will get value 256. This looks like
value '1' in BE16 format.

Based on this experimenting (and headache obtained from reading the
demuxing code) - the IIO framework does not do channel demuxing if the
'available_scan_masks' is not given? To me this was somewhat unexpected.

Finally, when the watermark IRQ is used, we can't omit reading the
pressure data because clearing the WMI is done based on the pressure
data in FIFO.

So, I would propose we do:

static const unsigned long bm1390_scan_masks[] = {
BIT(BM1390_CHAN_PRESSURE) | BIT(BM1390_CHAN_TEMP),
BIT(BM1390_CHAN_PRESSURE), 0

which better reflects what the hardware is capable of - and, unless I am
missing something, also allows us to offload the buffer demuxing to the IIO.

Still, as mentioned in 1), the

>>> +static const unsigned long bm1390_scan_masks[] = {
>>> + BIT(BM1390_CHAN_PRESSURE) | BIT(BM1390_CHAN_TEMP), 0

does not seem to prevent enabling only the temperature channel - so in
the driver buffer handler we still must unconditionally read the
pressure data regardles the active_scan_mask.

>>
>>> +     * called as a result of a read operation from userspace and hence
>>> +     * before the watermark interrupt was triggered, take a timestamp
>>> +     * now. We can fall anywhere in between two samples so the error
>>> in this
>>> +     * case is at most one sample period.
>>> +     * We need to have the IRQ disabled or we risk of messing-up
>>> +     * the timestamps. If we are ran from IRQ, then the
>>> +     * IRQF_ONESHOT has us covered - but if we are ran by the
>>> +     * user-space read we need to disable the IRQ to be on a safe
>>> +     * side. We do this usng synchronous disable so that if the
>>> +     * IRQ thread is being ran on other CPU we wait for it to be
>>> +     * finished.
>>
>> That irq disable is potentially expensive.
>> Why not just pass the current timestamp into the __bm1390_fifo_flush >
>> The locks should prevent other races I think..
>
> Gah. I hate you Jonathan ;) (Not really!)
>
> Actually, thank you (as always) for pointing this out. I don't instantly
> see why it wouldn't work, but going throught the IRQ races is never
> trivial (for me). It's work I've learned not to do at afternoon as my
> brains work better at the morning :) So, I will still go through this as
> a first thing tomorrow when I start my work day...

After staring this for a while, I see no reason why we couldn't do as
you suggested. Thanks! It really improves this :)

Yours,
-- Matti

--
Matti Vaittinen
Linux kernel developer at ROHM Semiconductors
Oulu Finland

~~ When things go utterly wrong vim users can always type :help! ~~

\
 
 \ /
  Last update: 2023-09-19 13:35    [W:0.116 / U:0.052 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site