diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu index 00b4a2916..abb9b7854 100644 --- a/drivers/gpu/nvgpu/Makefile.nvgpu +++ b/drivers/gpu/nvgpu/Makefile.nvgpu @@ -116,6 +116,7 @@ nvgpu-$(CONFIG_TEGRA_GR_VIRTUALIZATION) += \ nvgpu-$(CONFIG_TEGRA_CLK_FRAMEWORK) += gk20a/clk_gk20a.o ifneq (,$filter y,$(CONFIG_TEGRA_CLK_FRAMEWORK),$(CONFIG_COMMON_CLK)) nvgpu-y += \ + tegra/linux/clk.o \ clk/clk_common.o \ gm20b/clk_gm20b.o endif diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 5a4eaf39d..695d2d1a6 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -691,6 +691,8 @@ struct gpu_ops { int (*suspend_clk_support)(struct gk20a *g); u32 (*get_crystal_clk_hz)(struct gk20a *g); 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; struct { u32 (*get_arbiter_clk_domains)(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_scale.c b/drivers/gpu/nvgpu/gk20a/gk20a_scale.c index edf92de6d..b9e92f153 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_scale.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_scale.c @@ -19,10 +19,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -188,11 +186,11 @@ static int gk20a_scale_target(struct device *dev, unsigned long *freq, if (rounded_rate == g->last_freq) 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; else { - platform->clk_set_rate(dev, rounded_rate); - *freq = platform->clk_get_rate(dev); + g->ops.clk.set_rate(g, CTRL_CLK_DOMAIN_GPCCLK, rounded_rate); + *freq = g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_GPCCLK); } 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 */ 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_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) { - struct gk20a_platform *platform = dev_get_drvdata(dev); - *freq = platform->clk_get_rate(dev); + struct gk20a *g = get_gk20a(dev); + *freq = g->ops.clk.get_rate(g, CTRL_CLK_DOMAIN_GPCCLK); return 0; } diff --git a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c index 9eb8e8353..23725b8bb 100644 --- a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c @@ -143,7 +143,7 @@ int gk20a_init_hal(struct gk20a *g) struct gpu_ops *gops = &g->ops; struct nvgpu_gpu_characteristics *c = &g->gpu_characteristics; - *gops = gk20a_ops; + gops->clock_gating = gk20a_ops.clock_gating; gops->privsecurity = 0; gops->securegpccs = 0; gops->pmupstate = false; diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h index 42be22711..b23d00913 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h @@ -196,11 +196,8 @@ struct gk20a_platform { unsigned long **freqs, int *num_freqs); /* clk related supported functions */ - unsigned long (*clk_get_rate)(struct device *dev); long (*clk_round_rate)(struct device *dev, unsigned long rate); - int (*clk_set_rate)(struct device *dev, - unsigned long rate); /* Called to register GPCPLL with common clk framework */ int (*clk_register)(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 7e37762c1..c7e68f440 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c @@ -18,7 +18,6 @@ #include /* for mdelay */ #include -#include #include #include #include @@ -2474,7 +2473,6 @@ int pmu_reset(struct pmu_gk20a *pmu) int pmu_bootstrap(struct pmu_gk20a *pmu) { struct gk20a *g = gk20a_from_pmu(pmu); - struct gk20a_platform *platform = dev_get_drvdata(g->dev); struct mm_gk20a *mm = &g->mm; struct pmu_ucode_desc *desc = pmu->desc; u64 addr_code, addr_data, addr_load; @@ -2499,7 +2497,7 @@ int pmu_bootstrap(struct pmu_gk20a *pmu) pmu, GK20A_PMU_DMAIDX_VIRT); 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( gk20a_readl(g, pwr_falcon_hwcfg_r())) diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c index ed144c0fe..2d932b678 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c @@ -13,7 +13,6 @@ #include /* for mdelay */ #include -#include #include #include #include @@ -1317,7 +1316,6 @@ static int gm20b_init_pmu_setup_hw1(struct gk20a *g, struct pmu_gk20a *pmu = &g->pmu; int err; - struct gk20a_platform *platform = dev_get_drvdata(g->dev); gk20a_dbg_fn(""); @@ -1345,7 +1343,7 @@ static int gm20b_init_pmu_setup_hw1(struct gk20a *g, /*Copying pmu cmdline args*/ 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_trace_size( pmu, GK20A_PMU_TRACE_BUFSIZE); diff --git a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c index d9fb2c53e..ad041f674 100644 --- a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c @@ -185,7 +185,7 @@ int gm20b_init_hal(struct gk20a *g) struct gk20a_platform *platform = dev_get_drvdata(g->dev); u32 val; - *gops = gm20b_ops; + gops->clock_gating = gm20b_ops.clock_gating; gops->securegpccs = false; gops->pmupstate = false; #ifdef CONFIG_TEGRA_ACR diff --git a/drivers/gpu/nvgpu/gp106/acr_gp106.c b/drivers/gpu/nvgpu/gp106/acr_gp106.c index 37a3d1529..8c744a733 100644 --- a/drivers/gpu/nvgpu/gp106/acr_gp106.c +++ b/drivers/gpu/nvgpu/gp106/acr_gp106.c @@ -13,7 +13,6 @@ #include /* for mdelay */ #include -#include #include #include #include diff --git a/drivers/gpu/nvgpu/gp106/clk_gp106.c b/drivers/gpu/nvgpu/gp106/clk_gp106.c index 6bc4f3b04..487ba3c30 100644 --- a/drivers/gpu/nvgpu/gp106/clk_gp106.c +++ b/drivers/gpu/nvgpu/gp106/clk_gp106.c @@ -16,12 +16,10 @@ * along with this program. If not, see . */ -#include #include /* for mdelay */ #include #include #include -#include #include #include "gk20a/gk20a.h" diff --git a/drivers/gpu/nvgpu/gp106/hal_gp106.c b/drivers/gpu/nvgpu/gp106/hal_gp106.c index d07223c9f..a05b71ab2 100644 --- a/drivers/gpu/nvgpu/gp106/hal_gp106.c +++ b/drivers/gpu/nvgpu/gp106/hal_gp106.c @@ -218,7 +218,7 @@ int gp106_init_hal(struct gk20a *g) gk20a_dbg_fn(""); - *gops = gp106_ops; + gops->clock_gating = gp106_ops.clock_gating; gops->privsecurity = 1; gops->securegpccs = 1; diff --git a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c index 96919d2ef..c4d097a7e 100644 --- a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c @@ -13,7 +13,6 @@ * more details. */ -#include #include #include #include @@ -2255,12 +2254,11 @@ static int gp10b_gr_fuse_override(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; u64 sysclk_rate; 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); gk20a_writel(g, gr_fe_gfxp_wfi_timeout_r(), gr_fe_gfxp_wfi_timeout_count_f(sysclk_cycles)); diff --git a/drivers/gpu/nvgpu/gp10b/hal_gp10b.c b/drivers/gpu/nvgpu/gp10b/hal_gp10b.c index b57fcb5f5..18e1ffdc9 100644 --- a/drivers/gpu/nvgpu/gp10b/hal_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/hal_gp10b.c @@ -193,7 +193,7 @@ int gp10b_init_hal(struct gk20a *g) struct gk20a_platform *platform = dev_get_drvdata(g->dev); u32 val; - *gops = gp10b_ops; + gops->clock_gating = gp10b_ops.clock_gating; gops->pmupstate = false; #ifdef CONFIG_TEGRA_ACR if (platform->is_fmodel) { diff --git a/drivers/gpu/nvgpu/tegra/linux/clk.c b/drivers/gpu/nvgpu/tegra/linux/clk.c new file mode 100644 index 000000000..3982054cb --- /dev/null +++ b/drivers/gpu/nvgpu/tegra/linux/clk.c @@ -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 . + */ + +#include + +#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; +} diff --git a/drivers/gpu/nvgpu/tegra/linux/clk.h b/drivers/gpu/nvgpu/tegra/linux/clk.h new file mode 100644 index 000000000..614a7fd73 --- /dev/null +++ b/drivers/gpu/nvgpu/tegra/linux/clk.h @@ -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 . + */ + +#ifndef NVGPU_COMMON_LINUX_CLK_H + +struct gk20a; +void nvgpu_linux_init_clk_support(struct gk20a *g); + +#endif diff --git a/drivers/gpu/nvgpu/tegra/linux/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/tegra/linux/platform_gk20a_tegra.c index 56ba1ecdf..1b40702ae 100644 --- a/drivers/gpu/nvgpu/tegra/linux/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/tegra/linux/platform_gk20a_tegra.c @@ -49,6 +49,8 @@ #include "gk20a/gk20a_scale.h" #include "gm20b/clk_gm20b.h" +#include "clk.h" + #define TEGRA_GK20A_BW_PER_FREQ 32 #define TEGRA_GM20B_BW_PER_FREQ 64 #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; gk20a_tegra_get_clocks(dev); + nvgpu_linux_init_clk_support(platform->g); if (platform->clk_register) { 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) -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) { 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); } -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, unsigned long **freqs, int *num_freqs) { @@ -1056,9 +1042,7 @@ struct gk20a_platform gk20a_tegra_platform = { .reset_deassert = gk20a_tegra_reset_deassert, #ifdef CONFIG_TEGRA_CLK_FRAMEWORK - .clk_get_rate = gk20a_get_clk_rate, .clk_round_rate = gk20a_round_clk_rate, - .clk_set_rate = gk20a_set_clk_rate, .get_clk_freqs = gk20a_clk_get_freqs, #endif @@ -1124,9 +1108,7 @@ struct gk20a_platform gm20b_tegra_platform = { #endif #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_set_rate = gk20a_set_clk_rate, .get_clk_freqs = gk20a_clk_get_freqs, #endif diff --git a/drivers/gpu/nvgpu/tegra/linux/platform_gp10b_tegra.c b/drivers/gpu/nvgpu/tegra/linux/platform_gp10b_tegra.c index f0c3640a4..27db9c122 100644 --- a/drivers/gpu/nvgpu/tegra/linux/platform_gp10b_tegra.c +++ b/drivers/gpu/nvgpu/tegra/linux/platform_gp10b_tegra.c @@ -29,6 +29,8 @@ #include +#include "clk.h" + #include "gk20a/platform_gk20a.h" #include "gk20a/gk20a.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; gp10b_tegra_get_clocks(dev); + nvgpu_linux_init_clk_support(platform->g); return 0; } @@ -329,14 +332,6 @@ static void gp10b_tegra_postscale(struct device *pdev, 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) { 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]; } -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, unsigned long **freqs, int *num_freqs) { @@ -440,9 +428,7 @@ struct gk20a_platform gp10b_tegra_platform = { .has_ce = true, - .clk_get_rate = gp10b_get_clk_rate, .clk_round_rate = gp10b_round_clk_rate, - .clk_set_rate = gp10b_set_clk_rate, .get_clk_freqs = gp10b_clk_get_freqs, /* frequency scaling configuration */