iio: hrtimer: Allow sub Hz granularity

Started by Gwendal Grignou on Jan 12, 2021 · 3 messages from 2 authors · Last reply Jan 13, 2021

Subsystems (3)

Maintainers (3)

STALE2128d

open the first message on its own page

Message details and related content
Allow setting frequency below 1Hz or sub 1Hz precision.
Useful for slow sensors like ALS.

Test frequency is set properly:
modprobe iio-trig-hrtimer && \
mkdir /sys/kernel/config/iio/triggers/hrtimer/t1 && \
cd /sys/bus/iio/devices/triggerX ;
for i in 1 .1 .01 .001 ; do
  echo $i > sampling_frequency
  cat sampling_frequency
done

Signed-off-by: Gwendal Grignou <redacted>
---
Changes since v4:
- Use do_div() properly.

Changes since v3:
- Fix rebasing issue.

Changes since v2:
- Add do_div to allow divide by a u64 on 32bit machines.

Changes since v1:
- Added documentation.

 Documentation/iio/iio_configfs.rst     |  1 +
 drivers/iio/trigger/iio-trig-hrtimer.c | 26 ++++++++++++++++----------
 2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/Documentation/iio/iio_configfs.rst b/Documentation/iio/iio_configfs.rst
index ecbfdb3afef7e..807589ef2bea0 100644
--- a/Documentation/iio/iio_configfs.rst
+++ b/Documentation/iio/iio_configfs.rst
@@ -99,3 +99,4 @@ Each trigger can have one or more attributes specific to the trigger type.
 
 "hrtimer" trigger type doesn't have any configurable attribute from /config dir.
 It does introduce the sampling_frequency attribute to trigger directory.
+That attribute sets the polling frequency in Hz, with mHz precision.
diff --git a/drivers/iio/trigger/iio-trig-hrtimer.c b/drivers/iio/trigger/iio-trig-hrtimer.c
index 58c1c30d5612b..1effab04e00a8 100644
--- a/drivers/iio/trigger/iio-trig-hrtimer.c
+++ b/drivers/iio/trigger/iio-trig-hrtimer.c
@@ -22,7 +22,7 @@
 struct iio_hrtimer_info {
 	struct iio_sw_trigger swt;
 	struct hrtimer timer;
-	unsigned long sampling_frequency;
+	int sampling_frequency[2];
 	ktime_t period;
 };
 
@@ -38,7 +38,9 @@ ssize_t iio_hrtimer_show_sampling_frequency(struct device *dev,
 	struct iio_trigger *trig = to_iio_trigger(dev);
 	struct iio_hrtimer_info *info = iio_trigger_get_drvdata(trig);
 
-	return snprintf(buf, PAGE_SIZE, "%lu\n", info->sampling_frequency);
+	return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO,
+			ARRAY_SIZE(info->sampling_frequency),
+			info->sampling_frequency);
 }
 
 static
