1 /* 2 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 */ 22 #include "priv.h" 23 24 #include <core/memory.h> 25 #include <subdev/acr.h> 26 #include <subdev/timer.h> 27 28 #include <nvfw/flcn.h> 29 #include <nvfw/sec2.h> 30 31 int 32 gp102_sec2_nofw(struct nvkm_sec2 *sec2, int ver, 33 const struct nvkm_sec2_fwif *fwif) 34 { 35 nvkm_warn(&sec2->engine.subdev, "firmware unavailable\n"); 36 return 0; 37 } 38 39 static int 40 gp102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nvfw_falcon_msg *hdr) 41 { 42 struct nv_sec2_acr_bootstrap_falcon_msg *msg = 43 container_of(hdr, typeof(*msg), msg.hdr); 44 struct nvkm_subdev *subdev = priv; 45 const char *name = nvkm_acr_lsf_id(msg->falcon_id); 46 47 if (msg->error_code) { 48 nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for " 49 "falcon %d [%s]: %08x\n", 50 msg->falcon_id, name, msg->error_code); 51 return -EINVAL; 52 } 53 54 nvkm_debug(subdev, "%s booted\n", name); 55 return 0; 56 } 57 58 static int 59 gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, 60 enum nvkm_acr_lsf_id id) 61 { 62 struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon); 63 struct nv_sec2_acr_bootstrap_falcon_cmd cmd = { 64 .cmd.hdr.unit_id = sec2->func->unit_acr, 65 .cmd.hdr.size = sizeof(cmd), 66 .cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON, 67 .flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES, 68 .falcon_id = id, 69 }; 70 71 return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr, 72 gp102_sec2_acr_bootstrap_falcon_callback, 73 &sec2->engine.subdev, 74 msecs_to_jiffies(1000)); 75 } 76 77 static void 78 gp102_sec2_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) 79 { 80 struct loader_config_v1 hdr; 81 nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); 82 hdr.code_dma_base = hdr.code_dma_base + adjust; 83 hdr.data_dma_base = hdr.data_dma_base + adjust; 84 hdr.overlay_dma_base = hdr.overlay_dma_base + adjust; 85 nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); 86 loader_config_v1_dump(&acr->subdev, &hdr); 87 } 88 89 static void 90 gp102_sec2_acr_bld_write(struct nvkm_acr *acr, u32 bld, 91 struct nvkm_acr_lsfw *lsfw) 92 { 93 const struct loader_config_v1 hdr = { 94 .dma_idx = FALCON_SEC2_DMAIDX_UCODE, 95 .code_dma_base = lsfw->offset.img + lsfw->app_start_offset, 96 .code_size_total = lsfw->app_size, 97 .code_size_to_load = lsfw->app_resident_code_size, 98 .code_entry_point = lsfw->app_imem_entry, 99 .data_dma_base = lsfw->offset.img + lsfw->app_start_offset + 100 lsfw->app_resident_data_offset, 101 .data_size = lsfw->app_resident_data_size, 102 .overlay_dma_base = lsfw->offset.img + lsfw->app_start_offset, 103 .argc = 1, 104 .argv = lsfw->falcon->func->emem_addr, 105 }; 106 107 nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); 108 } 109 110 static const struct nvkm_acr_lsf_func 111 gp102_sec2_acr_0 = { 112 .bld_size = sizeof(struct loader_config_v1), 113 .bld_write = gp102_sec2_acr_bld_write, 114 .bld_patch = gp102_sec2_acr_bld_patch, 115 .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | 116 BIT_ULL(NVKM_ACR_LSF_GPCCS) | 117 BIT_ULL(NVKM_ACR_LSF_SEC2), 118 .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, 119 }; 120 121 int 122 gp102_sec2_initmsg(struct nvkm_sec2 *sec2) 123 { 124 struct nv_sec2_init_msg msg; 125 int ret, i; 126 127 ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg)); 128 if (ret) 129 return ret; 130 131 if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT || 132 msg.msg_type != NV_SEC2_INIT_MSG_INIT) 133 return -EINVAL; 134 135 for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) { 136 if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) { 137 nvkm_falcon_msgq_init(sec2->msgq, 138 msg.queue_info[i].index, 139 msg.queue_info[i].offset, 140 msg.queue_info[i].size); 141 } else { 142 nvkm_falcon_cmdq_init(sec2->cmdq, 143 msg.queue_info[i].index, 144 msg.queue_info[i].offset, 145 msg.queue_info[i].size); 146 } 147 } 148 149 return 0; 150 } 151 152 irqreturn_t 153 gp102_sec2_intr(struct nvkm_inth *inth) 154 { 155 struct nvkm_sec2 *sec2 = container_of(inth, typeof(*sec2), engine.subdev.inth); 156 struct nvkm_subdev *subdev = &sec2->engine.subdev; 157 struct nvkm_falcon *falcon = &sec2->falcon; 158 u32 disp = nvkm_falcon_rd32(falcon, 0x01c); 159 u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16); 160 161 if (intr & 0x00000040) { 162 if (unlikely(atomic_read(&sec2->initmsg) == 0)) { 163 int ret = sec2->func->initmsg(sec2); 164 165 if (ret) 166 nvkm_error(subdev, "error parsing init message: %d\n", ret); 167 168 atomic_set(&sec2->initmsg, ret ?: 1); 169 } 170 171 if (atomic_read(&sec2->initmsg) > 0) { 172 if (!nvkm_falcon_msgq_empty(sec2->msgq)) 173 nvkm_falcon_msgq_recv(sec2->msgq); 174 } 175 176 nvkm_falcon_wr32(falcon, 0x004, 0x00000040); 177 intr &= ~0x00000040; 178 } 179 180 if (intr & 0x00000010) { 181 nvkm_falcon_wr32(falcon, 0x004, 0x00000010); 182 intr &= ~0x00000010; 183 } 184 185 if (intr) { 186 nvkm_error(subdev, "unhandled intr %08x\n", intr); 187 nvkm_falcon_wr32(falcon, 0x004, intr); 188 } 189 190 return IRQ_HANDLED; 191 } 192 193 static const struct nvkm_falcon_func 194 gp102_sec2_flcn = { 195 .disable = gm200_flcn_disable, 196 .enable = gm200_flcn_enable, 197 .reset_pmc = true, 198 .reset_eng = gp102_flcn_reset_eng, 199 .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing, 200 .debug = 0x408, 201 .bind_inst = gm200_flcn_bind_inst, 202 .bind_stat = gm200_flcn_bind_stat, 203 .bind_intr = true, 204 .imem_pio = &gm200_flcn_imem_pio, 205 .dmem_pio = &gm200_flcn_dmem_pio, 206 .emem_addr = 0x01000000, 207 .emem_pio = &gp102_flcn_emem_pio, 208 .start = nvkm_falcon_v1_start, 209 .cmdq = { 0xa00, 0xa04, 8 }, 210 .msgq = { 0xa30, 0xa34, 8 }, 211 }; 212 213 const struct nvkm_sec2_func 214 gp102_sec2 = { 215 .flcn = &gp102_sec2_flcn, 216 .unit_unload = NV_SEC2_UNIT_UNLOAD, 217 .unit_acr = NV_SEC2_UNIT_ACR, 218 .intr = gp102_sec2_intr, 219 .initmsg = gp102_sec2_initmsg, 220 }; 221 222 MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin"); 223 MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin"); 224 MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin"); 225 MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin"); 226 MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin"); 227 MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin"); 228 MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin"); 229 MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin"); 230 MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin"); 231 MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin"); 232 MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin"); 233 MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin"); 234 235 static void 236 gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust) 237 { 238 struct flcn_bl_dmem_desc_v2 hdr; 239 nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); 240 hdr.code_dma_base = hdr.code_dma_base + adjust; 241 hdr.data_dma_base = hdr.data_dma_base + adjust; 242 nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); 243 flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr); 244 } 245 246 static void 247 gp102_sec2_acr_bld_write_1(struct nvkm_acr *acr, u32 bld, 248 struct nvkm_acr_lsfw *lsfw) 249 { 250 const struct flcn_bl_dmem_desc_v2 hdr = { 251 .ctx_dma = FALCON_SEC2_DMAIDX_UCODE, 252 .code_dma_base = lsfw->offset.img + lsfw->app_start_offset, 253 .non_sec_code_off = lsfw->app_resident_code_offset, 254 .non_sec_code_size = lsfw->app_resident_code_size, 255 .code_entry_point = lsfw->app_imem_entry, 256 .data_dma_base = lsfw->offset.img + lsfw->app_start_offset + 257 lsfw->app_resident_data_offset, 258 .data_size = lsfw->app_resident_data_size, 259 .argc = 1, 260 .argv = lsfw->falcon->func->emem_addr, 261 }; 262 263 nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); 264 } 265 266 const struct nvkm_acr_lsf_func 267 gp102_sec2_acr_1 = { 268 .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), 269 .bld_write = gp102_sec2_acr_bld_write_1, 270 .bld_patch = gp102_sec2_acr_bld_patch_1, 271 .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | 272 BIT_ULL(NVKM_ACR_LSF_GPCCS) | 273 BIT_ULL(NVKM_ACR_LSF_SEC2), 274 .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, 275 }; 276 277 int 278 gp102_sec2_load(struct nvkm_sec2 *sec2, int ver, 279 const struct nvkm_sec2_fwif *fwif) 280 { 281 return nvkm_acr_lsfw_load_sig_image_desc_v1(&sec2->engine.subdev, 282 &sec2->falcon, 283 NVKM_ACR_LSF_SEC2, "sec2/", 284 ver, fwif->acr); 285 } 286 287 MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin"); 288 MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin"); 289 MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin"); 290 MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin"); 291 MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin"); 292 MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin"); 293 MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin"); 294 MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin"); 295 MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin"); 296 MODULE_FIRMWARE("nvidia/gp107/sec2/desc-1.bin"); 297 MODULE_FIRMWARE("nvidia/gp107/sec2/image-1.bin"); 298 MODULE_FIRMWARE("nvidia/gp107/sec2/sig-1.bin"); 299 300 static const struct nvkm_sec2_fwif 301 gp102_sec2_fwif[] = { 302 { 1, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_1 }, 303 { 0, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_0 }, 304 { -1, gp102_sec2_nofw, &gp102_sec2 }, 305 {} 306 }; 307 308 int 309 gp102_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, 310 struct nvkm_sec2 **psec2) 311 { 312 return nvkm_sec2_new_(gp102_sec2_fwif, device, type, inst, 0, psec2); 313 } 314