Files
Dipen Patel e7c8a70f65 drivers: Add GTE support
The CL adds GTE driver support in OOT. The driver is copied from nvidia
directory in dev-main with below changes.
- Added removable module support

This driver as module is needed as per the oot development requirement.

Bug 3583612

Change-Id: I2772078fb96e1b172e45befe643b4c7c569866d9
Signed-off-by: Dipen Patel <dipenp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2706260
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2022-12-07 23:57:14 -08:00

163 lines
3.4 KiB
C

/*
* Copyright (c) 2020-2022, NVIDIA CORPORATION & AFFILIATES.All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0
*/
/*
* tegra_gte_mon - monitor GPIO line events from userspace and hardware
* timestamp.
*
* Example Usage:
* tegra_gte_mon -d <device> -g <global gpio pin> -r -f
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <poll.h>
#include <fcntl.h>
#include <getopt.h>
#include <inttypes.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/tegra-gte-ioctl.h>
int monitor_device(const char *device_name,
unsigned int gnum,
unsigned int eventflags,
unsigned int loops)
{
struct tegra_gte_hts_event_req req = {0};
struct tegra_gte_hts_event_data event;
char *chrdev_name;
int fd;
int ret;
int i = 0;
ret = asprintf(&chrdev_name, "/dev/%s", device_name);
if (ret < 0)
return -ENOMEM;
fd = open(chrdev_name, 0);
if (fd == -1) {
ret = -errno;
perror("Error: ");
goto exit_close_error;
}
req.global_gpio_pin = gnum;
req.eventflags = eventflags;
ret = ioctl(fd, TEGRA_GTE_HTS_CREATE_GPIO_EV_IOCTL, &req);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue GET EVENT "
"IOCTL (%d)\n",
ret);
goto exit_close_error;
}
fprintf(stdout, "Monitoring line %d on %s\n", gnum, device_name);
while (1) {
ret = read(req.fd, &event, sizeof(event));
if (ret == -1) {
if (errno == -EAGAIN) {
fprintf(stderr, "nothing available\n");
continue;
} else {
ret = -errno;
fprintf(stderr, "Failed to read event (%d)\n",
ret);
break;
}
}
if (ret != sizeof(event)) {
fprintf(stderr, "Reading event failed\n");
ret = -EIO;
break;
}
fprintf(stdout, "HW timestamp GPIO EVENT %" PRIu64 "\n",
event.timestamp);
i++;
if (i == loops)
break;
}
exit_close_error:
if (close(fd) == -1)
perror("Failed to close GPIO character device file");
free(chrdev_name);
return ret;
}
void print_usage(char *bin_name)
{
fprintf(stderr, "Usage: %s [options]...\n"
"Listen to events on GPIO lines, 0->1 1->0\n"
" -d <name> Listen using named HW ts engine device\n"
" -g <n> GPIO global id\n"
" -r Listen for rising edges\n"
" -f Listen for falling edges\n"
" [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n"
" -h This helptext\n"
"\n"
"Example:\n"
"%s -d gtechip0 -g 257 -r -f\n"
"(means GPIO 257 rising and falling edge monitoring)\n",
bin_name, bin_name
);
}
int main(int argc, char **argv)
{
const char *device_name = NULL;
unsigned int gnum = -1;
unsigned int loops = 0;
unsigned int eventflags = 0;
int c;
while ((c = getopt(argc, argv, "c:g:d:rfh")) != -1) {
switch (c) {
case 'c':
loops = strtoul(optarg, NULL, 10);
break;
case 'd':
device_name = optarg;
break;
case 'g':
gnum = strtoul(optarg, NULL, 10);
break;
case 'r':
eventflags |= TEGRA_GTE_EVENT_RISING_EDGE;
break;
case 'f':
eventflags |= TEGRA_GTE_EVENT_FALLING_EDGE;
break;
case 'h':
print_usage(argv[0]);
return 1;
}
}
if (!device_name || gnum == -1) {
print_usage(argv[0]);
return 1;
}
if (!eventflags) {
printf("No flags specified, listening on both rising and "
"falling edges\n");
eventflags = TEGRA_GTE_EVENT_REQ_BOTH_EDGES;
}
return monitor_device(device_name, gnum, eventflags, loops);
}