diff --git a/drivers/gpu/nvgpu/common/linux/clk.c b/drivers/gpu/nvgpu/common/linux/clk.c index ea5b023d5..8bffc07bb 100644 --- a/drivers/gpu/nvgpu/common/linux/clk.c +++ b/drivers/gpu/nvgpu/common/linux/clk.c @@ -1,7 +1,7 @@ /* * Linux clock support * - * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -34,9 +34,13 @@ static unsigned long nvgpu_linux_clk_get_rate(struct gk20a *g, u32 api_domain) switch (api_domain) { case CTRL_CLK_DOMAIN_GPCCLK: if (g->clk.tegra_clk) - ret = clk_get_rate(g->clk.tegra_clk); + ret = g->clk.cached_rate ? + g->clk.cached_rate : + clk_get_rate(g->clk.tegra_clk); else - ret = clk_get_rate(platform->clk[0]); + ret = platform->cached_rate ? + platform->cached_rate : + clk_get_rate(platform->clk[0]); break; case CTRL_CLK_DOMAIN_PWRCLK: ret = clk_get_rate(platform->clk[1]); @@ -58,10 +62,15 @@ static int nvgpu_linux_clk_set_rate(struct gk20a *g, switch (api_domain) { case CTRL_CLK_DOMAIN_GPCCLK: - if (g->clk.tegra_clk) + if (g->clk.tegra_clk) { ret = clk_set_rate(g->clk.tegra_clk, rate); - else + if (!ret) + g->clk.cached_rate = rate; + } else { ret = clk_set_rate(platform->clk[0], rate); + if (!ret) + platform->cached_rate = rate; + } break; case CTRL_CLK_DOMAIN_PWRCLK: ret = clk_set_rate(platform->clk[1], rate); diff --git a/drivers/gpu/nvgpu/common/linux/platform_gk20a.h b/drivers/gpu/nvgpu/common/linux/platform_gk20a.h index aed50ed78..43afbbf9b 100644 --- a/drivers/gpu/nvgpu/common/linux/platform_gk20a.h +++ b/drivers/gpu/nvgpu/common/linux/platform_gk20a.h @@ -256,6 +256,9 @@ struct gk20a_platform { /* stream id to use */ u32 ltc_streamid; + + /* scaling rate */ + unsigned long cached_rate; }; static inline struct gk20a_platform *gk20a_get_platform( diff --git a/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c index 3e1c69961..82648ca32 100644 --- a/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/common/linux/platform_gk20a_tegra.c @@ -506,6 +506,8 @@ static int gk20a_tegra_get_clocks(struct device *dev) rate = clk_round_rate(c, rate); clk_set_rate(c, rate); platform->clk[i] = c; + if (i == 0) + platform->cached_rate = rate; } platform->num_clks = i; diff --git a/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c index 782a3d882..96acf24bf 100644 --- a/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c +++ b/drivers/gpu/nvgpu/common/linux/platform_gp10b_tegra.c @@ -57,11 +57,13 @@ gp10b_freq_table[GP10B_MAX_SUPPORTED_FREQS / GP10B_FREQ_SELECT_STEP]; #define EMC_BW_RATIO (TEGRA_GP10B_BW_PER_FREQ / TEGRA_DDR4_BW_PER_FREQ) +#define GPCCLK_INIT_RATE 1000000000 + static struct { char *name; unsigned long default_rate; } tegra_gp10b_clocks[] = { - {"gpu", 1000000000}, + {"gpu", GPCCLK_INIT_RATE}, {"gpu_sys", 204000000} }; static void gr_gp10b_remove_sysfs(struct device *dev); @@ -90,6 +92,8 @@ int gp10b_tegra_get_clocks(struct device *dev) } else { clk_set_rate(c, rate); platform->clk[i] = c; + if (i == 0) + platform->cached_rate = rate; } } platform->num_clks = i; diff --git a/drivers/gpu/nvgpu/gk20a/clk_gk20a.h b/drivers/gpu/nvgpu/gk20a/clk_gk20a.h index ec7022aa5..d84e59692 100644 --- a/drivers/gpu/nvgpu/gk20a/clk_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/clk_gk20a.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 - 2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011 - 2018, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -96,6 +96,9 @@ struct clk_gk20a { #if defined(CONFIG_COMMON_CLK) struct clk *tegra_clk; struct clk_hw hw; + + /* scaling rate */ + unsigned long cached_rate; #endif struct pll gpc_pll; struct pll gpc_pll_last;