RK3368 GPU: Rogue N Init.
[firefly-linux-kernel-4.4.55.git] / drivers / staging / imgtec / apollo / sysconfig.c
1 /*************************************************************************/ /*!
2 @File
3 @Title          System Configuration
4 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
5 @Description    System Configuration functions
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 #include "sysinfo.h"
45 #include "apollo_regs.h"
46
47 #include "pvrsrv_device.h"
48 #include "rgxdevice.h"
49 #include "syscommon.h"
50 #include "allocmem.h"
51 #include "pvr_debug.h"
52
53 #if defined(SUPPORT_ION)
54 #include PVR_ANDROID_ION_HEADER
55 #include "ion_support.h"
56 #include "ion_sys.h"
57 #endif
58
59 #include "apollo_drv.h"
60
61 #include <linux/platform_device.h>
62
63 #if !defined(LMA)
64 #error Apollo only supports LMA at the minute
65 #endif
66
67 /* Valid values for the TC_MEMORY_CONFIG configuration option */
68 #define TC_MEMORY_LOCAL         (1)
69 #define TC_MEMORY_HOST          (2)
70 #define TC_MEMORY_HYBRID        (3)
71
72 #if TC_MEMORY_CONFIG != TC_MEMORY_LOCAL
73 #error Apollo only supports TC_MEMORY_LOCAL at the minute
74 #endif
75
76 /* These must be consecutive */
77 #define PHYS_HEAP_IDX_GENERAL   0
78 #define PHYS_HEAP_IDX_DMABUF    1
79 #define PHYS_HEAP_IDX_COUNT             2
80
81 #define SYS_RGX_ACTIVE_POWER_LATENCY_MS (10)
82
83 #if defined(PVR_DVFS) || defined(SUPPORT_PDVFS)
84
85 /* Dummy DVFS configuration used purely for testing purposes */
86
87 static const IMG_OPP asOPPTable[] =
88 {
89         { 8,  25000000},
90         { 16, 50000000},
91         { 32, 75000000},
92         { 64, 100000000},
93 };
94
95 #define LEVEL_COUNT (sizeof(asOPPTable) / sizeof(IMG_OPP))
96
97 static void SetFrequency(IMG_UINT32 ui32Frequency)
98 {
99         PVR_DPF((PVR_DBG_ERROR, "SetFrequency %u", ui32Frequency));
100 }
101
102 static void SetVoltage(IMG_UINT32 ui32Voltage)
103 {
104         PVR_DPF((PVR_DBG_ERROR, "SetVoltage %u", ui32Voltage));
105 }
106
107 #endif
108
109 static void TCLocalCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
110                                       IMG_UINT32 ui32NumOfAddr,
111                                       IMG_DEV_PHYADDR *psDevPAddr,
112                                       IMG_CPU_PHYADDR *psCpuPAddr);
113
114 static void TCLocalDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
115                                       IMG_UINT32 ui32NumOfAddr,
116                                       IMG_CPU_PHYADDR *psCpuPAddr,
117                                       IMG_DEV_PHYADDR *psDevPAddr);
118
119 static IMG_UINT32 TCLocalGetRegionId(IMG_HANDLE hPrivData,
120                                           PVRSRV_MEMALLOCFLAGS_T uiAllocFlags);
121
122 static PHYS_HEAP_FUNCTIONS gsLocalPhysHeapFuncs =
123 {
124         .pfnCpuPAddrToDevPAddr = TCLocalCpuPAddrToDevPAddr,
125         .pfnDevPAddrToCpuPAddr = TCLocalDevPAddrToCpuPAddr,
126         .pfnGetRegionId = TCLocalGetRegionId,
127 };
128
129 static void TCIonCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
130                                     IMG_UINT32 ui32NumOfAddr,
131                                     IMG_DEV_PHYADDR *psDevPAddr,
132                                     IMG_CPU_PHYADDR *psCpuPAddr);
133
134 static void TCIonDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
135                                     IMG_UINT32 ui32NumOfAddr,
136                                     IMG_CPU_PHYADDR *psCpuPAddr,
137                                     IMG_DEV_PHYADDR *psDevPAddr);
138
139 static IMG_UINT32 TCIonGetRegionId(IMG_HANDLE hPrivData,
140                                           PVRSRV_MEMALLOCFLAGS_T uiAllocFlags);
141
142 static PHYS_HEAP_FUNCTIONS gsIonPhysHeapFuncs =
143 {
144         .pfnCpuPAddrToDevPAddr = TCIonCpuPAddrToDevPAddr,
145         .pfnDevPAddrToCpuPAddr = TCIonDevPAddrToCpuPAddr,
146         .pfnGetRegionId = TCIonGetRegionId,
147 };
148
149 /* BIF Tiling mode configuration */
150 static RGXFWIF_BIFTILINGMODE geBIFTilingMode = RGXFWIF_BIFTILINGMODE_256x16;
151
152 /* Default BIF tiling heap x-stride configurations. */
153 static IMG_UINT32 gauiBIFTilingHeapXStrides[RGXFWIF_NUM_BIF_TILING_CONFIGS] =
154 {
155         0, /* BIF tiling heap 1 x-stride */
156         1, /* BIF tiling heap 2 x-stride */
157         2, /* BIF tiling heap 3 x-stride */
158         3  /* BIF tiling heap 4 x-stride */
159 };
160
161 typedef struct _SYS_DATA_ SYS_DATA;
162
163 struct _SYS_DATA_
164 {
165         struct platform_device *pdev;
166
167         struct apollo_rogue_platform_data *pdata;
168
169         struct resource *registers;
170
171 #if defined(SUPPORT_ION)
172         struct ion_client *ion_client;
173         struct ion_handle *ion_rogue_allocation;
174 #endif
175 };
176
177 #define SYSTEM_INFO_FORMAT_STRING       "FPGA Revision: %s\tTCF Core Revision: %s\tTCF Core Target Build ID: %s\tPCI Version: %s\tMacro Version: %s"
178 static IMG_CHAR *GetDeviceVersionString(SYS_DATA *psSysData)
179 {
180         int err;
181         char str_fpga_rev[12];
182         char str_tcf_core_rev[12];
183         char str_tcf_core_target_build_id[4];
184         char str_pci_ver[4];
185         char str_macro_ver[8];
186
187         IMG_CHAR *pszVersion;
188         IMG_UINT32 ui32StringLength;
189
190         err = apollo_sys_strings(psSysData->pdev->dev.parent,
191                                                          str_fpga_rev, sizeof(str_fpga_rev),
192                                                          str_tcf_core_rev, sizeof(str_tcf_core_rev),
193                                                          str_tcf_core_target_build_id, sizeof(str_tcf_core_target_build_id),
194                                                          str_pci_ver, sizeof(str_pci_ver),
195                                                          str_macro_ver, sizeof(str_macro_ver));
196         if (err)
197         {
198                 return NULL;
199         }
200
201         ui32StringLength = OSStringLength(SYSTEM_INFO_FORMAT_STRING);
202         ui32StringLength += OSStringLength(str_fpga_rev);
203         ui32StringLength += OSStringLength(str_tcf_core_rev);
204         ui32StringLength += OSStringLength(str_tcf_core_target_build_id);
205         ui32StringLength += OSStringLength(str_pci_ver);
206         ui32StringLength += OSStringLength(str_macro_ver);
207
208         /* Create the version string */
209         pszVersion = OSAllocZMem(ui32StringLength * sizeof(IMG_CHAR));
210         if (pszVersion)
211         {
212                 OSSNPrintf(&pszVersion[0], ui32StringLength,
213                                    SYSTEM_INFO_FORMAT_STRING,
214                                    str_fpga_rev,
215                                    str_tcf_core_rev,
216                                    str_tcf_core_target_build_id,
217                                    str_pci_ver,
218                                    str_macro_ver);
219         }
220
221         return pszVersion;
222 }
223
224 #if defined(SUPPORT_ION)
225 static SYS_DATA *gpsIonPrivateData;
226
227 PVRSRV_ERROR IonInit(void *pvPrivateData)
228 {
229         PVRSRV_ERROR eError = PVRSRV_OK;
230         SYS_DATA *psSysData = pvPrivateData;
231         gpsIonPrivateData = psSysData;
232
233         psSysData->ion_client = ion_client_create(psSysData->pdata->ion_device, SYS_RGX_DEV_NAME);
234         if (IS_ERR(psSysData->ion_client))
235         {
236                 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create ION client (%ld)", __func__, PTR_ERR(psSysData->ion_client)));
237                 /* FIXME: Find a better matching error code */
238                 eError = PVRSRV_ERROR_PCI_CALL_FAILED;
239                 goto err_out;
240         }
241         /* Allocate the whole rogue ion heap and pass that to services to manage */
242         psSysData->ion_rogue_allocation = ion_alloc(psSysData->ion_client, psSysData->pdata->rogue_heap_memory_size, 4096, (1 << psSysData->pdata->ion_heap_id), 0);
243         if (IS_ERR(psSysData->ion_rogue_allocation))
244         {
245                 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate ION rogue buffer (%ld)", __func__, PTR_ERR(psSysData->ion_rogue_allocation)));
246                 /* FIXME: Find a better matching error code */
247                 eError = PVRSRV_ERROR_PCI_CALL_FAILED;
248                 goto err_destroy_client;
249
250         }
251
252         return PVRSRV_OK;
253 err_destroy_client:
254         ion_client_destroy(psSysData->ion_client);
255         psSysData->ion_client = NULL;
256 err_out:
257         return eError;
258 }
259
260 void IonDeinit(void)
261 {
262         SYS_DATA *psSysData = gpsIonPrivateData;
263         ion_free(psSysData->ion_client, psSysData->ion_rogue_allocation);
264         psSysData->ion_rogue_allocation = NULL;
265         ion_client_destroy(psSysData->ion_client);
266         psSysData->ion_client = NULL;
267 }
268
269 struct ion_device *IonDevAcquire(void)
270 {
271         return gpsIonPrivateData->pdata->ion_device;
272 }
273
274 void IonDevRelease(struct ion_device *ion_device)
275 {
276         PVR_ASSERT(ion_device == gpsIonPrivateData->pdata->ion_device);
277 }
278 #endif /* defined(SUPPORT_ION) */
279
280 static void TCLocalCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
281                                       IMG_UINT32 ui32NumOfAddr,
282                                       IMG_DEV_PHYADDR *psDevPAddr,
283                                       IMG_CPU_PHYADDR *psCpuPAddr)
284 {
285         PVRSRV_DEVICE_CONFIG *psDevConfig = (PVRSRV_DEVICE_CONFIG *)hPrivData;
286
287         /* Optimise common case */
288         psDevPAddr[0].uiAddr = psCpuPAddr[0].uiAddr - psDevConfig->pasPhysHeaps[0].pasRegions[0].sStartAddr.uiAddr;
289         if (ui32NumOfAddr > 1)
290         {
291                 IMG_UINT32 ui32Idx;
292                 for (ui32Idx = 1; ui32Idx < ui32NumOfAddr; ++ui32Idx)
293                 {
294                         psDevPAddr[ui32Idx].uiAddr = psCpuPAddr[ui32Idx].uiAddr - psDevConfig->pasPhysHeaps[0].pasRegions[0].sStartAddr.uiAddr;
295                 }
296         }
297 }
298
299 static void TCLocalDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
300                                       IMG_UINT32 ui32NumOfAddr,
301                                       IMG_CPU_PHYADDR *psCpuPAddr,
302                                       IMG_DEV_PHYADDR *psDevPAddr)
303 {
304         PVRSRV_DEVICE_CONFIG *psDevConfig = (PVRSRV_DEVICE_CONFIG *)hPrivData;
305         
306         /* Optimise common case */
307         psCpuPAddr[0].uiAddr = psDevPAddr[0].uiAddr + psDevConfig->pasPhysHeaps[0].pasRegions[0].sStartAddr.uiAddr;
308         if (ui32NumOfAddr > 1)
309         {
310                 IMG_UINT32 ui32Idx;
311                 for (ui32Idx = 1; ui32Idx < ui32NumOfAddr; ++ui32Idx)
312                 {
313                         psCpuPAddr[ui32Idx].uiAddr = psDevPAddr[ui32Idx].uiAddr + psDevConfig->pasPhysHeaps[0].pasRegions[0].sStartAddr.uiAddr;
314                 }
315         }
316 }
317
318 static IMG_UINT32 TCLocalGetRegionId(IMG_HANDLE hPrivData,
319                                           PVRSRV_MEMALLOCFLAGS_T uiAllocFlags)
320 {
321         /* Return first region which is always valid */
322         return 0;
323 }
324
325 static void TCIonCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
326                                     IMG_UINT32 ui32NumOfAddr,
327                                     IMG_DEV_PHYADDR *psDevPAddr,
328                                     IMG_CPU_PHYADDR *psCpuPAddr)
329 {
330         PVRSRV_DEVICE_CONFIG *psDevConfig = (PVRSRV_DEVICE_CONFIG *)hPrivData;
331         SYS_DATA *psSysData = psDevConfig->hSysData;
332         
333         /* Optimise common case */
334         psDevPAddr[0].uiAddr = psCpuPAddr[0].uiAddr - psSysData->pdata->apollo_memory_base;     
335         if (ui32NumOfAddr > 1)
336         {
337                 IMG_UINT32 ui32Idx;
338                 for (ui32Idx = 1; ui32Idx < ui32NumOfAddr; ++ui32Idx)
339                 {
340                         psDevPAddr[ui32Idx].uiAddr = psCpuPAddr[ui32Idx].uiAddr - psSysData->pdata->apollo_memory_base;
341                 }
342         }
343 }
344
345 static void TCIonDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
346                                     IMG_UINT32 ui32NumOfAddr,
347                                     IMG_CPU_PHYADDR *psCpuPAddr,
348                                     IMG_DEV_PHYADDR *psDevPAddr)
349 {
350         PVRSRV_DEVICE_CONFIG *psDevConfig = (PVRSRV_DEVICE_CONFIG *)hPrivData;
351         SYS_DATA *psSysData = psDevConfig->hSysData;
352
353         /* Optimise common case */
354         psCpuPAddr[0].uiAddr = psDevPAddr[0].uiAddr + psSysData->pdata->apollo_memory_base;
355         if (ui32NumOfAddr > 1)
356         {
357                 IMG_UINT32 ui32Idx;
358                 for (ui32Idx = 1; ui32Idx < ui32NumOfAddr; ++ui32Idx)
359                 {
360                         psCpuPAddr[ui32Idx].uiAddr = psDevPAddr[ui32Idx].uiAddr + psSysData->pdata->apollo_memory_base;
361                 }
362         }
363 }
364
365 static IMG_UINT32 TCIonGetRegionId(IMG_HANDLE hPrivData,
366                                           PVRSRV_MEMALLOCFLAGS_T uiAllocFlags)
367 {
368         /* Return first region which is always valid */
369         return 0;
370 }
371
372 static PVRSRV_ERROR PhysHeapsCreate(SYS_DATA *psSysData,
373                                                                         void *pvPrivData,
374                                                                         PHYS_HEAP_CONFIG **ppasPhysHeapsOut,
375                                                                         IMG_UINT32 *puiPhysHeapCountOut)
376 {
377         static IMG_UINT32 uiHeapIDBase = 0;
378         PHYS_HEAP_CONFIG *pasPhysHeaps;
379         PHYS_HEAP_REGION *psRegion;
380         PVRSRV_ERROR eError;
381
382         pasPhysHeaps = OSAllocMem(sizeof(*pasPhysHeaps) * PHYS_HEAP_IDX_COUNT);
383         if (!pasPhysHeaps)
384         {
385                 return PVRSRV_ERROR_OUT_OF_MEMORY;
386         }
387
388         psRegion = OSAllocMem(sizeof(*psRegion));
389         if (!psRegion)
390         {
391                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
392                 goto ErrorFreePhysHeaps;
393         }
394
395         psRegion->sStartAddr.uiAddr = psSysData->pdata->rogue_heap_memory_base;
396         psRegion->sCardBase.uiAddr = 0;
397         psRegion->uiSize = psSysData->pdata->rogue_heap_memory_size;
398
399         pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].ui32PhysHeapID =
400                 uiHeapIDBase + PHYS_HEAP_IDX_GENERAL;
401         pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].eType = PHYS_HEAP_TYPE_LMA;
402         pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].pszPDumpMemspaceName = "LMA";
403         pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].psMemFuncs = &gsLocalPhysHeapFuncs;
404         pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].pasRegions = psRegion;
405         pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].ui32NumOfRegions = 1;
406         pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].hPrivData = pvPrivData;
407
408         psRegion = OSAllocMem(sizeof(*psRegion));
409         if (!psRegion)
410         {
411                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
412                 goto ErrorGeneralPhysHeapDestroy;
413         }
414
415         psRegion->sStartAddr.uiAddr = psSysData->pdata->pdp_heap_memory_base;
416         psRegion->sCardBase.uiAddr = 0;
417         psRegion->uiSize = psSysData->pdata->pdp_heap_memory_size;
418
419         pasPhysHeaps[PHYS_HEAP_IDX_DMABUF].ui32PhysHeapID =
420                 uiHeapIDBase + PHYS_HEAP_IDX_DMABUF;
421         pasPhysHeaps[PHYS_HEAP_IDX_DMABUF].eType = PHYS_HEAP_TYPE_LMA;
422         pasPhysHeaps[PHYS_HEAP_IDX_DMABUF].pszPDumpMemspaceName = "LMA";
423         pasPhysHeaps[PHYS_HEAP_IDX_DMABUF].psMemFuncs = &gsIonPhysHeapFuncs;
424         pasPhysHeaps[PHYS_HEAP_IDX_DMABUF].pasRegions = psRegion;
425         pasPhysHeaps[PHYS_HEAP_IDX_DMABUF].ui32NumOfRegions = 1;
426         pasPhysHeaps[PHYS_HEAP_IDX_DMABUF].hPrivData = pvPrivData;
427
428         uiHeapIDBase += PHYS_HEAP_IDX_COUNT;
429
430         *ppasPhysHeapsOut = pasPhysHeaps;
431         *puiPhysHeapCountOut = PHYS_HEAP_IDX_COUNT;
432
433         return PVRSRV_OK;
434
435 ErrorGeneralPhysHeapDestroy:
436         OSFreeMem(pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].pasRegions);
437
438 ErrorFreePhysHeaps:
439         OSFreeMem(pasPhysHeaps);
440         return eError;
441 }
442
443 static void PhysHeapsDestroy(PHYS_HEAP_CONFIG *pasPhysHeaps,
444                                                          IMG_UINT32 uiPhysHeapCount)
445 {
446         IMG_UINT32 i;
447
448         for (i = 0; i < uiPhysHeapCount; i++)
449         {
450                 if (pasPhysHeaps[i].pasRegions)
451                 {
452                         OSFreeMem(pasPhysHeaps[i].pasRegions);
453                 }
454         }
455
456         OSFreeMem(pasPhysHeaps);
457 }
458
459 static PVRSRV_ERROR DeviceConfigCreate(SYS_DATA *psSysData,
460                                                                            PVRSRV_DEVICE_CONFIG **ppsDevConfigOut)
461 {
462         PVRSRV_DEVICE_CONFIG *psDevConfig;
463         RGX_DATA *psRGXData;
464         RGX_TIMING_INFORMATION *psRGXTimingInfo;
465         PHYS_HEAP_CONFIG *pasPhysHeaps;
466         IMG_UINT32 uiPhysHeapCount;
467         PVRSRV_ERROR eError;
468
469         psDevConfig = OSAllocZMem(sizeof(*psDevConfig) +
470                                                           sizeof(*psRGXData) +
471                                                           sizeof(*psRGXTimingInfo));
472         if (!psDevConfig)
473         {
474                 return PVRSRV_ERROR_OUT_OF_MEMORY;
475         }
476
477         psRGXData = (RGX_DATA *)((IMG_CHAR *)psDevConfig + sizeof(*psDevConfig));
478         psRGXTimingInfo = (RGX_TIMING_INFORMATION *)((IMG_CHAR *)psRGXData + sizeof(*psRGXData));
479
480         eError = PhysHeapsCreate(psSysData, psDevConfig, &pasPhysHeaps, &uiPhysHeapCount);
481         if (eError != PVRSRV_OK)
482         {
483                 goto ErrorFreeDevConfig;
484         }
485
486         /* Setup RGX specific timing data */
487         psRGXTimingInfo->ui32CoreClockSpeed = apollo_core_clock_speed(&psSysData->pdev->dev) * 6;
488         psRGXTimingInfo->bEnableActivePM = IMG_FALSE;
489         psRGXTimingInfo->bEnableRDPowIsland = IMG_FALSE;
490         psRGXTimingInfo->ui32ActivePMLatencyms = SYS_RGX_ACTIVE_POWER_LATENCY_MS;
491
492         /* Set up the RGX data */
493         psRGXData->psRGXTimingInfo = psRGXTimingInfo;
494
495         /* Setup the device config */
496         psDevConfig->pvOSDevice = &psSysData->pdev->dev;
497         psDevConfig->pszName = "apollo";
498         psDevConfig->pszVersion = GetDeviceVersionString(psSysData);
499
500         psDevConfig->sRegsCpuPBase.uiAddr = psSysData->registers->start;
501         psDevConfig->ui32RegsSize = resource_size(psSysData->registers);
502
503         psDevConfig->ui32IRQ = APOLLO_INTERRUPT_EXT;
504
505         psDevConfig->eCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_NONE;
506
507         psDevConfig->pasPhysHeaps = pasPhysHeaps;
508         psDevConfig->ui32PhysHeapCount = uiPhysHeapCount;
509
510         psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_GPU_LOCAL] =
511                 pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].ui32PhysHeapID;
512         psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL] =
513                 pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].ui32PhysHeapID;
514         psDevConfig->aui32PhysHeapID[PVRSRV_DEVICE_PHYS_HEAP_FW_LOCAL] =
515                 pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].ui32PhysHeapID;
516
517         psDevConfig->eBIFTilingMode = geBIFTilingMode;
518         psDevConfig->pui32BIFTilingHeapConfigs = &gauiBIFTilingHeapXStrides[0];
519         psDevConfig->ui32BIFTilingHeapCount = IMG_ARR_NUM_ELEMS(gauiBIFTilingHeapXStrides);
520
521         psDevConfig->hDevData = psRGXData;
522         psDevConfig->hSysData = psSysData;
523
524 #if defined(PVR_DVFS) || defined(SUPPORT_PDVFS)
525         /* Dummy DVFS configuration used purely for testing purposes */
526         psDevConfig->sDVFS.sDVFSDeviceCfg.pasOPPTable = asOPPTable;
527         psDevConfig->sDVFS.sDVFSDeviceCfg.ui32OPPTableSize = LEVEL_COUNT;
528         psDevConfig->sDVFS.sDVFSDeviceCfg.pfnSetFrequency = SetFrequency;
529         psDevConfig->sDVFS.sDVFSDeviceCfg.pfnSetVoltage = SetVoltage;
530 #endif
531 #if defined(PVR_DVFS)
532         psDevConfig->sDVFS.sDVFSDeviceCfg.ui32PollMs = 1000;
533         psDevConfig->sDVFS.sDVFSDeviceCfg.bIdleReq = IMG_TRUE;
534         psDevConfig->sDVFS.sDVFSGovernorCfg.ui32UpThreshold = 90;
535         psDevConfig->sDVFS.sDVFSGovernorCfg.ui32DownDifferential = 10;
536 #endif
537
538         *ppsDevConfigOut = psDevConfig;
539
540         return PVRSRV_OK;
541
542 ErrorFreeDevConfig:
543         OSFreeMem(psDevConfig);
544         return eError;
545 }
546
547 static void DeviceConfigDestroy(PVRSRV_DEVICE_CONFIG *psDevConfig)
548 {
549         if (psDevConfig->pszVersion)
550         {
551                 OSFreeMem(psDevConfig->pszVersion);
552         }
553
554         PhysHeapsDestroy(psDevConfig->pasPhysHeaps, psDevConfig->ui32PhysHeapCount);
555
556         OSFreeMem(psDevConfig);
557 }
558
559 PVRSRV_ERROR SysDevInit(void *pvOSDevice, PVRSRV_DEVICE_CONFIG **ppsDevConfig)
560 {
561         PVRSRV_DEVICE_CONFIG *psDevConfig;
562         SYS_DATA *psSysData;
563         resource_size_t uiRegistersSize;
564         PVRSRV_ERROR eError;
565         int err = 0;
566
567         PVR_ASSERT(pvOSDevice);
568
569         psSysData = OSAllocZMem(sizeof(*psSysData));
570         if (psSysData == NULL)
571         {
572                 return PVRSRV_ERROR_OUT_OF_MEMORY;
573         }
574
575         psSysData->pdev = to_platform_device((struct device *)pvOSDevice);
576         psSysData->pdata = psSysData->pdev->dev.platform_data;
577
578         err = apollo_enable(psSysData->pdev->dev.parent);
579         if (err)
580         {
581                 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to enable PCI device (%d)", __func__, err));
582                 eError = PVRSRV_ERROR_PCI_CALL_FAILED;
583                 goto ErrFreeSysData;
584         }
585
586         psSysData->registers = platform_get_resource_byname(psSysData->pdev,
587                                                                                                                 IORESOURCE_MEM,
588                                                                                                                 "rogue-regs");
589         if (!psSysData->registers)
590         {
591                 PVR_DPF((PVR_DBG_ERROR,
592                                  "%s: Failed to get Rogue register information",
593                                  __func__));
594                 eError = PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
595                 goto ErrorDevDisable;
596         }
597
598         /* Check the address range is large enough. */
599         uiRegistersSize = resource_size(psSysData->registers);
600         if (uiRegistersSize < SYS_RGX_REG_REGION_SIZE)
601         {
602                 PVR_DPF((PVR_DBG_ERROR,
603                                  "%s: Rogue register region isn't big enough (was %pa, required 0x%08x)",
604                                  __FUNCTION__, &uiRegistersSize, SYS_RGX_REG_REGION_SIZE));
605
606                 eError = PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
607                 goto ErrorDevDisable;
608         }
609
610         /* Reserve the address range */
611         if (!request_mem_region(psSysData->registers->start,
612                                                         resource_size(psSysData->registers),
613                                                         SYS_RGX_DEV_NAME))
614         {
615                 PVR_DPF((PVR_DBG_ERROR, "%s: Rogue register memory region not available", __FUNCTION__));
616                 eError = PVRSRV_ERROR_PCI_CALL_FAILED;
617
618                 goto ErrorDevDisable;
619         }
620
621         eError = DeviceConfigCreate(psSysData, &psDevConfig);
622         if (eError != PVRSRV_OK)
623         {
624                 goto ErrorReleaseMemRegion;
625         }
626
627 #if defined(SUPPORT_ION)
628         eError = IonInit(psSysData);
629         if (eError != PVRSRV_OK)
630         {
631                 PVR_DPF((PVR_DBG_ERROR, "%s: Failed to initialise ION", __func__));
632                 goto ErrorDeviceConfigDestroy;
633         }
634 #endif
635
636         *ppsDevConfig = psDevConfig;
637
638         return PVRSRV_OK;
639
640 #if defined(SUPPORT_ION)
641 ErrorDeviceConfigDestroy:
642         DeviceConfigDestroy(psDevConfig);
643 #endif
644 ErrorReleaseMemRegion:
645         release_mem_region(psSysData->registers->start,
646                                            resource_size(psSysData->registers));
647 ErrorDevDisable:
648         apollo_disable(psSysData->pdev->dev.parent);
649 ErrFreeSysData:
650         OSFreeMem(psSysData);
651         return eError;
652 }
653
654 void SysDevDeInit(PVRSRV_DEVICE_CONFIG *psDevConfig)
655 {
656         SYS_DATA *psSysData = (SYS_DATA *)psDevConfig->hSysData;
657
658 #if defined(SUPPORT_ION)
659         IonDeinit();
660 #endif
661
662         DeviceConfigDestroy(psDevConfig);
663
664         release_mem_region(psSysData->registers->start,
665                                            resource_size(psSysData->registers));
666         apollo_disable(psSysData->pdev->dev.parent);
667
668         OSFreeMem(psSysData);
669 }
670
671 PVRSRV_ERROR SysDebugInfo(PVRSRV_DEVICE_CONFIG *psDevConfig,
672                                 DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
673                                 void *pvDumpDebugFile)
674 {
675 #if defined(TC_APOLLO_TCF5)
676         PVR_UNREFERENCED_PARAMETER(psDevConfig);
677         PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
678         return PVRSRV_OK;
679 #else
680         SYS_DATA *psSysData = psDevConfig->hSysData;
681         PVRSRV_ERROR eError = PVRSRV_OK;
682         u32 tmp = 0;
683         u32 pll;
684
685         PVR_DUMPDEBUG_LOG("------[ rgx_tc system debug ]------");
686
687         if (apollo_sys_info(psSysData->pdev->dev.parent, &tmp, &pll))
688                 goto err_out;
689
690         if (tmp > 0)
691                 PVR_DUMPDEBUG_LOG("Chip temperature: %d degrees C", tmp);
692         PVR_DUMPDEBUG_LOG("PLL status: %x", pll);
693
694 err_out:
695         return eError;
696 #endif
697 }
698
699 typedef struct
700 {
701         struct device *psDev;
702         int iInterruptID;
703         void *pvData;
704         PFN_LISR pfnLISR;
705 } LISR_DATA;
706
707 static void ApolloInterruptHandler(void* pvData)
708 {
709         LISR_DATA *psLISRData = pvData;
710         psLISRData->pfnLISR(psLISRData->pvData);
711 }
712
713 PVRSRV_ERROR SysInstallDeviceLISR(IMG_HANDLE hSysData,
714                                   IMG_UINT32 ui32IRQ,
715                                   const IMG_CHAR *pszName,
716                                   PFN_LISR pfnLISR,
717                                   void *pvData,
718                                   IMG_HANDLE *phLISRData)
719 {
720         SYS_DATA *psSysData = (SYS_DATA *)hSysData;
721         LISR_DATA *psLISRData;
722         PVRSRV_ERROR eError;
723         int err;
724
725         if (ui32IRQ != APOLLO_INTERRUPT_EXT)
726         {
727                 PVR_DPF((PVR_DBG_ERROR, "%s: No device matching IRQ %d", __func__, ui32IRQ));
728                 return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
729         }
730
731         psLISRData = OSAllocZMem(sizeof(*psLISRData));
732         if (!psLISRData)
733         {
734                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
735                 goto err_out;
736         }
737
738         psLISRData->pfnLISR = pfnLISR;
739         psLISRData->pvData = pvData;
740         psLISRData->iInterruptID = ui32IRQ;
741         psLISRData->psDev = psSysData->pdev->dev.parent;
742
743         err = apollo_set_interrupt_handler(psLISRData->psDev, psLISRData->iInterruptID, ApolloInterruptHandler, psLISRData);
744         if (err)
745         {
746                 PVR_DPF((PVR_DBG_ERROR, "%s: apollo_set_interrupt_handler() failed (%d)", __func__, err));
747                 eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
748                 goto err_free_data;
749         }
750
751         err = apollo_enable_interrupt(psLISRData->psDev, psLISRData->iInterruptID);
752         if (err)
753         {
754                 PVR_DPF((PVR_DBG_ERROR, "%s: apollo_enable_interrupt() failed (%d)", __func__, err));
755                 eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
756                 goto err_unset_interrupt_handler;
757         }
758
759         *phLISRData = psLISRData;
760         eError = PVRSRV_OK;
761
762         PVR_TRACE(("Installed device LISR %pf to irq %u", pfnLISR, ui32IRQ));
763
764 err_out:
765         return eError;
766 err_unset_interrupt_handler:
767         apollo_set_interrupt_handler(psLISRData->psDev, psLISRData->iInterruptID, NULL, NULL);
768 err_free_data:
769         OSFreeMem(psLISRData);
770         goto err_out;
771 }
772
773 PVRSRV_ERROR SysUninstallDeviceLISR(IMG_HANDLE hLISRData)
774 {
775         LISR_DATA *psLISRData = (LISR_DATA *) hLISRData;
776         int err;
777
778         err = apollo_disable_interrupt(psLISRData->psDev, psLISRData->iInterruptID);
779         if (err)
780         {
781                 PVR_DPF((PVR_DBG_ERROR, "%s: apollo_enable_interrupt() failed (%d)", __func__, err));
782         }
783
784         err = apollo_set_interrupt_handler(psLISRData->psDev, psLISRData->iInterruptID, NULL, NULL);
785         if (err)
786         {
787                 PVR_DPF((PVR_DBG_ERROR, "%s: apollo_set_interrupt_handler() failed (%d)", __func__, err));
788         }
789
790         PVR_TRACE(("Uninstalled device LISR %pf from irq %u", psLISRData->pfnLISR, psLISRData->iInterruptID));
791
792         OSFreeMem(psLISRData);
793
794         return PVRSRV_OK;
795 }