From ad85b60bb051c51ba01ae2ca2c44a54678f92f14 Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Wed, 16 Feb 2022 16:24:14 +0530 Subject: [PATCH] gpu: nvgpu: use nvmem API to read fuses Replace the usage of tegra_fuse_readl with nvmem_cell_read_u32 for the below fuse registers added as nvmem cells on v5.10+ kernels. Older nvidia kernels do not have these tegra nvmem cell support. 1. FUSE_GCPLEX_CONFIG_FUSE_0 2. FUSE_RESERVED_CALIB0_0 3. FUSE_PDI0 4. FUSE_PDI1 bug 200633045 Change-Id: I187400720929233fcbc1970c9bbed34347b0a9a7 Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2670828 Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-cert Reviewed-by: Jonathan Hunter Reviewed-by: Alex Waterman GVS: Gerrit_Virtual_Submit --- arch/nvgpu-linux.yaml | 4 + drivers/gpu/nvgpu/Makefile | 1 + drivers/gpu/nvgpu/Makefile.linux.configs | 10 +++ drivers/gpu/nvgpu/include/nvgpu/linux/nvmem.h | 74 +++++++++++++++++ .../gpu/nvgpu/include/nvgpu/linux/soc_fuse.h | 22 ++--- drivers/gpu/nvgpu/os/linux/fuse.c | 15 +++- drivers/gpu/nvgpu/os/linux/nvmem.c | 80 +++++++++++++++++++ .../gpu/nvgpu/os/linux/platform_ga10b_tegra.c | 1 - 8 files changed, 195 insertions(+), 12 deletions(-) create mode 100644 drivers/gpu/nvgpu/include/nvgpu/linux/nvmem.h create mode 100644 drivers/gpu/nvgpu/os/linux/nvmem.c diff --git a/arch/nvgpu-linux.yaml b/arch/nvgpu-linux.yaml index 594feb17d..95f68a498 100644 --- a/arch/nvgpu-linux.yaml +++ b/arch/nvgpu-linux.yaml @@ -101,6 +101,9 @@ firmware: fuse: sources: [ os/linux/fuse.c ] +nvmem: + sources: [ os/linux/nvmem.c ] + intr: sources: [ os/linux/intr.c ] @@ -252,6 +255,7 @@ headers: include/nvgpu/linux/os_fence_android.h, include/nvgpu/linux/os_fence_dma.h, include/nvgpu/linux/rwsem.h, + include/nvgpu/linux/nvmem.h, include/nvgpu/linux/sim.h, include/nvgpu/linux/sim_pci.h, include/nvgpu/linux/soc_fuse.h, diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 67cfa089e..e0833e71a 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -536,6 +536,7 @@ nvgpu-$(CONFIG_TEGRA_GK20A) += \ ifeq ($(CONFIG_TEGRA_GK20A),y) nvgpu-$(CONFIG_NVGPU_TEGRA_FUSE) += os/linux/soc.o +nvgpu-$(CONFIG_NVGPU_NVMEM_FUSE) += os/linux/nvmem.o endif nvgpu-$(CONFIG_NVGPU_SYNCFD_ANDROID) += \ diff --git a/drivers/gpu/nvgpu/Makefile.linux.configs b/drivers/gpu/nvgpu/Makefile.linux.configs index b4a82dd2f..010b6cbc6 100644 --- a/drivers/gpu/nvgpu/Makefile.linux.configs +++ b/drivers/gpu/nvgpu/Makefile.linux.configs @@ -103,8 +103,15 @@ ifdef CONFIG_TEGRA_EPL CONFIG_NVGPU_ENABLE_MISC_EC := y endif +CONFIG_NVGPU_NVMEM_FUSE := n + ifneq ($(findstring 5.10,$(NV_BUILD_KERNEL_OPTIONS)),) CONFIG_NVGPU_NVMAP_NEXT := y +CONFIG_NVGPU_NVMEM_FUSE := y +endif + +ifneq ($(findstring stable,$(NV_BUILD_KERNEL_OPTIONS)),) +CONFIG_NVGPU_NVMEM_FUSE := y endif ifeq ($(findstring stable,$(NV_BUILD_KERNEL_OPTIONS)),) @@ -233,6 +240,9 @@ endif ifeq ($(CONFIG_TEGRA_GK20A_NVHOST_HOST1X),y) ccflags-y += -DCONFIG_TEGRA_GK20A_NVHOST_HOST1X endif +ifeq ($(CONFIG_NVGPU_NVMEM_FUSE),y) +ccflags-y += -DCONFIG_NVGPU_NVMEM_FUSE +endif ifeq ($(CONFIG_NVGPU_NVMAP_NEXT),y) ccflags-y += -DCONFIG_NVGPU_NVMAP_NEXT endif diff --git a/drivers/gpu/nvgpu/include/nvgpu/linux/nvmem.h b/drivers/gpu/nvgpu/include/nvgpu/linux/nvmem.h new file mode 100644 index 000000000..7b9a718fd --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/linux/nvmem.h @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, 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_LINUX_NVMEM_H__ +#define __NVGPU_LINUX_NVMEM_H__ + +#ifdef CONFIG_NVGPU_NVMEM_FUSE + +/** + * @file + * + * Interface for nvmem ops. + */ + +struct gk20a; + +#include +#include + +/** + * @brief - Reads calibration fuse. + * + * @param g [in] - GPU super structure. + * @param val [out] - Populated with calibration fuse value. + * + * - Provide information about the calibration fuse. + * + * @return 0 on success. + * + */ +int nvgpu_tegra_nvmem_read_reserved_calib(struct gk20a *g, u32 *val); + +/** + * @brief - Reads GCPLEX_CONFIG_FUSE configuration. + * + * @param g [in] - GPU super structure. + * @param val [out] - Populated with register GCPLEX_CONFIG_FUSE value. + * + * - Provide information about the GPU complex configuration. + * + * @return 0 on success. + * + */ +int nvgpu_tegra_nvmem_read_gcplex_config_fuse(struct gk20a *g, u32 *val); + +/** + * @brief - Reads the per-device identifier fuses. + * + * @param g [in] - GPU super structure. + * @param pdi [out] - Per-device identifier + * + * The per-device identifier fuses are FUSE_PDI0 and FUSE_PDI1. + * + * @return 0 on success + */ +int nvgpu_tegra_nvmem_read_per_device_identifier(struct gk20a *g, u64 *pdi); + +#endif /* CONFIG_NVGPU_NVMEM_FUSE */ + +#endif /* __NVGPU_LINUX_NVMEM_H__ */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/linux/soc_fuse.h b/drivers/gpu/nvgpu/include/nvgpu/linux/soc_fuse.h index ed8d73863..1194d90d5 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/linux/soc_fuse.h +++ b/drivers/gpu/nvgpu/include/nvgpu/linux/soc_fuse.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2020-2022, 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, @@ -18,13 +18,17 @@ #define NVGPU_LINUX_SOC_FUSE_H /* - * Note: Following defines should be ideally in tegra fuse driver. They are - * defined here since nvgpu uses the tegra_fuse_readl API directly to read - * those fuses. Once nvgpu starts using nvmem API to read these fuses, - * these offsets can be defined in tegra fuse driver. - * See Bug 200633045. + * Note: Following define should be ideally in tegra fuse driver. It is + * defined here since nvgpu uses the tegra_fuse_readl API directly to + * read that fuse. See Bug 200633045. */ +#ifndef FUSE_OPT_GPC_DISABLE_0 +#define FUSE_OPT_GPC_DISABLE_0 0x188 +#endif + +#ifndef CONFIG_NVGPU_NVMEM_FUSE + #ifndef FUSE_GCPLEX_CONFIG_FUSE_0 #define FUSE_GCPLEX_CONFIG_FUSE_0 0x1c8 #endif @@ -33,14 +37,12 @@ #define FUSE_RESERVED_CALIB0_0 0x204 #endif -#ifndef FUSE_OPT_GPC_DISABLE_0 -#define FUSE_OPT_GPC_DISABLE_0 0x188 -#endif - /* T186+ */ #if !defined(FUSE_PDI0) && !defined(FUSE_PDI1) #define FUSE_PDI0 0x300 #define FUSE_PDI1 0x304 #endif +#endif /* !CONFIG_NVGPU_NVMEM_FUSE */ + #endif /* NVGPU_LINUX_SOC_FUSE_H */ diff --git a/drivers/gpu/nvgpu/os/linux/fuse.c b/drivers/gpu/nvgpu/os/linux/fuse.c index ee0710b8a..7a4337930 100644 --- a/drivers/gpu/nvgpu/os/linux/fuse.c +++ b/drivers/gpu/nvgpu/os/linux/fuse.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2022, 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, @@ -14,6 +14,7 @@ #include #include +#include #include @@ -26,12 +27,20 @@ int nvgpu_tegra_get_gpu_speedo_id(struct gk20a *g, int *id) int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val) { +#ifdef CONFIG_NVGPU_NVMEM_FUSE + return nvgpu_tegra_nvmem_read_reserved_calib(g, val); +#else return tegra_fuse_readl(FUSE_RESERVED_CALIB0_0, val); +#endif } int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val) { +#ifdef CONFIG_NVGPU_NVMEM_FUSE + return nvgpu_tegra_nvmem_read_gcplex_config_fuse(g, val); +#else return tegra_fuse_readl(FUSE_GCPLEX_CONFIG_FUSE_0, val); +#endif } int nvgpu_tegra_fuse_read_opt_gpc_disable(struct gk20a *g, u32 *val) @@ -41,6 +50,9 @@ int nvgpu_tegra_fuse_read_opt_gpc_disable(struct gk20a *g, u32 *val) int nvgpu_tegra_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi) { +#ifdef CONFIG_NVGPU_NVMEM_FUSE + return nvgpu_tegra_nvmem_read_per_device_identifier(g, pdi); +#else u32 lo = 0U; u32 hi = 0U; int err; @@ -56,6 +68,7 @@ int nvgpu_tegra_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi) *pdi = ((u64)lo) | (((u64)hi) << 32); return 0; +#endif } #ifdef CONFIG_NVGPU_TEGRA_FUSE diff --git a/drivers/gpu/nvgpu/os/linux/nvmem.c b/drivers/gpu/nvgpu/os/linux/nvmem.c new file mode 100644 index 000000000..be39d6fc7 --- /dev/null +++ b/drivers/gpu/nvgpu/os/linux/nvmem.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, 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 + +#include + +#include "os_linux.h" + +#define NVMEM_CELL_GCPLEX_CONFIG_FUSE "gcplex-config-fuse" +#define NVMEM_CELL_CALIBRATION "calibration" +#define NVMEM_CELL_PDI0 "pdi0" +#define NVMEM_CELL_PDI1 "pdi1" + +int nvgpu_tegra_nvmem_read_reserved_calib(struct gk20a *g, u32 *val) +{ + struct device *dev = dev_from_gk20a(g); + int ret; + + ret = nvmem_cell_read_u32(dev, NVMEM_CELL_CALIBRATION, val); + if (ret < 0) { + nvgpu_err(g, "%s nvmem cell read failed %d", + NVMEM_CELL_CALIBRATION, ret); + return ret; + } + + return 0; +} + +int nvgpu_tegra_nvmem_read_gcplex_config_fuse(struct gk20a *g, u32 *val) +{ + struct device *dev = dev_from_gk20a(g); + int ret; + + ret = nvmem_cell_read_u32(dev, NVMEM_CELL_GCPLEX_CONFIG_FUSE, val); + if (ret < 0) { + nvgpu_err(g, "%s nvmem cell read failed %d", + NVMEM_CELL_GCPLEX_CONFIG_FUSE, ret); + return ret; + } + + return 0; +} + +int nvgpu_tegra_nvmem_read_per_device_identifier(struct gk20a *g, u64 *pdi) +{ + struct device *dev = dev_from_gk20a(g); + u32 lo = 0U; + u32 hi = 0U; + int err; + + err = nvmem_cell_read_u32(dev, NVMEM_CELL_PDI0, &lo); + if (err) { + return err; + } + + err = nvmem_cell_read_u32(dev, NVMEM_CELL_PDI1, &hi); + if (err) { + return err; + } + + *pdi = ((u64)lo) | (((u64)hi) << 32); + + return 0; +} diff --git a/drivers/gpu/nvgpu/os/linux/platform_ga10b_tegra.c b/drivers/gpu/nvgpu/os/linux/platform_ga10b_tegra.c index caa6e4d6d..9c1f0aa10 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_ga10b_tegra.c +++ b/drivers/gpu/nvgpu/os/linux/platform_ga10b_tegra.c @@ -33,7 +33,6 @@ #include #include #include -#include #ifdef CONFIG_NV_TEGRA_BPMP #include