blob: f6a656a906f1d6dc749ef46f24155554798f40d4 [file] [log] [blame]
/*************************************************************************/ /*!
@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_km.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"
#include "rgxdevice.h"
#endif
#define SOC_FEATURE_STRICT_SAME_ADDRESS_WRITE_ORDERING
#if !defined(FIX_HW_BRN_37453)
/*!
*******************************************************************************
@Function RGXEnableClocks
@Description Enable RGX Clocks
@Input hPrivate : Implementation specific data
@Return void
******************************************************************************/
static void RGXEnableClocks(const void *hPrivate)
{
RGXCommentLogPower(hPrivate, "RGX clock: use default (automatic clock gating)");
}
#endif
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);
RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVDATAT, ui32RegValue);
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);
/* 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)
{
RGXCommentLogPower(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)
{
RGXCommentLogPower(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 (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
{
/* Set PC = 0 for fences */
ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PC_BASE_CLRMSK;
ui64GartenConfig |= (IMG_UINT64)META_MMU_CONTEXT_MAPPING
<< RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PC_BASE_SHIFT;
if (!RGXDeviceHasErnBrnPower(hPrivate, FIX_HW_BRN_51281_BIT_MASK))
{
/* Ensure the META fences go all the way to external memory */
ui64GartenConfig |= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_SLC_COHERENT_EN; /* SLC Coherent 1 */
ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG__S7_TOP__FENCE_PERSISTENCE_CLRMSK; /* SLC Persistence 0 */
}
}
else
{
/* Set PC = 0 for fences */
ui64GartenConfig &= RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_CLRMSK;
ui64GartenConfig |= (IMG_UINT64)META_MMU_CONTEXT_MAPPING
<< RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_PC_BASE_SHIFT;
/* Set SLC DM=META */
ui64GartenConfig |= ((IMG_UINT64) RGXFW_SEGMMU_META_DM_ID) << RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_FENCE_DM_SHIFT;
}
RGXCommentLogPower(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 */
RGXCommentLogPower(hPrivate, "RGXStart: Configure MIPS wrapper");
/*
* MIPS wrapper (registers transaction ID and ISA mode) setup
*/
RGXAcquireGPURegsAddr(hPrivate, &sPhyAddr);
RGXCommentLogPower(hPrivate, "RGXStart: Write wrapper config register");
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
RGXCommentLogPower(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);
/*
* Data remap setup
*/
RGXAcquireDataRemapAddr(hPrivate, &sPhyAddr);
#if defined(SUPPORT_TRUSTED_DEVICE)
/* Remapped data in non-secure memory */
ui64RemapSettings &= RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_TRUSTED_CLRMSK;
#endif
RGXCommentLogPower(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
RGXCommentLogPower(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);
/*
* 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
RGXCommentLogPower(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 */
RGXCommentLogPower(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 __RGXInitSLC
@Description Initialise RGX SLC
@Input hPrivate : Implementation specific data
@Return void
******************************************************************************/
static void __RGXInitSLC(const void *hPrivate)
{
if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_CACHE_HIERARCHY_BIT_MASK))
{
IMG_UINT32 ui32Reg;
IMG_UINT32 ui32RegVal;
if (RGXDeviceHasErnBrnPower(hPrivate, HW_ERN_51468_BIT_MASK))
{
/*
* SLC control
*/
ui32Reg = RGX_CR_SLC3_CTRL_MISC;
ui32RegVal = RGX_CR_SLC3_CTRL_MISC_ADDR_DECODE_MODE_WEAVED_HASH |
RGX_CR_SLC3_CTRL_MISC_WRITE_COMBINER_EN;
RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
}
else
{
/*
* 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);
}
}
}
if (RGXDeviceHasErnBrnPower(hPrivate, HW_ERN_45914_BIT_MASK))
{
/* Disable the forced SLC coherency which the hardware enables for compatibility with older pdumps */
RGXCommentLogPower(hPrivate, "Disable forced SLC coherency");
RGXWriteReg64(hPrivate, RGX_CR_GARTEN_SLC, 0);
}
}
else
{
IMG_UINT32 ui32Reg;
IMG_UINT32 ui32RegVal;
#if defined(FIX_HW_BRN_36492)
/* Because the WA for this BRN forbids using SLC reset, need to inval it instead */
RGXCommentLogPower(hPrivate, "Invalidate the SLC");
RGXWriteReg32(hPrivate, RGX_CR_SLC_CTRL_FLUSH_INVAL, RGX_CR_SLC_CTRL_FLUSH_INVAL_ALL_EN);
/* Poll for completion */
RGXPollReg32(hPrivate, RGX_CR_SLC_STATUS0, 0x0, RGX_CR_SLC_STATUS0_MASKFULL);
#endif
/*
* SLC Bypass control
*/
ui32Reg = RGX_CR_SLC_CTRL_BYPASS;
ui32RegVal = 0;
if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_SLCSIZE8_BIT_MASK) ||
RGXDeviceHasErnBrnPower(hPrivate, FIX_HW_BRN_61450_BIT_MASK))
{
RGXCommentLogPower(hPrivate, "Bypass SLC for IPF_OBJ and IPF_CPF");
ui32RegVal |= RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_OBJ_EN | RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_EN;
}
if (RGXGetDeviceSLCSize(hPrivate) < (128*1024))
{
/* Bypass SLC for textures if the SLC size is less than 128kB */
RGXCommentLogPower(hPrivate, "Bypass SLC for TPU");
ui32RegVal |= RGX_CR_SLC_CTRL_BYPASS_REQ_TPU_EN;
}
if (ui32RegVal != 0)
{
RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
}
/*
* 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 (RGXDeviceHasErnBrnPower(hPrivate, FIX_HW_BRN_60084_BIT_MASK))
{
#if !defined(SOC_FEATURE_STRICT_SAME_ADDRESS_WRITE_ORDERING)
ui32RegVal |= RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN;
#else
if (RGXDeviceHasErnBrnPower(hPrivate, HW_ERN_61389_BIT_MASK))
{
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 (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_MIPS_BIT_MASK))
{
IMG_DEV_PHYADDR sPCAddr;
/*
* Acquire the address of the Kernel Page Catalogue.
*/
RGXAcquireKernelMMUPC(hPrivate, &sPCAddr);
/*
* Write the kernel catalogue base.
*/
RGXCommentLogPower(hPrivate, "RGX firmware MMU Page Catalogue");
if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_SLC_VIVT_BIT_MASK))
{
/* 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);
/*
* Trusted Firmware boot
*/
#if defined(SUPPORT_TRUSTED_DEVICE)
RGXCommentLogPower(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, 0);
/* 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 defined(SUPPORT_TRUSTED_DEVICE)
/* Set-up MMU ID 1 mapping to the same PC used by MMU ID 0 */
RGXWriteReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT, 1);
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 /* SUPPORT_TRUSTED_DEVICE */
}
}
else
{
/*
* Trusted Firmware boot
*/
#if defined(SUPPORT_TRUSTED_DEVICE)
RGXCommentLogPower(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 (RGXDeviceHasErnBrnPower(hPrivate, FIX_HW_BRN_42321_BIT_MASK))
{
ui64RegVal |= (((IMG_UINT64) 1) << RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITELINEUNIQUE_SHIFT);
}
#if defined(SUPPORT_TRUSTED_DEVICE)
if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_SLC_VIVT_BIT_MASK))
{
RGXCommentLogPower(hPrivate, "OSID 0 and 1 are trusted");
ui64RegVal |= IMG_UINT64_C(0xFC)
<< RGX_CR_AXI_ACE_LITE_CONFIGURATION_OSID_SECURITY_SHIFT;
}
#endif
RGXCommentLogPower(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 (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_MIPS_BIT_MASK))
{
pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_MIPS;
bMetaFW = IMG_FALSE;
bDoFWSlaveBoot = IMG_FALSE;
}
else
{
pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_META;
bMetaFW = IMG_TRUE;
bDoFWSlaveBoot = RGXDoFWSlaveBoot(hPrivate);
}
if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_SYS_BUS_SECURE_RESET_BIT_MASK))
{
/* Disable the default sys_bus_secure protection to perform minimal setup */
RGXCommentLogPower(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(FIX_HW_BRN_37453)
/* Force all clocks on*/
RGXCommentLogPower(hPrivate, "RGXStart: force all clocks on");
RGXWriteReg64(hPrivate, RGX_CR_CLK_CTRL, RGX_CR_CLK_CTRL_ALL_ON);
#endif
#if defined(SUPPORT_SHARED_SLC) && !defined(FIX_HW_BRN_36492)
/* 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. If HW_BRN_36492, the bit is already masked out.
*/
#define RGX_CR_SOFT_RESET_ALL (RGX_CR_SOFT_RESET_MASKFULL ^ RGX_CR_SOFT_RESET_SLC_EN)
RGXCommentLogPower(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 (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
{
/* Set RGX in soft-reset */
RGXCommentLogPower(hPrivate, "RGXStart: soft reset assert step 1");
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_S7_SOFT_RESET_DUSTS);
RGXCommentLogPower(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);
/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
/* Take everything out of reset but META/MIPS */
RGXCommentLogPower(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);
RGXCommentLogPower(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 */
RGXCommentLogPower(hPrivate, "RGXStart: soft reset everything");
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_ALL);
/* Take Rascal and Dust out of reset */
RGXCommentLogPower(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);
/* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
(void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
/* Take everything out of reset but META/MIPS */
RGXCommentLogPower(hPrivate, "RGXStart: Take everything out of reset but %s", pcRGXFW_PROCESSOR);
RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
}
#if !defined(FIX_HW_BRN_37453)
/* Enable clocks */
RGXEnableClocks(hPrivate);
#endif
/*
* Initialise SLC.
*/
#if !defined(SUPPORT_SHARED_SLC)
__RGXInitSLC(hPrivate);
#endif
if (bMetaFW)
{
if (bDoFWSlaveBoot)
{
/* Configure META to Slave boot */
RGXCommentLogPower(hPrivate, "RGXStart: META Slave boot");
RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, 0);
}
else
{
/* Configure META to Master boot */
RGXCommentLogPower(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
{
RGXInitMipsProcWrapper(hPrivate);
}
if (RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_AXI_ACELITE_BIT_MASK))
{
/* We must init the AXI-ACE interface before 1st BIF transaction */
RGXAXIACELiteInit(hPrivate);
}
/*
* Initialise BIF.
*/
RGXInitBIF(hPrivate);
RGXCommentLogPower(hPrivate, "RGXStart: Take %s out of reset", pcRGXFW_PROCESSOR);
/* Need to wait for at least 16 cycles before taking META/MIPS 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 defined(FIX_HW_BRN_37453)
/* We rely on the 32 clk sleep from above */
/* Switch clocks back to auto */
RGXCommentLogPower(hPrivate, "RGXStart: set clocks back to auto");
RGXWriteReg64(hPrivate, RGX_CR_CLK_CTRL, RGX_CR_CLK_CTRL_ALL_AUTO);
#endif
if (bMetaFW && bDoFWSlaveBoot)
{
eError = RGXIOCoherencyTest(hPrivate);
if (eError != PVRSRV_OK) return eError;
RGXCommentLogPower(hPrivate, "RGXStart: RGX Firmware Slave boot Start");
eError = RGXStartFirmware(hPrivate);
if (eError != PVRSRV_OK) return eError;
}
else
{
RGXCommentLogPower(hPrivate, "RGXStart: RGX Firmware Master boot Start");
}
/* Enable Sys Bus security */
#if defined(SUPPORT_TRUSTED_DEVICE)
RGXCommentLogPower(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;
}
static INLINE void ClearIRQStatusRegister(const void *hPrivate, IMG_BOOL bMetaFW)
{
IMG_UINT32 ui32IRQClearReg;
IMG_UINT32 ui32IRQClearMask;
if(bMetaFW)
{
ui32IRQClearReg = RGX_CR_META_SP_MSLVIRQSTATUS;
ui32IRQClearMask = RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK;
}
else
{
ui32IRQClearReg = RGX_CR_MIPS_WRAPPER_IRQ_CLEAR;
ui32IRQClearMask = RGX_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN;
}
RGXWriteReg32(hPrivate, ui32IRQClearReg, ui32IRQClearMask);
#if defined(RGX_FEATURE_OCPBUS)
RGXWriteReg32(hPrivate, RGX_CR_OCP_IRQSTATUS_2, RGX_CR_OCP_IRQSTATUS_2_RGX_IRQ_STATUS_EN);
#endif
}
PVRSRV_ERROR RGXStop(const void *hPrivate)
{
IMG_BOOL bMetaFW = !RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_MIPS_BIT_MASK);
PVRSRV_ERROR eError;
ClearIRQStatusRegister(hPrivate, bMetaFW);
/* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper */
if (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
{
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 (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
{
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);
/* 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 (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK) &&
!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK))
{
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 (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
{
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 (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
{
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 (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_FASTRENDER_DM_BIT_MASK))
{
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 (!RGXDeviceHasFeaturePower(hPrivate, RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK))
{
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
{
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->sPowerParams;
#if !defined(FIX_HW_BRN_36492)
/* reset the SLC */
RGXCommentLogPower(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);
#endif
__RGXInitSLC(pvPowerParams);
return PVRSRV_OK;
}
#endif