platform: tegra: adsp: use bwmgr to set emc freq

Shared clocks on 4.9 have been deprecated.
This has been replaced by tegra bandwidth managers.

bug 200359628

Change-Id: Ib23ad57d36c501c16ade33d27d846f0d24217b34
Signed-off-by: Prateek Patel <prpatel@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1597879
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Prateek Patel
2017-11-14 04:55:15 -08:00
committed by Laxman Dewangan
parent a82f3515d6
commit d25d71e53f
5 changed files with 75 additions and 158 deletions

View File

@@ -100,7 +100,6 @@ struct adsp_dfs_policy {
struct clk *adsp_clk;
struct clk *aclk_clk;
struct clk *adsp_cpu_abus_clk;
struct notifier_block rate_change_nb;
struct nvadsp_mbox mbox;
#ifdef CONFIG_DEBUG_FS
@@ -126,7 +125,6 @@ struct adsp_freq_stats {
static struct adsp_dfs_policy *policy;
static struct adsp_freq_stats freq_stats;
static struct device *device;
static struct clk *ape_emc_clk;
static DEFINE_MUTEX(policy_mutex);
@@ -265,37 +263,9 @@ static void adspfreq_stats_update(void)
freq_stats.last_time = cur_time;
}
/* adsp clock rate change notifier callback */
static int adsp_dfs_rc_callback(
struct notifier_block *nb, unsigned long rate, void *v)
{
unsigned long freq = rate / 1000;
int old_index, new_index = 0;
/* update states */
adspfreq_stats_update();
old_index = freq_stats.last_index;
adsp_get_target_freq(rate, &new_index);
if (old_index != new_index)
freq_stats.last_index = new_index;
if (policy->ovr_freq && freq == policy->ovr_freq) {
/* Re-init ACTMON when user requested override freq is met */
actmon_rate_change(freq, true);
policy->ovr_freq = 0;
} else
actmon_rate_change(freq, false);
return NOTIFY_OK;
};
static struct adsp_dfs_policy dfs_policy = {
.enable = 1,
.clk_name = "adsp_cpu",
.rate_change_nb = {
.notifier_call = adsp_dfs_rc_callback,
},
};
static int adsp_update_freq_handshake(unsigned long tfreq_hz, int index)
@@ -396,16 +366,12 @@ static unsigned long update_freq(unsigned long freq_khz)
efreq = adsp_to_emc_freq(tfreq_hz / 1000);
if (IS_ENABLED(CONFIG_COMMON_CLK)) {
tegra_bwmgr_set_emc(drv->bwmgr, efreq * 1000,
TEGRA_BWMGR_SET_EMC_FLOOR);
} else {
ret = clk_set_rate(ape_emc_clk, efreq * 1000);
if (ret) {
dev_err(device, "failed to set ape.emc clk:%d\n", ret);
policy->update_freq_flag = false;
goto err_out;
}
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);
policy->update_freq_flag = false;
goto err_out;
}
/*
@@ -439,18 +405,14 @@ err_out:
}
efreq = adsp_to_emc_freq(old_freq_khz);
if (IS_ENABLED(CONFIG_COMMON_CLK)) {
tegra_bwmgr_set_emc(drv->bwmgr, efreq * 1000,
TEGRA_BWMGR_SET_EMC_FLOOR);
} else {
ret = clk_set_rate(ape_emc_clk, efreq * 1000);
if (ret) {
dev_err(device,
"failed to set ape.emc clk:%d\n", ret);
policy->update_freq_flag = false;
}
}
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);
policy->update_freq_flag = false;
}
tfreq_hz = old_freq_khz * 1000;
}
return tfreq_hz / 1000;
@@ -853,29 +815,6 @@ int adsp_dfs_core_init(struct platform_device *pdev)
if (ret)
goto end;
if (IS_ENABLED(CONFIG_COMMON_CLK)) {
drv->bwmgr = tegra_bwmgr_register(TEGRA_BWMGR_CLIENT_APE_ADSP);
if (IS_ERR_OR_NULL(drv->bwmgr)) {
dev_err(&pdev->dev, "unable to register bwmgr\n");
ret = PTR_ERR(drv->bwmgr);
goto end;
}
} else {
/* Change emc freq as per the adsp to emc lookup table */
ape_emc_clk = clk_get_sys("ape", "emc");
if (IS_ERR_OR_NULL(ape_emc_clk)) {
dev_err(device, "unable to find ape.emc clock\n");
ret = PTR_ERR(ape_emc_clk);
goto end;
}
ret = clk_prepare_enable(ape_emc_clk);
if (ret) {
dev_err(device, "unable to enable ape.emc clock\n");
goto end;
}
}
policy->max = policy->cpu_max = drv->adsp_freq; /* adsp_freq in KHz */
policy->min = policy->cpu_min = adsp_cpu_freq_table[0] / 1000;
@@ -884,15 +823,11 @@ int adsp_dfs_core_init(struct platform_device *pdev)
efreq = adsp_to_emc_freq(policy->cur);
if (IS_ENABLED(CONFIG_COMMON_CLK)) {
tegra_bwmgr_set_emc(drv->bwmgr, efreq * 1000,
TEGRA_BWMGR_SET_EMC_FLOOR);
} else {
ret = clk_set_rate(ape_emc_clk, efreq * 1000);
if (ret) {
dev_err(device, "failed to set ape.emc clk:%d\n", ret);
goto end;
}
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);
goto end;
}
adsp_get_target_freq(policy->cur * 1000, &freq_stats.last_index);
@@ -907,30 +842,6 @@ int adsp_dfs_core_init(struct platform_device *pdev)
goto end;
}
#if !defined(CONFIG_COMMON_CLK)
if (policy->rate_change_nb.notifier_call) {
/*
* "adsp_cpu" clk is a shared user of parent adsp_cpu_bus clk;
* rate change notification should come from bus clock itself.
*/
struct clk *p = clk_get_parent(policy->adsp_clk);
if (!p) {
dev_err(&pdev->dev, "Failed to find adsp cpu parent clock\n");
ret = -EINVAL;
goto end;
}
ret = tegra_register_clk_rate_notifier(p,
&policy->rate_change_nb);
if (ret) {
dev_err(&pdev->dev, "rate change notifier err: %s\n",
policy->clk_name);
nvadsp_mbox_close(&policy->mbox);
goto end;
}
}
#endif
#ifdef CONFIG_DEBUG_FS
adsp_dfs_debugfs_init(pdev);
#endif
@@ -942,15 +853,6 @@ end:
adsp_clk_put(policy);
if (IS_ENABLED(CONFIG_COMMON_CLK) && drv->bwmgr) {
tegra_bwmgr_set_emc(drv->bwmgr, 0,
TEGRA_BWMGR_SET_EMC_FLOOR);
tegra_bwmgr_unregister(drv->bwmgr);
} else if (ape_emc_clk) {
clk_disable_unprepare(ape_emc_clk);
clk_put(ape_emc_clk);
}
return ret;
}
@@ -968,21 +870,8 @@ int adsp_dfs_core_exit(struct platform_device *pdev)
dev_info(&pdev->dev,
"adsp dfs exit failed: mbox close error. ret:%d\n", ret);
#if !defined(CONFIG_COMMON_CLK)
tegra_unregister_clk_rate_notifier(clk_get_parent(policy->adsp_clk),
&policy->rate_change_nb);
#endif
adsp_clk_put(policy);
if (IS_ENABLED(CONFIG_COMMON_CLK) && drv->bwmgr) {
tegra_bwmgr_set_emc(drv->bwmgr, 0,
TEGRA_BWMGR_SET_EMC_FLOOR);
tegra_bwmgr_unregister(drv->bwmgr);
} else if (ape_emc_clk) {
clk_disable_unprepare(ape_emc_clk);
clk_put(ape_emc_clk);
}
drv->dfs_initialized = false;
dev_dbg(&pdev->dev, "adsp dfs has exited ....\n");

