diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/sec2')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 164 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c | 197 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 318 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c | 43 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 86 |
7 files changed, 849 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild new file mode 100644 index 000000000..19feadb1f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: MIT +nvkm-y += nvkm/engine/sec2/base.o +nvkm-y += nvkm/engine/sec2/gp102.o +nvkm-y += nvkm/engine/sec2/gp108.o +nvkm-y += nvkm/engine/sec2/tu102.o +nvkm-y += nvkm/engine/sec2/ga102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c new file mode 100644 index 000000000..f2c60da5d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2017, 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. + */ +#include "priv.h" + +#include <core/firmware.h> +#include <subdev/mc.h> +#include <subdev/timer.h> + +#include <nvfw/sec2.h> + +static int +nvkm_sec2_finimsg(void *priv, struct nvfw_falcon_msg *hdr) +{ + struct nvkm_sec2 *sec2 = priv; + + atomic_set(&sec2->running, 0); + return 0; +} + +static int +nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) +{ + struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + struct nvkm_subdev *subdev = &sec2->engine.subdev; + struct nvkm_falcon *falcon = &sec2->falcon; + struct nvkm_falcon_cmdq *cmdq = sec2->cmdq; + struct nvfw_falcon_cmd cmd = { + .unit_id = sec2->func->unit_unload, + .size = sizeof(cmd), + }; + int ret; + + if (!subdev->use.enabled) + return 0; + + if (atomic_read(&sec2->initmsg) == 1) { + ret = nvkm_falcon_cmdq_send(cmdq, &cmd, nvkm_sec2_finimsg, sec2, + msecs_to_jiffies(1000)); + WARN_ON(ret); + + nvkm_msec(subdev->device, 2000, + if (nvkm_falcon_rd32(falcon, 0x100) & 0x00000010) + break; + ); + } + + nvkm_inth_block(&subdev->inth); + + nvkm_falcon_cmdq_fini(cmdq); + falcon->func->disable(falcon); + nvkm_falcon_put(falcon, subdev); + return 0; +} + +static int +nvkm_sec2_init(struct nvkm_engine *engine) +{ + struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + struct nvkm_subdev *subdev = &sec2->engine.subdev; + struct nvkm_falcon *falcon = &sec2->falcon; + int ret; + + ret = nvkm_falcon_get(falcon, subdev); + if (ret) + return ret; + + nvkm_falcon_wr32(falcon, 0x014, 0xffffffff); + atomic_set(&sec2->initmsg, 0); + atomic_set(&sec2->running, 1); + nvkm_inth_allow(&subdev->inth); + + nvkm_falcon_start(falcon); + return 0; +} + +static int +nvkm_sec2_oneinit(struct nvkm_engine *engine) +{ + struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + struct nvkm_subdev *subdev = &sec2->engine.subdev; + struct nvkm_intr *intr = &sec2->engine.subdev.device->mc->intr; + enum nvkm_intr_type type = NVKM_INTR_SUBDEV; + + if (sec2->func->intr_vector) { + intr = sec2->func->intr_vector(sec2, &type); + if (IS_ERR(intr)) + return PTR_ERR(intr); + } + + return nvkm_inth_add(intr, type, NVKM_INTR_PRIO_NORMAL, subdev, sec2->func->intr, + &subdev->inth); +} + +static void * +nvkm_sec2_dtor(struct nvkm_engine *engine) +{ + struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + + nvkm_falcon_msgq_del(&sec2->msgq); + nvkm_falcon_cmdq_del(&sec2->cmdq); + nvkm_falcon_qmgr_del(&sec2->qmgr); + nvkm_falcon_dtor(&sec2->falcon); + return sec2; +} + +static const struct nvkm_engine_func +nvkm_sec2 = { + .dtor = nvkm_sec2_dtor, + .oneinit = nvkm_sec2_oneinit, + .init = nvkm_sec2_init, + .fini = nvkm_sec2_fini, +}; + +int +nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device, + enum nvkm_subdev_type type, int inst, u32 addr, struct nvkm_sec2 **psec2) +{ + struct nvkm_sec2 *sec2; + int ret; + + if (!(sec2 = *psec2 = kzalloc(sizeof(*sec2), GFP_KERNEL))) + return -ENOMEM; + + ret = nvkm_engine_ctor(&nvkm_sec2, device, type, inst, true, &sec2->engine); + if (ret) + return ret; + + fwif = nvkm_firmware_load(&sec2->engine.subdev, fwif, "Sec2", sec2); + if (IS_ERR(fwif)) + return PTR_ERR(fwif); + + sec2->func = fwif->func; + + ret = nvkm_falcon_ctor(sec2->func->flcn, &sec2->engine.subdev, + sec2->engine.subdev.name, addr, &sec2->falcon); + if (ret) + return ret; + + if ((ret = nvkm_falcon_qmgr_new(&sec2->falcon, &sec2->qmgr)) || + (ret = nvkm_falcon_cmdq_new(sec2->qmgr, "cmdq", &sec2->cmdq)) || + (ret = nvkm_falcon_msgq_new(sec2->qmgr, "msgq", &sec2->msgq))) + return ret; + + return 0; +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c new file mode 100644 index 000000000..945abb815 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c @@ -0,0 +1,197 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ +#include "priv.h" +#include <subdev/acr.h> +#include <subdev/vfn.h> + +#include <nvfw/flcn.h> +#include <nvfw/sec2.h> + +static int +ga102_sec2_initmsg(struct nvkm_sec2 *sec2) +{ + struct nv_sec2_init_msg_v1 msg; + int ret, i; + + ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg)); + if (ret) + return ret; + + if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT || + msg.msg_type != NV_SEC2_INIT_MSG_INIT) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) { + if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) { + nvkm_falcon_msgq_init(sec2->msgq, msg.queue_info[i].index, + msg.queue_info[i].offset, + msg.queue_info[i].size); + } else { + nvkm_falcon_cmdq_init(sec2->cmdq, msg.queue_info[i].index, + msg.queue_info[i].offset, + msg.queue_info[i].size); + } + } + + return 0; +} + +static struct nvkm_intr * +ga102_sec2_intr_vector(struct nvkm_sec2 *sec2, enum nvkm_intr_type *pvector) +{ + struct nvkm_device *device = sec2->engine.subdev.device; + struct nvkm_falcon *falcon = &sec2->falcon; + int ret; + + ret = ga102_flcn_select(falcon); + if (ret) + return ERR_PTR(ret); + + *pvector = nvkm_rd32(device, 0x8403e0) & 0x000000ff; + return &device->vfn->intr; +} + +static int +ga102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nvfw_falcon_msg *hdr) +{ + struct nv_sec2_acr_bootstrap_falcon_msg_v1 *msg = + container_of(hdr, typeof(*msg), msg.hdr); + struct nvkm_subdev *subdev = priv; + const char *name = nvkm_acr_lsf_id(msg->falcon_id); + + if (msg->error_code) { + nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for falcon %d [%s]: %08x %08x\n", + msg->falcon_id, name, msg->error_code, msg->unkn08); + return -EINVAL; + } + + nvkm_debug(subdev, "%s booted\n", name); + return 0; +} + +static int +ga102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, enum nvkm_acr_lsf_id id) +{ + struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon); + struct nv_sec2_acr_bootstrap_falcon_cmd_v1 cmd = { + .cmd.hdr.unit_id = sec2->func->unit_acr, + .cmd.hdr.size = sizeof(cmd), + .cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON, + .flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES, + .falcon_id = id, + }; + + return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr, + ga102_sec2_acr_bootstrap_falcon_callback, + &sec2->engine.subdev, + msecs_to_jiffies(1000)); +} + +static const struct nvkm_acr_lsf_func +ga102_sec2_acr_0 = { + .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), + .bld_write = gp102_sec2_acr_bld_write_1, + .bld_patch = gp102_sec2_acr_bld_patch_1, + .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | + BIT_ULL(NVKM_ACR_LSF_GPCCS) | + BIT_ULL(NVKM_ACR_LSF_SEC2), + .bootstrap_falcon = ga102_sec2_acr_bootstrap_falcon, +}; + +static const struct nvkm_falcon_func +ga102_sec2_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .select = ga102_flcn_select, + .addr2 = 0x1000, + .reset_pmc = true, + .reset_eng = gp102_flcn_reset_eng, + .reset_prep = ga102_flcn_reset_prep, + .reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing, + .imem_dma = &ga102_flcn_dma, + .dmem_pio = &gm200_flcn_dmem_pio, + .dmem_dma = &ga102_flcn_dma, + .emem_addr = 0x01000000, + .emem_pio = &gp102_flcn_emem_pio, + .start = nvkm_falcon_v1_start, + .cmdq = { 0xc00, 0xc04, 8 }, + .msgq = { 0xc80, 0xc84, 8 }, +}; + +static const struct nvkm_sec2_func +ga102_sec2 = { + .flcn = &ga102_sec2_flcn, + .intr_vector = ga102_sec2_intr_vector, + .intr = gp102_sec2_intr, + .initmsg = ga102_sec2_initmsg, + .unit_acr = NV_SEC2_UNIT_V2_ACR, + .unit_unload = NV_SEC2_UNIT_V2_UNLOAD, +}; + +MODULE_FIRMWARE("nvidia/ga102/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga102/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga102/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga102/sec2/hs_bl_sig.bin"); + +MODULE_FIRMWARE("nvidia/ga103/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga103/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga103/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga103/sec2/hs_bl_sig.bin"); + +MODULE_FIRMWARE("nvidia/ga104/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga104/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga104/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga104/sec2/hs_bl_sig.bin"); + +MODULE_FIRMWARE("nvidia/ga106/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga106/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga106/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga106/sec2/hs_bl_sig.bin"); + +MODULE_FIRMWARE("nvidia/ga107/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/ga107/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/ga107/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/ga107/sec2/hs_bl_sig.bin"); + +static int +ga102_sec2_load(struct nvkm_sec2 *sec2, int ver, + const struct nvkm_sec2_fwif *fwif) +{ + return nvkm_acr_lsfw_load_sig_image_desc_v2(&sec2->engine.subdev, &sec2->falcon, + NVKM_ACR_LSF_SEC2, "sec2/", ver, fwif->acr); +} + +static const struct nvkm_sec2_fwif +ga102_sec2_fwif[] = { + { 0, ga102_sec2_load, &ga102_sec2, &ga102_sec2_acr_0 }, + { -1, gp102_sec2_nofw, &ga102_sec2 } +}; + +int +ga102_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_sec2 **psec2) +{ + /* TOP info wasn't updated on Turing to reflect the PRI + * address change for some reason. We override it here. + */ + return nvkm_sec2_new_(ga102_sec2_fwif, device, type, inst, 0x840000, psec2); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c new file mode 100644 index 000000000..c64013d10 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2017, 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. + */ +#include "priv.h" + +#include <core/memory.h> +#include <subdev/acr.h> +#include <subdev/timer.h> + +#include <nvfw/flcn.h> +#include <nvfw/sec2.h> + +int +gp102_sec2_nofw(struct nvkm_sec2 *sec2, int ver, + const struct nvkm_sec2_fwif *fwif) +{ + nvkm_warn(&sec2->engine.subdev, "firmware unavailable\n"); + return 0; +} + +static int +gp102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nvfw_falcon_msg *hdr) +{ + struct nv_sec2_acr_bootstrap_falcon_msg *msg = + container_of(hdr, typeof(*msg), msg.hdr); + struct nvkm_subdev *subdev = priv; + const char *name = nvkm_acr_lsf_id(msg->falcon_id); + + if (msg->error_code) { + nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for " + "falcon %d [%s]: %08x\n", + msg->falcon_id, name, msg->error_code); + return -EINVAL; + } + + nvkm_debug(subdev, "%s booted\n", name); + return 0; +} + +static int +gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, + enum nvkm_acr_lsf_id id) +{ + struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon); + struct nv_sec2_acr_bootstrap_falcon_cmd cmd = { + .cmd.hdr.unit_id = sec2->func->unit_acr, + .cmd.hdr.size = sizeof(cmd), + .cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON, + .flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES, + .falcon_id = id, + }; + + return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr, + gp102_sec2_acr_bootstrap_falcon_callback, + &sec2->engine.subdev, + msecs_to_jiffies(1000)); +} + +static void +gp102_sec2_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) +{ + struct loader_config_v1 hdr; + nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); + hdr.code_dma_base = hdr.code_dma_base + adjust; + hdr.data_dma_base = hdr.data_dma_base + adjust; + hdr.overlay_dma_base = hdr.overlay_dma_base + adjust; + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); + loader_config_v1_dump(&acr->subdev, &hdr); +} + +static void +gp102_sec2_acr_bld_write(struct nvkm_acr *acr, u32 bld, + struct nvkm_acr_lsfw *lsfw) +{ + const struct loader_config_v1 hdr = { + .dma_idx = FALCON_SEC2_DMAIDX_UCODE, + .code_dma_base = lsfw->offset.img + lsfw->app_start_offset, + .code_size_total = lsfw->app_size, + .code_size_to_load = lsfw->app_resident_code_size, + .code_entry_point = lsfw->app_imem_entry, + .data_dma_base = lsfw->offset.img + lsfw->app_start_offset + + lsfw->app_resident_data_offset, + .data_size = lsfw->app_resident_data_size, + .overlay_dma_base = lsfw->offset.img + lsfw->app_start_offset, + .argc = 1, + .argv = lsfw->falcon->func->emem_addr, + }; + + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); +} + +static const struct nvkm_acr_lsf_func +gp102_sec2_acr_0 = { + .bld_size = sizeof(struct loader_config_v1), + .bld_write = gp102_sec2_acr_bld_write, + .bld_patch = gp102_sec2_acr_bld_patch, + .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | + BIT_ULL(NVKM_ACR_LSF_GPCCS) | + BIT_ULL(NVKM_ACR_LSF_SEC2), + .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, +}; + +int +gp102_sec2_initmsg(struct nvkm_sec2 *sec2) +{ + struct nv_sec2_init_msg msg; + int ret, i; + + ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg)); + if (ret) + return ret; + + if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT || + msg.msg_type != NV_SEC2_INIT_MSG_INIT) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) { + if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) { + nvkm_falcon_msgq_init(sec2->msgq, + msg.queue_info[i].index, + msg.queue_info[i].offset, + msg.queue_info[i].size); + } else { + nvkm_falcon_cmdq_init(sec2->cmdq, + msg.queue_info[i].index, + msg.queue_info[i].offset, + msg.queue_info[i].size); + } + } + + return 0; +} + +irqreturn_t +gp102_sec2_intr(struct nvkm_inth *inth) +{ + struct nvkm_sec2 *sec2 = container_of(inth, typeof(*sec2), engine.subdev.inth); + struct nvkm_subdev *subdev = &sec2->engine.subdev; + struct nvkm_falcon *falcon = &sec2->falcon; + u32 disp = nvkm_falcon_rd32(falcon, 0x01c); + u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16); + + if (intr & 0x00000040) { + if (unlikely(atomic_read(&sec2->initmsg) == 0)) { + int ret = sec2->func->initmsg(sec2); + + if (ret) + nvkm_error(subdev, "error parsing init message: %d\n", ret); + + atomic_set(&sec2->initmsg, ret ?: 1); + } + + if (atomic_read(&sec2->initmsg) > 0) { + if (!nvkm_falcon_msgq_empty(sec2->msgq)) + nvkm_falcon_msgq_recv(sec2->msgq); + } + + nvkm_falcon_wr32(falcon, 0x004, 0x00000040); + intr &= ~0x00000040; + } + + if (intr & 0x00000010) { + if (atomic_read(&sec2->running)) { + FLCN_ERR(falcon, "halted"); + gm200_flcn_tracepc(falcon); + } + + nvkm_falcon_wr32(falcon, 0x004, 0x00000010); + intr &= ~0x00000010; + } + + if (intr) { + nvkm_error(subdev, "unhandled intr %08x\n", intr); + nvkm_falcon_wr32(falcon, 0x004, intr); + } + + return IRQ_HANDLED; +} + +static const struct nvkm_falcon_func +gp102_sec2_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .reset_pmc = true, + .reset_eng = gp102_flcn_reset_eng, + .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, + .debug = 0x408, + .bind_inst = gm200_flcn_bind_inst, + .bind_stat = gm200_flcn_bind_stat, + .bind_intr = true, + .imem_pio = &gm200_flcn_imem_pio, + .dmem_pio = &gm200_flcn_dmem_pio, + .emem_addr = 0x01000000, + .emem_pio = &gp102_flcn_emem_pio, + .start = nvkm_falcon_v1_start, + .cmdq = { 0xa00, 0xa04, 8 }, + .msgq = { 0xa30, 0xa34, 8 }, +}; + +const struct nvkm_sec2_func +gp102_sec2 = { + .flcn = &gp102_sec2_flcn, + .unit_unload = NV_SEC2_UNIT_UNLOAD, + .unit_acr = NV_SEC2_UNIT_ACR, + .intr = gp102_sec2_intr, + .initmsg = gp102_sec2_initmsg, +}; + +MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin"); + +void +gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust) +{ + struct flcn_bl_dmem_desc_v2 hdr; + nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); + hdr.code_dma_base = hdr.code_dma_base + adjust; + hdr.data_dma_base = hdr.data_dma_base + adjust; + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); + flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr); +} + +void +gp102_sec2_acr_bld_write_1(struct nvkm_acr *acr, u32 bld, + struct nvkm_acr_lsfw *lsfw) +{ + const struct flcn_bl_dmem_desc_v2 hdr = { + .ctx_dma = FALCON_SEC2_DMAIDX_UCODE, + .code_dma_base = lsfw->offset.img + lsfw->app_start_offset, + .non_sec_code_off = lsfw->app_resident_code_offset, + .non_sec_code_size = lsfw->app_resident_code_size, + .code_entry_point = lsfw->app_imem_entry, + .data_dma_base = lsfw->offset.img + lsfw->app_start_offset + + lsfw->app_resident_data_offset, + .data_size = lsfw->app_resident_data_size, + .argc = 1, + .argv = lsfw->falcon->func->emem_addr, + }; + + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); +} + +const struct nvkm_acr_lsf_func +gp102_sec2_acr_1 = { + .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), + .bld_write = gp102_sec2_acr_bld_write_1, + .bld_patch = gp102_sec2_acr_bld_patch_1, + .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | + BIT_ULL(NVKM_ACR_LSF_GPCCS) | + BIT_ULL(NVKM_ACR_LSF_SEC2), + .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, +}; + +int +gp102_sec2_load(struct nvkm_sec2 *sec2, int ver, + const struct nvkm_sec2_fwif *fwif) +{ + return nvkm_acr_lsfw_load_sig_image_desc_v1(&sec2->engine.subdev, + &sec2->falcon, + NVKM_ACR_LSF_SEC2, "sec2/", + ver, fwif->acr); +} + +MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin"); +MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin"); +MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/desc-1.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/image-1.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/sig-1.bin"); + +static const struct nvkm_sec2_fwif +gp102_sec2_fwif[] = { + { 1, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_1 }, + { 0, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_0 }, + { -1, gp102_sec2_nofw, &gp102_sec2 }, + {} +}; + +int +gp102_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_sec2 **psec2) +{ + return nvkm_sec2_new_(gp102_sec2_fwif, device, type, inst, 0, psec2); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c new file mode 100644 index 000000000..3e9f5c842 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c @@ -0,0 +1,43 @@ +/* + * Copyright 2019 Red Hat Inc. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ +#include "priv.h" +#include <subdev/acr.h> + +MODULE_FIRMWARE("nvidia/gp108/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp108/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp108/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/gv100/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gv100/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gv100/sec2/sig.bin"); + +static const struct nvkm_sec2_fwif +gp108_sec2_fwif[] = { + { 0, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_1 }, + {} +}; + +int +gp108_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_sec2 **psec2) +{ + return nvkm_sec2_new_(gp108_sec2_fwif, device, type, inst, 0, psec2); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h new file mode 100644 index 000000000..172d2705c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_SEC2_PRIV_H__ +#define __NVKM_SEC2_PRIV_H__ +#include <engine/sec2.h> +struct nvkm_acr_lsfw; + +struct nvkm_sec2_func { + const struct nvkm_falcon_func *flcn; + u8 unit_unload; + u8 unit_acr; + struct nvkm_intr *(*intr_vector)(struct nvkm_sec2 *, enum nvkm_intr_type *); + irqreturn_t (*intr)(struct nvkm_inth *); + int (*initmsg)(struct nvkm_sec2 *); +}; + +irqreturn_t gp102_sec2_intr(struct nvkm_inth *); +int gp102_sec2_initmsg(struct nvkm_sec2 *); + +struct nvkm_sec2_fwif { + int version; + int (*load)(struct nvkm_sec2 *, int ver, const struct nvkm_sec2_fwif *); + const struct nvkm_sec2_func *func; + const struct nvkm_acr_lsf_func *acr; +}; + +int gp102_sec2_nofw(struct nvkm_sec2 *, int, const struct nvkm_sec2_fwif *); +int gp102_sec2_load(struct nvkm_sec2 *, int, const struct nvkm_sec2_fwif *); +extern const struct nvkm_sec2_func gp102_sec2; +extern const struct nvkm_acr_lsf_func gp102_sec2_acr_1; +void gp102_sec2_acr_bld_write_1(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *); +void gp102_sec2_acr_bld_patch_1(struct nvkm_acr *, u32, s64); + +int nvkm_sec2_new_(const struct nvkm_sec2_fwif *, struct nvkm_device *, enum nvkm_subdev_type, + int, u32 addr, struct nvkm_sec2 **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c new file mode 100644 index 000000000..0afc4b2fa --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -0,0 +1,86 @@ +/* + * Copyright 2019 Red Hat Inc. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ +#include "priv.h" +#include <subdev/acr.h> + +#include <nvfw/sec2.h> + +static const struct nvkm_falcon_func +tu102_sec2_flcn = { + .disable = gm200_flcn_disable, + .enable = gm200_flcn_enable, + .reset_pmc = true, + .reset_eng = gp102_flcn_reset_eng, + .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, + .debug = 0x408, + .bind_inst = gm200_flcn_bind_inst, + .bind_stat = gm200_flcn_bind_stat, + .bind_intr = true, + .imem_pio = &gm200_flcn_imem_pio, + .dmem_pio = &gm200_flcn_dmem_pio, + .emem_addr = 0x01000000, + .emem_pio = &gp102_flcn_emem_pio, + .start = nvkm_falcon_v1_start, + .cmdq = { 0xc00, 0xc04, 8 }, + .msgq = { 0xc80, 0xc84, 8 }, +}; + +static const struct nvkm_sec2_func +tu102_sec2 = { + .flcn = &tu102_sec2_flcn, + .unit_unload = NV_SEC2_UNIT_V2_UNLOAD, + .unit_acr = NV_SEC2_UNIT_V2_ACR, + .intr = gp102_sec2_intr, + .initmsg = gp102_sec2_initmsg, +}; + +MODULE_FIRMWARE("nvidia/tu102/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/tu102/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/tu102/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/tu104/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/tu104/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/tu104/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/tu106/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/tu106/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/tu106/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/tu116/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/tu116/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/tu116/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/tu117/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/tu117/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/tu117/sec2/sig.bin"); + +static const struct nvkm_sec2_fwif +tu102_sec2_fwif[] = { + { 0, gp102_sec2_load, &tu102_sec2, &gp102_sec2_acr_1 }, + { -1, gp102_sec2_nofw, &tu102_sec2 } +}; + +int +tu102_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, + struct nvkm_sec2 **psec2) +{ + /* TOP info wasn't updated on Turing to reflect the PRI + * address change for some reason. We override it here. + */ + return nvkm_sec2_new_(tu102_sec2_fwif, device, type, inst, 0x840000, psec2); +} |