From: Alessio Belle <[email protected]> Ensure all accesses to the META firmware interface are done via the generic firmware interface.
To achieve this: - Introduce a new function to the firmware processor table to remove the last direct access to the META firmware interface from outside of the generic firmware logic. - Remove the META firmware interface header. - Rename the META firmware processor header adding an "internal" suffix. - Add guard to the META firmware processor header to prevent accidental inclusion outside of the META firmware specific logic. - Add a multi_dm_thread_assoc property to struct pvr_fw_defs to isolate that behaviour from the architecture. Signed-off-by: Alessio Belle <[email protected]> Signed-off-by: Alexandru Dadu <[email protected]> --- drivers/gpu/drm/imagination/pvr_fw.h | 26 +++++++++ drivers/gpu/drm/imagination/pvr_fw_meta.c | 28 ++++++++-- drivers/gpu/drm/imagination/pvr_fw_meta.h | 14 ----- drivers/gpu/drm/imagination/pvr_fw_mips.c | 1 + drivers/gpu/drm/imagination/pvr_fw_riscv.c | 1 + drivers/gpu/drm/imagination/pvr_fw_startstop.c | 61 ++++++++++++---------- drivers/gpu/drm/imagination/pvr_gem.h | 1 - ...{pvr_rogue_meta.h => pvr_rogue_meta_internal.h} | 10 ++-- 8 files changed, 93 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h index 4b25291135b6..610406668bbb 100644 --- a/drivers/gpu/drm/imagination/pvr_fw.h +++ b/drivers/gpu/drm/imagination/pvr_fw.h @@ -184,6 +184,23 @@ struct pvr_fw_defs { */ void (*irq_clear)(struct pvr_device *pvr_dev); + /** + * @must_wait_fw_idle: Check if the FW stop sequence should wait for hardware + * to report FW idle before proceeding. + * + * @pvr_dev: Target PowerVR device. + * @wait[out]: Whether the FW stop sequence should wait for FW idle. + * + * This function is optional. The assumption is that we must always wait + * for the firmware to reach idle; implement this function and return + * %false to alter this behavior. + * + * Returns: + * * 0 on success. + * * Any appropriate error on failure. + */ + int (*must_wait_fw_idle)(struct pvr_device *pvr_dev, bool *wait); + /** * @has_fixed_data_addr: Specify whether the firmware fixed data must be loaded at the * address given by the firmware layout table. @@ -191,6 +208,15 @@ struct pvr_fw_defs { * This value is mandatory. */ bool has_fixed_data_addr; + + /** + * @multi_dm_thread_assoc: Specify that all threads must be associated + * with the DM separately rather than just the + * first thread (the default behaviour). + * + * This value is mandatory. + */ + bool multi_dm_thread_assoc; }; /** diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.c b/drivers/gpu/drm/imagination/pvr_fw_meta.c index 84f568b5510f..f451f97a4f2f 100644 --- a/drivers/gpu/drm/imagination/pvr_fw_meta.c +++ b/drivers/gpu/drm/imagination/pvr_fw_meta.c @@ -4,10 +4,11 @@ #include "pvr_device.h" #include "pvr_fw.h" #include "pvr_fw_info.h" -#include "pvr_fw_meta.h" #include "pvr_gem.h" #include "pvr_rogue_cr_defs.h" -#include "pvr_rogue_meta.h" +#define PVR_ROGUE_META_INTERNAL_H_EXPLICIT_INCLUDE +#include "pvr_rogue_meta_internal.h" +#undef PVR_ROGUE_META_INTERNAL_H_EXPLICIT_INCLUDE #include "pvr_vm.h" #include <linux/compiler.h> @@ -32,7 +33,7 @@ * * 0 on success, or * * Any error returned by pvr_cr_poll_reg32(). */ -int +static int pvr_meta_cr_read32(struct pvr_device *pvr_dev, u32 reg_addr, u32 *reg_value_out) { int err; @@ -563,6 +564,25 @@ pvr_meta_irq_clear(struct pvr_device *pvr_dev) ROGUE_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK); } +static int +pvr_meta_must_wait_fw_idle(struct pvr_device *pvr_dev, bool *wait) +{ + u32 reg_value; + int err; + + err = pvr_meta_cr_read32(pvr_dev, META_CR_TxVECINT_BHALT, ®_value); + if (err) + return err; + + /* + * Wait for Sidekick/Jones to signal IDLE including the Garten + * Wrapper if there is no debugger attached (TxVECINT_BHALT = 0x0). + */ + *wait = !reg_value; + + return 0; +} + const struct pvr_fw_defs pvr_fw_defs_meta = { .init = pvr_meta_init, .fini = pvr_meta_fini, @@ -573,5 +593,7 @@ const struct pvr_fw_defs pvr_fw_defs_meta = { .wrapper_init = pvr_meta_wrapper_init, .irq_pending = pvr_meta_irq_pending, .irq_clear = pvr_meta_irq_clear, + .must_wait_fw_idle = pvr_meta_must_wait_fw_idle, .has_fixed_data_addr = false, + .multi_dm_thread_assoc = true, }; diff --git a/drivers/gpu/drm/imagination/pvr_fw_meta.h b/drivers/gpu/drm/imagination/pvr_fw_meta.h deleted file mode 100644 index 911ad700cba6..000000000000 --- a/drivers/gpu/drm/imagination/pvr_fw_meta.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ -/* Copyright (c) 2023 Imagination Technologies Ltd. */ - -#ifndef PVR_FW_META_H -#define PVR_FW_META_H - -#include <linux/types.h> - -/* Forward declaration from pvr_device.h */ -struct pvr_device; - -int pvr_meta_cr_read32(struct pvr_device *pvr_dev, u32 reg_addr, u32 *reg_value_out); - -#endif /* PVR_FW_META_H */ diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c index 6914fc46db50..ec0dad1692c3 100644 --- a/drivers/gpu/drm/imagination/pvr_fw_mips.c +++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c @@ -196,4 +196,5 @@ const struct pvr_fw_defs pvr_fw_defs_mips = { .irq_pending = pvr_mips_irq_pending, .irq_clear = pvr_mips_irq_clear, .has_fixed_data_addr = true, + .multi_dm_thread_assoc = false, }; diff --git a/drivers/gpu/drm/imagination/pvr_fw_riscv.c b/drivers/gpu/drm/imagination/pvr_fw_riscv.c index 2b24c40bc20f..ef2801276252 100644 --- a/drivers/gpu/drm/imagination/pvr_fw_riscv.c +++ b/drivers/gpu/drm/imagination/pvr_fw_riscv.c @@ -182,4 +182,5 @@ const struct pvr_fw_defs pvr_fw_defs_riscv = { .irq_pending = pvr_riscv_irq_pending, .irq_clear = pvr_riscv_irq_clear, .has_fixed_data_addr = false, + .multi_dm_thread_assoc = false, }; diff --git a/drivers/gpu/drm/imagination/pvr_fw_startstop.c b/drivers/gpu/drm/imagination/pvr_fw_startstop.c index 98ca2692239d..9a617f78256e 100644 --- a/drivers/gpu/drm/imagination/pvr_fw_startstop.c +++ b/drivers/gpu/drm/imagination/pvr_fw_startstop.c @@ -3,10 +3,8 @@ #include "pvr_device.h" #include "pvr_fw.h" -#include "pvr_fw_meta.h" #include "pvr_fw_startstop.h" #include "pvr_rogue_cr_defs.h" -#include "pvr_rogue_meta.h" #include "pvr_vm.h" #include <linux/compiler.h> @@ -199,6 +197,30 @@ pvr_fw_start(struct pvr_device *pvr_dev) return err; } +static inline bool layout_is_mars(struct pvr_device *pvr_dev) +{ + u64 layout_mars_value = 0; + + if (PVR_FEATURE_VALUE(pvr_dev, layout_mars, &layout_mars_value)) + return layout_mars_value > 0; + + return false; +} + +static inline int must_wait_fw_idle_before_stop(struct pvr_device *pvr_dev) +{ + bool wait_fw_idle = false; + int err; + + if (pvr_dev->fw_dev.defs->must_wait_fw_idle) { + err = pvr_dev->fw_dev.defs->must_wait_fw_idle(pvr_dev, &wait_fw_idle); + if (err) + return err; + } + + return wait_fw_idle; +} + /** * pvr_fw_stop() - Stop FW processor * @pvr_dev: Target PowerVR device. @@ -214,15 +236,9 @@ pvr_fw_stop(struct pvr_device *pvr_dev) ~(ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN | ROGUE_CR_SIDEKICK_IDLE_SOCIF_EN | ROGUE_CR_SIDEKICK_IDLE_HOSTIF_EN); - bool skip_garten_idle = false; - u64 layout_mars_value = 0; - bool layout_mars = false; - bool meta_fw = pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_META; - u32 reg_value; - int err; - if (PVR_FEATURE_VALUE(pvr_dev, layout_mars, &layout_mars_value) == 0) - layout_mars = layout_mars_value > 0; + bool layout_mars = layout_is_mars(pvr_dev); + int err; /* * For cores with the LAYOUT_MARS feature, SIDEKICK and SLC would have been @@ -250,7 +266,7 @@ pvr_fw_stop(struct pvr_device *pvr_dev) ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_MASKFULL & ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK); - if (meta_fw) { + if (pvr_dev->fw_dev.defs->multi_dm_thread_assoc) { pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC, ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL & ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK); @@ -297,6 +313,8 @@ pvr_fw_stop(struct pvr_device *pvr_dev) * powered down by the FW. */ if (!layout_mars) { + int wait_fw_idle; + /* Wait for SLC to signal IDLE. */ err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE, ROGUE_CR_SLC_IDLE_MASKFULL, @@ -309,24 +327,12 @@ pvr_fw_stop(struct pvr_device *pvr_dev) sidekick_idle_mask, POLL_TIMEOUT_USEC); if (err) return err; - } - if (meta_fw) { - err = pvr_meta_cr_read32(pvr_dev, META_CR_TxVECINT_BHALT, ®_value); - if (err) - return err; - - /* - * Wait for Sidekick/Jones to signal IDLE including the Garten - * Wrapper if there is no debugger attached (TxVECINT_BHALT = - * 0x0). - */ - if (reg_value) - skip_garten_idle = true; - } + wait_fw_idle = must_wait_fw_idle_before_stop(pvr_dev); + if (wait_fw_idle < 0) + return wait_fw_idle; - if (meta_fw || !layout_mars) { - if (!skip_garten_idle) { + if (wait_fw_idle) { err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN, ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN, @@ -346,7 +352,6 @@ pvr_fw_stop(struct pvr_device *pvr_dev) ROGUE_CR_MARS_IDLE_CPU_EN | ROGUE_CR_MARS_IDLE_MH_SYSARB0_EN, POLL_TIMEOUT_USEC); - if (err) return err; } diff --git a/drivers/gpu/drm/imagination/pvr_gem.h b/drivers/gpu/drm/imagination/pvr_gem.h index ae7af82b6f17..e84be25f8576 100644 --- a/drivers/gpu/drm/imagination/pvr_gem.h +++ b/drivers/gpu/drm/imagination/pvr_gem.h @@ -5,7 +5,6 @@ #define PVR_GEM_H #include "pvr_heap_config.h" -#include "pvr_rogue_meta.h" #include <uapi/drm/pvr_drm.h> diff --git a/drivers/gpu/drm/imagination/pvr_rogue_meta.h b/drivers/gpu/drm/imagination/pvr_rogue_meta_internal.h similarity index 98% rename from drivers/gpu/drm/imagination/pvr_rogue_meta.h rename to drivers/gpu/drm/imagination/pvr_rogue_meta_internal.h index 3020e6582daa..dd978988ed40 100644 --- a/drivers/gpu/drm/imagination/pvr_rogue_meta.h +++ b/drivers/gpu/drm/imagination/pvr_rogue_meta_internal.h @@ -1,8 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-only OR MIT */ /* Copyright (c) 2023 Imagination Technologies Ltd. */ -#ifndef PVR_ROGUE_META_H -#define PVR_ROGUE_META_H +#ifndef PVR_ROGUE_META_INTERNAL_H +#define PVR_ROGUE_META_INTERNAL_H + +#ifndef PVR_ROGUE_META_INTERNAL_H_EXPLICIT_INCLUDE +#error This file may only be included if explicitly defined +#endif /***** The META HW register definitions in the file are updated manually *****/ @@ -353,4 +357,4 @@ struct rogue_meta_ldr_cfg_blk { #define ROGUE_FW_PROCESSOR_META "META" -#endif /* PVR_ROGUE_META_H */ +#endif /* PVR_ROGUE_META_INTERNAL_H */ -- 2.43.0
