static void
_TimerFunction(
    gctPOINTER Data
    )
{
    gceSTATUS status = gcvSTATUS_OK;
    gckDVFS dvfs = (gckDVFS) Data;
    gckHARDWARE hardware = dvfs->hardware;
    gctUINT32 value;
    gctUINT32 frequency;
    gctUINT8 scale;
    gctUINT32 t1, t2, consumed;

    gckOS_GetTicks(&t1);

    gcmkONERROR(gckHARDWARE_QueryLoad(hardware, &value));

    /* determine target sacle. */
    _Policy(dvfs, value, &scale);

    /* Set frequency and voltage. */
    gcmkONERROR(gckOS_SetGPUFrequency(hardware->os, hardware->core, scale));

    /* Query real frequency. */
    gcmkONERROR(
        gckOS_QueryGPUFrequency(hardware->os,
                                hardware->core,
                                &frequency,
                                &dvfs->currentScale));

    _RecordFrequencyHistory(dvfs, frequency);

    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_POWER,
                   "Current frequency = %d",
                   frequency);

    /* Set period. */
    gcmkONERROR(gckHARDWARE_SetDVFSPeroid(hardware, frequency));

OnError:
    /* Determine next querying time. */
    gckOS_GetTicks(&t2);

    consumed = gcmMIN(((long)t2 - (long)t1), 5);

    if (dvfs->stop == gcvFALSE)
    {
        gcmkVERIFY_OK(gckOS_StartTimer(hardware->os,
                                       dvfs->timer,
                                       dvfs->pollingTime - consumed));
    }

    return;
}
/* echo xx > /proc/driver/gc set ... */
static ssize_t gc_proc_write(struct file *file,
		const char *buff, size_t len, loff_t *off)
{
    char messages[256];

	if(len > 256)
		len = 256;

	if(copy_from_user(messages, buff, len))
		return -EFAULT;

    printk("\n");
    if(strncmp(messages, "printPID", 8) == 0)
    {
        galDevice->printPID = galDevice->printPID ? gcvFALSE : gcvTRUE;
        printk("==>Change printPID to %s\n", galDevice->printPID ? "gcvTRUE" : "gcvFALSE");
    }
    else if(strncmp(messages, "profile", 7) == 0)
    {
        gctUINT32 idleTime, timeSlice;
        gctUINT32 start,end;
        timeSlice = 10000;
        start = gckOS_GetTicks();
        gckOS_IdleProfile(galDevice->os, &timeSlice, &idleTime);
        end = gckOS_GetTicks();

        printk("idle:total [%d, %d]\n", idleTime, timeSlice);
        printk("profile cost %d\n", end - start);
    }
    else if(strncmp(messages, "hang", 4) == 0)
    {
		galDevice->kernel->hardware->hang = galDevice->kernel->hardware->hang ? gcvFALSE : gcvTRUE;
    }
    else if(strncmp(messages, "reset", 5) == 0)
    {
        galDevice->reset = galDevice->reset ? gcvFALSE : gcvTRUE;
    }
#ifdef CONFIG_PXA_DVFM
    else if(strncmp(messages, "d2debug", 7) == 0)
    {
        galDevice->needD2DebugInfo = galDevice->needD2DebugInfo ? gcvFALSE : gcvTRUE;
    }
    else if(strncmp(messages, "D1", 2) == 0)
    {
        galDevice->enableD1 = galDevice->enableD1 ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "D2", 2) == 0)
    {
        galDevice->enableD2 = galDevice->enableD2 ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "D0", 2) == 0)
    {
        galDevice->enableD0CS= galDevice->enableD0CS ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "CG", 2) == 0)
    {
        galDevice->enableCG= galDevice->enableCG ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "needreset", 9) == 0)
    {
        galDevice->needResetAfterD2 = galDevice->needResetAfterD2 ? gcvFALSE : gcvTRUE;
    }
#endif
    else if(strncmp(messages, "su", 2) == 0)
    {
        gceSTATUS status;

        if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_OFF)
        {
            status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_OFF);
            if (gcmIS_ERROR(status))
            {
                return -1;
            }

            gckOS_SuspendInterrupt(galDevice->os);
            gckOS_ClockOff();
        }
    }
    else if(strncmp(messages, "re", 2) == 0)
    {
        gceSTATUS status;

        if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_ON)
        {
            gckOS_ClockOn(0);
            gckOS_ResumeInterrupt(galDevice->os);

            status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_ON);
		if (gcmIS_ERROR(status))
		{
			return -1;
		}
        }
    }
    else if(strncmp(messages, "stress", 6) == 0)
    {
        int i;
         /* struct vmalloc_info vmi; */

     /* {get_vmalloc_info(&vmi);printk("%s,%d,VmallocUsed: %8lu kB\n",__func__,__LINE__,vmi.used >> 10); } */

#ifdef _DEBUG
	gckOS_SetDebugLevel(gcvLEVEL_VERBOSE);
	gckOS_SetDebugZone(1023);
#endif

        for(i=0;i<20000;i++)
        {
            gceSTATUS status;
            static int count = 0;

            printk("count:%d\n",count++);
            printk("!!!\t");
            if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_OFF)
            {
                status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_OFF);
		if (gcmIS_ERROR(status))
		{
			return -1;
		}

                gckOS_SuspendInterrupt(galDevice->os);
                gckOS_ClockOff();

            }
            printk("@@@\t");
            if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_ON)
            {
                gckOS_ClockOn(0);
                gckOS_ResumeInterrupt(galDevice->os);

                status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_ON);
		if (gcmIS_ERROR(status))
		{
			return -1;
		}
            }
            printk("###\n");
        }

    }
    else if(strncmp(messages, "debug", 5) == 0)
    {
#ifdef _DEBUG
        static int count = 0;

        if(count%2 == 0)
        {
		gckOS_SetDebugLevel(gcvLEVEL_VERBOSE);
		gckOS_SetDebugZone(1023);
        }
        else
        {
            gckOS_SetDebugLevel(gcvLEVEL_NONE);
		gckOS_SetDebugZone(0);
        }
        count++;
#endif
    }
    else if(strncmp(messages, "16", 2) == 0)
    {
		printk("frequency change to 1/16\n");
        /* frequency change to 1/16 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x210));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x010));

    }
    else if(strncmp(messages, "32", 2) == 0)
    {
		printk("frequency change to 1/32\n");
        /* frequency change to 1/32*/
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x208));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x008));

    }
	else if(strncmp(messages, "64", 2) == 0)
    {
		printk("frequency change to 1/64\n");
        /* frequency change to 1/64 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x204));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x004));

    }
    else if('1' == messages[0])
    {
        printk("frequency change to full speed\n");
        /* frequency change to full speed */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x300));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x100));

    }
    else if('2' == messages[0])
    {
        printk("frequency change to 1/2\n");
        /* frequency change to 1/2 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x280));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x080));

    }
    else if('4' == messages[0])
    {
        printk("frequency change to 1/4\n");
        /* frequency change to 1/4 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x240));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x040));

    }
    else if('8' == messages[0])
    {
        printk("frequency change to 1/8\n");
        /* frequency change to 1/8 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x220));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x020));

    }
    else
    {
        printk("unknown echo\n");
    }

    return len;
}