From b117f40f6c79e8ebea43e829a5645d6ce89eea04 Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Thu, 2 Jul 2020 18:01:31 +0530 Subject: [PATCH] gpu: nvgpu: separate tegra fuse read from under CONFIG_NVGPU_TEGRA_FUSE tegra_fuse_readl is supported in upstream. Separate out the functions using this API from the config CONFIG_NVGPU_TEGRA_FUSE. Following four fuses are defined in downstream kernel repositories in tegra fuse header. It can be incorporated in upstream if nvgpu starts reading those fuses using nvmem APIs. Hence define those fuse offsets in nvgpu itself for now. 1. FUSE_RESERVED_CALIB0_0 2. FUSE_GCPLEX_CONFIG_FUSE_0 3. FUSE_PDI0 4. FUSE_PDI1 Bug 200625647 Change-Id: I8da8c0c3a0682fdab806fa57035fedd29ef22c26 Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2369955 Reviewed-by: automaticguardword Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-misra Reviewed-by: Jonathan Hunter Reviewed-by: Sami Kiminki Reviewed-by: Vaibhav Kachore Reviewed-by: Debarshi Dutta Reviewed-by: mobile promotions Tested-by: mobile promotions GVS: Gerrit_Virtual_Submit --- arch/nvgpu-linux.yaml | 1 + drivers/gpu/nvgpu/Makefile | 5 +- drivers/gpu/nvgpu/Makefile.sources | 7 +- drivers/gpu/nvgpu/include/nvgpu/fuse.h | 87 ++++++------------- .../gpu/nvgpu/include/nvgpu/linux/soc_fuse.h | 42 +++++++++ drivers/gpu/nvgpu/os/linux/fuse.c | 66 +++++++------- drivers/gpu/nvgpu/os/posix/fuse.c | 79 +++++++++-------- 7 files changed, 152 insertions(+), 135 deletions(-) create mode 100644 drivers/gpu/nvgpu/include/nvgpu/linux/soc_fuse.h diff --git a/arch/nvgpu-linux.yaml b/arch/nvgpu-linux.yaml index dff9cbe94..098a644fa 100644 --- a/arch/nvgpu-linux.yaml +++ b/arch/nvgpu-linux.yaml @@ -238,6 +238,7 @@ headers: include/nvgpu/linux/rwsem.h, include/nvgpu/linux/sim.h, include/nvgpu/linux/sim_pci.h, + include/nvgpu/linux/soc_fuse.h, include/nvgpu/linux/thread.h, include/nvgpu/linux/log.h, include/nvgpu/linux/utils.h, diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 3d0339ac7..922cfe889 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -430,8 +430,8 @@ nvgpu-$(CONFIG_DEBUG_FS) += \ os/linux/debug_fecs_trace.o endif - nvgpu-$(CONFIG_TEGRA_GK20A) += \ + os/linux/fuse.o \ os/linux/module.o \ os/linux/module_usermode.o \ os/linux/platform_gk20a_tegra.o \ @@ -439,8 +439,7 @@ nvgpu-$(CONFIG_TEGRA_GK20A) += \ os/linux/platform_gv11b_tegra.o ifeq ($(CONFIG_TEGRA_GK20A),y) -nvgpu-$(CONFIG_NVGPU_TEGRA_FUSE) += os/linux/fuse.o \ - os/linux/soc.o +nvgpu-$(CONFIG_NVGPU_TEGRA_FUSE) += os/linux/soc.o endif nvgpu-$(CONFIG_NVGPU_SYNCFD_ANDROID) += \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index 7fb4b8ed1..c631e41f2 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -37,16 +37,13 @@ srcs += os/posix/nvgpu.c \ os/posix/stubs.c \ os/posix/posix-nvhost.c \ os/posix/posix-vgpu.c \ - os/posix/posix-dt.c + os/posix/posix-dt.c \ + os/posix/fuse.c ifdef CONFIG_NVGPU_VPR srcs += os/posix/posix-vpr.c endif -ifdef CONFIG_NVGPU_TEGRA_FUSE -srcs += os/posix/fuse.c -endif - ifdef CONFIG_NVGPU_FECS_TRACE srcs += os/posix/fecs_trace_posix.c endif diff --git a/drivers/gpu/nvgpu/include/nvgpu/fuse.h b/drivers/gpu/nvgpu/include/nvgpu/fuse.h index e52f77e8c..8d4c13d77 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/fuse.h +++ b/drivers/gpu/nvgpu/include/nvgpu/fuse.h @@ -36,13 +36,38 @@ struct gk20a; #include "include/nvgpu/nvgpu_next_fuse.h" #endif -#ifdef CONFIG_NVGPU_TEGRA_FUSE - #ifdef CONFIG_NVGPU_NON_FUSA int nvgpu_tegra_get_gpu_speedo_id(struct gk20a *g, int *id); int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val); #endif /* CONFIG_NVGPU_NON_FUSA */ +/** + * @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_fuse_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_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi); + +#ifdef CONFIG_NVGPU_TEGRA_FUSE + /** * @brief - Write Fuse bypass register which controls fuse bypass. * @@ -92,46 +117,8 @@ void nvgpu_tegra_fuse_write_opt_gpu_tpc0_disable(struct gk20a *g, u32 val); */ void nvgpu_tegra_fuse_write_opt_gpu_tpc1_disable(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_fuse_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_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi); - #else /* CONFIG_NVGPU_TEGRA_FUSE */ -#ifdef CONFIG_NVGPU_NON_FUSA -static inline int nvgpu_tegra_get_gpu_speedo_id(struct gk20a *g, int *id) -{ - return -EINVAL; -} - -static inline int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, - u32 *val) -{ - return -EINVAL; -} -#endif /* CONFIG_NVGPU_NON_FUSA */ - static inline void nvgpu_tegra_fuse_write_bypass(struct gk20a *g, u32 val) { } @@ -150,24 +137,6 @@ static inline void nvgpu_tegra_fuse_write_opt_gpu_tpc1_disable(struct gk20a *g, { } -static inline int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, - u32 *val) -{ - /* - * Setting gcplex_config fuse to wpr_enabled/vpr_auto_fetch_disable - * by default that is expected on the production chip. - */ - *val = 0x4; - - return 0; -} - -static inline int nvgpu_tegra_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi) -{ - *pdi = 0U; - - return 0; -} - #endif /* CONFIG_NVGPU_TEGRA_FUSE */ + #endif /* NVGPU_FUSE_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/linux/soc_fuse.h b/drivers/gpu/nvgpu/include/nvgpu/linux/soc_fuse.h new file mode 100644 index 000000000..01c480c4c --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/linux/soc_fuse.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020, 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_SOC_FUSE_H +#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. + */ + +#ifndef FUSE_GCPLEX_CONFIG_FUSE_0 +#define FUSE_GCPLEX_CONFIG_FUSE_0 0x1c8 +#endif + +#ifndef FUSE_RESERVED_CALIB0_0 +#define FUSE_RESERVED_CALIB0_0 0x204 +#endif + +/* T186+ */ +#if !defined(FUSE_PDI0) && !defined(FUSE_PDI1) +#define FUSE_PDI0 0x300 +#define FUSE_PDI1 0x304 +#endif + +#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 ca2748d19..ada735ee5 100644 --- a/drivers/gpu/nvgpu/os/linux/fuse.c +++ b/drivers/gpu/nvgpu/os/linux/fuse.c @@ -11,10 +11,12 @@ * more details. */ -#include - #include +#include + +#include + int nvgpu_tegra_get_gpu_speedo_id(struct gk20a *g, int *id) { *id = tegra_sku_info.gpu_speedo_id; @@ -22,6 +24,37 @@ int nvgpu_tegra_get_gpu_speedo_id(struct gk20a *g, int *id) return 0; } +int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val) +{ + return tegra_fuse_readl(FUSE_RESERVED_CALIB0_0, val); +} + +int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val) +{ + return tegra_fuse_readl(FUSE_GCPLEX_CONFIG_FUSE_0, val); +} + +int nvgpu_tegra_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi) +{ + u32 lo = 0U; + u32 hi = 0U; + int err; + + err = tegra_fuse_readl(FUSE_PDI0, &lo); + if (err) + return err; + + err = tegra_fuse_readl(FUSE_PDI1, &hi); + if (err) + return err; + + *pdi = ((u64)lo) | (((u64)hi) << 32); + + return 0; +} + +#ifdef CONFIG_NVGPU_TEGRA_FUSE + /* * Use tegra_fuse_control_read/write() APIs for fuse offsets upto 0x100 * Use tegra_fuse_readl/writel() APIs for fuse offsets above 0x100 @@ -46,31 +79,4 @@ void nvgpu_tegra_fuse_write_opt_gpu_tpc1_disable(struct gk20a *g, u32 val) tegra_fuse_writel(val, FUSE_OPT_GPU_TPC1_DISABLE_0); } -int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val) -{ - return tegra_fuse_readl(FUSE_GCPLEX_CONFIG_FUSE_0, val); -} - -int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val) -{ - return tegra_fuse_readl(FUSE_RESERVED_CALIB0_0, val); -} - -int nvgpu_tegra_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi) -{ - u32 lo = 0U; - u32 hi = 0U; - int err; - - err = tegra_fuse_readl(FUSE_PDI0, &lo); - if (err) - return err; - - err = tegra_fuse_readl(FUSE_PDI1, &hi); - if (err) - return err; - - *pdi = ((u64)lo) | (((u64)hi) << 32); - - return 0; -} +#endif /* CONFIG_NVGPU_TEGRA_FUSE */ diff --git a/drivers/gpu/nvgpu/os/posix/fuse.c b/drivers/gpu/nvgpu/os/posix/fuse.c index c97d9eb02..9d78e2f13 100644 --- a/drivers/gpu/nvgpu/os/posix/fuse.c +++ b/drivers/gpu/nvgpu/os/posix/fuse.c @@ -33,8 +33,48 @@ int nvgpu_tegra_get_gpu_speedo_id(struct gk20a *g, int *id) { return 0; } + +int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + if (p->callbacks == NULL || p->callbacks->tegra_fuse_readl == NULL) { + return -ENODEV; + } + + return p->callbacks->tegra_fuse_readl(FUSE_RESERVED_CALIB0_0, val); +} #endif +int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + if (p->callbacks == NULL || p->callbacks->tegra_fuse_readl == NULL) { + /* + * Generally for nvgpu, if priv_sec is enabled, we are expecting + * WPR to be enabled and auto fetching of VPR to _not_ be + * disabled (in other words VPR autofetch to be enabled - cause + * that's not confusing at all). + */ + *val = GCPLEX_CONFIG_WPR_ENABLED_MASK; + + return 0; + } + + return p->callbacks->tegra_fuse_readl(FUSE_GCPLEX_CONFIG_FUSE_0, val); +} + + +int nvgpu_tegra_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi) +{ + *pdi = 0; + + return 0; +} + +#ifdef CONFIG_NVGPU_TEGRA_FUSE + /* * Use tegra_fuse_control_read/write() APIs for fuse offsets upto 0x100 * Use tegra_fuse_readl/writel() APIs for fuse offsets above 0x100 @@ -84,41 +124,4 @@ void nvgpu_tegra_fuse_write_opt_gpu_tpc1_disable(struct gk20a *g, u32 val) return p->callbacks->tegra_fuse_writel(val, FUSE_OPT_GPU_TPC1_DISABLE_0); } -int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val) -{ - struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); - - if (p->callbacks == NULL || p->callbacks->tegra_fuse_readl == NULL) { - /* - * Generally for nvgpu, if priv_sec is enabled, we are expecting - * WPR to be enabled and auto fetching of VPR to _not_ be - * disabled (in other words VPR autofetch to be enabled - cause - * that's not confusing at all). - */ - *val = GCPLEX_CONFIG_WPR_ENABLED_MASK; - - return 0; - } - - return p->callbacks->tegra_fuse_readl(FUSE_GCPLEX_CONFIG_FUSE_0, val); -} - -#ifdef CONFIG_NVGPU_NON_FUSA -int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val) -{ - struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); - - if (p->callbacks == NULL || p->callbacks->tegra_fuse_readl == NULL) { - return -ENODEV; - } - - return p->callbacks->tegra_fuse_readl(FUSE_RESERVED_CALIB0_0, val); -} -#endif - -int nvgpu_tegra_fuse_read_per_device_identifier(struct gk20a *g, u64 *pdi) -{ - *pdi = 0; - - return 0; -} +#endif /* CONFIG_NVGPU_TEGRA_FUSE */