From cb8fd9beb2ba305b36fb7f071a47a94dc42920ae Mon Sep 17 00:00:00 2001 From: Hariharan Sivaraman Date: Mon, 4 Mar 2019 16:18:00 +0530 Subject: [PATCH] nvadsp: allocate adsp shared memory dynamically NVADSP driver tries to allocate shared memory for ADSP by requesting the DMA APIs to allocate at address hardcoded in DT. This poses an issue where if kernel has already allocated that memory to a different driver in same iommu group, this memory becomes unavailable and ADSP does not boot Adding support to allocate shared memory for ADSP dynamically to avoid dependencies on other drivers Jira EMA-1213 Change-Id: I1bc8d49f17ec8226d34f3c943cccabef97b2afb6 Signed-off-by: Hariharan Sivaraman Reviewed-on: https://git-master.nvidia.com/r/2134341 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Uday Gupta GVS: Gerrit_Virtual_Submit Tested-by: Niranjan Dighe Reviewed-by: Nitin Pai Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/platform/tegra/nvadsp/dev.c | 16 +++++++++------- drivers/platform/tegra/nvadsp/dev.h | 2 ++ drivers/platform/tegra/nvadsp/os.c | 28 +++++++++++++++++++++++----- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/drivers/platform/tegra/nvadsp/dev.c b/drivers/platform/tegra/nvadsp/dev.c index 93b3f4e8..82d50103 100644 --- a/drivers/platform/tegra/nvadsp/dev.c +++ b/drivers/platform/tegra/nvadsp/dev.c @@ -3,7 +3,7 @@ * * A device driver for ADSP and APE * - * Copyright (C) 2014-2018, NVIDIA Corporation. All rights reserved. + * Copyright (C) 2014-2019, NVIDIA Corporation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -414,9 +414,10 @@ static struct nvadsp_chipdata tegra210_adsp_chipdata = { .hwmbox2_reg = 0x60, .hwmbox3_reg = 0x64, }, - .adsp_state_hwmbox = -1, - .adsp_thread_hwmbox = -1, - .adsp_irq_hwmbox = -1, + .adsp_state_hwmbox = 0, + .adsp_thread_hwmbox = 0, + .adsp_irq_hwmbox = 0, + .adsp_shared_mem_hwmbox = 0, .reset_init = nvadsp_reset_t21x_init, .os_init = nvadsp_os_t21x_init, #ifdef CONFIG_PM @@ -439,9 +440,10 @@ static struct nvadsp_chipdata tegrat18x_adsp_chipdata = { .hwmbox6_reg = 0X30000, .hwmbox7_reg = 0X38000, }, - .adsp_state_hwmbox = 0x30000, - .adsp_thread_hwmbox = 0x20000, - .adsp_irq_hwmbox = 0x38000, + .adsp_shared_mem_hwmbox = 0x18000, /* HWMBOX3 */ + .adsp_thread_hwmbox = 0x20000, /* HWMBOX4 */ + .adsp_state_hwmbox = 0x30000, /* HWMBOX6 */ + .adsp_irq_hwmbox = 0x38000, /* HWMBOX7 */ .reset_init = nvadsp_reset_t18x_init, .os_init = nvadsp_os_t18x_init, #ifdef CONFIG_PM diff --git a/drivers/platform/tegra/nvadsp/dev.h b/drivers/platform/tegra/nvadsp/dev.h index dbdcbdbf..a11e7e9a 100644 --- a/drivers/platform/tegra/nvadsp/dev.h +++ b/drivers/platform/tegra/nvadsp/dev.h @@ -132,6 +132,7 @@ struct nvadsp_chipdata { u32 adsp_state_hwmbox; u32 adsp_thread_hwmbox; u32 adsp_irq_hwmbox; + u32 adsp_shared_mem_hwmbox; reset_init reset_init; os_init os_init; #ifdef CONFIG_PM @@ -182,6 +183,7 @@ struct nvadsp_drv_data { bool adsp_os_secload; void *shared_adsp_os_data; + dma_addr_t shared_adsp_os_data_iova; #ifdef CONFIG_TEGRA_ADSP_DFS bool dfs_initialized; diff --git a/drivers/platform/tegra/nvadsp/os.c b/drivers/platform/tegra/nvadsp/os.c index 73deff89..c6ae939e 100644 --- a/drivers/platform/tegra/nvadsp/os.c +++ b/drivers/platform/tegra/nvadsp/os.c @@ -775,12 +775,22 @@ static int __nvadsp_os_secload(struct platform_device *pdev) struct device *dev = &pdev->dev; void *dram_va; - dram_va = nvadsp_dma_alloc_and_map_at(pdev, size, addr, GFP_KERNEL); - if (!dram_va) { - dev_err(dev, "unable to allocate shared region\n"); - return -ENOMEM; + if (drv_data->chip_data->adsp_shared_mem_hwmbox != 0) { + dram_va = nvadsp_alloc_coherent(size, &addr, GFP_KERNEL); + if (dram_va == NULL) { + dev_err(dev, "unable to allocate shared region\n"); + return -ENOMEM; + } + } else { + dram_va = nvadsp_dma_alloc_and_map_at(pdev, size, addr, + GFP_KERNEL); + if (dram_va == NULL) { + dev_err(dev, "unable to allocate shared region\n"); + return -ENOMEM; + } } + drv_data->shared_adsp_os_data_iova = addr; nvadsp_set_shared_mem(pdev, dram_va, 0); return 0; @@ -1400,7 +1410,7 @@ static void get_adsp_state(void) drv_data = platform_get_drvdata(priv.pdev); dev = &priv.pdev->dev; - if (drv_data->chip_data->adsp_state_hwmbox == -1) { + if (drv_data->chip_data->adsp_state_hwmbox == 0) { dev_info(dev, "%s: No state hwmbox available\n", __func__); return; } @@ -1672,6 +1682,7 @@ int nvadsp_os_start(void) struct nvadsp_drv_data *drv_data; struct device *dev; int ret = 0; + static int cold_start = 1; if (!priv.pdev) { pr_err("ADSP Driver is not initialized\n"); @@ -1703,6 +1714,13 @@ int nvadsp_os_start(void) if (ret < 0) goto unlock; + if (cold_start && drv_data->chip_data->adsp_shared_mem_hwmbox != 0) { + hwmbox_writel((uint32_t)drv_data->shared_adsp_os_data_iova, + drv_data->chip_data->adsp_shared_mem_hwmbox); + /* Write ACSR base address only once */ + cold_start = 0; + } + ret = __nvadsp_os_start(); if (ret) { priv.os_running = drv_data->adsp_os_running = false;