1 /*************************************************************************/ /*!
3 @Title DDK implementation of the Services abstraction layer
4 @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description DDK implementation of the Services abstraction layer
6 @License Dual MIT/GPLv2
8 The contents of this file are subject to the MIT license as set out below.
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
20 Alternatively, the contents of this file may be used under the terms of
21 the GNU General Public License Version 2 ("GPL") in which case the provisions
22 of GPL are applicable instead of those above.
24 If you wish to allow use of your version of this file only under the terms of
25 GPL, and not to allow others to use your version of this file under the terms
26 of the MIT license, indicate your decision by deleting the provisions above
27 and replace them with the notice and other provisions required by GPL as set
28 out in the file called "GPL-COPYING" included in this distribution. If you do
29 not delete the provisions above, a recipient may use your version of this file
30 under the terms of either the MIT license or GPL.
32 This License is also included in this distribution in the file called
35 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
36 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
37 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
39 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
40 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 */ /**************************************************************************/
48 #include "rgxlayer_km_impl.h"
50 #include "devicemem_utils.h"
52 #include "rgxdevice.h"
53 #include "rgxfwutils.h"
55 void RGXWriteReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
57 RGX_POWER_LAYER_PARAMS *psPowerParams;
58 PVRSRV_RGXDEV_INFO *psDevInfo;
61 PVR_ASSERT(hPrivate != NULL);
62 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
63 psDevInfo = psPowerParams->psDevInfo;
64 pvRegsBase = psDevInfo->pvRegsBaseKM;
67 if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
70 OSWriteHWReg32(pvRegsBase, ui32RegAddr, ui32RegValue);
73 PDUMPREG32(RGX_PDUMPREG_NAME, ui32RegAddr, ui32RegValue, psPowerParams->ui32PdumpFlags);
76 void RGXWriteReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT64 ui64RegValue)
78 RGX_POWER_LAYER_PARAMS *psPowerParams;
79 PVRSRV_RGXDEV_INFO *psDevInfo;
82 PVR_ASSERT(hPrivate != NULL);
83 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
84 psDevInfo = psPowerParams->psDevInfo;
85 pvRegsBase = psDevInfo->pvRegsBaseKM;
88 if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
91 OSWriteHWReg64(pvRegsBase, ui32RegAddr, ui64RegValue);
94 PDUMPREG64(RGX_PDUMPREG_NAME, ui32RegAddr, ui64RegValue, psPowerParams->ui32PdumpFlags);
97 IMG_UINT32 RGXReadReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr)
99 RGX_POWER_LAYER_PARAMS *psPowerParams;
100 PVRSRV_RGXDEV_INFO *psDevInfo;
102 IMG_UINT32 ui32RegValue;
104 PVR_ASSERT(hPrivate != NULL);
105 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
106 psDevInfo = psPowerParams->psDevInfo;
107 pvRegsBase = psDevInfo->pvRegsBaseKM;
110 if(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW)
112 ui32RegValue = IMG_UINT32_MAX;
117 ui32RegValue = OSReadHWReg32(pvRegsBase, ui32RegAddr);
120 PDUMPREGREAD32(RGX_PDUMPREG_NAME, ui32RegAddr, psPowerParams->ui32PdumpFlags);
125 IMG_UINT64 RGXReadReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr)
127 RGX_POWER_LAYER_PARAMS *psPowerParams;
128 PVRSRV_RGXDEV_INFO *psDevInfo;
130 IMG_UINT64 ui64RegValue;
132 PVR_ASSERT(hPrivate != NULL);
133 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
134 psDevInfo = psPowerParams->psDevInfo;
135 pvRegsBase = psDevInfo->pvRegsBaseKM;
138 if(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW)
140 ui64RegValue = IMG_UINT64_MAX;
145 ui64RegValue = OSReadHWReg64(pvRegsBase, ui32RegAddr);
148 PDUMPREGREAD64(RGX_PDUMPREG_NAME, ui32RegAddr, PDUMP_FLAGS_CONTINUOUS);
153 PVRSRV_ERROR RGXPollReg32(const void *hPrivate,
154 IMG_UINT32 ui32RegAddr,
155 IMG_UINT32 ui32RegValue,
156 IMG_UINT32 ui32RegMask)
158 RGX_POWER_LAYER_PARAMS *psPowerParams;
159 PVRSRV_RGXDEV_INFO *psDevInfo;
162 PVR_ASSERT(hPrivate != NULL);
163 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
164 psDevInfo = psPowerParams->psDevInfo;
165 pvRegsBase = psDevInfo->pvRegsBaseKM;
168 if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
171 if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr),
173 ui32RegMask) != PVRSRV_OK)
175 PVR_DPF((PVR_DBG_ERROR, "RGXPollReg32: Poll for Reg (0x%x) failed", ui32RegAddr));
176 return PVRSRV_ERROR_TIMEOUT;
180 PDUMPREGPOL(RGX_PDUMPREG_NAME,
184 psPowerParams->ui32PdumpFlags,
185 PDUMP_POLL_OPERATOR_EQUAL);
190 PVRSRV_ERROR RGXPollReg64(const void *hPrivate,
191 IMG_UINT32 ui32RegAddr,
192 IMG_UINT64 ui64RegValue,
193 IMG_UINT64 ui64RegMask)
195 RGX_POWER_LAYER_PARAMS *psPowerParams;
196 PVRSRV_RGXDEV_INFO *psDevInfo;
199 /* Split lower and upper words */
200 IMG_UINT32 ui32UpperValue = (IMG_UINT32) (ui64RegValue >> 32);
201 IMG_UINT32 ui32LowerValue = (IMG_UINT32) (ui64RegValue);
202 IMG_UINT32 ui32UpperMask = (IMG_UINT32) (ui64RegMask >> 32);
203 IMG_UINT32 ui32LowerMask = (IMG_UINT32) (ui64RegMask);
205 PVR_ASSERT(hPrivate != NULL);
206 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
207 psDevInfo = psPowerParams->psDevInfo;
208 pvRegsBase = psDevInfo->pvRegsBaseKM;
211 if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
214 if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr + 4),
216 ui32UpperMask) != PVRSRV_OK)
218 PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for upper part of Reg (0x%x) failed", ui32RegAddr));
219 return PVRSRV_ERROR_TIMEOUT;
222 if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr),
224 ui32LowerMask) != PVRSRV_OK)
226 PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for upper part of Reg (0x%x) failed", ui32RegAddr));
227 return PVRSRV_ERROR_TIMEOUT;
231 PDUMPREGPOL(RGX_PDUMPREG_NAME,
235 psPowerParams->ui32PdumpFlags,
236 PDUMP_POLL_OPERATOR_EQUAL);
239 PDUMPREGPOL(RGX_PDUMPREG_NAME,
243 psPowerParams->ui32PdumpFlags,
244 PDUMP_POLL_OPERATOR_EQUAL);
249 void RGXWaitCycles(const void *hPrivate, IMG_UINT32 ui32Cycles, IMG_UINT32 ui32TimeUs)
251 PVR_UNREFERENCED_PARAMETER(hPrivate);
252 OSWaitus(ui32TimeUs);
253 PDUMPIDLWITHFLAGS(ui32Cycles, PDUMP_FLAGS_CONTINUOUS);
256 void RGXCommentLogPower(const void *hPrivate, const IMG_CHAR *pszString, ...)
260 va_start(argList, pszString);
261 PDumpCommentWithFlagsVA(PDUMP_FLAGS_CONTINUOUS, pszString, argList);
263 PVR_UNREFERENCED_PARAMETER(hPrivate);
265 PVR_UNREFERENCED_PARAMETER(hPrivate);
266 PVR_UNREFERENCED_PARAMETER(pszString);
271 void RGXAcquireKernelMMUPC(const void *hPrivate, IMG_DEV_PHYADDR *psPCAddr)
273 PVR_ASSERT(hPrivate != NULL);
274 *psPCAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sPCAddr;
279 void RGXWriteKernelMMUPC64(const void *hPrivate,
280 IMG_UINT32 ui32PCReg,
281 IMG_UINT32 ui32PCRegAlignShift,
282 IMG_UINT32 ui32PCRegShift,
283 IMG_UINT64 ui64PCVal)
285 PVRSRV_RGXDEV_INFO *psDevInfo;
287 PVR_ASSERT(hPrivate != NULL);
288 psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
290 /* Write the cat-base address */
291 OSWriteHWReg64(psDevInfo->pvRegsBaseKM, ui32PCReg, ui64PCVal);
293 /* Pdump catbase address */
294 MMU_PDumpWritePageCatBase(psDevInfo->psKernelMMUCtx,
300 PDUMP_FLAGS_CONTINUOUS);
303 void RGXWriteKernelMMUPC32(const void *hPrivate,
304 IMG_UINT32 ui32PCReg,
305 IMG_UINT32 ui32PCRegAlignShift,
306 IMG_UINT32 ui32PCRegShift,
307 IMG_UINT32 ui32PCVal)
309 PVRSRV_RGXDEV_INFO *psDevInfo;
311 PVR_ASSERT(hPrivate != NULL);
312 psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
314 /* Write the cat-base address */
315 OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32PCReg, ui32PCVal);
317 /* Pdump catbase address */
318 MMU_PDumpWritePageCatBase(psDevInfo->psKernelMMUCtx,
324 PDUMP_FLAGS_CONTINUOUS);
327 #endif /* defined(PDUMP) */
330 void RGXAcquireGPURegsAddr(const void *hPrivate, IMG_DEV_PHYADDR *psGPURegsAddr)
332 PVR_ASSERT(hPrivate != NULL);
333 *psGPURegsAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sGPURegAddr;
337 void RGXMIPSWrapperConfig(const void *hPrivate,
338 IMG_UINT32 ui32RegAddr,
339 IMG_UINT64 ui64GPURegsAddr,
340 IMG_UINT32 ui32GPURegsAlign,
341 IMG_UINT32 ui32BootMode)
343 PVRSRV_RGXDEV_INFO *psDevInfo;
345 PVR_ASSERT(hPrivate != NULL);
346 psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
348 OSWriteHWReg64(psDevInfo->pvRegsBaseKM,
350 (ui64GPURegsAddr >> ui32GPURegsAlign) | ui32BootMode);
352 /* Store register offset to temp PDump variable */
353 PDumpRegLabelToInternalVar(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", PDUMP_FLAGS_CONTINUOUS);
355 /* Align register transactions identifier */
356 PDumpWriteVarSHRValueOp(":SYSMEM:$1", ui32GPURegsAlign, PDUMP_FLAGS_CONTINUOUS);
358 /* Enable micromips instruction encoding */
359 PDumpWriteVarORValueOp(":SYSMEM:$1", ui32BootMode, PDUMP_FLAGS_CONTINUOUS);
361 /* Do the actual register write */
362 PDumpInternalVarToReg64(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", 0);
366 void RGXAcquireBootRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psBootRemapAddr)
368 PVR_ASSERT(hPrivate != NULL);
369 *psBootRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sBootRemapAddr;
372 void RGXAcquireCodeRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psCodeRemapAddr)
374 PVR_ASSERT(hPrivate != NULL);
375 *psCodeRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sCodeRemapAddr;
378 void RGXAcquireDataRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psDataRemapAddr)
380 PVR_ASSERT(hPrivate != NULL);
381 *psDataRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sDataRemapAddr;
384 void RGXAcquireTrampolineRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psTrampolineRemapAddr)
386 PVR_ASSERT(hPrivate != NULL);
387 *psTrampolineRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sTrampolineRemapAddr;
392 void RGXWriteRemapConfig2Reg(void *pvRegs,
394 IMG_DEVMEM_OFFSET_T uiLogicalOffset,
395 IMG_UINT32 ui32RegAddr,
396 IMG_UINT64 ui64PhyAddr,
397 IMG_UINT64 ui64PhyMask,
398 IMG_UINT64 ui64Settings)
400 OSWriteHWReg64(pvRegs, ui32RegAddr, (ui64PhyAddr & ui64PhyMask) | ui64Settings);
402 /* Store memory offset to temp PDump variable */
403 PDumpMemLabelToInternalVar(":SYSMEM:$1", psPMR, uiLogicalOffset, PDUMP_FLAGS_CONTINUOUS);
405 /* Keep only the relevant bits of the output physical address */
406 PDumpWriteVarANDValueOp(":SYSMEM:$1", ui64PhyMask, PDUMP_FLAGS_CONTINUOUS);
408 /* Extra settings for this remapped region */
409 PDumpWriteVarORValueOp(":SYSMEM:$1", ui64Settings, PDUMP_FLAGS_CONTINUOUS);
411 /* Do the actual register write */
412 PDumpInternalVarToReg32(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", PDUMP_FLAGS_CONTINUOUS);
415 void RGXBootRemapConfig(const void *hPrivate,
416 IMG_UINT32 ui32Config1RegAddr,
417 IMG_UINT64 ui64Config1RegValue,
418 IMG_UINT32 ui32Config2RegAddr,
419 IMG_UINT64 ui64Config2PhyAddr,
420 IMG_UINT64 ui64Config2PhyMask,
421 IMG_UINT64 ui64Config2Settings)
423 PVRSRV_RGXDEV_INFO *psDevInfo;
424 IMG_UINT32 ui32BootRemapMemOffset = RGXMIPSFW_BOOT_NMI_CODE_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
426 PVR_ASSERT(hPrivate != NULL);
427 psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
429 /* Write remap config1 register */
430 RGXWriteReg64(hPrivate,
432 ui64Config1RegValue);
434 /* Write remap config2 register */
435 RGXWriteRemapConfig2Reg(psDevInfo->pvRegsBaseKM,
436 psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
437 psDevInfo->psRGXFWCodeMemDesc->uiOffset + ui32BootRemapMemOffset,
441 ui64Config2Settings);
444 void RGXCodeRemapConfig(const void *hPrivate,
445 IMG_UINT32 ui32Config1RegAddr,
446 IMG_UINT64 ui64Config1RegValue,
447 IMG_UINT32 ui32Config2RegAddr,
448 IMG_UINT64 ui64Config2PhyAddr,
449 IMG_UINT64 ui64Config2PhyMask,
450 IMG_UINT64 ui64Config2Settings)
452 PVRSRV_RGXDEV_INFO *psDevInfo;
453 IMG_UINT32 ui32CodeRemapMemOffset = RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
455 PVR_ASSERT(hPrivate != NULL);
456 psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
458 /* Write remap config1 register */
459 RGXWriteReg64(hPrivate,
461 ui64Config1RegValue);
463 /* Write remap config2 register */
464 RGXWriteRemapConfig2Reg(psDevInfo->pvRegsBaseKM,
465 psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
466 psDevInfo->psRGXFWCodeMemDesc->uiOffset + ui32CodeRemapMemOffset,
470 ui64Config2Settings);
473 void RGXDataRemapConfig(const void *hPrivate,
474 IMG_UINT32 ui32Config1RegAddr,
475 IMG_UINT64 ui64Config1RegValue,
476 IMG_UINT32 ui32Config2RegAddr,
477 IMG_UINT64 ui64Config2PhyAddr,
478 IMG_UINT64 ui64Config2PhyMask,
479 IMG_UINT64 ui64Config2Settings)
481 PVRSRV_RGXDEV_INFO *psDevInfo;
482 IMG_UINT32 ui32DataRemapMemOffset = RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
484 PVR_ASSERT(hPrivate != NULL);
485 psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
487 /* Write remap config1 register */
488 RGXWriteReg64(hPrivate,
490 ui64Config1RegValue);
492 /* Write remap config2 register */
493 RGXWriteRemapConfig2Reg(psDevInfo->pvRegsBaseKM,
494 psDevInfo->psRGXFWDataMemDesc->psImport->hPMR,
495 psDevInfo->psRGXFWDataMemDesc->uiOffset + ui32DataRemapMemOffset,
499 ui64Config2Settings);
505 #define MAX_NUM_COHERENCY_TESTS (10)
506 IMG_BOOL RGXDoFWSlaveBoot(const void *hPrivate)
508 PVRSRV_RGXDEV_INFO *psDevInfo;
509 PVRSRV_DEVICE_CONFIG *psDevConfig;
511 PVR_ASSERT(hPrivate != NULL);
512 psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
514 if (psDevInfo->ui32CoherencyTestsDone >= MAX_NUM_COHERENCY_TESTS)
519 psDevConfig = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevConfig;
521 return PVRSRVSystemSnoopingOfCPUCache(psDevConfig);
524 PVRSRV_ERROR RGXIOCoherencyTest(const void *hPrivate)
526 PVRSRV_RGXDEV_INFO *psDevInfo;
527 DEVMEM_MEMDESC *psIOCoherencyTestMemDesc;
528 IMG_UINT32 *pui32CpuVirtAddr;
529 RGXFWIF_DEV_VIRTADDR sCoherencyTestBuffer;
530 IMG_DEVMEM_SIZE_T uiCoherencyBlockSize = sizeof(IMG_UINT64);
531 IMG_DEVMEM_ALIGN_T uiCoherencyBlockAlign = sizeof(IMG_UINT64);
532 IMG_UINT32 ui32SLCCTRL;
533 IMG_UINT32 ui32TestNum;
534 PVRSRV_ERROR eError = PVRSRV_OK;
536 PVR_ASSERT(hPrivate != NULL);
537 psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
539 /* Size and align are 'expanded' because we request an export align allocation */
540 DevmemExportalignAdjustSizeAndAlign(DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareHeap),
541 &uiCoherencyBlockSize,
542 &uiCoherencyBlockAlign);
544 /* Allocate, acquire cpu address and set firmware address */
545 eError = DevmemFwAllocateExportable(psDevInfo->psDeviceNode,
546 uiCoherencyBlockSize,
547 uiCoherencyBlockAlign,
548 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
549 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
550 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
551 PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT |
552 PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT |
553 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
554 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
555 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
556 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
557 "FwExIoCoherencyTestBuffer",
558 &psIOCoherencyTestMemDesc);
559 PVR_ASSERT(eError == PVRSRV_OK);
561 eError = DevmemAcquireCpuVirtAddr(psIOCoherencyTestMemDesc,
562 (void **) &pui32CpuVirtAddr);
563 PVR_ASSERT(eError == PVRSRV_OK);
565 /* Create a FW address which is uncached in the Meta DCache and in the SLC
566 * using the Meta bootloader segment.
567 * This segment is the only one configured correctly out of reset
568 * (when this test is meant to be executed).
571 RGXSetFirmwareAddress(&sCoherencyTestBuffer,
572 psIOCoherencyTestMemDesc,
574 RFW_FWADDR_FLAG_NONE);
576 /* Undo most of the FW mappings done by RGXSetFirmwareAddress */
577 sCoherencyTestBuffer.ui32Addr &= ~RGXFW_SEGMMU_DATA_META_CACHE_MASK;
578 sCoherencyTestBuffer.ui32Addr &= ~RGXFW_SEGMMU_DATA_VIVT_SLC_CACHE_MASK;
579 sCoherencyTestBuffer.ui32Addr -= RGXFW_SEGMMU_DATA_BASE_ADDRESS;
581 /* Map the buffer in the bootloader segment as uncached */
582 sCoherencyTestBuffer.ui32Addr |= RGXFW_BOOTLDR_META_ADDR;
583 sCoherencyTestBuffer.ui32Addr |= RGXFW_SEGMMU_DATA_META_UNCACHED;
586 /* Bypass the SLC when IO coherency is enabled */
587 ui32SLCCTRL = RGXReadReg32(hPrivate, RGX_CR_SLC_CTRL_BYPASS);
588 RGXWriteReg32(hPrivate,
589 RGX_CR_SLC_CTRL_BYPASS,
590 ui32SLCCTRL | RGX_CR_SLC_CTRL_BYPASS_BYP_CC_EN);
592 for (ui32TestNum = 1; ui32TestNum < 3; ui32TestNum++)
595 IMG_BOOL bPassed = IMG_TRUE;
597 PVR_LOG(("Startup I/O Coherency Test [pass #%u]", ui32TestNum));
599 for (i = 0; i < uiCoherencyBlockSize/sizeof(IMG_UINT32); i++)
601 IMG_UINT32 ui32FWAddr, ui32FWValue;
602 PVRSRV_ERROR eError2;
604 /* Ensures line is in dcache */
605 ui32FWValue = pui32CpuVirtAddr[i];
607 /* Dirty allocation in dcache */
608 pui32CpuVirtAddr[i] = i + ui32TestNum;
610 /* Flush possible cpu store-buffer(ing) */
611 OSWriteMemoryBarrier();
613 /* Read back value using RGX slave-port interface */
614 ui32FWAddr = sCoherencyTestBuffer.ui32Addr + (i * sizeof(IMG_UINT32));
616 eError2 = RGXReadMETAAddr(psDevInfo, ui32FWAddr, &ui32FWValue);
618 if (eError2 != PVRSRV_OK)
620 PVR_DPF((PVR_DBG_ERROR, "RGXReadWithSP error: %s",
621 PVRSRVGetErrorStringKM(eError2)));
624 /* Compare to see if I/O coherency worked */
625 if (pui32CpuVirtAddr[i] != ui32FWValue)
627 PVR_DPF((PVR_DBG_ERROR, "Expected: %x, Got: %x",
628 pui32CpuVirtAddr[i], ui32FWValue));
631 eError = PVRSRV_ERROR_INIT_FAILURE;
635 PVR_LOG(("I/O Coherency Test [pass #%u] completed, Passed? %d",
636 ui32TestNum, bPassed));
639 /* Restore SLC bypass settings */
640 RGXWriteReg32(hPrivate, RGX_CR_SLC_CTRL_BYPASS, ui32SLCCTRL);
642 RGXUnsetFirmwareAddress(psIOCoherencyTestMemDesc);
643 DevmemReleaseCpuVirtAddr(psIOCoherencyTestMemDesc);
644 DevmemFwFree(psDevInfo, psIOCoherencyTestMemDesc);
646 if (eError == PVRSRV_OK)
648 PVR_LOG(("I/O Coherency Test succeeded"));
649 psDevInfo->ui32CoherencyTestsDone = MAX_NUM_COHERENCY_TESTS + 1;
653 PVR_LOG(("I/O Coherency Test FAILED"));
654 psDevInfo->ui32CoherencyTestsDone++;
660 IMG_BOOL RGXDeviceHasFeaturePower(const void *hPrivate, IMG_UINT64 ui64Feature)
662 RGX_POWER_LAYER_PARAMS *psPowerParams;
663 PVRSRV_RGXDEV_INFO *psDevInfo;
665 PVR_ASSERT(hPrivate != NULL);
666 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
667 psDevInfo = psPowerParams->psDevInfo;
669 return (psDevInfo->sDevFeatureCfg.ui64Features & ui64Feature) != 0;
672 IMG_BOOL RGXDeviceHasErnBrnPower(const void *hPrivate, IMG_UINT64 ui64ErnsBrns)
674 RGX_POWER_LAYER_PARAMS *psPowerParams;
675 PVRSRV_RGXDEV_INFO *psDevInfo;
677 PVR_ASSERT(hPrivate != NULL);
678 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
679 psDevInfo = psPowerParams->psDevInfo;
681 return (psDevInfo->sDevFeatureCfg.ui64ErnsBrns & ui64ErnsBrns) != 0;
684 IMG_UINT32 RGXGetDeviceSLCBanks(const void *hPrivate)
686 RGX_POWER_LAYER_PARAMS *psPowerParams;
687 PVRSRV_RGXDEV_INFO *psDevInfo;
689 PVR_ASSERT(hPrivate != NULL);
690 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
691 psDevInfo = psPowerParams->psDevInfo;
693 return psDevInfo->sDevFeatureCfg.ui32SLCBanks;
696 IMG_UINT32 RGXGetDeviceSLCSize(const void *hPrivate)
698 RGX_POWER_LAYER_PARAMS *psPowerParams;
699 PVRSRV_RGXDEV_INFO *psDevInfo;
701 PVR_ASSERT(hPrivate != NULL);
702 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
703 psDevInfo = psPowerParams->psDevInfo;
705 return psDevInfo->sDevFeatureCfg.ui32SLCSize;
708 IMG_UINT32 RGXGetDeviceCacheLineSize(const void *hPrivate)
710 RGX_POWER_LAYER_PARAMS *psPowerParams;
711 PVRSRV_RGXDEV_INFO *psDevInfo;
713 PVR_ASSERT(hPrivate != NULL);
714 psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
715 psDevInfo = psPowerParams->psDevInfo;
717 return psDevInfo->sDevFeatureCfg.ui32CacheLineSize;