@@ -48,18 +50,22 @@ ssize_t iio_hrtimer_store_sampling_frequency(struct device *dev,
 {
 	struct iio_trigger *trig = to_iio_trigger(dev);
 	struct iio_hrtimer_info *info = iio_trigger_get_drvdata(trig);
-	unsigned long val;
-	int ret;
+	unsigned long long val;
+	int integer, fract, ret;
 
-	ret = kstrtoul(buf, 10, &val);
+	ret = iio_str_to_fixpoint(buf, 100, &integer, &fract);
 	if (ret)
 		return ret;
 
-	if (!val || val > NSEC_PER_SEC)
+	val = fract + 1000 * integer;
+
+	if (!val || val > NSEC_PER_SEC * 1000)
 		return -EINVAL;
 
-	info->sampling_frequency = val;
-	info->period = NSEC_PER_SEC / val;
+	info->sampling_frequency[0] = integer;
+	info->sampling_frequency[1] = fract * 1000;
+	info->period = NSEC_PER_SEC * 1000;
+	do_div(info->period, val);
 
 	return len;
 }
@@ -135,8 +141,8 @@ static struct iio_sw_trigger *iio_trig_hrtimer_probe(const char *name)
 	hrtimer_init(&trig_info->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
 	trig_info->timer.function = iio_hrtimer_trig_handler;
 
-	trig_info->sampling_frequency = HRTIMER_DEFAULT_SAMPLING_FREQUENCY;
-	trig_info->period = NSEC_PER_SEC / trig_info->sampling_frequency;
+	trig_info->sampling_frequency[0] = HRTIMER_DEFAULT_SAMPLING_FREQUENCY;
+	trig_info->period = NSEC_PER_SEC / trig_info->sampling_frequency[0];
 
 	ret = iio_trigger_register(trig_info->swt.trigger);
 	if (ret)
-- 
2.30.0.284.gd98b1dd5eaa7-goog
Message details and related content
On Tue, Jan 12, 2021 at 6:09 AM Gwendal Grignou [off-list ref] wrote:
Allow setting frequency below 1Hz or sub 1Hz precision.
Useful for slow sensors like ALS.

Test frequency is set properly:
modprobe iio-trig-hrtimer && \
mkdir /sys/kernel/config/iio/triggers/hrtimer/t1 && \
This && seems strange...
cd /sys/bus/iio/devices/triggerX ;
...because if the above fails, the below becomes a total train wreck.
for i in 1 .1 .01 .001 ; do
  echo $i > sampling_frequency
  cat sampling_frequency
done
Something like this perhaps (note {} and also I dropped unneeded ; and
whitespace)
  modprobe iio-trig-hrtimer && \
  mkdir /sys/kernel/config/iio/triggers/hrtimer/t1 && { \
    cd /sys/bus/iio/devices/triggerX
    for i in 1 .1 .01 .001; do
      echo $i > sampling_frequency
      cat sampling_frequency
    done
  }

...
+       if (!val || val > NSEC_PER_SEC * 1000)
                return -EINVAL;
+       info->period = NSEC_PER_SEC * 1000;
I didn't get these * 1000 parts, why not define and use PSEC_PER_SEC?

I'll send a patch soon. You may include it in your series as prerequisite.

-- 
With Best Regards,
Andy Shevchenko
Message details and related content
On Tue, Jan 12, 2021 at 6:22 AM Andy Shevchenko
[off-list ref] wrote:
On Tue, Jan 12, 2021 at 6:09 AM Gwendal Grignou [off-list ref] wrote:
quoted
Allow setting frequency below 1Hz or sub 1Hz precision.
Useful for slow sensors like ALS.

Test frequency is set properly:
modprobe iio-trig-hrtimer && \
mkdir /sys/kernel/config/iio/triggers/hrtimer/t1 && \
This && seems strange...
quoted
cd /sys/bus/iio/devices/triggerX ;
This is just for testing. X in triggerX should be replaced with the
newly created trigger.
...because if the above fails, the below becomes a total train wreck.
quoted
for i in 1 .1 .01 .001 ; do
  echo $i > sampling_frequency
  cat sampling_frequency
done
Something like this perhaps (note {} and also I dropped unneeded ; and
whitespace)
  modprobe iio-trig-hrtimer && \
  mkdir /sys/kernel/config/iio/triggers/hrtimer/t1 && { \
    cd /sys/bus/iio/devices/triggerX
    for i in 1 .1 .01 .001; do
      echo $i > sampling_frequency
      cat sampling_frequency
    done
  }

...
quoted
+       if (!val || val > NSEC_PER_SEC * 1000)
                return -EINVAL;
quoted
+       info->period = NSEC_PER_SEC * 1000;
I didn't get these * 1000 parts, why not define and use PSEC_PER_SEC?
Indeed only Nano and Femto SEC_PER_SEC are defined.
I'll send a patch soon. You may include it in your series as prerequisite.
Thanks,

Gwendal.
--
With Best Regards,
Andy Shevchenko
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help