From d5138e1c5874e5e17e72f10b66cc3554614e2b65 Mon Sep 17 00:00:00 2001 From: Viswanath L Date: Thu, 31 Aug 2023 12:23:52 +0000 Subject: [PATCH] nvadsp: Fix build issues and enable Fix build issues for nvadsp in OOT kernel and enable the build. - Below files copied from kernel/nvidia/include/linux/ - tegra_nvadsp.h (72af3e78a6aff0fa250e9fd36b8414264d0e4c9a) - tegra-firmwares.h (700223e52f49f300664dd91335fa11111af733aa) - tegra-hsp.h (988be8f05033e1d728e046e918b506d829106082) - Below file copied from kernel/nvidia/include/uapi/misc/ - adsp_console_ioctl.h (72af3e78a6aff0fa250e9fd36b8414264d0e4c9a) - Functions that needs additional AGIC APIs not supported in upstream are pushed under macro CONFIG_AGIC_EXT_APIS - T210 chip_data and references removed Bug 4164138 Bug 3682950 Change-Id: I5dfb570e578ca3631896de7350cea66698612568 Signed-off-by: Viswanath L Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2971924 Reviewed-by: Laxman Dewangan GVS: Gerrit_Virtual_Submit --- drivers/platform/tegra/Makefile | 4 + drivers/platform/tegra/nvadsp/Makefile | 39 +-- drivers/platform/tegra/nvadsp/amc.c | 2 +- drivers/platform/tegra/nvadsp/dev-t18x.c | 1 + drivers/platform/tegra/nvadsp/dev.c | 56 +-- drivers/platform/tegra/nvadsp/hwmailbox.c | 1 - drivers/platform/tegra/nvadsp/os-t18x.c | 2 +- drivers/platform/tegra/nvadsp/os.c | 25 +- include/linux/tegra-firmwares.h | 101 ++++++ include/linux/tegra-hsp.h | 121 +++++++ include/linux/tegra_nvadsp.h | 393 ++++++++++++++++++++++ include/uapi/misc/adsp_console_ioctl.h | 46 +++ 12 files changed, 700 insertions(+), 91 deletions(-) create mode 100644 include/linux/tegra-firmwares.h create mode 100644 include/linux/tegra-hsp.h create mode 100644 include/linux/tegra_nvadsp.h create mode 100644 include/uapi/misc/adsp_console_ioctl.h diff --git a/drivers/platform/tegra/Makefile b/drivers/platform/tegra/Makefile index 75d5f0b6..affd5729 100644 --- a/drivers/platform/tegra/Makefile +++ b/drivers/platform/tegra/Makefile @@ -20,3 +20,7 @@ obj-m += rtcpu/ endif obj-m += aon/ obj-m += tegra-uss-io-proxy.o + +ifneq ($(filter oot,$(patsubst -,$(space),$(NV_BUILD_KERNEL_OPTIONS))),) +obj-m += nvadsp/ +endif diff --git a/drivers/platform/tegra/nvadsp/Makefile b/drivers/platform/tegra/nvadsp/Makefile index 380d1649..39ec0c17 100644 --- a/drivers/platform/tegra/nvadsp/Makefile +++ b/drivers/platform/tegra/nvadsp/Makefile @@ -4,42 +4,13 @@ GCOV_PROFILE := y ccflags-y += -Werror -obj-$(CONFIG_TEGRA_NVADSP) := nvadsp.o +obj-m := nvadsp.o + nvadsp-objs += dev.o os.o app.o app_loader_linker.o\ amc.o nvadsp_shared_sema.o \ hwmailbox.o mailbox.o msgq.o \ mem_manager.o aram_manager.o dram_app_mem_manager.o \ - dev-t21x.o os-t21x.o dev-t18x.o os-t18x.o acast.o + acast.o adsp_console_dbfs.o - -ifeq ($(CONFIG_TEGRA_ADSP_DFS),y) -nvadsp-objs += adsp_dfs.o -endif - -ifeq ($(CONFIG_TEGRA_ADSP_ACTMON),y) -nvadsp-objs += ape_actmon.o -endif - -ifeq ($(CONFIG_TEGRA_EMC_APE_DFS),y) -nvadsp-objs += emc_dfs.o -endif - -ifeq ($(CONFIG_TEGRA_ADSP_CONSOLE),y) -nvadsp-objs += adsp_console_dbfs.o -endif - -ifeq ($(CONFIG_TEGRA_ADSP_CPUSTAT),y) -nvadsp-objs += adsp_cpustat.o -endif - -ifeq ($(CONFIG_TEGRA_ADSP_FILEIO),y) -nvadsp-objs += adspff.o -endif - -ifeq ($(CONFIG_TEGRA_ADSP_LPTHREAD),y) -nvadsp-objs += adsp_lpthread.o -endif - -ifeq ($(CONFIG_TEGRA_VIRT_AUDIO_IVC),y) -ccflags-y += -I$(srctree.nvidia)/drivers/platform/tegra/nvaudio_ivc/ -endif +# T234/T239/T194/T186 +nvadsp-objs += dev-t18x.o os-t18x.o diff --git a/drivers/platform/tegra/nvadsp/amc.c b/drivers/platform/tegra/nvadsp/amc.c index faac1f31..55ba22ea 100644 --- a/drivers/platform/tegra/nvadsp/amc.c +++ b/drivers/platform/tegra/nvadsp/amc.c @@ -4,10 +4,10 @@ */ #include -#include #include #include #include +#include #include "dev.h" #include "amc.h" diff --git a/drivers/platform/tegra/nvadsp/dev-t18x.c b/drivers/platform/tegra/nvadsp/dev-t18x.c index 057319b0..7334146d 100644 --- a/drivers/platform/tegra/nvadsp/dev-t18x.c +++ b/drivers/platform/tegra/nvadsp/dev-t18x.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include diff --git a/drivers/platform/tegra/nvadsp/dev.c b/drivers/platform/tegra/nvadsp/dev.c index cf8fa4db..47e9b4b8 100644 --- a/drivers/platform/tegra/nvadsp/dev.c +++ b/drivers/platform/tegra/nvadsp/dev.c @@ -16,11 +16,11 @@ #include #include #include +#include #include #include #include #include -#include #include "dev.h" #include "os.h" @@ -28,7 +28,6 @@ #include "ape_actmon.h" #include "aram_manager.h" -#include "dev-t21x.h" #include "dev-t18x.h" static struct nvadsp_drv_data *nvadsp_drv_data; @@ -501,31 +500,6 @@ static int nvadsp_remove(struct platform_device *pdev) } #ifdef CONFIG_OF -static struct nvadsp_chipdata tegra210_adsp_chipdata = { - .hwmb = { - .reg_idx = AMISC, - .hwmbox0_reg = 0x58, - .hwmbox1_reg = 0X5C, - .hwmbox2_reg = 0x60, - .hwmbox3_reg = 0x64, - }, - .adsp_state_hwmbox = 0, - .adsp_thread_hwmbox = 0, - .adsp_irq_hwmbox = 0, - .adsp_shared_mem_hwmbox = 0, - .adsp_os_config_hwmbox = 0, - .reset_init = nvadsp_reset_t21x_init, - .os_init = nvadsp_os_t21x_init, -#ifdef CONFIG_PM - .pm_init = nvadsp_pm_t21x_init, -#endif - .wdt_irq = INT_T210_ADSP_WDT, - .start_irq = INT_T210_AGIC_START, - .end_irq = INT_T210_AGIC_END, - - .amc_err_war = true, -}; - static struct nvadsp_chipdata tegrat18x_adsp_chipdata = { .hwmb = { .reg_idx = AHSP, @@ -550,9 +524,6 @@ static struct nvadsp_chipdata tegrat18x_adsp_chipdata = { #ifdef CONFIG_PM .pm_init = nvadsp_pm_t18x_init, #endif - .wdt_irq = INT_T18x_ATKE_WDT_IRQ, - .start_irq = INT_T18x_AGIC_START, - .end_irq = INT_T18x_AGIC_END, .amc_err_war = true, }; @@ -581,9 +552,6 @@ static struct nvadsp_chipdata tegra239_adsp_chipdata = { #ifdef CONFIG_PM .pm_init = nvadsp_pm_t18x_init, #endif - .wdt_irq = INT_T18x_ATKE_WDT_IRQ, - .start_irq = INT_T18x_AGIC_START, - .end_irq = INT_T18x_AGIC_END, .amc_err_war = false, @@ -593,9 +561,6 @@ static struct nvadsp_chipdata tegra239_adsp_chipdata = { static const struct of_device_id nvadsp_of_match[] = { { - .compatible = "nvidia,tegra210-adsp", - .data = &tegra210_adsp_chipdata, - }, { .compatible = "nvidia,tegra18x-adsp", .data = &tegrat18x_adsp_chipdata, }, { @@ -604,6 +569,7 @@ static const struct of_device_id nvadsp_of_match[] = { }, { }, }; +MODULE_DEVICE_TABLE(of, nvadsp_of_match); #endif static struct platform_driver nvadsp_driver __refdata = { @@ -616,21 +582,9 @@ static struct platform_driver nvadsp_driver __refdata = { .probe = nvadsp_probe, .remove = nvadsp_remove, }; - -static int __init nvadsp_init(void) -{ - return platform_driver_register(&nvadsp_driver); -} - -static void __exit nvadsp_exit(void) -{ - platform_driver_unregister(&nvadsp_driver); -} - -module_init(nvadsp_init); -module_exit(nvadsp_exit); +module_platform_driver(nvadsp_driver); MODULE_AUTHOR("NVIDIA"); MODULE_DESCRIPTION("Tegra Host ADSP Driver"); -MODULE_VERSION("1.0"); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION("6.0"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/tegra/nvadsp/hwmailbox.c b/drivers/platform/tegra/nvadsp/hwmailbox.c index 5d397ba0..a217bce4 100644 --- a/drivers/platform/tegra/nvadsp/hwmailbox.c +++ b/drivers/platform/tegra/nvadsp/hwmailbox.c @@ -9,7 +9,6 @@ #include #include #include -#include #include "dev.h" diff --git a/drivers/platform/tegra/nvadsp/os-t18x.c b/drivers/platform/tegra/nvadsp/os-t18x.c index ac7a01c3..2ab8e55f 100644 --- a/drivers/platform/tegra/nvadsp/os-t18x.c +++ b/drivers/platform/tegra/nvadsp/os-t18x.c @@ -5,10 +5,10 @@ #include #include +#include #include #include #include -#include #include "dev.h" #include "os.h" diff --git a/drivers/platform/tegra/nvadsp/os.c b/drivers/platform/tegra/nvadsp/os.c index 4f8d5914..c79f4ffb 100644 --- a/drivers/platform/tegra/nvadsp/os.c +++ b/drivers/platform/tegra/nvadsp/os.c @@ -11,17 +11,19 @@ #include #include #include +#if defined(CONFIG_TEGRA_NVADSP_ON_SMMU) #include +#endif #include #include #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -116,6 +118,9 @@ struct nvadsp_mappings { int len; }; +extern u8 tegra_get_major_rev(void); +extern u8 tegra_get_minor_rev(void); + static struct nvadsp_mappings adsp_map[NM_LOAD_MAPPINGS]; static int map_idx; static struct nvadsp_mbox adsp_com_mbox; @@ -601,6 +606,7 @@ static int nvadsp_os_elf_load(const struct firmware *fw) return ret; } +#if defined(CONFIG_TEGRA_NVADSP_ON_SMMU) /** * Allocate a dma buffer and map it to a specified iova * Return valid cpu virtual address on success or NULL on failure @@ -695,6 +701,7 @@ fail_dma_alloc: return NULL; } +#endif static int allocate_memory_for_adsp_os(void) { @@ -818,12 +825,20 @@ static int __nvadsp_os_secload(struct platform_device *pdev) return -ENOMEM; } } else { +#if defined(CONFIG_TEGRA_NVADSP_ON_SMMU) dram_va = nvadsp_dma_alloc_and_map_at(pdev, size, addr, GFP_KERNEL); if (dram_va == NULL) { dev_err(dev, "unable to allocate shared region\n"); return -ENOMEM; } +#else + dram_va = ioremap((phys_addr_t)addr, size); + if (dram_va == NULL) { + dev_err(dev, "remap failed on shared region\n"); + return -ENOMEM; + } +#endif } drv_data->shared_adsp_os_data_iova = addr; @@ -1021,6 +1036,7 @@ static int nvadsp_load_multi_fw(struct platform_device *pdev) mfw_smem_iova[i] = shrd_mem_iova; mfw_hsp_va[i] = hsp_va; +#ifdef CONFIG_AGIC_EXT_APIS /* * Interrupt routing of AHSP1-3 is only for the * sake of completion; CCPLEX<->ADSP communication @@ -1057,6 +1073,7 @@ static int nvadsp_load_multi_fw(struct platform_device *pdev) break; } } +#endif // CONFIG_AGIC_EXT_APIS if (j == 8) dev_info(dev, "Setup done for core %d FW\n", (i + 1)); @@ -1526,6 +1543,7 @@ static void dump_adsp_logs(void) static void print_agic_irq_states(void) { +#ifdef CONFIG_AGIC_EXT_API struct nvadsp_drv_data *drv_data = platform_get_drvdata(priv.pdev); int start_irq = drv_data->chip_data->start_irq; int end_irq = drv_data->chip_data->end_irq; @@ -1539,6 +1557,7 @@ static void print_agic_irq_states(void) tegra_agic_irq_is_active(i) ? "active" : "not active"); } +#endif // CONFIG_AGIC_EXT_APIS } static void print_arm_mode_regs(void) @@ -2278,6 +2297,7 @@ EXPORT_SYMBOL(nvadsp_os_suspend); static void nvadsp_os_restart(struct work_struct *work) { +#ifdef CONFIG_AGIC_EXT_APIS struct nvadsp_os_data *data = container_of(work, struct nvadsp_os_data, restart_os_work); struct nvadsp_drv_data *drv_data = platform_get_drvdata(data->pdev); @@ -2313,6 +2333,7 @@ static void nvadsp_os_restart(struct work_struct *work) if (nvadsp_os_start()) dev_crit(dev, "Unable to restart ADSP OS\n"); +#endif // CONFIG_AGIC_EXT_APIS } static irqreturn_t adsp_wfi_handler(int irq, void *arg) @@ -2490,11 +2511,9 @@ int __init nvadsp_os_probe(struct platform_device *pdev) if (adsp_create_debug_logger(drv_data->adsp_debugfs_root)) dev_err(dev, "unable to create adsp debug logger file\n"); -#ifdef CONFIG_TEGRA_ADSP_CONSOLE priv.console.dev = &pdev->dev; if (adsp_create_cnsl(drv_data->adsp_debugfs_root, &priv.console)) dev_err(dev, "unable to create adsp console file\n"); -#endif /* CONFIG_TEGRA_ADSP_CONSOLE */ if (adsp_create_os_version(drv_data->adsp_debugfs_root)) dev_err(dev, "unable to create adsp_version file\n"); diff --git a/include/linux/tegra-firmwares.h b/include/linux/tegra-firmwares.h new file mode 100644 index 00000000..6e11cd10 --- /dev/null +++ b/include/linux/tegra-firmwares.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Copyright (c) 2016-2023, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef __TEGRA_FIRMWARES_H +#define __TEGRA_FIRMWARES_H + +/* + * max size of version string + */ +#define TFW_VERSION_MAX_SIZE 256 + +#if IS_ENABLED(CONFIG_TEGRA_FIRMWARES_CLASS) + +struct device *tegrafw_register(const char *name, + const u32 flags, + ssize_t (*reader)(struct device *dev, char *, size_t), + const char *string); +void tegrafw_unregister(struct device *fwdev); +struct device *devm_tegrafw_register(struct device *dev, + const char *name, + const u32 flags, + ssize_t (*reader)(struct device *dev, char *, size_t), + const char *string); +void devm_tegrafw_unregister(struct device *dev, struct device *fwdev); +void tegrafw_invalidate(struct device *fwdev); +struct device *devm_tegrafw_register_dt_string(struct device *dev, + const char *name, + const char *path, + const char *property); +#else + +static inline struct device *tegrafw_register(const char *name, + const u32 flags, + ssize_t (*reader)(struct device *, char *, size_t), + const char *string) +{ + return ERR_PTR(-ENOTSUPP); +} + +static inline void tegrafw_unregister(struct device *fwdev) +{ +} + +static inline void tegrafw_invalidate(struct device *fwdev) +{ +} + +static inline struct device *devm_tegrafw_register(struct device *dev, + const char *name, + const u32 flags, + ssize_t (*reader)(struct device *dev, char *, size_t), + const char *string) +{ + return ERR_PTR(-ENOTSUPP); +} + +static inline void devm_tegrafw_unregister(struct device *dev, + struct device *fwdev) +{ +} + +static inline +struct device *devm_tegrafw_register_dt_string(struct device *dev, + const char *name, + const char *path, + const char *property) +{ + return ERR_PTR(-ENOTSUPP); +} + +#endif /* IS_ENABLED(...) */ + +enum { + TFW_NORMAL = 0x0000, + TFW_DONT_CACHE = 0x0001, + TFW_MAX = 0xFFFF, +}; + +static inline struct device *tegrafw_register_string(const char *name, + const char *string) +{ + return tegrafw_register(name, TFW_NORMAL, NULL, string); +} + +static inline struct device *devm_tegrafw_register_string(struct device *dev, + const char *name, + const char *string) +{ + return devm_tegrafw_register(dev, name, TFW_NORMAL, NULL, string); +} + +static inline struct device *tegrafw_register_dt_string(const char *name, + const char *path, + const char *property) +{ + return devm_tegrafw_register_dt_string(NULL, name, path, property); +} + +#endif /* __TEGRA_FIRMWARES_CLASS */ diff --git a/include/linux/tegra-hsp.h b/include/linux/tegra-hsp.h new file mode 100644 index 00000000..0efd0db7 --- /dev/null +++ b/include/linux/tegra-hsp.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef _LINUX_TEGRA_HSP_H +#define _LINUX_TEGRA_HSP_H + +#include + +enum tegra_hsp_master { + HSP_FIRST_MASTER = 1, + + /* secure */ + HSP_MASTER_SECURE_CCPLEX = HSP_FIRST_MASTER, + HSP_MASTER_SECURE_DPMU, + HSP_MASTER_SECURE_BPMP, + HSP_MASTER_SECURE_SPE, + HSP_MASTER_SECURE_SCE, + HSP_MASTER_SECURE_DMA, + HSP_MASTER_SECURE_TSECA, + HSP_MASTER_SECURE_TSECB, + HSP_MASTER_SECURE_JTAGM, + HSP_MASTER_SECURE_CSITE, + HSP_MASTER_SECURE_APE, + + /* non-secure */ + HSP_MASTER_CCPLEX = HSP_FIRST_MASTER + 16, + HSP_MASTER_DPMU, + HSP_MASTER_BPMP, + HSP_MASTER_SPE, + HSP_MASTER_SCE, + HSP_MASTER_DMA, + HSP_MASTER_TSECA, + HSP_MASTER_TSECB, + HSP_MASTER_JTAGM, + HSP_MASTER_CSITE, + HSP_MASTER_APE, + + HSP_LAST_MASTER = HSP_MASTER_APE, +}; + +enum tegra_hsp_doorbell { + HSP_FIRST_DB = 0, + HSP_DB_DPMU = HSP_FIRST_DB, + HSP_DB_CCPLEX, + HSP_DB_CCPLEX_TZ, + HSP_DB_BPMP, + HSP_DB_SPE, + HSP_DB_SCE, + HSP_DB_APE, + HSP_LAST_DB = HSP_DB_APE, + HSP_NR_DBS, +}; + +typedef void (*db_handler_t)(void *data); + +int tegra_hsp_init(void); + +int tegra_hsp_db_enable_master(enum tegra_hsp_master master); + +int tegra_hsp_db_disable_master(enum tegra_hsp_master master); + +int tegra_hsp_db_ring(enum tegra_hsp_doorbell dbell); + +int tegra_hsp_db_can_ring(enum tegra_hsp_doorbell dbell); + +int tegra_hsp_db_add_handler(int master, db_handler_t handler, void *data); + +int tegra_hsp_db_del_handler(int master); + +#define tegra_hsp_find_master(mask, master) ((mask) & (1 << (master))) + +typedef void (*tegra_hsp_sm_notify)(void *, u32); + +struct tegra_hsp_sm_tx; +struct tegra_hsp_sm_rx; +struct tegra_hsp_ss; + +struct tegra_hsp_sm_pair { + struct tegra_hsp_sm_rx *rx; + struct tegra_hsp_sm_tx *tx; +}; + +struct tegra_hsp_sm_pair *of_tegra_hsp_sm_pair_request( + const struct device_node *np, u32 index, + tegra_hsp_sm_notify full_notify, + tegra_hsp_sm_notify empty_notify, + void *data); +struct tegra_hsp_sm_pair *of_tegra_hsp_sm_pair_by_name( + struct device_node *np, char const *name, + tegra_hsp_sm_notify full_notify, + tegra_hsp_sm_notify empty_notify, + void *data); +void tegra_hsp_sm_pair_free(struct tegra_hsp_sm_pair *pair); +void tegra_hsp_sm_pair_write(const struct tegra_hsp_sm_pair *pair, u32 value); +bool tegra_hsp_sm_pair_is_empty(const struct tegra_hsp_sm_pair *pair); +void tegra_hsp_sm_pair_enable_empty_notify(struct tegra_hsp_sm_pair *pair); + +struct tegra_hsp_sm_tx *of_tegra_hsp_sm_tx_by_name( + struct device_node *np, char const *name, + tegra_hsp_sm_notify notify, void *data); +void tegra_hsp_sm_tx_free(struct tegra_hsp_sm_tx *tx); +bool tegra_hsp_sm_tx_is_empty(const struct tegra_hsp_sm_tx *tx); +void tegra_hsp_sm_tx_write(const struct tegra_hsp_sm_tx *tx, u32 value); +void tegra_hsp_sm_tx_enable_notify(struct tegra_hsp_sm_tx *tx); + +struct tegra_hsp_sm_rx *of_tegra_hsp_sm_rx_by_name( + struct device_node *np, char const *name, + tegra_hsp_sm_notify notify, void *data); +void tegra_hsp_sm_rx_free(struct tegra_hsp_sm_rx *rx); +bool tegra_hsp_sm_rx_is_empty(const struct tegra_hsp_sm_rx *rx); + +struct tegra_hsp_ss *of_tegra_hsp_ss_by_name( + struct device_node *np, char const *name); +void tegra_hsp_ss_free(struct tegra_hsp_ss *ss); +u32 tegra_hsp_ss_status(const struct tegra_hsp_ss *ss); +void tegra_hsp_ss_set(const struct tegra_hsp_ss *ss, u32 bits); +void tegra_hsp_ss_clr(const struct tegra_hsp_ss *ss, u32 bits); + +#endif diff --git a/include/linux/tegra_nvadsp.h b/include/linux/tegra_nvadsp.h new file mode 100644 index 00000000..fe3cfd16 --- /dev/null +++ b/include/linux/tegra_nvadsp.h @@ -0,0 +1,393 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef __LINUX_TEGRA_NVADSP_H +#define __LINUX_TEGRA_NVADSP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct nvadsp_platform_data { + phys_addr_t co_pa; + unsigned long co_size; +}; + +typedef int status_t; + +/* + * Shared Semaphores + */ +typedef struct { + int magic; /* 'ssem' */ + uint8_t id; + wait_queue_head_t wait; + struct timer_list timer; +} nvadsp_shared_sema_t; + +nvadsp_shared_sema_t * +nvadsp_shared_sema_init(uint8_t nvadsp_shared_sema_id); +status_t nvadsp_shared_sema_destroy(nvadsp_shared_sema_t *); +status_t nvadsp_shared_sema_acquire(nvadsp_shared_sema_t *); +status_t nvadsp_shared_sema_release(nvadsp_shared_sema_t *); + +/* + * Arbitrated Semaphores + */ +typedef struct { + int magic; /* 'asem' */ + uint8_t id; + wait_queue_head_t wait; + struct completion comp; +} nvadsp_arb_sema_t; + +nvadsp_arb_sema_t *nvadsp_arb_sema_init(uint8_t nvadsp_arb_sema_id); +status_t nvadsp_arb_sema_destroy(nvadsp_arb_sema_t *); +status_t nvadsp_arb_sema_acquire(nvadsp_arb_sema_t *); +status_t nvadsp_arb_sema_release(nvadsp_arb_sema_t *); + +/* + * Mailbox Queue + */ +#define NVADSP_MBOX_QUEUE_SIZE 32 +#define NVADSP_MBOX_QUEUE_SIZE_MASK (NVADSP_MBOX_QUEUE_SIZE - 1) +struct nvadsp_mbox_queue { + uint32_t array[NVADSP_MBOX_QUEUE_SIZE]; + uint16_t head; + uint16_t tail; + uint16_t count; + struct completion comp; + spinlock_t lock; +}; + +status_t nvadsp_mboxq_enqueue(struct nvadsp_mbox_queue *, uint32_t); + +/* + * Mailbox + */ +#define NVADSP_MBOX_NAME_MAX 16 +#define NVADSP_MBOX_NAME_MAX_STR (NVADSP_MBOX_NAME_MAX + 1) + +typedef status_t (*nvadsp_mbox_handler_t)(uint32_t, void *); + +struct nvadsp_mbox { + uint16_t id; + char name[NVADSP_MBOX_NAME_MAX_STR]; + struct nvadsp_mbox_queue recv_queue; + nvadsp_mbox_handler_t handler; +#ifdef CONFIG_MBOX_ACK_HANDLER + nvadsp_mbox_handler_t ack_handler; +#endif + void *hdata; +}; + +#define NVADSP_MBOX_SMSG 0x1 +#define NVADSP_MBOX_LMSG 0x2 + +status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox, uint16_t *mid, + const char *name, nvadsp_mbox_handler_t handler, + void *hdata); +status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox, uint32_t data, + uint32_t flags, bool block, unsigned int timeout); +status_t nvadsp_mbox_recv(struct nvadsp_mbox *mbox, uint32_t *data, bool block, + unsigned int timeout); +status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox); + +#ifdef CONFIG_MBOX_ACK_HANDLER +static inline void register_ack_handler(struct nvadsp_mbox *mbox, + nvadsp_mbox_handler_t handler) +{ + mbox->ack_handler = handler; +} +#endif + +/* + * Circular Message Queue + */ +typedef struct _msgq_message_t { + int32_t size; /* size of payload in words */ + int32_t payload[1]; /* variable length payload */ +} msgq_message_t; + +#define MSGQ_MESSAGE_HEADER_SIZE \ + (sizeof(msgq_message_t) - sizeof(((msgq_message_t *)0)->payload)) +#define MSGQ_MESSAGE_HEADER_WSIZE \ + (MSGQ_MESSAGE_HEADER_SIZE / sizeof(int32_t)) + +typedef struct _msgq_t { + int32_t size; /* queue size in words */ + int32_t write_index; /* queue write index */ + int32_t read_index; /* queue read index */ + int32_t queue[1]; /* variable length queue */ +} msgq_t; + +#define MSGQ_HEADER_SIZE (sizeof(msgq_t) - sizeof(((msgq_t *)0)->queue)) +#define MSGQ_HEADER_WSIZE (MSGQ_HEADER_SIZE / sizeof(int32_t)) +#define MSGQ_MAX_QUEUE_WSIZE (8192 - MSGQ_HEADER_WSIZE) +#define MSGQ_MSG_WSIZE(x) \ + (((sizeof(x) + sizeof(int32_t) - 1) & (~(sizeof(int32_t)-1))) >> 2) +#define MSGQ_MSG_PAYLOAD_WSIZE(x) \ + (MSGQ_MSG_WSIZE(x) - MSGQ_MESSAGE_HEADER_WSIZE) + +void msgq_init(msgq_t *msgq, int32_t size); +int32_t msgq_queue_message(msgq_t *msgq, const msgq_message_t *message); +int32_t msgq_dequeue_message(msgq_t *msgq, msgq_message_t *message); +#define msgq_discard_message(msgq) msgq_dequeue_message(msgq, NULL) + +/* + * DRAM Sharing + */ +typedef dma_addr_t nvadsp_iova_addr_t; +typedef enum dma_data_direction nvadsp_data_direction_t; + +nvadsp_iova_addr_t +nvadsp_dram_map_single(struct device *nvadsp_dev, + void *cpu_addr, size_t size, + nvadsp_data_direction_t direction); +void +nvadsp_dram_unmap_single(struct device *nvadsp_dev, + nvadsp_iova_addr_t iova_addr, size_t size, + nvadsp_data_direction_t direction); + +nvadsp_iova_addr_t +nvadsp_dram_map_page(struct device *nvadsp_dev, + struct page *page, unsigned long offset, size_t size, + nvadsp_data_direction_t direction); +void +nvadsp_dram_unmap_page(struct device *nvadsp_dev, + nvadsp_iova_addr_t iova_addr, size_t size, + nvadsp_data_direction_t direction); + +void +nvadsp_dram_sync_single_for_cpu(struct device *nvadsp_dev, + nvadsp_iova_addr_t iova_addr, size_t size, + nvadsp_data_direction_t direction); +void +nvadsp_dram_sync_single_for_device(struct device *nvadsp_dev, + nvadsp_iova_addr_t iova_addr, size_t size, + nvadsp_data_direction_t direction); + +/* + * ADSP OS + */ + +typedef const void *nvadsp_os_handle_t; + +void nvadsp_adsp_init(void); +int __must_check nvadsp_os_load(void); +int __must_check nvadsp_os_start(void); +void nvadsp_os_stop(void); +int __must_check nvadsp_os_suspend(void); +void dump_adsp_sys(void); +void nvadsp_get_os_version(char *, int); +int adsp_usage_set(unsigned int val); +unsigned int adsp_usage_get(void); +/* + * ADSP TSC + */ +uint64_t nvadsp_get_timestamp_counter(void); + +/* + * ADSP OS App + */ +#define ARGV_SIZE_IN_WORDS 128 + +enum { + NVADSP_APP_STATE_UNKNOWN, + NVADSP_APP_STATE_INITIALIZED, + NVADSP_APP_STATE_STARTED, + NVADSP_APP_STATE_STOPPED +}; + +enum adsp_app_status_msg { + OS_LOAD_ADSP_APPS, + RUN_ADSP_APP, + ADSP_APP_INIT, + ADSP_APP_START, + ADSP_APP_START_STATUS, + ADSP_APP_COMPLETE_STATUS +}; + +struct nvadsp_app_info; +typedef const void *nvadsp_app_handle_t; +typedef void (*app_complete_status_notifier)(struct nvadsp_app_info *, + enum adsp_app_status_msg, int32_t); + +typedef struct adsp_app_mem { + /* DRAM segment*/ + void *dram; + /* DRAM in shared memory segment. uncached */ + void *shared; + /* DRAM in shared memory segment. write combined */ + void *shared_wc; + /* ARAM if available, DRAM OK */ + void *aram; + /* set to 1 if ARAM allocation succeeded else 0 meaning allocated from + * dram. + */ + uint32_t aram_flag; + /* ARAM Segment. exclusively */ + void *aram_x; + /* set to 1 if ARAM allocation succeeded */ + uint32_t aram_x_flag; +} adsp_app_mem_t; + +typedef struct adsp_app_iova_mem { + /* DRAM segment*/ + uint32_t dram; + /* DRAM in shared memory segment. uncached */ + uint32_t shared; + /* DRAM in shared memory segment. write combined */ + uint32_t shared_wc; + /* ARAM if available, DRAM OK */ + uint32_t aram; + /* + * set to 1 if ARAM allocation succeeded else 0 meaning allocated from + * dram. + */ + uint32_t aram_flag; + /* ARAM Segment. exclusively */ + uint32_t aram_x; + /* set to 1 if ARAM allocation succeeded */ + uint32_t aram_x_flag; +} adsp_app_iova_mem_t; + + +typedef struct nvadsp_app_args { + /* number of arguments passed in */ + int32_t argc; + /* binary representation of arguments */ + int32_t argv[ARGV_SIZE_IN_WORDS]; +} nvadsp_app_args_t; + +typedef struct nvadsp_app_info { + const char *name; + const int instance_id; + const uint32_t token; + const int state; + adsp_app_mem_t mem; + adsp_app_iova_mem_t iova_mem; + struct list_head node; + uint32_t stack_size; + const void *handle; + int return_status; + struct completion wait_for_app_complete; + struct completion wait_for_app_start; + app_complete_status_notifier complete_status_notifier; + struct work_struct complete_work; + enum adsp_app_status_msg status_msg; + void *priv; +} nvadsp_app_info_t; + +nvadsp_app_handle_t __must_check nvadsp_app_load(const char *, const char *); +nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t, + nvadsp_app_args_t *); +void nvadsp_app_unload(nvadsp_app_handle_t); +int __must_check nvadsp_app_start(nvadsp_app_info_t *); +int nvadsp_app_stop(nvadsp_app_info_t *); +int nvadsp_app_deinit(nvadsp_app_info_t *); +void *nvadsp_alloc_coherent(size_t, dma_addr_t *, gfp_t); +void nvadsp_free_coherent(size_t, void *, dma_addr_t); +nvadsp_app_info_t __must_check *nvadsp_run_app(nvadsp_os_handle_t, const char *, + nvadsp_app_args_t *, app_complete_status_notifier, + uint32_t, uint32_t, bool); +void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate); + +static inline void +set_app_complete_notifier( + nvadsp_app_info_t *info, app_complete_status_notifier notifier) +{ + info->complete_status_notifier = notifier; +} + +static inline void wait_for_nvadsp_app_complete(nvadsp_app_info_t *info) +{ + /* + * wait_for_complete must be called only after app has started + */ + if (info->state == NVADSP_APP_STATE_STARTED) + wait_for_completion(&info->wait_for_app_complete); +} + +/** + * wait_for_nvadsp_app_complete_timeout: + * @info: pointer to nvadsp_app_info_t + * @timeout: timeout value in jiffies + * + * This waits for either a completion of a specific app to be signaled or for a + * specified timeout to expire. It is interruptible. The timeout is in jiffies. + * + * The return value is -ERESTARTSYS if interrupted, 0 if timed out, + * positive (at least 1, or number of jiffies left till timeout) if completed. + */ +static inline long wait_for_nvadsp_app_complete_timeout(nvadsp_app_info_t *info, + unsigned long timeout) +{ + int ret = -EINVAL; + /* + * wait_for_complete must be called only after app has started + */ + if (info->state == NVADSP_APP_STATE_STARTED) + ret = wait_for_completion_interruptible_timeout( + &info->wait_for_app_complete, timeout); + + return ret; +} + +/* + * set adma reg dump callback function pointer + * @cb_adma_regdump: function pointer for callback + * + * This api is exported and can be accessed by adsp audio driver, + * which during adsp init, calls this api to set the callback + * function pointer + */ +void nvadsp_set_adma_dump_reg(void (*cb_adma_regdump)(void)); + +#ifdef CONFIG_TEGRA_ADSP_DFS +/* + * Override adsp freq and reinit actmon counters + * + * @params: + * freq: adsp freq in KHz + * return - final freq got set. + * - 0, incase of error. + * + */ +unsigned long adsp_override_freq(unsigned long freq); +void adsp_update_dfs_min_rate(unsigned long freq); + +/* Enable / disable dynamic freq scaling */ +void adsp_update_dfs(bool enable); +#else +static inline unsigned long adsp_override_freq(unsigned long freq) +{ + return 0; +} + +static inline void adsp_update_dfs_min_rate(unsigned long freq) +{ + return; +} + +static inline void adsp_update_dfs(bool enable) +{ + return; +} +#endif + +void *nvadsp_aram_request(const char *name, size_t size); +bool nvadsp_aram_release(void *handle); + +unsigned long nvadsp_aram_get_address(void *handle); +void nvadsp_aram_print(void); + +#endif /* __LINUX_TEGRA_NVADSP_H */ diff --git a/include/uapi/misc/adsp_console_ioctl.h b/include/uapi/misc/adsp_console_ioctl.h new file mode 100644 index 00000000..68c1ac88 --- /dev/null +++ b/include/uapi/misc/adsp_console_ioctl.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * Copyright (c) 2016-2023, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef __UAPI_ADSP_CNSL_IOCTL_H +#define __UAPI_ADSP_CNSL_IOCTL_H +#include + +#if !defined(NVADSP_NAME_SZ) +#define NVADSP_NAME_SZ 128 +#endif + +#define NVADSP_NAME_SZ_MAX (NVADSP_NAME_SZ - 1) + +#if !defined(ARGV_SIZE_IN_WORDS) +#define ARGV_SIZE_IN_WORDS 128 +#endif + +#define NV_ADSP_CONSOLE_MAGIC 'q' + +struct adsp_consol_run_app_arg_t { + uint32_t core_id; + char app_name[NVADSP_NAME_SZ]; + char app_path[NVADSP_NAME_SZ]; + uint32_t args[ARGV_SIZE_IN_WORDS + 1]; + uint64_t ctx1; + uint64_t ctx2; +}; + +#define ADSP_CNSL_LOAD _IO(NV_ADSP_CONSOLE_MAGIC, 0x01) +#define ADSP_CNSL_CLR_BUFFER _IO(NV_ADSP_CONSOLE_MAGIC, 0x02) +#define ADSP_CNSL_PUT_DATA _IOW(NV_ADSP_CONSOLE_MAGIC, 0x03, uint32_t *) +#define ADSP_CNSL_RUN_APP _IOWR(NV_ADSP_CONSOLE_MAGIC, 0x04,\ + struct adsp_consol_run_app_arg_t *) +#define ADSP_CNSL_STOP_APP _IOWR(NV_ADSP_CONSOLE_MAGIC, 0x05,\ + struct adsp_consol_run_app_arg_t *) +#define ADSP_CNSL_OPN_MBX _IOW(NV_ADSP_CONSOLE_MAGIC, 0x06, void *) +#define ADSP_CNSL_CLOSE_MBX _IO(NV_ADSP_CONSOLE_MAGIC, 0x07) +#define ADSP_CNSL_PUT_MBX _IOW(NV_ADSP_CONSOLE_MAGIC, 0x08, uint32_t *) +#define ADSP_CNSL_GET_MBX _IOR(NV_ADSP_CONSOLE_MAGIC, 0x09, uint32_t *) +#define ADSP_CNSL_SUSPEND _IO(NV_ADSP_CONSOLE_MAGIC, 0x0a) +#define ADSP_CNSL_STOP _IO(NV_ADSP_CONSOLE_MAGIC, 0x0b) +#define ADSP_CNSL_RESUME _IO(NV_ADSP_CONSOLE_MAGIC, 0x0c) + +#endif