Commit aae84bf1 authored by Daniele Ceraolo Spurio's avatar Daniele Ceraolo Spurio Committed by Rodrigo Vivi

drm/xe/gsc: Implement WA 14015076503

When the GSC FW is loaded, we need to inform it when a GSCCS reset is
coming and then wait 200ms for it to get ready to process the reset.

v2: move WA code to GSC file, use variable in Makefile (John)
Signed-off-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: John Harrison <john.c.harrison@intel.com>
Reviewed-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent dd0e89e5
...@@ -37,7 +37,16 @@ quiet_cmd_wa_oob = GEN $(notdir $(generated_oob)) ...@@ -37,7 +37,16 @@ quiet_cmd_wa_oob = GEN $(notdir $(generated_oob))
$(generated_oob) &: $(obj)/xe_gen_wa_oob $(srctree)/$(src)/xe_wa_oob.rules $(generated_oob) &: $(obj)/xe_gen_wa_oob $(srctree)/$(src)/xe_wa_oob.rules
$(call cmd,wa_oob) $(call cmd,wa_oob)
$(obj)/xe_guc.o $(obj)/xe_migrate.o $(obj)/xe_ring_ops.o $(obj)/xe_vm.o $(obj)/xe_wa.o $(obj)/xe_ttm_stolen_mgr.o: $(generated_oob) uses_generated_oob := \
$(obj)/xe_gsc.o \
$(obj)/xe_guc.o \
$(obj)/xe_migrate.o \
$(obj)/xe_ring_ops.o \
$(obj)/xe_vm.o \
$(obj)/xe_wa.o \
$(obj)/xe_ttm_stolen_mgr.o
$(uses_generated_oob): $(generated_oob)
# Please keep these build lists sorted! # Please keep these build lists sorted!
......
...@@ -16,6 +16,13 @@ ...@@ -16,6 +16,13 @@
#define MTL_GSC_HECI1_BASE 0x00116000 #define MTL_GSC_HECI1_BASE 0x00116000
#define MTL_GSC_HECI2_BASE 0x00117000 #define MTL_GSC_HECI2_BASE 0x00117000
#define HECI_H_CSR(base) XE_REG((base) + 0x4)
#define HECI_H_CSR_IE REG_BIT(0)
#define HECI_H_CSR_IS REG_BIT(1)
#define HECI_H_CSR_IG REG_BIT(2)
#define HECI_H_CSR_RDY REG_BIT(3)
#define HECI_H_CSR_RST REG_BIT(4)
/* /*
* The FWSTS register values are FW defined and can be different between * The FWSTS register values are FW defined and can be different between
* HECI1 and HECI2 * HECI1 and HECI2
...@@ -26,4 +33,7 @@ ...@@ -26,4 +33,7 @@
#define HECI1_FWSTS1_PROXY_STATE_NORMAL 5 #define HECI1_FWSTS1_PROXY_STATE_NORMAL 5
#define HECI1_FWSTS1_INIT_COMPLETE REG_BIT(9) #define HECI1_FWSTS1_INIT_COMPLETE REG_BIT(9)
#define HECI_H_GS1(base) XE_REG((base) + 0xc4c)
#define HECI_H_GS1_ER_PREP REG_BIT(0)
#endif #endif
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <drm/drm_managed.h> #include <drm/drm_managed.h>
#include "generated/xe_wa_oob.h"
#include "xe_bb.h" #include "xe_bb.h"
#include "xe_bo.h" #include "xe_bo.h"
#include "xe_device.h" #include "xe_device.h"
...@@ -17,6 +18,7 @@ ...@@ -17,6 +18,7 @@
#include "xe_mmio.h" #include "xe_mmio.h"
#include "xe_sched_job.h" #include "xe_sched_job.h"
#include "xe_uc_fw.h" #include "xe_uc_fw.h"
#include "xe_wa.h"
#include "instructions/xe_gsc_commands.h" #include "instructions/xe_gsc_commands.h"
#include "regs/xe_gsc_regs.h" #include "regs/xe_gsc_regs.h"
...@@ -300,3 +302,30 @@ void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc) ...@@ -300,3 +302,30 @@ void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc)
if (xe_uc_fw_is_loadable(&gsc->fw) && gsc->wq) if (xe_uc_fw_is_loadable(&gsc->fw) && gsc->wq)
flush_work(&gsc->work); flush_work(&gsc->work);
} }
/*
* wa_14015076503: if the GSC FW is loaded, we need to alert it before doing a
* GSC engine reset by writing a notification bit in the GS1 register and then
* triggering an interrupt to GSC; from the interrupt it will take up to 200ms
* for the FW to get prepare for the reset, so we need to wait for that amount
* of time.
* After the reset is complete we need to then clear the GS1 register.
*/
void xe_gsc_wa_14015076503(struct xe_gt *gt, bool prep)
{
u32 gs1_set = prep ? HECI_H_GS1_ER_PREP : 0;
u32 gs1_clr = prep ? 0 : HECI_H_GS1_ER_PREP;
/* WA only applies if the GSC is loaded */
if (!XE_WA(gt, 14015076503) || !gsc_fw_is_loaded(gt))
return;
xe_mmio_rmw32(gt, HECI_H_GS1(MTL_GSC_HECI2_BASE), gs1_clr, gs1_set);
if (prep) {
/* make sure the reset bit is clear when writing the CSR reg */
xe_mmio_rmw32(gt, HECI_H_CSR(MTL_GSC_HECI2_BASE),
HECI_H_CSR_RST, HECI_H_CSR_IG);
msleep(200);
}
}
...@@ -8,9 +8,13 @@ ...@@ -8,9 +8,13 @@
#include "xe_gsc_types.h" #include "xe_gsc_types.h"
struct xe_gt;
int xe_gsc_init(struct xe_gsc *gsc); int xe_gsc_init(struct xe_gsc *gsc);
int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc); int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc);
void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc); void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc);
void xe_gsc_load_start(struct xe_gsc *gsc); void xe_gsc_load_start(struct xe_gsc *gsc);
void xe_gsc_wa_14015076503(struct xe_gt *gt, bool prep);
#endif #endif
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "xe_execlist.h" #include "xe_execlist.h"
#include "xe_force_wake.h" #include "xe_force_wake.h"
#include "xe_ggtt.h" #include "xe_ggtt.h"
#include "xe_gsc.h"
#include "xe_gt_clock.h" #include "xe_gt_clock.h"
#include "xe_gt_idle_sysfs.h" #include "xe_gt_idle_sysfs.h"
#include "xe_gt_mcr.h" #include "xe_gt_mcr.h"
...@@ -512,12 +513,16 @@ static int do_gt_reset(struct xe_gt *gt) ...@@ -512,12 +513,16 @@ static int do_gt_reset(struct xe_gt *gt)
{ {
int err; int err;
xe_gsc_wa_14015076503(gt, true);
xe_mmio_write32(gt, GDRST, GRDOM_FULL); xe_mmio_write32(gt, GDRST, GRDOM_FULL);
err = xe_mmio_wait32(gt, GDRST, GRDOM_FULL, 0, 5000, NULL, false); err = xe_mmio_wait32(gt, GDRST, GRDOM_FULL, 0, 5000, NULL, false);
if (err) if (err)
xe_gt_err(gt, "failed to clear GRDOM_FULL (%pe)\n", xe_gt_err(gt, "failed to clear GRDOM_FULL (%pe)\n",
ERR_PTR(err)); ERR_PTR(err));
xe_gsc_wa_14015076503(gt, false);
return err; return err;
} }
......
...@@ -20,3 +20,4 @@ ...@@ -20,3 +20,4 @@
16017236439 PLATFORM(PVC) 16017236439 PLATFORM(PVC)
22010954014 PLATFORM(DG2) 22010954014 PLATFORM(DG2)
14019821291 MEDIA_VERSION_RANGE(1300, 2000) 14019821291 MEDIA_VERSION_RANGE(1300, 2000)
14015076503 MEDIA_VERSION(1300)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment