mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
nvadsp: Add multi-instance support
ADSP host driver is enhanced to be multi-instance
capable and reentrant:
- Trailing unique identifier string in compatible DT property, like
"adsp", "adsp1" or "aon", is used to identify the driver instances
- Each probed driver instance is inserted into a global list, from
which the handle can be fetched using 'nvadsp_get_handle' API
(passing the above unique identifier as argument)
- Above unique identifier is also used as name for the DBFS
directory (containing files like adsp_console, adsp_logger, etc.)
- 'nvadsp_get_handle' is the only exported API; all other APIs are
accessible via function pointers within 'struct nvadsp_handle'
- APIs above maintain one-is-to-one correspondence with all
legacy APIs, with the addition of a new argument
'struct nvadsp_handle *' at the beginning
- Legacy APIs continue to be supported, but they are hardwired to
work only if the kernel probes just one driver instance
- All driver files are cleaned up to not use any global state
variables (necessary for reentrancy)
Bug 3682950
Change-Id: Id5db49e861b2f81716ae8352b36b406654da2bbd
Signed-off-by: Viswanath L <viswanathl@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3092701
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Dara Ramesh <dramesh@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
9458d6b97f
commit
e2a1904d46
@@ -9,7 +9,7 @@ obj-m := nvadsp.o
|
|||||||
nvadsp-objs += dev.o os.o app.o app_loader_linker.o\
|
nvadsp-objs += dev.o os.o app.o app_loader_linker.o\
|
||||||
amc.o nvadsp_shared_sema.o \
|
amc.o nvadsp_shared_sema.o \
|
||||||
hwmailbox.o mailbox.o msgq.o \
|
hwmailbox.o mailbox.o msgq.o \
|
||||||
mem_manager.o aram_manager.o dram_app_mem_manager.o \
|
mem_manager.o aram_manager.o \
|
||||||
acast.o adsp_console_dbfs.o
|
acast.o adsp_console_dbfs.o
|
||||||
|
|
||||||
# T234/T239/T194/T186
|
# T234/T239/T194/T186
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@@ -25,15 +25,9 @@
|
|||||||
|
|
||||||
#define USE_RUN_APP_API
|
#define USE_RUN_APP_API
|
||||||
|
|
||||||
static int open_cnt;
|
|
||||||
|
|
||||||
#define ADSP_APP_CTX_MAX 32
|
|
||||||
|
|
||||||
static uint64_t adsp_app_ctx_vals[ADSP_APP_CTX_MAX];
|
|
||||||
|
|
||||||
#define ACCESS_OK(addr, size) access_ok(addr, size)
|
#define ACCESS_OK(addr, size) access_ok(addr, size)
|
||||||
|
|
||||||
static int adsp_app_ctx_add(uint64_t ctx)
|
static int adsp_app_ctx_add(struct nvadsp_cnsl *console, uint64_t ctx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -41,15 +35,15 @@ static int adsp_app_ctx_add(uint64_t ctx)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < ADSP_APP_CTX_MAX; i++) {
|
for (i = 0; i < ADSP_APP_CTX_MAX; i++) {
|
||||||
if (adsp_app_ctx_vals[i] == 0) {
|
if (console->adsp_app_ctx_vals[i] == 0) {
|
||||||
adsp_app_ctx_vals[i] = ctx;
|
console->adsp_app_ctx_vals[i] = ctx;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int adsp_app_ctx_check(uint64_t ctx)
|
static int adsp_app_ctx_check(struct nvadsp_cnsl *console, uint64_t ctx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -57,20 +51,20 @@ static int adsp_app_ctx_check(uint64_t ctx)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < ADSP_APP_CTX_MAX; i++) {
|
for (i = 0; i < ADSP_APP_CTX_MAX; i++) {
|
||||||
if (adsp_app_ctx_vals[i] == ctx)
|
if (console->adsp_app_ctx_vals[i] == ctx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void adsp_app_ctx_remove(uint64_t ctx)
|
static void adsp_app_ctx_remove(struct nvadsp_cnsl *console, uint64_t ctx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ADSP_APP_CTX_MAX; i++) {
|
for (i = 0; i < ADSP_APP_CTX_MAX; i++) {
|
||||||
if (adsp_app_ctx_vals[i] == ctx) {
|
if (console->adsp_app_ctx_vals[i] == ctx) {
|
||||||
adsp_app_ctx_vals[i] = 0;
|
console->adsp_app_ctx_vals[i] = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,21 +79,23 @@ static int adsp_consol_open(struct inode *i, struct file *f)
|
|||||||
struct device *dev = console->dev;
|
struct device *dev = console->dev;
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
||||||
|
struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle;
|
||||||
|
|
||||||
if (open_cnt)
|
if (console->open_cnt)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
open_cnt++;
|
console->open_cnt++;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
f->private_data = console;
|
f->private_data = console;
|
||||||
if (!drv_data->adsp_os_running)
|
if (!drv_data->adsp_os_running)
|
||||||
goto exit_open;
|
goto exit_open;
|
||||||
ret = nvadsp_mbox_open(&console->shl_snd_mbox, &snd_mbox_id,
|
ret = nvadsp_handle->mbox_open(nvadsp_handle,
|
||||||
|
&console->shl_snd_mbox, &snd_mbox_id,
|
||||||
"adsp_send_cnsl", NULL, NULL);
|
"adsp_send_cnsl", NULL, NULL);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto exit_open;
|
goto exit_open;
|
||||||
pr_err("adsp_consol: Failed to init adsp_consol send mailbox");
|
pr_err("adsp_consol: Failed to init adsp_consol send mailbox");
|
||||||
memset(&console->shl_snd_mbox, 0, sizeof(struct nvadsp_mbox));
|
memset(&console->shl_snd_mbox, 0, sizeof(struct nvadsp_mbox));
|
||||||
open_cnt--;
|
console->open_cnt--;
|
||||||
exit_open:
|
exit_open:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -111,11 +107,12 @@ static int adsp_consol_close(struct inode *i, struct file *f)
|
|||||||
struct device *dev = console->dev;
|
struct device *dev = console->dev;
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
||||||
|
struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle;
|
||||||
|
|
||||||
open_cnt--;
|
console->open_cnt--;
|
||||||
if (!drv_data->adsp_os_running || (0 == mbox->id))
|
if (!drv_data->adsp_os_running || (0 == mbox->id))
|
||||||
goto exit_close;
|
goto exit_close;
|
||||||
ret = nvadsp_mbox_close(mbox);
|
ret = nvadsp_handle->mbox_close(nvadsp_handle, mbox);
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_err("adsp_consol: Failed to close adsp_consol send mailbox)");
|
pr_err("adsp_consol: Failed to close adsp_consol send mailbox)");
|
||||||
memset(mbox, 0, sizeof(struct nvadsp_mbox));
|
memset(mbox, 0, sizeof(struct nvadsp_mbox));
|
||||||
@@ -138,6 +135,7 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
struct device *dev = console->dev;
|
struct device *dev = console->dev;
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
||||||
|
struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle;
|
||||||
void __user *uarg = (void __user *)arg;
|
void __user *uarg = (void __user *)arg;
|
||||||
|
|
||||||
if (_IOC_TYPE(cmd) != NV_ADSP_CONSOLE_MAGIC)
|
if (_IOC_TYPE(cmd) != NV_ADSP_CONSOLE_MAGIC)
|
||||||
@@ -164,17 +162,17 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
break;
|
break;
|
||||||
mbxid = 30;
|
mbxid = 30;
|
||||||
mbox = &console->shl_snd_mbox;
|
mbox = &console->shl_snd_mbox;
|
||||||
ret = nvadsp_os_load();
|
ret = nvadsp_handle->os_load(nvadsp_handle);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_info(dev, "adsp_consol: Load OS Failed.");
|
dev_info(dev, "adsp_consol: Load OS Failed.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = nvadsp_os_start();
|
ret = nvadsp_handle->os_start(nvadsp_handle);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_info(dev, "adsp_consol: Start OS Failed.");
|
dev_info(dev, "adsp_consol: Start OS Failed.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = nvadsp_mbox_open(mbox, &mbxid,
|
ret = nvadsp_handle->mbox_open(nvadsp_handle, mbox, &mbxid,
|
||||||
"adsp_send_cnsl", NULL, NULL);
|
"adsp_send_cnsl", NULL, NULL);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
break;
|
break;
|
||||||
@@ -182,19 +180,19 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
memset(mbox, 0, sizeof(struct nvadsp_mbox));
|
memset(mbox, 0, sizeof(struct nvadsp_mbox));
|
||||||
break;
|
break;
|
||||||
case _IOC_NR(ADSP_CNSL_SUSPEND):
|
case _IOC_NR(ADSP_CNSL_SUSPEND):
|
||||||
ret = nvadsp_os_suspend();
|
ret = nvadsp_handle->os_suspend(nvadsp_handle);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_info(dev, "adsp_consol: OS Suspend Failed.");
|
dev_info(dev, "adsp_consol: OS Suspend Failed.");
|
||||||
break;
|
break;
|
||||||
case _IOC_NR(ADSP_CNSL_STOP):
|
case _IOC_NR(ADSP_CNSL_STOP):
|
||||||
nvadsp_os_stop();
|
nvadsp_handle->os_stop(nvadsp_handle);
|
||||||
break;
|
break;
|
||||||
case _IOC_NR(ADSP_CNSL_RESUME):
|
case _IOC_NR(ADSP_CNSL_RESUME):
|
||||||
if (!drv_data->adsp_os_suspended) {
|
if (!drv_data->adsp_os_suspended) {
|
||||||
dev_info(dev, "adsp_consol: OS is not suspended to perform resume.");
|
dev_info(dev, "adsp_consol: OS is not suspended to perform resume.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = nvadsp_os_start();
|
ret = nvadsp_handle->os_start(nvadsp_handle);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_info(dev, "adsp_consol: OS Resume Failed.");
|
dev_info(dev, "adsp_consol: OS Resume Failed.");
|
||||||
break;
|
break;
|
||||||
@@ -212,7 +210,8 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
app_args.app_name[NVADSP_NAME_SZ_MAX] = '\0';
|
app_args.app_name[NVADSP_NAME_SZ_MAX] = '\0';
|
||||||
|
|
||||||
#ifdef USE_RUN_APP_API
|
#ifdef USE_RUN_APP_API
|
||||||
app_args.ctx2 = (uint64_t)nvadsp_run_app(NULL,
|
app_args.ctx2 = (uint64_t)nvadsp_handle->run_app(
|
||||||
|
nvadsp_handle, NULL,
|
||||||
app_args.app_name,
|
app_args.app_name,
|
||||||
(nvadsp_app_args_t *)&app_args.args[0],
|
(nvadsp_app_args_t *)&app_args.args[0],
|
||||||
NULL, 0, app_args.core_id, true);
|
NULL, 0, app_args.core_id, true);
|
||||||
@@ -221,42 +220,43 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
app_args.app_name);
|
app_args.app_name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (adsp_app_ctx_add(app_args.ctx2)) {
|
if (adsp_app_ctx_add(console, app_args.ctx2)) {
|
||||||
dev_info(dev, "adsp_consol: unable to add %s ctx\n",
|
dev_info(dev, "adsp_consol: unable to add %s ctx\n",
|
||||||
app_args.app_name);
|
app_args.app_name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
app_args.ctx1 = (uint64_t)nvadsp_app_load(app_args.app_path,
|
app_args.ctx1 = (uint64_t)nvadsp_handle->app_load(
|
||||||
app_args.app_name);
|
nvadsp_handle, app_args.app_path,
|
||||||
|
app_args.app_name);
|
||||||
if (!app_args.ctx1) {
|
if (!app_args.ctx1) {
|
||||||
dev_info(dev,
|
dev_info(dev,
|
||||||
"adsp_consol: dynamic app load failed %s\n",
|
"adsp_consol: dynamic app load failed %s\n",
|
||||||
app_args.app_name);
|
app_args.app_name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (adsp_app_ctx_add(app_args.ctx1)) {
|
if (adsp_app_ctx_add(console, app_args.ctx1)) {
|
||||||
dev_info(dev, "adsp_consol: unable to add %s ctx\n",
|
dev_info(dev, "adsp_consol: unable to add %s ctx\n",
|
||||||
app_args.app_name);
|
app_args.app_name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_info(dev, "adsp_consol: calling nvadsp_app_init\n");
|
dev_info(dev, "adsp_consol: calling nvadsp_app_init\n");
|
||||||
app_args.ctx2 =
|
app_args.ctx2 = (uint64_t)nvadsp_handle->app_init(
|
||||||
(uint64_t)nvadsp_app_init((void *)app_args.ctx1, NULL);
|
nvadsp_handle, (void *)app_args.ctx1, NULL);
|
||||||
if (!app_args.ctx2) {
|
if (!app_args.ctx2) {
|
||||||
dev_info(dev,
|
dev_info(dev,
|
||||||
"adsp_consol: unable to initilize the app\n");
|
"adsp_consol: unable to initilize the app\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (adsp_app_ctx_add(app_args.ctx2)) {
|
if (adsp_app_ctx_add(console, app_args.ctx2)) {
|
||||||
dev_info(dev, "adsp_consol: unable to add %s ctx\n",
|
dev_info(dev, "adsp_consol: unable to add %s ctx\n",
|
||||||
app_args.app_name);
|
app_args.app_name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_info(dev, "adsp_consol: calling nvadsp_app_start\n");
|
dev_info(dev, "adsp_consol: calling nvadsp_app_start\n");
|
||||||
ret = nvadsp_app_start((void *)app_args.ctx2);
|
ret = nvadsp_handle->app_start(nvadsp_handle, (void *)app_args.ctx2);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_info(dev, "adsp_consol: unable to start the app\n");
|
dev_info(dev, "adsp_consol: unable to start the app\n");
|
||||||
break;
|
break;
|
||||||
@@ -281,7 +281,7 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (adsp_app_ctx_check(app_args.ctx2)) {
|
if (adsp_app_ctx_check(console, app_args.ctx2)) {
|
||||||
dev_info(dev, "adsp_consol: unable to check %s ctx\n",
|
dev_info(dev, "adsp_consol: unable to check %s ctx\n",
|
||||||
app_args.app_name);
|
app_args.app_name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -290,28 +290,32 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
app_args.ctx1 = (uint64_t)
|
app_args.ctx1 = (uint64_t)
|
||||||
((nvadsp_app_info_t *)app_args.ctx2)->handle;
|
((nvadsp_app_info_t *)app_args.ctx2)->handle;
|
||||||
|
|
||||||
nvadsp_exit_app((nvadsp_app_info_t *)app_args.ctx2, false);
|
nvadsp_handle->exit_app(nvadsp_handle,
|
||||||
nvadsp_app_unload((const void *)app_args.ctx1);
|
(nvadsp_app_info_t *)app_args.ctx2, false);
|
||||||
|
nvadsp_handle->app_unload(nvadsp_handle,
|
||||||
|
(const void *)app_args.ctx1);
|
||||||
|
|
||||||
adsp_app_ctx_remove(app_args.ctx2);
|
adsp_app_ctx_remove(console, app_args.ctx2);
|
||||||
#else
|
#else
|
||||||
if ((!app_args.ctx2) || (!app_args.ctx1)) {
|
if ((!app_args.ctx2) || (!app_args.ctx1)) {
|
||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adsp_app_ctx_check(app_args.ctx2) ||
|
if (adsp_app_ctx_check(console, app_args.ctx2) ||
|
||||||
adsp_app_ctx_check(app_args.ctx1)) {
|
adsp_app_ctx_check(console, app_args.ctx1)) {
|
||||||
dev_info(dev, "adsp_consol: unable to check %s ctx\n",
|
dev_info(dev, "adsp_consol: unable to check %s ctx\n",
|
||||||
app_args.app_name);
|
app_args.app_name);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
nvadsp_app_deinit((void *)app_args.ctx2);
|
nvadsp_handle->app_deinit(nvadsp_handle,
|
||||||
nvadsp_app_unload((void *)app_args.ctx1);
|
(void *)app_args.ctx2);
|
||||||
|
nvadsp_handle->nvadsp_app_unload(nvadsp_handle,
|
||||||
|
(void *)app_args.ctx1);
|
||||||
|
|
||||||
adsp_app_ctx_remove(app_args.ctx2);
|
adsp_app_ctx_remove(console, app_args.ctx2);
|
||||||
adsp_app_ctx_remove(app_args.ctx1);
|
adsp_app_ctx_remove(console, app_args.ctx1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -325,7 +329,7 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (adsp_app_ctx_check(ctx2)) {
|
if (adsp_app_ctx_check(console, ctx2)) {
|
||||||
dev_info(dev, "adsp_consol: unable to check ctx\n");
|
dev_info(dev, "adsp_consol: unable to check ctx\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -338,7 +342,8 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
mbxid = *mid;
|
mbxid = *mid;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nvadsp_mbox_open(&console->app_mbox, &mbxid,
|
ret = nvadsp_handle->mbox_open(nvadsp_handle,
|
||||||
|
&console->app_mbox, &mbxid,
|
||||||
"app_mbox", NULL, NULL);
|
"app_mbox", NULL, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("adsp_consol: Failed to open app mailbox");
|
pr_err("adsp_consol: Failed to open app mailbox");
|
||||||
@@ -347,9 +352,10 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
break;
|
break;
|
||||||
case _IOC_NR(ADSP_CNSL_CLOSE_MBX):
|
case _IOC_NR(ADSP_CNSL_CLOSE_MBX):
|
||||||
mbox = &console->app_mbox;
|
mbox = &console->app_mbox;
|
||||||
while (!nvadsp_mbox_recv(mbox, &data, 0, 0))
|
while (!nvadsp_handle->mbox_recv(nvadsp_handle,
|
||||||
|
mbox, &data, 0, 0))
|
||||||
;
|
;
|
||||||
ret = nvadsp_mbox_close(mbox);
|
ret = nvadsp_handle->mbox_close(nvadsp_handle, mbox);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
memset(mbox, 0, sizeof(struct nvadsp_mbox));
|
memset(mbox, 0, sizeof(struct nvadsp_mbox));
|
||||||
@@ -363,13 +369,15 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = nvadsp_mbox_send(&console->app_mbox, data,
|
ret = nvadsp_handle->mbox_send(nvadsp_handle,
|
||||||
|
&console->app_mbox, data,
|
||||||
NVADSP_MBOX_SMSG, 0, 0);
|
NVADSP_MBOX_SMSG, 0, 0);
|
||||||
break;
|
break;
|
||||||
case _IOC_NR(ADSP_CNSL_GET_MBX):
|
case _IOC_NR(ADSP_CNSL_GET_MBX):
|
||||||
if (!ACCESS_OK(uarg, sizeof(uint32_t)))
|
if (!ACCESS_OK(uarg, sizeof(uint32_t)))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
ret = nvadsp_mbox_recv(&console->app_mbox, &data, 0, 0);
|
ret = nvadsp_handle->mbox_recv(nvadsp_handle,
|
||||||
|
&console->app_mbox, &data, 0, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
ret = copy_to_user(uarg, &data,
|
ret = copy_to_user(uarg, &data,
|
||||||
@@ -385,7 +393,8 @@ adsp_consol_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
|||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return nvadsp_mbox_send(&console->shl_snd_mbox, data,
|
return nvadsp_handle->mbox_send(nvadsp_handle,
|
||||||
|
&console->shl_snd_mbox, data,
|
||||||
NVADSP_MBOX_SMSG, 0, 0);
|
NVADSP_MBOX_SMSG, 0, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ADSP_CNSL_DBFS_H
|
#ifndef ADSP_CNSL_DBFS_H
|
||||||
#define ADSP_CNSL_DBFS_H
|
#define ADSP_CNSL_DBFS_H
|
||||||
|
|
||||||
|
#define ADSP_APP_CTX_MAX 32
|
||||||
|
|
||||||
struct nvadsp_cnsl {
|
struct nvadsp_cnsl {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct nvadsp_mbox shl_snd_mbox;
|
struct nvadsp_mbox shl_snd_mbox;
|
||||||
struct nvadsp_mbox app_mbox;
|
struct nvadsp_mbox app_mbox;
|
||||||
|
int open_cnt;
|
||||||
|
uint64_t adsp_app_ctx_vals[ADSP_APP_CTX_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
@@ -10,19 +10,17 @@
|
|||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
#include "amc.h"
|
#include "amc.h"
|
||||||
|
|
||||||
static struct platform_device *nvadsp_pdev;
|
static inline u32 amc_readl(struct nvadsp_drv_data *drv, u32 reg)
|
||||||
static struct nvadsp_drv_data *nvadsp_drv_data;
|
|
||||||
|
|
||||||
static inline u32 amc_readl(u32 reg)
|
|
||||||
{
|
{
|
||||||
return readl(nvadsp_drv_data->base_regs[AMC] + reg);
|
return readl(drv->base_regs[AMC] + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void amc_writel(u32 val, u32 reg)
|
static inline void amc_writel(struct nvadsp_drv_data *drv, u32 val, u32 reg)
|
||||||
{
|
{
|
||||||
writel(val, nvadsp_drv_data->base_regs[AMC] + reg);
|
writel(val, drv->base_regs[AMC] + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_AMC_SAVE_RESTORE
|
||||||
static void wmemcpy_to_aram(u32 to_aram, const u32 *from_mem, size_t wlen)
|
static void wmemcpy_to_aram(u32 to_aram, const u32 *from_mem, size_t wlen)
|
||||||
{
|
{
|
||||||
u32 base, offset;
|
u32 base, offset;
|
||||||
@@ -116,20 +114,23 @@ int nvadsp_amc_restore(struct platform_device *pdev)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_AMC_SAVE_RESTORE */
|
||||||
|
|
||||||
static irqreturn_t nvadsp_amc_error_int_handler(int irq, void *devid)
|
static irqreturn_t nvadsp_amc_error_int_handler(int irq, void *devid)
|
||||||
{
|
{
|
||||||
|
struct platform_device *pdev = devid;
|
||||||
|
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
||||||
u32 val, addr, status, intr = 0;
|
u32 val, addr, status, intr = 0;
|
||||||
|
|
||||||
status = amc_readl(AMC_INT_STATUS);
|
status = amc_readl(drv, AMC_INT_STATUS);
|
||||||
addr = amc_readl(AMC_ERROR_ADDR);
|
addr = amc_readl(drv, AMC_ERROR_ADDR);
|
||||||
|
|
||||||
if (status & AMC_INT_STATUS_ARAM) {
|
if (status & AMC_INT_STATUS_ARAM) {
|
||||||
/*
|
/*
|
||||||
* Ignore addresses lesser than AMC_ERROR_ADDR_IGNORE (4k)
|
* Ignore addresses lesser than AMC_ERROR_ADDR_IGNORE (4k)
|
||||||
* as those are spurious ones due a hardware issue.
|
* as those are spurious ones due a hardware issue.
|
||||||
*/
|
*/
|
||||||
if (!(nvadsp_drv_data->chip_data->amc_err_war) ||
|
if (!(drv->chip_data->amc_err_war) ||
|
||||||
(addr > AMC_ERROR_ADDR_IGNORE))
|
(addr > AMC_ERROR_ADDR_IGNORE))
|
||||||
pr_info("nvadsp: invalid ARAM access. address: 0x%x\n",
|
pr_info("nvadsp: invalid ARAM access. address: 0x%x\n",
|
||||||
addr);
|
addr);
|
||||||
@@ -143,9 +144,9 @@ static irqreturn_t nvadsp_amc_error_int_handler(int irq, void *devid)
|
|||||||
intr |= AMC_INT_INVALID_REG_ACCESS;
|
intr |= AMC_INT_INVALID_REG_ACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = amc_readl(AMC_INT_CLR);
|
val = amc_readl(drv, AMC_INT_CLR);
|
||||||
val |= intr;
|
val |= intr;
|
||||||
amc_writel(val, AMC_INT_CLR);
|
amc_writel(drv, val, AMC_INT_CLR);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
@@ -154,13 +155,10 @@ void nvadsp_free_amc_interrupts(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct device_node *node;
|
|
||||||
|
|
||||||
if (drv->chip_data->amc_not_avlbl)
|
if (drv->chip_data->amc_not_avlbl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
node = dev->of_node;
|
|
||||||
|
|
||||||
if (!is_tegra_hypervisor_mode())
|
if (!is_tegra_hypervisor_mode())
|
||||||
devm_free_irq(dev, drv->agic_irqs[AMC_ERR_VIRQ], pdev);
|
devm_free_irq(dev, drv->agic_irqs[AMC_ERR_VIRQ], pdev);
|
||||||
}
|
}
|
||||||
@@ -169,16 +167,11 @@ int nvadsp_setup_amc_interrupts(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct device_node *node;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (drv->chip_data->amc_not_avlbl)
|
if (drv->chip_data->amc_not_avlbl)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
node = dev->of_node;
|
|
||||||
nvadsp_pdev = pdev;
|
|
||||||
nvadsp_drv_data = drv;
|
|
||||||
|
|
||||||
if (!is_tegra_hypervisor_mode())
|
if (!is_tegra_hypervisor_mode())
|
||||||
ret = devm_request_irq(dev, drv->agic_irqs[AMC_ERR_VIRQ],
|
ret = devm_request_irq(dev, drv->agic_irqs[AMC_ERR_VIRQ],
|
||||||
nvadsp_amc_error_int_handler, 0,
|
nvadsp_amc_error_int_handler, 0,
|
||||||
|
|||||||
@@ -50,9 +50,8 @@ struct nvadsp_app_priv_struct {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nvadsp_app_priv_struct priv;
|
static void delete_app_instance(struct nvadsp_app_priv_struct *,
|
||||||
|
nvadsp_app_info_t *);
|
||||||
static void delete_app_instance(nvadsp_app_info_t *);
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
static int dump_binary_in_2bytes_app_file_node(struct seq_file *s, void *data)
|
static int dump_binary_in_2bytes_app_file_node(struct seq_file *s, void *data)
|
||||||
@@ -219,17 +218,18 @@ ADSP_APP_FILE_OPERATION(dram_shared_wc);
|
|||||||
ADSP_APP_FILE_OPERATION(aram);
|
ADSP_APP_FILE_OPERATION(aram);
|
||||||
ADSP_APP_FILE_OPERATION(aram_exclusive);
|
ADSP_APP_FILE_OPERATION(aram_exclusive);
|
||||||
|
|
||||||
static int create_adsp_app_debugfs(struct nvadsp_app_service *ser)
|
static int create_adsp_app_debugfs(struct nvadsp_app_priv_struct *priv,
|
||||||
|
struct nvadsp_app_service *ser)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct app_mem_size *mem_size = (struct app_mem_size *)ser->mem_size;
|
struct app_mem_size *mem_size = (struct app_mem_size *)ser->mem_size;
|
||||||
struct device *dev = &priv.pdev->dev;
|
struct device *dev = &priv->pdev->dev;
|
||||||
struct dentry *instance_mem_sizes;
|
struct dentry *instance_mem_sizes;
|
||||||
struct dentry *root;
|
struct dentry *root;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
root = debugfs_create_dir(ser->name,
|
root = debugfs_create_dir(ser->name,
|
||||||
priv.adsp_app_debugfs_root);
|
priv->adsp_app_debugfs_root);
|
||||||
if (IS_ERR_OR_NULL(root)) {
|
if (IS_ERR_OR_NULL(root)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
@@ -256,19 +256,27 @@ err_out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init adsp_app_debug_init(struct dentry *root)
|
static int __init adsp_app_debug_init(struct nvadsp_app_priv_struct *priv,
|
||||||
|
struct dentry *root)
|
||||||
{
|
{
|
||||||
priv.adsp_app_debugfs_root = debugfs_create_dir("adsp_apps", root);
|
priv->adsp_app_debugfs_root = debugfs_create_dir("adsp_apps", root);
|
||||||
return IS_ERR_OR_NULL(priv.adsp_app_debugfs_root) ? -ENOMEM : 0;
|
return IS_ERR_OR_NULL(priv->adsp_app_debugfs_root) ? -ENOMEM : 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_DEBUG_FS */
|
#endif /* CONFIG_DEBUG_FS */
|
||||||
|
|
||||||
static struct nvadsp_app_service *get_loaded_service(const char *appfile)
|
static void _nvadsp_set_app_complete_cb(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *info, app_complete_status_notifier notifier)
|
||||||
{
|
{
|
||||||
struct device *dev = &priv.pdev->dev;
|
info->complete_status_notifier = notifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nvadsp_app_service *get_loaded_service(
|
||||||
|
struct nvadsp_app_priv_struct *priv, const char *appfile)
|
||||||
|
{
|
||||||
|
struct device *dev = &priv->pdev->dev;
|
||||||
struct nvadsp_app_service *ser;
|
struct nvadsp_app_service *ser;
|
||||||
|
|
||||||
list_for_each_entry(ser, &priv.service_list, node) {
|
list_for_each_entry(ser, &priv->service_list, node) {
|
||||||
if (!strcmp(appfile, ser->name)) {
|
if (!strcmp(appfile, ser->name)) {
|
||||||
dev_dbg(dev, "module %s already loaded\n", appfile);
|
dev_dbg(dev, "module %s already loaded\n", appfile);
|
||||||
return ser;
|
return ser;
|
||||||
@@ -287,18 +295,18 @@ static inline void extract_appname(char *appname, const char *appfile)
|
|||||||
appname[len] = '\0';
|
appname[len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static nvadsp_app_handle_t app_load(const char *appfile,
|
static nvadsp_app_handle_t app_load(struct nvadsp_app_priv_struct *priv,
|
||||||
struct adsp_shared_app *shared_app, bool dynamic)
|
const char *appfile, struct adsp_shared_app *shared_app, bool dynamic)
|
||||||
{
|
{
|
||||||
struct nvadsp_drv_data *drv_data;
|
struct nvadsp_drv_data *drv_data;
|
||||||
struct device *dev = &priv.pdev->dev;
|
struct device *dev = &priv->pdev->dev;
|
||||||
char appname[NVADSP_NAME_SZ] = { };
|
char appname[NVADSP_NAME_SZ] = { };
|
||||||
struct nvadsp_app_service *ser;
|
struct nvadsp_app_service *ser;
|
||||||
|
|
||||||
drv_data = platform_get_drvdata(priv.pdev);
|
drv_data = platform_get_drvdata(priv->pdev);
|
||||||
extract_appname(appname, appfile);
|
extract_appname(appname, appfile);
|
||||||
mutex_lock(&priv.service_lock_list);
|
mutex_lock(&priv->service_lock_list);
|
||||||
ser = get_loaded_service(appname);
|
ser = get_loaded_service(priv, appname);
|
||||||
if (!ser) {
|
if (!ser) {
|
||||||
|
|
||||||
/* dynamic loading is disabled when running in secure mode */
|
/* dynamic loading is disabled when running in secure mode */
|
||||||
@@ -329,78 +337,85 @@ static nvadsp_app_handle_t app_load(const char *appfile,
|
|||||||
INIT_LIST_HEAD(&ser->app_head);
|
INIT_LIST_HEAD(&ser->app_head);
|
||||||
|
|
||||||
/* add the app instance service to the list */
|
/* add the app instance service to the list */
|
||||||
list_add_tail(&ser->node, &priv.service_list);
|
list_add_tail(&ser->node, &priv->service_list);
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
create_adsp_app_debugfs(ser);
|
create_adsp_app_debugfs(priv, ser);
|
||||||
#endif
|
#endif
|
||||||
dev_dbg(dev, "loaded app %s\n", ser->name);
|
dev_dbg(dev, "loaded app %s\n", ser->name);
|
||||||
}
|
}
|
||||||
mutex_unlock(&priv.service_lock_list);
|
mutex_unlock(&priv->service_lock_list);
|
||||||
|
|
||||||
return ser;
|
return ser;
|
||||||
|
|
||||||
err_free_service:
|
err_free_service:
|
||||||
devm_kfree(dev, ser);
|
devm_kfree(dev, ser);
|
||||||
err:
|
err:
|
||||||
mutex_unlock(&priv.service_lock_list);
|
mutex_unlock(&priv->service_lock_list);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nvadsp_app_handle_t _nvadsp_app_load(struct nvadsp_handle *nvadsp_handle,
|
||||||
nvadsp_app_handle_t nvadsp_app_load(const char *appname, const char *appfile)
|
const char *appname, const char *appfile)
|
||||||
{
|
{
|
||||||
struct nvadsp_drv_data *drv_data;
|
struct nvadsp_drv_data *drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(priv.pdev)) {
|
if (!drv_data || !drv_data->pdev || !drv_data->app_priv) {
|
||||||
pr_err("ADSP Driver is not initialized\n");
|
pr_err("ADSP Driver is not initialized\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
drv_data = platform_get_drvdata(priv.pdev);
|
|
||||||
|
|
||||||
if (!drv_data->adsp_os_running)
|
if (!drv_data->adsp_os_running)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return app_load(appfile, NULL, true);
|
return app_load(drv_data->app_priv, appfile, NULL, true);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_app_load);
|
|
||||||
|
|
||||||
static void free_instance_memory(nvadsp_app_info_t *app,
|
static void free_instance_memory(struct nvadsp_app_priv_struct *priv,
|
||||||
const struct app_mem_size *sz)
|
nvadsp_app_info_t *app, const struct app_mem_size *sz)
|
||||||
{
|
{
|
||||||
adsp_app_mem_t *mem = &app->mem;
|
adsp_app_mem_t *mem = &app->mem;
|
||||||
adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
|
adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
|
||||||
|
struct nvadsp_drv_data *drv_data;
|
||||||
|
struct nvadsp_handle *nvadsp_handle;
|
||||||
|
|
||||||
|
drv_data = platform_get_drvdata(priv->pdev);
|
||||||
|
nvadsp_handle = &drv_data->nvadsp_handle;
|
||||||
|
|
||||||
if (mem->dram) {
|
if (mem->dram) {
|
||||||
nvadsp_free_coherent(sz->dram, mem->dram, iova_mem->dram);
|
nvadsp_handle->free_coherent(nvadsp_handle,
|
||||||
|
sz->dram, mem->dram, iova_mem->dram);
|
||||||
mem->dram = NULL;
|
mem->dram = NULL;
|
||||||
iova_mem->dram = 0;
|
iova_mem->dram = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem->shared) {
|
if (mem->shared) {
|
||||||
nvadsp_free_coherent(sz->dram_shared, mem->shared,
|
nvadsp_handle->free_coherent(nvadsp_handle,
|
||||||
|
sz->dram_shared, mem->shared,
|
||||||
iova_mem->shared);
|
iova_mem->shared);
|
||||||
mem->shared = NULL;
|
mem->shared = NULL;
|
||||||
iova_mem->shared = 0;
|
iova_mem->shared = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem->shared_wc) {
|
if (mem->shared_wc) {
|
||||||
nvadsp_free_coherent(sz->dram_shared_wc, mem->shared_wc,
|
nvadsp_handle->free_coherent(nvadsp_handle,
|
||||||
|
sz->dram_shared_wc, mem->shared_wc,
|
||||||
iova_mem->shared_wc);
|
iova_mem->shared_wc);
|
||||||
mem->shared_wc = NULL;
|
mem->shared_wc = NULL;
|
||||||
iova_mem->shared_wc = 0;
|
iova_mem->shared_wc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem->aram_flag)
|
if (mem->aram_flag)
|
||||||
nvadsp_aram_release(mem->aram);
|
nvadsp_aram_release(drv_data->aram_handle, mem->aram);
|
||||||
else if (mem->aram)
|
else if (mem->aram)
|
||||||
nvadsp_free_coherent(sz->aram, mem->aram, iova_mem->aram);
|
nvadsp_handle->free_coherent(nvadsp_handle,
|
||||||
|
sz->aram, mem->aram, iova_mem->aram);
|
||||||
mem->aram = NULL;
|
mem->aram = NULL;
|
||||||
iova_mem->aram = 0;
|
iova_mem->aram = 0;
|
||||||
mem->aram_flag = 0;
|
mem->aram_flag = 0;
|
||||||
|
|
||||||
if (mem->aram_x_flag) {
|
if (mem->aram_x_flag) {
|
||||||
nvadsp_aram_release(mem->aram_x);
|
nvadsp_aram_release(drv_data->aram_handle, mem->aram_x);
|
||||||
mem->aram_x = NULL;
|
mem->aram_x = NULL;
|
||||||
iova_mem->aram_x = 0;
|
iova_mem->aram_x = 0;
|
||||||
mem->aram_flag = 0;
|
mem->aram_flag = 0;
|
||||||
@@ -408,12 +423,14 @@ static void free_instance_memory(nvadsp_app_info_t *app,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int create_instance_memory(nvadsp_app_info_t *app,
|
static int create_instance_memory(struct nvadsp_app_priv_struct *priv,
|
||||||
const struct app_mem_size *sz)
|
nvadsp_app_info_t *app, const struct app_mem_size *sz)
|
||||||
{
|
{
|
||||||
adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
|
adsp_app_iova_mem_t *iova_mem = &app->iova_mem;
|
||||||
struct device *dev = &priv.pdev->dev;
|
struct device *dev = &priv->pdev->dev;
|
||||||
adsp_app_mem_t *mem = &app->mem;
|
adsp_app_mem_t *mem = &app->mem;
|
||||||
|
struct nvadsp_drv_data *drv_data;
|
||||||
|
struct nvadsp_handle *nvadsp_handle;
|
||||||
char name[NVADSP_NAME_SZ];
|
char name[NVADSP_NAME_SZ];
|
||||||
void *aram_handle;
|
void *aram_handle;
|
||||||
dma_addr_t da;
|
dma_addr_t da;
|
||||||
@@ -425,8 +442,12 @@ static int create_instance_memory(nvadsp_app_info_t *app,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drv_data = platform_get_drvdata(priv->pdev);
|
||||||
|
nvadsp_handle = &drv_data->nvadsp_handle;
|
||||||
|
|
||||||
if (sz->dram) {
|
if (sz->dram) {
|
||||||
mem->dram = nvadsp_alloc_coherent(sz->dram, &da, GFP_KERNEL);
|
mem->dram = nvadsp_handle->alloc_coherent(nvadsp_handle,
|
||||||
|
sz->dram, &da, GFP_KERNEL);
|
||||||
iova_mem->dram = (uint32_t)da;
|
iova_mem->dram = (uint32_t)da;
|
||||||
if (!mem->dram) {
|
if (!mem->dram) {
|
||||||
dev_err(dev, "app %s dram alloc failed\n",
|
dev_err(dev, "app %s dram alloc failed\n",
|
||||||
@@ -438,8 +459,8 @@ static int create_instance_memory(nvadsp_app_info_t *app,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sz->dram_shared) {
|
if (sz->dram_shared) {
|
||||||
mem->shared = nvadsp_alloc_coherent(sz->dram_shared,
|
mem->shared = nvadsp_handle->alloc_coherent(nvadsp_handle,
|
||||||
&da, GFP_KERNEL);
|
sz->dram_shared, &da, GFP_KERNEL);
|
||||||
if (!mem->shared) {
|
if (!mem->shared) {
|
||||||
dev_err(dev, "app %s shared dram alloc failed\n",
|
dev_err(dev, "app %s shared dram alloc failed\n",
|
||||||
name);
|
name);
|
||||||
@@ -451,8 +472,8 @@ static int create_instance_memory(nvadsp_app_info_t *app,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sz->dram_shared_wc) {
|
if (sz->dram_shared_wc) {
|
||||||
mem->shared_wc = nvadsp_alloc_coherent(sz->dram_shared_wc,
|
mem->shared_wc = nvadsp_handle->alloc_coherent(nvadsp_handle,
|
||||||
&da, GFP_KERNEL);
|
sz->dram_shared_wc, &da, GFP_KERNEL);
|
||||||
if (!mem->shared_wc) {
|
if (!mem->shared_wc) {
|
||||||
dev_err(dev, "app %s shared dram wc alloc failed\n",
|
dev_err(dev, "app %s shared dram wc alloc failed\n",
|
||||||
name);
|
name);
|
||||||
@@ -464,7 +485,8 @@ static int create_instance_memory(nvadsp_app_info_t *app,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sz->aram) {
|
if (sz->aram) {
|
||||||
aram_handle = nvadsp_aram_request(name, sz->aram);
|
aram_handle = nvadsp_aram_request(drv_data->aram_handle,
|
||||||
|
name, sz->aram);
|
||||||
if (!IS_ERR_OR_NULL(aram_handle)) {
|
if (!IS_ERR_OR_NULL(aram_handle)) {
|
||||||
iova_mem->aram = nvadsp_aram_get_address(aram_handle);
|
iova_mem->aram = nvadsp_aram_get_address(aram_handle);
|
||||||
mem->aram = aram_handle;
|
mem->aram = aram_handle;
|
||||||
@@ -473,8 +495,9 @@ static int create_instance_memory(nvadsp_app_info_t *app,
|
|||||||
} else {
|
} else {
|
||||||
dev_dbg(dev, "app %s no ARAM memory ! using DRAM\n",
|
dev_dbg(dev, "app %s no ARAM memory ! using DRAM\n",
|
||||||
name);
|
name);
|
||||||
mem->aram = nvadsp_alloc_coherent(sz->aram,
|
mem->aram = nvadsp_handle->alloc_coherent(
|
||||||
&da, GFP_KERNEL);
|
nvadsp_handle, sz->aram,
|
||||||
|
&da, GFP_KERNEL);
|
||||||
if (!mem->aram) {
|
if (!mem->aram) {
|
||||||
iova_mem->aram_flag = mem->aram_flag = 0;
|
iova_mem->aram_flag = mem->aram_flag = 0;
|
||||||
dev_err(dev,
|
dev_err(dev,
|
||||||
@@ -489,7 +512,8 @@ static int create_instance_memory(nvadsp_app_info_t *app,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sz->aram_x) {
|
if (sz->aram_x) {
|
||||||
aram_handle = nvadsp_aram_request(name, sz->aram);
|
aram_handle = nvadsp_aram_request(drv_data->aram_handle,
|
||||||
|
name, sz->aram);
|
||||||
if (!IS_ERR_OR_NULL(aram_handle)) {
|
if (!IS_ERR_OR_NULL(aram_handle)) {
|
||||||
iova_mem->aram_x = nvadsp_aram_get_address(aram_handle);
|
iova_mem->aram_x = nvadsp_aram_get_address(aram_handle);
|
||||||
mem->aram_x = aram_handle;
|
mem->aram_x = aram_handle;
|
||||||
@@ -505,7 +529,7 @@ static int create_instance_memory(nvadsp_app_info_t *app,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
free_instance_memory(app, sz);
|
free_instance_memory(priv, app, sz);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,14 +562,17 @@ static void fill_app_instance_data(nvadsp_app_info_t *app,
|
|||||||
memcpy(&data->mem_size, ser->mem_size, sizeof(struct app_mem_size));
|
memcpy(&data->mem_size, ser->mem_size, sizeof(struct app_mem_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
static nvadsp_app_info_t *create_app_instance(nvadsp_app_handle_t handle,
|
static nvadsp_app_info_t *create_app_instance(
|
||||||
|
struct nvadsp_app_priv_struct *priv, nvadsp_app_handle_t handle,
|
||||||
nvadsp_app_args_t *app_args, struct run_app_instance_data *data,
|
nvadsp_app_args_t *app_args, struct run_app_instance_data *data,
|
||||||
app_complete_status_notifier notifier, uint32_t stack_size,
|
app_complete_status_notifier notifier, uint32_t stack_size,
|
||||||
uint32_t core_id)
|
uint32_t core_id)
|
||||||
{
|
{
|
||||||
struct nvadsp_app_service *ser = (void *)handle;
|
struct nvadsp_app_service *ser = (void *)handle;
|
||||||
struct device *dev = &priv.pdev->dev;
|
struct device *dev = &priv->pdev->dev;
|
||||||
nvadsp_app_info_t *app;
|
nvadsp_app_info_t *app;
|
||||||
|
struct nvadsp_drv_data *drv_data;
|
||||||
|
struct nvadsp_handle *nvadsp_handle;
|
||||||
int *state;
|
int *state;
|
||||||
int *id;
|
int *id;
|
||||||
|
|
||||||
@@ -565,8 +592,11 @@ static nvadsp_app_info_t *create_app_instance(nvadsp_app_handle_t handle,
|
|||||||
*/
|
*/
|
||||||
app->handle = ser;
|
app->handle = ser;
|
||||||
|
|
||||||
|
drv_data = platform_get_drvdata(priv->pdev);
|
||||||
|
nvadsp_handle = &drv_data->nvadsp_handle;
|
||||||
|
|
||||||
/* create the instance memory required by the app instance */
|
/* create the instance memory required by the app instance */
|
||||||
if (create_instance_memory(app, ser->mem_size)) {
|
if (create_instance_memory(priv, app, ser->mem_size)) {
|
||||||
dev_err(dev, "instance creation failed for app %s:%d\n",
|
dev_err(dev, "instance creation failed for app %s:%d\n",
|
||||||
app->name, app->instance_id);
|
app->name, app->instance_id);
|
||||||
goto free_app;
|
goto free_app;
|
||||||
@@ -591,7 +621,7 @@ static nvadsp_app_info_t *create_app_instance(nvadsp_app_handle_t handle,
|
|||||||
|
|
||||||
init_completion(&app->wait_for_app_start);
|
init_completion(&app->wait_for_app_start);
|
||||||
init_completion(&app->wait_for_app_complete);
|
init_completion(&app->wait_for_app_complete);
|
||||||
set_app_complete_notifier(app, notifier);
|
_nvadsp_set_app_complete_cb(nvadsp_handle, app, notifier);
|
||||||
|
|
||||||
dev_dbg(dev, "app %s instance %d initilized\n",
|
dev_dbg(dev, "app %s instance %d initilized\n",
|
||||||
app->name, app->instance_id);
|
app->name, app->instance_id);
|
||||||
@@ -606,25 +636,27 @@ end:
|
|||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle,
|
static nvadsp_app_info_t *_nvadsp_app_init(struct nvadsp_handle *nvadsp_handle,
|
||||||
nvadsp_app_args_t *args)
|
nvadsp_app_handle_t handle, nvadsp_app_args_t *args)
|
||||||
{
|
{
|
||||||
struct nvadsp_app_shared_msg_pool *msg_pool;
|
struct nvadsp_app_shared_msg_pool *msg_pool;
|
||||||
struct nvadsp_shared_mem *shared_mem;
|
struct nvadsp_shared_mem *shared_mem;
|
||||||
union app_loader_message *message;
|
union app_loader_message *message;
|
||||||
struct nvadsp_drv_data *drv_data;
|
struct nvadsp_drv_data *drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
|
struct nvadsp_app_priv_struct *priv;
|
||||||
struct app_loader_data *data;
|
struct app_loader_data *data;
|
||||||
nvadsp_app_info_t *app;
|
nvadsp_app_info_t *app;
|
||||||
msgq_t *msgq_send;
|
msgq_t *msgq_send;
|
||||||
int *state;
|
int *state;
|
||||||
unsigned long flags, ret = 0;
|
unsigned long flags, ret = 0;
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(priv.pdev)) {
|
if (!drv_data || !drv_data->pdev || !drv_data->app_priv) {
|
||||||
pr_err("ADSP Driver is not initialized\n");
|
pr_err("ADSP Driver is not initialized\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
drv_data = platform_get_drvdata(priv.pdev);
|
priv = drv_data->app_priv;
|
||||||
|
|
||||||
if (!drv_data->adsp_os_running) {
|
if (!drv_data->adsp_os_running) {
|
||||||
pr_err("ADSP is not running\n");
|
pr_err("ADSP is not running\n");
|
||||||
@@ -648,7 +680,8 @@ nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle,
|
|||||||
data = &message->data;
|
data = &message->data;
|
||||||
|
|
||||||
/* Pinning app to core 0 by default */
|
/* Pinning app to core 0 by default */
|
||||||
app = create_app_instance(handle, args, &data->app_init, NULL, 0, 0);
|
app = create_app_instance(drv_data->app_priv, handle,
|
||||||
|
args, &data->app_init, NULL, 0, 0);
|
||||||
if (IS_ERR_OR_NULL(app)) {
|
if (IS_ERR_OR_NULL(app)) {
|
||||||
pr_err("Failed to create APP instance\n");
|
pr_err("Failed to create APP instance\n");
|
||||||
kfree(message);
|
kfree(message);
|
||||||
@@ -668,12 +701,13 @@ nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle,
|
|||||||
*state = NVADSP_APP_STATE_STARTED;
|
*state = NVADSP_APP_STATE_STARTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
nvadsp_mbox_send(&priv.mbox, 0, NVADSP_MBOX_SMSG, false, 0);
|
nvadsp_handle->mbox_send(nvadsp_handle, &priv->mbox,
|
||||||
|
0, NVADSP_MBOX_SMSG, false, 0);
|
||||||
|
|
||||||
ret = wait_for_completion_timeout(&app->wait_for_app_start,
|
ret = wait_for_completion_timeout(&app->wait_for_app_start,
|
||||||
msecs_to_jiffies(ADSP_APP_INIT_TIMEOUT));
|
msecs_to_jiffies(ADSP_APP_INIT_TIMEOUT));
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
delete_app_instance(app);
|
delete_app_instance(drv_data->app_priv, app);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
init_completion(&app->wait_for_app_start);
|
init_completion(&app->wait_for_app_start);
|
||||||
@@ -681,20 +715,23 @@ nvadsp_app_info_t __must_check *nvadsp_app_init(nvadsp_app_handle_t handle,
|
|||||||
err:
|
err:
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_app_init);
|
|
||||||
|
|
||||||
static int start_app_on_adsp(nvadsp_app_info_t *app,
|
static int start_app_on_adsp(struct nvadsp_app_priv_struct *priv,
|
||||||
union app_loader_message *message, bool block)
|
nvadsp_app_info_t *app,
|
||||||
|
union app_loader_message *message, bool block)
|
||||||
{
|
{
|
||||||
struct nvadsp_app_shared_msg_pool *msg_pool;
|
struct nvadsp_app_shared_msg_pool *msg_pool;
|
||||||
struct device *dev = &priv.pdev->dev;
|
struct device *dev = &priv->pdev->dev;
|
||||||
struct nvadsp_shared_mem *shared_mem;
|
struct nvadsp_shared_mem *shared_mem;
|
||||||
struct nvadsp_drv_data *drv_data;
|
|
||||||
msgq_t *msgq_send;
|
msgq_t *msgq_send;
|
||||||
|
struct nvadsp_drv_data *drv_data;
|
||||||
|
struct nvadsp_handle *nvadsp_handle;
|
||||||
int *state;
|
int *state;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
drv_data = platform_get_drvdata(priv.pdev);
|
drv_data = platform_get_drvdata(priv->pdev);
|
||||||
|
nvadsp_handle = &drv_data->nvadsp_handle;
|
||||||
|
|
||||||
shared_mem = drv_data->shared_adsp_os_data;
|
shared_mem = drv_data->shared_adsp_os_data;
|
||||||
msg_pool = &shared_mem->app_shared_msg_pool;
|
msg_pool = &shared_mem->app_shared_msg_pool;
|
||||||
msgq_send = &msg_pool->app_loader_send_message.msgq;
|
msgq_send = &msg_pool->app_loader_send_message.msgq;
|
||||||
@@ -708,7 +745,8 @@ static int start_app_on_adsp(nvadsp_app_info_t *app,
|
|||||||
state = (int *)&app->state;
|
state = (int *)&app->state;
|
||||||
*state = NVADSP_APP_STATE_STARTED;
|
*state = NVADSP_APP_STATE_STARTED;
|
||||||
|
|
||||||
nvadsp_mbox_send(&priv.mbox, 0, NVADSP_MBOX_SMSG, false, 0);
|
nvadsp_handle->mbox_send(nvadsp_handle, &priv->mbox,
|
||||||
|
0, NVADSP_MBOX_SMSG, false, 0);
|
||||||
|
|
||||||
if (block) {
|
if (block) {
|
||||||
wait_for_completion(&app->wait_for_app_start);
|
wait_for_completion(&app->wait_for_app_start);
|
||||||
@@ -723,56 +761,58 @@ static int start_app_on_adsp(nvadsp_app_info_t *app,
|
|||||||
return app->return_status;
|
return app->return_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nvadsp_app_start(nvadsp_app_info_t *app)
|
static int _nvadsp_app_start(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *app)
|
||||||
{
|
{
|
||||||
union app_loader_message *message = app->priv;
|
union app_loader_message *message = app->priv;
|
||||||
struct app_loader_data *data = &message->data;
|
struct app_loader_data *data = &message->data;
|
||||||
struct nvadsp_drv_data *drv_data;
|
struct nvadsp_drv_data *drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(app))
|
if (IS_ERR_OR_NULL(app))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(priv.pdev)) {
|
if (!drv_data || !drv_data->pdev || !drv_data->app_priv) {
|
||||||
pr_err("ADSP Driver is not initialized\n");
|
pr_err("ADSP Driver is not initialized\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
drv_data = platform_get_drvdata(priv.pdev);
|
|
||||||
|
|
||||||
if (!drv_data->adsp_os_running)
|
if (!drv_data->adsp_os_running)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
data->app_init.message = ADSP_APP_START;
|
data->app_init.message = ADSP_APP_START;
|
||||||
data->app_init.adsp_ref = app->token;
|
data->app_init.adsp_ref = app->token;
|
||||||
data->app_init.stack_size = app->stack_size;
|
data->app_init.stack_size = app->stack_size;
|
||||||
ret = start_app_on_adsp(app, app->priv, true);
|
ret = start_app_on_adsp(drv_data->app_priv, app, app->priv, true);
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_app_start);
|
|
||||||
|
|
||||||
nvadsp_app_info_t *nvadsp_run_app(nvadsp_os_handle_t os_handle,
|
static nvadsp_app_info_t *_nvadsp_run_app(struct nvadsp_handle *nvadsp_handle,
|
||||||
const char *appfile, nvadsp_app_args_t *app_args,
|
nvadsp_os_handle_t os_handle,
|
||||||
app_complete_status_notifier notifier, uint32_t stack_sz,
|
const char *appfile, nvadsp_app_args_t *app_args,
|
||||||
uint32_t core_id, bool block)
|
app_complete_status_notifier notifier, uint32_t stack_sz,
|
||||||
|
uint32_t core_id, bool block)
|
||||||
{
|
{
|
||||||
union app_loader_message message = {};
|
union app_loader_message message = {};
|
||||||
nvadsp_app_handle_t service_handle;
|
nvadsp_app_handle_t service_handle;
|
||||||
struct nvadsp_drv_data *drv_data;
|
struct nvadsp_drv_data *drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
|
struct nvadsp_app_priv_struct *priv;
|
||||||
nvadsp_app_info_t *info = NULL;
|
nvadsp_app_info_t *info = NULL;
|
||||||
struct app_loader_data *data;
|
struct app_loader_data *data;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(priv.pdev)) {
|
if (!drv_data || !drv_data->pdev || !drv_data->app_priv) {
|
||||||
pr_err("ADSP Driver is not initialized\n");
|
pr_err("ADSP Driver is not initialized\n");
|
||||||
info = ERR_PTR(-EINVAL);
|
info = ERR_PTR(-EINVAL);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
drv_data = platform_get_drvdata(priv.pdev);
|
priv = drv_data->app_priv;
|
||||||
dev = &priv.pdev->dev;
|
dev = &priv->pdev->dev;
|
||||||
|
|
||||||
if (!drv_data->adsp_os_running)
|
if (!drv_data->adsp_os_running)
|
||||||
goto end;
|
goto end;
|
||||||
@@ -781,13 +821,13 @@ nvadsp_app_info_t *nvadsp_run_app(nvadsp_os_handle_t os_handle,
|
|||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
data = &message.data;
|
data = &message.data;
|
||||||
service_handle = app_load(appfile, NULL, true);
|
service_handle = app_load(priv, appfile, NULL, true);
|
||||||
if (!service_handle) {
|
if (!service_handle) {
|
||||||
dev_err(dev, "unable to load the app %s\n", appfile);
|
dev_err(dev, "unable to load the app %s\n", appfile);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = create_app_instance(service_handle, app_args,
|
info = create_app_instance(priv, service_handle, app_args,
|
||||||
&data->app_init, notifier, stack_sz, core_id);
|
&data->app_init, notifier, stack_sz, core_id);
|
||||||
if (IS_ERR_OR_NULL(info)) {
|
if (IS_ERR_OR_NULL(info)) {
|
||||||
dev_err(dev, "unable to create instance for app %s\n", appfile);
|
dev_err(dev, "unable to create instance for app %s\n", appfile);
|
||||||
@@ -795,21 +835,21 @@ nvadsp_app_info_t *nvadsp_run_app(nvadsp_os_handle_t os_handle,
|
|||||||
}
|
}
|
||||||
data->app_init.message = RUN_ADSP_APP;
|
data->app_init.message = RUN_ADSP_APP;
|
||||||
|
|
||||||
ret = start_app_on_adsp(info, &message, block);
|
ret = start_app_on_adsp(priv, info, &message, block);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
delete_app_instance(info);
|
delete_app_instance(priv, info);
|
||||||
info = NULL;
|
info = NULL;
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_run_app);
|
|
||||||
|
|
||||||
static void delete_app_instance(nvadsp_app_info_t *app)
|
static void delete_app_instance(struct nvadsp_app_priv_struct *priv,
|
||||||
|
nvadsp_app_info_t *app)
|
||||||
{
|
{
|
||||||
struct nvadsp_app_service *ser =
|
struct nvadsp_app_service *ser =
|
||||||
(struct nvadsp_app_service *)app->handle;
|
(struct nvadsp_app_service *)app->handle;
|
||||||
struct device *dev = &priv.pdev->dev;
|
struct device *dev = &priv->pdev->dev;
|
||||||
|
|
||||||
dev_dbg(dev, "%s:freeing app %s:%d\n",
|
dev_dbg(dev, "%s:freeing app %s:%d\n",
|
||||||
__func__, app->name, app->instance_id);
|
__func__, app->name, app->instance_id);
|
||||||
@@ -821,16 +861,19 @@ static void delete_app_instance(nvadsp_app_info_t *app)
|
|||||||
mutex_unlock(&ser->lock);
|
mutex_unlock(&ser->lock);
|
||||||
|
|
||||||
/* free instance memory */
|
/* free instance memory */
|
||||||
free_instance_memory(app, ser->mem_size);
|
free_instance_memory(priv, app, ser->mem_size);
|
||||||
kfree(app->priv);
|
kfree(app->priv);
|
||||||
kfree(app);
|
kfree(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate)
|
static void _nvadsp_exit_app(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *app, bool terminate)
|
||||||
{
|
{
|
||||||
|
struct nvadsp_drv_data *drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
int *state;
|
int *state;
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(priv.pdev)) {
|
if (!drv_data || !drv_data->pdev || !drv_data->app_priv) {
|
||||||
pr_err("ADSP Driver is not initialized\n");
|
pr_err("ADSP Driver is not initialized\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -844,36 +887,38 @@ void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate)
|
|||||||
state = (int *)&app->state;
|
state = (int *)&app->state;
|
||||||
*state = NVADSP_APP_STATE_INITIALIZED;
|
*state = NVADSP_APP_STATE_INITIALIZED;
|
||||||
}
|
}
|
||||||
delete_app_instance(app);
|
delete_app_instance(drv_data->app_priv, app);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_exit_app);
|
|
||||||
|
|
||||||
int nvadsp_app_deinit(nvadsp_app_info_t *app)
|
static int _nvadsp_app_deinit(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *app)
|
||||||
{
|
{
|
||||||
nvadsp_exit_app(app, false);
|
_nvadsp_exit_app(nvadsp_handle, app, false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_app_deinit);
|
|
||||||
|
|
||||||
int nvadsp_app_stop(nvadsp_app_info_t *app)
|
static int _nvadsp_app_stop(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *app)
|
||||||
{
|
{
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_app_stop);
|
|
||||||
|
|
||||||
void nvadsp_app_unload(nvadsp_app_handle_t handle)
|
static void _nvadsp_app_unload(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_handle_t handle)
|
||||||
{
|
{
|
||||||
struct nvadsp_drv_data *drv_data;
|
struct nvadsp_drv_data *drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
|
struct nvadsp_app_priv_struct *priv;
|
||||||
struct nvadsp_app_service *ser;
|
struct nvadsp_app_service *ser;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
if (!priv.pdev) {
|
if (!drv_data || !drv_data->pdev || !drv_data->app_priv) {
|
||||||
pr_err("ADSP Driver is not initialized\n");
|
pr_err("ADSP Driver is not initialized\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
drv_data = platform_get_drvdata(priv.pdev);
|
priv = drv_data->app_priv;
|
||||||
dev = &priv.pdev->dev;
|
dev = &priv->pdev->dev;
|
||||||
|
|
||||||
if (!drv_data->adsp_os_running)
|
if (!drv_data->adsp_os_running)
|
||||||
return;
|
return;
|
||||||
@@ -886,7 +931,7 @@ void nvadsp_app_unload(nvadsp_app_handle_t handle)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef CONFIG_ADSP_DYNAMIC_APP
|
#ifdef CONFIG_ADSP_DYNAMIC_APP
|
||||||
mutex_lock(&priv.service_lock_list);
|
mutex_lock(&priv->service_lock_list);
|
||||||
if (ser->instance) {
|
if (ser->instance) {
|
||||||
dev_err(dev, "cannot unload app %s, has instances %d\n",
|
dev_err(dev, "cannot unload app %s, has instances %d\n",
|
||||||
ser->name, ser->instance);
|
ser->name, ser->instance);
|
||||||
@@ -899,10 +944,9 @@ void nvadsp_app_unload(nvadsp_app_handle_t handle)
|
|||||||
#endif
|
#endif
|
||||||
unload_adsp_module(ser->mod);
|
unload_adsp_module(ser->mod);
|
||||||
devm_kfree(dev, ser);
|
devm_kfree(dev, ser);
|
||||||
mutex_unlock(&priv.service_lock_list);
|
mutex_unlock(&priv->service_lock_list);
|
||||||
#endif // CONFIG_ADSP_DYNAMIC_APP
|
#endif // CONFIG_ADSP_DYNAMIC_APP
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_app_unload);
|
|
||||||
|
|
||||||
static status_t nvadsp_app_receive_handler(uint32_t msg, void *hdata)
|
static status_t nvadsp_app_receive_handler(uint32_t msg, void *hdata)
|
||||||
{
|
{
|
||||||
@@ -954,19 +998,13 @@ static status_t nvadsp_app_receive_handler(uint32_t msg, void *hdata)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_adsp_static_apps(void)
|
int load_adsp_static_apps(struct nvadsp_drv_data *drv_data)
|
||||||
{
|
{
|
||||||
struct nvadsp_app_shared_msg_pool *msg_pool;
|
struct nvadsp_app_shared_msg_pool *msg_pool;
|
||||||
struct nvadsp_shared_mem *shared_mem;
|
struct nvadsp_shared_mem *shared_mem;
|
||||||
struct nvadsp_drv_data *drv_data;
|
struct device *dev = &drv_data->pdev->dev;
|
||||||
struct platform_device *pdev;
|
|
||||||
struct device *dev;
|
|
||||||
msgq_t *msgq_recv;
|
msgq_t *msgq_recv;
|
||||||
|
|
||||||
pdev = priv.pdev;
|
|
||||||
dev = &pdev->dev;
|
|
||||||
drv_data = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
shared_mem = drv_data->shared_adsp_os_data;
|
shared_mem = drv_data->shared_adsp_os_data;
|
||||||
if (!shared_mem)
|
if (!shared_mem)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -993,37 +1031,88 @@ int load_adsp_static_apps(void)
|
|||||||
/* Skip Start on boot apps */
|
/* Skip Start on boot apps */
|
||||||
if (shared_app->flags & ADSP_APP_FLAG_START_ON_BOOT)
|
if (shared_app->flags & ADSP_APP_FLAG_START_ON_BOOT)
|
||||||
continue;
|
continue;
|
||||||
app_load(name, shared_app, false);
|
app_load(drv_data->app_priv, name, shared_app, false);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _nvadsp_wait_for_app_complete(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long _nvadsp_wait_for_app_complete_timeout(
|
||||||
|
struct nvadsp_handle *nvadsp_handle,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
int __init nvadsp_app_module_probe(struct platform_device *pdev)
|
int __init nvadsp_app_module_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_DEBUG_FS
|
|
||||||
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
||||||
#endif
|
struct nvadsp_handle *nvadsp_handle = &drv_data->nvadsp_handle;
|
||||||
uint16_t mbox_id = APP_LOADER_MBOX_ID;
|
uint16_t mbox_id = APP_LOADER_MBOX_ID;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
|
struct nvadsp_app_priv_struct *priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev_info(dev, "%s\n", __func__);
|
dev_info(dev, "%s\n", __func__);
|
||||||
|
|
||||||
ret = nvadsp_mbox_open(&priv.mbox, &mbox_id,
|
priv = devm_kzalloc(dev,
|
||||||
|
sizeof(struct nvadsp_app_priv_struct), GFP_KERNEL);
|
||||||
|
if (!priv) {
|
||||||
|
dev_err(dev, "Failed to allocate app_priv\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
drv_data->app_priv = priv;
|
||||||
|
|
||||||
|
ret = nvadsp_handle->mbox_open(nvadsp_handle, &priv->mbox, &mbox_id,
|
||||||
"app_service", nvadsp_app_receive_handler, pdev);
|
"app_service", nvadsp_app_receive_handler, pdev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "unable to open mailbox\n");
|
dev_err(dev, "unable to open mailbox\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
priv.pdev = pdev;
|
priv->pdev = pdev;
|
||||||
INIT_LIST_HEAD(&priv.service_list);
|
INIT_LIST_HEAD(&priv->service_list);
|
||||||
init_completion(&priv.os_load_complete);
|
init_completion(&priv->os_load_complete);
|
||||||
mutex_init(&priv.service_lock_list);
|
mutex_init(&priv->service_lock_list);
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
if (adsp_app_debug_init(drv_data->adsp_debugfs_root))
|
if (adsp_app_debug_init(priv, drv_data->adsp_debugfs_root))
|
||||||
dev_err(&pdev->dev, "unable to create adsp apps debugfs\n");
|
dev_err(dev, "unable to create adsp apps debugfs\n");
|
||||||
#endif
|
#endif
|
||||||
end:
|
end:
|
||||||
|
if (ret == 0) {
|
||||||
|
nvadsp_handle->app_load = _nvadsp_app_load;
|
||||||
|
nvadsp_handle->app_init = _nvadsp_app_init;
|
||||||
|
nvadsp_handle->app_start = _nvadsp_app_start;
|
||||||
|
nvadsp_handle->run_app = _nvadsp_run_app;
|
||||||
|
nvadsp_handle->app_stop = _nvadsp_app_stop;
|
||||||
|
nvadsp_handle->app_deinit = _nvadsp_app_deinit;
|
||||||
|
nvadsp_handle->exit_app = _nvadsp_exit_app;
|
||||||
|
nvadsp_handle->app_unload = _nvadsp_app_unload;
|
||||||
|
nvadsp_handle->set_app_complete_cb =
|
||||||
|
_nvadsp_set_app_complete_cb;
|
||||||
|
nvadsp_handle->wait_for_app_complete =
|
||||||
|
_nvadsp_wait_for_app_complete;
|
||||||
|
nvadsp_handle->wait_for_app_complete_timeout =
|
||||||
|
_nvadsp_wait_for_app_complete_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "dram_app_mem_manager.h"
|
|
||||||
#include "adsp_shared_struct.h"
|
#include "adsp_shared_struct.h"
|
||||||
|
|
||||||
#ifdef CONFIG_ADSP_DYNAMIC_APP
|
#ifdef CONFIG_ADSP_DYNAMIC_APP
|
||||||
@@ -17,6 +16,7 @@
|
|||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <asm/hwcap.h>
|
#include <asm/hwcap.h>
|
||||||
|
#include "dram_app_mem_manager.h"
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_SET_MODULE_RONX
|
#ifdef CONFIG_DEBUG_SET_MODULE_RONX
|
||||||
# define debug_align(X) ALIGN(X, PAGE_SIZE)
|
# define debug_align(X) ALIGN(X, PAGE_SIZE)
|
||||||
|
|||||||
@@ -10,22 +10,17 @@
|
|||||||
|
|
||||||
#include "aram_manager.h"
|
#include "aram_manager.h"
|
||||||
|
|
||||||
static void *aram_handle;
|
void nvadsp_aram_print(void *aram_handle)
|
||||||
|
|
||||||
static LIST_HEAD(aram_alloc_list);
|
|
||||||
static LIST_HEAD(aram_free_list);
|
|
||||||
|
|
||||||
void nvadsp_aram_print(void)
|
|
||||||
{
|
{
|
||||||
mem_print(aram_handle);
|
mem_print(aram_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *nvadsp_aram_request(const char *name, size_t size)
|
void *nvadsp_aram_request(void *aram_handle, const char *name, size_t size)
|
||||||
{
|
{
|
||||||
return mem_request(aram_handle, name, size);
|
return mem_request(aram_handle, name, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nvadsp_aram_release(void *handle)
|
bool nvadsp_aram_release(void *aram_handle, void *handle)
|
||||||
{
|
{
|
||||||
return mem_release(aram_handle, handle);
|
return mem_release(aram_handle, handle);
|
||||||
}
|
}
|
||||||
@@ -35,11 +30,11 @@ unsigned long nvadsp_aram_get_address(void *handle)
|
|||||||
return mem_get_address(handle);
|
return mem_get_address(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *aram_dump_debugfs_file;
|
|
||||||
|
|
||||||
static int nvadsp_aram_dump(struct seq_file *s, void *data)
|
static int nvadsp_aram_dump(struct seq_file *s, void *data)
|
||||||
{
|
{
|
||||||
mem_dump(aram_handle, s);
|
struct nvadsp_drv_data *drv_data = data;
|
||||||
|
|
||||||
|
mem_dump(drv_data->aram_handle, s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,29 +50,31 @@ static const struct file_operations aram_dump_fops = {
|
|||||||
.release = single_release,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
int nvadsp_aram_init(unsigned long addr, unsigned long size)
|
int nvadsp_aram_init(struct nvadsp_drv_data *drv_data,
|
||||||
|
unsigned long addr, unsigned long size)
|
||||||
{
|
{
|
||||||
aram_handle = create_mem_manager("ARAM", addr, size);
|
drv_data->aram_handle = create_mem_manager("ARAM", addr, size);
|
||||||
if (IS_ERR(aram_handle)) {
|
if (IS_ERR(drv_data->aram_handle)) {
|
||||||
pr_err("ERROR: failed to create aram memory_manager");
|
pr_err("ERROR: failed to create aram memory_manager");
|
||||||
return PTR_ERR(aram_handle);
|
return PTR_ERR(drv_data->aram_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debugfs_initialized()) {
|
if (debugfs_initialized()) {
|
||||||
aram_dump_debugfs_file = debugfs_create_file("aram_dump",
|
drv_data->aram_dump_debugfs_file = debugfs_create_file("aram_dump",
|
||||||
S_IRUSR, NULL, NULL, &aram_dump_fops);
|
S_IRUSR, drv_data->adsp_debugfs_root,
|
||||||
if (!aram_dump_debugfs_file) {
|
drv_data, &aram_dump_fops);
|
||||||
|
if (!drv_data->aram_dump_debugfs_file) {
|
||||||
pr_err("ERROR: failed to create aram_dump debugfs");
|
pr_err("ERROR: failed to create aram_dump debugfs");
|
||||||
destroy_mem_manager(aram_handle);
|
destroy_mem_manager(drv_data->aram_handle);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvadsp_aram_exit(void)
|
void nvadsp_aram_exit(struct nvadsp_drv_data *drv_data)
|
||||||
{
|
{
|
||||||
debugfs_remove(aram_dump_debugfs_file);
|
debugfs_remove(drv_data->aram_dump_debugfs_file);
|
||||||
destroy_mem_manager(aram_handle);
|
destroy_mem_manager(drv_data->aram_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TEGRA_NVADSP_ARAM_MANAGER_H
|
#ifndef __TEGRA_NVADSP_ARAM_MANAGER_H
|
||||||
#define __TEGRA_NVADSP_ARAM_MANAGER_H
|
#define __TEGRA_NVADSP_ARAM_MANAGER_H
|
||||||
|
|
||||||
#include "mem_manager.h"
|
#include "mem_manager.h"
|
||||||
|
#include "dev.h"
|
||||||
|
|
||||||
|
int nvadsp_aram_init(struct nvadsp_drv_data *drv_data,
|
||||||
|
unsigned long addr, unsigned long size);
|
||||||
|
void nvadsp_aram_exit(struct nvadsp_drv_data *drv_data);
|
||||||
|
|
||||||
int nvadsp_aram_init(unsigned long addr, unsigned long size);
|
|
||||||
void nvadsp_aram_exit(void);
|
|
||||||
#endif /* __TEGRA_NVADSP_ARAM_MANAGER_H */
|
#endif /* __TEGRA_NVADSP_ARAM_MANAGER_H */
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
@@ -13,6 +12,7 @@
|
|||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/tegra_nvadsp.h>
|
#include <linux/tegra_nvadsp.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
#include <soc/tegra/fuse-helper.h>
|
#include <soc/tegra/fuse-helper.h>
|
||||||
#include <soc/tegra/virt/hv-ivc.h>
|
#include <soc/tegra/virt/hv-ivc.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <asm/arch_timer.h>
|
#include <asm/arch_timer.h>
|
||||||
|
|
||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
|
#include "hwmailbox.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "amc.h"
|
#include "amc.h"
|
||||||
#include "ape_actmon.h"
|
#include "ape_actmon.h"
|
||||||
@@ -28,12 +29,69 @@
|
|||||||
|
|
||||||
#include "dev-t18x.h"
|
#include "dev-t18x.h"
|
||||||
|
|
||||||
static struct nvadsp_drv_data *nvadsp_drv_data;
|
#define MAX_DEV_STR_LEN (20)
|
||||||
|
|
||||||
|
struct nvadsp_handle_node {
|
||||||
|
char dev_str[MAX_DEV_STR_LEN];
|
||||||
|
struct nvadsp_handle *nvadsp_handle;
|
||||||
|
struct list_head list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Global list of driver instance handles */
|
||||||
|
static LIST_HEAD(nvadsp_handle_list);
|
||||||
|
static DEFINE_MUTEX(nvadsp_handle_mutex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nvadsp_get_handle: Fetch driver instance using unique identfier
|
||||||
|
*
|
||||||
|
* @dev_str : Unique identifier string for the driver instance
|
||||||
|
* (trailing unique identifer in compatible DT property,
|
||||||
|
* e.g. "adsp", "adsp1", etc.)
|
||||||
|
*
|
||||||
|
* Return : Driver instance handle on success, else NULL
|
||||||
|
*/
|
||||||
|
struct nvadsp_handle *nvadsp_get_handle(const char *dev_str)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle_node *handle_node;
|
||||||
|
struct nvadsp_handle *nvadsp_handle = NULL;
|
||||||
|
uint32_t num_devs = 0;
|
||||||
|
|
||||||
|
mutex_lock(&nvadsp_handle_mutex);
|
||||||
|
|
||||||
|
if (list_empty(&nvadsp_handle_list))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
list_for_each_entry(handle_node, &nvadsp_handle_list, list) {
|
||||||
|
num_devs++;
|
||||||
|
|
||||||
|
if (!strcmp(dev_str, handle_node->dev_str)) {
|
||||||
|
nvadsp_handle = handle_node->nvadsp_handle;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num_devs == 1) && !strcmp(dev_str, "")) {
|
||||||
|
handle_node = list_first_entry(
|
||||||
|
&nvadsp_handle_list,
|
||||||
|
struct nvadsp_handle_node, list);
|
||||||
|
nvadsp_handle = handle_node->nvadsp_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&nvadsp_handle_mutex);
|
||||||
|
|
||||||
|
if (!nvadsp_handle)
|
||||||
|
pr_err("Unable to find device %s in list\n", dev_str);
|
||||||
|
|
||||||
|
return nvadsp_handle;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(nvadsp_get_handle);
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
static int __init adsp_debug_init(struct nvadsp_drv_data *drv_data)
|
static int __init adsp_debug_init(struct nvadsp_drv_data *drv_data,
|
||||||
|
const char *dev_str)
|
||||||
{
|
{
|
||||||
drv_data->adsp_debugfs_root = debugfs_create_dir("tegra_ape", NULL);
|
drv_data->adsp_debugfs_root = debugfs_create_dir(dev_str, NULL);
|
||||||
if (!drv_data->adsp_debugfs_root)
|
if (!drv_data->adsp_debugfs_root)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -107,7 +165,6 @@ uint64_t nvadsp_get_timestamp_counter(void)
|
|||||||
{
|
{
|
||||||
return __arch_counter_get_cntvct_stable();
|
return __arch_counter_get_cntvct_stable();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_get_timestamp_counter);
|
|
||||||
|
|
||||||
int nvadsp_set_bw(struct nvadsp_drv_data *drv_data, u32 efreq)
|
int nvadsp_set_bw(struct nvadsp_drv_data *drv_data, u32 efreq)
|
||||||
{
|
{
|
||||||
@@ -343,13 +400,45 @@ static int __init nvadsp_probe(struct platform_device *pdev)
|
|||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct resource *res = NULL;
|
struct resource *res = NULL;
|
||||||
void __iomem *base = NULL;
|
void __iomem *base = NULL;
|
||||||
uint32_t aram_addr;
|
uint32_t aram_addr, aram_size;
|
||||||
uint32_t aram_size;
|
int irq_iter, iter, irq_num;
|
||||||
int irq_iter, iter;
|
const char *compat, *dev_str;
|
||||||
int irq_num;
|
struct nvadsp_handle_node *handle_node;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
dev_info(dev, "in probe()...\n");
|
mutex_lock(&nvadsp_handle_mutex);
|
||||||
|
|
||||||
|
ret = of_property_read_string(dev->of_node, "compatible", &compat);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trailing part of compatible string after the
|
||||||
|
* last '-' is taken as unique device string
|
||||||
|
*/
|
||||||
|
dev_str = strrchr(compat, '-');
|
||||||
|
if (strlen(dev_str) < 2) {
|
||||||
|
dev_err(dev, "Unable to extract device string\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
dev_str += 1;
|
||||||
|
|
||||||
|
if (strlen(dev_str) >= MAX_DEV_STR_LEN) {
|
||||||
|
dev_err(dev, "Device string %s out of bound\n", dev_str);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(handle_node, &nvadsp_handle_list, list) {
|
||||||
|
if (!strcmp(dev_str, handle_node->dev_str)) {
|
||||||
|
dev_err(dev, "Device %s already probed\n", dev_str);
|
||||||
|
ret = -EEXIST;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(dev, "in probe()...%s\n", dev_str);
|
||||||
|
|
||||||
drv_data = devm_kzalloc(dev, sizeof(*drv_data),
|
drv_data = devm_kzalloc(dev, sizeof(*drv_data),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
@@ -376,9 +465,9 @@ static int __init nvadsp_probe(struct platform_device *pdev)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
if (adsp_debug_init(drv_data))
|
if (adsp_debug_init(drv_data, dev_str))
|
||||||
dev_err(dev,
|
dev_err(dev,
|
||||||
"unable to create tegra_ape debug fs directory\n");
|
"unable to create %s debug fs directory\n", dev_str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
drv_data->base_regs =
|
drv_data->base_regs =
|
||||||
@@ -408,8 +497,9 @@ static int __init nvadsp_probe(struct platform_device *pdev)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
drv_data->base_regs[iter] = base;
|
drv_data->base_regs[iter] = base;
|
||||||
nvadsp_add_load_mappings(res->start, (void __force *)base,
|
nvadsp_add_load_mappings(drv_data,
|
||||||
resource_size(res));
|
res->start, (void __force *)base,
|
||||||
|
resource_size(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
drv_data->base_regs_saved = drv_data->base_regs;
|
drv_data->base_regs_saved = drv_data->base_regs;
|
||||||
@@ -425,8 +515,6 @@ static int __init nvadsp_probe(struct platform_device *pdev)
|
|||||||
drv_data->agic_irqs[irq_iter] = irq_num;
|
drv_data->agic_irqs[irq_iter] = irq_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
nvadsp_drv_data = drv_data;
|
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
pm_runtime_enable(dev);
|
pm_runtime_enable(dev);
|
||||||
|
|
||||||
@@ -465,7 +553,7 @@ static int __init nvadsp_probe(struct platform_device *pdev)
|
|||||||
aram_addr = drv_data->adsp_mem[ARAM_ALIAS_0_ADDR];
|
aram_addr = drv_data->adsp_mem[ARAM_ALIAS_0_ADDR];
|
||||||
aram_size = drv_data->adsp_mem[ARAM_ALIAS_0_SIZE];
|
aram_size = drv_data->adsp_mem[ARAM_ALIAS_0_SIZE];
|
||||||
if (aram_size) {
|
if (aram_size) {
|
||||||
ret = nvadsp_aram_init(aram_addr, aram_size);
|
ret = nvadsp_aram_init(drv_data, aram_addr, aram_size);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(dev, "Failed to init aram\n");
|
dev_err(dev, "Failed to init aram\n");
|
||||||
}
|
}
|
||||||
@@ -478,6 +566,20 @@ static int __init nvadsp_probe(struct platform_device *pdev)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle_node = kzalloc(sizeof(struct nvadsp_handle_node),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!handle_node) {
|
||||||
|
dev_err(dev, "Failed to allocate node mem for %s\n", dev_str);
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add probed device into list of handles */
|
||||||
|
strcpy(handle_node->dev_str, dev_str);
|
||||||
|
handle_node->nvadsp_handle = (struct nvadsp_handle *)drv_data;
|
||||||
|
INIT_LIST_HEAD(&handle_node->list);
|
||||||
|
list_add_tail(&handle_node->list, &nvadsp_handle_list);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
ret = pm_runtime_put_sync(dev);
|
ret = pm_runtime_put_sync(dev);
|
||||||
@@ -485,6 +587,8 @@ err:
|
|||||||
dev_err(dev, "pm_runtime_put_sync failed\n");
|
dev_err(dev, "pm_runtime_put_sync failed\n");
|
||||||
#endif
|
#endif
|
||||||
out:
|
out:
|
||||||
|
mutex_unlock(&nvadsp_handle_mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,11 +596,12 @@ static int nvadsp_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev);
|
||||||
uint32_t aram_size = drv_data->adsp_mem[ARAM_ALIAS_0_SIZE];
|
uint32_t aram_size = drv_data->adsp_mem[ARAM_ALIAS_0_SIZE];
|
||||||
|
struct nvadsp_handle_node *handle_node;
|
||||||
|
|
||||||
nvadsp_bw_unregister(drv_data);
|
nvadsp_bw_unregister(drv_data);
|
||||||
|
|
||||||
if (aram_size)
|
if (aram_size)
|
||||||
nvadsp_aram_exit();
|
nvadsp_aram_exit(drv_data);
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
@@ -505,6 +610,18 @@ static int nvadsp_remove(struct platform_device *pdev)
|
|||||||
nvadsp_runtime_suspend(&pdev->dev);
|
nvadsp_runtime_suspend(&pdev->dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
mutex_lock(&nvadsp_handle_mutex);
|
||||||
|
|
||||||
|
list_for_each_entry(handle_node, &nvadsp_handle_list, list) {
|
||||||
|
if (handle_node->nvadsp_handle ==
|
||||||
|
(struct nvadsp_handle *)drv_data) {
|
||||||
|
list_del(&handle_node->list);
|
||||||
|
kfree(handle_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&nvadsp_handle_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <linux/interconnect.h>
|
#include <linux/interconnect.h>
|
||||||
|
|
||||||
#include "hwmailbox.h"
|
|
||||||
#include "amc.h"
|
#include "amc.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -119,6 +118,9 @@ struct nvadsp_hwmb {
|
|||||||
u32 empty_int_ie;
|
u32 empty_int_ie;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Max SW mailboxes */
|
||||||
|
#define NVADSP_MAILBOX_MAX 1024
|
||||||
|
|
||||||
/* Max no. of entries in "nvidia,cluster_mem" */
|
/* Max no. of entries in "nvidia,cluster_mem" */
|
||||||
#define MAX_CLUSTER_MEM 3
|
#define MAX_CLUSTER_MEM 3
|
||||||
|
|
||||||
@@ -163,14 +165,33 @@ struct nvadsp_chipdata {
|
|||||||
size_t num_regs;
|
size_t num_regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Maximum number of LOAD MAPPINGS supported */
|
||||||
|
#define NM_LOAD_MAPPINGS 20
|
||||||
|
|
||||||
|
struct nvadsp_mappings {
|
||||||
|
phys_addr_t da;
|
||||||
|
void *va;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
struct nvadsp_drv_data {
|
struct nvadsp_drv_data {
|
||||||
|
/**
|
||||||
|
* API handle exposed to caller
|
||||||
|
* MUST BE THE FIRST FIELD IN THIS STRUCTURE
|
||||||
|
*/
|
||||||
|
struct nvadsp_handle nvadsp_handle;
|
||||||
|
|
||||||
void __iomem **base_regs;
|
void __iomem **base_regs;
|
||||||
void __iomem **base_regs_saved;
|
void __iomem **base_regs_saved;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
struct hwmbox_queue hwmbox_send_queue;
|
|
||||||
|
|
||||||
struct nvadsp_mbox **mboxes;
|
/* Memories allocated by subsidiary modules */
|
||||||
unsigned long *mbox_ids;
|
void *hwmbox_send_queue; /* struct hwmbox_queue */
|
||||||
|
void *os_priv; /* struct nvadsp_os_data */
|
||||||
|
void *app_priv; /* struct nvadsp_app_priv_struct */
|
||||||
|
|
||||||
|
struct nvadsp_mbox *mboxes[NVADSP_MAILBOX_MAX];
|
||||||
|
unsigned long mbox_ids[BITS_TO_LONGS(NVADSP_MAILBOX_MAX)];
|
||||||
spinlock_t mbox_lock;
|
spinlock_t mbox_lock;
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
@@ -259,6 +280,13 @@ struct nvadsp_drv_data {
|
|||||||
|
|
||||||
/* "nvidia,dram_map" */
|
/* "nvidia,dram_map" */
|
||||||
struct nvadsp_reg_map dram_map[MAX_DRAM_MAP];
|
struct nvadsp_reg_map dram_map[MAX_DRAM_MAP];
|
||||||
|
|
||||||
|
struct nvadsp_mappings adsp_map[NM_LOAD_MAPPINGS];
|
||||||
|
int map_idx;
|
||||||
|
|
||||||
|
/* ARAM manager */
|
||||||
|
void *aram_handle;
|
||||||
|
struct dentry *aram_dump_debugfs_file;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ADSP_CONFIG 0x04
|
#define ADSP_CONFIG 0x04
|
||||||
|
|||||||
@@ -9,63 +9,50 @@
|
|||||||
#include <linux/tegra_nvadsp.h>
|
#include <linux/tegra_nvadsp.h>
|
||||||
|
|
||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
|
#include "hwmailbox.h"
|
||||||
|
|
||||||
static struct platform_device *nvadsp_pdev;
|
|
||||||
static struct nvadsp_drv_data *nvadsp_drv_data;
|
|
||||||
/* Initialized to false by default */
|
|
||||||
static bool is_hwmbox_busy;
|
|
||||||
#ifdef CONFIG_MBOX_ACK_HANDLER
|
|
||||||
static int hwmbox_last_msg;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mailbox 0 is for receiving messages
|
* Mailbox 0 is for receiving messages
|
||||||
* from ADSP i.e. CPU <-- ADSP.
|
* from ADSP i.e. CPU <-- ADSP.
|
||||||
*/
|
*/
|
||||||
#define INT_RECV_HWMBOX INT_AMISC_MBOX_FULL0
|
static inline u32 recv_hwmbox(struct nvadsp_drv_data *drv)
|
||||||
|
|
||||||
static inline u32 recv_hwmbox(void)
|
|
||||||
{
|
{
|
||||||
return nvadsp_drv_data->chip_data->hwmb.hwmbox0_reg;
|
return drv->chip_data->hwmb.hwmbox0_reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mailbox 1 is for sending messages
|
* Mailbox 1 is for sending messages
|
||||||
* to ADSP i.e. CPU --> ADSP
|
* to ADSP i.e. CPU --> ADSP
|
||||||
*/
|
*/
|
||||||
#define INT_SEND_HWMBOX INT_AMISC_MBOX_EMPTY1
|
static inline u32 send_hwmbox(struct nvadsp_drv_data *drv)
|
||||||
|
|
||||||
static inline u32 send_hwmbox(void)
|
|
||||||
{
|
{
|
||||||
return nvadsp_drv_data->chip_data->hwmb.hwmbox1_reg;
|
return drv->chip_data->hwmb.hwmbox1_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 hwmb_reg_idx(struct nvadsp_drv_data *drv)
|
||||||
|
{
|
||||||
|
return drv->chip_data->hwmb.reg_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 hwmbox_readl(struct nvadsp_drv_data *drv, u32 reg)
|
||||||
|
{
|
||||||
|
return readl(drv->base_regs[hwmb_reg_idx(drv)] + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hwmbox_writel(struct nvadsp_drv_data *drv, u32 val, u32 reg)
|
||||||
|
{
|
||||||
|
writel(val, drv->base_regs[hwmb_reg_idx(drv)] + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u32 hwmb_reg_idx(void)
|
#define PRINT_HWMBOX(d, x) \
|
||||||
|
pr_err("%s: 0x%x\n", #x, hwmbox_readl(d, x))
|
||||||
|
|
||||||
|
void dump_mailbox_regs(struct nvadsp_drv_data *drv)
|
||||||
{
|
{
|
||||||
return nvadsp_drv_data->chip_data->hwmb.reg_idx;
|
pr_err("dumping hwmailbox registers ...\n");
|
||||||
}
|
PRINT_HWMBOX(drv, recv_hwmbox(drv));
|
||||||
|
PRINT_HWMBOX(drv, send_hwmbox(drv));
|
||||||
u32 hwmbox_readl(u32 reg)
|
|
||||||
{
|
|
||||||
return readl(nvadsp_drv_data->base_regs[hwmb_reg_idx()] + reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hwmbox_writel(u32 val, u32 reg)
|
|
||||||
{
|
|
||||||
writel(val, nvadsp_drv_data->base_regs[hwmb_reg_idx()] + reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define PRINT_HWMBOX(x) \
|
|
||||||
dev_info(&nvadsp_pdev->dev, "%s: 0x%x\n", #x, hwmbox_readl(x))
|
|
||||||
|
|
||||||
void dump_mailbox_regs(void)
|
|
||||||
{
|
|
||||||
dev_info(&nvadsp_pdev->dev, "dumping hwmailbox registers ...\n");
|
|
||||||
PRINT_HWMBOX(recv_hwmbox());
|
|
||||||
PRINT_HWMBOX(send_hwmbox());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hwmboxq_init(struct hwmbox_queue *queue)
|
static void hwmboxq_init(struct hwmbox_queue *queue)
|
||||||
@@ -75,6 +62,8 @@ static void hwmboxq_init(struct hwmbox_queue *queue)
|
|||||||
queue->count = 0;
|
queue->count = 0;
|
||||||
init_completion(&queue->comp);
|
init_completion(&queue->comp);
|
||||||
spin_lock_init(&queue->lock);
|
spin_lock_init(&queue->lock);
|
||||||
|
queue->is_hwmbox_busy = false;
|
||||||
|
queue->hwmbox_last_msg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must be called with queue lock held in non-interrupt context */
|
/* Must be called with queue lock held in non-interrupt context */
|
||||||
@@ -116,10 +105,12 @@ static status_t hwmboxq_enqueue(struct hwmbox_queue *queue,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t nvadsp_hwmbox_send_data(uint16_t mid, uint32_t data, uint32_t flags)
|
status_t nvadsp_hwmbox_send_data(struct nvadsp_drv_data *drv,
|
||||||
|
uint16_t mid, uint32_t data, uint32_t flags)
|
||||||
{
|
{
|
||||||
spinlock_t *lock = &nvadsp_drv_data->hwmbox_send_queue.lock;
|
struct hwmbox_queue *hwmbox_send_queue = drv->hwmbox_send_queue;
|
||||||
u32 empty_int_ie = nvadsp_drv_data->chip_data->hwmb.empty_int_ie;
|
spinlock_t *lock = &hwmbox_send_queue->lock;
|
||||||
|
u32 empty_int_ie = drv->chip_data->hwmb.empty_int_ie;
|
||||||
unsigned long lockflags;
|
unsigned long lockflags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -132,19 +123,18 @@ status_t nvadsp_hwmbox_send_data(uint16_t mid, uint32_t data, uint32_t flags)
|
|||||||
|
|
||||||
spin_lock_irqsave(lock, lockflags);
|
spin_lock_irqsave(lock, lockflags);
|
||||||
|
|
||||||
if (!is_hwmbox_busy) {
|
if (!hwmbox_send_queue->is_hwmbox_busy) {
|
||||||
is_hwmbox_busy = true;
|
hwmbox_send_queue->is_hwmbox_busy = true;
|
||||||
pr_debug("nvadsp_mbox_send: empty mailbox. write to mailbox.\n");
|
pr_debug("nvadsp_mbox_send: empty mailbox. write to mailbox.\n");
|
||||||
#ifdef CONFIG_MBOX_ACK_HANDLER
|
hwmbox_send_queue->hwmbox_last_msg = data;
|
||||||
hwmbox_last_msg = data;
|
hwmbox_writel(drv, data, send_hwmbox(drv));
|
||||||
#endif
|
if (empty_int_ie) {
|
||||||
hwmbox_writel(data, send_hwmbox());
|
hwmbox_writel(drv, INT_ENABLE,
|
||||||
if (empty_int_ie)
|
send_hwmbox(drv) + empty_int_ie);
|
||||||
hwmbox_writel(INT_ENABLE, send_hwmbox() + empty_int_ie);
|
}
|
||||||
} else {
|
} else {
|
||||||
pr_debug("nvadsp_mbox_send: enqueue data\n");
|
pr_debug("nvadsp_mbox_send: enqueue data\n");
|
||||||
ret = hwmboxq_enqueue(&nvadsp_drv_data->hwmbox_send_queue,
|
ret = hwmboxq_enqueue(hwmbox_send_queue, data);
|
||||||
data);
|
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(lock, lockflags);
|
spin_unlock_irqrestore(lock, lockflags);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -162,7 +152,7 @@ static status_t hwmboxq_dequeue(struct hwmbox_queue *queue,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_hwmboxq_full(queue))
|
if (is_hwmboxq_full(queue))
|
||||||
complete_all(&nvadsp_drv_data->hwmbox_send_queue.comp);
|
complete_all(&queue->comp);
|
||||||
|
|
||||||
*data = queue->array[queue->head];
|
*data = queue->array[queue->head];
|
||||||
queue->head = (queue->head + 1) & HWMBOX_QUEUE_SIZE_MASK;
|
queue->head = (queue->head + 1) & HWMBOX_QUEUE_SIZE_MASK;
|
||||||
@@ -174,51 +164,51 @@ static status_t hwmboxq_dequeue(struct hwmbox_queue *queue,
|
|||||||
|
|
||||||
static irqreturn_t hwmbox_send_empty_int_handler(int irq, void *devid)
|
static irqreturn_t hwmbox_send_empty_int_handler(int irq, void *devid)
|
||||||
{
|
{
|
||||||
spinlock_t *lock = &nvadsp_drv_data->hwmbox_send_queue.lock;
|
struct platform_device *pdev = devid;
|
||||||
struct device *dev = &nvadsp_pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
u32 empty_int_ie = nvadsp_drv_data->chip_data->hwmb.empty_int_ie;
|
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
||||||
|
struct hwmbox_queue *hwmbox_send_queue = drv->hwmbox_send_queue;
|
||||||
|
spinlock_t *lock = &hwmbox_send_queue->lock;
|
||||||
|
u32 empty_int_ie = drv->chip_data->hwmb.empty_int_ie;
|
||||||
unsigned long lockflags;
|
unsigned long lockflags;
|
||||||
uint32_t data;
|
uint32_t data, hwmbox_last_msg;
|
||||||
|
uint16_t last_mboxid;
|
||||||
|
struct nvadsp_mbox *mbox;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!is_hwmbox_busy)
|
if (!hwmbox_send_queue->is_hwmbox_busy)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
spin_lock_irqsave(lock, lockflags);
|
spin_lock_irqsave(lock, lockflags);
|
||||||
|
|
||||||
data = hwmbox_readl(send_hwmbox());
|
data = hwmbox_readl(drv, send_hwmbox(drv));
|
||||||
if (data != PREPARE_HWMBOX_EMPTY_MSG())
|
if (data != PREPARE_HWMBOX_EMPTY_MSG())
|
||||||
dev_err(dev, "last mailbox sent failed with 0x%x\n", data);
|
dev_err(dev, "last mailbox sent failed with 0x%x\n", data);
|
||||||
|
|
||||||
#ifdef CONFIG_MBOX_ACK_HANDLER
|
hwmbox_last_msg = hwmbox_send_queue->hwmbox_last_msg;
|
||||||
{
|
last_mboxid = HWMBOX_SMSG_MID(hwmbox_last_msg);
|
||||||
uint16_t last_mboxid = HWMBOX_SMSG_MID(hwmbox_last_msg);
|
mbox = drv->mboxes[last_mboxid];
|
||||||
struct nvadsp_mbox *mbox = nvadsp_drv_data->mboxes[last_mboxid];
|
|
||||||
|
|
||||||
if (mbox) {
|
if (mbox) {
|
||||||
nvadsp_mbox_handler_t ack_handler = mbox->ack_handler;
|
nvadsp_mbox_handler_t ack_handler = mbox->ack_handler;
|
||||||
|
|
||||||
if (ack_handler) {
|
if (ack_handler) {
|
||||||
uint32_t msg = HWMBOX_SMSG_MSG(hwmbox_last_msg);
|
uint32_t msg = HWMBOX_SMSG_MSG(hwmbox_last_msg);
|
||||||
|
|
||||||
ack_handler(msg, mbox->hdata);
|
ack_handler(msg, mbox->hdata);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
ret = hwmboxq_dequeue(&nvadsp_drv_data->hwmbox_send_queue,
|
ret = hwmboxq_dequeue(hwmbox_send_queue, &data);
|
||||||
&data);
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
#ifdef CONFIG_MBOX_ACK_HANDLER
|
hwmbox_send_queue->hwmbox_last_msg = data;
|
||||||
hwmbox_last_msg = data;
|
hwmbox_writel(drv, data, send_hwmbox(drv));
|
||||||
#endif
|
|
||||||
hwmbox_writel(data, send_hwmbox());
|
|
||||||
dev_dbg(dev, "Writing 0x%x to SEND_HWMBOX\n", data);
|
dev_dbg(dev, "Writing 0x%x to SEND_HWMBOX\n", data);
|
||||||
} else {
|
} else {
|
||||||
is_hwmbox_busy = false;
|
hwmbox_send_queue->is_hwmbox_busy = false;
|
||||||
if (empty_int_ie)
|
if (empty_int_ie)
|
||||||
hwmbox_writel(INT_DISABLE,
|
hwmbox_writel(drv, INT_DISABLE,
|
||||||
send_hwmbox() + empty_int_ie);
|
send_hwmbox(drv) + empty_int_ie);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(lock, lockflags);
|
spin_unlock_irqrestore(lock, lockflags);
|
||||||
|
|
||||||
@@ -227,18 +217,21 @@ static irqreturn_t hwmbox_send_empty_int_handler(int irq, void *devid)
|
|||||||
|
|
||||||
static irqreturn_t hwmbox_recv_full_int_handler(int irq, void *devid)
|
static irqreturn_t hwmbox_recv_full_int_handler(int irq, void *devid)
|
||||||
{
|
{
|
||||||
|
struct platform_device *pdev = devid;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
data = hwmbox_readl(recv_hwmbox());
|
data = hwmbox_readl(drv, recv_hwmbox(drv));
|
||||||
hwmbox_writel(PREPARE_HWMBOX_EMPTY_MSG(), recv_hwmbox());
|
hwmbox_writel(drv, PREPARE_HWMBOX_EMPTY_MSG(), recv_hwmbox(drv));
|
||||||
|
|
||||||
if (IS_HWMBOX_MSG_SMSG(data)) {
|
if (IS_HWMBOX_MSG_SMSG(data)) {
|
||||||
uint16_t mboxid = HWMBOX_SMSG_MID(data);
|
uint16_t mboxid = HWMBOX_SMSG_MID(data);
|
||||||
struct nvadsp_mbox *mbox = nvadsp_drv_data->mboxes[mboxid];
|
struct nvadsp_mbox *mbox = drv->mboxes[mboxid];
|
||||||
|
|
||||||
if (!mbox) {
|
if (!mbox) {
|
||||||
dev_info(&nvadsp_pdev->dev,
|
dev_info(dev,
|
||||||
"Failed to get mbox for mboxid: %u\n",
|
"Failed to get mbox for mboxid: %u\n",
|
||||||
mboxid);
|
mboxid);
|
||||||
goto out;
|
goto out;
|
||||||
@@ -250,7 +243,7 @@ static irqreturn_t hwmbox_recv_full_int_handler(int irq, void *devid)
|
|||||||
ret = nvadsp_mboxq_enqueue(&mbox->recv_queue,
|
ret = nvadsp_mboxq_enqueue(&mbox->recv_queue,
|
||||||
HWMBOX_SMSG_MSG(data));
|
HWMBOX_SMSG_MSG(data));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_info(&nvadsp_pdev->dev,
|
dev_info(dev,
|
||||||
"Failed to deliver msg 0x%x to"
|
"Failed to deliver msg 0x%x to"
|
||||||
" mbox id %u\n",
|
" mbox id %u\n",
|
||||||
HWMBOX_SMSG_MSG(data), mboxid);
|
HWMBOX_SMSG_MSG(data), mboxid);
|
||||||
@@ -266,7 +259,6 @@ static irqreturn_t hwmbox_recv_full_int_handler(int irq, void *devid)
|
|||||||
|
|
||||||
void nvadsp_free_hwmbox_interrupts(struct platform_device *pdev)
|
void nvadsp_free_hwmbox_interrupts(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
int recv_virq, send_virq;
|
int recv_virq, send_virq;
|
||||||
@@ -301,8 +293,8 @@ int nvadsp_setup_hwmbox_interrupts(struct platform_device *pdev)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (empty_int_ie)
|
if (empty_int_ie)
|
||||||
hwmbox_writel(INT_DISABLE,
|
hwmbox_writel(drv, INT_DISABLE,
|
||||||
send_hwmbox() + empty_int_ie);
|
send_hwmbox(drv) + empty_int_ie);
|
||||||
ret = devm_request_irq(dev, send_virq, hwmbox_send_empty_int_handler,
|
ret = devm_request_irq(dev, send_virq, hwmbox_send_empty_int_handler,
|
||||||
IRQF_TRIGGER_RISING,
|
IRQF_TRIGGER_RISING,
|
||||||
"hwmbox1_send_empty", pdev);
|
"hwmbox1_send_empty", pdev);
|
||||||
@@ -320,12 +312,19 @@ int nvadsp_setup_hwmbox_interrupts(struct platform_device *pdev)
|
|||||||
int __init nvadsp_hwmbox_init(struct platform_device *pdev)
|
int __init nvadsp_hwmbox_init(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
nvadsp_pdev = pdev;
|
drv->hwmbox_send_queue = devm_kzalloc(dev,
|
||||||
nvadsp_drv_data = drv;
|
sizeof(struct hwmbox_queue), GFP_KERNEL);
|
||||||
|
if (!drv->hwmbox_send_queue) {
|
||||||
|
dev_err(dev, "Failed to allocate hwmbox_send_queue\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
hwmboxq_init(&drv->hwmbox_send_queue);
|
hwmboxq_init(drv->hwmbox_send_queue);
|
||||||
|
|
||||||
|
exit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,15 +95,17 @@ struct hwmbox_queue {
|
|||||||
uint16_t count;
|
uint16_t count;
|
||||||
struct completion comp;
|
struct completion comp;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
bool is_hwmbox_busy;
|
||||||
|
uint32_t hwmbox_last_msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 hwmb_reg_idx(void);
|
u32 hwmbox_readl(struct nvadsp_drv_data *, u32 reg);
|
||||||
u32 hwmbox_readl(u32 reg);
|
void hwmbox_writel(struct nvadsp_drv_data *, u32 val, u32 reg);
|
||||||
void hwmbox_writel(u32 val, u32 reg);
|
status_t nvadsp_hwmbox_send_data(struct nvadsp_drv_data *,
|
||||||
int nvadsp_hwmbox_init(struct platform_device *);
|
uint16_t, uint32_t, uint32_t);
|
||||||
status_t nvadsp_hwmbox_send_data(uint16_t, uint32_t, uint32_t);
|
void dump_mailbox_regs(struct nvadsp_drv_data *);
|
||||||
void dump_mailbox_regs(void);
|
|
||||||
|
|
||||||
|
int nvadsp_hwmbox_init(struct platform_device *);
|
||||||
int nvadsp_setup_hwmbox_interrupts(struct platform_device *pdev);
|
int nvadsp_setup_hwmbox_interrupts(struct platform_device *pdev);
|
||||||
void nvadsp_free_hwmbox_interrupts(struct platform_device *pdev);
|
void nvadsp_free_hwmbox_interrupts(struct platform_device *pdev);
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,14 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
|
#include "hwmailbox.h"
|
||||||
#include <linux/nospec.h>
|
#include <linux/nospec.h>
|
||||||
#include <asm/barrier.h>
|
#include <asm/barrier.h>
|
||||||
|
|
||||||
#define NVADSP_MAILBOX_START 512
|
#define NVADSP_MAILBOX_START 512
|
||||||
#define NVADSP_MAILBOX_MAX 1024
|
|
||||||
#define NVADSP_MAILBOX_OS_MAX 16
|
|
||||||
|
|
||||||
static struct nvadsp_mbox *nvadsp_mboxes[NVADSP_MAILBOX_MAX];
|
|
||||||
static DECLARE_BITMAP(nvadsp_mbox_ids, NVADSP_MAILBOX_MAX);
|
|
||||||
static struct nvadsp_drv_data *nvadsp_drv_data;
|
|
||||||
|
|
||||||
static inline bool is_mboxq_empty(struct nvadsp_mbox_queue *queue)
|
static inline bool is_mboxq_empty(struct nvadsp_mbox_queue *queue)
|
||||||
{
|
{
|
||||||
@@ -123,7 +118,8 @@ static void mboxq_dump(struct nvadsp_mbox_queue *queue)
|
|||||||
spin_unlock_irqrestore(&queue->lock, flags);
|
spin_unlock_irqrestore(&queue->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t nvadsp_mbox_alloc_mboxid(void)
|
static uint16_t nvadsp_mbox_alloc_mboxid(
|
||||||
|
struct nvadsp_drv_data *nvadsp_drv_data)
|
||||||
{
|
{
|
||||||
unsigned long start = NVADSP_MAILBOX_START;
|
unsigned long start = NVADSP_MAILBOX_START;
|
||||||
unsigned int nr = 1;
|
unsigned int nr = 1;
|
||||||
@@ -138,20 +134,31 @@ static uint16_t nvadsp_mbox_alloc_mboxid(void)
|
|||||||
return mid;
|
return mid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static status_t nvadsp_mbox_free_mboxid(uint16_t mid)
|
static status_t nvadsp_mbox_free_mboxid(
|
||||||
|
struct nvadsp_drv_data *nvadsp_drv_data, uint16_t mid)
|
||||||
{
|
{
|
||||||
bitmap_clear(nvadsp_drv_data->mbox_ids, mid, 1);
|
bitmap_clear(nvadsp_drv_data->mbox_ids, mid, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox, uint16_t *mid,
|
static void _nvadsp_mbox_set_ack_handler(struct nvadsp_handle *nvadsp_handle,
|
||||||
const char *name, nvadsp_mbox_handler_t handler,
|
struct nvadsp_mbox *mbox,
|
||||||
void *hdata)
|
nvadsp_mbox_handler_t handler)
|
||||||
{
|
{
|
||||||
|
mbox->ack_handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
static status_t _nvadsp_mbox_open(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
struct nvadsp_mbox *mbox,
|
||||||
|
uint16_t *mid, const char *name,
|
||||||
|
nvadsp_mbox_handler_t handler, void *hdata)
|
||||||
|
{
|
||||||
|
struct nvadsp_drv_data *nvadsp_drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!nvadsp_drv_data) {
|
if (!nvadsp_drv_data || !nvadsp_drv_data->pdev) {
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -164,7 +171,7 @@ status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox, uint16_t *mid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*mid == 0) {
|
if (*mid == 0) {
|
||||||
mbox->id = nvadsp_mbox_alloc_mboxid();
|
mbox->id = nvadsp_mbox_alloc_mboxid(nvadsp_drv_data);
|
||||||
if (mbox->id >= NVADSP_MAILBOX_MAX) {
|
if (mbox->id >= NVADSP_MAILBOX_MAX) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
mbox->id = 0;
|
mbox->id = 0;
|
||||||
@@ -201,14 +208,18 @@ status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox, uint16_t *mid,
|
|||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_mbox_open);
|
|
||||||
|
|
||||||
status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox, uint32_t data,
|
static status_t _nvadsp_mbox_send(struct nvadsp_handle *nvadsp_handle,
|
||||||
uint32_t flags, bool block, unsigned int timeout)
|
struct nvadsp_mbox *mbox, uint32_t data,
|
||||||
|
uint32_t flags, bool block, unsigned int timeout)
|
||||||
{
|
{
|
||||||
|
struct nvadsp_drv_data *nvadsp_drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
|
struct hwmbox_queue *hwmbox_send_queue;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!nvadsp_drv_data) {
|
if (!nvadsp_drv_data || !nvadsp_drv_data->pdev ||
|
||||||
|
!nvadsp_drv_data->hwmbox_send_queue) {
|
||||||
pr_err("ADSP drv_data is NULL\n");
|
pr_err("ADSP drv_data is NULL\n");
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -220,16 +231,18 @@ status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox, uint32_t data,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hwmbox_send_queue = nvadsp_drv_data->hwmbox_send_queue;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
ret = nvadsp_hwmbox_send_data(mbox->id, data, flags);
|
ret = nvadsp_hwmbox_send_data(nvadsp_drv_data, mbox->id, data, flags);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (ret == -EBUSY) {
|
if (ret == -EBUSY) {
|
||||||
if (block) {
|
if (block) {
|
||||||
ret = wait_for_completion_timeout(
|
ret = wait_for_completion_timeout(
|
||||||
&nvadsp_drv_data->hwmbox_send_queue.comp,
|
&hwmbox_send_queue->comp,
|
||||||
msecs_to_jiffies(timeout));
|
msecs_to_jiffies(timeout));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_warn("ADSP HWMBOX send retry\n");
|
pr_warn("ADSP HWMBOX send retry\n");
|
||||||
block = false;
|
block = false;
|
||||||
@@ -250,14 +263,16 @@ status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox, uint32_t data,
|
|||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_mbox_send);
|
|
||||||
|
|
||||||
status_t nvadsp_mbox_recv(struct nvadsp_mbox *mbox, uint32_t *data, bool block,
|
static status_t _nvadsp_mbox_recv(struct nvadsp_handle *nvadsp_handle,
|
||||||
unsigned int timeout)
|
struct nvadsp_mbox *mbox, uint32_t *data,
|
||||||
|
bool block, unsigned int timeout)
|
||||||
{
|
{
|
||||||
|
struct nvadsp_drv_data *nvadsp_drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!nvadsp_drv_data) {
|
if (!nvadsp_drv_data || !nvadsp_drv_data->pdev) {
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -294,14 +309,16 @@ status_t nvadsp_mbox_recv(struct nvadsp_mbox *mbox, uint32_t *data, bool block,
|
|||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_mbox_recv);
|
|
||||||
|
|
||||||
status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox)
|
static status_t _nvadsp_mbox_close(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
struct nvadsp_mbox *mbox)
|
||||||
{
|
{
|
||||||
|
struct nvadsp_drv_data *nvadsp_drv_data =
|
||||||
|
(struct nvadsp_drv_data *)nvadsp_handle;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!nvadsp_drv_data) {
|
if (!nvadsp_drv_data || !nvadsp_drv_data->pdev) {
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -318,7 +335,7 @@ status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
nvadsp_mbox_free_mboxid(mbox->id);
|
nvadsp_mbox_free_mboxid(nvadsp_drv_data, mbox->id);
|
||||||
mboxq_destroy(&mbox->recv_queue);
|
mboxq_destroy(&mbox->recv_queue);
|
||||||
nvadsp_drv_data->mboxes[mbox->id] = NULL;
|
nvadsp_drv_data->mboxes[mbox->id] = NULL;
|
||||||
out:
|
out:
|
||||||
@@ -326,18 +343,22 @@ status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox)
|
|||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nvadsp_mbox_close);
|
|
||||||
|
|
||||||
status_t __init nvadsp_mbox_init(struct platform_device *pdev)
|
status_t __init nvadsp_mbox_init(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
struct nvadsp_drv_data *drv = platform_get_drvdata(pdev);
|
||||||
|
struct nvadsp_handle *nvadsp_handle = &drv->nvadsp_handle;
|
||||||
|
|
||||||
drv->mboxes = nvadsp_mboxes;
|
memset(drv->mboxes, 0, sizeof(drv->mboxes));
|
||||||
drv->mbox_ids = nvadsp_mbox_ids;
|
memset(drv->mbox_ids, 0, sizeof(drv->mbox_ids));
|
||||||
|
|
||||||
spin_lock_init(&drv->mbox_lock);
|
spin_lock_init(&drv->mbox_lock);
|
||||||
|
|
||||||
nvadsp_drv_data = drv;
|
nvadsp_handle->mbox_open = _nvadsp_mbox_open;
|
||||||
|
nvadsp_handle->mbox_close = _nvadsp_mbox_close;
|
||||||
|
nvadsp_handle->mbox_send = _nvadsp_mbox_send;
|
||||||
|
nvadsp_handle->mbox_recv = _nvadsp_mbox_recv;
|
||||||
|
nvadsp_handle->mbox_set_ack_handler = _nvadsp_mbox_set_ack_handler;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2015-2023, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2015-2024, NVIDIA CORPORATION. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <linux/tegra-hsp.h>
|
#include <linux/tegra-hsp.h>
|
||||||
|
|
||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
|
#include "hwmailbox.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "dev-t18x.h"
|
#include "dev-t18x.h"
|
||||||
|
|
||||||
@@ -78,10 +79,12 @@ int nvadsp_os_t18x_init(struct platform_device *pdev)
|
|||||||
val = val | (adma_ch_page << ADSP_CONFIG_DMA_PAGE_SHIFT);
|
val = val | (adma_ch_page << ADSP_CONFIG_DMA_PAGE_SHIFT);
|
||||||
|
|
||||||
/* Write to HWMBOX5 */
|
/* Write to HWMBOX5 */
|
||||||
hwmbox_writel(val, drv_data->chip_data->adsp_os_config_hwmbox);
|
hwmbox_writel(drv_data, val,
|
||||||
|
drv_data->chip_data->adsp_os_config_hwmbox);
|
||||||
|
|
||||||
/* Clear HWMBOX0 for ADSP Guest reset handling */
|
/* Clear HWMBOX0 for ADSP Guest reset handling */
|
||||||
hwmbox_writel(0, drv_data->chip_data->hwmb.hwmbox0_reg);
|
hwmbox_writel(drv_data, 0,
|
||||||
|
drv_data->chip_data->hwmb.hwmbox0_reg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -168,11 +168,12 @@ static inline int nvadsp_os_init(struct platform_device *pdev)
|
|||||||
|
|
||||||
int nvadsp_os_probe(struct platform_device *);
|
int nvadsp_os_probe(struct platform_device *);
|
||||||
int nvadsp_app_module_probe(struct platform_device *);
|
int nvadsp_app_module_probe(struct platform_device *);
|
||||||
void *nvadsp_da_to_va_mappings(u64 da, int len);
|
void *nvadsp_da_to_va_mappings(struct nvadsp_drv_data *, u64 da, int len);
|
||||||
int nvadsp_add_load_mappings(phys_addr_t pa, void *mapping, int len);
|
int nvadsp_add_load_mappings(struct nvadsp_drv_data *,
|
||||||
|
phys_addr_t pa, void *mapping, int len);
|
||||||
struct elf32_shdr *nvadsp_get_section(const struct firmware *, char *);
|
struct elf32_shdr *nvadsp_get_section(const struct firmware *, char *);
|
||||||
struct global_sym_info *find_global_symbol(const char *);
|
struct global_sym_info *find_global_symbol(struct nvadsp_drv_data *,
|
||||||
void update_nvadsp_app_shared_ptr(void *);
|
const char *);
|
||||||
|
|
||||||
struct adsp_module *load_adsp_dynamic_module(const char *, const char *,
|
struct adsp_module *load_adsp_dynamic_module(const char *, const char *,
|
||||||
struct device *);
|
struct device *);
|
||||||
@@ -180,7 +181,6 @@ struct adsp_module *load_adsp_static_module(const char *,
|
|||||||
struct adsp_shared_app *, struct device *);
|
struct adsp_shared_app *, struct device *);
|
||||||
void unload_adsp_module(struct adsp_module *);
|
void unload_adsp_module(struct adsp_module *);
|
||||||
|
|
||||||
int allocate_memory_from_adsp(void **, unsigned int);
|
int load_adsp_static_apps(struct nvadsp_drv_data *);
|
||||||
bool is_adsp_dram_addr(u64);
|
|
||||||
int load_adsp_static_apps(void);
|
|
||||||
#endif /* __TEGRA_NVADSP_OS_H */
|
#endif /* __TEGRA_NVADSP_OS_H */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/**
|
/**
|
||||||
* Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __LINUX_TEGRA_NVADSP_H
|
#ifndef __LINUX_TEGRA_NVADSP_H
|
||||||
@@ -16,11 +16,6 @@
|
|||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
|
|
||||||
struct nvadsp_platform_data {
|
|
||||||
phys_addr_t co_pa;
|
|
||||||
unsigned long co_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int status_t;
|
typedef int status_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -83,32 +78,13 @@ struct nvadsp_mbox {
|
|||||||
char name[NVADSP_MBOX_NAME_MAX_STR];
|
char name[NVADSP_MBOX_NAME_MAX_STR];
|
||||||
struct nvadsp_mbox_queue recv_queue;
|
struct nvadsp_mbox_queue recv_queue;
|
||||||
nvadsp_mbox_handler_t handler;
|
nvadsp_mbox_handler_t handler;
|
||||||
#ifdef CONFIG_MBOX_ACK_HANDLER
|
|
||||||
nvadsp_mbox_handler_t ack_handler;
|
nvadsp_mbox_handler_t ack_handler;
|
||||||
#endif
|
|
||||||
void *hdata;
|
void *hdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NVADSP_MBOX_SMSG 0x1
|
#define NVADSP_MBOX_SMSG 0x1
|
||||||
#define NVADSP_MBOX_LMSG 0x2
|
#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
|
* Circular Message Queue
|
||||||
*/
|
*/
|
||||||
@@ -142,54 +118,12 @@ 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);
|
int32_t msgq_dequeue_message(msgq_t *msgq, msgq_message_t *message);
|
||||||
#define msgq_discard_message(msgq) msgq_dequeue_message(msgq, NULL)
|
#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
|
* ADSP OS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef const void *nvadsp_os_handle_t;
|
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
|
* ADSP TSC
|
||||||
*/
|
*/
|
||||||
@@ -287,71 +221,6 @@ typedef struct nvadsp_app_info {
|
|||||||
void *priv;
|
void *priv;
|
||||||
} nvadsp_app_info_t;
|
} 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
|
#ifdef CONFIG_TEGRA_ADSP_DFS
|
||||||
/*
|
/*
|
||||||
* Override adsp freq and reinit actmon counters
|
* Override adsp freq and reinit actmon counters
|
||||||
@@ -384,10 +253,284 @@ static inline void adsp_update_dfs(bool enable)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void *nvadsp_aram_request(const char *name, size_t size);
|
void *nvadsp_aram_request(void *aram_handle, const char *name, size_t size);
|
||||||
bool nvadsp_aram_release(void *handle);
|
bool nvadsp_aram_release(void *aram_handle, void *handle);
|
||||||
|
|
||||||
unsigned long nvadsp_aram_get_address(void *handle);
|
unsigned long nvadsp_aram_get_address(void *handle);
|
||||||
void nvadsp_aram_print(void);
|
void nvadsp_aram_print(void *aram_handle);
|
||||||
|
|
||||||
|
int adsp_usage_set(unsigned int val);
|
||||||
|
unsigned int adsp_usage_get(void);
|
||||||
|
|
||||||
|
|
||||||
|
/* Multi-instance capable interface - START */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nvadsp_get_handle: Fetch driver instance using unique identfier
|
||||||
|
*
|
||||||
|
* @dev_str : Unique identifier string for the driver instance
|
||||||
|
* (trailing unique identifer in compatible DT property,
|
||||||
|
* e.g. "adsp", "adsp1", etc.)
|
||||||
|
*
|
||||||
|
* Return : Driver instance handle on success, else NULL
|
||||||
|
*/
|
||||||
|
struct nvadsp_handle *nvadsp_get_handle(const char *dev_str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct nvadsp_handle:
|
||||||
|
* - Function interfaces exposed on the driver handle
|
||||||
|
* - First argument to each API is the handle
|
||||||
|
* returned from nvadsp_get_handle()
|
||||||
|
*/
|
||||||
|
struct nvadsp_handle {
|
||||||
|
/* Mailbox interfaces */
|
||||||
|
status_t (*mbox_open)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
struct nvadsp_mbox *mbox,
|
||||||
|
uint16_t *mid, const char *name,
|
||||||
|
nvadsp_mbox_handler_t handler, void *hdata);
|
||||||
|
status_t (*mbox_close)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
struct nvadsp_mbox *mbox);
|
||||||
|
status_t (*mbox_send)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
struct nvadsp_mbox *mbox, uint32_t data,
|
||||||
|
uint32_t flags, bool block, unsigned int timeout);
|
||||||
|
status_t (*mbox_recv)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
struct nvadsp_mbox *mbox, uint32_t *data,
|
||||||
|
bool block, unsigned int timeout);
|
||||||
|
void (*mbox_set_ack_handler)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
struct nvadsp_mbox *mbox,
|
||||||
|
nvadsp_mbox_handler_t handler);
|
||||||
|
|
||||||
|
/* OS interfaces */
|
||||||
|
void (*get_os_version)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
char *buf, int buf_size);
|
||||||
|
int (*os_load)(struct nvadsp_handle *nvadsp_handle);
|
||||||
|
int (*os_start)(struct nvadsp_handle *nvadsp_handle);
|
||||||
|
int (*os_suspend)(struct nvadsp_handle *nvadsp_handle);
|
||||||
|
void (*os_stop)(struct nvadsp_handle *nvadsp_handle);
|
||||||
|
|
||||||
|
/* Debug interfaces */
|
||||||
|
void (*set_adma_dump_reg)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
void (*cb_adma_regdump)(void));
|
||||||
|
void (*dump_adsp_sys)(struct nvadsp_handle *nvadsp_handle);
|
||||||
|
|
||||||
|
/* Memory interfaces */
|
||||||
|
void *(*alloc_coherent)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
size_t size, dma_addr_t *da, gfp_t flags);
|
||||||
|
void (*free_coherent)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
size_t size, void *va, dma_addr_t da);
|
||||||
|
|
||||||
|
/* App interfaces */
|
||||||
|
nvadsp_app_handle_t (*app_load)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
const char *appname, const char *appfile);
|
||||||
|
nvadsp_app_info_t *(*app_init)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_handle_t handle, nvadsp_app_args_t *args);
|
||||||
|
int (*app_start)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *app);
|
||||||
|
nvadsp_app_info_t *(*run_app)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_os_handle_t os_handle,
|
||||||
|
const char *appfile, nvadsp_app_args_t *app_args,
|
||||||
|
app_complete_status_notifier notifier, uint32_t stack_sz,
|
||||||
|
uint32_t core_id, bool block);
|
||||||
|
int (*app_stop)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *app);
|
||||||
|
int (*app_deinit)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *app);
|
||||||
|
void (*exit_app)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *app, bool terminate);
|
||||||
|
void (*app_unload)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_handle_t handle);
|
||||||
|
void (*set_app_complete_cb)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *info, app_complete_status_notifier notifier);
|
||||||
|
void (*wait_for_app_complete)(struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *info);
|
||||||
|
long (*wait_for_app_complete_timeout)(
|
||||||
|
struct nvadsp_handle *nvadsp_handle,
|
||||||
|
nvadsp_app_info_t *info, unsigned long timeout);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Multi-instance capable interface - END */
|
||||||
|
|
||||||
|
|
||||||
|
/* Legacy interface - START (works if only one driver instance is probed) */
|
||||||
|
|
||||||
|
static inline status_t nvadsp_mbox_open(struct nvadsp_mbox *mbox,
|
||||||
|
uint16_t *mid, const char *name,
|
||||||
|
nvadsp_mbox_handler_t handler, void *hdata)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->mbox_open(h, mbox, mid, name, handler, hdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline status_t nvadsp_mbox_close(struct nvadsp_mbox *mbox)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->mbox_close(h, mbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline status_t nvadsp_mbox_send(struct nvadsp_mbox *mbox,
|
||||||
|
uint32_t data, uint32_t flags,
|
||||||
|
bool block, unsigned int timeout)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->mbox_send(h, mbox, data, flags, block, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline status_t nvadsp_mbox_recv(struct nvadsp_mbox *mbox,
|
||||||
|
uint32_t *data, bool block,
|
||||||
|
unsigned int timeout)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->mbox_recv(h, mbox, data, block, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void register_ack_handler(struct nvadsp_mbox *mbox,
|
||||||
|
nvadsp_mbox_handler_t handler)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->mbox_set_ack_handler(h, mbox, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nvadsp_get_os_version(char *buf, int buf_size)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->get_os_version(h, buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int nvadsp_os_load(void)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->os_load(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int nvadsp_os_start(void)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->os_start(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int nvadsp_os_suspend(void)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->os_suspend(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nvadsp_os_stop(void)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->os_stop(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nvadsp_set_adma_dump_reg(void (*cb_adma_regdump)(void))
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->set_adma_dump_reg(h, cb_adma_regdump);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dump_adsp_sys(void)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->dump_adsp_sys(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *nvadsp_alloc_coherent(
|
||||||
|
size_t size, dma_addr_t *da, gfp_t flags)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->alloc_coherent(h, size, da, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nvadsp_free_coherent(size_t size, void *va, dma_addr_t da)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->free_coherent(h, size, va, da);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline nvadsp_app_handle_t nvadsp_app_load(
|
||||||
|
const char *appname, const char *appfile)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->app_load(h, appname, appfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline nvadsp_app_info_t *nvadsp_app_init(
|
||||||
|
nvadsp_app_handle_t handle, nvadsp_app_args_t *args)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->app_init(h, handle, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int nvadsp_app_start(nvadsp_app_info_t *app)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->app_start(h, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline nvadsp_app_info_t *nvadsp_run_app(
|
||||||
|
nvadsp_os_handle_t os_handle, const char *appfile,
|
||||||
|
nvadsp_app_args_t *app_args, app_complete_status_notifier notifier,
|
||||||
|
uint32_t stack_sz, uint32_t core_id, bool block)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->run_app(h, os_handle, appfile, app_args,
|
||||||
|
notifier, stack_sz, core_id, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int nvadsp_app_stop(nvadsp_app_info_t *app)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->app_stop(h, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int nvadsp_app_deinit(nvadsp_app_info_t *app)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->app_deinit(h, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nvadsp_exit_app(nvadsp_app_info_t *app, bool terminate)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->exit_app(h, app, terminate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nvadsp_app_unload(nvadsp_app_handle_t handle)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->app_unload(h, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_app_complete_notifier(
|
||||||
|
nvadsp_app_info_t *info,
|
||||||
|
app_complete_status_notifier notifier)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->set_app_complete_cb(h, info, notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void wait_for_nvadsp_app_complete(nvadsp_app_info_t *info)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->wait_for_app_complete(h, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
struct nvadsp_handle *h = nvadsp_get_handle("");
|
||||||
|
return h->wait_for_app_complete_timeout(h, info, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Legacy interface - END */
|
||||||
|
|
||||||
#endif /* __LINUX_TEGRA_NVADSP_H */
|
#endif /* __LINUX_TEGRA_NVADSP_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user