gpu: nvgpu: Implement get_rate/set_rate as GPU op

Move clock APIs from gk20a_platform to gpu_ops. At the same time
allow use of internal get_rate/set_rate for querying both GPCCLK
and PWRCLK on iGPU.

At the same time we can replace calls to clk framework with the
new HAL and drop direct dependency to clk framework.

gp10b ops were replaced as a whole at HAL initialization. That
replaces anything set in platform probe stage, so reduce that to
touch only clock gating regs.

Change-Id: Iaf219b1f000d362dbf397d45832f52d25463b31c
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/1300113
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Terje Bergstrom
2017-02-02 13:24:21 -08:00
committed by mobile promotions
parent 686c3b701f
commit 589d6385b1
17 changed files with 120 additions and 65 deletions

View File

@@ -116,6 +116,7 @@ nvgpu-$(CONFIG_TEGRA_GR_VIRTUALIZATION) += \
nvgpu-$(CONFIG_TEGRA_CLK_FRAMEWORK) += gk20a/clk_gk20a.o nvgpu-$(CONFIG_TEGRA_CLK_FRAMEWORK) += gk20a/clk_gk20a.o
ifneq (,$filter y,$(CONFIG_TEGRA_CLK_FRAMEWORK),$(CONFIG_COMMON_CLK)) ifneq (,$filter y,$(CONFIG_TEGRA_CLK_FRAMEWORK),$(CONFIG_COMMON_CLK))
nvgpu-y += \ nvgpu-y += \
tegra/linux/clk.o \
clk/clk_common.o \ clk/clk_common.o \
gm20b/clk_gm20b.o gm20b/clk_gm20b.o
endif endif

View File

@@ -691,6 +691,8 @@ struct gpu_ops {
int (*suspend_clk_support)(struct gk20a *g); int (*suspend_clk_support)(struct gk20a *g);
u32 (*get_crystal_clk_hz)(struct gk20a *g); u32 (*get_crystal_clk_hz)(struct gk20a *g);
unsigned long (*measure_freq)(struct gk20a *g, u32 api_domain); unsigned long (*measure_freq)(struct gk20a *g, u32 api_domain);
unsigned long (*get_rate)(struct gk20a *g, u32 api_domain);
int (*set_rate)(struct gk20a *g, u32 api_domain, unsigned long rate);
} clk; } clk;
struct { struct {
u32 (*get_arbiter_clk_domains)(struct gk20a *g); u32 (*get_arbiter_clk_domains)(struct gk20a *g);

View File

@@ -19,10 +19,8 @@
#include <linux/devfreq.h> #include <linux/devfreq.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/clk.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/clk/tegra.h>
#include <soc/tegra/chip-id.h> #include <soc/tegra/chip-id.h>
#include <linux/platform_data/tegra_edp.h> #include <linux/platform_data/tegra_edp.h>
#include <linux/pm_qos.h> #include <linux/pm_qos.h>
@@ -188,11 +186,11 @@ static int gk20a_scale_target(struct device *dev, unsigned long *freq,
if (rounded_rate == g->last_freq) if (rounded_rate == g->last_freq)
return 0; return 0;
if (platform->clk_get_rate(dev) == rounded_rate) if (g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_GPCCLK) == rounded_rate)
*freq = rounded_rate; *freq = rounded_rate;
else { else {
platform->clk_set_rate(dev, rounded_rate); g->ops.clk.set_rate(g, CTRL_CLK_DOMAIN_GPCCLK, rounded_rate);
*freq = platform->clk_get_rate(dev); *freq = g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_GPCCLK);
} }
g->last_freq = *freq; g->last_freq = *freq;
@@ -321,7 +319,7 @@ static int gk20a_scale_get_dev_status(struct device *dev,
/* Make sure there are correct values for the current frequency */ /* Make sure there are correct values for the current frequency */
profile->dev_stat.current_frequency = profile->dev_stat.current_frequency =
platform->clk_get_rate(profile->dev); g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_GPCCLK);
/* Update load estimate */ /* Update load estimate */
update_load_estimate_gpmu(dev); update_load_estimate_gpmu(dev);
@@ -344,8 +342,8 @@ static int gk20a_scale_get_dev_status(struct device *dev,
static int get_cur_freq(struct device *dev, unsigned long *freq) static int get_cur_freq(struct device *dev, unsigned long *freq)
{ {
struct gk20a_platform *platform = dev_get_drvdata(dev); struct gk20a *g = get_gk20a(dev);
*freq = platform->clk_get_rate(dev); *freq = g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_GPCCLK);
return 0; return 0;
} }

View File

@@ -143,7 +143,7 @@ int gk20a_init_hal(struct gk20a *g)
struct gpu_ops *gops = &g->ops; struct gpu_ops *gops = &g->ops;
struct nvgpu_gpu_characteristics *c = &g->gpu_characteristics; struct nvgpu_gpu_characteristics *c = &g->gpu_characteristics;
*gops = gk20a_ops; gops->clock_gating = gk20a_ops.clock_gating;
gops->privsecurity = 0; gops->privsecurity = 0;
gops->securegpccs = 0; gops->securegpccs = 0;
gops->pmupstate = false; gops->pmupstate = false;

View File

@@ -196,11 +196,8 @@ struct gk20a_platform {
unsigned long **freqs, int *num_freqs); unsigned long **freqs, int *num_freqs);
/* clk related supported functions */ /* clk related supported functions */
unsigned long (*clk_get_rate)(struct device *dev);
long (*clk_round_rate)(struct device *dev, long (*clk_round_rate)(struct device *dev,
unsigned long rate); unsigned long rate);
int (*clk_set_rate)(struct device *dev,
unsigned long rate);
/* Called to register GPCPLL with common clk framework */ /* Called to register GPCPLL with common clk framework */
int (*clk_register)(struct gk20a *g); int (*clk_register)(struct gk20a *g);

