mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
gpu: nvgpu: ga10b: handling gpcclk requests with GPC floor-swept
ga10b supports floor-sweeping of GPCs. Check for tegra soc fuse info, before making gpcclk requests to BPMP for available GPCs. Bug 3362403 Change-Id: I3f5e2d85b785098ce3a8c8d7d8a5621446e94c15 Signed-off-by: Seshendra Gadagottu <sgadagottu@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2616898 Reviewed-by: Alex Waterman <alexw@nvidia.com> Reviewed-by: Seema Khowala <seemaj@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
f4ec400d5f
commit
a70df981e6
@@ -94,6 +94,19 @@ int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val);
|
|||||||
*/
|
*/
|
||||||
int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val);
|
int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief - Reads FUSE_OPT_GPC_DISABLE_0 fuse.
|
||||||
|
*
|
||||||
|
* @param g [in] - GPU super structure.
|
||||||
|
* @param val [out] - Populated with register FUSE_OPT_GPC_DISABLE_0 value.
|
||||||
|
*
|
||||||
|
* - Provide information about the GPU GPC floor-sweep info
|
||||||
|
*
|
||||||
|
* @return 0 on success or negative value on failure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int nvgpu_tegra_fuse_read_opt_gpc_disable(struct gk20a *g, u32 *val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - Reads the per-device identifier fuses.
|
* @brief - Reads the per-device identifier fuses.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -33,6 +33,10 @@
|
|||||||
#define FUSE_RESERVED_CALIB0_0 0x204
|
#define FUSE_RESERVED_CALIB0_0 0x204
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef FUSE_OPT_GPC_DISABLE_0
|
||||||
|
#define FUSE_OPT_GPC_DISABLE_0 0x188
|
||||||
|
#endif
|
||||||
|
|
||||||
/* T186+ */
|
/* T186+ */
|
||||||
#if !defined(FUSE_PDI0) && !defined(FUSE_PDI1)
|
#if !defined(FUSE_PDI0) && !defined(FUSE_PDI1)
|
||||||
#define FUSE_PDI0 0x300
|
#define FUSE_PDI0 0x300
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
|
* Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -34,6 +34,11 @@ int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val)
|
|||||||
return tegra_fuse_readl(FUSE_GCPLEX_CONFIG_FUSE_0, val);
|
return tegra_fuse_readl(FUSE_GCPLEX_CONFIG_FUSE_0, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nvgpu_tegra_fuse_read_opt_gpc_disable(struct gk20a *g, u32 *val)
|
||||||
|
{
|
||||||
|
return tegra_fuse_readl(FUSE_OPT_GPC_DISABLE_0, val);
|
||||||
|
}
|
||||||
|
|
||||||
int nvgpu_tegra_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi)
|
int nvgpu_tegra_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi)
|
||||||
{
|
{
|
||||||
u32 lo = 0U;
|
u32 lo = 0U;
|
||||||
|
|||||||
@@ -27,10 +27,13 @@
|
|||||||
#include <linux/platform/tegra/emc_bwmgr.h>
|
#include <linux/platform/tegra/emc_bwmgr.h>
|
||||||
#endif
|
#endif
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/fuse.h>
|
||||||
|
|
||||||
#include <nvgpu/gk20a.h>
|
#include <nvgpu/gk20a.h>
|
||||||
#include <nvgpu/nvhost.h>
|
#include <nvgpu/nvhost.h>
|
||||||
#include <nvgpu/soc.h>
|
#include <nvgpu/soc.h>
|
||||||
|
#include <nvgpu/fuse.h>
|
||||||
|
#include <nvgpu/linux/soc_fuse.h>
|
||||||
|
|
||||||
#ifdef CONFIG_NV_TEGRA_BPMP
|
#ifdef CONFIG_NV_TEGRA_BPMP
|
||||||
#include <soc/tegra/tegra-bpmp-dvfs.h>
|
#include <soc/tegra/tegra-bpmp-dvfs.h>
|
||||||
@@ -76,6 +79,34 @@ struct gk20a_platform_clk tegra_ga10b_clocks[] = {
|
|||||||
{"fuse", UINT_MAX}
|
{"fuse", UINT_MAX}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NVGPU_GPC0_DISABLE BIT(0)
|
||||||
|
#define NVGPU_GPC1_DISABLE BIT(1)
|
||||||
|
|
||||||
|
static bool ga10b_tegra_is_clock_available(struct gk20a *g, char *clk_name)
|
||||||
|
{
|
||||||
|
u32 gpc_disable = 0U;
|
||||||
|
|
||||||
|
/* Check for gpc floor-sweeping and report availability of gpcclks */
|
||||||
|
if (nvgpu_tegra_fuse_read_opt_gpc_disable(g, &gpc_disable)) {
|
||||||
|
nvgpu_err(g, "unable to read opt_gpc_disable fuse");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((strcmp(clk_name, "gpc0clk") == 0) &&
|
||||||
|
(gpc_disable & NVGPU_GPC0_DISABLE)) {
|
||||||
|
nvgpu_info(g, "GPC0 is floor-swept");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((strcmp(clk_name, "gpc1clk") == 0) &&
|
||||||
|
(gpc_disable & NVGPU_GPC1_DISABLE)) {
|
||||||
|
nvgpu_info(g, "GPC1 is floor-swept");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function finds clocks in tegra platform and populates
|
* This function finds clocks in tegra platform and populates
|
||||||
* the clock information to platform data.
|
* the clock information to platform data.
|
||||||
@@ -89,6 +120,7 @@ static int ga10b_tegra_acquire_platform_clocks(struct device *dev,
|
|||||||
struct gk20a *g = platform->g;
|
struct gk20a *g = platform->g;
|
||||||
struct device_node *np = nvgpu_get_node(g);
|
struct device_node *np = nvgpu_get_node(g);
|
||||||
unsigned int i, num_clks_dt;
|
unsigned int i, num_clks_dt;
|
||||||
|
int err;
|
||||||
|
|
||||||
/* Get clocks only on supported platforms(silicon and fpga) */
|
/* Get clocks only on supported platforms(silicon and fpga) */
|
||||||
if (!nvgpu_platform_is_silicon(g) && !nvgpu_platform_is_fpga(g)) {
|
if (!nvgpu_platform_is_silicon(g) && !nvgpu_platform_is_fpga(g)) {
|
||||||
@@ -107,15 +139,21 @@ static int ga10b_tegra_acquire_platform_clocks(struct device *dev,
|
|||||||
|
|
||||||
platform->num_clks = 0;
|
platform->num_clks = 0;
|
||||||
|
|
||||||
/* TODO add floorsweep check before requesting clocks */
|
|
||||||
for (i = 0; i < num_clks_dt; i++) {
|
for (i = 0; i < num_clks_dt; i++) {
|
||||||
long rate;
|
long rate;
|
||||||
struct clk *c = of_clk_get_by_name(np, clk_entries[i].name);
|
struct clk *c;
|
||||||
|
|
||||||
|
if (ga10b_tegra_is_clock_available(g, clk_entries[i].name)) {
|
||||||
|
c = of_clk_get_by_name(np, clk_entries[i].name);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_ERR(c)) {
|
if (IS_ERR(c)) {
|
||||||
nvgpu_info(g, "cannot get clock %s",
|
nvgpu_info(g, "cannot get clock %s",
|
||||||
clk_entries[i].name);
|
clk_entries[i].name);
|
||||||
/* Continue with other clocks enable */
|
err = PTR_ERR(c);
|
||||||
|
goto err_get_clock;
|
||||||
} else {
|
} else {
|
||||||
rate = clk_entries[i].default_rate;
|
rate = clk_entries[i].default_rate;
|
||||||
clk_set_rate(c, rate);
|
clk_set_rate(c, rate);
|
||||||
@@ -135,6 +173,14 @@ static int ga10b_tegra_acquire_platform_clocks(struct device *dev,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_get_clock:
|
||||||
|
while (i > 0 && i--) {
|
||||||
|
clk_put(platform->clk[i]);
|
||||||
|
platform->clk[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ga10b_tegra_get_clocks(struct device *dev)
|
static int ga10b_tegra_get_clocks(struct device *dev)
|
||||||
|
|||||||
Reference in New Issue
Block a user