Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
iio: hrtimer: Allow sub Hz granularity
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jonathan Cameron <[email protected]>
  • Loading branch information
gwendalcr authored and jic23 committed Mar 25, 2021
1 parent 7b3589f commit dafcf4e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
1 change: 1 addition & 0 deletions Documentation/iio/iio_configfs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
33 changes: 23 additions & 10 deletions drivers/iio/trigger/iio-trig-hrtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@
#include <linux/iio/trigger.h>
#include <linux/iio/sw_trigger.h>

/* Defined locally, not in time64.h yet. */
#define PSEC_PER_SEC 1000000000000LL

/* default sampling frequency - 100Hz */
#define HRTIMER_DEFAULT_SAMPLING_FREQUENCY 100

struct iio_hrtimer_info {
struct iio_sw_trigger swt;
struct hrtimer timer;
unsigned long sampling_frequency;
int sampling_frequency[2];
ktime_t period;
};

Expand All @@ -38,7 +41,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
Expand All @@ -48,18 +53,26 @@ 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;
u64 period;
int integer, fract, ret;

ret = kstrtoul(buf, 10, &val);
ret = iio_str_to_fixpoint(buf, 100, &integer, &fract);
if (ret)
return ret;
if (integer < 0 || fract < 0)
return -ERANGE;

val = fract + 1000 * integer; /* mHz */

if (!val || val > NSEC_PER_SEC)
if (!val || val > UINT_MAX)
return -EINVAL;

info->sampling_frequency = val;
info->period = NSEC_PER_SEC / val;
info->sampling_frequency[0] = integer; /* Hz */
info->sampling_frequency[1] = fract * 1000; /* uHz */
period = PSEC_PER_SEC;
do_div(period, val);
info->period = period; /* nS */

return len;
}
Expand Down Expand Up @@ -135,8 +148,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)
Expand Down

0 comments on commit dafcf4e

Please sign in to comment.