diff options
author | Alexandre Courbot <acourbot@nvidia.com> | 2017-02-16 01:13:49 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2017-03-07 02:05:15 -0500 |
commit | ec91cb028511d68193c792f27a1bcd8d3e756280 (patch) | |
tree | c000e1730828c51c3180c6a4b5bed8a19197d1b3 | |
parent | c5e1fef4875b75df48a7e9828243062799e444dc (diff) |
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 <acourbot@nvidia.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 33 |
1 files changed, 33 insertions, 0 deletions
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 @@ | |||
26 | #include <core/firmware.h> | 26 | #include <core/firmware.h> |
27 | #include <engine/falcon.h> | 27 | #include <engine/falcon.h> |
28 | #include <subdev/mc.h> | 28 | #include <subdev/mc.h> |
29 | #include <subdev/timer.h> | ||
29 | #include <subdev/pmu.h> | 30 | #include <subdev/pmu.h> |
30 | #include <core/msgqueue.h> | 31 | #include <core/msgqueue.h> |
31 | #include <engine/sec2.h> | 32 | #include <engine/sec2.h> |
@@ -977,6 +978,7 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb) | |||
977 | { | 978 | { |
978 | const struct nvkm_subdev *subdev = &sb->subdev; | 979 | const struct nvkm_subdev *subdev = &sb->subdev; |
979 | unsigned long managed_falcons = acr->base.managed_falcons; | 980 | unsigned long managed_falcons = acr->base.managed_falcons; |
981 | u32 reg; | ||
980 | int falcon_id; | 982 | int falcon_id; |
981 | int ret; | 983 | int ret; |
982 | 984 | ||
@@ -1025,6 +1027,37 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb) | |||
1025 | 1027 | ||
1026 | /* Start LS firmware on boot falcon */ | 1028 | /* Start LS firmware on boot falcon */ |
1027 | nvkm_falcon_start(sb->boot_falcon); | 1029 | nvkm_falcon_start(sb->boot_falcon); |
1030 | |||
1031 | /* | ||
1032 | * There is a bug where the LS firmware sometimes require to be started | ||
1033 | * twice (this happens only on SEC). Detect and workaround that | ||
1034 | * condition. | ||
1035 | * | ||
1036 | * Once started, the falcon will end up in STOPPED condition (bit 5) | ||
1037 | * if successful, or in HALT condition (bit 4) if not. | ||
1038 | */ | ||
1039 | nvkm_msec(subdev->device, 1, | ||
1040 | if ((reg = nvkm_rd32(subdev->device, | ||
1041 | sb->boot_falcon->addr + 0x100) | ||
1042 | & 0x30) != 0) | ||
1043 | break; | ||
1044 | ); | ||
1045 | if (reg & BIT(4)) { | ||
1046 | nvkm_debug(subdev, "applying workaround for start bug..."); | ||
1047 | nvkm_falcon_start(sb->boot_falcon); | ||
1048 | nvkm_msec(subdev->device, 1, | ||
1049 | if ((reg = nvkm_rd32(subdev->device, | ||
1050 | sb->boot_falcon->addr + 0x100) | ||
1051 | & 0x30) != 0) | ||
1052 | break; | ||
1053 | ); | ||
1054 | if (reg & BIT(4)) { | ||
1055 | nvkm_error(subdev, "%s failed to start\n", | ||
1056 | nvkm_secboot_falcon_name[acr->base.boot_falcon]); | ||
1057 | return -EINVAL; | ||
1058 | } | ||
1059 | } | ||
1060 | |||
1028 | nvkm_debug(subdev, "%s started\n", | 1061 | nvkm_debug(subdev, "%s started\n", |
1029 | nvkm_secboot_falcon_name[acr->base.boot_falcon]); | 1062 | nvkm_secboot_falcon_name[acr->base.boot_falcon]); |
1030 | 1063 | ||