OSDN Git Service

gpio: tegra186: Add debounce support
authorThierry Reding <treding@nvidia.com>
Fri, 8 Nov 2019 15:33:53 +0000 (16:33 +0100)
committerBartosz Golaszewski <bgolaszewski@baylibre.com>
Tue, 12 Nov 2019 15:31:17 +0000 (16:31 +0100)
The GPIO controller found on Tegra186 and later supports debouncing for
inputs for up to 255 ms.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
drivers/gpio/gpio-tegra186.c

index cb5efb8..55b43b7 100644 (file)
@@ -32,6 +32,7 @@
 #define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE (0x3 << 2)
 #define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK (0x3 << 2)
 #define  TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL BIT(4)
+#define  TEGRA186_GPIO_ENABLE_CONFIG_DEBOUNCE BIT(5)
 #define  TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT BIT(6)
 
 #define TEGRA186_GPIO_DEBOUNCE_CONTROL 0x04
@@ -217,6 +218,42 @@ static void tegra186_gpio_set(struct gpio_chip *chip, unsigned int offset,
        writel(value, base + TEGRA186_GPIO_OUTPUT_VALUE);
 }
 
+static int tegra186_gpio_set_config(struct gpio_chip *chip,
+                                   unsigned int offset,
+                                   unsigned long config)
+{
+       struct tegra_gpio *gpio = gpiochip_get_data(chip);
+       u32 debounce, value;
+       void __iomem *base;
+
+       base = tegra186_gpio_get_base(gpio, offset);
+       if (base == NULL)
+               return -ENXIO;
+
+       if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
+               return -ENOTSUPP;
+
+       debounce = pinconf_to_config_argument(config);
+
+       /*
+        * The Tegra186 GPIO controller supports a maximum of 255 ms debounce
+        * time.
+        */
+       if (debounce > 255000)
+               return -EINVAL;
+
+       debounce = DIV_ROUND_UP(debounce, USEC_PER_MSEC);
+
+       value = TEGRA186_GPIO_DEBOUNCE_CONTROL_THRESHOLD(debounce);
+       writel(value, base + TEGRA186_GPIO_DEBOUNCE_CONTROL);
+
+       value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
+       value |= TEGRA186_GPIO_ENABLE_CONFIG_DEBOUNCE;
+       writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
+
+       return 0;
+}
+
 static int tegra186_gpio_of_xlate(struct gpio_chip *chip,
                                  const struct of_phandle_args *spec,
                                  u32 *flags)
@@ -539,6 +576,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
        gpio->gpio.direction_output = tegra186_gpio_direction_output;
        gpio->gpio.get = tegra186_gpio_get,
        gpio->gpio.set = tegra186_gpio_set;
+       gpio->gpio.set_config = tegra186_gpio_set_config;
 
        gpio->gpio.base = -1;