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 */