RK3368 GPU: Rogue N Init.
[firefly-linux-kernel-4.4.55.git] / drivers / staging / imgtec / rogue / rgxlayer_km_impl.c
1 /*************************************************************************/ /*!
2 @File
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
7
8 The contents of this file are subject to the MIT license as set out below.
9
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:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
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.
23
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.
31
32 This License is also included in this distribution in the file called
33 "MIT-COPYING".
34
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 */ /**************************************************************************/
43
44 #if defined (PDUMP)
45 #include <stdarg.h>
46 #endif
47
48 #include "rgxlayer_km_impl.h"
49 #include "pdump_km.h"
50 #include "devicemem_utils.h"
51 #include "pvrsrv.h"
52 #include "rgxdevice.h"
53 #include "rgxfwutils.h"
54
55 void RGXWriteReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
56 {
57         RGX_POWER_LAYER_PARAMS *psPowerParams;
58         PVRSRV_RGXDEV_INFO *psDevInfo;
59         void *pvRegsBase;
60
61         PVR_ASSERT(hPrivate != NULL);
62         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
63         psDevInfo = psPowerParams->psDevInfo;
64         pvRegsBase = psDevInfo->pvRegsBaseKM;
65
66 #if defined(PDUMP)
67         if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
68 #endif
69         {
70                 OSWriteHWReg32(pvRegsBase, ui32RegAddr, ui32RegValue);
71         }
72
73         PDUMPREG32(RGX_PDUMPREG_NAME, ui32RegAddr, ui32RegValue, psPowerParams->ui32PdumpFlags);
74 }
75
76 void RGXWriteReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT64 ui64RegValue)
77 {
78         RGX_POWER_LAYER_PARAMS *psPowerParams;
79         PVRSRV_RGXDEV_INFO *psDevInfo;
80         void *pvRegsBase;
81
82         PVR_ASSERT(hPrivate != NULL);
83         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
84         psDevInfo = psPowerParams->psDevInfo;
85         pvRegsBase = psDevInfo->pvRegsBaseKM;
86
87 #if defined(PDUMP)
88         if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
89 #endif
90         {
91                 OSWriteHWReg64(pvRegsBase, ui32RegAddr, ui64RegValue);
92         }
93
94         PDUMPREG64(RGX_PDUMPREG_NAME, ui32RegAddr, ui64RegValue, psPowerParams->ui32PdumpFlags);
95 }
96
97 IMG_UINT32 RGXReadReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr)
98 {
99         RGX_POWER_LAYER_PARAMS *psPowerParams;
100         PVRSRV_RGXDEV_INFO *psDevInfo;
101         void *pvRegsBase;
102         IMG_UINT32 ui32RegValue;
103
104         PVR_ASSERT(hPrivate != NULL);
105         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
106         psDevInfo = psPowerParams->psDevInfo;
107         pvRegsBase = psDevInfo->pvRegsBaseKM;
108
109 #if defined(PDUMP)
110         if(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW)
111         {
112                 ui32RegValue = IMG_UINT32_MAX;
113         }
114         else
115 #endif
116         {
117                 ui32RegValue = OSReadHWReg32(pvRegsBase, ui32RegAddr);
118         }
119
120         PDUMPREGREAD32(RGX_PDUMPREG_NAME, ui32RegAddr, psPowerParams->ui32PdumpFlags);
121
122         return ui32RegValue;
123 }
124
125 IMG_UINT64 RGXReadReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr)
126 {
127         RGX_POWER_LAYER_PARAMS *psPowerParams;
128         PVRSRV_RGXDEV_INFO *psDevInfo;
129         void *pvRegsBase;
130         IMG_UINT64 ui64RegValue;
131
132         PVR_ASSERT(hPrivate != NULL);
133         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
134         psDevInfo = psPowerParams->psDevInfo;
135         pvRegsBase = psDevInfo->pvRegsBaseKM;
136
137 #if defined(PDUMP)
138         if(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW)
139         {
140                 ui64RegValue = IMG_UINT64_MAX;
141         }
142         else
143 #endif
144         {
145                 ui64RegValue = OSReadHWReg64(pvRegsBase, ui32RegAddr);
146         }
147
148         PDUMPREGREAD64(RGX_PDUMPREG_NAME, ui32RegAddr, PDUMP_FLAGS_CONTINUOUS);
149
150         return ui64RegValue;
151 }
152
153 PVRSRV_ERROR RGXPollReg32(const void *hPrivate,
154                           IMG_UINT32 ui32RegAddr,
155                           IMG_UINT32 ui32RegValue,
156                           IMG_UINT32 ui32RegMask)
157 {
158         RGX_POWER_LAYER_PARAMS *psPowerParams;
159         PVRSRV_RGXDEV_INFO *psDevInfo;
160         void *pvRegsBase;
161
162         PVR_ASSERT(hPrivate != NULL);
163         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
164         psDevInfo = psPowerParams->psDevInfo;
165         pvRegsBase = psDevInfo->pvRegsBaseKM;
166
167 #if defined(PDUMP)
168         if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
169 #endif
170         {
171                 if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr),
172                                          ui32RegValue,
173                                          ui32RegMask) != PVRSRV_OK)
174                 {
175                         PVR_DPF((PVR_DBG_ERROR, "RGXPollReg32: Poll for Reg (0x%x) failed", ui32RegAddr));
176                         return PVRSRV_ERROR_TIMEOUT;
177                 }
178         }
179
180         PDUMPREGPOL(RGX_PDUMPREG_NAME,
181                     ui32RegAddr,
182                     ui32RegValue,
183                     ui32RegMask,
184                     psPowerParams->ui32PdumpFlags,
185                     PDUMP_POLL_OPERATOR_EQUAL);
186
187         return PVRSRV_OK;
188 }
189
190 PVRSRV_ERROR RGXPollReg64(const void *hPrivate,
191                           IMG_UINT32 ui32RegAddr,
192                           IMG_UINT64 ui64RegValue,
193                           IMG_UINT64 ui64RegMask)
194 {
195         RGX_POWER_LAYER_PARAMS *psPowerParams;
196         PVRSRV_RGXDEV_INFO *psDevInfo;
197         void *pvRegsBase;
198
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);
204
205         PVR_ASSERT(hPrivate != NULL);
206         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
207         psDevInfo = psPowerParams->psDevInfo;
208         pvRegsBase = psDevInfo->pvRegsBaseKM;
209
210 #if defined(PDUMP)
211         if( !(psPowerParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW) )
212 #endif
213         {
214                 if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr + 4),
215                                          ui32UpperValue,
216                                          ui32UpperMask) != PVRSRV_OK)
217                 {
218                         PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for upper part of Reg (0x%x) failed", ui32RegAddr));
219                         return PVRSRV_ERROR_TIMEOUT;
220                 }
221
222                 if (PVRSRVPollForValueKM((IMG_UINT32 *)((IMG_UINT8*)pvRegsBase + ui32RegAddr),
223                                          ui32LowerValue,
224                                          ui32LowerMask) != PVRSRV_OK)
225                 {
226                         PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for upper part of Reg (0x%x) failed", ui32RegAddr));
227                         return PVRSRV_ERROR_TIMEOUT;
228                 }
229         }
230
231         PDUMPREGPOL(RGX_PDUMPREG_NAME,
232                     ui32RegAddr + 4,
233                     ui32UpperValue,
234                     ui32UpperMask,
235                     psPowerParams->ui32PdumpFlags,
236                     PDUMP_POLL_OPERATOR_EQUAL);
237
238
239         PDUMPREGPOL(RGX_PDUMPREG_NAME,
240                     ui32RegAddr,
241                     ui32LowerValue,
242                     ui32LowerMask,
243                     psPowerParams->ui32PdumpFlags,
244                     PDUMP_POLL_OPERATOR_EQUAL);
245
246         return PVRSRV_OK;
247 }
248
249 void RGXWaitCycles(const void *hPrivate, IMG_UINT32 ui32Cycles, IMG_UINT32 ui32TimeUs)
250 {
251         PVR_UNREFERENCED_PARAMETER(hPrivate);
252         OSWaitus(ui32TimeUs);
253         PDUMPIDLWITHFLAGS(ui32Cycles, PDUMP_FLAGS_CONTINUOUS);
254 }
255
256 void RGXCommentLogPower(const void *hPrivate, const IMG_CHAR *pszString, ...)
257 {
258 #if defined(PDUMP)
259         va_list argList;
260         va_start(argList, pszString);
261         PDumpCommentWithFlagsVA(PDUMP_FLAGS_CONTINUOUS, pszString, argList);
262         va_end(argList);
263         PVR_UNREFERENCED_PARAMETER(hPrivate);
264 #else
265         PVR_UNREFERENCED_PARAMETER(hPrivate);
266         PVR_UNREFERENCED_PARAMETER(pszString);
267 #endif
268 }
269
270
271 void RGXAcquireKernelMMUPC(const void *hPrivate, IMG_DEV_PHYADDR *psPCAddr)
272 {
273         PVR_ASSERT(hPrivate != NULL);
274         *psPCAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sPCAddr;
275 }
276
277 #if defined(PDUMP)
278
279 void RGXWriteKernelMMUPC64(const void *hPrivate,
280                            IMG_UINT32 ui32PCReg,
281                            IMG_UINT32 ui32PCRegAlignShift,
282                            IMG_UINT32 ui32PCRegShift,
283                            IMG_UINT64 ui64PCVal)
284 {
285         PVRSRV_RGXDEV_INFO *psDevInfo;
286
287         PVR_ASSERT(hPrivate != NULL);
288         psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
289
290         /* Write the cat-base address */
291         OSWriteHWReg64(psDevInfo->pvRegsBaseKM, ui32PCReg, ui64PCVal);
292
293         /* Pdump catbase address */
294         MMU_PDumpWritePageCatBase(psDevInfo->psKernelMMUCtx,
295                                   RGX_PDUMPREG_NAME,
296                                   ui32PCReg,
297                                   8,
298                                   ui32PCRegAlignShift,
299                                   ui32PCRegShift,
300                                   PDUMP_FLAGS_CONTINUOUS);
301 }
302
303 void RGXWriteKernelMMUPC32(const void *hPrivate,
304                            IMG_UINT32 ui32PCReg,
305                            IMG_UINT32 ui32PCRegAlignShift,
306                            IMG_UINT32 ui32PCRegShift,
307                            IMG_UINT32 ui32PCVal)
308 {
309         PVRSRV_RGXDEV_INFO *psDevInfo;
310
311         PVR_ASSERT(hPrivate != NULL);
312         psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
313
314         /* Write the cat-base address */
315         OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32PCReg, ui32PCVal);
316
317         /* Pdump catbase address */
318         MMU_PDumpWritePageCatBase(psDevInfo->psKernelMMUCtx,
319                                   RGX_PDUMPREG_NAME,
320                                   ui32PCReg,
321                                   4,
322                                   ui32PCRegAlignShift,
323                                   ui32PCRegShift,
324                                   PDUMP_FLAGS_CONTINUOUS);
325 }
326
327 #endif /* defined(PDUMP) */
328
329
330 void RGXAcquireGPURegsAddr(const void *hPrivate, IMG_DEV_PHYADDR *psGPURegsAddr)
331 {
332         PVR_ASSERT(hPrivate != NULL);
333         *psGPURegsAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sGPURegAddr;
334 }
335
336 #if defined(PDUMP)
337 void RGXMIPSWrapperConfig(const void *hPrivate,
338                           IMG_UINT32 ui32RegAddr,
339                           IMG_UINT64 ui64GPURegsAddr,
340                           IMG_UINT32 ui32GPURegsAlign,
341                           IMG_UINT32 ui32BootMode)
342 {
343         PVRSRV_RGXDEV_INFO *psDevInfo;
344
345         PVR_ASSERT(hPrivate != NULL);
346         psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
347
348         OSWriteHWReg64(psDevInfo->pvRegsBaseKM,
349                        ui32RegAddr,
350                        (ui64GPURegsAddr >> ui32GPURegsAlign) | ui32BootMode);
351
352         /* Store register offset to temp PDump variable */
353         PDumpRegLabelToInternalVar(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", PDUMP_FLAGS_CONTINUOUS);
354
355         /* Align register transactions identifier */
356         PDumpWriteVarSHRValueOp(":SYSMEM:$1", ui32GPURegsAlign, PDUMP_FLAGS_CONTINUOUS);
357
358         /* Enable micromips instruction encoding */
359         PDumpWriteVarORValueOp(":SYSMEM:$1", ui32BootMode, PDUMP_FLAGS_CONTINUOUS);
360
361         /* Do the actual register write */
362         PDumpInternalVarToReg64(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", 0);
363 }
364 #endif
365
366 void RGXAcquireBootRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psBootRemapAddr)
367 {
368         PVR_ASSERT(hPrivate != NULL);
369         *psBootRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sBootRemapAddr;
370 }
371
372 void RGXAcquireCodeRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psCodeRemapAddr)
373 {
374         PVR_ASSERT(hPrivate != NULL);
375         *psCodeRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sCodeRemapAddr;
376 }
377
378 void RGXAcquireDataRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psDataRemapAddr)
379 {
380         PVR_ASSERT(hPrivate != NULL);
381         *psDataRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sDataRemapAddr;
382 }
383
384 void RGXAcquireTrampolineRemapAddr(const void *hPrivate, IMG_DEV_PHYADDR *psTrampolineRemapAddr)
385 {
386         PVR_ASSERT(hPrivate != NULL);
387         *psTrampolineRemapAddr = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->sTrampolineRemapAddr;
388 }
389
390 #if defined(PDUMP)
391 static inline
392 void RGXWriteRemapConfig2Reg(void *pvRegs,
393                              PMR *psPMR,
394                              IMG_DEVMEM_OFFSET_T uiLogicalOffset,
395                              IMG_UINT32 ui32RegAddr,
396                              IMG_UINT64 ui64PhyAddr,
397                              IMG_UINT64 ui64PhyMask,
398                              IMG_UINT64 ui64Settings)
399 {
400         OSWriteHWReg64(pvRegs, ui32RegAddr, (ui64PhyAddr & ui64PhyMask) | ui64Settings);
401
402         /* Store memory offset to temp PDump variable */
403         PDumpMemLabelToInternalVar(":SYSMEM:$1", psPMR, uiLogicalOffset, PDUMP_FLAGS_CONTINUOUS);
404
405         /* Keep only the relevant bits of the output physical address */
406         PDumpWriteVarANDValueOp(":SYSMEM:$1", ui64PhyMask, PDUMP_FLAGS_CONTINUOUS);
407
408         /* Extra settings for this remapped region */
409         PDumpWriteVarORValueOp(":SYSMEM:$1", ui64Settings, PDUMP_FLAGS_CONTINUOUS);
410
411         /* Do the actual register write */
412         PDumpInternalVarToReg32(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", PDUMP_FLAGS_CONTINUOUS);
413 }
414
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)
422 {
423         PVRSRV_RGXDEV_INFO *psDevInfo;
424         IMG_UINT32 ui32BootRemapMemOffset = RGXMIPSFW_BOOT_NMI_CODE_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
425
426         PVR_ASSERT(hPrivate != NULL);
427         psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
428
429         /* Write remap config1 register */
430         RGXWriteReg64(hPrivate,
431                       ui32Config1RegAddr,
432                       ui64Config1RegValue);
433
434         /* Write remap config2 register */
435         RGXWriteRemapConfig2Reg(psDevInfo->pvRegsBaseKM,
436                                 psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
437                                 psDevInfo->psRGXFWCodeMemDesc->uiOffset + ui32BootRemapMemOffset,
438                                 ui32Config2RegAddr,
439                                 ui64Config2PhyAddr,
440                                 ui64Config2PhyMask,
441                                 ui64Config2Settings);
442 }
443
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)
451 {
452         PVRSRV_RGXDEV_INFO *psDevInfo;
453         IMG_UINT32 ui32CodeRemapMemOffset = RGXMIPSFW_EXCEPTIONSVECTORS_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
454
455         PVR_ASSERT(hPrivate != NULL);
456         psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
457
458         /* Write remap config1 register */
459         RGXWriteReg64(hPrivate,
460                       ui32Config1RegAddr,
461                       ui64Config1RegValue);
462
463         /* Write remap config2 register */
464         RGXWriteRemapConfig2Reg(psDevInfo->pvRegsBaseKM,
465                                 psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR,
466                                 psDevInfo->psRGXFWCodeMemDesc->uiOffset + ui32CodeRemapMemOffset,
467                                 ui32Config2RegAddr,
468                                 ui64Config2PhyAddr,
469                                 ui64Config2PhyMask,
470                                 ui64Config2Settings);
471 }
472
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)
480 {
481         PVRSRV_RGXDEV_INFO *psDevInfo;
482         IMG_UINT32 ui32DataRemapMemOffset = RGXMIPSFW_BOOT_NMI_DATA_BASE_PAGE * (IMG_UINT32)RGXMIPSFW_PAGE_SIZE;
483
484         PVR_ASSERT(hPrivate != NULL);
485         psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
486
487         /* Write remap config1 register */
488         RGXWriteReg64(hPrivate,
489                       ui32Config1RegAddr,
490                       ui64Config1RegValue);
491
492         /* Write remap config2 register */
493         RGXWriteRemapConfig2Reg(psDevInfo->pvRegsBaseKM,
494                                 psDevInfo->psRGXFWDataMemDesc->psImport->hPMR,
495                                 psDevInfo->psRGXFWDataMemDesc->uiOffset + ui32DataRemapMemOffset,
496                                 ui32Config2RegAddr,
497                                 ui64Config2PhyAddr,
498                                 ui64Config2PhyMask,
499                                 ui64Config2Settings);
500 }
501 #endif
502
503
504
505 #define MAX_NUM_COHERENCY_TESTS  (10)
506 IMG_BOOL RGXDoFWSlaveBoot(const void *hPrivate)
507 {
508         PVRSRV_RGXDEV_INFO *psDevInfo;
509         PVRSRV_DEVICE_CONFIG *psDevConfig;
510
511         PVR_ASSERT(hPrivate != NULL);
512         psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
513
514         if (psDevInfo->ui32CoherencyTestsDone >= MAX_NUM_COHERENCY_TESTS)
515         {
516                 return IMG_FALSE;
517         }
518
519         psDevConfig = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevConfig;
520
521         return PVRSRVSystemSnoopingOfCPUCache(psDevConfig);
522 }
523
524 PVRSRV_ERROR RGXIOCoherencyTest(const void *hPrivate)
525 {
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;
535
536         PVR_ASSERT(hPrivate != NULL);
537         psDevInfo = ((RGX_POWER_LAYER_PARAMS*)hPrivate)->psDevInfo;
538
539         /* Size and align are 'expanded' because we request an export align allocation */
540         DevmemExportalignAdjustSizeAndAlign(DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareHeap),
541                                             &uiCoherencyBlockSize,
542                                             &uiCoherencyBlockAlign);
543
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);
560
561         eError = DevmemAcquireCpuVirtAddr(psIOCoherencyTestMemDesc,
562                                           (void **) &pui32CpuVirtAddr);
563         PVR_ASSERT(eError == PVRSRV_OK);
564
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).
569          */
570         {
571                 RGXSetFirmwareAddress(&sCoherencyTestBuffer,
572                                       psIOCoherencyTestMemDesc,
573                                       0,
574                                       RFW_FWADDR_FLAG_NONE);
575
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;
580
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;
584         }
585
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);
591
592         for (ui32TestNum = 1; ui32TestNum < 3; ui32TestNum++)
593         {
594                 IMG_UINT32 i;
595                 IMG_BOOL bPassed = IMG_TRUE;
596
597                 PVR_LOG(("Startup I/O Coherency Test [pass #%u]", ui32TestNum));
598
599                 for (i = 0; i < uiCoherencyBlockSize/sizeof(IMG_UINT32); i++)
600                 {
601                         IMG_UINT32 ui32FWAddr, ui32FWValue;
602                         PVRSRV_ERROR eError2;
603
604                         /* Ensures line is in dcache */
605                         ui32FWValue = pui32CpuVirtAddr[i];
606
607                         /* Dirty allocation in dcache */
608                         pui32CpuVirtAddr[i] = i + ui32TestNum;
609
610                         /* Flush possible cpu store-buffer(ing) */
611                         OSWriteMemoryBarrier();
612
613                         /* Read back value using RGX slave-port interface */
614                         ui32FWAddr = sCoherencyTestBuffer.ui32Addr + (i * sizeof(IMG_UINT32));
615
616                         eError2 = RGXReadMETAAddr(psDevInfo, ui32FWAddr, &ui32FWValue);
617
618                         if (eError2 != PVRSRV_OK)
619                         {
620                                 PVR_DPF((PVR_DBG_ERROR, "RGXReadWithSP error: %s",
621                                          PVRSRVGetErrorStringKM(eError2)));
622                         }
623
624                         /* Compare to see if I/O coherency worked */
625                         if (pui32CpuVirtAddr[i] != ui32FWValue)
626                         {
627                                 PVR_DPF((PVR_DBG_ERROR, "Expected: %x, Got: %x",
628                                          pui32CpuVirtAddr[i], ui32FWValue));
629
630                                 bPassed = IMG_FALSE;
631                                 eError = PVRSRV_ERROR_INIT_FAILURE;
632                         }
633                 }
634
635                 PVR_LOG(("I/O Coherency Test [pass #%u] completed, Passed? %d",
636                          ui32TestNum, bPassed));
637         }
638
639         /* Restore SLC bypass settings */
640         RGXWriteReg32(hPrivate, RGX_CR_SLC_CTRL_BYPASS, ui32SLCCTRL);
641
642         RGXUnsetFirmwareAddress(psIOCoherencyTestMemDesc);
643         DevmemReleaseCpuVirtAddr(psIOCoherencyTestMemDesc);
644         DevmemFwFree(psDevInfo, psIOCoherencyTestMemDesc);
645
646         if (eError == PVRSRV_OK)
647         {
648                 PVR_LOG(("I/O Coherency Test succeeded"));
649                 psDevInfo->ui32CoherencyTestsDone = MAX_NUM_COHERENCY_TESTS + 1;
650         }
651         else
652         {
653                 PVR_LOG(("I/O Coherency Test FAILED"));
654                 psDevInfo->ui32CoherencyTestsDone++;
655         }
656
657         return eError;
658 }
659
660 IMG_BOOL RGXDeviceHasFeaturePower(const void *hPrivate, IMG_UINT64 ui64Feature)
661 {
662         RGX_POWER_LAYER_PARAMS *psPowerParams;
663         PVRSRV_RGXDEV_INFO *psDevInfo;
664
665         PVR_ASSERT(hPrivate != NULL);
666         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
667         psDevInfo = psPowerParams->psDevInfo;
668
669         return (psDevInfo->sDevFeatureCfg.ui64Features & ui64Feature) != 0;
670 }
671
672 IMG_BOOL RGXDeviceHasErnBrnPower(const void *hPrivate, IMG_UINT64 ui64ErnsBrns)
673 {
674         RGX_POWER_LAYER_PARAMS *psPowerParams;
675         PVRSRV_RGXDEV_INFO *psDevInfo;
676
677         PVR_ASSERT(hPrivate != NULL);
678         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
679         psDevInfo = psPowerParams->psDevInfo;
680
681         return (psDevInfo->sDevFeatureCfg.ui64ErnsBrns & ui64ErnsBrns) != 0;
682 }
683
684 IMG_UINT32 RGXGetDeviceSLCBanks(const void *hPrivate)
685 {
686         RGX_POWER_LAYER_PARAMS *psPowerParams;
687         PVRSRV_RGXDEV_INFO *psDevInfo;
688
689         PVR_ASSERT(hPrivate != NULL);
690         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
691         psDevInfo = psPowerParams->psDevInfo;
692
693         return psDevInfo->sDevFeatureCfg.ui32SLCBanks;
694 }
695
696 IMG_UINT32 RGXGetDeviceSLCSize(const void *hPrivate)
697 {
698         RGX_POWER_LAYER_PARAMS *psPowerParams;
699         PVRSRV_RGXDEV_INFO *psDevInfo;
700
701         PVR_ASSERT(hPrivate != NULL);
702         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
703         psDevInfo = psPowerParams->psDevInfo;
704
705         return psDevInfo->sDevFeatureCfg.ui32SLCSize;
706 }
707
708 IMG_UINT32 RGXGetDeviceCacheLineSize(const void *hPrivate)
709 {
710         RGX_POWER_LAYER_PARAMS *psPowerParams;
711         PVRSRV_RGXDEV_INFO *psDevInfo;
712
713         PVR_ASSERT(hPrivate != NULL);
714         psPowerParams = (RGX_POWER_LAYER_PARAMS*)hPrivate;
715         psDevInfo = psPowerParams->psDevInfo;
716
717         return psDevInfo->sDevFeatureCfg.ui32CacheLineSize;
718 }
719