From 589d6385b19a357cf566b75ded9355f9b8053ad7 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Thu, 2 Feb 2017 13:24:21 -0800 Subject: 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 Reviewed-on: http://git-master/r/1300113 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile.nvgpu | 1 + drivers/gpu/nvgpu/gk20a/gk20a.h | 2 + drivers/gpu/nvgpu/gk20a/gk20a_scale.c | 14 ++-- drivers/gpu/nvgpu/gk20a/hal_gk20a.c | 2 +- drivers/gpu/nvgpu/gk20a/platform_gk20a.h | 3 - drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 4 +- drivers/gpu/nvgpu/gm20b/acr_gm20b.c | 4 +- drivers/gpu/nvgpu/gm20b/hal_gm20b.c | 2 +- drivers/gpu/nvgpu/gp106/acr_gp106.c | 1 - drivers/gpu/nvgpu/gp106/clk_gp106.c | 2 - drivers/gpu/nvgpu/gp106/hal_gp106.c | 2 +- drivers/gpu/nvgpu/gp10b/gr_gp10b.c | 4 +- drivers/gpu/nvgpu/gp10b/hal_gp10b.c | 2 +- drivers/gpu/nvgpu/tegra/linux/clk.c | 76 ++++++++++++++++++++++ drivers/gpu/nvgpu/tegra/linux/clk.h | 22 +++++++ .../gpu/nvgpu/tegra/linux/platform_gk20a_tegra.c | 24 +------ .../gpu/nvgpu/tegra/linux/platform_gp10b_tegra.c | 20 +----- 17 files changed, 120 insertions(+), 65 deletions(-) create mode 100644 drivers/gpu/nvgpu/tegra/linux/clk.c create mode 100644 drivers/gpu/nvgpu/tegra/linux/clk.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu index 00b4a291..abb9b785 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 5a4eaf39..695d2d1a 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 edf92de6..b9e92f15 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 9eb8e835..23725b8b 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 42be2271..b23d0091 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 7e37762c..c7e68f44 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 ed144c0f..2d932b67 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 d9fb2c53..ad041f67 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 37a3d152..8c744a73 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 6bc4f3b0..487ba3c3 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 d07223c9..a05b71ab 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 96919d2e..c4d097a7 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 b57fcb5f..18e1ffdc 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 00000000..3982054c --- /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 00000000..614a7fd7 --- /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 56ba1ecd..1b40702a 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 f0c3640a..27db9c12 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 */ -- cgit v1.2.2