View File

@@ -18,7 +18,6 @@
#include <linux/delay.h> /* for mdelay */ #include <linux/delay.h> /* for mdelay */
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/clk.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
@@ -2474,7 +2473,6 @@ int pmu_reset(struct pmu_gk20a *pmu)
int pmu_bootstrap(struct pmu_gk20a *pmu) int pmu_bootstrap(struct pmu_gk20a *pmu)
{ {
struct gk20a *g = gk20a_from_pmu(pmu); struct gk20a *g = gk20a_from_pmu(pmu);
struct gk20a_platform *platform = dev_get_drvdata(g->dev);
struct mm_gk20a *mm = &g->mm; struct mm_gk20a *mm = &g->mm;
struct pmu_ucode_desc *desc = pmu->desc; struct pmu_ucode_desc *desc = pmu->desc;
u64 addr_code, addr_data, addr_load; u64 addr_code, addr_data, addr_load;
@@ -2499,7 +2497,7 @@ int pmu_bootstrap(struct pmu_gk20a *pmu)
pmu, GK20A_PMU_DMAIDX_VIRT); pmu, GK20A_PMU_DMAIDX_VIRT);
g->ops.pmu_ver.set_pmu_cmdline_args_cpu_freq(pmu, g->ops.pmu_ver.set_pmu_cmdline_args_cpu_freq(pmu,
clk_get_rate(platform->clk[1])); g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_PWRCLK));
addr_args = (pwr_falcon_hwcfg_dmem_size_v( addr_args = (pwr_falcon_hwcfg_dmem_size_v(
gk20a_readl(g, pwr_falcon_hwcfg_r())) gk20a_readl(g, pwr_falcon_hwcfg_r()))

View File

@@ -13,7 +13,6 @@
#include <linux/delay.h> /* for mdelay */ #include <linux/delay.h> /* for mdelay */
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/clk.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
@@ -1317,7 +1316,6 @@ static int gm20b_init_pmu_setup_hw1(struct gk20a *g,
struct pmu_gk20a *pmu = &g->pmu; struct pmu_gk20a *pmu = &g->pmu;
int err; int err;
struct gk20a_platform *platform = dev_get_drvdata(g->dev);
gk20a_dbg_fn(""); gk20a_dbg_fn("");
@@ -1345,7 +1343,7 @@ static int gm20b_init_pmu_setup_hw1(struct gk20a *g,
/*Copying pmu cmdline args*/ /*Copying pmu cmdline args*/
g->ops.pmu_ver.set_pmu_cmdline_args_cpu_freq(pmu, g->ops.pmu_ver.set_pmu_cmdline_args_cpu_freq(pmu,
clk_get_rate(platform->clk[1])); g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_PWRCLK));
g->ops.pmu_ver.set_pmu_cmdline_args_secure_mode(pmu, 1); g->ops.pmu_ver.set_pmu_cmdline_args_secure_mode(pmu, 1);
g->ops.pmu_ver.set_pmu_cmdline_args_trace_size( g->ops.pmu_ver.set_pmu_cmdline_args_trace_size(
pmu, GK20A_PMU_TRACE_BUFSIZE); pmu, GK20A_PMU_TRACE_BUFSIZE);

View File

@@ -185,7 +185,7 @@ int gm20b_init_hal(struct gk20a *g)
struct gk20a_platform *platform = dev_get_drvdata(g->dev); struct gk20a_platform *platform = dev_get_drvdata(g->dev);
u32 val; u32 val;
*gops = gm20b_ops; gops->clock_gating = gm20b_ops.clock_gating;
gops->securegpccs = false; gops->securegpccs = false;
gops->pmupstate = false; gops->pmupstate = false;
#ifdef CONFIG_TEGRA_ACR #ifdef CONFIG_TEGRA_ACR

View File

@@ -13,7 +13,6 @@
#include <linux/delay.h> /* for mdelay */ #include <linux/delay.h> /* for mdelay */
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/clk.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>

View File

@@ -16,12 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/clk.h>
#include <linux/delay.h> /* for mdelay */ #include <linux/delay.h> /* for mdelay */
#include <linux/module.h> #include <linux/module.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/clk/tegra.h>
#include <soc/tegra/fuse.h> #include <soc/tegra/fuse.h>
#include "gk20a/gk20a.h" #include "gk20a/gk20a.h"

View File

@@ -218,7 +218,7 @@ int gp106_init_hal(struct gk20a *g)
gk20a_dbg_fn(""); gk20a_dbg_fn("");
*gops = gp106_ops; gops->clock_gating = gp106_ops.clock_gating;
gops->privsecurity = 1; gops->privsecurity = 1;
gops->securegpccs = 1; gops->securegpccs = 1;

View File

@@ -13,7 +13,6 @@
* more details. * more details.
*/ */
#include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
@@ -2255,12 +2254,11 @@ static int gp10b_gr_fuse_override(struct gk20a *g)
static int gr_gp10b_init_preemption_state(struct gk20a *g) static int gr_gp10b_init_preemption_state(struct gk20a *g)
{ {
struct gk20a_platform *platform = gk20a_get_platform(g->dev);
u32 debug_2; u32 debug_2;
u64 sysclk_rate; u64 sysclk_rate;
u32 sysclk_cycles; u32 sysclk_cycles;
sysclk_rate = platform->clk_get_rate(g->dev); sysclk_rate = g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_GPCCLK);
sysclk_cycles = (u32)((sysclk_rate * NVGPU_GFXP_WFI_TIMEOUT_US) / 1000000ULL); sysclk_cycles = (u32)((sysclk_rate * NVGPU_GFXP_WFI_TIMEOUT_US) / 1000000ULL);
gk20a_writel(g, gr_fe_gfxp_wfi_timeout_r(), gk20a_writel(g, gr_fe_gfxp_wfi_timeout_r(),
gr_fe_gfxp_wfi_timeout_count_f(sysclk_cycles)); gr_fe_gfxp_wfi_timeout_count_f(sysclk_cycles));

View File

@@ -193,7 +193,7 @@ int gp10b_init_hal(struct gk20a *g)
struct gk20a_platform *platform = dev_get_drvdata(g->dev); struct gk20a_platform *platform = dev_get_drvdata(g->dev);
u32 val; u32 val;
*gops = gp10b_ops; gops->clock_gating = gp10b_ops.clock_gating;
gops->pmupstate = false; gops->pmupstate = false;
#ifdef CONFIG_TEGRA_ACR #ifdef CONFIG_TEGRA_ACR
if (platform->is_fmodel) { if (platform->is_fmodel) {

View File

@@ -0,0 +1,76 @@
/*
* Linux clock support
*
* Copyright (c) 2017, 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,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk.h>
#include "gk20a/gk20a.h"
static unsigned long nvgpu_linux_clk_get_rate(struct gk20a *g, u32 api_domain)
{
struct gk20a_platform *platform = gk20a_get_platform(g->dev);
unsigned long ret;
switch (api_domain) {
case CTRL_CLK_DOMAIN_GPCCLK:
if (g->clk.tegra_clk)
ret = clk_get_rate(g->clk.tegra_clk);
else
ret = clk_get_rate(platform->clk[0]);
break;
case CTRL_CLK_DOMAIN_PWRCLK:
ret = clk_get_rate(platform->clk[1]);
break;
default:
gk20a_err(g->dev, "unknown clock: %u", api_domain);
ret = 0;
break;
}
return ret;
}
static int nvgpu_linux_clk_set_rate(struct gk20a *g,
u32 api_domain, unsigned long rate)
{
struct gk20a_platform *platform = gk20a_get_platform(g->dev);
int ret;
switch (api_domain) {
case CTRL_CLK_DOMAIN_GPCCLK:
if (g->clk.tegra_clk)
ret = clk_set_rate(g->clk.tegra_clk, rate);
else
ret = clk_set_rate(platform->clk[0], rate);
break;
case CTRL_CLK_DOMAIN_PWRCLK:
ret = clk_set_rate(platform->clk[1], rate);
break;
default:
gk20a_err(g->dev, "unknown clock: %u", api_domain);
ret = -EINVAL;
break;
}
return ret;
}
void nvgpu_linux_init_clk_support(struct gk20a *g)
{
g->ops.clk.get_rate = nvgpu_linux_clk_get_rate;
g->ops.clk.set_rate = nvgpu_linux_clk_set_rate;
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2017, 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,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NVGPU_COMMON_LINUX_CLK_H
struct gk20a;
void nvgpu_linux_init_clk_support(struct gk20a *g);
#endif

View File

@@ -49,6 +49,8 @@
#include "gk20a/gk20a_scale.h" #include "gk20a/gk20a_scale.h"
#include "gm20b/clk_gm20b.h" #include "gm20b/clk_gm20b.h"
#include "clk.h"
#define TEGRA_GK20A_BW_PER_FREQ 32 #define TEGRA_GK20A_BW_PER_FREQ 32
#define TEGRA_GM20B_BW_PER_FREQ 64 #define TEGRA_GM20B_BW_PER_FREQ 64
#define TEGRA_DDR3_BW_PER_FREQ 16 #define TEGRA_DDR3_BW_PER_FREQ 16
@@ -938,6 +940,7 @@ static int gk20a_tegra_probe(struct device *dev)
platform->g->mm.vidmem_is_vidmem = platform->vidmem_is_vidmem; platform->g->mm.vidmem_is_vidmem = platform->vidmem_is_vidmem;
gk20a_tegra_get_clocks(dev); gk20a_tegra_get_clocks(dev);
nvgpu_linux_init_clk_support(platform->g);
if (platform->clk_register) { if (platform->clk_register) {
ret = platform->clk_register(platform->g); ret = platform->clk_register(platform->g);
@@ -975,15 +978,6 @@ static int gk20a_tegra_suspend(struct device *dev)
} }
#if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_COMMON_CLK) #if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_COMMON_CLK)
static unsigned long gk20a_get_clk_rate(struct device *dev)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
struct gk20a *g = platform->g;
return gk20a_clk_get_rate(g);
}
static long gk20a_round_clk_rate(struct device *dev, unsigned long rate) static long gk20a_round_clk_rate(struct device *dev, unsigned long rate)
{ {
struct gk20a_platform *platform = gk20a_get_platform(dev); struct gk20a_platform *platform = gk20a_get_platform(dev);
@@ -992,14 +986,6 @@ static long gk20a_round_clk_rate(struct device *dev, unsigned long rate)
return gk20a_clk_round_rate(g, rate); return gk20a_clk_round_rate(g, rate);
} }
static int gk20a_set_clk_rate(struct device *dev, unsigned long rate)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
struct gk20a *g = platform->g;
return gk20a_clk_set_rate(g, rate);
}
static int gk20a_clk_get_freqs(struct device *dev, static int gk20a_clk_get_freqs(struct device *dev,
unsigned long **freqs, int *num_freqs) unsigned long **freqs, int *num_freqs)
{ {
@@ -1056,9 +1042,7 @@ struct gk20a_platform gk20a_tegra_platform = {
.reset_deassert = gk20a_tegra_reset_deassert, .reset_deassert = gk20a_tegra_reset_deassert,
#ifdef CONFIG_TEGRA_CLK_FRAMEWORK #ifdef CONFIG_TEGRA_CLK_FRAMEWORK
.clk_get_rate = gk20a_get_clk_rate,
.clk_round_rate = gk20a_round_clk_rate, .clk_round_rate = gk20a_round_clk_rate,
.clk_set_rate = gk20a_set_clk_rate,
.get_clk_freqs = gk20a_clk_get_freqs, .get_clk_freqs = gk20a_clk_get_freqs,
#endif #endif
@@ -1124,9 +1108,7 @@ struct gk20a_platform gm20b_tegra_platform = {
#endif #endif
#if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_COMMON_CLK) #if defined(CONFIG_TEGRA_CLK_FRAMEWORK) || defined(CONFIG_COMMON_CLK)
.clk_get_rate = gk20a_get_clk_rate,
.clk_round_rate = gk20a_round_clk_rate, .clk_round_rate = gk20a_round_clk_rate,
.clk_set_rate = gk20a_set_clk_rate,
.get_clk_freqs = gk20a_clk_get_freqs, .get_clk_freqs = gk20a_clk_get_freqs,
#endif #endif

View File

@@ -29,6 +29,8 @@
#include <soc/tegra/tegra_bpmp.h> #include <soc/tegra/tegra_bpmp.h>
#include "clk.h"
#include "gk20a/platform_gk20a.h" #include "gk20a/platform_gk20a.h"
#include "gk20a/gk20a.h" #include "gk20a/gk20a.h"
#include "gk20a/gk20a_scale.h" #include "gk20a/gk20a_scale.h"
@@ -173,6 +175,7 @@ static int gp10b_tegra_probe(struct device *dev)
platform->g->mm.vidmem_is_vidmem = platform->vidmem_is_vidmem; platform->g->mm.vidmem_is_vidmem = platform->vidmem_is_vidmem;
gp10b_tegra_get_clocks(dev); gp10b_tegra_get_clocks(dev);
nvgpu_linux_init_clk_support(platform->g);
return 0; return 0;
} }
@@ -329,14 +332,6 @@ static void gp10b_tegra_postscale(struct device *pdev,
gk20a_dbg_fn("done"); gk20a_dbg_fn("done");
} }
static unsigned long gp10b_get_clk_rate(struct device *dev)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
return clk_get_rate(platform->clk[0]);
}
static long gp10b_round_clk_rate(struct device *dev, unsigned long rate) static long gp10b_round_clk_rate(struct device *dev, unsigned long rate)
{ {
struct gk20a *g = get_gk20a(dev); struct gk20a *g = get_gk20a(dev);
@@ -352,13 +347,6 @@ static long gp10b_round_clk_rate(struct device *dev, unsigned long rate)
return freq_table[max_states - 1]; return freq_table[max_states - 1];
} }
static int gp10b_set_clk_rate(struct device *dev, unsigned long rate)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
return clk_set_rate(platform->clk[0], rate);
}
static int gp10b_clk_get_freqs(struct device *dev, static int gp10b_clk_get_freqs(struct device *dev,
unsigned long **freqs, int *num_freqs) unsigned long **freqs, int *num_freqs)
{ {
@@ -440,9 +428,7 @@ struct gk20a_platform gp10b_tegra_platform = {
.has_ce = true, .has_ce = true,
.clk_get_rate = gp10b_get_clk_rate,
.clk_round_rate = gp10b_round_clk_rate, .clk_round_rate = gp10b_round_clk_rate,
.clk_set_rate = gp10b_set_clk_rate,
.get_clk_freqs = gp10b_clk_get_freqs, .get_clk_freqs = gp10b_clk_get_freqs,
/* frequency scaling configuration */ /* frequency scaling configuration */