summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpiolib-cdev.c
diff options
context:
space:
mode:
authorKent Gibson <warthog618@gmail.com>2020-10-15 02:11:56 +0300
committerLinus Walleij <linus.walleij@linaro.org>2020-12-06 01:22:47 +0300
commit26d060e47e25f2c715a1b2c48fea391f67907a30 (patch)
tree084ae8859583599fbf3f8ee1c7f9a472dc5eaaf2 /drivers/gpio/gpiolib-cdev.c
parent93224edf0b9fd7f643e7ead5b683bdac87f20aa2 (diff)
downloadlinux-26d060e47e25f2c715a1b2c48fea391f67907a30.tar.xz
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.c21
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;