Commit adce1183 authored by Thierry Reding's avatar Thierry Reding Committed by Bartosz Golaszewski
Browse files

gpio: tegra186: Add debounce support



The GPIO controller found on Tegra186 and later supports debouncing for
inputs for up to 255 ms.

Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
Signed-off-by: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
parent 22635ed8
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -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;