brintos

brintos / linux-shallow public Read only

0
0
Text · 9.1 KiB · 36cec22 Raw
307 lines · c
1// SPDX-License-Identifier: GPL-2.0-only OR MIT2/* 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 100000018 19static void20rogue_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 void37rogue_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 54static int55rogue_slc_init(struct pvr_device *pvr_dev)56{57	u16 slc_cache_line_size_bits;58	u32 reg_val;59	int err;60 61	/*62	 * SLC Misc control.63	 *64	 * Note: This is a 64bit register and we set only the lower 32bits65	 *       leaving the top 32bits (ROGUE_CR_SLC_CTRL_MISC_SCRAMBLE_BITS)66	 *       unchanged from the HW default.67	 */68	reg_val = (pvr_cr_read32(pvr_dev, ROGUE_CR_SLC_CTRL_MISC) &69		      ROGUE_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN) |70		     ROGUE_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1;71 72	err = PVR_FEATURE_VALUE(pvr_dev, slc_cache_line_size_bits, &slc_cache_line_size_bits);73	if (err)74		return err;75 76	/* Bypass burst combiner if SLC line size is smaller than 1024 bits. */77	if (slc_cache_line_size_bits < 1024)78		reg_val |= ROGUE_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_EN;79 80	if (PVR_HAS_QUIRK(pvr_dev, 71242) && !PVR_HAS_FEATURE(pvr_dev, gpu_multicore_support))81		reg_val |= ROGUE_CR_SLC_CTRL_MISC_LAZYWB_OVERRIDE_EN;82 83	pvr_cr_write32(pvr_dev, ROGUE_CR_SLC_CTRL_MISC, reg_val);84 85	return 0;86}87 88/**89 * pvr_fw_start() - Start FW processor and boot firmware90 * @pvr_dev: Target PowerVR device.91 *92 * Returns:93 *  * 0 on success, or94 *  * Any error returned by rogue_slc_init().95 */96int97pvr_fw_start(struct pvr_device *pvr_dev)98{99	bool has_reset2 = PVR_HAS_FEATURE(pvr_dev, xe_tpu2);100	u64 soft_reset_mask;101	int err;102 103	if (PVR_HAS_FEATURE(pvr_dev, pbe2_in_xe))104		soft_reset_mask = ROGUE_CR_SOFT_RESET__PBE2_XE__MASKFULL;105	else106		soft_reset_mask = ROGUE_CR_SOFT_RESET_MASKFULL;107 108	if (PVR_HAS_FEATURE(pvr_dev, sys_bus_secure_reset)) {109		/*110		 * Disable the default sys_bus_secure protection to perform111		 * minimal setup.112		 */113		pvr_cr_write32(pvr_dev, ROGUE_CR_SYS_BUS_SECURE, 0);114		(void)pvr_cr_read32(pvr_dev, ROGUE_CR_SYS_BUS_SECURE); /* Fence write */115	}116 117	/* Set Rogue in soft-reset. */118	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, soft_reset_mask);119	if (has_reset2)120		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET2, ROGUE_CR_SOFT_RESET2_MASKFULL);121 122	/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline. */123	(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET);124	if (has_reset2)125		(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET2);126 127	/* Take Rascal and Dust out of reset. */128	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET,129		       soft_reset_mask ^ ROGUE_CR_SOFT_RESET_RASCALDUSTS_EN);130	if (has_reset2)131		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET2, 0);132 133	(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET);134	if (has_reset2)135		(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET2);136 137	/* Take everything out of reset but the FW processor. */138	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, ROGUE_CR_SOFT_RESET_GARTEN_EN);139	if (has_reset2)140		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET2, 0);141 142	(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET);143	if (has_reset2)144		(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET2);145 146	err = rogue_slc_init(pvr_dev);147	if (err)148		goto err_reset;149 150	/* Initialise Firmware wrapper. */151	pvr_dev->fw_dev.defs->wrapper_init(pvr_dev);152 153	/* We must init the AXI-ACE interface before first BIF transaction. */154	rogue_axi_ace_list_init(pvr_dev);155 156	if (pvr_dev->fw_dev.processor_type != PVR_FW_PROCESSOR_TYPE_MIPS) {157		/* Initialise BIF. */158		rogue_bif_init(pvr_dev);159	}160 161	/* Need to wait for at least 16 cycles before taking the FW processor out of reset ... */162	udelay(3);163 164	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, 0x0);165	(void)pvr_cr_read64(pvr_dev, ROGUE_CR_SOFT_RESET);166 167	/* ... and afterwards. */168	udelay(3);169 170	return 0;171 172err_reset:173	/* Put everything back into soft-reset. */174	pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, soft_reset_mask);175 176	return err;177}178 179/**180 * pvr_fw_stop() - Stop FW processor181 * @pvr_dev: Target PowerVR device.182 *183 * Returns:184 *  * 0 on success, or185 *  * Any error returned by pvr_cr_poll_reg32().186 */187int188pvr_fw_stop(struct pvr_device *pvr_dev)189{190	const u32 sidekick_idle_mask = ROGUE_CR_SIDEKICK_IDLE_MASKFULL &191				       ~(ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN |192					 ROGUE_CR_SIDEKICK_IDLE_SOCIF_EN |193					 ROGUE_CR_SIDEKICK_IDLE_HOSTIF_EN);194	bool skip_garten_idle = false;195	u32 reg_value;196	int err;197 198	/*199	 * Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper.200	 * For cores with the LAYOUT_MARS feature, SIDEKICK would have been201	 * powered down by the FW.202	 */203	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,204				sidekick_idle_mask, POLL_TIMEOUT_USEC);205	if (err)206		return err;207 208	/* Unset MTS DM association with threads. */209	pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD0_DM_ASSOC,210		       ROGUE_CR_MTS_INTCTX_THREAD0_DM_ASSOC_MASKFULL &211		       ROGUE_CR_MTS_INTCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK);212	pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC,213		       ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_MASKFULL &214		       ROGUE_CR_MTS_BGCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK);215	pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC,216		       ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL &217		       ROGUE_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK);218	pvr_cr_write32(pvr_dev, ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC,219		       ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL &220		       ROGUE_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK);221 222	/* Extra Idle checks. */223	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIF_STATUS_MMU, 0,224				ROGUE_CR_BIF_STATUS_MMU_MASKFULL,225				POLL_TIMEOUT_USEC);226	if (err)227		return err;228 229	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIFPM_STATUS_MMU, 0,230				ROGUE_CR_BIFPM_STATUS_MMU_MASKFULL,231				POLL_TIMEOUT_USEC);232	if (err)233		return err;234 235	if (!PVR_HAS_FEATURE(pvr_dev, xt_top_infrastructure)) {236		err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIF_READS_EXT_STATUS, 0,237					ROGUE_CR_BIF_READS_EXT_STATUS_MASKFULL,238					POLL_TIMEOUT_USEC);239		if (err)240			return err;241	}242 243	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_BIFPM_READS_EXT_STATUS, 0,244				ROGUE_CR_BIFPM_READS_EXT_STATUS_MASKFULL,245				POLL_TIMEOUT_USEC);246	if (err)247		return err;248 249	err = pvr_cr_poll_reg64(pvr_dev, ROGUE_CR_SLC_STATUS1, 0,250				ROGUE_CR_SLC_STATUS1_MASKFULL,251				POLL_TIMEOUT_USEC);252	if (err)253		return err;254 255	/*256	 * Wait for SLC to signal IDLE.257	 * For cores with the LAYOUT_MARS feature, SLC would have been powered258	 * down by the FW.259	 */260	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SLC_IDLE,261				ROGUE_CR_SLC_IDLE_MASKFULL,262				ROGUE_CR_SLC_IDLE_MASKFULL, POLL_TIMEOUT_USEC);263	if (err)264		return err;265 266	/*267	 * Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper.268	 * For cores with the LAYOUT_MARS feature, SIDEKICK would have been powered269	 * down by the FW.270	 */271	err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE, sidekick_idle_mask,272				sidekick_idle_mask, POLL_TIMEOUT_USEC);273	if (err)274		return err;275 276	if (pvr_dev->fw_dev.processor_type == PVR_FW_PROCESSOR_TYPE_META) {277		err = pvr_meta_cr_read32(pvr_dev, META_CR_TxVECINT_BHALT, &reg_value);278		if (err)279			return err;280 281		/*282		 * Wait for Sidekick/Jones to signal IDLE including the Garten283		 * Wrapper if there is no debugger attached (TxVECINT_BHALT =284		 * 0x0).285		 */286		if (reg_value)287			skip_garten_idle = true;288	}289 290	if (!skip_garten_idle) {291		err = pvr_cr_poll_reg32(pvr_dev, ROGUE_CR_SIDEKICK_IDLE,292					ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,293					ROGUE_CR_SIDEKICK_IDLE_GARTEN_EN,294					POLL_TIMEOUT_USEC);295		if (err)296			return err;297	}298 299	if (PVR_HAS_FEATURE(pvr_dev, pbe2_in_xe))300		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET,301			       ROGUE_CR_SOFT_RESET__PBE2_XE__MASKFULL);302	else303		pvr_cr_write64(pvr_dev, ROGUE_CR_SOFT_RESET, ROGUE_CR_SOFT_RESET_MASKFULL);304 305	return 0;306}307