1 /*
2 * Copyright 2022 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
24 #include <subdev/fb.h>
25 #include <engine/sec2.h>
26
27 #include <rm/r535/nvrm/gsp.h>
28
29 #include <nvfw/flcn.h>
30 #include <nvfw/fw.h>
31 #include <nvfw/hs.h>
32
33 static int
tu102_gsp_booter_unload(struct nvkm_gsp * gsp,u32 mbox0,u32 mbox1)34 tu102_gsp_booter_unload(struct nvkm_gsp *gsp, u32 mbox0, u32 mbox1)
35 {
36 struct nvkm_subdev *subdev = &gsp->subdev;
37 struct nvkm_device *device = subdev->device;
38 u32 wpr2_hi;
39 int ret;
40
41 wpr2_hi = nvkm_rd32(device, 0x1fa828);
42 if (!wpr2_hi) {
43 nvkm_debug(subdev, "WPR2 not set - skipping booter unload\n");
44 return 0;
45 }
46
47 ret = nvkm_falcon_fw_boot(&gsp->booter.unload, &gsp->subdev, true, &mbox0, &mbox1, 0, 0);
48 if (WARN_ON(ret))
49 return ret;
50
51 wpr2_hi = nvkm_rd32(device, 0x1fa828);
52 if (WARN_ON(wpr2_hi))
53 return -EIO;
54
55 return 0;
56 }
57
58 static int
tu102_gsp_booter_load(struct nvkm_gsp * gsp,u32 mbox0,u32 mbox1)59 tu102_gsp_booter_load(struct nvkm_gsp *gsp, u32 mbox0, u32 mbox1)
60 {
61 return nvkm_falcon_fw_boot(&gsp->booter.load, &gsp->subdev, true, &mbox0, &mbox1, 0, 0);
62 }
63
64 int
tu102_gsp_booter_ctor(struct nvkm_gsp * gsp,const char * name,const struct firmware * blob,struct nvkm_falcon * falcon,struct nvkm_falcon_fw * fw)65 tu102_gsp_booter_ctor(struct nvkm_gsp *gsp, const char *name, const struct firmware *blob,
66 struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw)
67 {
68 struct nvkm_subdev *subdev = &gsp->subdev;
69 const struct nvkm_falcon_fw_func *func = &gm200_flcn_fw;
70 const struct nvfw_bin_hdr *hdr;
71 const struct nvfw_hs_header_v2 *hshdr;
72 const struct nvfw_hs_load_header_v2 *lhdr;
73 u32 loc, sig, cnt;
74 int ret;
75
76 hdr = nvfw_bin_hdr(subdev, blob->data);
77 hshdr = nvfw_hs_header_v2(subdev, blob->data + hdr->header_offset);
78 loc = *(u32 *)(blob->data + hshdr->patch_loc);
79 sig = *(u32 *)(blob->data + hshdr->patch_sig);
80 cnt = *(u32 *)(blob->data + hshdr->num_sig);
81
82 ret = nvkm_falcon_fw_ctor(func, name, subdev->device, true,
83 blob->data + hdr->data_offset, hdr->data_size, falcon, fw);
84 if (ret)
85 goto done;
86
87 ret = nvkm_falcon_fw_sign(fw, loc, hshdr->sig_prod_size / cnt, blob->data,
88 cnt, hshdr->sig_prod_offset + sig, 0, 0);
89 if (ret)
90 goto done;
91
92 lhdr = nvfw_hs_load_header_v2(subdev, blob->data + hshdr->header_offset);
93
94 fw->nmem_base_img = 0;
95 fw->nmem_base = lhdr->os_code_offset;
96 fw->nmem_size = lhdr->os_code_size;
97 fw->imem_base_img = fw->nmem_size;
98 fw->imem_base = lhdr->app[0].offset;
99 fw->imem_size = lhdr->app[0].size;
100 fw->dmem_base_img = lhdr->os_data_offset;
101 fw->dmem_base = 0;
102 fw->dmem_size = lhdr->os_data_size;
103 fw->dmem_sign = loc - fw->dmem_base_img;
104 fw->boot_addr = lhdr->os_code_offset;
105
106 done:
107 if (ret)
108 nvkm_falcon_fw_dtor(fw);
109
110 return ret;
111 }
112
113 static int
tu102_gsp_fwsec_load_bld(struct nvkm_falcon_fw * fw)114 tu102_gsp_fwsec_load_bld(struct nvkm_falcon_fw *fw)
115 {
116 struct flcn_bl_dmem_desc_v2 desc = {
117 .ctx_dma = FALCON_DMAIDX_PHYS_SYS_NCOH,
118 .code_dma_base = fw->fw.phys,
119 .non_sec_code_off = fw->nmem_base,
120 .non_sec_code_size = fw->nmem_size,
121 .sec_code_off = fw->imem_base,
122 .sec_code_size = fw->imem_size,
123 .code_entry_point = 0,
124 .data_dma_base = fw->fw.phys + fw->dmem_base_img,
125 .data_size = fw->dmem_size,
126 .argc = 0,
127 .argv = 0,
128 };
129
130 flcn_bl_dmem_desc_v2_dump(fw->falcon->user, &desc);
131
132 nvkm_falcon_mask(fw->falcon, 0x600 + desc.ctx_dma * 4, 0x00000007, 0x00000005);
133
134 return nvkm_falcon_pio_wr(fw->falcon, (u8 *)&desc, 0, 0, DMEM, 0, sizeof(desc), 0, 0);
135 }
136
137 const struct nvkm_falcon_fw_func
138 tu102_gsp_fwsec = {
139 .reset = gm200_flcn_fw_reset,
140 .load = gm200_flcn_fw_load,
141 .load_bld = tu102_gsp_fwsec_load_bld,
142 .boot = gm200_flcn_fw_boot,
143 };
144
145 int
tu102_gsp_reset(struct nvkm_gsp * gsp)146 tu102_gsp_reset(struct nvkm_gsp *gsp)
147 {
148 return gsp->falcon.func->reset_eng(&gsp->falcon);
149 }
150
151 int
tu102_gsp_fini(struct nvkm_gsp * gsp,bool suspend)152 tu102_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
153 {
154 u32 mbox0 = 0xff, mbox1 = 0xff;
155 int ret;
156
157 ret = r535_gsp_fini(gsp, suspend);
158 if (ret && suspend)
159 return ret;
160
161 nvkm_falcon_reset(&gsp->falcon);
162
163 ret = nvkm_gsp_fwsec_sb(gsp);
164 WARN_ON(ret);
165
166 if (suspend) {
167 mbox0 = lower_32_bits(gsp->sr.meta.addr);
168 mbox1 = upper_32_bits(gsp->sr.meta.addr);
169 }
170
171 ret = tu102_gsp_booter_unload(gsp, mbox0, mbox1);
172 WARN_ON(ret);
173 return 0;
174 }
175
176 int
tu102_gsp_init(struct nvkm_gsp * gsp)177 tu102_gsp_init(struct nvkm_gsp *gsp)
178 {
179 u32 mbox0, mbox1;
180 int ret;
181
182 if (!gsp->sr.meta.data) {
183 mbox0 = lower_32_bits(gsp->wpr_meta.addr);
184 mbox1 = upper_32_bits(gsp->wpr_meta.addr);
185 } else {
186 gsp->rm->api->gsp->set_rmargs(gsp, true);
187
188 mbox0 = lower_32_bits(gsp->sr.meta.addr);
189 mbox1 = upper_32_bits(gsp->sr.meta.addr);
190 }
191
192 /* Execute booter to handle (eventually...) booting GSP-RM. */
193 ret = tu102_gsp_booter_load(gsp, mbox0, mbox1);
194 if (WARN_ON(ret))
195 return ret;
196
197 return r535_gsp_init(gsp);
198 }
199
200 static int
tu102_gsp_wpr_meta_init(struct nvkm_gsp * gsp)201 tu102_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
202 {
203 GspFwWprMeta *meta;
204 int ret;
205
206 ret = nvkm_gsp_mem_ctor(gsp, sizeof(*meta), &gsp->wpr_meta);
207 if (ret)
208 return ret;
209
210 meta = gsp->wpr_meta.data;
211
212 meta->magic = GSP_FW_WPR_META_MAGIC;
213 meta->revision = GSP_FW_WPR_META_REVISION;
214
215 meta->sysmemAddrOfRadix3Elf = gsp->radix3.lvl0.addr;
216 meta->sizeOfRadix3Elf = gsp->fb.wpr2.elf.size;
217
218 meta->sysmemAddrOfBootloader = gsp->boot.fw.addr;
219 meta->sizeOfBootloader = gsp->boot.fw.size;
220 meta->bootloaderCodeOffset = gsp->boot.code_offset;
221 meta->bootloaderDataOffset = gsp->boot.data_offset;
222 meta->bootloaderManifestOffset = gsp->boot.manifest_offset;
223
224 meta->sysmemAddrOfSignature = gsp->sig.addr;
225 meta->sizeOfSignature = gsp->sig.size;
226
227 meta->gspFwRsvdStart = gsp->fb.heap.addr;
228 meta->nonWprHeapOffset = gsp->fb.heap.addr;
229 meta->nonWprHeapSize = gsp->fb.heap.size;
230 meta->gspFwWprStart = gsp->fb.wpr2.addr;
231 meta->gspFwHeapOffset = gsp->fb.wpr2.heap.addr;
232 meta->gspFwHeapSize = gsp->fb.wpr2.heap.size;
233 meta->gspFwOffset = gsp->fb.wpr2.elf.addr;
234 meta->bootBinOffset = gsp->fb.wpr2.boot.addr;
235 meta->frtsOffset = gsp->fb.wpr2.frts.addr;
236 meta->frtsSize = gsp->fb.wpr2.frts.size;
237 meta->gspFwWprEnd = ALIGN_DOWN(gsp->fb.bios.vga_workspace.addr, 0x20000);
238 meta->fbSize = gsp->fb.size;
239 meta->vgaWorkspaceOffset = gsp->fb.bios.vga_workspace.addr;
240 meta->vgaWorkspaceSize = gsp->fb.bios.vga_workspace.size;
241 meta->bootCount = 0;
242 meta->partitionRpcAddr = 0;
243 meta->partitionRpcRequestOffset = 0;
244 meta->partitionRpcReplyOffset = 0;
245 meta->verified = 0;
246 return 0;
247 }
248
249 u64
tu102_gsp_wpr_heap_size(struct nvkm_gsp * gsp)250 tu102_gsp_wpr_heap_size(struct nvkm_gsp *gsp)
251 {
252 u32 fb_size_gb = DIV_ROUND_UP_ULL(gsp->fb.size, 1 << 30);
253 u64 heap_size;
254
255 heap_size = gsp->rm->wpr->os_carveout_size +
256 gsp->rm->wpr->base_size +
257 ALIGN(GSP_FW_HEAP_PARAM_SIZE_PER_GB_FB * fb_size_gb, 1 << 20) +
258 ALIGN(GSP_FW_HEAP_PARAM_CLIENT_ALLOC_SIZE, 1 << 20);
259
260 return max(heap_size, gsp->rm->wpr->heap_size_min);
261 }
262
263 static u64
tu102_gsp_vga_workspace_addr(struct nvkm_gsp * gsp,u64 fb_size)264 tu102_gsp_vga_workspace_addr(struct nvkm_gsp *gsp, u64 fb_size)
265 {
266 struct nvkm_device *device = gsp->subdev.device;
267 const u64 base = fb_size - 0x100000;
268 u64 addr = 0;
269
270 if (device->disp)
271 addr = nvkm_rd32(gsp->subdev.device, 0x625f04);
272 if (!(addr & 0x00000008))
273 return base;
274
275 addr = (addr & 0xffffff00) << 8;
276 if (addr < base)
277 return fb_size - 0x20000;
278
279 return addr;
280 }
281
282 int
tu102_gsp_oneinit(struct nvkm_gsp * gsp)283 tu102_gsp_oneinit(struct nvkm_gsp *gsp)
284 {
285 struct nvkm_device *device = gsp->subdev.device;
286 int ret;
287
288 gsp->fb.size = nvkm_fb_vidmem_size(device);
289
290 gsp->fb.bios.vga_workspace.addr = tu102_gsp_vga_workspace_addr(gsp, gsp->fb.size);
291 gsp->fb.bios.vga_workspace.size = gsp->fb.size - gsp->fb.bios.vga_workspace.addr;
292 gsp->fb.bios.addr = gsp->fb.bios.vga_workspace.addr;
293 gsp->fb.bios.size = gsp->fb.bios.vga_workspace.size;
294
295 ret = gsp->func->booter.ctor(gsp, "booter-load", gsp->fws.booter.load,
296 &device->sec2->falcon, &gsp->booter.load);
297 if (ret)
298 return ret;
299
300 ret = gsp->func->booter.ctor(gsp, "booter-unload", gsp->fws.booter.unload,
301 &device->sec2->falcon, &gsp->booter.unload);
302 if (ret)
303 return ret;
304
305 ret = r535_gsp_oneinit(gsp);
306 if (ret)
307 return ret;
308
309 /* Calculate FB layout. */
310 gsp->fb.wpr2.frts.size = 0x100000;
311 gsp->fb.wpr2.frts.addr = ALIGN_DOWN(gsp->fb.bios.addr, 0x20000) - gsp->fb.wpr2.frts.size;
312
313 gsp->fb.wpr2.boot.size = gsp->boot.fw.size;
314 gsp->fb.wpr2.boot.addr = ALIGN_DOWN(gsp->fb.wpr2.frts.addr - gsp->fb.wpr2.boot.size, 0x1000);
315
316 gsp->fb.wpr2.elf.size = gsp->fw.len;
317 gsp->fb.wpr2.elf.addr = ALIGN_DOWN(gsp->fb.wpr2.boot.addr - gsp->fb.wpr2.elf.size, 0x10000);
318
319 gsp->fb.wpr2.heap.size = tu102_gsp_wpr_heap_size(gsp);
320
321 gsp->fb.wpr2.heap.addr = ALIGN_DOWN(gsp->fb.wpr2.elf.addr - gsp->fb.wpr2.heap.size, 0x100000);
322 gsp->fb.wpr2.heap.size = ALIGN_DOWN(gsp->fb.wpr2.elf.addr - gsp->fb.wpr2.heap.addr, 0x100000);
323
324 gsp->fb.wpr2.addr = ALIGN_DOWN(gsp->fb.wpr2.heap.addr - sizeof(GspFwWprMeta), 0x100000);
325 gsp->fb.wpr2.size = gsp->fb.wpr2.frts.addr + gsp->fb.wpr2.frts.size - gsp->fb.wpr2.addr;
326
327 gsp->fb.heap.size = 0x100000;
328 gsp->fb.heap.addr = gsp->fb.wpr2.addr - gsp->fb.heap.size;
329
330 ret = tu102_gsp_wpr_meta_init(gsp);
331 if (ret)
332 return ret;
333
334 ret = nvkm_gsp_fwsec_frts(gsp);
335 if (WARN_ON(ret))
336 return ret;
337
338 /* Reset GSP into RISC-V mode. */
339 ret = gsp->func->reset(gsp);
340 if (ret)
341 return ret;
342
343 nvkm_falcon_wr32(&gsp->falcon, 0x040, lower_32_bits(gsp->libos.addr));
344 nvkm_falcon_wr32(&gsp->falcon, 0x044, upper_32_bits(gsp->libos.addr));
345 return 0;
346 }
347
348 const struct nvkm_falcon_func
349 tu102_gsp_flcn = {
350 .disable = gm200_flcn_disable,
351 .enable = gm200_flcn_enable,
352 .addr2 = 0x1000,
353 .riscv_irqmask = 0x2b4,
354 .reset_eng = gp102_flcn_reset_eng,
355 .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
356 .bind_inst = gm200_flcn_bind_inst,
357 .bind_stat = gm200_flcn_bind_stat,
358 .bind_intr = true,
359 .imem_pio = &gm200_flcn_imem_pio,
360 .dmem_pio = &gm200_flcn_dmem_pio,
361 .riscv_active = tu102_flcn_riscv_active,
362 };
363
364 static const struct nvkm_gsp_func
365 tu102_gsp = {
366 .flcn = &tu102_gsp_flcn,
367 .fwsec = &tu102_gsp_fwsec,
368
369 .sig_section = ".fwsignature_tu10x",
370
371 .booter.ctor = tu102_gsp_booter_ctor,
372
373 .dtor = r535_gsp_dtor,
374 .oneinit = tu102_gsp_oneinit,
375 .init = tu102_gsp_init,
376 .fini = tu102_gsp_fini,
377 .reset = tu102_gsp_reset,
378
379 .rm.gpu = &tu1xx_gpu,
380 };
381
382 int
tu102_gsp_load_rm(struct nvkm_gsp * gsp,const struct nvkm_gsp_fwif * fwif)383 tu102_gsp_load_rm(struct nvkm_gsp *gsp, const struct nvkm_gsp_fwif *fwif)
384 {
385 struct nvkm_subdev *subdev = &gsp->subdev;
386 bool enable_gsp = fwif->enable;
387 int ret;
388
389 #if IS_ENABLED(CONFIG_DRM_NOUVEAU_GSP_DEFAULT)
390 enable_gsp = true;
391 #endif
392 if (!nvkm_boolopt(subdev->device->cfgopt, "NvGspRm", enable_gsp))
393 return -EINVAL;
394
395 ret = nvkm_gsp_load_fw(gsp, "gsp", fwif->ver, &gsp->fws.rm);
396 if (ret)
397 return ret;
398
399 ret = nvkm_gsp_load_fw(gsp, "bootloader", fwif->ver, &gsp->fws.bl);
400 if (ret)
401 return ret;
402
403 return 0;
404 }
405
406 int
tu102_gsp_load(struct nvkm_gsp * gsp,int ver,const struct nvkm_gsp_fwif * fwif)407 tu102_gsp_load(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif)
408 {
409 int ret;
410
411 ret = tu102_gsp_load_rm(gsp, fwif);
412 if (ret)
413 goto done;
414
415 ret = nvkm_gsp_load_fw(gsp, "booter_load", fwif->ver, &gsp->fws.booter.load);
416 if (ret)
417 goto done;
418
419 ret = nvkm_gsp_load_fw(gsp, "booter_unload", fwif->ver, &gsp->fws.booter.unload);
420
421 done:
422 if (ret)
423 nvkm_gsp_dtor_fws(gsp);
424
425 return ret;
426 }
427
428 static struct nvkm_gsp_fwif
429 tu102_gsps[] = {
430 { 1, tu102_gsp_load, &tu102_gsp, &r570_rm_tu102, "570.144" },
431 { 0, tu102_gsp_load, &tu102_gsp, &r535_rm_tu102, "535.113.01" },
432 { -1, gv100_gsp_nofw, &gv100_gsp },
433 {}
434 };
435
436 int
tu102_gsp_new(struct nvkm_device * device,enum nvkm_subdev_type type,int inst,struct nvkm_gsp ** pgsp)437 tu102_gsp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
438 struct nvkm_gsp **pgsp)
439 {
440 return nvkm_gsp_new_(tu102_gsps, device, type, inst, pgsp);
441 }
442
443 NVKM_GSP_FIRMWARE_BOOTER(tu102, 535.113.01);
444 NVKM_GSP_FIRMWARE_BOOTER(tu104, 535.113.01);
445 NVKM_GSP_FIRMWARE_BOOTER(tu106, 535.113.01);
446
447 NVKM_GSP_FIRMWARE_BOOTER(tu102, 570.144);
448 NVKM_GSP_FIRMWARE_BOOTER(tu104, 570.144);
449 NVKM_GSP_FIRMWARE_BOOTER(tu106, 570.144);
450