diff --git a/drivers/platform/tegra/nvadsp/adsp_dfs.c b/drivers/platform/tegra/nvadsp/adsp_dfs.c index 6e9f6884..3f3dd243 100644 --- a/drivers/platform/tegra/nvadsp/adsp_dfs.c +++ b/drivers/platform/tegra/nvadsp/adsp_dfs.c @@ -3,7 +3,7 @@ * * adsp dynamic frequency scaling * - * Copyright (C) 2014-2019, NVIDIA Corporation. All rights reserved. + * Copyright (C) 2014-2020, 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 @@ -361,10 +361,8 @@ static unsigned long update_freq(unsigned long freq_khz) efreq = adsp_to_emc_freq(tfreq_hz / 1000); - ret = tegra_bwmgr_set_emc(drv->bwmgr, efreq * 1000, - TEGRA_BWMGR_SET_EMC_FLOOR); + ret = nvadsp_set_bw(drv, efreq); if (ret) { - dev_err(device, "failed to set emc freq rate:%d\n", ret); policy->update_freq_flag = false; goto err_out; } @@ -401,13 +399,10 @@ err_out: efreq = adsp_to_emc_freq(old_freq_khz); - ret = tegra_bwmgr_set_emc(drv->bwmgr, efreq * 1000, - TEGRA_BWMGR_SET_EMC_FLOOR); - if (ret) { - dev_err(device, "failed to set emc freq rate:%d\n", - ret); + ret = nvadsp_set_bw(drv, efreq); + if (ret) policy->update_freq_flag = false; - } + tfreq_hz = old_freq_khz * 1000; } return tfreq_hz / 1000; @@ -829,12 +824,9 @@ int adsp_dfs_core_init(struct platform_device *pdev) efreq = adsp_to_emc_freq(policy->cur); - ret = tegra_bwmgr_set_emc(drv->bwmgr, efreq * 1000, - TEGRA_BWMGR_SET_EMC_FLOOR); - if (ret) { - dev_err(device, "failed to set emc freq rate:%d\n", ret); + ret = nvadsp_set_bw(drv, efreq); + if (ret) goto end; - } adsp_get_target_freq(policy->cur * 1000, &freq_stats.last_index); freq_stats.last_time = get_jiffies_64(); diff --git a/drivers/platform/tegra/nvadsp/dev.c b/drivers/platform/tegra/nvadsp/dev.c index 21997ae1..58114d70 100644 --- a/drivers/platform/tegra/nvadsp/dev.c +++ b/drivers/platform/tegra/nvadsp/dev.c @@ -136,6 +136,73 @@ uint64_t nvadsp_get_timestamp_counter(void) } EXPORT_SYMBOL(nvadsp_get_timestamp_counter); +int nvadsp_set_bw(struct nvadsp_drv_data *drv_data, u32 efreq) +{ + int ret = -EINVAL; + + if (drv_data->bwmgr) + ret = tegra_bwmgr_set_emc(drv_data->bwmgr, efreq * 1000, + TEGRA_BWMGR_SET_EMC_FLOOR); +#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE + else if (drv_data->icc_path_handle) + ret = icc_set_bw(drv_data->icc_path_handle, 0, + (unsigned long)FREQ2ICC(efreq * 1000)); +#endif + if (ret) + dev_err(&drv_data->pdev->dev, + "failed to set emc freq rate:%d\n", ret); + + return ret; +} + +static void nvadsp_bw_register(struct nvadsp_drv_data *drv_data) +{ + struct device *dev = &drv_data->pdev->dev; + + switch (tegra_get_chip_id()) { + case TEGRA210: + case TEGRA186: + case TEGRA194: + drv_data->bwmgr = tegra_bwmgr_register( + TEGRA_BWMGR_CLIENT_APE_ADSP); + if (IS_ERR(drv_data->bwmgr)) { + dev_err(dev, "unable to register bwmgr\n"); + drv_data->bwmgr = NULL; + } + break; + default: +#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE + /* Interconnect Support */ + drv_data->icc_path_handle = icc_get(dev, TEGRA_ICC_APE, + TEGRA_ICC_PRIMARY); + if (IS_ERR(drv_data->icc_path_handle)) { + dev_err(dev, + "%s: Failed to register Interconnect. err=%ld\n", + __func__, PTR_ERR(drv_data->icc_path_handle)); + drv_data->icc_path_handle = NULL; + } +#endif + break; + } +} + +static void nvadsp_bw_unregister(struct nvadsp_drv_data *drv_data) +{ + nvadsp_set_bw(drv_data, 0); + + if (drv_data->bwmgr) { + tegra_bwmgr_unregister(drv_data->bwmgr); + drv_data->bwmgr = NULL; + } + +#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE + if (drv_data->icc_path_handle) { + icc_put(drv_data->icc_path_handle); + drv_data->icc_path_handle = NULL; + } +#endif +} + static void __init nvadsp_parse_clk_entries(struct platform_device *pdev) { struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); @@ -376,10 +443,7 @@ static int __init nvadsp_probe(struct platform_device *pdev) if (ret) dev_err(dev, "Failed to init aram\n"); - drv_data->bwmgr = tegra_bwmgr_register(TEGRA_BWMGR_CLIENT_APE_ADSP); - ret = IS_ERR_OR_NULL(drv_data->bwmgr); - if (ret) - dev_err(&pdev->dev, "unable to register bwmgr\n"); + nvadsp_bw_register(drv_data); err: #ifdef CONFIG_PM ret = pm_runtime_put_sync(dev); @@ -393,17 +457,9 @@ out: static int nvadsp_remove(struct platform_device *pdev) { struct nvadsp_drv_data *drv_data = platform_get_drvdata(pdev); - int err; - if (drv_data->bwmgr) { - err = tegra_bwmgr_set_emc(drv_data->bwmgr, 0, - TEGRA_BWMGR_SET_EMC_FLOOR); - if (err) { - dev_err(&pdev->dev, "failed to set emc freq rate:%d\n", - err); - } - tegra_bwmgr_unregister(drv_data->bwmgr); - } + nvadsp_bw_unregister(drv_data); + nvadsp_aram_exit(); pm_runtime_disable(&pdev->dev); diff --git a/drivers/platform/tegra/nvadsp/dev.h b/drivers/platform/tegra/nvadsp/dev.h index 75bfc448..10a5a125 100644 --- a/drivers/platform/tegra/nvadsp/dev.h +++ b/drivers/platform/tegra/nvadsp/dev.h @@ -3,7 +3,7 @@ * * A header file for Host driver for ADSP and APE * - * Copyright (C) 2014-2019, NVIDIA Corporation. All rights reserved. + * Copyright (C) 2014-2020, 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 @@ -25,6 +25,11 @@ #include #include +#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE +#include +#include +#include +#endif #include "hwmailbox.h" #include "amc.h" @@ -89,6 +94,9 @@ enum adsp_unit_fpga_reset { #define AMISC_REG_MBOX_OFFSET 0x64 #define ADSP_ACTMON_REG_START_OFFSET 0x800 #define ADSP_ACTMON_REG_END_OFFSET 0x828 +#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE +#define FREQ2ICC(x) (Bps_to_icc(emc_freq_to_bw(x))) +#endif enum nvadsp_virqs { MBOX_SEND_VIRQ, @@ -214,6 +222,9 @@ struct nvadsp_drv_data { int agic_irqs[NVADSP_VIRQ_MAX]; struct tegra_bwmgr_client *bwmgr; +#if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE + struct icc_path *icc_path_handle; /* icc_path handle handle */ +#endif u32 evp_base[ADSP_EVP_END]; const struct nvadsp_chipdata *chip_data; @@ -227,6 +238,7 @@ status_t nvadsp_mbox_init(struct platform_device *pdev); int nvadsp_setup_amc_interrupts(struct platform_device *pdev); void nvadsp_free_amc_interrupts(struct platform_device *pdev); +int nvadsp_set_bw(struct nvadsp_drv_data *drv, u32 efreq); #ifdef CONFIG_TEGRA_ADSP_DFS void adsp_cpu_set_rate(unsigned long freq); diff --git a/drivers/platform/tegra/nvadsp/os.c b/drivers/platform/tegra/nvadsp/os.c index f860d479..d6eb7e85 100644 --- a/drivers/platform/tegra/nvadsp/os.c +++ b/drivers/platform/tegra/nvadsp/os.c @@ -936,10 +936,7 @@ static int nvadsp_set_ape_emc_freq(struct nvadsp_drv_data *drv_data) if (!ape_emc_freq) return 0; - ret = tegra_bwmgr_set_emc(drv_data->bwmgr, ape_emc_freq * 1000, - TEGRA_BWMGR_SET_EMC_FLOOR); - if (ret) - dev_err(dev, "failed to set emc freq rate:%d\n", ret); + ret = nvadsp_set_bw(drv_data, ape_emc_freq); dev_dbg(dev, "ape.emc freq %luKHz\n", tegra_bwmgr_get_emc_rate() / 1000);