static ssize_t show_clkreg (struct device *dev, struct device_attribute *attr, char * buf) { char *str = buf; int i; unsigned int clkreg; gckHARDWARE hardware; gceSTATUS status = gcvSTATUS_OK; for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (galDevice->kernels[i] != gcvNULL) { hardware = galDevice->kernels[i]->hardware; /* read clk control register */ gcmkONERROR(gckOS_ReadRegisterEx(hardware->os, hardware->core, 0x00000, &clkreg)); str += sprintf(str, "%x ", clkreg); } } if (str != buf) { *(str-1) = '\n'; } return (str-buf); OnError: return 0; }
static ssize_t store_register_stats (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { gctUINT32 core, offset, value; SYSFS_VERIFY_INPUT(sscanf(buf, "%d 0x%x", &core, &offset), 2); SYSFS_VERIFY_INPUT_RANGE(core, 0, gcdMAX_GPU_COUNT - 1); SYSFS_VERIFY_INPUT_RANGE(offset, 0, 0x30001); gcmkVERIFY_OK(gckOS_ReadRegisterEx(galDevice->os, core, offset, &value)); gcmkPRINT("Core(%d) Register[0x%x] value is 0x%08x\n", core, offset, value); return count; }
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, "dutycycle", 9) == 0) { gctINT32 option; gcuDATABASE_INFO gpuIdle; static gctUINT64 startTime = 0; static gctUINT64 endTime = 0; gcmkVERIFY_OK(gckOS_ZeroMemory((gctPOINTER)&gpuIdle, gcmSIZEOF(gcuDATABASE_INFO))); sscanf(messages+9, "%d", &option); switch(option) { case 0: gcmkVERIFY_OK(gckOS_GetProfileTick(&startTime)); gcmkVERIFY_OK(gckKERNEL_QueryDutyCycleDB(galDevice->kernels[gcvCORE_MAJOR], gcvTRUE, &gpuIdle)); gpuIdle.time = 0; endTime = 0; break; case 1: gcmkVERIFY_OK(gckKERNEL_QueryDutyCycleDB(galDevice->kernels[gcvCORE_MAJOR], gcvFALSE, &gpuIdle)); gcmkVERIFY_OK(gckOS_GetProfileTick(&endTime)); break; default: printk(KERN_INFO "usage: echo dutycycle [0|1] > /proc/driver/gc\n"); } if(startTime != 0 && endTime != 0) { gctUINT64 delta = endTime - startTime; gctUINT32 per = 100 - 100 * gckOS_ProfileToMS(gpuIdle.time) / gckOS_ProfileToMS(delta); printk(KERN_INFO "\n %%GPU START END DELTA IDLE\n"); printk(KERN_INFO "%5u%% %8u %8u %8u %8u\n\n", per, gckOS_ProfileToMS(startTime), gckOS_ProfileToMS(endTime), gckOS_ProfileToMS(delta), gckOS_ProfileToMS(gpuIdle.time)); } } else if(strncmp(messages, "reg", 3) == 0) { gctINT32 option; gctUINT32 idle, address, clockControl; sscanf(messages+3, "%d", &option); switch(option) { case 1: /* Read the current FE address. */ gckOS_ReadRegisterEx(galDevice->os, galDevice->kernels[0]->hardware->core, 0x00664, &address); gcmkPRINT("address: 0x%2x\n", address); break; case 2: /* Read idle register. */ gckOS_ReadRegisterEx(galDevice->os, galDevice->kernels[0]->hardware->core, 0x00004, &idle); gcmkPRINT("idle: 0x%2x\n", idle); break; case 3: gckOS_ReadRegisterEx(galDevice->os, gcvCORE_MAJOR, 0x00000, &clockControl); gcmkPRINT("clockControl: 0x%2x\n", clockControl); break; default: printk(KERN_INFO "usage: echo reg [1|2|3] > /proc/driver/gc\n"); } } else if(strncmp(messages, "help", 4) == 0) { printk("Supported options:\n" "dutycycle measure dutycycle in a period\n" "reg enable debugging for register reading\n" "help show this help page\n" "\n"); } else { gcmkPRINT("unknown echo\n"); } printk("\n"); return len; }