1 /****************************************************************************
3 * Copyright (C) 2005 - 2013 by Vivante Corp.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the license, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *****************************************************************************/
22 #include "gc_hal_kernel_linux.h"
23 #include <linux/pagemap.h>
24 #include <linux/seq_file.h>
26 #include <linux/mman.h>
27 #include <linux/slab.h>
28 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
29 #include <mach/hardware.h>
31 #include <linux/pm_runtime.h>
33 #define _GC_OBJ_ZONE gcvZONE_DEVICE
35 #define DEBUG_FILE "galcore_trace"
36 #define PARENT_FILE "gpu"
40 static struct dove_gpio_irq_handler gc500_handle;
43 #define gcmIS_CORE_PRESENT(Device, Core) (Device->irqLines[Core] > 0)
45 /******************************************************************************\
46 *************************** Memory Allocation Wrappers *************************
47 \******************************************************************************/
51 IN gckGALDEVICE Device,
53 OUT gctPOINTER *Logical,
54 OUT gctPHYS_ADDR *Physical,
55 OUT gctUINT32 *PhysAddr
60 gcmkHEADER_ARG("Device=0x%x Bytes=%lu", Device, Bytes);
62 gcmkVERIFY_ARGUMENT(Device != NULL);
63 gcmkVERIFY_ARGUMENT(Logical != NULL);
64 gcmkVERIFY_ARGUMENT(Physical != NULL);
65 gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
67 gcmkONERROR(gckOS_AllocateContiguous(
68 Device->os, gcvFALSE, &Bytes, Physical, Logical
71 *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle - Device->baseAddress;
75 "*Logical=0x%x *Physical=0x%x *PhysAddr=0x%08x",
76 *Logical, *Physical, *PhysAddr
88 IN gckGALDEVICE Device,
89 IN gctPOINTER Logical,
90 IN gctPHYS_ADDR Physical)
94 gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
95 Device, Logical, Physical);
97 gcmkVERIFY_ARGUMENT(Device != NULL);
99 status = gckOS_FreeContiguous(
100 Device->os, Physical, Logical,
101 ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
110 /******************************************************************************\
111 ******************************* Interrupt Handler ******************************
112 \******************************************************************************/
113 static irqreturn_t isrRoutine(int irq, void *ctxt)
118 device = (gckGALDEVICE) ctxt;
120 /* Call kernel interrupt notification. */
121 status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvTRUE);
123 if (gcmIS_SUCCESS(status))
125 device->dataReadys[gcvCORE_MAJOR] = gcvTRUE;
127 up(&device->semas[gcvCORE_MAJOR]);
135 static int threadRoutine(void *ctxt)
137 gckGALDEVICE device = (gckGALDEVICE) ctxt;
139 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
140 "Starting isr Thread with extension=%p",
147 down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
148 if (down); /*To make gcc 4.6 happye*/
149 device->dataReadys[gcvCORE_MAJOR] = gcvFALSE;
151 if (device->killThread == gcvTRUE)
153 /* The daemon exits. */
154 while (!kthread_should_stop())
156 gckOS_Delay(device->os, 1);
162 gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvFALSE);
166 static irqreturn_t isrRoutine2D(int irq, void *ctxt)
171 device = (gckGALDEVICE) ctxt;
173 /* Call kernel interrupt notification. */
174 status = gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvTRUE);
176 if (gcmIS_SUCCESS(status))
178 device->dataReadys[gcvCORE_2D] = gcvTRUE;
180 up(&device->semas[gcvCORE_2D]);
188 static int threadRoutine2D(void *ctxt)
190 gckGALDEVICE device = (gckGALDEVICE) ctxt;
192 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
193 "Starting isr Thread with extension=%p",
200 down = down_interruptible(&device->semas[gcvCORE_2D]);
201 if (down); /*To make gcc 4.6 happye*/
202 device->dataReadys[gcvCORE_2D] = gcvFALSE;
204 if (device->killThread == gcvTRUE)
206 /* The daemon exits. */
207 while (!kthread_should_stop())
209 gckOS_Delay(device->os, 1);
215 gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvFALSE);
219 static irqreturn_t isrRoutineVG(int irq, void *ctxt)
225 device = (gckGALDEVICE) ctxt;
227 /* Serve the interrupt. */
228 status = gckVGINTERRUPT_Enque(device->kernels[gcvCORE_VG]->vg->interrupt);
230 /* Determine the return value. */
231 return (status == gcvSTATUS_NOT_OUR_INTERRUPT)
239 static int threadRoutineVG(void *ctxt)
241 gckGALDEVICE device = (gckGALDEVICE) ctxt;
243 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
244 "Starting isr Thread with extension=%p",
251 down = down_interruptible(&device->semas[gcvCORE_VG]);
252 if (down); /*To make gcc 4.6 happye*/
253 device->dataReadys[gcvCORE_VG] = gcvFALSE;
255 if (device->killThread == gcvTRUE)
257 /* The daemon exits. */
258 while (!kthread_should_stop())
260 gckOS_Delay(device->os, 1);
266 gckKERNEL_Notify(device->kernels[gcvCORE_VG], gcvNOTIFY_INTERRUPT, gcvFALSE);
270 /******************************************************************************\
271 ******************************* gckGALDEVICE Code ******************************
272 \******************************************************************************/
274 /*******************************************************************************
276 ** gckGALDEVICE_Construct
284 ** gckGALDEVICE * Device
285 ** Pointer to a variable receiving the gckGALDEVICE object pointer on
289 gckGALDEVICE_Construct(
291 IN gctUINT32 RegisterMemBase,
292 IN gctSIZE_T RegisterMemSize,
294 IN gctUINT32 RegisterMemBase2D,
295 IN gctSIZE_T RegisterMemSize2D,
297 IN gctUINT32 RegisterMemBaseVG,
298 IN gctSIZE_T RegisterMemSizeVG,
299 IN gctUINT32 ContiguousBase,
300 IN gctSIZE_T ContiguousSize,
301 IN gctSIZE_T BankSize,
303 IN gctINT Compression,
304 IN gctUINT32 PhysBaseAddr,
305 IN gctUINT32 PhysSize,
307 IN gctUINT LogFileSize,
308 IN struct device *pdev,
309 IN gctINT PowerManagement,
310 OUT gckGALDEVICE *Device
313 gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
314 gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
315 gctUINT32 horizontalTileSize, verticalTileSize;
316 struct resource* mem_region;
322 gceHARDWARE_TYPE type;
323 gckDB sharedDB = gcvNULL;
324 gckKERNEL kernel = gcvNULL;
326 gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
327 "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
328 "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
329 "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
330 "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
331 IrqLine, RegisterMemBase, RegisterMemSize,
332 IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
333 IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
334 ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
335 PhysBaseAddr, PhysSize, Signal);
337 /* Allocate device structure. */
338 device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);
342 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
345 memset(device, 0, sizeof(struct _gckGALDEVICE));
347 device->dbgnode = gcvNULL;
350 if(gckDebugFileSystemCreateNode(LogFileSize,PARENT_FILE,DEBUG_FILE,&(device->dbgnode)) != 0)
353 gcvLEVEL_ERROR, gcvZONE_DRIVER,
354 "%s(%d): Failed to create the debug file system %s/%s \n",
355 __FUNCTION__, __LINE__,
356 PARENT_FILE, DEBUG_FILE
362 gckDebugFileSystemSetCurrentNode(device->dbgnode);
366 /*Init runtime pm for gpu*/
367 pm_runtime_enable(pdev);
368 device->pmdev = pdev;
371 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
372 /*get gpu regulator*/
373 device->gpu_regulator = regulator_get(pdev, "cpu_vddgpu");
374 if (IS_ERR(device->gpu_regulator)) {
375 gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
376 "%s(%d): Failed to get gpu regulator %s/%s \n",
377 __FUNCTION__, __LINE__,
378 PARENT_FILE, DEBUG_FILE);
379 gcmkONERROR(gcvSTATUS_NOT_FOUND);
382 /*Initialize the clock structure*/
384 device->clk_3d_core = clk_get(pdev, "gpu3d_clk");
385 if (!IS_ERR(device->clk_3d_core)) {
386 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
388 device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
389 if (IS_ERR(device->clk_3d_shader)) {
391 clk_put(device->clk_3d_core);
392 device->clk_3d_core = NULL;
393 device->clk_3d_shader = NULL;
394 gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
398 device->clk_3d_axi = clk_get(pdev, "gpu3d_axi_clk");
399 device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
400 if (IS_ERR(device->clk_3d_shader)) {
402 clk_put(device->clk_3d_core);
403 device->clk_3d_core = NULL;
404 device->clk_3d_shader = NULL;
405 gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
410 device->clk_3d_core = NULL;
411 gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n");
414 if ((IrqLine2D != -1) || (IrqLineVG != -1)) {
415 device->clk_2d_core = clk_get(pdev, "gpu2d_clk");
416 if (IS_ERR(device->clk_2d_core)) {
419 device->clk_2d_core = NULL;
420 gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n");
422 if (IrqLine2D != -1) {
423 device->clk_2d_axi = clk_get(pdev, "gpu2d_axi_clk");
424 if (IS_ERR(device->clk_2d_axi)) {
425 device->clk_2d_axi = NULL;
427 gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n");
430 if (IrqLineVG != -1) {
431 device->clk_vg_axi = clk_get(pdev, "openvg_axi_clk");
432 if (IS_ERR(device->clk_vg_axi)) {
434 device->clk_vg_axi = NULL;
435 gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n");
443 device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase;
444 device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize;
449 device->requestedRegisterMemBases[gcvCORE_2D] = RegisterMemBase2D;
450 device->requestedRegisterMemSizes[gcvCORE_2D] = RegisterMemSize2D;
455 device->requestedRegisterMemBases[gcvCORE_VG] = RegisterMemBaseVG;
456 device->requestedRegisterMemSizes[gcvCORE_VG] = RegisterMemSizeVG;
459 device->requestedContiguousBase = 0;
460 device->requestedContiguousSize = 0;
463 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
465 physical = device->requestedRegisterMemBases[i];
467 /* Set up register memory region. */
470 mem_region = request_mem_region(
471 physical, device->requestedRegisterMemSizes[i], "galcore register region"
474 if (mem_region == gcvNULL)
477 gcvLEVEL_ERROR, gcvZONE_DRIVER,
478 "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
479 __FUNCTION__, __LINE__,
480 physical, device->requestedRegisterMemSizes[i]
483 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
486 device->registerBases[i] = (gctPOINTER) ioremap_nocache(
487 physical, device->requestedRegisterMemSizes[i]);
489 if (device->registerBases[i] == gcvNULL)
492 gcvLEVEL_ERROR, gcvZONE_DRIVER,
493 "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
494 __FUNCTION__, __LINE__,
495 physical, device->requestedRegisterMemSizes[i]
498 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
501 physical += device->requestedRegisterMemSizes[i];
505 device->registerBases[i] = gcvNULL;
509 /* Set the base address */
510 device->baseAddress = PhysBaseAddr;
512 /* Construct the gckOS object. */
513 gcmkONERROR(gckOS_Construct(device, &device->os));
517 /* Construct the gckKERNEL object. */
518 gcmkONERROR(gckKERNEL_Construct(
519 device->os, gcvCORE_MAJOR, device,
520 gcvNULL, &device->kernels[gcvCORE_MAJOR]));
522 sharedDB = device->kernels[gcvCORE_MAJOR]->db;
524 /* Initialize core mapping */
525 for (i = 0; i < 8; i++)
527 device->coreMapping[i] = gcvCORE_MAJOR;
530 /* Setup the ISR manager. */
531 gcmkONERROR(gckHARDWARE_SetIsrManager(
532 device->kernels[gcvCORE_MAJOR]->hardware,
533 (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
534 (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
538 gcmkONERROR(gckHARDWARE_SetFastClear(
539 device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
542 gcmkONERROR(gckHARDWARE_SetPowerManagement(
543 device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement
546 #if COMMAND_PROCESSOR_VERSION == 1
547 /* Start the command queue. */
548 gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
553 device->kernels[gcvCORE_MAJOR] = gcvNULL;
558 gcmkONERROR(gckKERNEL_Construct(
559 device->os, gcvCORE_2D, device,
560 sharedDB, &device->kernels[gcvCORE_2D]));
562 if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;
564 /* Verify the hardware type */
565 gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));
567 if (type != gcvHARDWARE_2D)
570 gcvLEVEL_ERROR, gcvZONE_DRIVER,
571 "%s(%d): Unexpected hardware type: %d\n",
572 __FUNCTION__, __LINE__,
576 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
579 /* Initialize core mapping */
580 if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
582 for (i = 0; i < 8; i++)
584 device->coreMapping[i] = gcvCORE_2D;
589 device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
592 /* Setup the ISR manager. */
593 gcmkONERROR(gckHARDWARE_SetIsrManager(
594 device->kernels[gcvCORE_2D]->hardware,
595 (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
596 (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
600 gcmkONERROR(gckHARDWARE_SetPowerManagement(
601 device->kernels[gcvCORE_2D]->hardware, PowerManagement
604 #if COMMAND_PROCESSOR_VERSION == 1
605 /* Start the command queue. */
606 gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
611 device->kernels[gcvCORE_2D] = gcvNULL;
617 gcmkONERROR(gckKERNEL_Construct(
618 device->os, gcvCORE_VG, device,
619 sharedDB, &device->kernels[gcvCORE_VG]));
620 /* Initialize core mapping */
621 if (device->kernels[gcvCORE_MAJOR] == gcvNULL
622 && device->kernels[gcvCORE_2D] == gcvNULL
625 for (i = 0; i < 8; i++)
627 device->coreMapping[i] = gcvCORE_VG;
632 device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
636 gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
637 device->kernels[gcvCORE_VG]->vg->hardware,
644 device->kernels[gcvCORE_VG] = gcvNULL;
647 /* Initialize the ISR. */
648 device->irqLines[gcvCORE_MAJOR] = IrqLine;
649 device->irqLines[gcvCORE_2D] = IrqLine2D;
650 device->irqLines[gcvCORE_VG] = IrqLineVG;
652 /* Initialize the kernel thread semaphores. */
653 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
655 if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
658 device->signal = Signal;
660 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
662 if (device->kernels[i] != gcvNULL) break;
665 if (i == gcdMAX_GPU_COUNT)
667 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
673 /* Query the ceiling of the system memory. */
674 gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
675 device->kernels[i]->vg->hardware,
676 &device->systemMemorySize,
677 &device->systemMemoryBaseAddress
679 /* query the amount of video memory */
680 gcmkONERROR(gckVGHARDWARE_QueryMemory(
681 device->kernels[i]->vg->hardware,
682 &device->internalSize, &internalBaseAddress, &internalAlignment,
683 &device->externalSize, &externalBaseAddress, &externalAlignment,
684 &horizontalTileSize, &verticalTileSize
690 /* Query the ceiling of the system memory. */
691 gcmkONERROR(gckHARDWARE_QuerySystemMemory(
692 device->kernels[i]->hardware,
693 &device->systemMemorySize,
694 &device->systemMemoryBaseAddress
697 /* query the amount of video memory */
698 gcmkONERROR(gckHARDWARE_QueryMemory(
699 device->kernels[i]->hardware,
700 &device->internalSize, &internalBaseAddress, &internalAlignment,
701 &device->externalSize, &externalBaseAddress, &externalAlignment,
702 &horizontalTileSize, &verticalTileSize
707 /* Grab the first availiable kernel */
708 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
710 if (device->irqLines[i] != -1)
712 kernel = device->kernels[i];
717 /* Set up the internal memory region. */
718 if (device->internalSize > 0)
720 status = gckVIDMEM_Construct(
722 internalBaseAddress, device->internalSize, internalAlignment,
723 0, &device->internalVidMem
726 if (gcmIS_ERROR(status))
728 /* Error, disable internal heap. */
729 device->internalSize = 0;
733 /* Map internal memory. */
734 device->internalLogical
735 = (gctPOINTER) ioremap_nocache(physical, device->internalSize);
737 if (device->internalLogical == gcvNULL)
739 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
742 device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
743 device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical);
744 physical += device->internalSize;
748 if (device->externalSize > 0)
750 /* create the external memory heap */
751 status = gckVIDMEM_Construct(
753 externalBaseAddress, device->externalSize, externalAlignment,
754 0, &device->externalVidMem
757 if (gcmIS_ERROR(status))
759 /* Error, disable internal heap. */
760 device->externalSize = 0;
764 /* Map external memory. */
765 device->externalLogical
766 = (gctPOINTER) ioremap_nocache(physical, device->externalSize);
768 if (device->externalLogical == gcvNULL)
770 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
773 device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
774 device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical);
775 physical += device->externalSize;
779 /* set up the contiguous memory */
780 device->contiguousSize = ContiguousSize;
782 if (ContiguousSize > 0)
784 if (ContiguousBase == 0)
786 while (device->contiguousSize > 0)
788 /* Allocate contiguous memory. */
789 status = _AllocateMemory(
791 device->contiguousSize,
792 &device->contiguousBase,
793 &device->contiguousPhysical,
797 if (gcmIS_SUCCESS(status))
799 device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical);
800 status = gckVIDMEM_Construct(
802 physAddr | device->systemMemoryBaseAddress,
803 device->contiguousSize,
806 &device->contiguousVidMem
809 if (gcmIS_SUCCESS(status))
814 gcmkONERROR(_FreeMemory(
816 device->contiguousBase,
817 device->contiguousPhysical
820 gcmRELEASE_NAME(device->contiguousPhysicalName);
821 device->contiguousBase = gcvNULL;
822 device->contiguousPhysical = gcvNULL;
825 if (device->contiguousSize <= (4 << 20))
827 device->contiguousSize = 0;
831 device->contiguousSize -= (4 << 20);
837 /* Create the contiguous memory heap. */
838 status = gckVIDMEM_Construct(
840 ContiguousBase | device->systemMemoryBaseAddress,
843 &device->contiguousVidMem
846 if (gcmIS_ERROR(status))
848 /* Error, disable contiguous memory pool. */
849 device->contiguousVidMem = gcvNULL;
850 device->contiguousSize = 0;
854 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
855 mem_region = request_mem_region(
856 ContiguousBase, ContiguousSize, "galcore managed memory"
859 if (mem_region == gcvNULL)
862 gcvLEVEL_ERROR, gcvZONE_DRIVER,
863 "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
864 __FUNCTION__, __LINE__,
865 ContiguousSize, ContiguousBase
868 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
872 device->requestedContiguousBase = ContiguousBase;
873 device->requestedContiguousSize = ContiguousSize;
875 #if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
876 if (gcmIS_CORE_PRESENT(device, gcvCORE_VG))
878 device->contiguousBase
879 #if gcdPAGED_MEMORY_CACHEABLE
880 = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize);
882 = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
884 if (device->contiguousBase == gcvNULL)
886 device->contiguousVidMem = gcvNULL;
887 device->contiguousSize = 0;
889 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
894 device->contiguousPhysical = gcvNULL;
895 device->contiguousPhysicalName = 0;
896 device->contiguousSize = ContiguousSize;
897 device->contiguousMapped = gcvTRUE;
902 /* Return pointer to the device. */
905 gcmkFOOTER_ARG("*Device=0x%x", * Device);
910 gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
916 /*******************************************************************************
918 ** gckGALDEVICE_Destroy
935 gckGALDEVICE_Destroy(
939 gceSTATUS status = gcvSTATUS_OK;
940 gckKERNEL kernel = gcvNULL;
942 gcmkHEADER_ARG("Device=0x%x", Device);
944 if (Device != gcvNULL)
946 /* Grab the first availiable kernel */
947 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
949 if (Device->irqLines[i] != -1)
951 kernel = Device->kernels[i];
955 if (Device->internalPhysicalName != 0)
957 gcmRELEASE_NAME(Device->internalPhysicalName);
958 Device->internalPhysicalName = 0;
960 if (Device->externalPhysicalName != 0)
962 gcmRELEASE_NAME(Device->externalPhysicalName);
963 Device->externalPhysicalName = 0;
965 if (Device->contiguousPhysicalName != 0)
967 gcmRELEASE_NAME(Device->contiguousPhysicalName);
968 Device->contiguousPhysicalName = 0;
972 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
974 if (Device->kernels[i] != gcvNULL)
976 /* Destroy the gckKERNEL object. */
977 gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernels[i]));
978 Device->kernels[i] = gcvNULL;
983 if (Device->internalLogical != gcvNULL)
985 /* Unmap the internal memory. */
986 iounmap(Device->internalLogical);
987 Device->internalLogical = gcvNULL;
990 if (Device->internalVidMem != gcvNULL)
992 /* Destroy the internal heap. */
993 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
994 Device->internalVidMem = gcvNULL;
999 if (Device->externalLogical != gcvNULL)
1001 /* Unmap the external memory. */
1002 iounmap(Device->externalLogical);
1003 Device->externalLogical = gcvNULL;
1006 if (Device->externalVidMem != gcvNULL)
1008 /* destroy the external heap */
1009 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
1010 Device->externalVidMem = gcvNULL;
1015 if (Device->contiguousBase != gcvNULL)
1017 if (Device->contiguousMapped)
1019 #if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
1020 if (Device->contiguousBase)
1022 /* Unmap the contiguous memory. */
1023 iounmap(Device->contiguousBase);
1029 gcmkONERROR(_FreeMemory(
1031 Device->contiguousBase,
1032 Device->contiguousPhysical
1036 Device->contiguousBase = gcvNULL;
1037 Device->contiguousPhysical = gcvNULL;
1040 if (Device->requestedContiguousBase != 0)
1042 release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
1043 Device->requestedContiguousBase = 0;
1044 Device->requestedContiguousSize = 0;
1047 if (Device->contiguousVidMem != gcvNULL)
1049 /* Destroy the contiguous heap. */
1050 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
1051 Device->contiguousVidMem = gcvNULL;
1056 if(gckDebugFileSystemIsEnabled())
1058 gckDebugFileSystemFreeNode(Device->dbgnode);
1059 kfree(Device->dbgnode);
1060 Device->dbgnode = gcvNULL;
1064 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1066 if (Device->registerBases[i] != gcvNULL)
1068 /* Unmap register memory. */
1069 iounmap(Device->registerBases[i]);
1070 if (Device->requestedRegisterMemBases[i] != 0)
1072 release_mem_region(Device->requestedRegisterMemBases[i], Device->requestedRegisterMemSizes[i]);
1075 Device->registerBases[i] = gcvNULL;
1076 Device->requestedRegisterMemBases[i] = 0;
1077 Device->requestedRegisterMemSizes[i] = 0;
1082 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
1083 if (Device->clk_3d_axi) {
1084 clk_put(Device->clk_3d_axi);
1085 Device->clk_3d_axi = NULL;
1088 if (Device->clk_3d_core) {
1089 clk_put(Device->clk_3d_core);
1090 Device->clk_3d_core = NULL;
1092 if (Device->clk_3d_shader) {
1093 clk_put(Device->clk_3d_shader);
1094 Device->clk_3d_shader = NULL;
1096 if (Device->clk_2d_core) {
1097 clk_put(Device->clk_2d_core);
1098 Device->clk_2d_core = NULL;
1100 if (Device->clk_2d_axi) {
1101 clk_put(Device->clk_2d_axi);
1102 Device->clk_2d_axi = NULL;
1104 if (Device->clk_vg_axi) {
1105 clk_put(Device->clk_vg_axi);
1106 Device->clk_vg_axi = NULL;
1111 pm_runtime_disable(Device->pmdev);
1114 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
1115 if (Device->gpu_regulator) {
1116 regulator_put(Device->gpu_regulator);
1117 Device->gpu_regulator = NULL;
1121 /* Destroy the gckOS object. */
1122 if (Device->os != gcvNULL)
1124 gcmkVERIFY_OK(gckOS_Destroy(Device->os));
1125 Device->os = gcvNULL;
1128 /* Free the device. */
1133 return gcvSTATUS_OK;
1140 /*******************************************************************************
1142 ** gckGALDEVICE_Setup_ISR
1144 ** Start the ISR routine.
1148 ** gckGALDEVICE Device
1149 ** Pointer to an gckGALDEVICE object.
1158 ** Setup successfully.
1159 ** gcvSTATUS_GENERIC_IO
1163 gckGALDEVICE_Setup_ISR(
1164 IN gckGALDEVICE Device
1170 gcmkHEADER_ARG("Device=0x%x", Device);
1172 gcmkVERIFY_ARGUMENT(Device != NULL);
1174 if (Device->irqLines[gcvCORE_MAJOR] < 0)
1176 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1179 /* Hook up the isr based on the irq line. */
1181 gc500_handle.dev_name = "galcore interrupt service";
1182 gc500_handle.dev_id = Device;
1183 gc500_handle.handler = isrRoutine;
1184 gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
1185 gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1187 ret = dove_gpio_request(
1188 DOVE_GPIO0_7, &gc500_handle
1192 Device->irqLines[gcvCORE_MAJOR], isrRoutine, IRQF_DISABLED,
1193 "galcore interrupt service", Device
1200 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1201 "%s(%d): Could not register irq line %d (error=%d)\n",
1202 __FUNCTION__, __LINE__,
1203 Device->irqLines[gcvCORE_MAJOR], ret
1206 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1209 /* Mark ISR as initialized. */
1210 Device->isrInitializeds[gcvCORE_MAJOR] = gcvTRUE;
1213 return gcvSTATUS_OK;
1221 gckGALDEVICE_Setup_ISR_2D(
1222 IN gckGALDEVICE Device
1228 gcmkHEADER_ARG("Device=0x%x", Device);
1230 gcmkVERIFY_ARGUMENT(Device != NULL);
1232 if (Device->irqLines[gcvCORE_2D] < 0)
1234 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1237 /* Hook up the isr based on the irq line. */
1239 gc500_handle.dev_name = "galcore interrupt service";
1240 gc500_handle.dev_id = Device;
1241 gc500_handle.handler = isrRoutine2D;
1242 gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
1243 gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1245 ret = dove_gpio_request(
1246 DOVE_GPIO0_7, &gc500_handle
1250 Device->irqLines[gcvCORE_2D], isrRoutine2D, IRQF_DISABLED,
1251 "galcore interrupt service for 2D", Device
1258 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1259 "%s(%d): Could not register irq line %d (error=%d)\n",
1260 __FUNCTION__, __LINE__,
1261 Device->irqLines[gcvCORE_2D], ret
1264 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1267 /* Mark ISR as initialized. */
1268 Device->isrInitializeds[gcvCORE_2D] = gcvTRUE;
1271 return gcvSTATUS_OK;
1279 gckGALDEVICE_Setup_ISR_VG(
1280 IN gckGALDEVICE Device
1286 gcmkHEADER_ARG("Device=0x%x", Device);
1288 gcmkVERIFY_ARGUMENT(Device != NULL);
1290 if (Device->irqLines[gcvCORE_VG] < 0)
1292 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1295 /* Hook up the isr based on the irq line. */
1297 gc500_handle.dev_name = "galcore interrupt service";
1298 gc500_handle.dev_id = Device;
1299 gc500_handle.handler = isrRoutineVG;
1300 gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
1301 gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1303 ret = dove_gpio_request(
1304 DOVE_GPIO0_7, &gc500_handle
1308 Device->irqLines[gcvCORE_VG], isrRoutineVG, IRQF_DISABLED,
1309 "galcore interrupt service for 2D", Device
1316 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1317 "%s(%d): Could not register irq line %d (error=%d)\n",
1318 __FUNCTION__, __LINE__,
1319 Device->irqLines[gcvCORE_VG], ret
1322 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1325 /* Mark ISR as initialized. */
1326 Device->isrInitializeds[gcvCORE_VG] = gcvTRUE;
1329 return gcvSTATUS_OK;
1336 /*******************************************************************************
1338 ** gckGALDEVICE_Release_ISR
1340 ** Release the irq line.
1344 ** gckGALDEVICE Device
1345 ** Pointer to an gckGALDEVICE object.
1356 gckGALDEVICE_Release_ISR(
1357 IN gckGALDEVICE Device
1360 gcmkHEADER_ARG("Device=0x%x", Device);
1362 gcmkVERIFY_ARGUMENT(Device != NULL);
1364 /* release the irq */
1365 if (Device->isrInitializeds[gcvCORE_MAJOR])
1368 dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1370 free_irq(Device->irqLines[gcvCORE_MAJOR], Device);
1373 Device->isrInitializeds[gcvCORE_MAJOR] = gcvFALSE;
1377 return gcvSTATUS_OK;
1381 gckGALDEVICE_Release_ISR_2D(
1382 IN gckGALDEVICE Device
1385 gcmkHEADER_ARG("Device=0x%x", Device);
1387 gcmkVERIFY_ARGUMENT(Device != NULL);
1389 /* release the irq */
1390 if (Device->isrInitializeds[gcvCORE_2D])
1393 dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1395 free_irq(Device->irqLines[gcvCORE_2D], Device);
1398 Device->isrInitializeds[gcvCORE_2D] = gcvFALSE;
1402 return gcvSTATUS_OK;
1406 gckGALDEVICE_Release_ISR_VG(
1407 IN gckGALDEVICE Device
1410 gcmkHEADER_ARG("Device=0x%x", Device);
1412 gcmkVERIFY_ARGUMENT(Device != NULL);
1414 /* release the irq */
1415 if (Device->isrInitializeds[gcvCORE_VG])
1418 dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1420 free_irq(Device->irqLines[gcvCORE_VG], Device);
1423 Device->isrInitializeds[gcvCORE_VG] = gcvFALSE;
1427 return gcvSTATUS_OK;
1430 /*******************************************************************************
1432 ** gckGALDEVICE_Start_Threads
1434 ** Start the daemon threads.
1438 ** gckGALDEVICE Device
1439 ** Pointer to an gckGALDEVICE object.
1448 ** Start successfully.
1449 ** gcvSTATUS_GENERIC_IO
1453 gckGALDEVICE_Start_Threads(
1454 IN gckGALDEVICE Device
1458 struct task_struct * task;
1460 gcmkHEADER_ARG("Device=0x%x", Device);
1462 gcmkVERIFY_ARGUMENT(Device != NULL);
1464 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
1466 /* Start the kernel thread. */
1467 task = kthread_run(threadRoutine, Device, "galcore daemon thread");
1472 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1473 "%s(%d): Could not start the kernel thread.\n",
1474 __FUNCTION__, __LINE__
1477 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1480 Device->threadCtxts[gcvCORE_MAJOR] = task;
1481 Device->threadInitializeds[gcvCORE_MAJOR] = gcvTRUE;
1484 if (Device->kernels[gcvCORE_2D] != gcvNULL)
1486 /* Start the kernel thread. */
1487 task = kthread_run(threadRoutine2D, Device, "galcore daemon thread for 2D");
1492 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1493 "%s(%d): Could not start the kernel thread.\n",
1494 __FUNCTION__, __LINE__
1497 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1500 Device->threadCtxts[gcvCORE_2D] = task;
1501 Device->threadInitializeds[gcvCORE_2D] = gcvTRUE;
1505 Device->threadInitializeds[gcvCORE_2D] = gcvFALSE;
1508 if (Device->kernels[gcvCORE_VG] != gcvNULL)
1510 /* Start the kernel thread. */
1511 task = kthread_run(threadRoutineVG, Device, "galcore daemon thread for VG");
1516 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1517 "%s(%d): Could not start the kernel thread.\n",
1518 __FUNCTION__, __LINE__
1521 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1524 Device->threadCtxts[gcvCORE_VG] = task;
1525 Device->threadInitializeds[gcvCORE_VG] = gcvTRUE;
1529 Device->threadInitializeds[gcvCORE_VG] = gcvFALSE;
1533 return gcvSTATUS_OK;
1540 /*******************************************************************************
1542 ** gckGALDEVICE_Stop_Threads
1544 ** Stop the gal device, including the following actions: stop the daemon
1545 ** thread, release the irq.
1549 ** gckGALDEVICE Device
1550 ** Pointer to an gckGALDEVICE object.
1561 gckGALDEVICE_Stop_Threads(
1567 gcmkHEADER_ARG("Device=0x%x", Device);
1569 gcmkVERIFY_ARGUMENT(Device != NULL);
1571 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1573 /* Stop the kernel threads. */
1574 if (Device->threadInitializeds[i])
1576 Device->killThread = gcvTRUE;
1577 up(&Device->semas[i]);
1579 kthread_stop(Device->threadCtxts[i]);
1580 Device->threadCtxts[i] = gcvNULL;
1581 Device->threadInitializeds[i] = gcvFALSE;
1586 return gcvSTATUS_OK;
1589 /*******************************************************************************
1591 ** gckGALDEVICE_Start
1593 ** Start the gal device, including the following actions: setup the isr routine
1594 ** and start the daemoni thread.
1598 ** gckGALDEVICE Device
1599 ** Pointer to an gckGALDEVICE object.
1608 ** Start successfully.
1612 IN gckGALDEVICE Device
1617 gcmkHEADER_ARG("Device=0x%x", Device);
1619 /* Start the kernel thread. */
1620 gcmkONERROR(gckGALDEVICE_Start_Threads(Device));
1622 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
1624 /* Setup the ISR routine. */
1625 gcmkONERROR(gckGALDEVICE_Setup_ISR(Device));
1627 /* Switch to SUSPEND power state. */
1628 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1629 Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF_BROADCAST
1633 if (Device->kernels[gcvCORE_2D] != gcvNULL)
1635 /* Setup the ISR routine. */
1636 gcmkONERROR(gckGALDEVICE_Setup_ISR_2D(Device));
1638 /* Switch to SUSPEND power state. */
1639 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1640 Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF_BROADCAST
1644 if (Device->kernels[gcvCORE_VG] != gcvNULL)
1646 /* Setup the ISR routine. */
1647 gcmkONERROR(gckGALDEVICE_Setup_ISR_VG(Device));
1649 /* Switch to SUSPEND power state. */
1650 gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
1651 Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF_BROADCAST
1656 return gcvSTATUS_OK;
1663 /*******************************************************************************
1665 ** gckGALDEVICE_Stop
1667 ** Stop the gal device, including the following actions: stop the daemon
1668 ** thread, release the irq.
1672 ** gckGALDEVICE Device
1673 ** Pointer to an gckGALDEVICE object.
1690 gcmkHEADER_ARG("Device=0x%x", Device);
1692 gcmkVERIFY_ARGUMENT(Device != NULL);
1694 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
1696 /* Switch to OFF power state. */
1697 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1698 Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF
1701 /* Remove the ISR routine. */
1702 gcmkONERROR(gckGALDEVICE_Release_ISR(Device));
1705 if (Device->kernels[gcvCORE_2D] != gcvNULL)
1707 /* Setup the ISR routine. */
1708 gcmkONERROR(gckGALDEVICE_Release_ISR_2D(Device));
1710 /* Switch to OFF power state. */
1711 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1712 Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF
1716 if (Device->kernels[gcvCORE_VG] != gcvNULL)
1718 /* Setup the ISR routine. */
1719 gcmkONERROR(gckGALDEVICE_Release_ISR_VG(Device));
1722 /* Switch to OFF power state. */
1723 gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
1724 Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF
1729 /* Stop the kernel thread. */
1730 gcmkONERROR(gckGALDEVICE_Stop_Threads(Device));
1733 return gcvSTATUS_OK;