diff options
author | Kent Gibson <warthog618@gmail.com> | 2020-10-15 07:11:56 +0800 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2020-12-05 23:22:47 +0100 |
commit | 26d060e47e25f2c715a1b2c48fea391f67907a30 (patch) | |
tree | 084ae8859583599fbf3f8ee1c7f9a472dc5eaaf2 /drivers/gpio/gpiolib-cdev.c | |
parent | 93224edf0b9fd7f643e7ead5b683bdac87f20aa2 (diff) |
gpiolib: cdev: allow edge event timestamps to be configured as REALTIME
Using CLOCK_REALTIME as the source for event timestamps is crucial for
some specific applications, particularly those requiring timetamps
relative to a PTP clock, so provide an option to switch the event
timestamp source from the default CLOCK_MONOTONIC to CLOCK_REALTIME.
Note that CLOCK_REALTIME was the default source clock for GPIO until
Linux 5.7 when it was changed to CLOCK_MONOTONIC due to issues with the
shifting of the realtime clock.
Providing this option maintains the CLOCK_MONOTONIC as the default,
while also providing a path forward for those dependent on the pre-5.7
behaviour.
Suggested-by: Jack Winch <sunt.un.morcov@gmail.com>
Signed-off-by: Kent Gibson <warthog618@gmail.com>
Link: https://lore.kernel.org/r/20201014231158.34117-2-warthog618@gmail.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpiolib-cdev.c')
-rw-r--r-- | drivers/gpio/gpiolib-cdev.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 192721f829a3..f64a35767434 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -509,6 +509,7 @@ struct linereq { GPIO_V2_LINE_DIRECTION_FLAGS | \ GPIO_V2_LINE_DRIVE_FLAGS | \ GPIO_V2_LINE_EDGE_FLAGS | \ + GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME | \ GPIO_V2_LINE_BIAS_FLAGS) static void linereq_put_event(struct linereq *lr, @@ -529,6 +530,14 @@ static void linereq_put_event(struct linereq *lr, pr_debug_ratelimited("event FIFO is full - event dropped\n"); } +static u64 line_event_timestamp(struct line *line) +{ + if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &line->desc->flags)) + return ktime_get_real_ns(); + + return ktime_get_ns(); +} + static irqreturn_t edge_irq_thread(int irq, void *p) { struct line *line = p; @@ -546,7 +555,7 @@ static irqreturn_t edge_irq_thread(int irq, void *p) * which case we didn't get the timestamp from * edge_irq_handler(). */ - le.timestamp_ns = ktime_get_ns(); + le.timestamp_ns = line_event_timestamp(line); if (lr->num_lines != 1) line->req_seqno = atomic_inc_return(&lr->seqno); } @@ -590,7 +599,7 @@ static irqreturn_t edge_irq_handler(int irq, void *p) * Just store the timestamp in hardirq context so we get it as * close in time as possible to the actual event. */ - line->timestamp_ns = ktime_get_ns(); + line->timestamp_ns = line_event_timestamp(line); if (lr->num_lines != 1) line->req_seqno = atomic_inc_return(&lr->seqno); @@ -663,7 +672,7 @@ static void debounce_work_func(struct work_struct *work) memset(&le, 0, sizeof(le)); lr = line->req; - le.timestamp_ns = ktime_get_ns(); + le.timestamp_ns = line_event_timestamp(line); le.offset = gpio_chip_hwgpio(line->desc); line->line_seqno++; le.line_seqno = line->line_seqno; @@ -967,6 +976,9 @@ static void gpio_v2_line_config_flags_to_desc_flags(u64 flags, flags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN); assign_bit(FLAG_BIAS_DISABLE, flagsp, flags & GPIO_V2_LINE_FLAG_BIAS_DISABLED); + + assign_bit(FLAG_EVENT_CLOCK_REALTIME, flagsp, + flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME); } static long linereq_get_values(struct linereq *lr, void __user *ip) @@ -1930,6 +1942,9 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, if (test_bit(FLAG_EDGE_FALLING, &desc->flags)) info->flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; + if (test_bit(FLAG_EVENT_CLOCK_REALTIME, &desc->flags)) + info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME; + debounce_period_us = READ_ONCE(desc->debounce_period_us); if (debounce_period_us) { info->attrs[num_attrs].id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE; |