1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
31int
32gp102_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
39static int
40gp102_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
58static int
59gp102_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
77static int
78gp102_sec2_acr_boot(struct nvkm_falcon *falcon)
79{
80 struct nv_sec2_args args = {};
81 nvkm_falcon_load_dmem(falcon, &args,
82 falcon->func->emem_addr, sizeof(args), 0);
83 nvkm_falcon_start(falcon);
84 return 0;
85}
86
87static void
88gp102_sec2_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
89{
90 struct loader_config_v1 hdr;
91 nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr));
92 hdr.code_dma_base = hdr.code_dma_base + adjust;
93 hdr.data_dma_base = hdr.data_dma_base + adjust;
94 hdr.overlay_dma_base = hdr.overlay_dma_base + adjust;
95 nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
96 loader_config_v1_dump(&acr->subdev, &hdr);
97}
98
99static void
100gp102_sec2_acr_bld_write(struct nvkm_acr *acr, u32 bld,
101 struct nvkm_acr_lsfw *lsfw)
102{
103 const struct loader_config_v1 hdr = {
104 .dma_idx = FALCON_SEC2_DMAIDX_UCODE,
105 .code_dma_base = lsfw->offset.img + lsfw->app_start_offset,
106 .code_size_total = lsfw->app_size,
107 .code_size_to_load = lsfw->app_resident_code_size,
108 .code_entry_point = lsfw->app_imem_entry,
109 .data_dma_base = lsfw->offset.img + lsfw->app_start_offset +
110 lsfw->app_resident_data_offset,
111 .data_size = lsfw->app_resident_data_size,
112 .overlay_dma_base = lsfw->offset.img + lsfw->app_start_offset,
113 .argc = 1,
114 .argv = lsfw->falcon->func->emem_addr,
115 };
116
117 nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
118}
119
120static const struct nvkm_acr_lsf_func
121gp102_sec2_acr_0 = {
122 .bld_size = sizeof(struct loader_config_v1),
123 .bld_write = gp102_sec2_acr_bld_write,
124 .bld_patch = gp102_sec2_acr_bld_patch,
125 .boot = gp102_sec2_acr_boot,
126 .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
127 BIT_ULL(NVKM_ACR_LSF_GPCCS) |
128 BIT_ULL(NVKM_ACR_LSF_SEC2),
129 .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
130};
131
132int
133gp102_sec2_initmsg(struct nvkm_sec2 *sec2)
134{
135 struct nv_sec2_init_msg msg;
136 int ret, i;
137
138 ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg));
139 if (ret)
140 return ret;
141
142 if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT ||
143 msg.msg_type != NV_SEC2_INIT_MSG_INIT)
144 return -EINVAL;
145
146 for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) {
147 if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) {
148 nvkm_falcon_msgq_init(sec2->msgq,
149 msg.queue_info[i].index,
150 msg.queue_info[i].offset,
151 msg.queue_info[i].size);
152 } else {
153 nvkm_falcon_cmdq_init(sec2->cmdq,
154 msg.queue_info[i].index,
155 msg.queue_info[i].offset,
156 msg.queue_info[i].size);
157 }
158 }
159
160 return 0;
161}
162
163void
164gp102_sec2_intr(struct nvkm_sec2 *sec2)
165{
166 struct nvkm_subdev *subdev = &sec2->engine.subdev;
167 struct nvkm_falcon *falcon = &sec2->falcon;
168 u32 disp = nvkm_falcon_rd32(falcon, 0x01c);
169 u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16);
170
171 if (intr & 0x00000040) {
172 schedule_work(&sec2->work);
173 nvkm_falcon_wr32(falcon, 0x004, 0x00000040);
174 intr &= ~0x00000040;
175 }
176
177 if (intr) {
178 nvkm_error(subdev, "unhandled intr %08x\n", intr);
179 nvkm_falcon_wr32(falcon, 0x004, intr);
180 }
181}
182
183int
184gp102_sec2_flcn_enable(struct nvkm_falcon *falcon)
185{
186 nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001);
187 udelay(10);
188 nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000);
189 return nvkm_falcon_v1_enable(falcon);
190}
191
192void
193gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon,
194 struct nvkm_memory *ctx)
195{
196 struct nvkm_device *device = falcon->owner->device;
197
198 nvkm_falcon_v1_bind_context(falcon, ctx);
199 if (!ctx)
200 return;
201
202
203
204
205
206
207
208
209
210
211
212
213 nvkm_msec(device, 10,
214 u32 irqstat = nvkm_falcon_rd32(falcon, 0x008);
215 u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc);
216 if ((irqstat & 0x00000008) &&
217 (flcn0dc & 0x00007000) == 0x00005000)
218 break;
219 );
220
221 nvkm_falcon_mask(falcon, 0x004, 0x00000008, 0x00000008);
222 nvkm_falcon_mask(falcon, 0x058, 0x00000002, 0x00000002);
223
224 nvkm_msec(device, 10,
225 u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc);
226 if ((flcn0dc & 0x00007000) == 0x00000000)
227 break;
228 );
229}
230
231static const struct nvkm_falcon_func
232gp102_sec2_flcn = {
233 .debug = 0x408,
234 .fbif = 0x600,
235 .load_imem = nvkm_falcon_v1_load_imem,
236 .load_dmem = nvkm_falcon_v1_load_dmem,
237 .read_dmem = nvkm_falcon_v1_read_dmem,
238 .emem_addr = 0x01000000,
239 .bind_context = gp102_sec2_flcn_bind_context,
240 .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
241 .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
242 .set_start_addr = nvkm_falcon_v1_set_start_addr,
243 .start = nvkm_falcon_v1_start,
244 .enable = gp102_sec2_flcn_enable,
245 .disable = nvkm_falcon_v1_disable,
246 .cmdq = { 0xa00, 0xa04, 8 },
247 .msgq = { 0xa30, 0xa34, 8 },
248};
249
250const struct nvkm_sec2_func
251gp102_sec2 = {
252 .flcn = &gp102_sec2_flcn,
253 .unit_acr = NV_SEC2_UNIT_ACR,
254 .intr = gp102_sec2_intr,
255 .initmsg = gp102_sec2_initmsg,
256};
257
258MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin");
259MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin");
260MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin");
261MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin");
262MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin");
263MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin");
264MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin");
265MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin");
266MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin");
267MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin");
268MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin");
269MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin");
270
271static void
272gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust)
273{
274 struct flcn_bl_dmem_desc_v2 hdr;
275 nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr));
276 hdr.code_dma_base = hdr.code_dma_base + adjust;
277 hdr.data_dma_base = hdr.data_dma_base + adjust;
278 nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
279 flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr);
280}
281
282static void
283gp102_sec2_acr_bld_write_1(struct nvkm_acr *acr, u32 bld,
284 struct nvkm_acr_lsfw *lsfw)
285{
286 const struct flcn_bl_dmem_desc_v2 hdr = {
287 .ctx_dma = FALCON_SEC2_DMAIDX_UCODE,
288 .code_dma_base = lsfw->offset.img + lsfw->app_start_offset,
289 .non_sec_code_off = lsfw->app_resident_code_offset,
290 .non_sec_code_size = lsfw->app_resident_code_size,
291 .code_entry_point = lsfw->app_imem_entry,
292 .data_dma_base = lsfw->offset.img + lsfw->app_start_offset +
293 lsfw->app_resident_data_offset,
294 .data_size = lsfw->app_resident_data_size,
295 .argc = 1,
296 .argv = lsfw->falcon->func->emem_addr,
297 };
298
299 nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
300}
301
302const struct nvkm_acr_lsf_func
303gp102_sec2_acr_1 = {
304 .bld_size = sizeof(struct flcn_bl_dmem_desc_v2),
305 .bld_write = gp102_sec2_acr_bld_write_1,
306 .bld_patch = gp102_sec2_acr_bld_patch_1,
307 .boot = gp102_sec2_acr_boot,
308 .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
309 BIT_ULL(NVKM_ACR_LSF_GPCCS) |
310 BIT_ULL(NVKM_ACR_LSF_SEC2),
311 .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
312};
313
314int
315gp102_sec2_load(struct nvkm_sec2 *sec2, int ver,
316 const struct nvkm_sec2_fwif *fwif)
317{
318 return nvkm_acr_lsfw_load_sig_image_desc_v1(&sec2->engine.subdev,
319 &sec2->falcon,
320 NVKM_ACR_LSF_SEC2, "sec2/",
321 ver, fwif->acr);
322}
323
324MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin");
325MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin");
326MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin");
327MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin");
328MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin");
329MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin");
330MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin");
331MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin");
332MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin");
333MODULE_FIRMWARE("nvidia/gp107/sec2/desc-1.bin");
334MODULE_FIRMWARE("nvidia/gp107/sec2/image-1.bin");
335MODULE_FIRMWARE("nvidia/gp107/sec2/sig-1.bin");
336
337static const struct nvkm_sec2_fwif
338gp102_sec2_fwif[] = {
339 { 1, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_1 },
340 { 0, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_0 },
341 { -1, gp102_sec2_nofw, &gp102_sec2 },
342 {}
343};
344
345int
346gp102_sec2_new(struct nvkm_device *device, int index, struct nvkm_sec2 **psec2)
347{
348 return nvkm_sec2_new_(gp102_sec2_fwif, device, index, 0, psec2);
349}
350