View File

@@ -58,11 +58,6 @@ static int nvadsp_t18x_clocks_disable(struct platform_device *pdev)
drv_data->apb2ape_clk = NULL;
}
if (drv_data->ape_emc_clk) {
clk_disable_unprepare(drv_data->ape_emc_clk);
dev_dbg(dev, "ape.emc clock disabled\n");
drv_data->ape_emc_clk = NULL;
}
return 0;
}
@@ -122,19 +117,6 @@ static int nvadsp_t18x_clocks_enable(struct platform_device *pdev)
}
dev_dbg(dev, "adsp neon clock enabled\n");
drv_data->ape_emc_clk = devm_clk_get(dev, "adsp.emc");
if (IS_ERR_OR_NULL(drv_data->ape_emc_clk)) {
dev_err(dev, "unable to find adsp.emc clock\n");
ret = PTR_ERR(drv_data->ape_emc_clk);
goto end;
}
ret = clk_prepare_enable(drv_data->ape_emc_clk);
if (ret) {
dev_err(dev, "unable to enable adsp.emc clock\n");
goto end;
}
dev_dbg(dev, "ape.emc is enabled\n");
drv_data->apb2ape_clk = devm_clk_get(dev, "adsp.apb2ape");
if (IS_ERR_OR_NULL(drv_data->apb2ape_clk)) {
dev_err(dev, "unable to find adsp.apb2ape clk\n");

View File

@@ -330,17 +330,12 @@ static int __init nvadsp_probe(struct platform_device *pdev)
if (ret)
goto err;
#ifdef CONFIG_TEGRA_EMC_APE_DFS
ret = emc_dfs_init(pdev);
if (ret)
goto err;
#endif
#ifdef CONFIG_TEGRA_ADSP_ACTMON
ret = ape_actmon_probe(pdev);
if (ret)
goto err;
#endif
ret = nvadsp_os_probe(pdev);
if (ret)
goto err;
@@ -360,6 +355,11 @@ static int __init nvadsp_probe(struct platform_device *pdev)
ret = nvadsp_aram_init(aram_addr, aram_size);
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");
err:
#ifdef CONFIG_PM
ret = pm_runtime_put_sync(dev);
@@ -372,9 +372,18 @@ out:
static int nvadsp_remove(struct platform_device *pdev)
{
#ifdef CONFIG_TEGRA_EMC_APE_DFS
emc_dfs_exit();
#endif
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_aram_exit();
pm_runtime_disable(&pdev->dev);

View File

@@ -162,7 +162,6 @@ struct nvadsp_drv_data {
struct clk *aclk_clk;
struct clk *adsp_cpu_abus_clk;
struct clk *adsp_neon_clk;
struct clk *ape_emc_clk;
struct clk *uartape_clk;
struct clk *ahub_clk;
unsigned long adsp_freq; /* in KHz*/

View File

@@ -770,6 +770,40 @@ u32 adsp_to_emc_freq(u32 adspfreq)
return 0; /* emc min */
}
static int nvadsp_set_ape_emc_freq(struct nvadsp_drv_data *drv_data)
{
unsigned long ape_emc_freq;
struct device *dev = &priv.pdev->dev;
int ret;
#ifdef CONFIG_TEGRA_ADSP_DFS
/* pass adsp freq in KHz. adsp_emc_freq in Hz */
ape_emc_freq = adsp_to_emc_freq(drv_data->adsp_freq / 1000) * 1000;
#else
ape_emc_freq = drv_data->ape_emc_freq * 1000; /* in Hz */
#endif
dev_dbg(dev, "requested adsp cpu freq %luKHz",
drv_data->adsp_freq / 1000);
dev_dbg(dev, "emc freq %luHz\n", ape_emc_freq / 1000);
/*
* ape_emc_freq is not required to set if adsp_freq
* is lesser than 204.8 MHz
*/
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);
dev_dbg(dev, "ape.emc freq %luKHz\n",
tegra_bwmgr_get_emc_rate() / 1000);
return ret;
}
static int nvadsp_set_ape_freq(struct nvadsp_drv_data *drv_data)
{
unsigned long ape_freq = drv_data->ape_freq * 1000; /* in Hz*/
@@ -983,7 +1017,11 @@ static int nvadsp_set_boot_freqs(struct nvadsp_drv_data *drv_data)
if (ret)
goto end;
}
if (drv_data->bwmgr) {
ret = nvadsp_set_ape_emc_freq(drv_data);
if (ret)
goto end;
}
end:
return ret;
}