mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-24 13:13:57 +08:00
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:
parent
59d5592d3b
commit
a558be625c
@ -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;
|
||||
|
@ -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 **);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user