diff --git a/drivers/Makefile b/drivers/Makefile index ad388da5..59d5bea6 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -# SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. LINUXINCLUDE += -I$(srctree.nvidia-oot)/include LINUXINCLUDE += -I$(srctree.nvidia-oot)/drivers/gpu/host1x/hw/ @@ -79,7 +79,5 @@ obj-m += virt/tegra/ ifdef CONFIG_TEGRA_HOST1X obj-m += media/ endif -obj-m += staging/platform/tegra/gte/ -obj-m += staging/platform/tegra/gte_test/ obj-m += nv-virtio/ obj-m += usb/ diff --git a/drivers/staging/platform/tegra/gte/Makefile b/drivers/staging/platform/tegra/gte/Makefile deleted file mode 100644 index e29e3b6d..00000000 --- a/drivers/staging/platform/tegra/gte/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. - -obj-m += tegra194_gte.o diff --git a/drivers/staging/platform/tegra/gte/tegra194_gte.c b/drivers/staging/platform/tegra/gte/tegra194_gte.c deleted file mode 100644 index 79dcfc0b..00000000 --- a/drivers/staging/platform/tegra/gte/tegra194_gte.c +++ /dev/null @@ -1,1363 +0,0 @@ -/* - * Copyright (c) 2020-2023, NVIDIA CORPORATION & AFFILIATES.All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GTE_SUSPEND 0 -#define GTE_DEV_IN_REG 0 - -/* GTE source clock TSC is 31.25MHz */ -#define GTE_TS_NS 32ULL -#define GTE_TS_NS_SHIFT __builtin_ctz(GTE_TS_NS) - -/* char device related */ -static DEFINE_IDA(gte_ida); -static dev_t gte_devt; -#define GTE_DEV_MAX 2 -static struct bus_type gte_bus_type = { - .name = "gte", -}; - -/* Global list of the probed GTE devices */ -static DEFINE_MUTEX(gte_list_lock); -static LIST_HEAD(gte_devices); - -/* AON GTE event map For slice 1 */ -#define NV_AON_GTE_SLICE1_IRQ_GPIO_28 12 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_29 13 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_30 14 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_31 15 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_32 16 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_33 17 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_34 18 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_35 19 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_36 20 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_37 21 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_38 22 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_39 23 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_40 24 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_41 25 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_42 26 -#define NV_AON_GTE_SLICE1_IRQ_GPIO_43 27 - -/* AON GTE event map For slice 2 */ -#define NV_AON_GTE_SLICE2_IRQ_GPIO_0 0 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_1 1 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_2 2 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_3 3 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_4 4 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_5 5 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_6 6 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_7 7 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_8 8 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_9 9 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_10 10 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_11 11 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_12 12 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_13 13 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_14 14 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_15 15 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_16 16 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_17 17 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_18 18 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_19 19 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_20 20 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_21 21 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_22 22 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_23 23 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_24 24 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_25 25 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_26 26 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_27 27 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_28 28 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_29 29 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_30 30 -#define NV_AON_GTE_SLICE2_IRQ_GPIO_31 31 - -#define GTE_TECTRL 0x0 -#define GTE_TETSCH 0x4 -#define GTE_TETSCL 0x8 -#define GTE_TESRC 0xC -#define GTE_TECCV 0x10 -#define GTE_TEPCV 0x14 -#define GTE_TEENCV 0x18 -#define GTE_TECMD 0x1C -#define GTE_TESTATUS 0x20 -#define GTE_SLICE0_TETEN 0x40 -#define GTE_SLICE1_TETEN 0x60 - -#define GTE_SLICE_SIZE (GTE_SLICE1_TETEN - GTE_SLICE0_TETEN) - -#define GTE_TECTRL_ENABLE_MASK 0x1 -#define GTE_TECTRL_ENABLE_DISABLE 0x0 -#define GTE_TECTRL_ENABLE_ENABLE 0x1 - -#define GTE_TECTRL_OCCU_SHIFT 0x8 -#define GTE_TECTRL_INTR_SHIFT 0x1 -#define GTE_TECTRL_INTR_ENABLE 0x1 - -#define GTE_TESRC_SLICE_SHIFT 16 -#define GTE_TESRC_SLICE_DEFAULT_MASK 0xFF - -#define GTE_TECMD_CMD_POP 0x1 - -#define GTE_TESTATUS_OCCUPANCY_SHIFT 8 -#define GTE_TESTATUS_OCCUPANCY_MASK 0xFF - -#define GTE_EVENT_REGISTERED 0 -#define GTE_EVENT_UNREGISTERING 1 - -#define GTE_EV_FIFO_EL 32 -#define GTE_MAX_EV_NAME_SZ 9 - -struct gte_slices { - u32 r_val; - unsigned long flags; - /* to prevent events mapped to same slice updating its register */ - spinlock_t s_lock; -}; - -struct tegra_gte_ev_mapped { - u32 pin; - u32 slice; - u32 bit_index; -}; - -struct tegra_gte_ev_table { - int map_sz; - const struct tegra_gte_ev_mapped *map; -}; - -struct tegra_gte_dev { - int gte_irq; - int num_events; - int id; - unsigned long flags; - u32 itr_thrshld; - u32 conf_rval; - atomic_t usage; - bool is_chardev; - struct device c_dev; - struct cdev chrdev; - struct device *pdev; - struct kobject *kobj; - struct gte_slices *sl; - struct tegra_gte_event_info *ev; - const struct tegra_gte_ev_table *ev_map; - struct list_head list; - void __iomem *regs; - spinlock_t lock; /* Hardware access lock */ -}; - -struct tegra_gte_ev_el { - int dir; - u64 tsc; -}; - -struct tegra_gte_event_info { - u32 reg; - unsigned long flags; - atomic_t usage; - atomic_t dropped_evs; - spinlock_t lock; /* Sync ev_fifo accesses */ - struct mutex ev_lock; - struct kobject kobj; - struct kfifo ev_fifo; - struct tegra_gte_dev *dev; - struct tegra_gte_ev_desc pv; -}; - -static const struct tegra_gte_ev_mapped tegra194_aon_gpio_map[] = { - /* pin num, slice, bit_index */ - [0] = {11, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_0}, - [1] = {10, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_1}, - [2] = {9, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_2}, - [3] = {8, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_3}, - [4] = {7, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_4}, - [5] = {6, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_5}, - [6] = {5, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_6}, - [7] = {4, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_7}, - [8] = {3, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_8}, - [9] = {2, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_9}, - [10] = {1, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_10}, - [11] = {0, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_11}, - [12] = {22, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_12}, - [13] = {21, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_13}, - [14] = {20, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_14}, - [15] = {19, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_15}, - [16] = {18, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_16}, - [17] = {17, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_17}, - [18] = {16, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_18}, - [19] = {15, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_19}, - [20] = {14, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_20}, - [21] = {13, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_21}, - [22] = {12, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_22}, - [23] = {29, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_23}, - [24] = {28, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_24}, - [25] = {27, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_25}, - [26] = {26, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_26}, - [27] = {25, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_27}, - [28] = {24, 1, NV_AON_GTE_SLICE1_IRQ_GPIO_28}, - [29] = {23, 1, NV_AON_GTE_SLICE1_IRQ_GPIO_29}, -}; - -static const struct tegra_gte_ev_mapped tegra234_aon_gpio_map[] = { - /* pin num, slice, bit_index */ - [0] = {11, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_0}, - [1] = {10, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_1}, - [2] = {9, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_2}, - [3] = {8, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_3}, - [4] = {7, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_4}, - [5] = {6, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_5}, - [6] = {5, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_6}, - [7] = {4, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_7}, - [8] = {3, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_8}, - [9] = {2, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_9}, - [10] = {1, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_10}, - [11] = {0, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_11}, - [12] = {22, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_12}, - [13] = {21, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_13}, - [14] = {20, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_14}, - [15] = {19, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_15}, - [16] = {18, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_16}, - [17] = {17, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_17}, - [18] = {16, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_18}, - [19] = {15, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_19}, - [20] = {14, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_20}, - [21] = {13, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_21}, - [22] = {12, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_22}, - [23] = {31, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_23}, - [24] = {30, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_24}, - [25] = {29, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_25}, - [26] = {28, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_26}, - [27] = {27, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_27}, - [28] = {26, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_28}, - [29] = {25, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_29}, - [30] = {24, 2, NV_AON_GTE_SLICE1_IRQ_GPIO_30}, - [31] = {23, 2, NV_AON_GTE_SLICE2_IRQ_GPIO_31}, -}; - -static const struct tegra_gte_ev_table t194_aon_gte_map = { - .map_sz = ARRAY_SIZE(tegra194_aon_gpio_map), - .map = tegra194_aon_gpio_map, -}; - -static const struct tegra_gte_ev_table t234_aon_gte_map = { - .map_sz = ARRAY_SIZE(tegra234_aon_gpio_map), - .map = tegra234_aon_gpio_map, -}; - -static inline u32 tegra_gte_readl(struct tegra_gte_dev *gte, u32 reg) -{ - return readl(gte->regs + reg); -} - -static inline void tegra_gte_writel(struct tegra_gte_dev *gte, u32 reg, - u32 val) -{ - writel(val, gte->regs + reg); -} - -/* Event specific sysfs management */ - -static struct kobj_type gte_ev_kobj_type = { - .sysfs_ops = &kobj_sysfs_ops, -}; - -static void tegra_gte_read_fifo(struct tegra_gte_dev *gte); - -/* Stat for the dropped events due to FIFO overflow */ -static ssize_t show_num_dropped_events(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - struct tegra_gte_event_info *ev = - container_of(kobj, struct tegra_gte_event_info, kobj); - return scnprintf(buf, PAGE_SIZE, "%d\n", - atomic_read(&ev->dropped_evs)); -} - -/* Total timestamp elements available to retrieve */ -static ssize_t show_num_events_avail(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - struct tegra_gte_event_info *ev = - container_of(kobj, struct tegra_gte_event_info, kobj); - return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&ev->usage)); -} - -static struct kobj_attribute num_events_avail_attr = - __ATTR(num_events_avail, 0400, show_num_events_avail, NULL); -static struct kobj_attribute num_dropped_events_attr = - __ATTR(num_dropped_events, 0400, show_num_dropped_events, NULL); - -static struct attribute *ev_attrs[] = { - &num_events_avail_attr.attr, - &num_dropped_events_attr.attr, - NULL, -}; - -static struct attribute_group event_attr_group = { - .attrs = ev_attrs, -}; - -/* - * Clears the resources related to event, resets the FIFO, removes the sysfs - * related to event - */ -int tegra_gte_unregister_event(struct tegra_gte_ev_desc *data) -{ - u32 slice, val; - int ev_id, ret; - unsigned long flags; - struct tegra_gte_dev *gte_dev; - struct tegra_gte_ev_desc *pri; - struct tegra_gte_event_info *ev; - - if (!data) - return -EINVAL; - - pri = data; - ev = container_of(pri, struct tegra_gte_event_info, pv); - gte_dev = ev->dev; - ev_id = pri->id; - slice = pri->slice; - - set_bit(GTE_EVENT_UNREGISTERING, &ev->flags); - - if (!test_bit(GTE_EVENT_REGISTERED, &ev->flags)) { - dev_dbg(gte_dev->pdev, "Event:%d is not registered", ev_id); - ret = -EUSERS; - goto clear_unregister; - } - - spin_lock(>e_dev->sl[slice].s_lock); - if (test_bit(GTE_SUSPEND, >e_dev->sl[slice].flags)) { - spin_unlock(>e_dev->sl[slice].s_lock); - dev_dbg(gte_dev->pdev, "device suspended\n"); - ret = -EBUSY; - goto clear_unregister; - } - - val = tegra_gte_readl(gte_dev, ev->reg); - val = val & (~(1 << pri->ev_bit)); - tegra_gte_writel(gte_dev, ev->reg, val); - spin_unlock(>e_dev->sl[slice].s_lock); - - spin_lock_irqsave(&ev->lock, flags); - clear_bit(GTE_EVENT_REGISTERED, &ev->flags); - spin_unlock_irqrestore(&ev->lock, flags); - - atomic_dec(>e_dev->usage); - atomic_set(&ev->usage, 0); - atomic_set(&ev->dropped_evs, 0); - memset(&ev->pv, 0, sizeof(ev->pv)); - kobject_put(&ev->kobj); - memset(&ev->kobj, 0, sizeof(ev->kobj)); - kfifo_free(&ev->ev_fifo); - - ret = 0; - - module_put(gte_dev->pdev->driver->owner); - - dev_dbg(gte_dev->pdev, "%s: event id:%d, slice:%d", - __func__, ev_id, slice); - -clear_unregister: - clear_bit(GTE_EVENT_UNREGISTERING, &ev->flags); - - return ret; -} -EXPORT_SYMBOL(tegra_gte_unregister_event); - -static int tegra_gte_convert_to_offset(u32 ev_id, - struct tegra_gte_dev *gte_dev) -{ - struct gpio_chip *chip; - int offset; - - dev_dbg(gte_dev->pdev, "gpio gte is requested\n"); - - chip = gpiod_to_chip(gpio_to_desc(ev_id)); - if (!chip) { - dev_err(gte_dev->pdev, - "GPIO controller not found for the gpio: %u\n", - ev_id); - return -EINVAL; - } - - offset = (int)(ev_id - chip->base); - if (offset < 0) { - dev_err(gte_dev->pdev, "Invalid gpio pin: %u\n", ev_id); - return -EINVAL; - } - - return offset; -} - -static void tegra_gte_map_to_ev_id(u32 eid, struct tegra_gte_dev *gdev, - u32 *mapped) -{ - const struct tegra_gte_ev_mapped *m; - int nums, i; - - if (gdev->ev_map) { - m = gdev->ev_map->map; - nums = gdev->ev_map->map_sz; - for (i = 0; i < nums; i++) { - if (m[i].pin == eid) { - *mapped = (m[i].slice << 5) + m[i].bit_index; - return; - } - } - } - *mapped = eid; -} - -static struct tegra_gte_ev_desc *__gte_register_event(u32 eid, - struct tegra_gte_dev *gte_dev) -{ - u32 slice, sl_bit_shift, ev_bit, offset, val, reg; - int ret, sysfs_created = 0; - struct tegra_gte_event_info *ev; - - sl_bit_shift = __builtin_ctz(GTE_SLICE_SIZE); - - if (!try_module_get(gte_dev->pdev->driver->owner)) - return ERR_PTR(-ENODEV); - - tegra_gte_map_to_ev_id(eid, gte_dev, &offset); - - if (offset > gte_dev->num_events) { - dev_err(gte_dev->pdev, - "Invalid event id:%u and GTE event offset: %u", - eid, offset); - ret = -EINVAL; - goto put_mod; - } - - ev = gte_dev->ev; - if (test_bit(GTE_EVENT_UNREGISTERING, &ev[offset].flags)) { - dev_err(gte_dev->pdev, "Event:%d is getting unregistered", - offset); - ret = -EUSERS; - goto put_mod; - } - - /* - * There a chance that both kernel client driver and userspace calling - * register API with same event id, lock here. - */ - mutex_lock(&ev[offset].ev_lock); - - if (test_bit(GTE_EVENT_REGISTERED, &ev[offset].flags)) { - dev_err(gte_dev->pdev, "Event:%d is already registered", - offset); - ret = -EUSERS; - goto error_unlock; - } - - slice = offset >> 5; - ev_bit = offset & (32 - 1); - - if (kfifo_alloc(&ev[offset].ev_fifo, - GTE_EV_FIFO_EL * sizeof(struct tegra_gte_ev_el), GFP_KERNEL)) { - dev_err(gte_dev->pdev, "Fifo allocation failed"); - ret = -ENOMEM; - goto error_unlock; - } - - reg = (slice << sl_bit_shift) + GTE_SLICE0_TETEN; - - ev[offset].reg = reg; - ev[offset].pv.ev_bit = ev_bit; - ev[offset].pv.slice = slice; - ev[offset].pv.id = offset; - - ret = kobject_init_and_add(&ev[offset].kobj, >e_ev_kobj_type, - gte_dev->kobj, "event%d", offset); - if (!ret) { - ret = sysfs_create_group(&ev[offset].kobj, - &event_attr_group); - if (ret) { - kobject_put(&ev[offset].kobj); - memset(&ev[offset].kobj, 0, sizeof(ev[offset].kobj)); - } else { - sysfs_created = 1; - } - } else { - kobject_put(&ev[offset].kobj); - } - - spin_lock(>e_dev->sl[slice].s_lock); - if (test_bit(GTE_SUSPEND, >e_dev->sl[slice].flags)) { - spin_unlock(>e_dev->sl[slice].s_lock); - if (sysfs_created == 1) { - kobject_put(&ev[offset].kobj); - memset(&ev[offset].kobj, 0, sizeof(ev[offset].kobj)); - } - dev_dbg(gte_dev->pdev, "device suspended"); - ret = -EBUSY; - goto error_fifo_free; - } - - val = tegra_gte_readl(gte_dev, reg); - val = val | (1 << ev_bit); - tegra_gte_writel(gte_dev, reg, val); - spin_unlock(>e_dev->sl[slice].s_lock); - - atomic_inc(>e_dev->usage); - set_bit(GTE_EVENT_REGISTERED, &ev[offset].flags); - dev_dbg(gte_dev->pdev, - "%s: slice: %u, bit: %u, offset: %d, reg = 0x%x", - __func__, slice, ev_bit, offset, reg); - mutex_unlock(&ev[offset].ev_lock); - - return &ev[offset].pv; - -error_fifo_free: - kfifo_free(&ev[offset].ev_fifo); -error_unlock: - mutex_unlock(&ev[offset].ev_lock); -put_mod: - module_put(gte_dev->pdev->driver->owner); - - return ERR_PTR(ret); -} - -/* - * registers the event with GTE, allocates FIFO, creates sysfs for the event - * stats. Also asks GPIO driver to enable timestamp bit in case of the GPIO - * event to monitor. - */ -struct tegra_gte_ev_desc *tegra_gte_register_event(struct device_node *np, - u32 ev_id) -{ - struct tegra_gte_dev *gte_dev = NULL; - struct tegra_gte_ev_desc *desc; - int offset; - - if (!np) { - pr_err("Node empty\n"); - return ERR_PTR(-EINVAL); - } - - mutex_lock(>e_list_lock); - - list_for_each_entry(gte_dev, >e_devices, list) { - if (gte_dev->pdev->of_node == np) { - dev_dbg(gte_dev->pdev, "found the match\n"); - break; - } - } - - if (!gte_dev) { - pr_err("No device found\n"); - mutex_unlock(>e_list_lock); - return ERR_PTR(-ENODEV); - } - - set_bit(GTE_DEV_IN_REG, >e_dev->flags); - mutex_unlock(>e_list_lock); - - if (!of_device_is_compatible(np, "nvidia,tegra194-gte-lic")) { - offset = tegra_gte_convert_to_offset(ev_id, gte_dev); - if (offset < 0) - return ERR_PTR(offset); - } else { - offset = ev_id; - } - - desc = __gte_register_event(offset, gte_dev); - - clear_bit(GTE_DEV_IN_REG, >e_dev->flags); - - return desc; -} -EXPORT_SYMBOL(tegra_gte_register_event); - -int tegra_gte_retrieve_event(const struct tegra_gte_ev_desc *data, - struct tegra_gte_ev_detail *hts) -{ - int ret, ev_id; - unsigned long flags; - struct tegra_gte_ev_el el; - const struct tegra_gte_ev_desc *pri; - struct tegra_gte_event_info *ev; - struct tegra_gte_dev *gte_dev; - - if (!data || !hts) - return -EINVAL; - - pri = data; - ev = container_of(pri, struct tegra_gte_event_info, pv); - ev_id = pri->id; - gte_dev = ev->dev; - - /* test - read from HW to make sure we are not missing anything */ - tegra_gte_read_fifo(gte_dev); - - spin_lock_irqsave(&ev->lock, flags); - - if (!test_bit(GTE_EVENT_REGISTERED, &ev->flags)) { - dev_dbg(gte_dev->pdev, "Event: %d is not registered", ev_id); - ret = -EINVAL; - goto unlock; - } - - if (kfifo_is_empty(&ev->ev_fifo)) { - dev_dbg(gte_dev->pdev, "Event: %d fifo is empty", ev_id); - ret = -EAGAIN; - goto unlock; - } - - ret = kfifo_out(&ev->ev_fifo, (unsigned char *)&el, sizeof(el)); - if (unlikely(ret != sizeof(el))) { - dev_dbg(gte_dev->pdev, - "Event: %d retrieved element is in improper size", - ev_id); - ret = -EINVAL; - goto unlock; - } - - hts->dir = el.dir; - hts->ts_raw = el.tsc; - hts->ts_ns = el.tsc << GTE_TS_NS_SHIFT; - atomic_dec(&ev->usage); - ret = 0; - -unlock: - spin_unlock_irqrestore(&ev->lock, flags); - return ret; -} -EXPORT_SYMBOL(tegra_gte_retrieve_event); - -/* - * GPIO event monitoring from userspace management. Only GPIO type is supported - * to be monitored and timestamp using GTE from the userspace. - */ -struct gte_uspace_event_state { - struct tegra_gte_dev *gdev; - u32 eflags; - u32 gpio_in; - int irq; - char *irqname; - char *label; - wait_queue_head_t wait; - struct mutex read_lock; - DECLARE_KFIFO(events, struct tegra_gte_hts_event_data, GTE_EV_FIFO_EL); - struct tegra_gte_ev_desc *gte_data; -}; - -static __poll_t gte_event_poll(struct file *filep, - struct poll_table_struct *wait) -{ - struct gte_uspace_event_state *le = filep->private_data; - __poll_t events = 0; - - poll_wait(filep, &le->wait, wait); - - if (!kfifo_is_empty(&le->events)) - events = POLLIN | POLLRDNORM; - - return events; -} - - -static ssize_t gte_event_read(struct file *filep, char __user *buf, - size_t count, - loff_t *f_ps) -{ - struct gte_uspace_event_state *le = filep->private_data; - unsigned int copied; - int ret; - - if (count < sizeof(struct tegra_gte_hts_event_data)) - return -EINVAL; - - do { - if (kfifo_is_empty(&le->events)) { - if (filep->f_flags & O_NONBLOCK) - return -EAGAIN; - - ret = wait_event_interruptible(le->wait, - !kfifo_is_empty(&le->events)); - if (ret) - return ret; - } - - if (mutex_lock_interruptible(&le->read_lock)) - return -ERESTARTSYS; - ret = kfifo_to_user(&le->events, buf, count, &copied); - mutex_unlock(&le->read_lock); - - if (ret) - return ret; - - /* - * If we couldn't read anything from the fifo (a different - * thread might have been faster) we either return -EAGAIN if - * the file descriptor is non-blocking, otherwise we go back to - * sleep and wait for more data to arrive. - */ - if (copied == 0 && (filep->f_flags & O_NONBLOCK)) - return -EAGAIN; - - } while (copied == 0); - - return copied; -} - -static int gte_event_release(struct inode *inode, struct file *filep) -{ - struct gte_uspace_event_state *le = filep->private_data; - struct tegra_gte_dev *gdev = le->gdev; - - tegra_gte_unregister_event(le->gte_data); - free_irq(le->irq, le); - gpio_free(le->gpio_in); - kfree(le->irqname); - kfree(le->label); - kfree(le); - put_device(&gdev->c_dev); - return 0; -} - -static const struct file_operations gte_event_fileops = { - .release = gte_event_release, - .read = gte_event_read, - .poll = gte_event_poll, - .owner = THIS_MODULE, - .llseek = noop_llseek, -}; - -static irqreturn_t gte_event_irq_thread(int irq, void *p) -{ - int ret; - struct gte_uspace_event_state *le = p; - struct tegra_gte_hts_event_data ge; - struct tegra_gte_ev_detail hw; - - memset(&ge, 0, sizeof(ge)); - ret = tegra_gte_retrieve_event(le->gte_data, &hw); - if (ret == 0) { - ge.timestamp = hw.ts_ns; - ge.dir = hw.dir; - } else { - dev_dbg(le->gdev->pdev, "failed to retrieve event\n"); - return IRQ_HANDLED; - } - - ret = kfifo_put(&le->events, ge); - if (ret != 0) - wake_up_poll(&le->wait, POLLIN); - - return IRQ_HANDLED; -} - -#define GPIOEVENT_REQUEST_VALID_FLAGS (TEGRA_GTE_EVENT_RISING_EDGE | \ - TEGRA_GTE_EVENT_FALLING_EDGE) - -static int gte_event_create(struct tegra_gte_dev *gdev, void __user *ip) -{ - struct tegra_gte_hts_event_req eventreq; - struct gte_uspace_event_state *le; - struct file *file; - int offset; - u32 eflags; - int fd; - int ret; - int irqflags = 0; - - if (copy_from_user(&eventreq, ip, sizeof(eventreq))) - return -EFAULT; - - offset = tegra_gte_convert_to_offset(eventreq.global_gpio_pin, gdev); - if (offset < 0) - return -EINVAL; - - eflags = eventreq.eventflags; - /* Return an error if a unknown flag is set */ - if (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS) { - dev_err(gdev->pdev, "Invalid event flags\n"); - return -EINVAL; - } - - le = kzalloc(sizeof(*le), GFP_KERNEL); - if (!le) - return -ENOMEM; - - get_device(&gdev->c_dev); - - le->gdev = gdev; - - le->label = kzalloc(GTE_MAX_EV_NAME_SZ, GFP_KERNEL); - if (!le->label) { - ret = -ENOMEM; - goto out_free_le; - } - scnprintf(le->label, GTE_MAX_EV_NAME_SZ, "gevent%d", offset); - - ret = gpio_request(eventreq.global_gpio_pin, le->label); - if (ret) { - dev_err(gdev->pdev, "failed to request gpio\n"); - ret = -EINVAL; - goto out_free_label; - } - - ret = gpio_direction_input(eventreq.global_gpio_pin); - if (ret) { - dev_err(gdev->pdev, "failed to set pin direction\n"); - ret = -EINVAL; - goto out_free_label; - } - - /* IRQ setup */ - ret = gpio_to_irq(eventreq.global_gpio_pin); - if (ret < 0) { - dev_err(gdev->pdev, "failed to map GPIO to IRQ: %d\n", ret); - ret = -EINVAL; - goto out_free_label; - } - le->irq = ret; - - if (eflags & TEGRA_GTE_EVENT_RISING_EDGE) - irqflags |= IRQF_TRIGGER_RISING; - if (eflags & TEGRA_GTE_EVENT_FALLING_EDGE) - irqflags |= IRQF_TRIGGER_FALLING; - irqflags |= IRQF_ONESHOT; - irqflags |= IRQF_SHARED; - - le->irqname = kzalloc(GTE_MAX_EV_NAME_SZ, GFP_KERNEL); - if (!le->irqname) { - ret = -ENOMEM; - goto out_free_label; - } - - scnprintf(le->irqname, GTE_MAX_EV_NAME_SZ, "event%d", offset); - - /* Request a thread to read the events */ - ret = request_threaded_irq(le->irq, NULL, gte_event_irq_thread, - irqflags, le->irqname, le); - if (ret) { - dev_err(gdev->pdev, "failed request irq\n"); - goto out_free_name; - } - - le->gpio_in = eventreq.global_gpio_pin; - INIT_KFIFO(le->events); - init_waitqueue_head(&le->wait); - mutex_init(&le->read_lock); - - fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC); - if (fd < 0) { - ret = fd; - goto out_free_irq; - } - - file = anon_inode_getfile("gte-gpio-event", >e_event_fileops, le, - O_RDONLY | O_CLOEXEC); - if (IS_ERR(file)) { - ret = PTR_ERR(file); - dev_err(gdev->pdev, "failed to create file\n"); - goto out_put_unused_fd; - } - - eventreq.fd = fd; - - le->gte_data = __gte_register_event(offset, gdev); - if (IS_ERR(le->gte_data)) { - ret = PTR_ERR(le->gte_data); - dev_err(gdev->pdev, "failed gte register event\n"); - goto out_put_file; - } - - if (copy_to_user(ip, &eventreq, sizeof(eventreq))) { - dev_err(gdev->pdev, "failed to copy user\n"); - ret = -EFAULT; - goto out_put_file; - } - - fd_install(fd, file); - dev_dbg(gdev->pdev, "GPIO event has been created\n"); - - return 0; - -out_put_file: - fput(file); -out_put_unused_fd: - put_unused_fd(fd); -out_free_irq: - free_irq(le->irq, le); -out_free_name: - kfree(le->irqname); -out_free_label: - kfree(le->label); -out_free_le: - kfree(le); - put_device(&gdev->c_dev); - return ret; -} - -static long gte_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - struct tegra_gte_dev *gdev = filp->private_data; - void __user *ip = (void __user *)arg; - - if (!gdev) - return -ENODEV; - - if (cmd == TEGRA_GTE_HTS_CREATE_GPIO_EV_IOCTL) - return gte_event_create(gdev, ip); - - return -EINVAL; -} - -#ifdef CONFIG_COMPAT -static long gte_ioctl_compat(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - return gte_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - -static int gte_chrdev_open(struct inode *inode, struct file *filp) -{ - struct tegra_gte_dev *gdev = container_of(inode->i_cdev, - struct tegra_gte_dev, - chrdev); - - get_device(&gdev->c_dev); - filp->private_data = gdev; - - return nonseekable_open(inode, filp); -} - -static int gte_chrdev_release(struct inode *inode, struct file *filp) -{ - struct tegra_gte_dev *gdev = container_of(inode->i_cdev, - struct tegra_gte_dev, - chrdev); - - put_device(&gdev->c_dev); - return 0; -} - -static const struct file_operations gte_fileops = { - .release = gte_chrdev_release, - .open = gte_chrdev_open, - .owner = THIS_MODULE, - .llseek = no_llseek, - .unlocked_ioctl = gte_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = gte_ioctl_compat, -#endif -}; - -static void tegra_gte_read_fifo(struct tegra_gte_dev *gte) -{ - u32 tsh, tsl, src, pv, cv, acv, slice, bit_index, ev_id; - u64 tsc; - int dir; - unsigned long flags, hw_spin_lock_flags; - struct tegra_gte_ev_el ts; - struct tegra_gte_event_info *ev = gte->ev; - - spin_lock_irqsave(>e->lock, hw_spin_lock_flags); - - while ((tegra_gte_readl(gte, GTE_TESTATUS) >> - GTE_TESTATUS_OCCUPANCY_SHIFT) & - GTE_TESTATUS_OCCUPANCY_MASK) { - tsh = tegra_gte_readl(gte, GTE_TETSCH); - tsl = tegra_gte_readl(gte, GTE_TETSCL); - tsc = (((u64)tsh << 32) | tsl); - - src = tegra_gte_readl(gte, GTE_TESRC); - slice = (src >> GTE_TESRC_SLICE_SHIFT) & - GTE_TESRC_SLICE_DEFAULT_MASK; - - pv = tegra_gte_readl(gte, GTE_TEPCV); - cv = tegra_gte_readl(gte, GTE_TECCV); - acv = pv ^ cv; - - while (acv) { - bit_index = __builtin_ctz(acv); - if ((pv >> bit_index) & BIT(0)) - dir = TEGRA_GTE_EVENT_RISING_EDGE; - else - dir = TEGRA_GTE_EVENT_FALLING_EDGE; - - ev_id = bit_index + (slice << 5); - spin_lock_irqsave(&ev[ev_id].lock, flags); - if (test_bit(GTE_EVENT_REGISTERED, &ev[ev_id].flags)) { - ts.tsc = tsc; - ts.dir = dir; - dev_dbg(gte->pdev, "ISR for ev id:%d, ts:%llu", - ev_id, tsc); - if (kfifo_avail(&ev[ev_id].ev_fifo) >= - sizeof(ts)) { - kfifo_in(&ev[ev_id].ev_fifo, - (unsigned char *)&ts, - sizeof(ts)); - atomic_inc(&ev[ev_id].usage); - } else { - atomic_inc(&ev[ev_id].dropped_evs); - } - } - spin_unlock_irqrestore(&ev[ev_id].lock, flags); - acv &= ~BIT(bit_index); - } - - tegra_gte_writel(gte, GTE_TECMD, GTE_TECMD_CMD_POP); - } - - spin_unlock_irqrestore(>e->lock, hw_spin_lock_flags); -} - -static irqreturn_t tegra_gte_isr(int irq, void *dev_id) -{ - struct tegra_gte_dev *gte = dev_id; - - tegra_gte_read_fifo(gte); - - return IRQ_HANDLED; -} - -/* Device specific sysfs management */ - -/* Shows total numbers of events registered with the given device */ -static ssize_t show_events_registered(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct tegra_gte_dev *gte_dev = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%d\n", - atomic_read(>e_dev->usage)); -} - -static DEVICE_ATTR(events_registered, 0444, show_events_registered, NULL); - -static struct attribute *gte_dev_attrs[] = { - &dev_attr_events_registered.attr, - NULL, -}; - -static struct attribute_group gte_def_attr_group = { - .attrs = gte_dev_attrs, -}; - -static int tegra_gte_sysfs_create(struct platform_device *pdev) -{ - return sysfs_create_group(&pdev->dev.kobj, >e_def_attr_group); -} - -static int tegra_gte_chardv_create(struct tegra_gte_dev *gdev) -{ - int ret; - - ret = bus_register(>e_bus_type); - if (ret < 0) { - dev_err(gdev->pdev, "could not register gte bus type\n"); - return ret; - } - - ret = alloc_chrdev_region(>e_devt, 0, GTE_DEV_MAX, "gtechip"); - if (ret < 0) { - dev_err(gdev->pdev, "failed to allocate char dev region\n"); - bus_unregister(>e_bus_type); - return ret; - } - - gdev->c_dev.bus = >e_bus_type; - gdev->id = ida_simple_get(>e_ida, 0, 0, GFP_KERNEL); - - dev_set_name(&gdev->c_dev, "gtechip%d", gdev->id); - device_initialize(&gdev->c_dev); - dev_set_drvdata(&gdev->c_dev, gdev); - - cdev_init(&gdev->chrdev, >e_fileops); - gdev->chrdev.owner = THIS_MODULE; - gdev->chrdev.kobj.parent = &gdev->c_dev.kobj; - gdev->c_dev.devt = MKDEV(MAJOR(gte_devt), gdev->id); - ret = cdev_add(&gdev->chrdev, gdev->c_dev.devt, 1); - if (ret < 0) - dev_warn(gdev->pdev, "failed to add char device %d:%d\n", - MAJOR(gte_devt), gdev->id); - else - dev_dbg(gdev->pdev, "added GTE chardev (%d:%d)\n", - MAJOR(gte_devt), gdev->id); - ret = device_add(&gdev->c_dev); - if (ret) { - dev_err(gdev->pdev, "failed to add char dev:%d\n", ret); - goto err_remove_chardev; - } - - gdev->is_chardev = true; - - return 0; - -err_remove_chardev: - ida_simple_remove(>e_ida, gdev->id); - cdev_del(&gdev->chrdev); - unregister_chrdev_region(gte_devt, GTE_DEV_MAX); - bus_unregister(>e_bus_type); - - return ret; -} - -static const struct of_device_id tegra_gte_of_match[] = { - { .compatible = "nvidia,tegra194-gte-lic"}, - { .compatible = "nvidia,tegra194-gte-aon", .data = &t194_aon_gte_map}, - { .compatible = "nvidia,tegra234-gte-aon", .data = &t234_aon_gte_map}, - { } -}; -MODULE_DEVICE_TABLE(of, tegra_gte_of_match); - -static void tegra_gte_add_to_list(struct tegra_gte_dev *gdev) -{ - mutex_lock(>e_list_lock); - list_add_tail(&gdev->list, >e_devices); - mutex_unlock(>e_list_lock); -} - -static void tegra_gte_init_and_enable(struct tegra_gte_dev *gte) -{ - u32 val = 0, slices; - int i; - struct tegra_gte_event_info *ev = gte->ev; - - slices = gte->num_events >> 5; - atomic_set(>e->usage, 0); - - spin_lock_init(>e->lock); - - for (i = 0; i < slices; i++) { - gte->sl[i].flags = 0; - spin_lock_init(>e->sl[i].s_lock); - } - for (i = 0; i < gte->num_events; i++) { - ev[i].flags = 0; - ev[i].dev = gte; - atomic_set(&ev[i].usage, 0); - atomic_set(&ev[i].dropped_evs, 0); - spin_lock_init(&ev[i].lock); - mutex_init(&ev[i].ev_lock); - } - - val = GTE_TECTRL_ENABLE_ENABLE | - (GTE_TECTRL_INTR_ENABLE << GTE_TECTRL_INTR_SHIFT) | - (gte->itr_thrshld << GTE_TECTRL_OCCU_SHIFT); - tegra_gte_writel(gte, GTE_TECTRL, val); - - tegra_gte_add_to_list(gte); -} - -static void tegra_gte_chardv_remove(struct tegra_gte_dev *gdev) -{ - device_del(&gdev->c_dev); - cdev_del(&gdev->chrdev); - unregister_chrdev_region(gte_devt, GTE_DEV_MAX); - bus_unregister(>e_bus_type); - ida_simple_remove(>e_ida, gdev->id); -} - -static int tegra_gte_disable(struct tegra_gte_dev *gte) -{ - int ret = 0; - - mutex_lock(>e_list_lock); - if (test_bit(GTE_DEV_IN_REG, >e->flags)) { - ret = -EBUSY; - goto unlock; - } - - __list_del_entry(>e->list); - tegra_gte_writel(gte, GTE_TECTRL, 0); - -unlock: - mutex_unlock(>e_list_lock); - - return ret; -} - -static int tegra_gte_remove(struct platform_device *pdev) -{ - struct tegra_gte_dev *gte_dev = dev_get_drvdata(&pdev->dev); - - if (tegra_gte_disable(gte_dev)) - return -EBUSY; - - sysfs_remove_group(&pdev->dev.kobj, >e_def_attr_group); - if (gte_dev->is_chardev) - tegra_gte_chardv_remove(gte_dev); - - return 0; -} - -static int tegra_gte_probe(struct platform_device *pdev) -{ - int ret; - u32 slices; - struct resource *res; - struct device *dev; - struct tegra_gte_dev *gte_dev; - - dev = &pdev->dev; - - gte_dev = devm_kzalloc(dev, sizeof(*gte_dev), GFP_KERNEL); - if (!gte_dev) - return -ENOMEM; - - dev_set_drvdata(&pdev->dev, gte_dev); - gte_dev->pdev = dev; - gte_dev->ev_map = of_device_get_match_data(&pdev->dev); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "no mem resource\n"); - return -EINVAL; - } - - gte_dev->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(gte_dev->regs)) - return PTR_ERR(gte_dev->regs); - - ret = of_property_read_u32(dev->of_node, "nvidia,int-threshold", - >e_dev->itr_thrshld); - if (ret != 0) - gte_dev->itr_thrshld = 1; - - ret = of_property_read_u32(dev->of_node, "nvidia,num-slices", &slices); - if (ret != 0) { - dev_err(dev, "Could not read slices\n"); - return -EINVAL; - } - - gte_dev->num_events = slices << 5; - - gte_dev->sl = devm_kzalloc(dev, sizeof(struct gte_slices) * slices, - GFP_KERNEL); - if (!gte_dev->sl) - return -ENOMEM; - - gte_dev->ev = devm_kzalloc(dev, sizeof(struct tegra_gte_event_info) * - gte_dev->num_events, GFP_KERNEL); - if (!gte_dev->ev) - return -ENOMEM; - - ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "get irq failed.\n"); - return ret; - } - gte_dev->gte_irq = ret; - ret = devm_request_irq(dev, gte_dev->gte_irq, tegra_gte_isr, 0, - dev_name(dev), gte_dev); - if (ret < 0) { - dev_err(dev, "request irq failed.\n"); - return ret; - } - gte_dev->kobj = &dev->kobj; - - if (!of_device_is_compatible(dev->of_node, "nvidia,tegra194-gte-lic")) - tegra_gte_chardv_create(gte_dev); - - ret = tegra_gte_sysfs_create(pdev); - if (ret) - dev_err(dev, "sysfs creation failed\n"); - - tegra_gte_init_and_enable(gte_dev); - - dev_dbg(gte_dev->pdev, "events: %d, slices:%d", - gte_dev->num_events, slices); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int tegra_gte_resume_early(struct device *dev) -{ - int i; - struct tegra_gte_dev *gte_dev = dev_get_drvdata(dev); - u32 slices = gte_dev->num_events >> 5; - u32 sl_bit_shift = __builtin_ctz(GTE_SLICE_SIZE); - - tegra_gte_writel(gte_dev, GTE_TECTRL, gte_dev->conf_rval); - - for (i = 0; i < slices; i++) { - spin_lock(>e_dev->sl[i].s_lock); - tegra_gte_writel(gte_dev, - ((i << sl_bit_shift) + GTE_SLICE0_TETEN), - gte_dev->sl[i].r_val); - clear_bit(GTE_SUSPEND, >e_dev->sl[i].flags); - spin_unlock(>e_dev->sl[i].s_lock); - } - - return 0; -} - -static int tegra_gte_suspend_late(struct device *dev) -{ - int i; - struct tegra_gte_dev *gte_dev = dev_get_drvdata(dev); - u32 slices = gte_dev->num_events >> 5; - u32 sl_bit_shift = __builtin_ctz(GTE_SLICE_SIZE); - - gte_dev->conf_rval = tegra_gte_readl(gte_dev, GTE_TECTRL); - for (i = 0; i < slices; i++) { - spin_lock(>e_dev->sl[i].s_lock); - gte_dev->sl[i].r_val = tegra_gte_readl(gte_dev, - ((i << sl_bit_shift) + GTE_SLICE0_TETEN)); - set_bit(GTE_SUSPEND, >e_dev->sl[i].flags); - spin_unlock(>e_dev->sl[i].s_lock); - } - - return 0; -} -#endif - -static const struct dev_pm_ops tegra_gte_pm = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(tegra_gte_suspend_late, - tegra_gte_resume_early) -}; - -static struct platform_driver tegra_gte_driver = { - .probe = tegra_gte_probe, - .remove = tegra_gte_remove, - .driver = { - .name = "tegra_gte", - .pm = &tegra_gte_pm, - .of_match_table = tegra_gte_of_match, - }, -}; - -module_platform_driver(tegra_gte_driver); - -MODULE_AUTHOR("Dipen Patel "); -MODULE_DESCRIPTION("NVIDIA Tegra GTE (Generic Timestamping Engine) driver"); -MODULE_LICENSE("GPL v2"); - diff --git a/drivers/staging/platform/tegra/gte_test/Makefile b/drivers/staging/platform/tegra/gte_test/Makefile deleted file mode 100644 index 112deaa6..00000000 --- a/drivers/staging/platform/tegra/gte_test/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. - -obj-m += tegra194_gte_test.o diff --git a/drivers/staging/platform/tegra/gte_test/tegra194_gte_test.c b/drivers/staging/platform/tegra/gte_test/tegra194_gte_test.c deleted file mode 100644 index 18461b05..00000000 --- a/drivers/staging/platform/tegra/gte_test/tegra194_gte_test.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 2020-2023, NVIDIA CORPORATION & AFFILIATES.All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Sample GTE test driver demonstrating GTE API usage. - * - * Sample drivers monitors LIC IRQ provided by lic_irq module parameter and - * GPIO provided by gpio_in parameter. - * - * Note: gpio_out and gpio_in need to be shorted externally using some wire - * in order for this test driver to work for the GPIO monitoring. - */ - -/* - * This represents global ID of the GPIO since global ID or logical - * partitioning of the GPIOs across various GPIO controller happens - * at the run time, user has to provide this parameter in order to - * request. - * - * gpio_in will be used in GTE to monitor the event and will be configured - * as input. - */ -static int gpio_in = -EINVAL; -module_param(gpio_in, int, 0660); - -/* - * Same comment as gpio_in but will be used as output and to toggle gpio_in - * state. - */ -static int gpio_out = -EINVAL; -module_param(gpio_out, int, 0660); - -/* IRQ number to monitor */ -static int lic_irq = -EINVAL; -module_param(lic_irq, int, 0660); - -static struct tegra_gte_test { - struct tegra_gte_ev_desc *data_lic; - struct tegra_gte_ev_desc *data_gpio; - int gpio_in_irq; - struct timer_list timer; - struct kobject *kobj; -} gte; - -/* - * Sysfs attribute to register/unregister GTE gpio event for 1 and 0 values - */ -static ssize_t store_gpio_en_dis(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) -{ - int ret = count; - unsigned long val = 0; - struct device_node *np; - np = of_find_compatible_node(NULL, NULL, "nvidia,tegra194-gte-aon"); - - if (!np) { - np = of_find_compatible_node(NULL, NULL, "nvidia,tegra234-gte-aon"); - if (!np) { - pr_err("Could not locate aon gte node\n"); - return -EINVAL; - } - } - - if (kstrtoul(buf, 10, &val) < 0) { - ret = -EINVAL; - goto error; - } - - if (val == 1) { - if (gte.data_gpio) { - pr_info("gpio_in is already registered\n"); - ret = -EEXIST; - goto error; - } - gte.data_gpio = tegra_gte_register_event(np, gpio_in); - if (IS_ERR(gte.data_gpio)) { - pr_err("Could not register gpio\n"); - ret = PTR_ERR(gte.data_gpio); - gte.data_gpio = NULL; - goto error; - } - } else if (val == 0) { - if (!gte.data_gpio) { - pr_info("gpio_in is not registered\n"); - ret = -EINVAL; - goto error; - } - ret = tegra_gte_unregister_event(gte.data_gpio); - if (ret == -EBUSY) { - /* User should retry */ - pr_err("failed to unregister gpio in\n"); - goto error; - } else { /* For anything else set data to null */ - gte.data_gpio = NULL; - if (ret == 0) - ret = count; - } - } else { - ret = -EINVAL; - } - -error: - of_node_put(np); - return ret; -} - -/* - * Sysfs attribute to register/unregister GTE LIC IRQ event for 1 and 0 values - */ -static ssize_t store_lic_irq_en_dis(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) -{ - int ret = count; - unsigned long val = 0; - struct device_node *np; - np = of_find_compatible_node(NULL, NULL, "nvidia,tegra194-gte-lic"); - - if (!np) { - pr_err("Could not locate lic gte node\n"); - return -EINVAL; - } - - if (kstrtoul(buf, 10, &val) < 0) { - ret = -EINVAL; - goto error; - } - - if (val == 1) { - if (gte.data_lic) { - pr_info("lic_irq is already registered\n"); - ret = -EEXIST; - goto error; - } - gte.data_lic = tegra_gte_register_event(np, lic_irq); - if (IS_ERR(gte.data_lic)) { - pr_err("Could not register lic irq\n"); - ret = PTR_ERR(gte.data_lic); - gte.data_lic = NULL; - goto error; - } - } else if (val == 0) { - if (!gte.data_lic) { - pr_info("lic_irq is not registered\n"); - ret = -EINVAL; - goto error; - } - ret = tegra_gte_unregister_event(gte.data_lic); - if (ret == -EBUSY) { - /* User should retry */ - pr_err("failed to unregister lic irq\n"); - goto error; - } else { /* For anything else set data to null */ - gte.data_lic = NULL; - if (ret == 0) - ret = count; - } - } else { - ret = -EINVAL; - } - -error: - of_node_put(np); - return ret; -} - -/* Shows LIC event timestamp information */ -static ssize_t show_lic_irq_ts(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - struct tegra_gte_ev_detail hts; - - if (tegra_gte_retrieve_event((gte.data_lic), &hts) != 0) - return -EINVAL; - - pr_debug("Retrieved lic event ts_raw: %llu, ts_ns %llu\n", - hts.ts_raw, hts.ts_ns); - return scnprintf(buf, PAGE_SIZE, "ts_raw: %llu, ts_ns: %llu\n", - hts.ts_raw, hts.ts_ns); -} - -static struct kobj_attribute gpio_en_dis_attr = - __ATTR(gpio_en_dis, 0220, NULL, store_gpio_en_dis); -static struct kobj_attribute lic_irq_en_dis_attr = - __ATTR(lic_irq_en_dis, 0220, NULL, store_lic_irq_en_dis); -static struct kobj_attribute lic_irq_ts_attr = - __ATTR(lic_irq_ts, 0440, show_lic_irq_ts, NULL); - -static struct attribute *attrs[] = { - &gpio_en_dis_attr.attr, - &lic_irq_en_dis_attr.attr, - &lic_irq_ts_attr.attr, - NULL, -}; - -static struct attribute_group tegra_gte_test_attr_group = { - .attrs = attrs, -}; - -static int tegra_gte_test_sysfs_create(void) -{ - int ret; - - /* Creates object under /sys/kernel/ */ - gte.kobj = kobject_create_and_add("tegra_gte_test", kernel_kobj); - if (!gte.kobj) - return -ENOMEM; - - ret = sysfs_create_group(gte.kobj, &tegra_gte_test_attr_group); - if (ret) - kobject_put(gte.kobj); - return ret; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) -static void gpio_timer_cb(unsigned long data) -#else -static void gpio_timer_cb(struct timer_list *t) -#endif -{ - gpio_set_value(gpio_out, !gpio_get_value(gpio_out)); - mod_timer(>e.timer, jiffies + msecs_to_jiffies(5000)); -} - -static irqreturn_t tegra_gte_test_gpio_isr(int irq, void *data) -{ - struct tegra_gte_ev_detail hts; - struct tegra_gte_test *gte = data; - - if (tegra_gte_retrieve_event((gte->data_gpio), &hts) != 0) { - pr_info("No timestamp available\n"); - return IRQ_HANDLED; - } - - pr_info("GPIO HW Timestamp: raw %llu, ns %llu\n", - hts.ts_raw, hts.ts_ns); - return IRQ_HANDLED; -} - -static int __init tegra_gte_test_init(void) -{ - int ret = 0; - - if (gpio_out == -EINVAL || gpio_in == -EINVAL || lic_irq == EINVAL) { - pr_err("Invalid gpio_out, gpio_in and irq\n"); - return -EINVAL; - } - - gte.data_lic = NULL; - gte.data_gpio = NULL; - - ret = gpio_request(gpio_out, "gte_test_gpio_out"); - if (ret) { - pr_err("failed request gpio out\n"); - return -EINVAL; - } - - ret = gpio_direction_output(gpio_out, 0); - if (ret) { - pr_err("failed to set pin direction\n"); - ret = -EINVAL; - goto free_gpio_out; - } - - ret = gpio_request(gpio_in, "gte_test_gpio_in"); - if (ret) { - pr_err("failed to request gpio in\n"); - ret = -EINVAL; - goto free_gpio_out; - } - - ret = gpio_direction_input(gpio_in); - if (ret) { - pr_err("failed to set pin direction\n"); - ret = -EINVAL; - goto free_gpio_in; - - } - - /* IRQ setup */ - ret = gpio_to_irq(gpio_in); - if (ret < 0) { - pr_err("failed to map GPIO to IRQ: %d\n", ret); - ret = -EINVAL; - goto free_gpio_in; - } - - gte.gpio_in_irq = ret; - - ret = request_irq(ret, tegra_gte_test_gpio_isr, - IRQF_TRIGGER_RISING | IRQF_NO_THREAD, - "tegra_gte_test_isr", >e); - if (ret) { - pr_err("failed to acquire IRQ\n"); - ret = -EINVAL; - goto free_gpio_in; - } - - ret = tegra_gte_test_sysfs_create(); - if (ret != 0) { - pr_err("sysfs creation failed\n"); - ret = -EINVAL; - goto free_irq; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) - setup_timer(>e.timer, gpio_timer_cb, 0); -#else - timer_setup(>e.timer, gpio_timer_cb, 0); -#endif - - mod_timer(>e.timer, jiffies + msecs_to_jiffies(5000)); - - return 0; - -free_irq: - free_irq(gte.gpio_in_irq, >e); -free_gpio_in: - gpio_free(gpio_in); -free_gpio_out: - gpio_free(gpio_out); - - return ret; -} - -static void __exit tegra_gte_test_exit(void) -{ - free_irq(gte.gpio_in_irq, >e); - gpio_free(gpio_in); - gpio_free(gpio_out); - tegra_gte_unregister_event(gte.data_gpio); - tegra_gte_unregister_event(gte.data_lic); - kobject_put(gte.kobj); - del_timer(>e.timer); -} - -module_init(tegra_gte_test_init); -module_exit(tegra_gte_test_exit); -MODULE_AUTHOR("Dipen Patel "); -MODULE_DESCRIPTION("NVIDIA Tegra GTE driver test"); -MODULE_LICENSE("GPL v2");