1 /* 2 * Copyright 2021 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 #include "priv.h" 23 #include <subdev/acr.h> 24 #include <subdev/vfn.h> 25 26 #include <nvfw/flcn.h> 27 #include <nvfw/sec2.h> 28 29 static int 30 ga102_sec2_initmsg(struct nvkm_sec2 *sec2) 31 { 32 struct nv_sec2_init_msg_v1 msg; 33 int ret, i; 34 35 ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg)); 36 if (ret) 37 return ret; 38 39 if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT || 40 msg.msg_type != NV_SEC2_INIT_MSG_INIT) 41 return -EINVAL; 42 43 for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) { 44 if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) { 45 nvkm_falcon_msgq_init(sec2->msgq, msg.queue_info[i].index, 46 msg.queue_info[i].offset, 47 msg.queue_info[i].size); 48 } else { 49 nvkm_falcon_cmdq_init(sec2->cmdq, msg.queue_info[i].index, 50 msg.queue_info[i].offset, 51 msg.queue_info[i].size); 52 } 53 } 54 55 return 0; 56 } 57 58 static struct nvkm_intr * 59 ga102_sec2_intr_vector(struct nvkm_sec2 *sec2, enum nvkm_intr_type *pvector) 60 { 61 struct nvkm_device *device = sec2->engine.subdev.device; 62 struct nvkm_falcon *falcon = &sec2->falcon; 63 int ret; 64 65 ret = ga102_flcn_select(falcon); 66 if (ret) 67 return ERR_PTR(ret); 68 69 *pvector = nvkm_rd32(device, 0x8403e0) & 0x000000ff; 70 return &device->vfn->intr; 71 } 72 73 static int 74 ga102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nvfw_falcon_msg *hdr) 75 { 76 struct nv_sec2_acr_bootstrap_falcon_msg_v1 *msg = 77 container_of(hdr, typeof(*msg), msg.hdr); 78 struct nvkm_subdev *subdev = priv; 79 const char *name = nvkm_acr_lsf_id(msg->falcon_id); 80 81 if (msg->error_code) { 82 nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for falcon %d [%s]: %08x %08x\n", 83 msg->falcon_id, name, msg->error_code, msg->unkn08); 84 return -EINVAL; 85 } 86 87 nvkm_debug(subdev, "%s booted\n", name); 88 return 0; 89 } 90 91 static int 92 ga102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, enum nvkm_acr_lsf_id id) 93 { 94 struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon); 95 struct nv_sec2_acr_bootstrap_falcon_cmd_v1 cmd = { 96 .cmd.hdr.unit_id = sec2->func->unit_acr, 97 .cmd.hdr.size = sizeof(cmd), 98 .cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON, 99 .flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES, 100 .falcon_id = id, 101 }; 102 103 return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr, 104 ga102_sec2_acr_bootstrap_falcon_callback, 105 &sec2->engine.subdev, 106 msecs_to_jiffies(1000)); 107 } 108 109 static const struct nvkm_acr_lsf_func 110 ga102_sec2_acr_0 = { 111 .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), 112 .bld_write = gp102_sec2_acr_bld_write_1, 113 .bld_patch = gp102_sec2_acr_bld_patch_1, 114 .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | 115 BIT_ULL(NVKM_ACR_LSF_GPCCS) | 116 BIT_ULL(NVKM_ACR_LSF_SEC2), 117 .bootstrap_falcon = ga102_sec2_acr_bootstrap_falcon, 118 }; 119 120 static const struct nvkm_falcon_func 121 ga102_sec2_flcn = { 122 .disable = gm200_flcn_disable, 123 .enable = gm200_flcn_enable, 124 .select = ga102_flcn_select, 125 .addr2 = 0x1000, 126 .reset_pmc = true, 127 .reset_eng = gp102_flcn_reset_eng, 128 .reset_prep = ga102_flcn_reset_prep, 129 .reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing, 130 .imem_dma = &ga102_flcn_dma, 131 .dmem_pio = &gm200_flcn_dmem_pio, 132 .dmem_dma = &ga102_flcn_dma, 133 .emem_addr = 0x01000000, 134 .emem_pio = &gp102_flcn_emem_pio, 135 .start = nvkm_falcon_v1_start, 136 .cmdq = { 0xc00, 0xc04, 8 }, 137 .msgq = { 0xc80, 0xc84, 8 }, 138 }; 139 140 static const struct nvkm_sec2_func 141 ga102_sec2 = { 142 .flcn = &ga102_sec2_flcn, 143 .intr_vector = ga102_sec2_intr_vector, 144 .intr = gp102_sec2_intr, 145 .initmsg = ga102_sec2_initmsg, 146 .unit_acr = NV_SEC2_UNIT_V2_ACR, 147 .unit_unload = NV_SEC2_UNIT_V2_UNLOAD, 148 }; 149 150 MODULE_FIRMWARE("nvidia/ga102/sec2/desc.bin"); 151 MODULE_FIRMWARE("nvidia/ga102/sec2/image.bin"); 152 MODULE_FIRMWARE("nvidia/ga102/sec2/sig.bin"); 153 MODULE_FIRMWARE("nvidia/ga102/sec2/hs_bl_sig.bin"); 154 155 MODULE_FIRMWARE("nvidia/ga103/sec2/desc.bin"); 156 MODULE_FIRMWARE("nvidia/ga103/sec2/image.bin"); 157 MODULE_FIRMWARE("nvidia/ga103/sec2/sig.bin"); 158 MODULE_FIRMWARE("nvidia/ga103/sec2/hs_bl_sig.bin"); 159 160 MODULE_FIRMWARE("nvidia/ga104/sec2/desc.bin"); 161 MODULE_FIRMWARE("nvidia/ga104/sec2/image.bin"); 162 MODULE_FIRMWARE("nvidia/ga104/sec2/sig.bin"); 163 MODULE_FIRMWARE("nvidia/ga104/sec2/hs_bl_sig.bin"); 164 165 MODULE_FIRMWARE("nvidia/ga106/sec2/desc.bin"); 166 MODULE_FIRMWARE("nvidia/ga106/sec2/image.bin"); 167 MODULE_FIRMWARE("nvidia/ga106/sec2/sig.bin"); 168 MODULE_FIRMWARE("nvidia/ga106/sec2/hs_bl_sig.bin"); 169 170 MODULE_FIRMWARE("nvidia/ga107/sec2/desc.bin"); 171 MODULE_FIRMWARE("nvidia/ga107/sec2/image.bin"); 172 MODULE_FIRMWARE("nvidia/ga107/sec2/sig.bin"); 173 MODULE_FIRMWARE("nvidia/ga107/sec2/hs_bl_sig.bin"); 174 175 static int 176 ga102_sec2_load(struct nvkm_sec2 *sec2, int ver, 177 const struct nvkm_sec2_fwif *fwif) 178 { 179 return nvkm_acr_lsfw_load_sig_image_desc_v2(&sec2->engine.subdev, &sec2->falcon, 180 NVKM_ACR_LSF_SEC2, "sec2/", ver, fwif->acr); 181 } 182 183 static const struct nvkm_sec2_fwif 184 ga102_sec2_fwif[] = { 185 { 0, ga102_sec2_load, &ga102_sec2, &ga102_sec2_acr_0 }, 186 { -1, gp102_sec2_nofw, &ga102_sec2 } 187 }; 188 189 int 190 ga102_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, 191 struct nvkm_sec2 **psec2) 192 { 193 /* TOP info wasn't updated on Turing to reflect the PRI 194 * address change for some reason. We override it here. 195 */ 196 return nvkm_sec2_new_(ga102_sec2_fwif, device, type, inst, 0x840000, psec2); 197 } 198