aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2017-03-29 05:31:15 -0400
committerBen Skeggs <bskeggs@redhat.com>2017-04-06 00:39:04 -0400
commita558be625cf9072fb31aa7c5e592bd1e1dd73845 (patch)
treee29140a9a3927586259581db0123f36d0bbe1f95 /drivers
parent59d5592d3bf2e70b9c56212cf5c9f1bfab6f0147 (diff)
drm/nouveau/msgqueue: support for GP10B PMU firmware
The GP10B firmware is very close to GM20B's. The only difference is that it supports booting multiple falcons. In order to avoid having too much functions and structures shared, implement its support in the same source file as GM20B firmware. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c112
3 files changed, 117 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
index f7101a910bc7..d45d7947a964 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
@@ -501,6 +501,9 @@ nvkm_msgqueue_new(u32 version, struct nvkm_falcon *falcon,
501 case 0x0137c63d: 501 case 0x0137c63d:
502 ret = msgqueue_0137c63d_new(falcon, sb, queue); 502 ret = msgqueue_0137c63d_new(falcon, sb, queue);
503 break; 503 break;
504 case 0x0137bca5:
505 ret = msgqueue_0137bca5_new(falcon, sb, queue);
506 break;
504 case 0x0148cdec: 507 case 0x0148cdec:
505 ret = msgqueue_0148cdec_new(falcon, sb, queue); 508 ret = msgqueue_0148cdec_new(falcon, sb, queue);
506 break; 509 break;
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
index 2b3a6c3b8f6a..13b54f8d8e04 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
@@ -205,6 +205,8 @@ void nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *,
205 205
206int msgqueue_0137c63d_new(struct nvkm_falcon *, const struct nvkm_secboot *, 206int msgqueue_0137c63d_new(struct nvkm_falcon *, const struct nvkm_secboot *,
207 struct nvkm_msgqueue **); 207 struct nvkm_msgqueue **);
208int msgqueue_0137bca5_new(struct nvkm_falcon *, const struct nvkm_secboot *,
209 struct nvkm_msgqueue **);
208int msgqueue_0148cdec_new(struct nvkm_falcon *, const struct nvkm_secboot *, 210int msgqueue_0148cdec_new(struct nvkm_falcon *, const struct nvkm_secboot *,
209 struct nvkm_msgqueue **); 211 struct nvkm_msgqueue **);
210 212
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
index 935b9a7e60a9..fec0273158f6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
@@ -43,6 +43,15 @@ struct msgqueue_0137c63d {
43#define msgqueue_0137c63d(q) \ 43#define msgqueue_0137c63d(q) \
44 container_of(q, struct msgqueue_0137c63d, base) 44 container_of(q, struct msgqueue_0137c63d, base)
45 45
46struct msgqueue_0137bca5 {
47 struct msgqueue_0137c63d base;
48
49 u64 wpr_addr;
50};
51#define msgqueue_0137bca5(q) \
52 container_of(container_of(q, struct msgqueue_0137c63d, base), \
53 struct msgqueue_0137bca5, base);
54
46static struct nvkm_msgqueue_queue * 55static struct nvkm_msgqueue_queue *
47msgqueue_0137c63d_cmd_queue(struct nvkm_msgqueue *queue, 56msgqueue_0137c63d_cmd_queue(struct nvkm_msgqueue *queue,
48 enum msgqueue_msg_priority priority) 57 enum msgqueue_msg_priority priority)
@@ -180,6 +189,7 @@ msgqueue_0137c63d_init_func = {
180enum { 189enum {
181 ACR_CMD_INIT_WPR_REGION = 0x00, 190 ACR_CMD_INIT_WPR_REGION = 0x00,
182 ACR_CMD_BOOTSTRAP_FALCON = 0x01, 191 ACR_CMD_BOOTSTRAP_FALCON = 0x01,
192 ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS = 0x03,
183}; 193};
184 194
185static void 195static void
@@ -286,11 +296,81 @@ acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon)
286 return 0; 296 return 0;
287} 297}
288 298
299static void
300acr_boot_multiple_falcons_callback(struct nvkm_msgqueue *priv,
301 struct nvkm_msgqueue_hdr *hdr)
302{
303 struct acr_bootstrap_falcon_msg {
304 struct nvkm_msgqueue_msg base;
305
306 u32 falcon_mask;
307 } *msg = (void *)hdr;
308 const struct nvkm_subdev *subdev = priv->falcon->owner;
309 unsigned long falcon_mask = msg->falcon_mask;
310 u32 falcon_id, falcon_treated = 0;
311
312 for_each_set_bit(falcon_id, &falcon_mask, NVKM_SECBOOT_FALCON_END) {
313 nvkm_debug(subdev, "%s booted\n",
314 nvkm_secboot_falcon_name[falcon_id]);
315 falcon_treated |= BIT(falcon_id);
316 }
317
318 if (falcon_treated != msg->falcon_mask) {
319 nvkm_error(subdev, "in bootstrap falcon callback:\n");
320 nvkm_error(subdev, "invalid falcon mask 0x%x\n",
321 msg->falcon_mask);
322 return;
323 }
324}
325
326static int
327acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask)
328{
329 DECLARE_COMPLETION_ONSTACK(completed);
330 /*
331 * flags - Flag specifying RESET or no RESET.
332 * falcon id - Falcon id specifying falcon to bootstrap.
333 */
334 struct {
335 struct nvkm_msgqueue_hdr hdr;
336 u8 cmd_type;
337 u32 flags;
338 u32 falcon_mask;
339 u32 use_va_mask;
340 u32 wpr_lo;
341 u32 wpr_hi;
342 } cmd;
343 struct msgqueue_0137bca5 *queue = msgqueue_0137bca5(priv);
344
345 memset(&cmd, 0, sizeof(cmd));
346
347 cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR;
348 cmd.hdr.size = sizeof(cmd);
349 cmd.cmd_type = ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS;
350 cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
351 cmd.falcon_mask = falcon_mask;
352 cmd.wpr_lo = lower_32_bits(queue->wpr_addr);
353 cmd.wpr_hi = upper_32_bits(queue->wpr_addr);
354 nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr,
355 acr_boot_multiple_falcons_callback, &completed, true);
356
357 if (!wait_for_completion_timeout(&completed, msecs_to_jiffies(1000)))
358 return -ETIMEDOUT;
359
360 return 0;
361}
362
289static const struct nvkm_msgqueue_acr_func 363static const struct nvkm_msgqueue_acr_func
290msgqueue_0137c63d_acr_func = { 364msgqueue_0137c63d_acr_func = {
291 .boot_falcon = acr_boot_falcon, 365 .boot_falcon = acr_boot_falcon,
292}; 366};
293 367
368static const struct nvkm_msgqueue_acr_func
369msgqueue_0137bca5_acr_func = {
370 .boot_falcon = acr_boot_falcon,
371 .boot_multiple_falcons = acr_boot_multiple_falcons,
372};
373
294static void 374static void
295msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue) 375msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue)
296{ 376{
@@ -322,3 +402,35 @@ msgqueue_0137c63d_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb,
322 402
323 return 0; 403 return 0;
324} 404}
405
406static const struct nvkm_msgqueue_func
407msgqueue_0137bca5_func = {
408 .init_func = &msgqueue_0137c63d_init_func,
409 .acr_func = &msgqueue_0137bca5_acr_func,
410 .cmd_queue = msgqueue_0137c63d_cmd_queue,
411 .recv = msgqueue_0137c63d_process_msgs,
412 .dtor = msgqueue_0137c63d_dtor,
413};
414
415int
416msgqueue_0137bca5_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb,
417 struct nvkm_msgqueue **queue)
418{
419 struct msgqueue_0137bca5 *ret;
420
421 ret = kzalloc(sizeof(*ret), GFP_KERNEL);
422 if (!ret)
423 return -ENOMEM;
424
425 *queue = &ret->base.base;
426
427 /*
428 * FIXME this must be set to the address of a *GPU* mapping within the
429 * ACR address space!
430 */
431 /* ret->wpr_addr = sb->wpr_addr; */
432
433 nvkm_msgqueue_ctor(&msgqueue_0137bca5_func, falcon, &ret->base.base);
434
435 return 0;
436}