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>
This commit is contained in:
Alexandre Courbot 2017-03-29 18:31:15 +09:00 committed by Ben Skeggs
parent 59d5592d3b
commit a558be625c
3 changed files with 117 additions and 0 deletions

View File

@ -501,6 +501,9 @@ nvkm_msgqueue_new(u32 version, struct nvkm_falcon *falcon,
case 0x0137c63d:
ret = msgqueue_0137c63d_new(falcon, sb, queue);
break;
case 0x0137bca5:
ret = msgqueue_0137bca5_new(falcon, sb, queue);
break;
case 0x0148cdec:
ret = msgqueue_0148cdec_new(falcon, sb, queue);
break;

View File

@ -205,6 +205,8 @@ void nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *,
int msgqueue_0137c63d_new(struct nvkm_falcon *, const struct nvkm_secboot *,
struct nvkm_msgqueue **);
int msgqueue_0137bca5_new(struct nvkm_falcon *, const struct nvkm_secboot *,
struct nvkm_msgqueue **);
int msgqueue_0148cdec_new(struct nvkm_falcon *, const struct nvkm_secboot *,
struct nvkm_msgqueue **);

View File

@ -43,6 +43,15 @@ struct msgqueue_0137c63d {
#define msgqueue_0137c63d(q) \
container_of(q, struct msgqueue_0137c63d, base)
struct msgqueue_0137bca5 {
struct msgqueue_0137c63d base;
u64 wpr_addr;
};
#define msgqueue_0137bca5(q) \
container_of(container_of(q, struct msgqueue_0137c63d, base), \
struct msgqueue_0137bca5, base);
static struct nvkm_msgqueue_queue *
msgqueue_0137c63d_cmd_queue(struct nvkm_msgqueue *queue,
enum msgqueue_msg_priority priority)
@ -180,6 +189,7 @@ msgqueue_0137c63d_init_func = {
enum {
ACR_CMD_INIT_WPR_REGION = 0x00,
ACR_CMD_BOOTSTRAP_FALCON = 0x01,
ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS = 0x03,
};
static void
@ -286,11 +296,81 @@ acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon)
return 0;
}
static void
acr_boot_multiple_falcons_callback(struct nvkm_msgqueue *priv,
struct nvkm_msgqueue_hdr *hdr)
{
struct acr_bootstrap_falcon_msg {
struct nvkm_msgqueue_msg base;
u32 falcon_mask;
} *msg = (void *)hdr;
const struct nvkm_subdev *subdev = priv->falcon->owner;
unsigned long falcon_mask = msg->falcon_mask;
u32 falcon_id, falcon_treated = 0;
for_each_set_bit(falcon_id, &falcon_mask, NVKM_SECBOOT_FALCON_END) {
nvkm_debug(subdev, "%s booted\n",
nvkm_secboot_falcon_name[falcon_id]);
falcon_treated |= BIT(falcon_id);
}
if (falcon_treated != msg->falcon_mask) {
nvkm_error(subdev, "in bootstrap falcon callback:\n");
nvkm_error(subdev, "invalid falcon mask 0x%x\n",
msg->falcon_mask);
return;
}
}
static int
acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask)
{
DECLARE_COMPLETION_ONSTACK(completed);
/*
* flags - Flag specifying RESET or no RESET.
* falcon id - Falcon id specifying falcon to bootstrap.
*/
struct {
struct nvkm_msgqueue_hdr hdr;
u8 cmd_type;
u32 flags;
u32 falcon_mask;
u32 use_va_mask;
u32 wpr_lo;
u32 wpr_hi;
} cmd;
struct msgqueue_0137bca5 *queue = msgqueue_0137bca5(priv);
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR;
cmd.hdr.size = sizeof(cmd);
cmd.cmd_type = ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS;
cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
cmd.falcon_mask = falcon_mask;
cmd.wpr_lo = lower_32_bits(queue->wpr_addr);
cmd.wpr_hi = upper_32_bits(queue->wpr_addr);
nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr,
acr_boot_multiple_falcons_callback, &completed, true);
if (!wait_for_completion_timeout(&completed, msecs_to_jiffies(1000)))
return -ETIMEDOUT;
return 0;
}
static const struct nvkm_msgqueue_acr_func
msgqueue_0137c63d_acr_func = {
.boot_falcon = acr_boot_falcon,
};
static const struct nvkm_msgqueue_acr_func
msgqueue_0137bca5_acr_func = {
.boot_falcon = acr_boot_falcon,
.boot_multiple_falcons = acr_boot_multiple_falcons,
};
static void
msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue)
{
@ -322,3 +402,35 @@ msgqueue_0137c63d_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb,
return 0;
}
static const struct nvkm_msgqueue_func
msgqueue_0137bca5_func = {
.init_func = &msgqueue_0137c63d_init_func,
.acr_func = &msgqueue_0137bca5_acr_func,
.cmd_queue = msgqueue_0137c63d_cmd_queue,
.recv = msgqueue_0137c63d_process_msgs,
.dtor = msgqueue_0137c63d_dtor,
};
int
msgqueue_0137bca5_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb,
struct nvkm_msgqueue **queue)
{
struct msgqueue_0137bca5 *ret;
ret = kzalloc(sizeof(*ret), GFP_KERNEL);
if (!ret)
return -ENOMEM;
*queue = &ret->base.base;
/*
* FIXME this must be set to the address of a *GPU* mapping within the
* ACR address space!
*/
/* ret->wpr_addr = sb->wpr_addr; */
nvkm_msgqueue_ctor(&msgqueue_0137bca5_func, falcon, &ret->base.base);
return 0;
}