From d6eb4eaa82396fd8d8f31abab6c6cae09f4d43dc Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 3 Apr 2023 13:26:29 +0000 Subject: [PATCH 001/108] misc: mods: Remove Makefile to prepare for mods integration mods driver is available in the kernel/nvidia and to integrate with git history, it is required to remove the dummy Makefile. Bug 4038415 Change-Id: Ib66eab27e6168bf416df2f73c8df4a4a50af39f8 Signed-off-by: Laxman Dewangan --- drivers/misc/mods/Makefile | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 drivers/misc/mods/Makefile diff --git a/drivers/misc/mods/Makefile b/drivers/misc/mods/Makefile deleted file mode 100644 index 94a7d142..00000000 --- a/drivers/misc/mods/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. - -# NOTE: Do not change or add anything in this makefile. -# The source code and makefile rules are copied from the -# kernel/nvidia/drivers/misc/mods. This file is -# just place-holder for empty makefile to avoid any build -# issue when copy is not done from command line and building -# the tree independent of source copy. From 1f6ca0cb271826c2d33fecce982fe4b8651590f5 Mon Sep 17 00:00:00 2001 From: Chris Dragan Date: Mon, 22 May 2017 05:33:33 -0700 Subject: [PATCH 002/108] misc: add mods driver * copy driver sources from kernel-4.4 repository * sync with copy in Perforce * fix several formatting errors * fix issues reported by Coverity Bug 200295104 Change-Id: I0a37cd12041d8fdcafb72b2e67d1a9234320e11b Signed-off-by: Chris Dragan Reviewed-on: http://git-master/r/1487057 Reviewed-by: svccoveritychecker GVS: Gerrit_Virtual_Submit Reviewed-by: Bharat Nihalani Reviewed-by: Vivek Aseeja Reviewed-by: Kiran Kasamsetty --- drivers/misc/mods/Makefile.nvidia | 15 + drivers/misc/mods/mods.dts | 27 + drivers/misc/mods/mods.h | 1188 ++++++++++++++++++ drivers/misc/mods/mods_acpi.c | 452 +++++++ drivers/misc/mods/mods_adsp.c | 95 ++ drivers/misc/mods/mods_clock.c | 621 ++++++++++ drivers/misc/mods/mods_config.h | 63 + drivers/misc/mods/mods_debugfs.c | 807 +++++++++++++ drivers/misc/mods/mods_dma.c | 502 ++++++++ drivers/misc/mods/mods_dmabuf.c | 142 +++ drivers/misc/mods/mods_internal.h | 589 +++++++++ drivers/misc/mods/mods_irq.c | 1385 +++++++++++++++++++++ drivers/misc/mods/mods_krnl.c | 1582 ++++++++++++++++++++++++ drivers/misc/mods/mods_mem.c | 1808 ++++++++++++++++++++++++++++ drivers/misc/mods/mods_netdevice.c | 46 + drivers/misc/mods/mods_pci.c | 925 ++++++++++++++ drivers/misc/mods/mods_tegradc.c | 346 ++++++ drivers/misc/mods/mods_tegraprod.c | 632 ++++++++++ 18 files changed, 11225 insertions(+) create mode 100644 drivers/misc/mods/Makefile.nvidia create mode 100644 drivers/misc/mods/mods.dts create mode 100644 drivers/misc/mods/mods.h create mode 100644 drivers/misc/mods/mods_acpi.c create mode 100644 drivers/misc/mods/mods_adsp.c create mode 100644 drivers/misc/mods/mods_clock.c create mode 100644 drivers/misc/mods/mods_config.h create mode 100644 drivers/misc/mods/mods_debugfs.c create mode 100644 drivers/misc/mods/mods_dma.c create mode 100644 drivers/misc/mods/mods_dmabuf.c create mode 100644 drivers/misc/mods/mods_internal.h create mode 100644 drivers/misc/mods/mods_irq.c create mode 100644 drivers/misc/mods/mods_krnl.c create mode 100644 drivers/misc/mods/mods_mem.c create mode 100644 drivers/misc/mods/mods_netdevice.c create mode 100644 drivers/misc/mods/mods_pci.c create mode 100644 drivers/misc/mods/mods_tegradc.c create mode 100644 drivers/misc/mods/mods_tegraprod.c diff --git a/drivers/misc/mods/Makefile.nvidia b/drivers/misc/mods/Makefile.nvidia new file mode 100644 index 00000000..95ea2916 --- /dev/null +++ b/drivers/misc/mods/Makefile.nvidia @@ -0,0 +1,15 @@ +obj-$(CONFIG_MODS) := mods.o +mods-y := mods_krnl.o +mods-y += mods_mem.o +mods-y += mods_irq.o +mods-y += mods_clock.o +mods-$(CONFIG_ARCH_TEGRA) += mods_tegraprod.o +mods-$(CONFIG_PCI) += mods_pci.o +mods-$(CONFIG_ACPI) += mods_acpi.o +mods-$(CONFIG_ARCH_TEGRA) += mods_dmabuf.o +mods-$(CONFIG_DMA_ENGINE) += mods_dma.o +mods-$(CONFIG_DEBUG_FS) += mods_debugfs.o +mods-$(CONFIG_TEGRA_DC) += mods_tegradc.o +mods-$(CONFIG_TEGRA_NVADSP) += mods_adsp.o +mods-$(CONFIG_NET) += mods_netdevice.o +mods-objs := mods.dtb.o diff --git a/drivers/misc/mods/mods.dts b/drivers/misc/mods/mods.dts new file mode 100644 index 00000000..818b2b0d --- /dev/null +++ b/drivers/misc/mods/mods.dts @@ -0,0 +1,27 @@ +/* + * mods.dts - This file is part of NVIDIA MODS kernel driver. + * + * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA MODS kernel driver is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * NVIDIA MODS kernel driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVIDIA MODS kernel driver. + * If not, see . + */ + +/dts-v1/; + +/ { + mods { + compatible = "nvidia,tegra-mods"; + status = "okay"; + }; +}; diff --git a/drivers/misc/mods/mods.h b/drivers/misc/mods/mods.h new file mode 100644 index 00000000..1d59872b --- /dev/null +++ b/drivers/misc/mods/mods.h @@ -0,0 +1,1188 @@ +/* + * mods.h - This file is part of NVIDIA MODS kernel driver. + * + * Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA MODS kernel driver is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * NVIDIA MODS kernel driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVIDIA MODS kernel driver. + * If not, see . + */ + +#ifndef _MODS_H_ +#define _MODS_H_ + +#include + +/* Driver version */ +#define MODS_DRIVER_VERSION_MAJOR 3 +#define MODS_DRIVER_VERSION_MINOR 73 +#define MODS_DRIVER_VERSION ((MODS_DRIVER_VERSION_MAJOR << 8) | \ + ((MODS_DRIVER_VERSION_MINOR/10) << 4) | \ + (MODS_DRIVER_VERSION_MINOR%10)) + +#pragma pack(push, 1) + +/* ************************************************************************* */ +/* ** ESCAPE INTERFACE STRUCTURE */ +/* ************************************************************************* */ + +struct mods_pci_dev_2 { + __u16 domain; + __u16 bus; + __u16 device; + __u16 function; +}; + +struct mods_pci_dev { + __u16 bus; + __u8 device; + __u8 function; +}; + +/* MODS_ESC_ALLOC_PAGES */ +struct MODS_ALLOC_PAGES { + /* IN */ + __u32 num_bytes; + __u32 contiguous; + __u32 address_bits; + __u32 attrib; + + /* OUT */ + __u64 memory_handle; +}; + +/* MODS_ESC_DEVICE_ALLOC_PAGES_2 */ +struct MODS_DEVICE_ALLOC_PAGES_2 { + /* IN */ + __u32 num_bytes; + __u32 contiguous; + __u32 address_bits; + __u32 attrib; + struct mods_pci_dev_2 pci_device; + + /* OUT */ + __u64 memory_handle; +}; + +/* MODS_ESC_DEVICE_ALLOC_PAGES */ +struct MODS_DEVICE_ALLOC_PAGES { + /* IN */ + __u32 num_bytes; + __u32 contiguous; + __u32 address_bits; + __u32 attrib; + struct mods_pci_dev pci_device; + + /* OUT */ + __u64 memory_handle; +}; + +/* MODS_ESC_FREE_PAGES */ +struct MODS_FREE_PAGES { + /* IN */ + __u64 memory_handle; +}; + +/* MODS_ESC_GET_PHYSICAL_ADDRESS */ +struct MODS_GET_PHYSICAL_ADDRESS { + /* IN */ + __u64 memory_handle; + __u32 offset; + + /* OUT */ + __u64 physical_address; +}; + +/* MODS_ESC_GET_PHYSICAL_ADDRESS */ +struct MODS_GET_PHYSICAL_ADDRESS_2 { + /* IN */ + __u64 memory_handle; + __u32 offset; + struct mods_pci_dev_2 pci_device; + + /* OUT */ + __u64 physical_address; +}; + +/* MODS_ESC_VIRTUAL_TO_PHYSICAL */ +struct MODS_VIRTUAL_TO_PHYSICAL { + /* IN */ + __u64 virtual_address; + + /* OUT */ + __u64 physical_address; +}; + +/* MODS_ESC_PHYSICAL_TO_VIRTUAL */ +struct MODS_PHYSICAL_TO_VIRTUAL { + /* IN */ + __u64 physical_address; + + /* OUT */ + __u64 virtual_address; + +}; + +/* MODS_ESC_FLUSH_CACHE_RANGE */ +#define MODS_FLUSH_CPU_CACHE 1 +#define MODS_INVALIDATE_CPU_CACHE 2 + +struct MODS_FLUSH_CPU_CACHE_RANGE { + /* IN */ + __u64 virt_addr_start; + __u64 virt_addr_end; + __u32 flags; +}; + +/* MODS_ESC_DMA_MAP_MEMORY */ +struct MODS_DMA_MAP_MEMORY { + /* IN */ + __u64 memory_handle; + struct mods_pci_dev_2 pci_device; +}; + +/* MODS_ESC_FIND_PCI_DEVICE_2 */ +struct MODS_FIND_PCI_DEVICE_2 { + /* IN */ + __u32 device_id; + __u32 vendor_id; + __u32 index; + + /* OUT */ + struct mods_pci_dev_2 pci_device; +}; + +/* MODS_ESC_FIND_PCI_DEVICE */ +struct MODS_FIND_PCI_DEVICE { + /* IN */ + __u32 device_id; + __u32 vendor_id; + __u32 index; + + /* OUT */ + __u32 bus_number; + __u32 device_number; + __u32 function_number; +}; + +/* MODS_ESC_FIND_PCI_CLASS_CODE_2 */ +struct MODS_FIND_PCI_CLASS_CODE_2 { + /* IN */ + __u32 class_code; + __u32 index; + + /* OUT */ + struct mods_pci_dev_2 pci_device; +}; + +/* MODS_ESC_FIND_PCI_CLASS_CODE */ +struct MODS_FIND_PCI_CLASS_CODE { + /* IN */ + __u32 class_code; + __u32 index; + + /* OUT */ + __u32 bus_number; + __u32 device_number; + __u32 function_number; +}; + +/* MODS_ESC_PCI_GET_BAR_INFO_2 */ +struct MODS_PCI_GET_BAR_INFO_2 { + /* IN */ + struct mods_pci_dev_2 pci_device; + __u32 bar_index; + + /* OUT */ + __u64 base_address; + __u64 bar_size; +}; + +/* MODS_ESC_PCI_GET_BAR_INFO */ +struct MODS_PCI_GET_BAR_INFO { + /* IN */ + struct mods_pci_dev pci_device; + __u32 bar_index; + + /* OUT */ + __u64 base_address; + __u64 bar_size; +}; + +/* MODS_ESC_PCI_GET_IRQ_2 */ +struct MODS_PCI_GET_IRQ_2 { + /* IN */ + struct mods_pci_dev_2 pci_device; + + /* OUT */ + __u32 irq; +}; + +/* MODS_ESC_PCI_GET_IRQ */ +struct MODS_PCI_GET_IRQ { + /* IN */ + struct mods_pci_dev pci_device; + + /* OUT */ + __u32 irq; +}; + +/* MODS_ESC_PCI_READ_2 */ +struct MODS_PCI_READ_2 { + /* IN */ + struct mods_pci_dev_2 pci_device; + __u32 address; + __u32 data_size; + + /* OUT */ + __u32 data; +}; + +/* MODS_ESC_PCI_READ */ +struct MODS_PCI_READ { + /* IN */ + __u32 bus_number; + __u32 device_number; + __u32 function_number; + __u32 address; + __u32 data_size; + + /* OUT */ + __u32 data; +}; + +/* MODS_ESC_PCI_WRITE_2 */ +struct MODS_PCI_WRITE_2 { + /* IN */ + struct mods_pci_dev_2 pci_device; + __u32 address; + __u32 data; + __u32 data_size; +}; + +/* MODS_ESC_PCI_WRITE */ +struct MODS_PCI_WRITE { + /* IN */ + __u32 bus_number; + __u32 device_number; + __u32 function_number; + __u32 address; + __u32 data; + __u32 data_size; +}; + +/* MODS_ESC_PCI_HOT_RESET */ +struct MODS_PCI_HOT_RESET { + /* IN */ + struct mods_pci_dev_2 pci_device; +}; + +/* MODS_ESC_SET_PPC_TCE_BYPASS */ +#define MODS_PPC_TCE_BYPASS_DEFAULT 0 +#define MODS_PPC_TCE_BYPASS_ON 1 +#define MODS_PPC_TCE_BYPASS_OFF 2 +struct MODS_SET_PPC_TCE_BYPASS { + /* IN */ + __u8 mode; + __u8 _dummy_align[7]; + struct mods_pci_dev_2 pci_device; + __u64 device_dma_mask; + + /* OUT */ + __u64 dma_base_address; +}; + +/* MODS_ESC_PCI_BUS_ADD_DEVICES*/ +struct MODS_PCI_BUS_ADD_DEVICES { + /* IN */ + __u32 bus; +}; + +/* MODS_ESC_PCI_MAP_RESOURCE */ +struct MODS_PCI_MAP_RESOURCE { + /* IN */ + struct mods_pci_dev_2 local_pci_device; + struct mods_pci_dev_2 remote_pci_device; + __u32 resource_index; + __u64 page_count; + + /* IN/OUT */ + __u64 va; +}; + +/* MODS_ESC_PCI_UNMAP_RESOURCE */ +struct MODS_PCI_UNMAP_RESOURCE { + /* IN */ + struct mods_pci_dev_2 pci_device; + __u64 va; +}; + +/* MODS_ESC_PIO_READ */ +struct MODS_PIO_READ { + /* IN */ + __u16 port; + __u32 data_size; + + /* OUT */ + __u32 data; +}; + +/* MODS_ESC_PIO_WRITE */ +struct MODS_PIO_WRITE { + /* IN */ + __u16 port; + __u32 data; + __u32 data_size; +}; + +#define INQ_CNT 8 + +struct mods_irq_data { + __u32 irq; + __u32 delay; +}; + +struct mods_irq_status { + struct mods_irq_data data[INQ_CNT]; + __u32 irqbits:INQ_CNT; + __u32 otherirq:1; +}; + +/* MODS_ESC_IRQ */ +struct MODS_IRQ { + /* IN */ + __u32 cmd; + __u32 size; /* memory size */ + __u32 irq; /* the irq number to be registered in driver */ + + /* IN OUT */ + __u32 channel; /* application id allocated by driver. */ + + /* OUT */ + struct mods_irq_status stat; /* for querying irq */ + __u64 phys; /* the memory physical address */ +}; +#define MODS_IRQ_MAX_MASKS 16 + +/* MODS_ESC_REGISTER_IRQ_3 */ +struct mods_mask_info2 { + __u8 mask_type; /*mask type 32/64 bit access*/ + __u8 reserved[7]; /*force 64bit alignment */ + __u32 irq_pending_offset; /* register to read IRQ pending status*/ + __u32 irq_enabled_offset; /* register to read IRQ enabled status */ + __u32 irq_enable_offset; /* register to write to enable IRQs */ + __u32 irq_disable_offset; /* register to write to disable IRQs */ + __u64 and_mask; /*and mask for clearing bits in this register */ + __u64 or_mask; /*or mask for setting bit in this register */ +}; + +struct MODS_REGISTER_IRQ_3 { + /* IN */ + struct mods_pci_dev_2 dev; /* device identifying interrupt for */ + /* which the mask will be applied */ + __u64 aperture_addr; /* physical address of aperture */ + __u32 aperture_size; /* size of the mapped region */ + __u32 mask_info_cnt; /* number of entries in mask_info[]*/ + struct mods_mask_info2 mask_info[MODS_IRQ_MAX_MASKS]; + __u8 irq_type; /* MODS_IRQ_TYPE_* */ + __u8 reserved[7]; /* keep alignment to 64bits */ +}; + +/* MODS_ESC_REGISTER_IRQ_2 */ +/* MODS_ESC_UNREGISTER_IRQ_2 */ +/* MODS_ESC_IRQ_HANDLED_2 */ +struct MODS_REGISTER_IRQ_2 { + /* IN */ + struct mods_pci_dev_2 dev; /* device which generates the interrupt */ + __u8 type; /* MODS_IRQ_TYPE_* */ +}; + +/* MODS_ESC_REGISTER_IRQ */ +/* MODS_ESC_UNREGISTER_IRQ */ +/* MODS_ESC_IRQ_HANDLED */ +struct MODS_REGISTER_IRQ { + /* IN */ + struct mods_pci_dev dev; /* device which generates */ + /* the interrupt */ + __u8 type; /* MODS_IRQ_TYPE_* */ +}; + +struct mods_irq_2 { + __u32 delay; /* delay in ns between the irq */ + /* occurring and MODS querying for it */ + struct mods_pci_dev_2 dev; /* device which generated the interrupt */ +}; + +struct mods_irq { + __u32 delay; /* delay in ns between the irq */ + /* occurring and MODS querying */ + /* for it */ + struct mods_pci_dev dev; /* device which generated */ + /* the interrupt */ +}; + +#define MODS_MAX_IRQS 32 + +/* MODS_ESC_QUERY_IRQ_2 */ +struct MODS_QUERY_IRQ_2 { + /* OUT */ + struct mods_irq_2 irq_list[MODS_MAX_IRQS]; + __u8 more; /* indicates that more interrupts */ + /* are waiting */ +}; + +/* MODS_ESC_QUERY_IRQ */ +struct MODS_QUERY_IRQ { + /* OUT */ + struct mods_irq irq_list[MODS_MAX_IRQS]; + __u8 more; /* indicates that more interrupts are waiting */ +}; + +#define MODS_IRQ_TYPE_INT 0 +#define MODS_IRQ_TYPE_MSI 1 +#define MODS_IRQ_TYPE_CPU 2 + +/* MODS_ESC_SET_IRQ_MULTIMASK */ +struct mods_mask_info { + __u8 mask_type; /*mask type 32/64 bit access*/ + __u8 reserved[3]; + __u32 reg_offset; /* offset of register within the bar aperture*/ + __u64 and_mask; /*and mask for clearing bits in this register */ + __u64 or_mask; /*or value for setting bit in this register */ +}; +struct MODS_SET_IRQ_MULTIMASK { + /* IN */ + __u64 aperture_addr; /* physical address of aperture */ + __u32 aperture_size; /* size of the mapped region */ + struct mods_pci_dev_2 dev; /* device identifying interrupt for */ + /* which the mask will be applied */ + __u32 mask_info_cnt; /* number of entries in mask_info[]*/ + struct mods_mask_info mask_info[MODS_IRQ_MAX_MASKS]; + __u8 irq_type; /* irq type */ +}; + + +/* MODS_ESC_SET_IRQ_MASK_2 */ +struct MODS_SET_IRQ_MASK_2 { + /* IN */ + __u64 aperture_addr;/* physical address of aperture */ + __u32 aperture_size;/* size of the mapped region */ + __u32 reg_offset; /* offset of the irq mask */ + /* register within the aperture */ + __u64 and_mask; /* and mask for clearing bits */ + /* in the irq mask register */ + __u64 or_mask; /* or mask for setting bits in */ + /* the irq mask register */ + struct mods_pci_dev_2 dev; /* device identifying interrupt */ + /* for which the mask will be */ + /* applied */ + __u8 irq_type; /* irq type */ + __u8 mask_type; /* mask type */ +}; + +/* MODS_ESC_SET_IRQ_MASK */ +struct MODS_SET_IRQ_MASK { + /* IN */ + __u64 aperture_addr; /* physical address of aperture */ + __u32 aperture_size; /* size of the mapped region */ + __u32 reg_offset; /* offset of the irq mask register */ + /* within the aperture */ + __u32 and_mask; /* and mask for clearing bits in */ + /* the irq mask register */ + __u32 or_mask; /* or mask for setting bits in */ + /* the irq mask register */ + struct mods_pci_dev dev; /* device identifying interrupt */ + /* for which the mask will be */ + /* applied */ + __u8 irq_type; /* irq type */ + __u8 mask_type; /* mask type */ +}; + +#define MAX_DT_SIZE 64 +#define MAX_FULL_SIZE 128 + +/*MODS_ESC_MAP_INTERRUPT*/ +struct MODS_DT_INFO { + /* OUT */ + /* Logical irq number*/ + __u32 irq; + /* IN */ + /* DT name for looking up device tree node */ + char dt_name[MAX_DT_SIZE]; + /* Full name of node as in device tree */ + char full_name[MAX_FULL_SIZE]; + /* Irq index corresponding to physical irq */ + __u32 index; +}; + +#define MODS_MASK_TYPE_IRQ_DISABLE 0 +#define MODS_MASK_TYPE_IRQ_DISABLE64 1 + +#define ACPI_MODS_TYPE_INTEGER 1 +#define ACPI_MODS_TYPE_BUFFER 2 +#define ACPI_MAX_BUFFER_LENGTH 4096 +#define ACPI_MAX_METHOD_LENGTH 12 +#define ACPI_MAX_ARGUMENT_NUMBER 12 + +union ACPI_ARGUMENT { + __u32 type; + + struct { + __u32 type; + __u32 value; + } integer; + + struct { + __u32 type; + __u32 length; + __u32 offset; + } buffer; +}; + +/* MODS_ESC_EVAL_ACPI_METHOD */ +struct MODS_EVAL_ACPI_METHOD { + /* IN */ + char method_name[ACPI_MAX_METHOD_LENGTH]; + __u32 argument_count; + union ACPI_ARGUMENT argument[ACPI_MAX_ARGUMENT_NUMBER]; + __u8 in_buffer[ACPI_MAX_BUFFER_LENGTH]; + + /* IN OUT */ + __u32 out_data_size; + + /* OUT */ + __u8 out_buffer[ACPI_MAX_BUFFER_LENGTH]; + __u32 out_status; +}; + +/* MODS_ESC_EVAL_DEV_ACPI_METHOD_2 */ +struct MODS_EVAL_DEV_ACPI_METHOD_2 { + /* IN OUT */ + struct MODS_EVAL_ACPI_METHOD method; + + /* IN */ + struct mods_pci_dev_2 device; +}; + +/* MODS_ESC_EVAL_DEV_ACPI_METHOD */ +struct MODS_EVAL_DEV_ACPI_METHOD { + /* IN OUT */ + struct MODS_EVAL_ACPI_METHOD method; + + /* IN */ + struct mods_pci_dev device; +}; + +/* MODS_ESC_ACPI_GET_DDC_2 */ +struct MODS_ACPI_GET_DDC_2 { + /* OUT */ + __u32 out_data_size; + __u8 out_buffer[ACPI_MAX_BUFFER_LENGTH]; + + /* IN */ + struct mods_pci_dev_2 device; +}; + +/* MODS_ESC_ACPI_GET_DDC */ +struct MODS_ACPI_GET_DDC { + /* OUT */ + __u32 out_data_size; + __u8 out_buffer[ACPI_MAX_BUFFER_LENGTH]; + + /* IN */ + struct mods_pci_dev device; +}; + +/* MODS_ESC_GET_VERSION */ +struct MODS_GET_VERSION { + /* OUT */ + __u64 version; +}; + +/* MODS_ESC_SET_PARA */ +struct MODS_SET_PARA { + /* IN */ + __u64 Highmem4g; + __u64 debug; +}; + +/* MODS_ESC_SET_MEMORY_TYPE */ +struct MODS_MEMORY_TYPE { + /* IN */ + __u64 physical_address; + __u64 size; + __u32 type; +}; + +#define MAX_CLOCK_HANDLE_NAME 64 + +/* MODS_ESC_GET_CLOCK_HANDLE */ +struct MODS_GET_CLOCK_HANDLE { + /* OUT */ + __u32 clock_handle; + + /* IN */ + char device_name[MAX_CLOCK_HANDLE_NAME]; + char controller_name[MAX_CLOCK_HANDLE_NAME]; +}; + +/* MODS_ESC_SET_CLOCK_RATE, MODS_ESC_GET_CLOCK_RATE, */ +/* MODS_ESC_GET_CLOCK_MAX_RATE, MODS_ESC_SET_CLOCK_MAX_RATE */ +struct MODS_CLOCK_RATE { + /* IN/OUT */ + __u64 clock_rate_hz; + + /* IN */ + __u32 clock_handle; +}; + +/* MODS_ESC_SET_CLOCK_PARENT, MODS_ESC_GET_CLOCK_PARENT */ +struct MODS_CLOCK_PARENT { + /* IN */ + __u32 clock_handle; + + /* IN/OUT */ + __u32 clock_parent_handle; +}; + +/* MODS_ESC_ENABLE_CLOCK, MODS_ESC_DISABLE_CLOCK, */ +/* MODS_ESC_CLOCK_RESET_ASSERT, MODS_ESC_CLOCK_RESET_DEASSERT */ +struct MODS_CLOCK_HANDLE { + /* IN */ + __u32 clock_handle; +}; + +/* MODS_ESC_IS_CLOCK_ENABLED */ +struct MODS_CLOCK_ENABLED { + /* IN */ + __u32 clock_handle; + + /* OUT */ + __u32 enable_count; +}; + +#if defined(CONFIG_PPC64) || defined(PPC64LE) +#define MAX_CPU_MASKS 64 /* 32 masks of 32bits = 2048 CPUs max */ +#else +#define MAX_CPU_MASKS 32 /* 32 masks of 32bits = 1024 CPUs max */ +#endif +/* MODS_ESC_DEVICE_NUMA_INFO_2 */ +struct MODS_DEVICE_NUMA_INFO_2 { + /* IN */ + struct mods_pci_dev_2 pci_device; + + /* OUT */ + __s32 node; + __u32 node_count; + __u32 node_cpu_mask[MAX_CPU_MASKS]; + __u32 cpu_count; +}; + +/* MODS_ESC_DEVICE_NUMA_INFO */ +struct MODS_DEVICE_NUMA_INFO { + /* IN */ + struct mods_pci_dev pci_device; + + /* OUT */ + __s32 node; + __u32 node_count; + __u32 node_cpu_mask[MAX_CPU_MASKS]; + __u32 cpu_count; +}; + +/* The ids match MODS ids */ +#define MODS_MEMORY_CACHED 5 +#define MODS_MEMORY_UNCACHED 1 +#define MODS_MEMORY_WRITECOMBINE 2 + +struct MODS_TEGRA_DC_WINDOW { + __s32 index; + __u32 flags; + __u32 x; + __u32 y; + __u32 w; + __u32 h; + __u32 out_x; + __u32 out_y; + __u32 out_w; + __u32 out_h; + __u32 pixformat; /* NVDC pix format */ + + __u32 bandwidth; +}; +#define MODS_TEGRA_DC_WINDOW_FLAG_ENABLED (1 << 0) +#define MODS_TEGRA_DC_WINDOW_FLAG_TILED (1 << 1) +#define MODS_TEGRA_DC_WINDOW_FLAG_SCAN_COL (1 << 2) +#define MODS_TEGRA_DC_MAX_WINDOWS (6) + +/* MODS_ESC_TEGRA_DC_CONFIG_POSSIBLE */ +struct MODS_TEGRA_DC_CONFIG_POSSIBLE { + /* IN/OUT */ + struct MODS_TEGRA_DC_WINDOW windows[MODS_TEGRA_DC_MAX_WINDOWS]; + + /* IN */ + __u8 head; + __u8 win_num; + + /* OUT */ + __u8 possible; +}; + + +#define MODS_TEGRA_DC_SETUP_SD_LUT_SIZE 9 +#define MODS_TEGRA_DC_SETUP_BLTF_SIZE 16 +/* MODS_ESC_TEGRA_DC_SETUP_SD */ +struct MODS_TEGRA_DC_SETUP_SD { + /* IN */ + __u8 head; + __u8 enable; + + __u8 use_vid_luma; + __u8 csc_r; + __u8 csc_g; + __u8 csc_b; + __u8 aggressiveness; + __u8 bin_width_log2; + + __u32 lut[MODS_TEGRA_DC_SETUP_SD_LUT_SIZE]; + __u32 bltf[MODS_TEGRA_DC_SETUP_BLTF_SIZE]; + + __u32 klimit; + __u32 soft_clipping_threshold; + __u32 smooth_k_inc; + __u8 k_init_bias; + + + __u32 win_x; + __u32 win_y; + __u32 win_w; + __u32 win_h; +}; + +/* MODS_ESC_DMABUF_GET_PHYSICAL_ADDRESS */ +struct MODS_DMABUF_GET_PHYSICAL_ADDRESS { + /* IN */ + __s32 buf_fd; + __u32 padding; + __u64 offset; + + /* OUT */ + __u64 physical_address; + __u64 segment_size; +}; + +#define MODS_ADSP_APP_NAME_SIZE 64 +#define MODS_ADSP_APP_MAX_PARAM 128 +struct MODS_ADSP_RUN_APP_INFO { + char app_name[MODS_ADSP_APP_NAME_SIZE]; + char app_file_name[MODS_ADSP_APP_NAME_SIZE]; + __u32 argc; + __u32 argv[MODS_ADSP_APP_MAX_PARAM]; + __u32 timeout; +}; + +/* MODS_ESC_GET_SCREEN_INFO */ +struct MODS_SCREEN_INFO { + /* OUT */ + __u8 orig_video_mode; + __u8 orig_video_is_vga; + __u16 lfb_width; + __u16 lfb_height; + __u16 lfb_depth; + __u32 lfb_base; + __u32 lfb_size; + __u16 lfb_linelength; +}; + +enum MODS_DMA_TRANSACTION_TYPE { + MODS_DMA_MEMCPY, + MODS_DMA_XOR, + MODS_DMA_PQ, + MODS_DMA_XOR_VAL, + MODS_DMA_PQ_VAL, + MODS_DMA_MEMSET, + MODS_DMA_MEMSET_SG, + MODS_DMA_INTERRUPT, + MODS_DMA_SG, + MODS_DMA_PRIVATE, + MODS_DMA_ASYNC_TX, + MODS_DMA_SLAVE, + MODS_DMA_CYCLIC, + MODS_DMA_INTERLEAVE, +/* last transaction type for creation of the capabilities mask */ + MODS_DMA_TX_TYPE_END +}; + +struct MODS_DMA_HANDLE { + /* IN */ + __u32 dma_type; /* Indicate the DMA Type*/ + /* OUT */ + __u32 dma_id; /* Inditify for the DMA */ +}; + +enum MODS_DMA_TRANSFER_DIRECTION { + MODS_DMA_MEM_TO_MEM, + MODS_DMA_MEM_TO_DEV, + MODS_DMA_DEV_TO_MEM, + MODS_DMA_DEV_TO_DEV, + MODS_DMA_TRANS_NONE +}; + +enum MODS_DMA_BUSWIDTH { + MODS_DMA_BUSWIDTH_UNDEFINED = 0, + MODS_DMA_BUSWIDTH_1_BYTE = 1, + MODS_DMA_BUSWIDTH_2_BYTES = 2, + MODS_DMA_BUSWIDTH_4_BYTES = 4, + MODS_DMA_BUSWIDTH_8_BYTES = 8 +}; + +struct MODS_DMA_CHANNEL_CONFIG { + __u64 src_addr; + __u64 dst_addr; + struct MODS_DMA_HANDLE handle; + __u32 direction; + __u32 src_addr_width; + __u32 dst_addr_width; + __u32 src_maxburst; + __u32 dst_maxburst; + __u32 slave_id; + __u32 device_fc; +}; + +/* Node: Only support SINGLE MODS so far*/ +enum MODS_DMA_TX_MODE { + MODS_DMA_SINGLE = 0, + MODS_DMA_TX_CYCLIC, + MODS_DMA_INTERLEAVED /* Common to Slave as well as M2M clients. */ +}; + +typedef __s32 mods_dma_cookie_t; + +struct MODS_DMA_TX_DESC { + /* IN */ + __u64 phys; + __u64 phys_2; /* only valid for MEMCPY */ + struct MODS_DMA_HANDLE handle; + __u32 mode; + __u32 data_dir; + __u32 length; + __u32 flags; + /* OUT */ + mods_dma_cookie_t cookie; +}; + +enum MODS_DMA_WAIT_TYPE { + MODS_DMA_SYNC_WAIT, /* wait until finished */ + MODS_DMA_ASYNC_WAIT /* just check tx status */ +}; + +struct MODS_DMA_WAIT_DESC { + struct MODS_DMA_HANDLE handle; + mods_dma_cookie_t cookie; + __u32 type; + /* OUT */ + __u32 tx_complete; +}; + +#define MAX_NET_DEVICE_NAME_LENGTH 16 +struct MODS_NET_DEVICE_NAME { + /* in */ + char device_name[MAX_NET_DEVICE_NAME_LENGTH]; +}; +struct MODS_DMA_COHERENT_MEM_HANDLE { + __u32 num_bytes; + __u32 attrib; + __u64 memory_handle_phys; + __u64 memory_handle_virt; +}; + +/* MODS_ESC_DMA_COPY_TO_USER */ +struct MODS_DMA_COPY_TO_USER { + __u32 num_bytes; + __u32 attrib; + __u64 memory_handle_src; + __u64 memory_handle_dst; +}; + +struct MODS_TEGRA_PROD_SET_TUPLE { + /* IN */ + __u64 prod_dev_handle; + __u64 ctrl_dev_handle; + char prod_name[MAX_DT_SIZE]; + __u32 index; + __u32 offset; + __u32 mask; +}; + +struct MODS_TEGRA_PROD_IS_SUPPORTED { + /* IN */ + __u64 prod_dev_handle; + char prod_name[MAX_DT_SIZE]; + /* OUT */ + __u32 is_supported; +}; + +struct MODS_TEGRA_PROD_ITERATOR { + /* IN */ + __u64 device_handle; + char name[MAX_DT_SIZE]; + char next_name[MAX_DT_SIZE]; + __u32 index; + __u32 is_leaf; + /* OUT */ + __u64 next_device_handle; +}; + +/* MODS_ESC_GET_ATS_ADDRESS_RANGE */ +struct MODS_GET_ATS_ADDRESS_RANGE { + /* IN */ + struct mods_pci_dev_2 pci_device; + __s32 npu_index; + __u8 reserved[4]; /* Alignment */ + + /* OUT */ + struct mods_pci_dev_2 npu_device; + __u64 phys_addr; + __u64 guest_addr; + __u64 aperture_size; + __s32 numa_memory_node; +}; + +#pragma pack(pop) + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ** */ +/* ** ESCAPE CALLS */ +/* ** */ +/* ************************************************************************* */ +/* ************************************************************************* */ +#define MODS_IOC_MAGIC 'x' +#define MODS_ESC_ALLOC_PAGES \ + _IOWR(MODS_IOC_MAGIC, 0, struct MODS_ALLOC_PAGES) +#define MODS_ESC_FREE_PAGES \ + _IOWR(MODS_IOC_MAGIC, 1, struct MODS_FREE_PAGES) +#define MODS_ESC_GET_PHYSICAL_ADDRESS \ + _IOWR(MODS_IOC_MAGIC, 2, struct MODS_GET_PHYSICAL_ADDRESS) +#define MODS_ESC_VIRTUAL_TO_PHYSICAL \ + _IOWR(MODS_IOC_MAGIC, 3, struct MODS_VIRTUAL_TO_PHYSICAL) +#define MODS_ESC_PHYSICAL_TO_VIRTUAL \ + _IOWR(MODS_IOC_MAGIC, 4, struct MODS_PHYSICAL_TO_VIRTUAL) +#define MODS_ESC_FIND_PCI_DEVICE \ + _IOWR(MODS_IOC_MAGIC, 5, struct MODS_FIND_PCI_DEVICE) +#define MODS_ESC_FIND_PCI_CLASS_CODE \ + _IOWR(MODS_IOC_MAGIC, 6, struct MODS_FIND_PCI_CLASS_CODE) +#define MODS_ESC_PCI_READ \ + _IOWR(MODS_IOC_MAGIC, 7, struct MODS_PCI_READ) +#define MODS_ESC_PCI_WRITE \ + _IOWR(MODS_IOC_MAGIC, 8, struct MODS_PCI_WRITE) +#define MODS_ESC_PIO_READ \ + _IOWR(MODS_IOC_MAGIC, 9, struct MODS_PIO_READ) +#define MODS_ESC_PIO_WRITE \ + _IOWR(MODS_IOC_MAGIC, 10, struct MODS_PIO_WRITE) +#define MODS_ESC_IRQ_REGISTER \ + _IOWR(MODS_IOC_MAGIC, 11, struct MODS_IRQ) +#define MODS_ESC_IRQ_FREE \ + _IOWR(MODS_IOC_MAGIC, 12, struct MODS_IRQ) +#define MODS_ESC_IRQ_INQUIRY \ + _IOWR(MODS_IOC_MAGIC, 13, struct MODS_IRQ) +#define MODS_ESC_EVAL_ACPI_METHOD \ + _IOWR_BAD(MODS_IOC_MAGIC, 16, struct MODS_EVAL_ACPI_METHOD) +#define MODS_ESC_GET_API_VERSION \ + _IOWR(MODS_IOC_MAGIC, 17, struct MODS_GET_VERSION) +#define MODS_ESC_GET_KERNEL_VERSION \ + _IOWR(MODS_IOC_MAGIC, 18, struct MODS_GET_VERSION) +#define MODS_ESC_SET_DRIVER_PARA \ + _IOWR(MODS_IOC_MAGIC, 19, struct MODS_SET_PARA) +#define MODS_ESC_MSI_REGISTER \ + _IOWR(MODS_IOC_MAGIC, 20, struct MODS_IRQ) +#define MODS_ESC_REARM_MSI \ + _IOWR(MODS_IOC_MAGIC, 21, struct MODS_IRQ) +#define MODS_ESC_SET_MEMORY_TYPE \ + _IOW(MODS_IOC_MAGIC, 22, struct MODS_MEMORY_TYPE) +#define MODS_ESC_PCI_BUS_ADD_DEVICES \ + _IOW(MODS_IOC_MAGIC, 23, struct MODS_PCI_BUS_ADD_DEVICES) +#define MODS_ESC_REGISTER_IRQ \ + _IOW(MODS_IOC_MAGIC, 24, struct MODS_REGISTER_IRQ) +#define MODS_ESC_UNREGISTER_IRQ \ + _IOW(MODS_IOC_MAGIC, 25, struct MODS_REGISTER_IRQ) +#define MODS_ESC_QUERY_IRQ \ + _IOR(MODS_IOC_MAGIC, 26, struct MODS_QUERY_IRQ) +#define MODS_ESC_EVAL_DEV_ACPI_METHOD \ + _IOWR_BAD(MODS_IOC_MAGIC, 27, struct MODS_EVAL_DEV_ACPI_METHOD) +#define MODS_ESC_ACPI_GET_DDC \ + _IOWR(MODS_IOC_MAGIC, 28, struct MODS_ACPI_GET_DDC) +#define MODS_ESC_GET_CLOCK_HANDLE \ + _IOWR(MODS_IOC_MAGIC, 29, struct MODS_GET_CLOCK_HANDLE) +#define MODS_ESC_SET_CLOCK_RATE \ + _IOW(MODS_IOC_MAGIC, 30, struct MODS_CLOCK_RATE) +#define MODS_ESC_GET_CLOCK_RATE \ + _IOWR(MODS_IOC_MAGIC, 31, struct MODS_CLOCK_RATE) +#define MODS_ESC_SET_CLOCK_PARENT \ + _IOW(MODS_IOC_MAGIC, 32, struct MODS_CLOCK_PARENT) +#define MODS_ESC_GET_CLOCK_PARENT \ + _IOWR(MODS_IOC_MAGIC, 33, struct MODS_CLOCK_PARENT) +#define MODS_ESC_ENABLE_CLOCK \ + _IOW(MODS_IOC_MAGIC, 34, struct MODS_CLOCK_HANDLE) +#define MODS_ESC_DISABLE_CLOCK \ + _IOW(MODS_IOC_MAGIC, 35, struct MODS_CLOCK_HANDLE) +#define MODS_ESC_IS_CLOCK_ENABLED \ + _IOWR(MODS_IOC_MAGIC, 36, struct MODS_CLOCK_ENABLED) +#define MODS_ESC_CLOCK_RESET_ASSERT \ + _IOW(MODS_IOC_MAGIC, 37, struct MODS_CLOCK_HANDLE) +#define MODS_ESC_CLOCK_RESET_DEASSERT \ + _IOW(MODS_IOC_MAGIC, 38, struct MODS_CLOCK_HANDLE) +#define MODS_ESC_SET_IRQ_MASK \ + _IOW(MODS_IOC_MAGIC, 39, struct MODS_SET_IRQ_MASK) +#define MODS_ESC_MEMORY_BARRIER \ + _IO(MODS_IOC_MAGIC, 40) +#define MODS_ESC_IRQ_HANDLED \ + _IOW(MODS_IOC_MAGIC, 41, struct MODS_REGISTER_IRQ) +#define MODS_ESC_FLUSH_CPU_CACHE_RANGE \ + _IOW(MODS_IOC_MAGIC, 42, struct MODS_FLUSH_CPU_CACHE_RANGE) +#define MODS_ESC_GET_CLOCK_MAX_RATE \ + _IOWR(MODS_IOC_MAGIC, 43, struct MODS_CLOCK_RATE) +#define MODS_ESC_SET_CLOCK_MAX_RATE \ + _IOW(MODS_IOC_MAGIC, 44, struct MODS_CLOCK_RATE) +#define MODS_ESC_DEVICE_ALLOC_PAGES \ + _IOWR(MODS_IOC_MAGIC, 45, struct MODS_DEVICE_ALLOC_PAGES) +#define MODS_ESC_DEVICE_NUMA_INFO \ + _IOWR(MODS_IOC_MAGIC, 46, struct MODS_DEVICE_NUMA_INFO) +#define MODS_ESC_TEGRA_DC_CONFIG_POSSIBLE \ + _IOWR(MODS_IOC_MAGIC, 47, \ + struct MODS_TEGRA_DC_CONFIG_POSSIBLE) +#define MODS_ESC_TEGRA_DC_SETUP_SD \ + _IOW(MODS_IOC_MAGIC, 48, struct MODS_TEGRA_DC_SETUP_SD) +#define MODS_ESC_DMABUF_GET_PHYSICAL_ADDRESS \ + _IOWR(MODS_IOC_MAGIC, 49, \ + struct MODS_DMABUF_GET_PHYSICAL_ADDRESS) +#define MODS_ESC_ADSP_LOAD \ + _IO(MODS_IOC_MAGIC, 50) +#define MODS_ESC_ADSP_START \ + _IO(MODS_IOC_MAGIC, 51) +#define MODS_ESC_ADSP_STOP \ + _IO(MODS_IOC_MAGIC, 52) +#define MODS_ESC_ADSP_RUN_APP \ + _IOW(MODS_IOC_MAGIC, 53, struct MODS_ADSP_RUN_APP_INFO) +#define MODS_ESC_PCI_GET_BAR_INFO \ + _IOWR(MODS_IOC_MAGIC, 54, struct MODS_PCI_GET_BAR_INFO) +#define MODS_ESC_PCI_GET_IRQ \ + _IOWR(MODS_IOC_MAGIC, 55, struct MODS_PCI_GET_IRQ) +#define MODS_ESC_GET_MAPPED_PHYSICAL_ADDRESS \ + _IOWR(MODS_IOC_MAGIC, 56, \ + struct MODS_GET_PHYSICAL_ADDRESS) +#define MODS_ESC_DEVICE_ALLOC_PAGES_2 \ + _IOWR(MODS_IOC_MAGIC, 57, struct MODS_DEVICE_ALLOC_PAGES_2) +#define MODS_ESC_FIND_PCI_DEVICE_2 \ + _IOWR(MODS_IOC_MAGIC, 58, struct MODS_FIND_PCI_DEVICE_2) +#define MODS_ESC_FIND_PCI_CLASS_CODE_2 \ + _IOWR(MODS_IOC_MAGIC, 59, \ + struct MODS_FIND_PCI_CLASS_CODE_2) +#define MODS_ESC_PCI_GET_BAR_INFO_2 \ + _IOWR(MODS_IOC_MAGIC, 60, struct MODS_PCI_GET_BAR_INFO_2) +#define MODS_ESC_PCI_GET_IRQ_2 \ + _IOWR(MODS_IOC_MAGIC, 61, struct MODS_PCI_GET_IRQ_2) +#define MODS_ESC_PCI_READ_2 \ + _IOWR(MODS_IOC_MAGIC, 62, struct MODS_PCI_READ_2) +#define MODS_ESC_PCI_WRITE_2 \ + _IOW(MODS_IOC_MAGIC, 63, struct MODS_PCI_WRITE_2) +#define MODS_ESC_REGISTER_IRQ_2 \ + _IOW(MODS_IOC_MAGIC, 64, struct MODS_REGISTER_IRQ_2) +#define MODS_ESC_UNREGISTER_IRQ_2 \ + _IOW(MODS_IOC_MAGIC, 65, struct MODS_REGISTER_IRQ_2) +#define MODS_ESC_IRQ_HANDLED_2 \ + _IOW(MODS_IOC_MAGIC, 66, struct MODS_REGISTER_IRQ_2) +#define MODS_ESC_QUERY_IRQ_2 \ + _IOR(MODS_IOC_MAGIC, 67, struct MODS_QUERY_IRQ_2) +#define MODS_ESC_SET_IRQ_MASK_2 \ + _IOW(MODS_IOC_MAGIC, 68, struct MODS_SET_IRQ_MASK_2) +#define MODS_ESC_EVAL_DEV_ACPI_METHOD_2 \ + _IOWR_BAD(MODS_IOC_MAGIC, 69,\ + struct MODS_EVAL_DEV_ACPI_METHOD_2) +#define MODS_ESC_DEVICE_NUMA_INFO_2 \ + _IOWR(MODS_IOC_MAGIC, 70, struct MODS_DEVICE_NUMA_INFO_2) +#define MODS_ESC_ACPI_GET_DDC_2 \ + _IOWR(MODS_IOC_MAGIC, 71, struct MODS_ACPI_GET_DDC_2) +#define MODS_ESC_GET_SCREEN_INFO \ + _IOR(MODS_IOC_MAGIC, 72, struct MODS_SCREEN_INFO) +#define MODS_ESC_PCI_HOT_RESET \ + _IOW(MODS_IOC_MAGIC, 73, struct MODS_PCI_HOT_RESET) +#define MODS_ESC_SET_PPC_TCE_BYPASS \ + _IOWR(MODS_IOC_MAGIC, 74, struct MODS_SET_PPC_TCE_BYPASS) +#define MODS_ESC_DMA_MAP_MEMORY \ + _IOW(MODS_IOC_MAGIC, 75, struct MODS_DMA_MAP_MEMORY) +#define MODS_ESC_DMA_UNMAP_MEMORY \ + _IOW(MODS_IOC_MAGIC, 76, struct MODS_DMA_MAP_MEMORY) +#define MODS_ESC_GET_MAPPED_PHYSICAL_ADDRESS_2 \ + _IOWR(MODS_IOC_MAGIC, 77, \ + struct MODS_GET_PHYSICAL_ADDRESS_2) +#define MODS_ESC_PCI_MAP_RESOURCE \ + _IOWR(MODS_IOC_MAGIC, 78, struct MODS_PCI_MAP_RESOURCE) +#define MODS_ESC_PCI_UNMAP_RESOURCE \ + _IOW(MODS_IOC_MAGIC, 79, struct MODS_PCI_UNMAP_RESOURCE) +#define MODS_ESC_DMA_REQUEST_HANDLE \ + _IOR(MODS_IOC_MAGIC, 80, struct MODS_DMA_HANDLE) +#define MODS_ESC_DMA_RELEASE_HANDLE \ + _IOW(MODS_IOC_MAGIC, 81, struct MODS_DMA_HANDLE) +#define MODS_ESC_DMA_SET_CONFIG \ + _IOW(MODS_IOC_MAGIC, 82, struct MODS_DMA_CHANNEL_CONFIG) +#define MODS_ESC_DMA_TX_SUBMIT \ + _IOW(MODS_IOC_MAGIC, 83, struct MODS_DMA_TX_DESC) +#define MODS_ESC_DMA_TX_WAIT \ + _IOWR(MODS_IOC_MAGIC, 84, struct MODS_DMA_WAIT_DESC) +#define MODS_ESC_DMA_ISSUE_PENDING \ + _IOW(MODS_IOC_MAGIC, 85, struct MODS_DMA_HANDLE) +#define MODS_ESC_SET_IRQ_MULTIMASK \ + _IOW(MODS_IOC_MAGIC, 86, struct MODS_SET_IRQ_MULTIMASK) +#define MODS_ESC_NET_FORCE_LINK \ + _IOW(MODS_IOC_MAGIC, 87, struct MODS_NET_DEVICE_NAME) +#define MODS_ESC_REGISTER_IRQ_3 \ + _IOW(MODS_IOC_MAGIC, 88, struct MODS_REGISTER_IRQ_3) +#define MODS_ESC_DMA_ALLOC_COHERENT \ + _IOWR(MODS_IOC_MAGIC, 89, \ + struct MODS_DMA_COHERENT_MEM_HANDLE) +#define MODS_ESC_DMA_FREE_COHERENT \ + _IOWR(MODS_IOC_MAGIC, 90, \ + struct MODS_DMA_COHERENT_MEM_HANDLE) +#define MODS_ESC_DMA_COPY_TO_USER \ + _IOWR(MODS_IOC_MAGIC, 91, \ + struct MODS_DMA_COPY_TO_USER) +#define MODS_ESC_MAP_INTERRUPT \ + _IOWR(MODS_IOC_MAGIC, 92, \ + struct MODS_DT_INFO) +#define MODS_ESC_LOCK_CONSOLE \ + _IO(MODS_IOC_MAGIC, 93) +#define MODS_ESC_UNLOCK_CONSOLE \ + _IO(MODS_IOC_MAGIC, 94) +#define MODS_ESC_TEGRA_PROD_IS_SUPPORTED \ + _IOWR(MODS_IOC_MAGIC, 95, \ + struct MODS_TEGRA_PROD_IS_SUPPORTED) +#define MODS_ESC_TEGRA_PROD_SET_PROD_ALL \ + _IOW(MODS_IOC_MAGIC, 96, \ + struct MODS_TEGRA_PROD_SET_TUPLE) +#define MODS_ESC_TEGRA_PROD_SET_PROD_BOOT \ + _IOW(MODS_IOC_MAGIC, 97, \ + struct MODS_TEGRA_PROD_SET_TUPLE) +#define MODS_ESC_TEGRA_PROD_SET_PROD_BY_NAME \ + _IOW(MODS_IOC_MAGIC, 98, \ + struct MODS_TEGRA_PROD_SET_TUPLE) +#define MODS_ESC_TEGRA_PROD_SET_PROD_EXACT \ + _IOW(MODS_IOC_MAGIC, 99, \ + struct MODS_TEGRA_PROD_SET_TUPLE) +#define MODS_ESC_TEGRA_PROD_ITERATE_DT \ + _IOWR(MODS_IOC_MAGIC, 100, \ + struct MODS_TEGRA_PROD_ITERATOR) +#define MODS_ESC_GET_ATS_ADDRESS_RANGE \ + _IOWR(MODS_IOC_MAGIC, 101, \ + struct MODS_GET_ATS_ADDRESS_RANGE) + +#endif /* _MODS_H_ */ diff --git a/drivers/misc/mods/mods_acpi.c b/drivers/misc/mods/mods_acpi.c new file mode 100644 index 00000000..90974ec9 --- /dev/null +++ b/drivers/misc/mods/mods_acpi.c @@ -0,0 +1,452 @@ +/* + * mods_acpi.c - This file is part of NVIDIA MODS kernel driver. + * + * Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA MODS kernel driver is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * NVIDIA MODS kernel driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVIDIA MODS kernel driver. + * If not, see . + */ + +#include "mods_internal.h" + +#include +#include +#include +#include + +static acpi_status mods_acpi_find_acpi_handler(acpi_handle, + u32, + void *, + void **); + +/********************* + * PRIVATE FUNCTIONS * + *********************/ + +/* store handle if found. */ +static void mods_acpi_handle_init(char *method_name, acpi_handle *handler) +{ + MODS_ACPI_WALK_NAMESPACE(ACPI_TYPE_ANY, + ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + mods_acpi_find_acpi_handler, + method_name, + handler); + + if (!(*handler)) { + mods_debug_printk(DEBUG_ACPI, "ACPI method %s not found\n", + method_name); + return; + } +} + +static acpi_status mods_acpi_find_acpi_handler( + acpi_handle handle, + u32 nest_level, + void *dummy1, + void **dummy2 +) +{ + acpi_handle acpi_method_handler_temp; + + if (!acpi_get_handle(handle, dummy1, &acpi_method_handler_temp)) + *dummy2 = acpi_method_handler_temp; + + return OK; +} + +static int mods_extract_acpi_object( + char *method, + union acpi_object *obj, + u8 **buf, + u8 *buf_end +) +{ + int ret = OK; + + switch (obj->type) { + + case ACPI_TYPE_BUFFER: + if (obj->buffer.length == 0) { + mods_error_printk( + "empty ACPI output buffer from ACPI method %s\n", + method); + ret = -EINVAL; + } else if (obj->buffer.length <= buf_end-*buf) { + u32 size = obj->buffer.length; + + memcpy(*buf, obj->buffer.pointer, size); + *buf += size; + } else { + mods_error_printk( + "output buffer too small for ACPI method %s\n", + method); + ret = -EINVAL; + } + break; + + case ACPI_TYPE_INTEGER: + if (buf_end - *buf >= 4) { + if (obj->integer.value > 0xFFFFFFFFU) { + mods_error_printk( + "integer value from ACPI method %s out of range\n", + method); + ret = -EINVAL; + } else { + memcpy(*buf, &obj->integer.value, 4); + *buf += 4; + } + } else { + mods_error_printk( + "output buffer too small for ACPI method %s\n", + method); + ret = -EINVAL; + } + break; + + case ACPI_TYPE_PACKAGE: + if (obj->package.count == 0) { + mods_error_printk( + "empty ACPI output package from ACPI method %s\n", + method); + ret = -EINVAL; + } else { + union acpi_object *elements = obj->package.elements; + u32 size = 0; + u32 i; + + for (i = 0; i < obj->package.count; i++) { + u8 *old_buf = *buf; + + ret = mods_extract_acpi_object(method, + &elements[i], + buf, + buf_end); + if (ret == OK) { + u32 new_size = *buf - old_buf; + + if (size == 0) { + size = new_size; + } else if (size != new_size) { + mods_error_printk( + "ambiguous package element size from ACPI method %s\n", + method); + ret = -EINVAL; + } + } else + break; + } + } + break; + + default: + mods_error_printk( + "unsupported ACPI output type 0x%02x from method %s\n", + (unsigned int)obj->type, method); + ret = -EINVAL; + break; + + } + return ret; +} + +static int mods_eval_acpi_method(struct file *pfile, + struct MODS_EVAL_ACPI_METHOD *p, + struct mods_pci_dev_2 *pdevice) +{ + int ret = OK; + int i; + acpi_status status; + struct acpi_object_list input; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *acpi_method = NULL; + union acpi_object acpi_params[ACPI_MAX_ARGUMENT_NUMBER]; + acpi_handle acpi_method_handler = NULL; + + if (pdevice) { + unsigned int devfn; + struct pci_dev *dev; + + mods_debug_printk(DEBUG_ACPI, + "ACPI %s for device %04x:%x:%02x.%x\n", + p->method_name, + (unsigned int)pdevice->domain, + (unsigned int)pdevice->bus, + (unsigned int)pdevice->device, + (unsigned int)pdevice->function); + + devfn = PCI_DEVFN(pdevice->device, pdevice->function); + dev = MODS_PCI_GET_SLOT(pdevice->domain, pdevice->bus, devfn); + if (!dev) { + mods_error_printk("ACPI: PCI device not found\n"); + return -EINVAL; + } + acpi_method_handler = MODS_ACPI_HANDLE(&dev->dev); + } else { + mods_debug_printk(DEBUG_ACPI, "ACPI %s\n", p->method_name); + mods_acpi_handle_init(p->method_name, &acpi_method_handler); + } + + if (!acpi_method_handler) { + mods_debug_printk(DEBUG_ACPI, "ACPI: handle for %s not found\n", + p->method_name); + return -EINVAL; + } + + if (p->argument_count >= ACPI_MAX_ARGUMENT_NUMBER) { + mods_error_printk("invalid argument count for ACPI call\n"); + return -EINVAL; + } + + for (i = 0; i < p->argument_count; i++) { + switch (p->argument[i].type) { + case ACPI_MODS_TYPE_INTEGER: { + acpi_params[i].integer.type = ACPI_TYPE_INTEGER; + acpi_params[i].integer.value + = p->argument[i].integer.value; + break; + } + case ACPI_MODS_TYPE_BUFFER: { + acpi_params[i].buffer.type = ACPI_TYPE_BUFFER; + acpi_params[i].buffer.length + = p->argument[i].buffer.length; + acpi_params[i].buffer.pointer + = p->in_buffer + p->argument[i].buffer.offset; + break; + } + default: { + mods_error_printk("unsupported ACPI argument type\n"); + return -EINVAL; + } + } + } + + input.count = p->argument_count; + input.pointer = acpi_params; + + status = acpi_evaluate_object(acpi_method_handler, + pdevice ? p->method_name : NULL, + &input, + &output); + + if (ACPI_FAILURE(status)) { + mods_error_printk("ACPI method %s failed\n", p->method_name); + return -EINVAL; + } + + acpi_method = output.pointer; + if (!acpi_method) { + mods_error_printk("missing output from ACPI method %s\n", + p->method_name); + ret = -EINVAL; + } else { + u8 *buf = p->out_buffer; + + ret = mods_extract_acpi_object(p->method_name, + acpi_method, + &buf, + buf+sizeof(p->out_buffer)); + p->out_data_size = (ret == OK) ? (buf - p->out_buffer) : 0; + } + + kfree(output.pointer); + return ret; +} + +static int mods_acpi_get_ddc(struct file *pfile, + struct MODS_ACPI_GET_DDC_2 *p, + struct mods_pci_dev_2 *pci_device) +{ + acpi_status status; + struct acpi_device *device = NULL; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *ddc; + union acpi_object ddc_arg0 = { ACPI_TYPE_INTEGER }; + struct acpi_object_list input = { 1, &ddc_arg0 }; + struct list_head *node, *next; + u32 i; + acpi_handle dev_handle = NULL; + acpi_handle lcd_dev_handle = NULL; + + mods_debug_printk(DEBUG_ACPI, + "ACPI _DDC (EDID) for device %04x:%x:%02x.%x\n", + (unsigned int)pci_device->domain, + (unsigned int)pci_device->bus, + (unsigned int)pci_device->device, + (unsigned int)pci_device->function); + + { + unsigned int devfn = PCI_DEVFN(pci_device->device, + pci_device->function); + struct pci_dev *dev = MODS_PCI_GET_SLOT(pci_device->domain, + pci_device->bus, devfn); + if (!dev) { + mods_error_printk("ACPI: PCI device not found\n"); + return -EINVAL; + } + dev_handle = MODS_ACPI_HANDLE(&dev->dev); + } + if (!dev_handle) { + mods_debug_printk(DEBUG_ACPI, + "ACPI: handle for _DDC not found\n"); + return -EINVAL; + } + status = acpi_bus_get_device(dev_handle, &device); + + if (ACPI_FAILURE(status) || !device) { + mods_error_printk("ACPI: device for _DDC not found\n"); + return -EINVAL; + } + + list_for_each_safe(node, next, &device->children) { +#ifdef MODS_ACPI_DEVID_64 + unsigned long long +#else + unsigned long +#endif + device_id = 0; + + struct acpi_device *dev = + list_entry(node, struct acpi_device, node); + + if (!dev) + continue; + + status = acpi_evaluate_integer(dev->handle, + "_ADR", + NULL, + &device_id); + if (ACPI_FAILURE(status)) + /* Couldnt query device_id for this device */ + continue; + + device_id = (device_id & 0xffff); + + if ((device_id == 0x0110) || /* Only for an LCD*/ + (device_id == 0x0118) || + (device_id == 0x0400)) { + + lcd_dev_handle = dev->handle; + mods_debug_printk(DEBUG_ACPI, + "ACPI: Found LCD 0x%x on device %04x:%x:%02x.%x\n", + (unsigned int)device_id, + (unsigned int)p->device.domain, + (unsigned int)p->device.bus, + (unsigned int)p->device.device, + (unsigned int)p->device.function); + break; + } + + } + + if (lcd_dev_handle == NULL) { + mods_error_printk( + "ACPI: LCD not found for device %04x:%x:%02x.%x\n", + (unsigned int)p->device.domain, + (unsigned int)p->device.bus, + (unsigned int)p->device.device, + (unsigned int)p->device.function); + return -EINVAL; + } + + /* + * As per ACPI Spec 3.0: + * ARG0 = 0x1 for 128 bytes EDID buffer + * ARG0 = 0x2 for 256 bytes EDID buffer + */ + for (i = 1; i <= 2; i++) { + ddc_arg0.integer.value = i; + status = acpi_evaluate_object(lcd_dev_handle, + "_DDC", + &input, + &output); + if (ACPI_SUCCESS(status)) + break; + } + + if (ACPI_FAILURE(status)) { + mods_error_printk("ACPI method _DDC (EDID) failed\n"); + return -EINVAL; + } + + ddc = output.pointer; + if (ddc && (ddc->type == ACPI_TYPE_BUFFER) + && (ddc->buffer.length > 0)) { + + if (ddc->buffer.length <= sizeof(p->out_buffer)) { + p->out_data_size = ddc->buffer.length; + memcpy(p->out_buffer, + ddc->buffer.pointer, + p->out_data_size); + } else { + mods_error_printk( + "output buffer too small for ACPI method _DDC (EDID)\n"); + kfree(output.pointer); + return -EINVAL; + } + } else { + mods_error_printk("unsupported ACPI output type\n"); + kfree(output.pointer); + return -EINVAL; + } + + kfree(output.pointer); + return OK; +} + +/************************* + * ESCAPE CALL FUNCTIONS * + *************************/ + +int esc_mods_eval_acpi_method(struct file *pfile, + struct MODS_EVAL_ACPI_METHOD *p) +{ + return mods_eval_acpi_method(pfile, p, 0); +} + +int esc_mods_eval_dev_acpi_method_2(struct file *pfile, + struct MODS_EVAL_DEV_ACPI_METHOD_2 *p) +{ + return mods_eval_acpi_method(pfile, &p->method, &p->device); +} + +int esc_mods_eval_dev_acpi_method(struct file *pfile, + struct MODS_EVAL_DEV_ACPI_METHOD *p) +{ + struct mods_pci_dev_2 device = {0}; + + device.domain = 0; + device.bus = p->device.bus; + device.device = p->device.device; + device.function = p->device.function; + return mods_eval_acpi_method(pfile, &p->method, &device); +} + +int esc_mods_acpi_get_ddc_2(struct file *pfile, + struct MODS_ACPI_GET_DDC_2 *p) +{ + return mods_acpi_get_ddc(pfile, p, &p->device); +} + +int esc_mods_acpi_get_ddc(struct file *pfile, struct MODS_ACPI_GET_DDC *p) +{ + struct MODS_ACPI_GET_DDC_2 *pp = (struct MODS_ACPI_GET_DDC_2 *) p; + struct mods_pci_dev_2 device = {0}; + + device.domain = 0; + device.bus = p->device.bus; + device.device = p->device.device; + device.function = p->device.function; + + return mods_acpi_get_ddc(pfile, pp, &device); +} diff --git a/drivers/misc/mods/mods_adsp.c b/drivers/misc/mods/mods_adsp.c new file mode 100644 index 00000000..244dcc05 --- /dev/null +++ b/drivers/misc/mods/mods_adsp.c @@ -0,0 +1,95 @@ +/* + * mods_adsp.c - This file is part of NVIDIA MODS kernel driver. + * + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA MODS kernel driver is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * NVIDIA MODS kernel driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVIDIA MODS kernel driver. + * If not, see . + */ + +#include +#include "mods_internal.h" +#include + +int esc_mods_adsp_load(struct file *pfile) +{ + return nvadsp_os_load(); +} + +int esc_mods_adsp_start(struct file *pfile) +{ + return nvadsp_os_start(); +} + +int esc_mods_adsp_stop(struct file *pfile) +{ + nvadsp_os_stop(); + return OK; +} + +int esc_mods_adsp_run_app(struct file *pfile, struct MODS_ADSP_RUN_APP_INFO *p) +{ + int rc = -1; + int max_retry = 3; + int rcount = 0; + nvadsp_app_handle_t handle; + nvadsp_app_info_t *p_app_info; + nvadsp_app_args_t app_args; + + handle = nvadsp_app_load(p->app_name, p->app_file_name); + if (!handle) { + mods_error_printk("load adsp app fail"); + return -1; + } + + if (p->argc > 0 && p->argc <= MODS_ADSP_APP_MAX_PARAM) { + app_args.argc = p->argc; + memcpy(app_args.argv, p->argv, p->argc * sizeof(__u32)); + p_app_info = nvadsp_app_init(handle, &app_args); + } else + p_app_info = nvadsp_app_init(handle, NULL); + + if (!p_app_info) { + mods_error_printk("init adsp app fail"); + nvadsp_app_unload(handle); + return -1; + } + + rc = nvadsp_app_start(p_app_info); + if (rc) { + mods_error_printk("start adsp app fail"); + goto failed; + } + + while (rcount++ < max_retry) { + rc = wait_for_nvadsp_app_complete_timeout(p_app_info, + msecs_to_jiffies(p->timeout)); + if (rc == -ERESTARTSYS) + continue; + else if (rc == 0) { + mods_error_printk("app timeout(%d)", p->timeout); + rc = -1; + } else if (rc < 0) { + mods_error_printk("run app failed, err=%d\n", rc); + rc = -1; + } else + rc = 0; + break; + } + +failed: + nvadsp_app_deinit(p_app_info); + nvadsp_app_unload(handle); + + return rc; +} diff --git a/drivers/misc/mods/mods_clock.c b/drivers/misc/mods/mods_clock.c new file mode 100644 index 00000000..09101719 --- /dev/null +++ b/drivers/misc/mods/mods_clock.c @@ -0,0 +1,621 @@ +/* + * mods_clock.c - This file is part of NVIDIA MODS kernel driver. + * + * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA MODS kernel driver is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * NVIDIA MODS kernel driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVIDIA MODS kernel driver. + * If not, see . + */ + +#include "mods_internal.h" +#include +#include +#if defined(CONFIG_TEGRA_CLK_FRAMEWORK) + #include +#elif defined(CONFIG_COMMON_CLK) && defined(CONFIG_OF_RESOLVE) && \ +defined(CONFIG_OF_DYNAMIC) + #define MODS_COMMON_CLK 1 +#endif +#if defined(MODS_COMMON_CLK) + #include + #include + #include + #include + #include + #define ARBITRARY_MAX_CLK_FREQ 3500000000 +#endif + +static struct list_head mods_clock_handles; +static spinlock_t mods_clock_lock; +static u32 last_handle; + +struct clock_entry { + struct clk *pclk; + u32 handle; + struct list_head list; +}; + +#if defined(MODS_COMMON_CLK) +static struct device_node *find_clocks_node(const char *name) +{ + const char *node_name = "mods-simple-bus"; + struct device_node *pp = NULL, *np = NULL; + + pp = of_find_node_by_name(NULL, node_name); + + if (!pp) { + mods_error_printk("'mods-simple-bus' node not found in device tree\n"); + return pp; + } + + np = of_get_child_by_name(pp, name); + return np; +} +#endif + +void mods_init_clock_api(void) +{ +#if defined(MODS_COMMON_CLK) + const char *okay_value = "okay"; + struct device_node *mods_np = 0; + struct property *pp = 0; + int size_value = 0; + + mods_np = find_clocks_node("mods-clocks"); + if (!mods_np) { + mods_error_printk("'mods-clocks' node not found in device tree\n"); + goto err; + } + + pp = of_find_property(mods_np, "status", NULL); + if (IS_ERR(pp)) { + mods_error_printk("'status' prop not found in 'mods-clocks' node."); + goto err; + } + + /* if status is 'okay', then skip updating property */ + if (of_device_is_available(mods_np)) + goto err; + + size_value = strlen(okay_value) + 1; + pp->value = kmalloc(size_value, GFP_KERNEL); + strncpy(pp->value, okay_value, size_value); + pp->length = size_value; + +err: + of_node_put(mods_np); +#endif + + spin_lock_init(&mods_clock_lock); + INIT_LIST_HEAD(&mods_clock_handles); + last_handle = 0; +} + +void mods_shutdown_clock_api(void) +{ + struct list_head *head = &mods_clock_handles; + struct list_head *iter; + struct list_head *tmp; + + spin_lock(&mods_clock_lock); + + list_for_each_safe(iter, tmp, head) { + struct clock_entry *entry + = list_entry(iter, struct clock_entry, list); + list_del(iter); + kfree(entry); + } + + spin_unlock(&mods_clock_lock); +} + +static u32 mods_get_clock_handle(struct clk *pclk) +{ + struct list_head *head = &mods_clock_handles; + struct list_head *iter; + struct clock_entry *entry = 0; + u32 handle = 0; + + spin_lock(&mods_clock_lock); + + list_for_each(iter, head) { + struct clock_entry *cur + = list_entry(iter, struct clock_entry, list); + if (cur->pclk == pclk) { + entry = cur; + handle = cur->handle; + break; + } + } + + if (!entry) { + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + if (!unlikely(!entry)) { + entry->pclk = pclk; + entry->handle = ++last_handle; + handle = entry->handle; + list_add(&entry->list, &mods_clock_handles); + } + } + + spin_unlock(&mods_clock_lock); + + return handle; +} + +static struct clk *mods_get_clock(u32 handle) +{ + struct list_head *head = &mods_clock_handles; + struct list_head *iter; + struct clk *pclk = 0; + + spin_lock(&mods_clock_lock); + + list_for_each(iter, head) { + struct clock_entry *entry + = list_entry(iter, struct clock_entry, list); + if (entry->handle == handle) { + pclk = entry->pclk; + break; + } + } + + spin_unlock(&mods_clock_lock); + + return pclk; +} + +int esc_mods_get_clock_handle(struct file *pfile, + struct MODS_GET_CLOCK_HANDLE *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + +#if defined(CONFIG_TEGRA_CLK_FRAMEWORK) + LOG_ENT(); + + p->device_name[sizeof(p->device_name)-1] = 0; + p->controller_name[sizeof(p->controller_name)-1] = 0; + pclk = clk_get_sys(p->device_name, p->controller_name); + + if (IS_ERR(pclk)) { + mods_error_printk("invalid clock specified: dev=%s, ctx=%s\n", + p->device_name, p->controller_name); + } else { + p->clock_handle = mods_get_clock_handle(pclk); + ret = OK; + } +#elif defined(MODS_COMMON_CLK) + struct device_node *mods_np = 0; + struct property *pp = 0; + + LOG_ENT(); + + mods_np = find_clocks_node("mods-clocks"); + if (!mods_np || !of_device_is_available(mods_np)) { + mods_error_printk("'mods-clocks' node not found in device tree\n"); + goto err; + } + pp = of_find_property(mods_np, "clock-names", NULL); + if (IS_ERR(pp)) { + mods_error_printk( + "No 'clock-names' prop in 'mods-clocks' node for dev %s\n", + p->controller_name); + goto err; + } + + pclk = of_clk_get_by_name(mods_np, p->controller_name); + + if (IS_ERR(pclk)) + mods_error_printk("clk (%s) not found\n", p->controller_name); + else { + p->clock_handle = mods_get_clock_handle(pclk); + ret = OK; + } +err: + of_node_put(mods_np); +#endif + LOG_EXT(); + return ret; +} + +int esc_mods_set_clock_rate(struct file *pfile, struct MODS_CLOCK_RATE *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else { + ret = clk_set_rate(pclk, p->clock_rate_hz); + if (ret) { + mods_error_printk( + "unable to set rate %lluHz on clock 0x%x\n", + p->clock_rate_hz, p->clock_handle); + } else { + mods_debug_printk(DEBUG_CLOCK, + "successfuly set rate %lluHz on clock 0x%x\n", + p->clock_rate_hz, p->clock_handle); + } + } + + LOG_EXT(); + return ret; +} + +int esc_mods_get_clock_rate(struct file *pfile, struct MODS_CLOCK_RATE *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else { + p->clock_rate_hz = clk_get_rate(pclk); + mods_debug_printk(DEBUG_CLOCK, "clock 0x%x has rate %lluHz\n", + p->clock_handle, p->clock_rate_hz); + ret = OK; + } + + LOG_EXT(); + return ret; +} + +int esc_mods_get_clock_max_rate(struct file *pfile, struct MODS_CLOCK_RATE *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); +#if defined(CONFIG_TEGRA_CLK_FRAMEWORK) + } else if (!pclk->ops || !pclk->ops->round_rate) { + mods_error_printk( + "unable to detect max rate for clock handle 0x%x\n", + p->clock_handle); + } else { + long rate = pclk->ops->round_rate(pclk, pclk->max_rate); + + p->clock_rate_hz = rate < 0 ? pclk->max_rate + : (unsigned long)rate; +#elif defined(MODS_COMMON_CLK) + } else { + long rate = clk_round_rate(pclk, ARBITRARY_MAX_CLK_FREQ); + + p->clock_rate_hz = rate < 0 ? ARBITRARY_MAX_CLK_FREQ + : (unsigned long)rate; +#endif + mods_debug_printk(DEBUG_CLOCK, + "clock 0x%x has max rate %lluHz\n", + p->clock_handle, p->clock_rate_hz); + ret = OK; + } + + LOG_EXT(); + return ret; +} + +int esc_mods_set_clock_max_rate(struct file *pfile, struct MODS_CLOCK_RATE *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else { +#if defined(CONFIG_TEGRA_CLOCK_DEBUG_FUNC) + ret = tegra_clk_set_max(pclk, p->clock_rate_hz); + if (ret) { + mods_error_printk( + "unable to override max clock rate %lluHz on clock 0x%x\n", + p->clock_rate_hz, p->clock_handle); + } else { + mods_debug_printk(DEBUG_CLOCK, + "successfuly set max rate %lluHz on clock 0x%x\n", + p->clock_rate_hz, p->clock_handle); + } +#else + mods_error_printk("unable to override max clock rate\n"); + mods_error_printk( + "reconfigure kernel with CONFIG_TEGRA_CLOCK_DEBUG_FUNC=y\n"); + ret = -EINVAL; +#endif + } + + LOG_EXT(); + return ret; +} + +int esc_mods_set_clock_parent(struct file *pfile, struct MODS_CLOCK_PARENT *p) +{ + struct clk *pclk = 0; + struct clk *pparent = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + pparent = mods_get_clock(p->clock_parent_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else if (!pparent) { + mods_error_printk("unrecognized parent clock handle: 0x%x\n", + p->clock_parent_handle); + } else { + ret = clk_set_parent(pclk, pparent); + if (ret) { + mods_error_printk( + "unable to make clock 0x%x parent of clock 0x%x\n", + p->clock_parent_handle, p->clock_handle); + } else { + mods_debug_printk(DEBUG_CLOCK, + "successfuly made clock 0x%x parent of clock 0x%x\n", + p->clock_parent_handle, p->clock_handle); + } + } + + LOG_EXT(); + return ret; +} + +int esc_mods_get_clock_parent(struct file *pfile, struct MODS_CLOCK_PARENT *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else { + struct clk *pparent = clk_get_parent(pclk); + + p->clock_parent_handle = mods_get_clock_handle(pparent); + mods_debug_printk(DEBUG_CLOCK, + "clock 0x%x is parent of clock 0x%x\n", + p->clock_parent_handle, p->clock_handle); + ret = OK; + } + + LOG_EXT(); + return ret; +} + +int esc_mods_enable_clock(struct file *pfile, struct MODS_CLOCK_HANDLE *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else { +#if defined(MODS_COMMON_CLK) + ret = clk_prepare(pclk); + if (ret) { + mods_error_printk( + "unable to prepare clock 0x%x before enabling\n", + p->clock_handle); + } +#endif + ret = clk_enable(pclk); + if (ret) { + mods_error_printk("failed to enable clock 0x%x\n", + p->clock_handle); + } else { + mods_debug_printk(DEBUG_CLOCK, "clock 0x%x enabled\n", + p->clock_handle); + } + } + + LOG_EXT(); + return ret; +} + +int esc_mods_disable_clock(struct file *pfile, struct MODS_CLOCK_HANDLE *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else { + clk_disable(pclk); +#if defined(MODS_COMMON_CLK) + clk_unprepare(pclk); +#endif + mods_debug_printk(DEBUG_CLOCK, "clock 0x%x disabled\n", + p->clock_handle); + ret = OK; + } + + LOG_EXT(); + return ret; +} + +int esc_mods_is_clock_enabled(struct file *pfile, struct MODS_CLOCK_ENABLED *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else { +#if defined(CONFIG_TEGRA_CLK_FRAMEWORK) + p->enable_count = pclk->refcnt; +#elif defined(MODS_COMMON_CLK) + p->enable_count = (u32)__clk_is_enabled(pclk); +#endif + mods_debug_printk(DEBUG_CLOCK, "clock 0x%x enable count is %u\n", + p->clock_handle, p->enable_count); + ret = OK; + } + + LOG_EXT(); + return ret; +} + +int esc_mods_clock_reset_assert(struct file *pfile, + struct MODS_CLOCK_HANDLE *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else { +#if defined(MODS_COMMON_CLK) + const char *clk_name = 0; + struct reset_control *prst = 0; + struct device_node *mods_np = 0; + struct property *pp = 0; + + mods_np = find_clocks_node("mods-clocks"); + if (!mods_np || !of_device_is_available(mods_np)) { + mods_error_printk("'mods-clocks' node not found in DTB\n"); + goto err; + } + pp = of_find_property(mods_np, "reset-names", NULL); + if (IS_ERR(pp)) { + mods_error_printk( + "No 'reset-names' prop in 'mods-clocks' node for dev %s\n", + __clk_get_name(pclk)); + goto err; + } + + clk_name = __clk_get_name(pclk); + + prst = of_reset_control_get(mods_np, clk_name); + if (IS_ERR(prst)) { + mods_error_printk("reset device %s not found\n", + clk_name); + goto err; + } + ret = reset_control_assert(prst); + if (ret) { + mods_error_printk("failed to assert reset on '%s'\n", + clk_name); + } else { + mods_debug_printk(DEBUG_CLOCK, "asserted reset on '%s'", + clk_name); + } + +err: + of_node_put(mods_np); +#endif + } + LOG_EXT(); + return ret; +} + +int esc_mods_clock_reset_deassert(struct file *pfile, + struct MODS_CLOCK_HANDLE *p) +{ + struct clk *pclk = 0; + int ret = -EINVAL; + + LOG_ENT(); + + pclk = mods_get_clock(p->clock_handle); + + if (!pclk) { + mods_error_printk("unrecognized clock handle: 0x%x\n", + p->clock_handle); + } else { +#if defined(MODS_COMMON_CLK) + const char *clk_name = 0; + struct reset_control *prst = 0; + struct device_node *mods_np = 0; + struct property *pp = 0; + + mods_np = find_clocks_node("mods-clocks"); + if (!mods_np || !of_device_is_available(mods_np)) { + mods_error_printk("'mods-clocks' node not found in DTB\n"); + goto err; + } + pp = of_find_property(mods_np, "reset-names", NULL); + if (IS_ERR(pp)) { + mods_error_printk( + "No 'reset-names' prop in 'mods-clocks' node for dev %s\n", + __clk_get_name(pclk)); + goto err; + } + + clk_name = __clk_get_name(pclk); + + prst = of_reset_control_get(mods_np, clk_name); + if (IS_ERR(prst)) { + mods_error_printk( + "reset device %s not found\n", clk_name); + goto err; + } + ret = reset_control_deassert(prst); + if (ret) { + mods_error_printk("failed to assert reset on '%s'\n", + clk_name); + } else { + mods_debug_printk(DEBUG_CLOCK, "deasserted reset on '%s'", + clk_name); + } + +err: + of_node_put(mods_np); +#endif + } + + LOG_EXT(); + return ret; +} diff --git a/drivers/misc/mods/mods_config.h b/drivers/misc/mods/mods_config.h new file mode 100644 index 00000000..3978af12 --- /dev/null +++ b/drivers/misc/mods/mods_config.h @@ -0,0 +1,63 @@ +/* + * mods_config.h - This file is part of NVIDIA MODS kernel driver. + * + * Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA MODS kernel driver is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * NVIDIA MODS kernel driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVIDIA MODS kernel driver. + * If not, see . + */ + +#ifndef _MODS_CONFIG_H_ +#define _MODS_CONFIG_H_ + +#define MODS_KERNEL_VERSION KERNEL_VERSION(3, 18, 0) + +#define MODS_IRQ_HANDLE_NO_REGS 1 +#define MODS_HAS_SET_MEMORY 1 +#define MODS_ACPI_DEVID_64 1 +#define MODS_HAS_WC 1 +#define MODS_HAS_DEV_TO_NUMA_NODE 1 +#define MODS_HAS_NEW_ACPI_WALK 1 +#ifdef CONFIG_DEBUG_FS +#define MODS_HAS_DEBUGFS 1 +#endif +#if defined(CONFIG_TEGRA_KFUSE) +#define MODS_HAS_KFUSE 1 +#endif +#ifdef CONFIG_DMA_SHARED_BUFFER +#define MODS_HAS_DMABUF 1 +#endif +#define MODS_MULTI_INSTANCE_DEFAULT_VALUE 1 +#define MODS_HAS_IORESOURCE_MEM_64 1 +#undef MODS_HAS_NEW_ACPI_HANDLE /* new in 3.13 */ +#if defined(CONFIG_ARCH_TEGRA) +#define MODS_TEGRA 1 +#endif +#if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || \ + (defined(CONFIG_COMMON_CLK) && defined(CONFIG_OF_RESOLVE) && \ + defined(CONFIG_OF_DYNAMIC)) +#define MODS_HAS_CLOCK 1 +#endif +#ifdef CONFIG_NET +#define MODS_HAS_NET 1 +#endif +#ifdef CONFIG_ZONE_DMA32 +#define MODS_HAS_DMA32 1 +#endif +#ifdef CONFIG_PCI +#define MODS_CAN_REGISTER_PCI_DEV 1 +#endif + +#endif /* _MODS_CONFIG_H_ */ + +/* vim: set ts=8 sw=8 noet: */ diff --git a/drivers/misc/mods/mods_debugfs.c b/drivers/misc/mods/mods_debugfs.c new file mode 100644 index 00000000..50f484d7 --- /dev/null +++ b/drivers/misc/mods/mods_debugfs.c @@ -0,0 +1,807 @@ +/* + * mods_debugfs.c - This file is part of NVIDIA MODS kernel driver. + * + * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA MODS kernel driver is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * NVIDIA MODS kernel driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NVIDIA MODS kernel driver. + * If not, see . + */ + +#include "mods_internal.h" + +#ifdef MODS_HAS_DEBUGFS + +#include +#include +#include +#include +#include +#include + +static struct dentry *mods_debugfs_dir; + +#if defined(MODS_TEGRA) && defined(MODS_HAS_KFUSE) +#include +#endif + +#ifdef CONFIG_TEGRA_DC +#include