File Index
Files and directories
Sign in
FILE

pvr_fw_startstop.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/imagination/pvr_fw_startstop.c C
  1// SPDX-License-Identifier: GPL-2.0-only OR MIT
  2/* Copyright (c) 2023 Imagination Technologies Ltd. */
  3
  4#include "pvr_device.h"
  5#include "pvr_fw.h"
  6#include "pvr_fw_meta.h"
  7#include "pvr_fw_startstop.h"
  8#include "pvr_rogue_cr_defs.h"
  9#include "pvr_rogue_meta.h"
 10#include "pvr_vm.h"
 11
 12#include <linux/compiler.h>
 13#include <linux/delay.h>
 14#include <linux/ktime.h>
 15#include <linux/types.h>
 16
 17#define POLL_TIMEOUT_USEC 1000000
 18
 19static void
 20rogue_axi_ace_list_init(struct pvr_device *pvr_dev)
 21{
 22	/* Setup AXI-ACE config. Set everything to outer cache. */
 23	u64 reg_val =
 24		(3U << ROGUE_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_NON_SNOOPING_SHIFT) |
 25		(3U << ROGUE_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_NON_SNOOPING_SHIFT) |
 26		(2U << ROGUE_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_CACHE_MAINTENANCE_SHIFT) |
 27		(2U << ROGUE_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_COHERENT_SHIFT) |
 28		(2U << ROGUE_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_COHERENT_SHIFT) |
 29		(2U << ROGUE_CR_AXI_ACE_LITE_CONFIGURATION_AWCACHE_COHERENT_SHIFT) |
 30		(2U << ROGUE_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_COHERENT_SHIFT) |
 31		(2U << ROGUE_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_CACHE_MAINTENANCE_SHIFT);
 32
 33	pvr_cr_write64(pvr_dev, ROGUE_CR_AXI_ACE_LITE_CONFIGURATION, reg_val);
 34}
 35
 36static void
 37rogue_bif_init(struct pvr_device *pvr_dev)
 38{
 39	dma_addr_t pc_dma_addr;
 40	u64 pc_addr;
 41
 42	/* Acquire the address of the Kernel Page Catalogue. */
 43	pc_dma_addr = pvr_vm_get_page_table_root_addr(pvr_dev->kernel_vm_ctx);
 44
 45	/* Write the kernel catalogue base. */
 46	pc_addr = ((((u64)pc_dma_addr >> ROGUE_CR_BIF_CAT_BASE0_ADDR_ALIGNSHIFT)
 47		    << ROGUE_CR_BIF_CAT_BASE0_ADDR_SHIFT) &
 48		   ~ROGUE_CR_BIF_CAT_BASE0_ADDR_CLRMSK);
 49
 50	pvr_cr_write64(pvr_dev, BIF_CAT_BASEX(MMU_CONTEXT_MAPPING_FWPRIV),
 51		       pc_addr);
 52
 53	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_RISCV) {
 54		pc_addr = (((u64)pc_dma_addr >> ROGUE_CR_FWCORE_MEM_CAT_BASE0_ADDR_ALIGNSHIFT)
 55			   << ROGUE_CR_FWCORE_MEM_CAT_BASE0_ADDR_SHIFT) &
 56			  ~ROGUE_CR_FWCORE_MEM_CAT_BASE0_ADDR_CLRMSK;
 57
 58		pvr_cr_write64(pvr_dev, FWCORE_MEM_CAT_BASEX(MMU_CONTEXT_MAPPING_FWPRIV), pc_addr);
 59	}
 60}
 61
 62static int
 63rogue_slc_init(struct pvr_device *pvr_dev)
 64{
 65	u16 slc_cache_line_size_bits;
 66	u32 reg_val;
 67	int err;
 68
 69	/*
 70	 * SLC Misc control.
 71	 *
 72	 * Note: This is a 64bit register and we set only the lower 32bits
 73	 *       leaving the top 32bits (ROGUE_CR_SLC_CTRL_MISC_SCRAMBLE_BITS)
 74	 *       unchanged from the HW default.
 75	 */
 76	reg_val = (pvr_cr_read32(pvr_dev, ROGUE_CR_SLC_CTRL_MISC) &
 77		      ROGUE_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN) |
 78		     ROGUE_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1;
 79
 80	err = PVR_FEATURE_VALUE(pvr_dev, slc_cache_line_size_bits, &slc_cache_line_size_bits);
 81	if (err)
 82		return err;
 83
 84	/* Bypass burst combiner if SLC line size is smaller than 1024 bits. */
 85	if (slc_cache_line_size_bits < 1024)
 86		reg_val |= ROGUE_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_EN;
 87
 88	if (PVR_HAS_QUIRK(pvr_dev, 71242) && !PVR_HAS_FEATURE(pvr_dev, gpu_multicore_support))
 89		reg_val |= ROGUE_CR_SLC_CTRL_MISC_LAZYWB_OVERRIDE_EN;
 90
 91	pvr_cr_write32(pvr_dev, ROGUE_CR_SLC_CTRL_MISC, reg_val);
 92
 93	return 0;
 94}
 95
 96/**
 97 * pvr_fw_start() - Start FW processor and boot firmware
 98 * @pvr_dev: Target PowerVR device.
 99 *
100 * Returns:
101 *  * 0 on success, or
102 *  * Any error returned by rogue_slc_init().
103 */
104int
105pvr_fw_start(struct pvr_device *pvr_dev)
106{
107	bool has_reset2 = PVR_HAS_FEATURE(pvr_dev, xe_tpu2);
108	u64 soft_reset_mask;
109	int err;
110
111	if (PVR_HAS_FEATURE(pvr_dev, pbe2_in_xe))
112		soft_reset_mask = ROGUE_CR_SOFT_RESET__PBE2_XE__MASKFULL;
113	else
114		soft_reset_mask = ROGUE_CR_SOFT_RESET_MASKFULL;
115
116	if (PVR_HAS_FEATURE(pvr_dev, sys_bus_secure_reset)) {
117		/*
118		 * Disable the default sys_bus_secure protection to perform
119		 * minimal setup.
120		 */
121		pvr_cr_write32(pvr_dev, ROGUE_CR_SYS_BUS_SECURE, 0);
122		(void)pvr_cr_read32(pvr_dev, ROGUE_CR_SYS_BUS_SECURE); /* Fence write */
123	}
124
125	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_RISCV)
126		pvr_cr_write32(pvr_dev, ROGUE_CR_FWCORE_BOOT, 0);
127
128	/* Set Rogue in soft-reset. */
129	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, soft_reset_mask);
130	if (has_reset2)
131		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET2, ROGUE_CR_SOFT_RESET2_MASKFULL);
132
133	/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline. */
134	(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET);
135	if (has_reset2)
136		(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET2);
137
138	/* Take Rascal and Dust out of reset. */
139	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET,
140		       soft_reset_mask ^ ROGUE_CR_SOFT_RESET_RASCALDUSTS_EN);
141	if (has_reset2)
142		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET2, 0);
143
144	(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET);
145	if (has_reset2)
146		(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET2);
147
148	/* Take everything out of reset but the FW processor. */
149	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, ROGUE_CR_SOFT_RESET_GARTEN_EN);
150	if (has_reset2)
151		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET2, 0);
152
153	(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET);
154	if (has_reset2)
155		(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET2);
156
157	err = rogue_slc_init(pvr_dev);
158	if (err)
159		goto err_reset;
160
161	/* Initialise Firmware wrapper. */
162	pvr_dev->fw_dev.defs->wrapper_init(pvr_dev);
163
164	/* We must init the AXI-ACE interface before first BIF transaction. */
165	rogue_axi_ace_list_init(pvr_dev);
166
167	if (pvr_dev->fw_dev.processor_type != PVR_FW_PROCESSOR_TYPE_MIPS) {
168		/* Initialise BIF. */
169		rogue_bif_init(pvr_dev);
170	}
171
172	/* Need to wait for at least 16 cycles before taking the FW processor out of reset ... */
173	udelay(3);
174
175	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, 0x0);
176	(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET);
177
178	/* ... and afterwards. */
179	udelay(3);
180
181	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_RISCV) {
182		/* Boot the FW. */
183		pvr_cr_write32(pvr_dev, ROGUE_CR_FWCORE_BOOT, 1);
184		udelay(3);
185	}
186
187	return 0;
188
189err_reset:
190	/* Put everything back into soft-reset. */
191	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, soft_reset_mask);
192
193	return err;
194}
195
196/**
197 * pvr_fw_stop() - Stop FW processor
198 * @pvr_dev: Target PowerVR device.
199 *
200 * Returns:
201 *  * 0 on success, or
202 *  * Any error returned by pvr_cr_poll_reg32().
203 */
204int
205pvr_fw_stop(struct pvr_device *pvr_dev)
206{
207	const u32 sidekick_idle_mask = ROGUE_CR_SIDEKICK_IDLE_MASKFULL &
208				       ~(ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN |
209					 ROGUE_CR_SIDEKICK_IDLE_SOCIF_EN |
210					 ROGUE_CR_SIDEKICK_IDLE_HOSTIF_EN);
211	bool skip_garten_idle = false;
212	u32 reg_value;
213	int err;
214
215	/*
216	 * Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper.
217	 * For cores with the LAYOUT_MARS feature, SIDEKICK would have been
218	 * powered down by the FW.
219	 */
220	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
221				sidekick_idle_mask, POLL_TIMEOUT_USEC);
222	if (err)
223		return err;
224
225	/* Unset MTS DM association with threads. */
226	pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD0_DM_ASSOC,
227		       ROGUE_CR_MTS_INTCTX_THREAD0_DM_ASSOC_MASKFULL &
228		       ROGUE_CR_MTS_INTCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK);
229	pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC,
230		       ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_MASKFULL &
231		       ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK);
232	pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC,
233		       ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL &
234		       ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK);
235	pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC,
236		       ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL &
237		       ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK);
238
239	/* Extra Idle checks. */
240	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIF_STATUS_MMU, 0,
241				ROGUE_CR_BIF_STATUS_MMU_MASKFULL,
242				POLL_TIMEOUT_USEC);
243	if (err)
244		return err;
245
246	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIFPM_STATUS_MMU, 0,
247				ROGUE_CR_BIFPM_STATUS_MMU_MASKFULL,
248				POLL_TIMEOUT_USEC);
249	if (err)
250		return err;
251
252	if (!PVR_HAS_FEATURE(pvr_dev, xt_top_infrastructure)) {
253		err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIF_READS_EXT_STATUS, 0,
254					ROGUE_CR_BIF_READS_EXT_STATUS_MASKFULL,
255					POLL_TIMEOUT_USEC);
256		if (err)
257			return err;
258	}
259
260	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIFPM_READS_EXT_STATUS, 0,
261				ROGUE_CR_BIFPM_READS_EXT_STATUS_MASKFULL,
262				POLL_TIMEOUT_USEC);
263	if (err)
264		return err;
265
266	err = pvr_cr_poll_reg64(pvr_dev, ROGUE_CR_SLC_STATUS1, 0,
267				ROGUE_CR_SLC_STATUS1_MASKFULL,
268				POLL_TIMEOUT_USEC);
269	if (err)
270		return err;
271
272	/*
273	 * Wait for SLC to signal IDLE.
274	 * For cores with the LAYOUT_MARS feature, SLC would have been powered
275	 * down by the FW.
276	 */
277	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE,
278				ROGUE_CR_SLC_IDLE_MASKFULL,
279				ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC);
280	if (err)
281		return err;
282
283	/*
284	 * Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper.
285	 * For cores with the LAYOUT_MARS feature, SIDEKICK would have been powered
286	 * down by the FW.
287	 */
288	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,
289				sidekick_idle_mask, POLL_TIMEOUT_USEC);
290	if (err)
291		return err;
292
293	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_META) {
294		err = pvr_meta_cr_read32(pvr_dev, META_CR_TxVECINT_BHALT, &reg_value);
295		if (err)
296			return err;
297
298		/*
299		 * Wait for Sidekick/Jones to signal IDLE including the Garten
300		 * Wrapper if there is no debugger attached (TxVECINT_BHALT =
301		 * 0x0).
302		 */
303		if (reg_value)
304			skip_garten_idle = true;
305	}
306
307	if (!skip_garten_idle) {
308		err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE,
309					ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
310					ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,
311					POLL_TIMEOUT_USEC);
312		if (err)
313			return err;
314	}
315
316	if (PVR_HAS_FEATURE(pvr_dev, pbe2_in_xe))
317		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET,
318			       ROGUE_CR_SOFT_RESET__PBE2_XE__MASKFULL);
319	else
320		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, ROGUE_CR_SOFT_RESET_MASKFULL);
321
322	return 0;
323}
~/ Read-only file preview.