diff --git a/arch/nvgpu-posix.yaml b/arch/nvgpu-posix.yaml index 79268aa16..6f43c90f8 100644 --- a/arch/nvgpu-posix.yaml +++ b/arch/nvgpu-posix.yaml @@ -47,6 +47,7 @@ headers: include/nvgpu/posix/pci.h, include/nvgpu/posix/posix-fault-injection.h, include/nvgpu/posix/probe.h, + include/nvgpu/posix/soc_fuse.h, include/nvgpu/posix/sort.h, include/nvgpu/posix/vm.h, include/nvgpu/posix/posix_vidmem.h ] diff --git a/drivers/gpu/nvgpu/include/nvgpu/fuse.h b/drivers/gpu/nvgpu/include/nvgpu/fuse.h index 1d459a919..4bd3961bc 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/fuse.h +++ b/drivers/gpu/nvgpu/include/nvgpu/fuse.h @@ -32,6 +32,7 @@ void nvgpu_tegra_fuse_write_bypass(struct gk20a *g, u32 val); void nvgpu_tegra_fuse_write_access_sw(struct gk20a *g, u32 val); 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); +void nvgpu_tegra_fuse_write_gcplex_config_fuse(struct gk20a *g, u32 val); int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val); int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val); diff --git a/drivers/gpu/nvgpu/include/nvgpu/posix/io.h b/drivers/gpu/nvgpu/include/nvgpu/posix/io.h index ca5eeea28..b6bfd0945 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/posix/io.h +++ b/drivers/gpu/nvgpu/include/nvgpu/posix/io.h @@ -62,6 +62,10 @@ struct nvgpu_posix_io_callbacks { void (*bar1_readl)(struct gk20a *g, struct nvgpu_reg_access *access); void (*usermode_writel)(struct gk20a *g, struct nvgpu_reg_access *access); + void (*tegra_fuse_control_write)(u32 value, unsigned long offset); + int (*tegra_fuse_control_read)(unsigned long offset, u32 *value); + void (*tegra_fuse_writel)(u32 value, unsigned long offset); + int (*tegra_fuse_readl)(unsigned long offset, u32 *value); }; struct nvgpu_posix_io_callbacks *nvgpu_posix_register_io( diff --git a/drivers/gpu/nvgpu/include/nvgpu/posix/soc_fuse.h b/drivers/gpu/nvgpu/include/nvgpu/posix/soc_fuse.h new file mode 100644 index 000000000..e7623fdab --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/posix/soc_fuse.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef NVGPU_POSIX_SOC_FUSE_H +#define NVGPU_POSIX_SOC_FUSE_H + +#define FUSE_FUSEBYPASS_0 0x24 +#define FUSE_WRITE_ACCESS_SW_0 0x30 +#define FUSE_OPT_GPU_TPC0_DISABLE_0 0x20c +#define FUSE_OPT_GPU_TPC1_DISABLE_0 0x23c +#define FUSE_GCPLEX_CONFIG_FUSE_0 0x1c8 +#define FUSE_RESERVED_CALIB0_0 0x204 + +#endif /* NVGPU_POSIX_SOC_FUSE_H */ diff --git a/drivers/gpu/nvgpu/os/posix/fuse.c b/drivers/gpu/nvgpu/os/posix/fuse.c index 54a600186..b4b18b672 100644 --- a/drivers/gpu/nvgpu/os/posix/fuse.c +++ b/drivers/gpu/nvgpu/os/posix/fuse.c @@ -19,38 +19,85 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - #include +#include + +#include +#include + int nvgpu_tegra_get_gpu_speedo_id(struct gk20a *g) { return 0; } +/* + * Use tegra_fuse_control_read/write() APIs for fuse offsets upto 0x100 + * Use tegra_fuse_readl/writel() APIs for fuse offsets above 0x100 + */ void nvgpu_tegra_fuse_write_bypass(struct gk20a *g, u32 val) { + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + if (p->callbacks == NULL || + p->callbacks->tegra_fuse_control_write == NULL) { + return; + } + p->callbacks->tegra_fuse_control_write(val, FUSE_FUSEBYPASS_0); } void nvgpu_tegra_fuse_write_access_sw(struct gk20a *g, u32 val) { + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + if (p->callbacks == NULL || + p->callbacks->tegra_fuse_control_write == NULL) { + return; + } + + p->callbacks->tegra_fuse_control_write(val, FUSE_WRITE_ACCESS_SW_0); } void nvgpu_tegra_fuse_write_opt_gpu_tpc0_disable(struct gk20a *g, u32 val) { + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + if (p->callbacks == NULL || p->callbacks->tegra_fuse_writel == NULL) { + return; + } + + p->callbacks->tegra_fuse_writel(val, FUSE_OPT_GPU_TPC0_DISABLE_0); } void nvgpu_tegra_fuse_write_opt_gpu_tpc1_disable(struct gk20a *g, u32 val) { + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + if (p->callbacks == NULL || p->callbacks->tegra_fuse_writel == NULL) { + return; + } + + 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) { - *val = 0; + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); - return 0; + if (p->callbacks == NULL || p->callbacks->tegra_fuse_readl == NULL) { + return 0; + } + + return p->callbacks->tegra_fuse_readl(FUSE_GCPLEX_CONFIG_FUSE_0, val); } int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val) { - return -ENODEV; + 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); } diff --git a/userspace/units/fifo/nvgpu-fifo-gv11b.c b/userspace/units/fifo/nvgpu-fifo-gv11b.c index 2f7f426b0..7884174b3 100644 --- a/userspace/units/fifo/nvgpu-fifo-gv11b.c +++ b/userspace/units/fifo/nvgpu-fifo-gv11b.c @@ -27,9 +27,12 @@ #include #include +#include #include +#include "hal/fuse/fuse_gm20b.h" + #include "nvgpu-fifo-gv11b.h" u32 gv11b_fuse_regs[] = { @@ -13490,6 +13493,14 @@ static void readl_access_reg_fn(struct gk20a *g, access->value = nvgpu_posix_io_readl_reg_space(g, access->addr); } +static int tegra_fuse_readl_access_reg_fn(unsigned long offset, u32 *value) +{ + if (offset == FUSE_GCPLEX_CONFIG_FUSE_0) { + *value = GCPLEX_CONFIG_WPR_ENABLED_MASK; + } + return 0; +} + static struct nvgpu_posix_io_callbacks test_reg_callbacks = { /* Write APIs all can use the same accessor. */ .writel = writel_access_reg_fn, @@ -13501,6 +13512,8 @@ static struct nvgpu_posix_io_callbacks test_reg_callbacks = { .__readl = readl_access_reg_fn, .readl = readl_access_reg_fn, .bar1_readl = readl_access_reg_fn, + + .tegra_fuse_readl = tegra_fuse_readl_access_reg_fn, }; int test_fifo_setup_gv11b_reg_space(struct unit_module *m, struct gk20a *g) @@ -13583,7 +13596,7 @@ clean_up_top: nvgpu_posix_io_unregister_reg_space(g, &gv11b_top_reg_space); clean_up_master: nvgpu_posix_io_unregister_reg_space(g, &gv11b_master_reg_space); - return UNIT_FAIL; + return -ENOMEM; } void test_fifo_cleanup_gv11b_reg_space(struct unit_module *m, struct gk20a *g) diff --git a/userspace/units/fifo/tsg/nvgpu-tsg.c b/userspace/units/fifo/tsg/nvgpu-tsg.c index e969d3572..7f9707fcc 100644 --- a/userspace/units/fifo/tsg/nvgpu-tsg.c +++ b/userspace/units/fifo/tsg/nvgpu-tsg.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "hal/fifo/tsg_gk20a.h" @@ -86,14 +87,8 @@ static int test_fifo_init_support(struct unit_module *m, goto fail; } - /* - * set IS_FMODEL to avoid reading fuses - * TODO: add fuses reg space to avoid this - */ - nvgpu_set_enabled(g, NVGPU_IS_FMODEL, true); gv11b_init_hal(g); g->ops.fifo.init_fifo_setup_hw = NULL; - nvgpu_set_enabled(g, NVGPU_IS_FMODEL, false); #ifdef NVGPU_USERD /* @@ -140,7 +135,7 @@ static int test_tsg_release(struct unit_module *m, struct test_tsg_args *t = args; if (t->tsg == NULL) { - unit_return_fail(m, "tsg in NULL"); + unit_return_fail(m, "tsg is NULL"); } nvgpu_ref_put(&t->tsg->refcount, nvgpu_tsg_release);