From: Alexandre Courbot Date: Thu, 16 Feb 2017 06:13:49 +0000 (+0900) Subject: drm/nouveau/secboot: workaround bug when starting SEC2 firmware X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=ec91cb028511d68193c792f27a1bcd8d3e756280;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git drm/nouveau/secboot: workaround bug when starting SEC2 firmware For some unknown reason the LS SEC2 firmware needs to be started twice to operate. Detect and address that condition. Signed-off-by: Alexandre Courbot Signed-off-by: Ben Skeggs --- diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c index b4e0add13a33..72ca537b0b59 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -977,6 +978,7 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb) { const struct nvkm_subdev *subdev = &sb->subdev; unsigned long managed_falcons = acr->base.managed_falcons; + u32 reg; int falcon_id; int ret; @@ -1025,6 +1027,37 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb) /* Start LS firmware on boot falcon */ nvkm_falcon_start(sb->boot_falcon); + + /* + * There is a bug where the LS firmware sometimes require to be started + * twice (this happens only on SEC). Detect and workaround that + * condition. + * + * Once started, the falcon will end up in STOPPED condition (bit 5) + * if successful, or in HALT condition (bit 4) if not. + */ + nvkm_msec(subdev->device, 1, + if ((reg = nvkm_rd32(subdev->device, + sb->boot_falcon->addr + 0x100) + & 0x30) != 0) + break; + ); + if (reg & BIT(4)) { + nvkm_debug(subdev, "applying workaround for start bug..."); + nvkm_falcon_start(sb->boot_falcon); + nvkm_msec(subdev->device, 1, + if ((reg = nvkm_rd32(subdev->device, + sb->boot_falcon->addr + 0x100) + & 0x30) != 0) + break; + ); + if (reg & BIT(4)) { + nvkm_error(subdev, "%s failed to start\n", + nvkm_secboot_falcon_name[acr->base.boot_falcon]); + return -EINVAL; + } + } + nvkm_debug(subdev, "%s started\n", nvkm_secboot_falcon_name[acr->base.boot_falcon]);