]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00170751 Enable clock gating while gpu core comes to idle
authorLoren Huang <b02279@freescale.com>
Mon, 26 Dec 2011 07:46:06 +0000 (15:46 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:33:42 +0000 (08:33 +0200)
-Correct gc355 initial power state to poweroff.
-Separate clock gating operation in function gckOS_SetGPUPower().
-Turn on clock while suspend GPU cores.
-Remove clock switch in drv_open().

Signed-off-by: Loren Huang <b02279@freescale.com>
Acked-by: Lily Zhang
drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c

index 20c79b88806f5468721282c227f38095e1edaf48..a9aec1484508fa1c23ca1a1631a914df465edfb0 100644 (file)
@@ -246,7 +246,7 @@ gckVGHARDWARE_Construct(
 
         hardware->powerMutex            = gcvNULL;
         hardware->idleSemaphore         = gcvNULL;
-        hardware->chipPowerState        = gcvPOWER_ON;
+        hardware->chipPowerState        = gcvPOWER_OFF;
         hardware->chipPowerStateGlobal  = gcvPOWER_ON;
         hardware->clockState            = gcvTRUE;
         hardware->powerState            = gcvTRUE;
@@ -1678,7 +1678,7 @@ gckVGHARDWARE_SetPowerManagementState(
     if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
     {
         /* Turn on the power. */
-        gcmkONERROR(gckOS_SetGPUPower(os, gcvTRUE, gcvTRUE));
+        gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG , gcvTRUE, gcvTRUE));
 
         /* Mark clock and power as enabled. */
         Hardware->clockState = gcvTRUE;
@@ -1749,6 +1749,7 @@ gckVGHARDWARE_SetPowerManagementState(
         /* Turn off the GPU power. */
         gcmkONERROR(
             gckOS_SetGPUPower(os,
+                              gcvCORE_VG,
                               (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
                                                                : gcvTRUE,
                               (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
index 0ceced9754bbe6db598c50a6ada33dc6cfaabd93..5321a2d68a9831a096f68904574f2627c3bdb9f4 100644 (file)
@@ -421,7 +421,7 @@ gckHARDWARE_Construct(
     gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
 
     /* Enable the GPU. */
-    gcmkONERROR(gckOS_SetGPUPower(Os, gcvTRUE, gcvTRUE));
+    gcmkONERROR(gckOS_SetGPUPower(Os, Core, gcvTRUE, gcvTRUE));
     gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00000, 0));
 
     status = _ResetGPU(Os, Core);
@@ -527,7 +527,7 @@ OnError:
     if (hardware != gcvNULL)
     {
         /* Turn off the power. */
-        gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvFALSE, gcvFALSE));
+        gcmkVERIFY_OK(gckOS_SetGPUPower(Os, hardware->core, gcvFALSE, gcvFALSE));
 
         if (hardware->globalSemaphore != gcvNULL)
         {
@@ -585,7 +585,7 @@ gckHARDWARE_Destroy(
     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
 
     /* Turn off the power. */
-    gcmkVERIFY_OK(gckOS_SetGPUPower(Hardware->os, gcvFALSE, gcvFALSE));
+    gcmkVERIFY_OK(gckOS_SetGPUPower(Hardware->os, Hardware->core, gcvFALSE, gcvFALSE));
 
     /* Destroy the power semaphore. */
     gcmkVERIFY_OK(gckOS_DestroySemaphore(Hardware->os,
@@ -3749,7 +3749,7 @@ gckHARDWARE_SetPowerManagementState(
     if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
     {
         /* Turn on the power. */
-        gcmkONERROR(gckOS_SetGPUPower(os, gcvTRUE, gcvTRUE));
+        gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvTRUE, gcvTRUE));
 
         /* Mark clock and power as enabled. */
         Hardware->clockState = gcvTRUE;
@@ -3896,6 +3896,7 @@ gckHARDWARE_SetPowerManagementState(
         /* Turn off the GPU power. */
         gcmkONERROR(
             gckOS_SetGPUPower(os,
+                              Hardware->core,
                               (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
                                                                : gcvTRUE,
                               (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
index 2dfa3e74f5de84dfc3b15967db06c57a0ef5b896..e2a6b66fa1bb865ab74f2d9e6a0ba54235b67546 100644 (file)
@@ -1243,6 +1243,9 @@ gckOS_BroadcastCalibrateSpeed(
 **      gckOS Os
 **          Pointer to a gckOS object.ß
 **
+**      gceCORE Core
+**          Core type.
+**
 **      gctBOOL Clock
 **          gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
 **
@@ -1256,6 +1259,7 @@ gckOS_BroadcastCalibrateSpeed(
 gceSTATUS
 gckOS_SetGPUPower(
     IN gckOS Os,
+    IN gceCORE Core,
     IN gctBOOL Clock,
     IN gctBOOL Power
     );
index 7c0c5beae463f2ffc887e0eb1b9e0fe9ac2b48e0..6d3b91bbc79206db26e1fbf25a82355624ae6b7f 100644 (file)
@@ -376,6 +376,34 @@ gckGALDEVICE_Construct(
 
     memset(device, 0, sizeof(struct _gckGALDEVICE));
 
+    /*Initialize the clock structure*/
+    if (IrqLine != -1) {
+        device->clk_3d_core = clk_get(NULL, "gpu3d_clk");
+        if (!IS_ERR(device->clk_3d_core)) {
+            device->clk_3d_shader = clk_get(NULL, "gpu3d_shader_clk");
+            if (IS_ERR(device->clk_3d_shader)) {
+                IrqLine = -1;
+                clk_put(device->clk_3d_core);
+                device->clk_3d_core = NULL;
+                device->clk_3d_shader = NULL;
+                gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
+            }
+        } else {
+            IrqLine = -1;
+            device->clk_3d_core = NULL;
+            gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n");
+        }
+    }
+    if ((IrqLine2D != -1) || (IrqLineVG != -1)) {
+        device->clk_2d_core = clk_get(NULL, "gpu2d_clk");
+        if (IS_ERR(device->clk_2d_core)) {
+            IrqLine2D = -1;
+            IrqLineVG = -1;
+            device->clk_2d_core = NULL;
+            gckOS_Print("galcore: clk_get 2d clock failed, disable 2d/vg!\n");
+        }
+    }
+
     if (IrqLine != -1)
     {
         device->requestedRegisterMemBases[gcvCORE_MAJOR]    = RegisterMemBase;
@@ -941,6 +969,23 @@ gckGALDEVICE_Destroy(
             }
         }
 
+        /*Disable clock*/
+        if (Device->clk_3d_core) {
+           clk_disable(Device->clk_3d_core);
+           clk_put(Device->clk_3d_core);
+           Device->clk_3d_core = NULL;
+        }
+        if (Device->clk_3d_shader) {
+           clk_disable(Device->clk_3d_shader);
+           clk_put(Device->clk_3d_shader);
+           Device->clk_3d_shader = NULL;
+        }
+        if (Device->clk_2d_core) {
+           clk_disable(Device->clk_2d_core);
+           clk_put(Device->clk_2d_core);
+           Device->clk_2d_core = NULL;
+        }
+
         /* Destroy the gckOS object. */
         if (Device->os != gcvNULL)
         {
index 08c5e82696ba2aa5314d1890967f17f75bf10560..86333ba34732841167794e8dc1a816132cb135fa 100644 (file)
@@ -82,6 +82,12 @@ typedef struct _gckGALDEVICE
     /* Core mapping */
     gceCORE             coreMapping[8];
 
+    /* Clock management.*/
+    struct clk         *clk_3d_core;
+    struct clk         *clk_3d_shader;
+    struct clk         *clk_2d_core;
+    gctBOOL clk_flag[gcdCORE_COUNT];
+
 #if gcdPOWEROFF_TIMEOUT
     struct task_struct  *pmThreadCtxts;
     gctBOOL             pmThreadInitializeds;
index e4ef19b8c654262b62ba63c4626e0f658356174c..86ef0c67d8a7e7a9f91720ed73f06a7d9efb4b3e 100644 (file)
@@ -111,10 +111,6 @@ module_param(showArgs, int, 0644);
     module_param(coreClock, ulong, 0644);
 #endif
 
-static struct clk * clk_3d_core;
-static struct clk * clk_3d_shader;
-static struct clk * clk_2d_core;
-
 static int drv_open(
     struct inode* inode,
     struct file* filp
@@ -709,38 +705,6 @@ static int drv_init(void)
 #if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
         gc_pwr(1);
 #   endif
-# else
-    if (irqLine != -1) {
-        clk_3d_core = clk_get(NULL, "gpu3d_clk");
-        if (!IS_ERR(clk_3d_core)) {
-            clk_3d_shader = clk_get(NULL, "gpu3d_shader_clk");
-            if (!IS_ERR(clk_3d_shader)) {
-                clk_enable(clk_3d_core);
-                clk_enable(clk_3d_shader);
-            } else {
-                irqLine = -1;
-                clk_put(clk_3d_core);
-                clk_3d_core = NULL;
-                clk_3d_shader = NULL;
-                printk(KERN_ERR "galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
-            }
-        } else {
-            irqLine = -1;
-            clk_3d_core = NULL;
-            printk(KERN_ERR "galcore: clk_get gpu3d_clk failed, disable 3d!\n");
-        }
-    }
-    if ((irqLine2D != -1) || (irqLineVG != -1)) {
-        clk_2d_core = clk_get(NULL, "gpu2d_clk");
-        if (IS_ERR(clk_2d_core)) {
-            irqLine2D = -1;
-            irqLineVG = -1;
-            clk_2d_core = NULL;
-            printk(KERN_ERR "galcore: clk_get 2d clock failed, disable 2d/vg!\n");
-        } else {
-            clk_enable(clk_2d_core);
-        }
-    }
 # endif
     }
 #endif
@@ -913,22 +877,6 @@ static void drv_exit(void)
 #endif
         clk = clk_get(NULL, "GCCLK");
         clk_disable(clk);
-# else
-    if (clk_3d_core) {
-       clk_disable(clk_3d_core);
-       clk_put(clk_3d_core);
-       clk_3d_core = NULL;
-    }
-    if (clk_3d_shader) {
-       clk_disable(clk_3d_shader);
-       clk_put(clk_3d_shader);
-       clk_3d_shader = NULL;
-    }
-    if (clk_2d_core) {
-        clk_disable(clk_2d_core);
-        clk_put(clk_2d_core);
-        clk_2d_core = NULL;
-    }
 # endif
     }
 #endif
@@ -1038,7 +986,8 @@ static int __devinit gpu_suspend(struct platform_device *dev, pm_message_t state
             {
                 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
             }
-
+            /*gpu clock must be turned on before power down*/
+            gckOS_SetGPUPower(device->os, i, gcvTRUE, gcvFALSE);
             if (gcmIS_ERROR(status))
             {
                 return -1;
index eacee2791b9383dd293d38d90fe7985f039f7aa1..619cd768530098269da44bcacf4561c65a328f5f 100644 (file)
@@ -6287,6 +6287,9 @@ gckOS_GetThreadID(
 **      gckOS Os
 **          Pointer to a gckOS object.
 **
+**      gceCORE Core
+**          Core type.
+**
 **      gctBOOL Clock
 **          gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
 **
@@ -6300,12 +6303,65 @@ gckOS_GetThreadID(
 gceSTATUS
 gckOS_SetGPUPower(
     IN gckOS Os,
+    IN gceCORE Core,
     IN gctBOOL Clock,
     IN gctBOOL Power
     )
 {
-    gcmkHEADER_ARG("Os=0x%X Clock=%d Power=%d", Os, Clock, Power);
-
+    struct clk *clk_3dcore = Os->device->clk_3d_core;
+    struct clk *clk_3dshader = Os->device->clk_3d_shader;
+    struct clk *clk_2dcore = Os->device->clk_2d_core;
+
+    gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
+    if (Clock == gcvTRUE) {
+        switch (Core) {
+        case gcvCORE_MAJOR:
+            if (!Os->device->clk_flag[gcvCORE_MAJOR]) {
+                clk_enable(clk_3dcore);
+                clk_enable(clk_3dshader);
+            }
+            Os->device->clk_flag[gcvCORE_MAJOR] = gcvTRUE;
+            break;
+        case gcvCORE_2D:
+            if (!(Os->device->clk_flag[gcvCORE_2D] || Os->device->clk_flag[gcvCORE_VG])) {
+                clk_enable(clk_2dcore);
+            }
+            Os->device->clk_flag[gcvCORE_2D] = gcvTRUE;
+            break;
+        case gcvCORE_VG:
+            if (!(Os->device->clk_flag[gcvCORE_2D] || Os->device->clk_flag[gcvCORE_VG])) {
+                clk_enable(clk_2dcore);
+            }
+            Os->device->clk_flag[gcvCORE_VG] = gcvTRUE;
+            break;
+        default:
+            break;
+        }
+    } else {
+        switch (Core) {
+        case gcvCORE_MAJOR:
+            if (Os->device->clk_flag[gcvCORE_MAJOR]) {
+                clk_disable(clk_3dshader);
+                clk_disable(clk_3dcore);
+            }
+            Os->device->clk_flag[gcvCORE_MAJOR] = gcvFALSE;
+            break;
+        case gcvCORE_2D:
+            if (Os->device->clk_flag[gcvCORE_2D] && (!Os->device->clk_flag[gcvCORE_VG])) {
+                clk_disable(clk_2dcore);
+            }
+            Os->device->clk_flag[gcvCORE_2D] = gcvFALSE;
+            break;
+        case gcvCORE_VG:
+            if ((!Os->device->clk_flag[gcvCORE_2D]) && Os->device->clk_flag[gcvCORE_VG]) {
+                clk_disable(clk_2dcore);
+            }
+            Os->device->clk_flag[gcvCORE_VG] = gcvFALSE;
+            break;
+        default:
+            break;
+        }
+    }
     /* TODO: Put your code here. */
 
     gcmkFOOTER_NO();