Skip to content

Commit 10e4afd

Browse files
pateldipen1984-nvthierryreding
authored andcommitted
gpio: tegra186: Add HTE support
Tegra194 AON GPIO controller with the use of its internal hardware timestamping engine (HTE), also known as GTE, can timestamp GPIO lines through system counter. This patch implements enable/disable callbacks for the GPIO controller. In enable call, it will set timestamp function bit and GPIO line rising/falling edges in the config register. In disable call, it restores the state. Signed-off-by: Dipen Patel <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent 42112dd commit 10e4afd

File tree

1 file changed

+80
-1
lines changed

1 file changed

+80
-1
lines changed

drivers/gpio/gpio-tegra186.c

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/*
3-
* Copyright (c) 2016-2017 NVIDIA Corporation
3+
* Copyright (c) 2016-2022 NVIDIA Corporation
44
*
55
* Author: Thierry Reding <[email protected]>
6+
* Dipen Patel <[email protected]>
67
*/
78

89
#include <linux/gpio/driver.h>
@@ -11,6 +12,7 @@
1112
#include <linux/module.h>
1213
#include <linux/of_device.h>
1314
#include <linux/platform_device.h>
15+
#include <linux/hte.h>
1416

1517
#include <dt-bindings/gpio/tegra186-gpio.h>
1618
#include <dt-bindings/gpio/tegra194-gpio.h>
@@ -36,6 +38,7 @@
3638
#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL BIT(4)
3739
#define TEGRA186_GPIO_ENABLE_CONFIG_DEBOUNCE BIT(5)
3840
#define TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT BIT(6)
41+
#define TEGRA186_GPIO_ENABLE_CONFIG_TIMESTAMP_FUNC BIT(7)
3942

4043
#define TEGRA186_GPIO_DEBOUNCE_CONTROL 0x04
4144
#define TEGRA186_GPIO_DEBOUNCE_CONTROL_THRESHOLD(x) ((x) & 0xff)
@@ -76,6 +79,7 @@ struct tegra_gpio_soc {
7679
const struct tegra186_pin_range *pin_ranges;
7780
unsigned int num_pin_ranges;
7881
const char *pinmux;
82+
bool has_gte;
7983
};
8084

8185
struct tegra_gpio {
@@ -194,6 +198,76 @@ static int tegra186_gpio_direction_output(struct gpio_chip *chip,
194198
return 0;
195199
}
196200

201+
#define HTE_BOTH_EDGES (HTE_RISING_EDGE_TS | HTE_FALLING_EDGE_TS)
202+
203+
static int tegra186_gpio_en_hw_ts(struct gpio_chip *gc, u32 offset,
204+
unsigned long flags)
205+
{
206+
struct tegra_gpio *gpio;
207+
void __iomem *base;
208+
int value;
209+
210+
if (!gc)
211+
return -EINVAL;
212+
213+
gpio = gpiochip_get_data(gc);
214+
if (!gpio)
215+
return -ENODEV;
216+
217+
base = tegra186_gpio_get_base(gpio, offset);
218+
if (WARN_ON(base == NULL))
219+
return -EINVAL;
220+
221+
value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
222+
value |= TEGRA186_GPIO_ENABLE_CONFIG_TIMESTAMP_FUNC;
223+
224+
if (flags == HTE_BOTH_EDGES) {
225+
value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE;
226+
} else if (flags == HTE_RISING_EDGE_TS) {
227+
value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;
228+
value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;
229+
} else if (flags == HTE_FALLING_EDGE_TS) {
230+
value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;
231+
}
232+
233+
writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
234+
235+
return 0;
236+
}
237+
238+
static int tegra186_gpio_dis_hw_ts(struct gpio_chip *gc, u32 offset,
239+
unsigned long flags)
240+
{
241+
struct tegra_gpio *gpio;
242+
void __iomem *base;
243+
int value;
244+
245+
if (!gc)
246+
return -EINVAL;
247+
248+
gpio = gpiochip_get_data(gc);
249+
if (!gpio)
250+
return -ENODEV;
251+
252+
base = tegra186_gpio_get_base(gpio, offset);
253+
if (WARN_ON(base == NULL))
254+
return -EINVAL;
255+
256+
value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
257+
value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TIMESTAMP_FUNC;
258+
if (flags == HTE_BOTH_EDGES) {
259+
value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE;
260+
} else if (flags == HTE_RISING_EDGE_TS) {
261+
value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;
262+
value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;
263+
} else if (flags == HTE_FALLING_EDGE_TS) {
264+
value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;
265+
}
266+
writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
267+
268+
return 0;
269+
}
270+
197271
static int tegra186_gpio_get(struct gpio_chip *chip, unsigned int offset)
198272
{
199273
struct tegra_gpio *gpio = gpiochip_get_data(chip);
@@ -726,6 +800,10 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
726800
gpio->gpio.set = tegra186_gpio_set;
727801
gpio->gpio.set_config = tegra186_gpio_set_config;
728802
gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges;
803+
if (gpio->soc->has_gte) {
804+
gpio->gpio.en_hw_timestamp = tegra186_gpio_en_hw_ts;
805+
gpio->gpio.dis_hw_timestamp = tegra186_gpio_dis_hw_ts;
806+
}
729807

730808
gpio->gpio.base = -1;
731809

@@ -977,6 +1055,7 @@ static const struct tegra_gpio_soc tegra194_aon_soc = {
9771055
.name = "tegra194-gpio-aon",
9781056
.instance = 1,
9791057
.num_irqs_per_bank = 8,
1058+
.has_gte = true,
9801059
};
9811060

9821061
#define TEGRA234_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \

0 commit comments

Comments
 (0)