blob: dbbb9259e5d561a59fbe9a36ca497208b867b288 [file] [edit]
/*************************************************************************/ /*!
@File
@Title Device specific start/stop routines
@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@Description Device specific start/stop routines
@License Dual MIT/GPLv2
The contents of this file are subject to the MIT license as set out below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.
This License is also included in this distribution in the file called
"MIT-COPYING".
EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ /**************************************************************************/
/* The routines implemented here are built on top of an abstraction layer to
* hide DDK/OS-specific details in case they are used outside of the DDK
* (e.g. when trusted device is enabled).
* Any new dependency should be added to rgxlayer.h.
* Any new code should be built on top of the existing abstraction layer,
* which should be extended when necessary. */
#include "rgxstartstop.h"
#if defined(SUPPORT_SHARED_SLC)
#include "rgxapi_km.h"
#endif
#include "rgxdevice.h"
#include "km/rgxdefs_km.h"
#define SOC_FEATURE_STRICT_SAME_ADDRESS_WRITE_ORDERING
/*!
*******************************************************************************
@Function RGXEnableClocks
@Description Enable RGX Clocks
@Input hPrivate : Implementation specific data
@Return void
******************************************************************************/
static void RGXEnableClocks(const void *hPrivate)
{
RGXCommentLog(hPrivate, "RGX clock: use default (automatic clock gating)");
}
static PVRSRV_ERROR RGXWriteMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
{
PVRSRV_ERROR eError = PVRSRV_OK;
/* Wait for Slave Port to be Ready */
eError = RGXPollReg32(hPrivate,
RGX_CR_META_SP_MSLVCTRL1,
RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
if (eError != PVRSRV_OK) return eError;
/* Issue a Write */
RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0, ui32RegAddr);
(void)RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0); /* Fence write */
RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVDATAT, ui32RegValue);
(void)RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVDATAT); /* Fence write */
return eError;
}
static PVRSRV_ERROR RGXReadMetaRegThroughSP(const void *hPrivate,
IMG_UINT32 ui32RegAddr,
IMG_UINT32* ui32RegValue)
{
PVRSRV_ERROR eError = PVRSRV_OK;
/* Wait for Slave Port to be Ready */
eError = RGXPollReg32(hPrivate,
RGX_CR_META_SP_MSLVCTRL1,
RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
if (eError != PVRSRV_OK) return eError;
/* Issue a Read */
RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0, ui32RegAddr | RGX_CR_META_SP_MSLVCTRL0_RD_EN);
(void)RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0); /* Fence write */
/* Wait for Slave Port to be Ready */
eError = RGXPollReg32(hPrivate,
RGX_CR_META_SP_MSLVCTRL1,
RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
if (eError != PVRSRV_OK) return eError;
#if !defined(NO_HARDWARE)
*ui32RegValue = RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVDATAX);
#else
*ui32RegValue = 0xFFFFFFFF;
#endif
return eError;
}
static PVRSRV_ERROR RGXWriteMetaCoreRegThoughSP(const void *hPrivate,
IMG_UINT32 ui32CoreReg,
IMG_UINT32 ui32Value)
{
IMG_UINT32 i = 0;
RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXUXXRXDT_OFFSET, ui32Value);
RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXUXXRXRQ_OFFSET, ui32CoreReg & ~META_CR_TXUXXRXRQ_RDnWR_BIT);
do
{
RGXReadMetaRegThroughSP(hPrivate, META_CR_TXUXXRXRQ_OFFSET, &ui32Value);
} while (((ui32Value & META_CR_TXUXXRXRQ_DREADY_BIT) != META_CR_TXUXXRXRQ_DREADY_BIT) && (i++ < 1000));
if (i == 1000)
{
RGXCommentLog(hPrivate, "RGXWriteMetaCoreRegThoughSP: Timeout");
return PVRSRV_ERROR_TIMEOUT;
}
return PVRSRV_OK;
}
static PVRSRV_ERROR RGXStartFirmware(const void *hPrivate)
{
PVRSRV_ERROR eError;
/* Give privilege to debug and slave port */
RGXWriteMetaRegThroughSP(hPrivate, META_CR_SYSC_JTAG_THREAD, META_CR_SYSC_JTAG_THREAD_PRIV_EN);
/* Point Meta to the bootloader address, global (uncached) range */
eError = RGXWriteMetaCoreRegThoughSP(hPrivate,
PC_ACCESS(0),
RGXFW_BOOTLDR_META_ADDR | META_MEM_GLOBAL_RANGE_BIT);
if (eError != PVRSRV_OK)
{
RGXCommentLog(hPrivate, "RGXStart: RGX Firmware Slave boot Start failed!");
return eError;
}
/* Enable minim encoding */
RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXPRIVEXT, META_CR_TXPRIVEXT_MINIM_EN);
/* Enable Meta thread */
RGXWriteMetaRegThroughSP(hPrivate, META_CR_T0ENABLE_OFFSET, META_CR_TXENABLE_ENABLE_BIT);
return PVRSRV_OK;
}
/*!
*******************************************************************************
@Function RGXInitMetaProcWrapper
@Description Configures the hardware wrapper of the META processor
@Input hPrivate : Implementation specific data
@Return void
******************************************************************************/
static void RGXInitMetaProcWrapper(const void *hPrivate)
{
IMG_UINT64 ui64GartenConfig;
/* Set Garten IDLE to META idle and Set the Garten Wrapper BIF Fence address */
/* Garten IDLE bit controlled by META */
ui64GartenConfig = RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META;
/* The fence addr is set at the fw init sequence */
if (RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
{
/* Set PC = 0 for fences */
ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PC_BASE_CLRMSK;
ui64GartenConfig |= (IMG_UINT64)MMU_CONTEXT_MAPPING_FWPRIV
<< RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PC_BASE_SHIFT;
}
else
{
/* Set PC = 0 for fences */
ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_CLRMSK;
ui64GartenConfig |= (IMG_UINT64)MMU_CONTEXT_MAPPING_FWPRIV
<< RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_SHIFT;
/* Set SLC DM=META */
ui64GartenConfig |= ((IMG_UINT64) RGXFW_SEGMMU_META_BIFDM_ID) << RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_DM_SHIFT;
}
RGXCommentLog(hPrivate, "RGXStart: Configure META wrapper");
RGXWriteReg64(hPrivate, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, ui64GartenConfig);
}
/*!
*******************************************************************************
@Function RGXInitMipsProcWrapper
@Description Configures the hardware wrapper of the MIPS processor
@Input hPrivate : Implementation specific data
@Return void
******************************************************************************/
static void RGXInitMipsProcWrapper(const void *hPrivate)
{
IMG_DEV_PHYADDR sPhyAddr;
IMG_UINT64 ui64RemapSettings = RGXMIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE; /* Same for all remap registers */
RGXCommentLog(hPrivate, "RGXStart: Configure MIPS wrapper");
/*
* MIPS wrapper (registers transaction ID and ISA mode) setup
*/
RGXCommentLog(hPrivate, "RGXStart: Write wrapper config register");
if (RGXGetDevicePhysBusWidth(hPrivate) > 32)
{
RGXWriteReg32(hPrivate,
RGX_CR_MIPS_WRAPPER_CONFIG,
(RGXMIPSFW_REGISTERS_VIRTUAL_BASE >>
RGXMIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN) |
RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS);
}
else
{
RGXAcquireGPURegsAddr(hPrivate, &sPhyAddr);
RGXMIPSWrapperConfig(hPrivate,
RGX_CR_MIPS_WRAPPER_CONFIG,
sPhyAddr.uiAddr,
RGXMIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN,
RGX_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS);
}
/*
* Boot remap setup
*/
RGXAcquireBootRemapAddr(hPrivate, &sPhyAddr);
#if defined(SUPPORT_TRUSTED_DEVICE)
/* Do not mark accesses to a FW code remap region as DRM accesses */
ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK;
#endif
#if defined(MIPS_FW_CODE_OSID)
ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_OS_ID_CLRMSK;
ui64RemapSettings |= MIPS_FW_CODE_OSID << RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_OS_ID_SHIFT;
#endif
RGXCommentLog(hPrivate, "RGXStart: Write boot remap registers");
RGXBootRemapConfig(hPrivate,
RGX_CR_MIPS_ADDR_REMAP1_CONFIG1,
RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN | RGX_CR_MIPS_ADDR_REMAP1_CONFIG1_MODE_ENABLE_EN,
RGX_CR_MIPS_ADDR_REMAP1_CONFIG2,
sPhyAddr.uiAddr,
~RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_CLRMSK,
ui64RemapSettings);
if (RGX_DEVICE_HAS_BRN(hPrivate, 63553))
{
IMG_BOOL bPhysBusAbove32Bit = RGXGetDevicePhysBusWidth(hPrivate) > 32;
IMG_BOOL bDevicePA0IsValid = RGXDevicePA0IsValid(hPrivate);
/* WA always required on 36 bit cores, to avoid continuous unmapped memory accesses to address 0x0 */
if (bPhysBusAbove32Bit || !bDevicePA0IsValid)
{
RGXCodeRemapConfig(hPrivate,
RGX_CR_MIPS_ADDR_REMAP5_CONFIG1,
0x0 | RGX_CR_MIPS_ADDR_REMAP5_CONFIG1_MODE_ENABLE_EN,
RGX_CR_MIPS_ADDR_REMAP5_CONFIG2,
sPhyAddr.uiAddr,
~RGX_CR_MIPS_ADDR_REMAP5_CONFIG2_ADDR_OUT_CLRMSK,
ui64RemapSettings);
}
}
/*
* Data remap setup
*/
RGXAcquireDataRemapAddr(hPrivate, &sPhyAddr);
#if defined(SUPPORT_TRUSTED_DEVICE)
if (RGXGetDevicePhysBusWidth(hPrivate) > 32)
{
/* Remapped private data in secure memory */
ui64RemapSettings |= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_EN;
}
else
{
/* Remapped data in non-secure memory */
ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK;
}
#endif
#if defined(MIPS_FW_CODE_OSID)
ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_OS_ID_CLRMSK;
#endif
RGXCommentLog(hPrivate, "RGXStart: Write data remap registers");
RGXDataRemapConfig(hPrivate,
RGX_CR_MIPS_ADDR_REMAP2_CONFIG1,
RGXMIPSFW_DATA_REMAP_PHYS_ADDR_IN | RGX_CR_MIPS_ADDR_REMAP2_CONFIG1_MODE_ENABLE_EN,
RGX_CR_MIPS_ADDR_REMAP2_CONFIG2,
sPhyAddr.uiAddr,
~RGX_CR_MIPS_ADDR_REMAP2_CONFIG2_ADDR_OUT_CLRMSK,
ui64RemapSettings);
/*
* Code remap setup
*/
RGXAcquireCodeRemapAddr(hPrivate, &sPhyAddr);
#if defined(SUPPORT_TRUSTED_DEVICE)
/* Do not mark accesses to a FW code remap region as DRM accesses */
ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK;
#endif
#if defined(MIPS_FW_CODE_OSID)
ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_OS_ID_CLRMSK;
ui64RemapSettings |= MIPS_FW_CODE_OSID << RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_OS_ID_SHIFT;
#endif
RGXCommentLog(hPrivate, "RGXStart: Write exceptions remap registers");
RGXCodeRemapConfig(hPrivate,
RGX_CR_MIPS_ADDR_REMAP3_CONFIG1,
RGXMIPSFW_CODE_REMAP_PHYS_ADDR_IN | RGX_CR_MIPS_ADDR_REMAP3_CONFIG1_MODE_ENABLE_EN,
RGX_CR_MIPS_ADDR_REMAP3_CONFIG2,
sPhyAddr.uiAddr,
~RGX_CR_MIPS_ADDR_REMAP3_CONFIG2_ADDR_OUT_CLRMSK,
ui64RemapSettings);
if (RGXGetDevicePhysBusWidth(hPrivate) == 32)
{
/*
* Trampoline remap setup
*/
RGXAcquireTrampolineRemapAddr(hPrivate, &sPhyAddr);
ui64RemapSettings = RGXMIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE;
#if defined(SUPPORT_TRUSTED_DEVICE)
/* Remapped data in non-secure memory */
ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK;
#endif
#if defined(MIPS_FW_CODE_OSID)
ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_OS_ID_CLRMSK;
#endif
RGXCommentLog(hPrivate, "RGXStart: Write trampoline remap registers");
RGXTrampolineRemapConfig(hPrivate,
RGX_CR_MIPS_ADDR_REMAP4_CONFIG1,
sPhyAddr.uiAddr | RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_MODE_ENABLE_EN,
RGX_CR_MIPS_ADDR_REMAP4_CONFIG2,
RGXMIPSFW_TRAMPOLINE_TARGET_PHYS_ADDR,
~RGX_CR_MIPS_ADDR_REMAP4_CONFIG2_ADDR_OUT_CLRMSK,
ui64RemapSettings);
}
/* Garten IDLE bit controlled by MIPS */
RGXCommentLog(hPrivate, "RGXStart: Set GARTEN_IDLE type to MIPS");
RGXWriteReg64(hPrivate, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META);
/* Turn on the EJTAG probe (only useful driver live) */
RGXWriteReg32(hPrivate, RGX_CR_MIPS_DEBUG_CONFIG, 0);
}
/*!
*******************************************************************************
@Function RGXInitRiscvProcWrapper
@Description Configures the hardware wrapper of the RISCV processor
@Input hPrivate : Implementation specific data
@Return void
******************************************************************************/
static void RGXInitRiscvProcWrapper(const void *hPrivate)
{
IMG_DEV_VIRTADDR sTmp;
RGXCommentLog(hPrivate, "RGXStart: Configure RISCV wrapper");
RGXCommentLog(hPrivate, "RGXStart: Write boot code remap");
RGXAcquireBootCodeAddr(hPrivate, &sTmp);
RGXWriteReg64(hPrivate,
RGXRISCVFW_BOOTLDR_CODE_REMAP,
sTmp.uiAddr |
(IMG_UINT64) (RGX_FIRMWARE_RAW_HEAP_SIZE >> TMP_RGX_CR_FWCORE_ADDR_REMAP0_CONFIG_REGION_SIZE_ALIGN)
<< TMP_RGX_CR_FWCORE_ADDR_REMAP0_CONFIG_REGION_SIZE_SHIFT |
(IMG_UINT64) MMU_CONTEXT_MAPPING_FWPRIV << TMP_RGX_CR_FWCORE_ADDR_REMAP0_CONFIG_MMU_CONTEXT_SHIFT |
TMP_RGX_CR_FWCORE_ADDR_REMAP0_CONFIG_FETCH_EN);
RGXCommentLog(hPrivate, "RGXStart: Write boot data remap");
RGXAcquireBootDataAddr(hPrivate, &sTmp);
RGXWriteReg64(hPrivate,
RGXRISCVFW_BOOTLDR_DATA_REMAP,
sTmp.uiAddr |
(IMG_UINT64) (RGX_FIRMWARE_RAW_HEAP_SIZE >> TMP_RGX_CR_FWCORE_ADDR_REMAP0_CONFIG_REGION_SIZE_ALIGN)
<< TMP_RGX_CR_FWCORE_ADDR_REMAP0_CONFIG_REGION_SIZE_SHIFT |
(IMG_UINT64) MMU_CONTEXT_MAPPING_FWPRIV << TMP_RGX_CR_FWCORE_ADDR_REMAP0_CONFIG_MMU_CONTEXT_SHIFT |
TMP_RGX_CR_FWCORE_ADDR_REMAP0_CONFIG_LOAD_STORE_EN);
/* Garten IDLE bit controlled by RISCV */
RGXCommentLog(hPrivate, "RGXStart: Set GARTEN_IDLE type to RISCV");
RGXWriteReg64(hPrivate, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META);
}
/*!
*******************************************************************************
@Function __RGXInitSLC
@Description Initialise RGX SLC
@Input hPrivate : Implementation specific data
@Return void
******************************************************************************/
static void __RGXInitSLC(const void *hPrivate)
{
if (RGX_DEVICE_HAS_FEATURE(hPrivate, S7_CACHE_HIERARCHY))
{
IMG_UINT32 ui32Reg;
IMG_UINT32 ui32RegVal;
/*
* SLC control
*/
ui32Reg = RGX_CR_SLC3_CTRL_MISC;
ui32RegVal = RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_SCRAMBLE_PVR_HASH |
RGX_CR_SLC3_CTRL_MISC_WRITE_COMBINER_EN;
RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
/*
* SLC scramble bits
*/
{
IMG_UINT32 i;
IMG_UINT32 ui32Count=0;
IMG_UINT32 ui32SLCBanks = RGXGetDeviceSLCBanks(hPrivate);
IMG_UINT64 aui64ScrambleValues[4];
IMG_UINT32 aui32ScrambleRegs[] = {
RGX_CR_SLC3_SCRAMBLE,
RGX_CR_SLC3_SCRAMBLE2,
RGX_CR_SLC3_SCRAMBLE3,
RGX_CR_SLC3_SCRAMBLE4
};
if (2 == ui32SLCBanks)
{
aui64ScrambleValues[0] = IMG_UINT64_C(0x6965a99a55696a6a);
aui64ScrambleValues[1] = IMG_UINT64_C(0x6aa9aa66959aaa9a);
aui64ScrambleValues[2] = IMG_UINT64_C(0x9a5665965a99a566);
aui64ScrambleValues[3] = IMG_UINT64_C(0x5aa69596aa66669a);
ui32Count = 4;
}
else if (4 == ui32SLCBanks)
{
aui64ScrambleValues[0] = IMG_UINT64_C(0xc6788d722dd29ce4);
aui64ScrambleValues[1] = IMG_UINT64_C(0x7272e4e11b279372);
aui64ScrambleValues[2] = IMG_UINT64_C(0x87d872d26c6c4be1);
aui64ScrambleValues[3] = IMG_UINT64_C(0xe1b4878d4b36e478);
ui32Count = 4;
}
else if (8 == ui32SLCBanks)
{
aui64ScrambleValues[0] = IMG_UINT64_C(0x859d6569e8fac688);
aui64ScrambleValues[1] = IMG_UINT64_C(0xf285e1eae4299d33);
aui64ScrambleValues[2] = IMG_UINT64_C(0x1e1af2be3c0aa447);
ui32Count = 3;
}
for (i = 0; i < ui32Count; i++)
{
IMG_UINT32 ui32Reg = aui32ScrambleRegs[i];
IMG_UINT64 ui64Value = aui64ScrambleValues[i];
RGXWriteReg64(hPrivate, ui32Reg, ui64Value);
}
}
{
/* Disable the forced SLC coherency which the hardware enables for compatibility with older pdumps */
RGXCommentLog(hPrivate, "Disable forced SLC coherency");
RGXWriteReg64(hPrivate, RGX_CR_GARTEN_SLC, 0);
}
}
else
{
IMG_UINT32 ui32Reg;
IMG_UINT32 ui32RegVal;
IMG_UINT64 ui64RegVal;
IMG_UINT32 ui32SLCSize = RGXGetDeviceSLCSize(hPrivate);
/*
* SLC Bypass control
*/
ui32Reg = RGX_CR_SLC_CTRL_BYPASS;
ui64RegVal = 0;
if (RGX_DEVICE_HAS_FEATURE(hPrivate, SLCSIZE8) ||
RGX_DEVICE_HAS_BRN(hPrivate, 61450))
{
RGXCommentLog(hPrivate, "Bypass SLC for IPF_OBJ and IPF_CPF");
ui64RegVal |= (IMG_UINT64) RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_OBJ_EN |
(IMG_UINT64) RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_EN;
}
if (ui32SLCSize < RGX_TPU_CACHED_SLC_SIZE_THRESHOLD)
{
/* Bypass SLC for textures if the SLC size is less than the threshold. */
RGXCommentLog(hPrivate, "Bypass SLC for TPU");
ui64RegVal |= (IMG_UINT64) RGX_CR_SLC_CTRL_BYPASS_REQ_TPU_EN;
}
if (ui64RegVal != 0)
{
RGXReadModifyWriteReg64(hPrivate, ui32Reg, ui64RegVal, ~ui64RegVal);
}
if (RGX_DEVICE_HAS_FEATURE(hPrivate, XE_MEMORY_HIERARCHY) && (ui32SLCSize > RGX_TCU_CACHED_SLC_SIZE_THRESHOLD))
{
/* The default for the TCU bit is 1 and we want to knock it down,
* which is not possible as part of the rmw above. So, repeat
* the rmw here OR'ing a value of 0.
*/
RGXReadModifyWriteReg64(hPrivate, RGX_CR_SLC_CTRL_BYPASS, 0, RGX_CR_SLC_CTRL_BYPASS_REQ_TCU_CLRMSK);
}
/*
* SLC Misc control.
*
* Note: This is a 64bit register and we set only the lower 32bits leaving the top
* 32bits (RGX_CR_SLC_CTRL_MISC_SCRAMBLE_BITS) unchanged from the HW default.
*/
ui32Reg = RGX_CR_SLC_CTRL_MISC;
ui32RegVal = (RGXReadReg32(hPrivate, ui32Reg) & RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN) |
RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1;
if (RGX_DEVICE_HAS_BRN(hPrivate, 60084))
{
#if !defined(SOC_FEATURE_STRICT_SAME_ADDRESS_WRITE_ORDERING)
ui32RegVal |= RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN;
#else
if (RGX_DEVICE_HAS_ERN(hPrivate, 61389))
{
ui32RegVal |= RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN;
}
#endif
}
/* Bypass burst combiner if SLC line size is smaller than 1024 bits */
if (RGXGetDeviceCacheLineSize(hPrivate) < 1024)
{
ui32RegVal |= RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_EN;
}
RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
}
}
/*!
*******************************************************************************
@Function RGXInitBIF
@Description Initialise RGX BIF
@Input hPrivate : Implementation specific data
@Return void
******************************************************************************/
static void RGXInitBIF(const void *hPrivate)
{
if (!RGX_DEVICE_HAS_FEATURE(hPrivate, MIPS))
{
IMG_DEV_PHYADDR sPCAddr;
/*
* Acquire the address of the Kernel Page Catalogue.
*/
RGXAcquireKernelMMUPC(hPrivate, &sPCAddr);
/*
* Write the kernel catalogue base.
*/
RGXCommentLog(hPrivate, "RGX firmware MMU Page Catalogue");
if (!RGX_DEVICE_HAS_FEATURE(hPrivate, SLC_VIVT))
{
/* Write the cat-base address */
RGXWriteKernelMMUPC64(hPrivate,
RGX_CR_BIF_CAT_BASE0,
RGX_CR_BIF_CAT_BASE0_ADDR_ALIGNSHIFT,
RGX_CR_BIF_CAT_BASE0_ADDR_SHIFT,
((sPCAddr.uiAddr
>> RGX_CR_BIF_CAT_BASE0_ADDR_ALIGNSHIFT)
<< RGX_CR_BIF_CAT_BASE0_ADDR_SHIFT)
& ~RGX_CR_BIF_CAT_BASE0_ADDR_CLRMSK);
if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
{
/* Keep catbase registers in sync */
RGXWriteKernelMMUPC64(hPrivate,
TMP_RGX_CR_FWCORE_MEM_CAT_BASE0,
TMP_RGX_CR_FWCORE_MEM_CAT_BASE0_ADDR_ALIGNSHIFT,
TMP_RGX_CR_FWCORE_MEM_CAT_BASE0_ADDR_SHIFT,
((sPCAddr.uiAddr
>> TMP_RGX_CR_FWCORE_MEM_CAT_BASE0_ADDR_ALIGNSHIFT)
<< TMP_RGX_CR_FWCORE_MEM_CAT_BASE0_ADDR_SHIFT)
& ~TMP_RGX_CR_FWCORE_MEM_CAT_BASE0_ADDR_CLRMSK);
}
/*
* Trusted Firmware boot
*/
#if defined(SUPPORT_TRUSTED_DEVICE)
RGXCommentLog(hPrivate, "RGXInitBIF: Trusted Device enabled");
RGXWriteReg32(hPrivate, RGX_CR_BIF_TRUST, RGX_CR_BIF_TRUST_ENABLE_EN);
#endif
}
else
{
IMG_UINT32 uiPCAddr;
uiPCAddr = (((sPCAddr.uiAddr >> RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT)
<< RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT)
& ~RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_CLRMSK);
/* Set the mapping context */
RGXWriteReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT, MMU_CONTEXT_MAPPING_FWPRIV);
(void)RGXReadReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT); /* Fence write */
/* Write the cat-base address */
RGXWriteKernelMMUPC32(hPrivate,
RGX_CR_MMU_CBASE_MAPPING,
RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT,
RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT,
uiPCAddr);
#if (MMU_CONTEXT_MAPPING_FWIF != MMU_CONTEXT_MAPPING_FWPRIV)
/* Set-up different MMU ID mapping to the same PC used above */
RGXWriteReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT, MMU_CONTEXT_MAPPING_FWIF);
(void)RGXReadReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT); /* Fence write */
RGXWriteKernelMMUPC32(hPrivate,
RGX_CR_MMU_CBASE_MAPPING,
RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT,
RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT,
uiPCAddr);
#endif
}
}
else
{
/*
* Trusted Firmware boot
*/
#if defined(SUPPORT_TRUSTED_DEVICE)
RGXCommentLog(hPrivate, "RGXInitBIF: Trusted Device enabled");
RGXWriteReg32(hPrivate, RGX_CR_BIF_TRUST, RGX_CR_BIF_TRUST_ENABLE_EN);
#endif
}
}
/*!
*******************************************************************************
@Function RGXAXIACELiteInit
@Description Initialise AXI-ACE Lite interface
@Input hPrivate : Implementation specific data
@Return void
******************************************************************************/
static void RGXAXIACELiteInit(const void *hPrivate)
{
IMG_UINT32 ui32RegAddr;
IMG_UINT64 ui64RegVal;
ui32RegAddr = RGX_CR_AXI_ACE_LITE_CONFIGURATION;
/* Setup AXI-ACE config. Set everything to outer cache */
ui64RegVal = (3U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_NON_SNOOPING_SHIFT) |
(3U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_NON_SNOOPING_SHIFT) |
(2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_CACHE_MAINTENANCE_SHIFT) |
(2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWDOMAIN_COHERENT_SHIFT) |
(2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARDOMAIN_COHERENT_SHIFT) |
(2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_AWCACHE_COHERENT_SHIFT) |
(2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_COHERENT_SHIFT) |
(2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_CACHE_MAINTENANCE_SHIFT);
if (RGX_DEVICE_HAS_BRN(hPrivate, 42321))
{
ui64RegVal |= (((IMG_UINT64) 1) << RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITELINEUNIQUE_SHIFT);
}
if (RGX_DEVICE_HAS_BRN(hPrivate, 68186))
{
/* default value for reg_enable_fence_out is zero. Force to 1 to allow core_clk < mem_clk */
ui64RegVal |= (IMG_UINT64)1 << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ENABLE_FENCE_OUT_SHIFT;
}
#if defined(SUPPORT_TRUSTED_DEVICE)
if (RGX_DEVICE_HAS_FEATURE(hPrivate, SLC_VIVT))
{
RGXCommentLog(hPrivate, "OSID 0 and 1 are trusted");
ui64RegVal |= IMG_UINT64_C(0xFC)
<< RGX_CR_AXI_ACE_LITE_CONFIGURATION_OSID_SECURITY_SHIFT;
}
#endif
RGXCommentLog(hPrivate, "Init AXI-ACE interface");
RGXWriteReg64(hPrivate, ui32RegAddr, ui64RegVal);
}
PVRSRV_ERROR RGXStart(const void *hPrivate)
{
PVRSRV_ERROR eError = PVRSRV_OK;
IMG_BOOL bDoFWSlaveBoot;
IMG_CHAR *pcRGXFW_PROCESSOR;
IMG_BOOL bMetaFW;
if (RGX_DEVICE_HAS_FEATURE(hPrivate, MIPS))
{
pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_MIPS;
bMetaFW = IMG_FALSE;
bDoFWSlaveBoot = IMG_FALSE;
}
else if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
{
pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_RISCV;
bMetaFW = IMG_FALSE;
bDoFWSlaveBoot = IMG_FALSE;
}
else
{
pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_META;
bMetaFW = IMG_TRUE;
bDoFWSlaveBoot = RGXDoFWSlaveBoot(hPrivate);
}
if (RGX_DEVICE_HAS_FEATURE(hPrivate, SYS_BUS_SECURE_RESET))
{
/* Disable the default sys_bus_secure protection to perform minimal setup */
RGXCommentLog(hPrivate, "RGXStart: Disable sys_bus_secure");
RGXWriteReg32(hPrivate, RGX_CR_SYS_BUS_SECURE, 0);
(void) RGXReadReg32(hPrivate, RGX_CR_SYS_BUS_SECURE); /* Fence write */
}
#if defined(SUPPORT_SHARED_SLC)
/* When the SLC is shared, the SLC reset is performed by the System layer when calling
* RGXInitSLC (before any device uses it), therefore mask out the SLC bit to avoid
* soft_resetting it here.
*/
#define RGX_CR_SOFT_RESET_ALL (RGX_CR_SOFT_RESET_MASKFULL ^ RGX_CR_SOFT_RESET_SLC_EN)
RGXCommentLog(hPrivate, "RGXStart: Shared SLC (don't reset SLC as part of RGX reset)");
#else
#define RGX_CR_SOFT_RESET_ALL (RGX_CR_SOFT_RESET_MASKFULL)
#endif
if (RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
{
/* Set RGX in soft-reset */
RGXCommentLog(hPrivate, "RGXStart: soft reset assert step 1");
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_DUSTS);
/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET2);
RGXCommentLog(hPrivate, "RGXStart: soft reset assert step 2");
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_JONES_ALL | RGX_S7_SOFT_RESET_DUSTS);
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET2, RGX_S7_SOFT_RESET2);
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET2);
/* Take everything out of reset but the FW processor */
RGXCommentLog(hPrivate, "RGXStart: soft reset de-assert step 1 excluding %s", pcRGXFW_PROCESSOR);
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_DUSTS | RGX_CR_SOFT_RESET_GARTEN_EN);
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET2, 0x0);
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET2);
RGXCommentLog(hPrivate, "RGXStart: soft reset de-assert step 2 excluding %s", pcRGXFW_PROCESSOR);
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
}
else
{
/* Set RGX in soft-reset */
RGXCommentLog(hPrivate, "RGXStart: soft reset everything");
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL);
/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
/* Take Rascal and Dust out of reset */
RGXCommentLog(hPrivate, "RGXStart: Rascal and Dust out of reset");
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL ^ RGX_CR_SOFT_RESET_RASCALDUSTS_EN);
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
/* Take everything out of reset but the FW processor */
RGXCommentLog(hPrivate, "RGXStart: Take everything out of reset but %s", pcRGXFW_PROCESSOR);
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
}
/* Enable clocks */
RGXEnableClocks(hPrivate);
/*
* Initialise SLC.
*/
#if !defined(SUPPORT_SHARED_SLC)
__RGXInitSLC(hPrivate);
#endif
if (bMetaFW)
{
if (bDoFWSlaveBoot)
{
/* Configure META to Slave boot */
RGXCommentLog(hPrivate, "RGXStart: META Slave boot");
RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, 0);
}
else
{
/* Configure META to Master boot */
RGXCommentLog(hPrivate, "RGXStart: META Master boot");
RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, RGX_CR_META_BOOT_MODE_EN);
}
}
/*
* Initialise Firmware wrapper
*/
if (bMetaFW)
{
RGXInitMetaProcWrapper(hPrivate);
}
else if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
{
RGXInitRiscvProcWrapper(hPrivate);
}
else
{
RGXInitMipsProcWrapper(hPrivate);
}
if (RGX_DEVICE_HAS_FEATURE(hPrivate, AXI_ACELITE))
{
/* We must init the AXI-ACE interface before 1st BIF transaction */
RGXAXIACELiteInit(hPrivate);
}
/*
* Initialise BIF.
*/
RGXInitBIF(hPrivate);
RGXCommentLog(hPrivate, "RGXStart: Take %s out of reset", pcRGXFW_PROCESSOR);
/* Need to wait for at least 16 cycles before taking the FW processor out of reset ... */
RGXWaitCycles(hPrivate, 32, 3);
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, 0x0);
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
/* ... and afterwards */
RGXWaitCycles(hPrivate, 32, 3);
if (bMetaFW && bDoFWSlaveBoot)
{
eError = RGXFabricCoherencyTest(hPrivate);
if (eError != PVRSRV_OK) return eError;
RGXCommentLog(hPrivate, "RGXStart: RGX Firmware Slave boot Start");
eError = RGXStartFirmware(hPrivate);
if (eError != PVRSRV_OK) return eError;
}
else
{
RGXCommentLog(hPrivate, "RGXStart: RGX Firmware Master boot Start");
if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
{
RGXWriteReg32(hPrivate, TMP_RGX_CR_FWCORE_BOOT, 1);
RGXWaitCycles(hPrivate, 32, 3);
}
}
#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(SUPPORT_SECURITY_VALIDATION)
RGXCommentLog(hPrivate, "RGXStart: Enable sys_bus_secure");
RGXWriteReg32(hPrivate, RGX_CR_SYS_BUS_SECURE, RGX_CR_SYS_BUS_SECURE_ENABLE_EN);
(void) RGXReadReg32(hPrivate, RGX_CR_SYS_BUS_SECURE); /* Fence write */
#endif
return eError;
}
PVRSRV_ERROR RGXStop(const void *hPrivate)
{
IMG_BOOL bMipsFW = RGX_DEVICE_HAS_FEATURE(hPrivate, MIPS);
IMG_BOOL bRiscvFW = RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR);
IMG_BOOL bMetaFW = !bMipsFW && !bRiscvFW;
PVRSRV_ERROR eError;
RGX_LAYER_PARAMS *psParams;
PVRSRV_RGXDEV_INFO *psDevInfo;
PVR_ASSERT(hPrivate != NULL);
psParams = (RGX_LAYER_PARAMS*)hPrivate;
psDevInfo = psParams->psDevInfo;
RGXDeviceIrqEventRx(hPrivate);
/* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper */
if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
{
eError = RGXPollReg32(hPrivate,
RGX_CR_SIDEKICK_IDLE,
RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
}
else
{
eError = RGXPollReg32(hPrivate,
RGX_CR_JONES_IDLE,
RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN));
}
if (eError != PVRSRV_OK) return eError;
#if !defined(SUPPORT_SHARED_SLC)
/* Wait for SLC to signal IDLE */
if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
{
eError = RGXPollReg32(hPrivate,
RGX_CR_SLC_IDLE,
RGX_CR_SLC_IDLE_MASKFULL,
RGX_CR_SLC_IDLE_MASKFULL);
}
else
{
eError = RGXPollReg32(hPrivate,
RGX_CR_SLC3_IDLE,
RGX_CR_SLC3_IDLE_MASKFULL,
RGX_CR_SLC3_IDLE_MASKFULL);
}
#endif /* SUPPORT_SHARED_SLC */
if (eError != PVRSRV_OK) return eError;
/* Unset MTS DM association with threads */
RGXWriteReg32(hPrivate,
RGX_CR_MTS_INTCTX_THREAD0_DM_ASSOC,
RGX_CR_MTS_INTCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK
& RGX_CR_MTS_INTCTX_THREAD0_DM_ASSOC_MASKFULL);
RGXWriteReg32(hPrivate,
RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC,
RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK
& RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC_MASKFULL);
RGXWriteReg32(hPrivate,
RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC,
RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK
& RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL);
RGXWriteReg32(hPrivate,
RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC,
RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK
& RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL);
#if defined(PDUMP)
if (bMetaFW)
{
/* Disabling threads is only required for pdumps to stop the fw gracefully */
/* Disable thread 0 */
eError = RGXWriteMetaRegThroughSP(hPrivate,
META_CR_T0ENABLE_OFFSET,
~META_CR_TXENABLE_ENABLE_BIT);
if (eError != PVRSRV_OK) return eError;
/* Disable thread 1 */
eError = RGXWriteMetaRegThroughSP(hPrivate,
META_CR_T1ENABLE_OFFSET,
~META_CR_TXENABLE_ENABLE_BIT);
if (eError != PVRSRV_OK) return eError;
/* Clear down any irq raised by META (done after disabling the FW
* threads to avoid a race condition).
* This is only really needed for PDumps but we do it anyway driver-live.
*/
RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVIRQSTATUS, 0x0);
(void)RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVIRQSTATUS); /* Fence write */
/* Wait for the Slave Port to finish all the transactions */
eError = RGXPollReg32(hPrivate,
RGX_CR_META_SP_MSLVCTRL1,
RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
if (eError != PVRSRV_OK) return eError;
}
#endif
/* Extra Idle checks */
eError = RGXPollReg32(hPrivate,
RGX_CR_BIF_STATUS_MMU,
0,
RGX_CR_BIF_STATUS_MMU_MASKFULL);
if (eError != PVRSRV_OK) return eError;
eError = RGXPollReg32(hPrivate,
RGX_CR_BIFPM_STATUS_MMU,
0,
RGX_CR_BIFPM_STATUS_MMU_MASKFULL);
if (eError != PVRSRV_OK) return eError;
if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE) &&
!RGX_DEVICE_HAS_FEATURE(hPrivate, XT_TOP_INFRASTRUCTURE))
{
eError = RGXPollReg32(hPrivate,
RGX_CR_BIF_READS_EXT_STATUS,
0,
RGX_CR_BIF_READS_EXT_STATUS_MASKFULL);
if (eError != PVRSRV_OK) return eError;
}
eError = RGXPollReg32(hPrivate,
RGX_CR_BIFPM_READS_EXT_STATUS,
0,
RGX_CR_BIFPM_READS_EXT_STATUS_MASKFULL);
if (eError != PVRSRV_OK) return eError;
{
IMG_UINT64 ui64SLCMask = RGX_CR_SLC_STATUS1_MASKFULL;
eError = RGXPollReg64(hPrivate,
RGX_CR_SLC_STATUS1,
0,
ui64SLCMask);
if (eError != PVRSRV_OK) return eError;
}
if (4 == RGXGetDeviceSLCBanks(hPrivate))
{
eError = RGXPollReg64(hPrivate,
RGX_CR_SLC_STATUS2,
0,
RGX_CR_SLC_STATUS2_MASKFULL);
if (eError != PVRSRV_OK) return eError;
}
#if !defined(SUPPORT_SHARED_SLC)
/* Wait for SLC to signal IDLE */
if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
{
eError = RGXPollReg32(hPrivate,
RGX_CR_SLC_IDLE,
RGX_CR_SLC_IDLE_MASKFULL,
RGX_CR_SLC_IDLE_MASKFULL);
}
else
{
eError = RGXPollReg32(hPrivate,
RGX_CR_SLC3_IDLE,
RGX_CR_SLC3_IDLE_MASKFULL,
RGX_CR_SLC3_IDLE_MASKFULL);
}
#endif /* SUPPORT_SHARED_SLC */
if (eError != PVRSRV_OK) return eError;
/* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper */
if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
{
eError = RGXPollReg32(hPrivate,
RGX_CR_SIDEKICK_IDLE,
RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
}
else
{
if (!RGX_DEVICE_HAS_FEATURE(hPrivate, FASTRENDER_DM))
{
eError = RGXPollReg32(hPrivate,
RGX_CR_JONES_IDLE,
RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN));
}
}
if (eError != PVRSRV_OK) return eError;
if (bMetaFW)
{
IMG_UINT32 ui32RegValue;
eError = RGXReadMetaRegThroughSP(hPrivate,
META_CR_TxVECINT_BHALT,
&ui32RegValue);
if (eError != PVRSRV_OK) return eError;
if ((ui32RegValue & 0xFFFFFFFFU) == 0x0)
{
/* Wait for Sidekick/Jones to signal IDLE including
* the Garten Wrapper if there is no debugger attached
* (TxVECINT_BHALT = 0x0) */
if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
{
eError = RGXPollReg32(hPrivate,
RGX_CR_SIDEKICK_IDLE,
RGX_CR_SIDEKICK_IDLE_GARTEN_EN,
RGX_CR_SIDEKICK_IDLE_GARTEN_EN);
if (eError != PVRSRV_OK) return eError;
}
else
{
eError = RGXPollReg32(hPrivate,
RGX_CR_JONES_IDLE,
RGX_CR_JONES_IDLE_GARTEN_EN,
RGX_CR_JONES_IDLE_GARTEN_EN);
if (eError != PVRSRV_OK) return eError;
}
}
}
else
{
if (PVRSRV_GET_DEVICE_FEATURE_VALUE(psDevInfo->psDeviceNode, LAYOUT_MARS) > 0)
{
/* As FW has been separated from SIDEKICK to the new MARS domain,
* checking for CPU & System Arbiter idle bits( SOCIF will never be Idle if
* Host polling on this register) */
eError = RGXPollReg32(hPrivate,
RGX_CR_MARS_IDLE,
RGX_CR_MARS_IDLE_CPU_EN | RGX_CR_MARS_IDLE_MH_SYSARB0_EN,
RGX_CR_MARS_IDLE_CPU_EN | RGX_CR_MARS_IDLE_MH_SYSARB0_EN);
if (eError != PVRSRV_OK) return eError;
}
else
{
eError = RGXPollReg32(hPrivate,
RGX_CR_SIDEKICK_IDLE,
RGX_CR_SIDEKICK_IDLE_GARTEN_EN,
RGX_CR_SIDEKICK_IDLE_GARTEN_EN);
if (eError != PVRSRV_OK) return eError;
}
}
return eError;
}
/*
* RGXInitSLC
*/
#if defined(SUPPORT_SHARED_SLC)
PVRSRV_ERROR RGXInitSLC(IMG_HANDLE hDevHandle)
{
PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
PVRSRV_RGXDEV_INFO *psDevInfo;
void *pvPowerParams;
if (psDeviceNode == NULL)
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
psDevInfo = psDeviceNode->pvDevice;
pvPowerParams = &psDevInfo->sLayerParams;
/* reset the SLC */
RGXCommentLog(pvPowerParams, "RGXInitSLC: soft reset SLC");
RGXWriteReg64(pvPowerParams, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_SLC_EN);
/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
(void) RGXReadReg64(pvPowerParams, RGX_CR_SOFT_RESET);
/* Take everything out of reset */
RGXWriteReg64(pvPowerParams, RGX_CR_SOFT_RESET, 0x0);
__RGXInitSLC(pvPowerParams);
return PVRSRV_OK;
}
#endif