gpiolib: Add HTE support
authorDipen Patel <dipenp@nvidia.com>
Fri, 22 Apr 2022 20:52:16 +0000 (13:52 -0700)
committerThierry Reding <treding@nvidia.com>
Wed, 4 May 2022 09:06:13 +0000 (11:06 +0200)
Some GPIO chip can provide hardware timestamp support on its GPIO lines
, in order to support that, additional API needs to be added which
can talk to both GPIO chip and HTE (hardware timestamping engine)
providers if there is any dependencies. This patch introduces optional
hooks to enable and disable hardware timestamping related features
in the GPIO controller chip.

Signed-off-by: Dipen Patel <dipenp@nvidia.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.h
include/linux/gpio/consumer.h
include/linux/gpio/driver.h

index e59884cc12a718f16df09981b9fda2fffd81e9c4..60cd7cc3364708001c1f5ae24dcc1612c950bfca 100644 (file)
@@ -2434,6 +2434,64 @@ set_output_flag:
 }
 EXPORT_SYMBOL_GPL(gpiod_direction_output);
 
+/**
+ * gpiod_enable_hw_timestamp_ns - Enable hardware timestamp in nanoseconds.
+ *
+ * @desc: GPIO to enable.
+ * @flags: Flags related to GPIO edge.
+ *
+ * Return 0 in case of success, else negative error code.
+ */
+int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags)
+{
+       int ret = 0;
+       struct gpio_chip *gc;
+
+       VALIDATE_DESC(desc);
+
+       gc = desc->gdev->chip;
+       if (!gc->en_hw_timestamp) {
+               gpiod_warn(desc, "%s: hw ts not supported\n", __func__);
+               return -ENOTSUPP;
+       }
+
+       ret = gc->en_hw_timestamp(gc, gpio_chip_hwgpio(desc), flags);
+       if (ret)
+               gpiod_warn(desc, "%s: hw ts request failed\n", __func__);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(gpiod_enable_hw_timestamp_ns);
+
+/**
+ * gpiod_disable_hw_timestamp_ns - Disable hardware timestamp.
+ *
+ * @desc: GPIO to disable.
+ * @flags: Flags related to GPIO edge, same value as used during enable call.
+ *
+ * Return 0 in case of success, else negative error code.
+ */
+int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags)
+{
+       int ret = 0;
+       struct gpio_chip *gc;
+
+       VALIDATE_DESC(desc);
+
+       gc = desc->gdev->chip;
+       if (!gc->dis_hw_timestamp) {
+               gpiod_warn(desc, "%s: hw ts not supported\n", __func__);
+               return -ENOTSUPP;
+       }
+
+       ret = gc->dis_hw_timestamp(gc, gpio_chip_hwgpio(desc), flags);
+       if (ret)
+               gpiod_warn(desc, "%s: hw ts release failed\n", __func__);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(gpiod_disable_hw_timestamp_ns);
+
 /**
  * gpiod_set_config - sets @config for a GPIO
  * @desc: descriptor of the GPIO for which to set the configuration
index 06f3faa9fbefb8112d730957a80d5ef170ea02b7..29a7d39062b39c5cc40df38aea2a0a77b62a8986 100644 (file)
@@ -158,6 +158,7 @@ struct gpio_desc {
 #define FLAG_EDGE_RISING     16        /* GPIO CDEV detects rising edge events */
 #define FLAG_EDGE_FALLING    17        /* GPIO CDEV detects falling edge events */
 #define FLAG_EVENT_CLOCK_REALTIME      18 /* GPIO CDEV reports REALTIME timestamps in events */
+#define FLAG_EVENT_CLOCK_HTE           19 /* GPIO CDEV reports hardware timestamps in events */
 
        /* Connection label */
        const char              *label;
index c3aa8b330e1c67f57e92faab99e8a4c471f39a31..7eaec081ae6c1d53824907e32c59bda31bc8a0da 100644 (file)
@@ -109,6 +109,8 @@ int gpiod_get_direction(struct gpio_desc *desc);
 int gpiod_direction_input(struct gpio_desc *desc);
 int gpiod_direction_output(struct gpio_desc *desc, int value);
 int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
+int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags);
+int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc, unsigned long flags);
 
 /* Value get/set from non-sleeping context */
 int gpiod_get_value(const struct gpio_desc *desc);
@@ -350,8 +352,18 @@ static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
        WARN_ON(desc);
        return -ENOSYS;
 }
-
-
+static inline int gpiod_enable_hw_timestamp_ns(struct gpio_desc *desc,
+                                              unsigned long flags)
+{
+       WARN_ON(desc);
+       return -ENOSYS;
+}
+static inline int gpiod_disable_hw_timestamp_ns(struct gpio_desc *desc,
+                                               unsigned long flags)
+{
+       WARN_ON(desc);
+       return -ENOSYS;
+}
 static inline int gpiod_get_value(const struct gpio_desc *desc)
 {
        /* GPIO can never have been requested */
index 98c93510640e9398c09714692dd73564ae314dad..0ce96ebdaa36905b33fe007d8b0e485fc8d8f2ba 100644 (file)
@@ -323,6 +323,10 @@ struct gpio_irq_chip {
  * @add_pin_ranges: optional routine to initialize pin ranges, to be used when
  *     requires special mapping of the pins that provides GPIO functionality.
  *     It is called after adding GPIO chip and before adding IRQ chip.
+ * @en_hw_timestamp: Dependent on GPIO chip, an optional routine to
+ *     enable hardware timestamp.
+ * @dis_hw_timestamp: Dependent on GPIO chip, an optional routine to
+ *     disable hardware timestamp.
  * @base: identifies the first GPIO number handled by this chip;
  *     or, if negative during registration, requests dynamic ID allocation.
  *     DEPRECATION: providing anything non-negative and nailing the base
@@ -419,6 +423,12 @@ struct gpio_chip {
 
        int                     (*add_pin_ranges)(struct gpio_chip *gc);
 
+       int                     (*en_hw_timestamp)(struct gpio_chip *gc,
+                                                  u32 offset,
+                                                  unsigned long flags);
+       int                     (*dis_hw_timestamp)(struct gpio_chip *gc,
+                                                   u32 offset,
+                                                   unsigned long flags);
        int                     base;
        u16                     ngpio;
        u16                     offset;