b7d9c855c3e782376c1dfd985110eee36bdb10d5
1 /**
2 * @file PerfUtils.c
3 *
4 * @brief This modules provides functions for measuring performance
5 *
6 * ============================================================================
7 *
8 * Copyright (c) 2009-2012, Texas Instruments Incorporated
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * * Neither the name of Texas Instruments Incorporated nor the names of
22 * its contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
32 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * Contact information for paper mail:
37 * Texas Instruments
38 * Post Office Box 655303
39 * Dallas, Texas 75265
40 * Contact information:
41 * http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
42 * DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
43 * ============================================================================
44 *
45 */
47 /* Linux specific header files */
48 #include <sys/time.h>
49 /* Standard headers */
50 #include <stdlib.h>
51 #include <string.h>
53 /* OSAL & Utils headers */
54 #include <PerfUtils.h>
56 /* Linux specific header files */
57 #include <sys/types.h>
58 #include <sys/ioctl.h>
59 #include <fcntl.h>
60 #include <stdio.h>
61 #include <unistd.h>
62 #include <errno.h>
63 #include <sys/mman.h>
64 /* OSAL & Utils headers */
65 #include <stdint.h>
68 #define SYSM3_PROC 2
69 #define APPM3_PROC 3
70 /* PERF UTILS ERROR CODES START */
71 /*Reserved index CML4 clock*/
72 typedef enum perf_util_index{
73 PERF_UTIL_KERNEL_INDEX = 0,
74 PERF_UTIL_GPTIMER_INDEX,
75 PERF_UTIL_SYSCLK_INDEX,
76 PERF_UTILS_CML4_INDEX,
77 PERF_UTILS_MAX_IDENX ,
78 PERF_UTILS_RECORDS_INDEX = -2
79 }perf_util_index;
81 //#define PERF_UTILS_DEBUG_SUPPORT 1
82 #define PERF_UTILS_SUCCESS (0)
83 #define PERF_UTILS_FAILURE (-1)
84 #define PERF_UTILS_INIT_FAILED (-2)
85 #define PERF_UTILS_GPTIMER_TEN (10)
86 //#define PERF_UTILS_DEBUG_SUPPORT 1
87 #define SYSLINK_MEM_IPC_HEAP2_ADDR 0x97FAA000
88 /* 6K memory mapping for perfutils*/
89 #define SYSLINK_MEM_IPC_HEAP2_SIZE ((MAX_NUM_KERNELSPACE_RECORDS) * (sizeof(Perf_FunctionRecord)))
90 //#define SYSLINK_MEM_IPC_HEAP2_SIZE 0x2900
91 /* PERF UTILS ERROR CODES END */
93 /* GENERIC MACROS TO ACCESS GPTIMER REGISTERS */
94 #define REG(MODULE,MODULENO,NAME,BASEADDR) \
95 REG_OFFSET(MODULE##MODULENO, _##NAME,BASEADDR)
96 //#define REG_OFFSET(CMODULE_NO,NAME) REG_ADDR(CMODULE_NO##NAME##REG_OFFSET,CMODULE_NO##_MODULE_BASE##_ADDR)
97 #define REG_OFFSET(CMODULE_NO, NAME,BASEADDR) \
98 REG_ADDR(CMODULE_NO##NAME##REG_OFFSET,BASEADDR)
100 #define REG_ADDR(OFFSET, BASE) ((OFFSET) + (BASE))
102 /* GP TIMER REGISTER ADDRESSES AND OFFSET */
103 #define GPTIMER_MODULE_REGSET_SIZE 0x00000058
104 #define GPTIMER_CTRLREG_AR_BIT_POS 0x00000001
105 #define GPTIMER_CTRLREG_PTV_BIT_POS 0x00000002
106 #define GPTIMER_CTRLREG_PRE_BIT_POS 0x00000005
107 #define GPTIMER_CTRLREG_ST_BIT_POS 0x00000000
109 /* GP TIMER 10 */
110 #define GPTIMER10_MODULE_BASE_ADDR 0x48086000
111 #if defined (SYSLINK_PLATFORM_OMAP4430)
112 #define GPTIMER10_CTRLREG_OFFSET 0x00000009
113 #define GPTIMER10_CRRREG_OFFSET 0x0000000a
114 #define GPTIMER10_LDRREG_OFFSET 0x0000000b
115 #elif defined(SYSLINK_PLATFORM_OMAP5430)
116 #define GPTIMER10_CTRLREG_OFFSET 0x0000000e
117 #define GPTIMER10_CRRREG_OFFSET 0x0000000f
118 #define GPTIMER10_LDRREG_OFFSET 0x00000010
119 #endif
121 /*GP TIMER 9 */
122 #define GPTIMER9_MODULE_BASE_ADDR 0x4803E000
123 #define GPIMER9_CLRREG_OFFSET 0x00000038
124 #define GPTIMER9_CRRREG_OFFSET 0x0000003C
125 #define GPTIMER9_LDRREG_OFFSET 0x00000040
127 /* L4PER_CM2 registers */
128 #define CM_L4PER_GPTIMER_BASE_ADDR 0x4A009400
129 #if defined(SYSLINK_PLATFORM_OMAP4430)
130 #define CM_SYS_CLKSEL_REG 0x4A306110
131 #elif defined(SYSLINK_PLATFORM_OMAP5430)
132 #define CM_SYS_CLKSEL_REG 0x4AE06110
133 #endif
134 #define CM_L4PER_GPTIMER_REGSET_SIZE 0x00000030
135 #define CM_L4PER_GPTIMER10_CLKCTRLREG_OFFSET 0x0000000A
136 #define CM_L4PER_GPTIMER10_CLKCTRLREG 0x4A009428
137 #define CM_L4PER_GPTIMER10_CLKCTRLREG_SIZE 0x00000004
139 #define SYS_CLK_UNINITIALIZED 0x0000000
140 #define SYS_CLK_12MHZ_FREQ 0x0B71B00
141 #define SYS_CLK_13MHZ_FREQ 0x0C65D40
142 #define SYS_CLK_16_8MHZ_FREQ 0x1005900
143 #define SYS_CLK_19_2MHZ_FREQ 0x124F800
144 #define SYS_CLK_26MHZ_FREQ 0x18CBA80
145 #define SYS_CLK_27MHZ_FREQ 0x19BFCC0
146 #define SYS_CLK_38_4MHZ_FREQ 0x249F000
147 #define CONV_FACTOR_SEC_TO_USEC 1000000
149 // Must match struct definition on Ducati side
150 #define MAX_NUM_USERSPACE_RECORDS 10
151 #define MAX_NUM_KERNELSPACE_RECORDS 5
153 typedef struct {
154 unsigned int numEntries;
155 unsigned int enterTimes[MAX_ENTRIES_PER_FUNCTION];
156 unsigned int exitTimes[MAX_ENTRIES_PER_FUNCTION];
157 char fxnName[128];
158 unsigned int client_proc;
159 unsigned int server_proc;
160 unsigned int msg_size;
161 } Perf_FunctionRecord;
163 typedef struct
164 {
165 unsigned int numEntries;
166 struct timeval enterTimes[MAX_ENTRIES_PER_FUNCTION];
167 struct timeval exitTimes[MAX_ENTRIES_PER_FUNCTION];
168 char fxnName[128];
169 unsigned int client_proc;
170 unsigned int server_proc;
171 unsigned int msg_size;
172 } Perf_LocalRecord;
174 #ifdef USE_GPTIMER
175 static Perf_FunctionRecord perfRecordsArr[MAX_NUM_USERSPACE_RECORDS];
176 static Perf_FunctionRecord *perfRecordsUserSpace;
177 #else
178 static Perf_LocalRecord perfRecordsArr[MAX_NUM_USERSPACE_RECORDS];
179 static Perf_LocalRecord *perfRecordsUserSpace;
180 #endif
182 typedef struct
183 {
184 unsigned int enablePrescale:1;
185 unsigned int enableautoReload:1;
186 unsigned int valuePrescalar:3;
187 unsigned int gpTimer:4;
188 }Perf_GptimerConfig;
190 typedef struct Memory_MapInfo_tag {
191 unsigned int src;
192 /*!< Address to be mapped. */
193 unsigned int size;
194 /*!< Size of memory region to be mapped. */
195 unsigned int dst;
196 /*!< Mapped address. */
197 } Memory_MapInfo ;
199 static Memory_MapInfo memoryMap[PERF_UTILS_MAX_IDENX];
201 static volatile unsigned int* addrGptimerCtrlReg;
202 static volatile unsigned int* addrGptimerReadReg;
203 static volatile unsigned int* addrGptimerLoadReg;
204 static volatile unsigned int* addrGptimerBaseReg;
205 static volatile unsigned int* addrCmSysClkSelReg;
206 static volatile unsigned int* timeStampUserSpace;
207 static volatile unsigned int* addrCmL4GptimerBaseReg;
208 static volatile unsigned int* addrCmL4PGptimerCtrlReg;
210 static unsigned int sysClockFreq;
211 static unsigned int valuePrescalar;
213 static unsigned int
214 OsalDrv_ioMap (unsigned int addr, unsigned int size)
215 {
216 unsigned int pageSize = getpagesize ();
217 unsigned int taddr;
218 unsigned int tsize;
219 uintptr_t * userAddr = NULL;
221 taddr = addr;
222 tsize = size;
223 /* Align the physical address to page boundary */
224 tsize = tsize + (taddr % pageSize);
225 taddr = taddr - (taddr % pageSize);
226 userAddr = (uintptr_t *)mmap_device_io(tsize, taddr);
227 if (userAddr == (uintptr_t *) MAP_FAILED) {
228 userAddr = NULL;
229 perror ("Failed to map memory to user space with mmap_device_io!");
230 }
231 else {
232 /* Change the user address to reflect the actual user address of
233 * memory block mapped. This is done since during mmap memory block
234 * was shifted (+-) so that it is aligned to page boundary.
235 */
236 taddr = (unsigned int)userAddr;
237 taddr = taddr + (addr % pageSize);
238 }
240 return taddr;
241 }
244 /*!
245 * @brief Function to unmap a memory region specific to the driver.
246 *
247 * @sa OsalDrv_close,OsalDrv_open,OsalDrv_map
248 */
249 static void
250 OsalDrv_ioUnmap (unsigned int addr, unsigned int size)
251 {
252 unsigned int pageSize = getpagesize ();
253 unsigned int taddr;
254 unsigned int tsize;
255 unsigned int status;
257 taddr = addr;
258 tsize = size;
260 /* Get the actual user address and size. Since these are modified at the
261 * time of mmaping, to have memory block page boundary aligned.
262 */
263 tsize = tsize + (taddr % pageSize);
264 taddr = taddr - (taddr % pageSize);
265 status = munmap_device_io((uintptr_t) taddr, tsize);
266 if (status == -1) {
267 perror ("Failed to unmap memory with munmap_device_io! ");
268 }
269 }
271 /*========= PerfUtils_calcSysClkFreq============
272 * read the status from CM_SYS_CLK_REG
273 * and will map that value to sys freq
274 */
275 static
276 unsigned int PerfUtils_calcSysClkFreq (void)
277 {
278 unsigned int reg;
279 unsigned int sysClkFreq;
280 static int statusInit = 0;
281 Memory_MapInfo *cmSysClkSel;
283 cmSysClkSel = &(memoryMap[PERF_UTIL_SYSCLK_INDEX]);
284 cmSysClkSel->src = CM_SYS_CLKSEL_REG;
285 cmSysClkSel->size = 0x4;
287 #ifdef PERF_UTILS_DEBUG_SUPPORT
288 printf ("PerfUtils_calcSysClkFreq :Enter\n");
289 #endif
290 if (0 == statusInit) {
292 cmSysClkSel->dst = OsalDrv_ioMap (cmSysClkSel->src, cmSysClkSel->size);
293 if(cmSysClkSel->dst == NULL) {
294 printf("PerfUtils_calcSysClkFreq: Memory_map failed"
295 "returned [0x%x]\n", errno);
296 return -1;
297 }
298 statusInit = 1;
299 }
301 printf ("PerfUtils_calcSysClkFreq :Enter1\n");
302 addrCmSysClkSelReg = (unsigned int*)cmSysClkSel->dst;
303 printf ("PerfUtils_calcSysClkFreq :Enter2\n");
304 reg = (unsigned int)*addrCmSysClkSelReg;
305 printf ("PerfUtils_calcSysClkFreq :Enter3\n");
306 //reg &= 0x00000007;
308 printf ("PerfUtils_calcSysClkFreq :Enter4\n");
309 #if 0
310 switch (reg) {
311 case 0 :
312 sysClkFreq = SYS_CLK_UNINITIALIZED;
313 break;
314 case 1 :
315 sysClkFreq = SYS_CLK_12MHZ_FREQ;
316 break;
317 case 2 :
318 sysClkFreq = SYS_CLK_13MHZ_FREQ;
319 break;
320 case 3 :
321 sysClkFreq = SYS_CLK_16_8MHZ_FREQ;
322 break;
323 case 4 :
324 sysClkFreq = SYS_CLK_19_2MHZ_FREQ;
325 break;
326 case 5 :
327 sysClkFreq = SYS_CLK_26MHZ_FREQ;
328 break;
329 case 6 :
330 sysClkFreq = SYS_CLK_27MHZ_FREQ;
331 break;
332 case 7 :
333 sysClkFreq = SYS_CLK_38_4MHZ_FREQ;
334 break;
335 }
336 #endif
337 sysClkFreq = SYS_CLK_38_4MHZ_FREQ;
339 OsalDrv_ioUnmap(cmSysClkSel->dst, cmSysClkSel->size);
340 #ifdef PERF_UTILS_DEBUG_SUPPORT
341 printf("SysClk is cloking @ [%d]\n",sysClkFreq);
342 printf ("PerfUtils_calcSysClkFreq :Leave\n");
343 #endif
344 return sysClkFreq;
345 }
346 /*
347 *========= PerfUtils_setRegValue==============
348 * Generic function for writing value to register
349 */
350 static inline
351 void PerfUtils_setRegValue (volatile unsigned int *addrReg, unsigned int bitPos,
352 unsigned int noBits, unsigned int value)
353 {
354 unsigned int valueTmp = 0xFFFFFFFF;
355 unsigned int valueMask = (0x1 << noBits);
356 unsigned int valueStore;
358 #ifdef PERF_UTILS_DEBUG_SUPPORT
359 printf ("PerfUtils_setRegValue:Enter addrReg:[%x] *addrReg[%x] bitPos:[%x]\n"
360 "noBits:[%x] value:[%x]\n", (unsigned int)addrReg, (unsigned int)*addrReg, bitPos, noBits, value);
361 #endif
362 valueMask -= 1;
364 if (0 == value) {
365 valueTmp ^= ((valueMask << bitPos));
366 *(addrReg) &= valueTmp;
367 }
368 else {
369 valueStore = (value << bitPos);
370 #ifdef PERF_UTILS_DEBUG_SUPPORT
371 printf ("PerfUtils_setRegValue:Writing value [%x] to [%x]\n",
372 valueStore,(unsigned int)addrReg);
373 #endif
374 *(addrReg) |= valueStore;
375 }
376 #ifdef PERF_UTILS_DEBUG_SUPPORT
377 printf ("PerfUtils_setRegValue:Leave addrReg:[%x] *addrReg[%x] bitPos:[%x]\n"
378 "noBits:[%x] value:[%x]\n", (unsigned int)addrReg, (unsigned int)*addrReg, bitPos, noBits, value);
379 #endif
381 }
382 /*
383 *============= PerfUtils_gptimerModuleConfig===========
384 * Configure the gptimer module for autoreload,prescalar
385 */
386 static
387 int PerfUtils_gptimerModuleConfig (Perf_GptimerConfig *gptimerConfig)
388 {
390 Memory_MapInfo *gptimerModConf;
391 int status = PERF_UTILS_SUCCESS;
392 unsigned int valueTest;
394 #ifdef PERF_UTILS_DEBUG_SUPPORT
395 printf ("PerfUtils_gptimerModuleConfig :Enter\n");
396 #endif
397 if (NULL == gptimerConfig) {
398 printf ("Module cconfiguration parameted passed is NULL\n");
399 return PERF_UTILS_FAILURE;
400 }
401 gptimerModConf = &(memoryMap[PERF_UTIL_GPTIMER_INDEX]);
402 gptimerModConf->src = GPTIMER10_MODULE_BASE_ADDR;
403 gptimerModConf->size = GPTIMER_MODULE_REGSET_SIZE;
405 gptimerModConf->dst = OsalDrv_ioMap(gptimerModConf->src, gptimerModConf->size);
406 if (gptimerModConf->dst == NULL) {
407 printf ("PerfUtils_gptimerModuleConfig:Memory_map\
408 failed status [%x]\n", status);
409 return status;
410 }
412 addrGptimerBaseReg = (unsigned int*)gptimerModConf->dst;
413 #ifdef PERF_UTILS_DEBUG_SUPPORT
414 printf ("PerfUtils_gptimerModuleConfig:addrGptimerBaseReg [%x]\n",
415 (unsigned int)addrGptimerBaseReg);
416 #endif
417 addrGptimerCtrlReg = REG(GPTIMER, 10, CTRL, addrGptimerBaseReg);
418 #ifdef PERF_UTILS_DEBUG_SUPPORT
419 printf ("PerfUtils_gptimerModuleConfig:addrGptimerCtrlReg [%x]\n",
420 (unsigned int)addrGptimerCtrlReg);
421 #endif
422 addrGptimerReadReg = REG(GPTIMER, 10, CRR, addrGptimerBaseReg);
424 #ifdef PERF_UTILS_DEBUG_SUPPORT
425 printf ("PerfUtils_gptimerModuleConfig:addrGptimerReadReg [%x]\n",
426 (unsigned int)addrGptimerReadReg);
427 #endif
428 addrGptimerLoadReg = REG(GPTIMER, 10, LDR, addrGptimerBaseReg);
429 #ifdef PERF_UTILS_DEBUG_SUPPORT
430 printf ("PerfUtils_gptimerModuleConfig:addrGptimerLoadReg [%x]\n",
431 (unsigned int)addrGptimerLoadReg);
432 #endif
434 /* Setting to Autoreload mode
435 0x0: One shot timer
436 0x1: Autoreload timer
437 */
438 if (gptimerConfig->enableautoReload) {
439 PerfUtils_setRegValue (addrGptimerCtrlReg,
440 GPTIMER_CTRLREG_AR_BIT_POS, 1, 1);
441 }
443 /*The timer counter is prescaled with the value 2(PTV+1).
444 Example: PTV = 3, counter increases value (if started)
445 after 16 functional clock periods.
446 */
447 if (gptimerConfig->enablePrescale) {
448 PerfUtils_setRegValue (addrGptimerCtrlReg,GPTIMER_CTRLREG_PTV_BIT_POS,
449 gptimerConfig->valuePrescalar, 1);
450 valuePrescalar = (0x1 << 2);
452 /* Enabling prescalar
453 0x0: The TIMER clock input pin clocks the counter.
454 0x1: The divided input pin clocks the counter.
455 */
456 PerfUtils_setRegValue (addrGptimerCtrlReg,
457 GPTIMER_CTRLREG_PRE_BIT_POS, 1, 0);
458 }
459 #ifdef PERF_UTILS_DEBUG_SUPPORT
460 printf ("PerfUtils_gptimerModuleConfig:*addrGptimerCtrlReg [%x]\n",
461 *addrGptimerCtrlReg);
462 #endif
463 /*Initializing Timer Counter value to 0 */
464 *addrGptimerReadReg = 0x00000000;
465 /*Initializing Loader Register value to 0 */
466 *addrGptimerLoadReg = 0x00000000;
468 timeStampUserSpace = addrGptimerReadReg;
469 valueTest = *(timeStampUserSpace);
471 #ifdef PERF_UTILS_DEBUG_SUPPORT
472 printf ("PerfUtils_gptimerModuleConfig :Leave\n");
473 #endif
474 return status;
475 }
476 /*
477 *========= PerfUtils_startGpTimer======
478 * To start the gptimer
479 */
480 void PerfUtils_startGpTimer (int gpTimerNo)
481 {
482 #ifdef PERF_UTILS_DEBUG_SUPPORT
483 printf ("PerfUtils_startGpTimer :Enter GPTIMER[%x]\n", gpTimerNo);
484 #endif
485 #ifdef USE_GPTIMER
486 PerfUtils_setRegValue (addrGptimerCtrlReg,
487 GPTIMER_CTRLREG_ST_BIT_POS, 1, 1);
488 #endif
489 #ifdef PERF_UTILS_DEBUG_SUPPORT
490 printf ("PerfUtils_startGpTimer :Leave GPTIMER[%x]\n", gpTimerNo);
491 #endif
492 }
493 /*======= PerfUtils_stopGpTimer=========
494 * To Stop the gptimer
495 */
497 void PerfUtils_stopGpTimer (int gpTimerNo)
498 {
499 #ifdef PERF_UTILS_DEBUG_SUPPORT
500 printf ("PerfUtils_stopGpTimer :Enter GPTIMER[%x]\n", gpTimerNo);
501 #endif
502 #ifdef USE_GPTIMER
503 PerfUtils_setRegValue (addrGptimerCtrlReg,
504 GPTIMER_CTRLREG_ST_BIT_POS, 1, 0);
506 /* Resetting Read Register Value */
507 *addrGptimerReadReg = 0x00000000;
508 #endif
509 #ifdef PERF_UTILS_DEBUG_SUPPORT
510 printf ("PerfUtils_stopGpTimer :Leave GPTIMER[%x]\n", gpTimerNo);
511 #endif
512 }
513 /*
514 *============PerfUtils_selectClkSrc================
515 * Selecting the clock src b/w 32Khz and system clock
516 */
517 static
518 int PerfUtils_selectClkSrc (int clkSrc)
519 {
520 int status = PERF_UTILS_SUCCESS;
521 unsigned int readvalue;
522 Memory_MapInfo *clkMgmntL4Gptimer =
523 &(memoryMap[PERF_UTILS_CML4_INDEX]);
525 clkMgmntL4Gptimer->src = (CM_L4PER_GPTIMER_BASE_ADDR);
526 clkMgmntL4Gptimer->size = (CM_L4PER_GPTIMER_REGSET_SIZE);
528 clkMgmntL4Gptimer->dst = OsalDrv_ioMap(clkMgmntL4Gptimer->src, clkMgmntL4Gptimer->size);
529 if (clkMgmntL4Gptimer->dst == NULL) {
530 printf ("PerfUtils_selectClkSrc:Memory_map failed status[%x]\n", status);
531 return status;
532 }
534 addrCmL4GptimerBaseReg = (unsigned int*) (clkMgmntL4Gptimer->dst);
535 addrCmL4PGptimerCtrlReg = REG(CM_L4PER_GPTIMER, 10, CLKCTRL,
536 addrCmL4GptimerBaseReg);
537 readvalue = *addrCmL4PGptimerCtrlReg;
538 while (!(readvalue & 0x02)) {
539 PerfUtils_setRegValue (addrCmL4PGptimerCtrlReg, 0, 2, 2);
540 readvalue = *addrCmL4PGptimerCtrlReg;
541 }
543 OsalDrv_ioUnmap(clkMgmntL4Gptimer->dst, clkMgmntL4Gptimer->size);
544 return status;
545 }
547 /*
548 * ========= PerfUtils_init ========
549 */
550 int PerfUtils_init()
551 {
552 int status;
553 unsigned int sysClkFreq;
554 Perf_GptimerConfig gpTimerConfig;
556 PerfUtils_selectClkSrc (10);
557 #ifdef USE_GPTIMER
558 sysClkFreq = PerfUtils_calcSysClkFreq();
559 if (0 == sysClkFreq) {
560 printf("PerfUtils_init : SYSCLK not initialized in kernel\n"
561 "can't use sys clk timer for profiling\n");
562 status = PERF_UTILS_INIT_FAILED;
563 return status;
564 }
566 sysClockFreq = sysClkFreq;
567 gpTimerConfig.enableautoReload = 1;
568 gpTimerConfig.enablePrescale = 0;
569 gpTimerConfig.valuePrescalar = 0;
570 gpTimerConfig.gpTimer =10;
571 status = PerfUtils_gptimerModuleConfig (&gpTimerConfig);
572 if (0 > status) {
573 printf ("PerfUtils_init:PerfUtils_gptimerModuleConfig"
574 "failed status[%x]\n", status);
575 return status;
576 }
577 #endif
579 perfRecordsUserSpace = perfRecordsArr;
581 memset(perfRecordsUserSpace, 0, sizeof(perfRecordsUserSpace)
582 * MAX_NUM_USERSPACE_RECORDS);
584 return status;
585 }
587 /*
588 * ========PerfUtils_destroy========
589 * To destroy the gptimer module
590 */
591 int PerfUtils_destroy (void)
592 {
593 int status = 0;
595 OsalDrv_ioUnmap((unsigned int)addrGptimerBaseReg, GPTIMER_MODULE_REGSET_SIZE);
597 return status;
598 }
601 /*
602 * ======== PerfUtils_addFxn ========
603 * To add functions for profiling
604 */
605 void PerfUtils_addFxn(unsigned int fxnIndex, char * fxnName, unsigned int clientproc, unsigned int serverproc, unsigned int msgsize)
606 {
607 #ifdef USE_GPTIMER
608 Perf_FunctionRecord *record = &(perfRecordsUserSpace[fxnIndex]);
609 #else
610 Perf_LocalRecord *record = &(perfRecordsUserSpace[fxnIndex]);
611 #endif
613 #ifdef PERF_UTILS_DEBUG_SUPPORT
614 printf("PerfUtils_addFxn: Enter\n");
615 printf("PerfUtils_addFxn: Adding function %s\n",fxnName);
616 #endif
618 strcpy(record->fxnName, fxnName);
619 record->client_proc = clientproc;
620 record->server_proc = serverproc;
621 record->msg_size = msgsize;
623 #ifdef PERF_UTILS_DEBUG_SUPPORT
624 printf("PerfUtils_addFxn: Leave\n");
625 #endif
626 }
628 /*
629 * ============= PerfUtils_enter ============
630 * Record enter timing for the registered function
631 */
632 int PerfUtils_enter(unsigned int fxnIndex)
633 {
634 int status = 0;
635 int noEntry = 0;
636 #ifdef USE_GPTIMER
637 Perf_FunctionRecord *record = (perfRecordsUserSpace + fxnIndex);
638 #else
639 Perf_LocalRecord *record = (perfRecordsUserSpace + fxnIndex);
640 #endif
642 #ifdef PERF_UTILS_DEBUG_SUPPORT
643 printf ("PerfUtils_enter: Enter\n");
644 #endif
645 noEntry = record->numEntries;
648 if(noEntry < MAX_ENTRIES_PER_FUNCTION) {
649 #ifdef USE_GPTIMER
650 record->enterTimes[record->numEntries] = *(timeStampUserSpace);
651 #else
652 status = gettimeofday(&(record->enterTimes[noEntry]),NULL);
654 #ifdef PERF_UTILS_DEBUG_SUPPORT
655 printf("enter Timestamp sec [%d] usec [%d] \n",record->enterTimes[noEntry].tv_sec,
656 record->enterTimes[noEntry].tv_usec);
657 #endif
658 if (0 != status) {
659 printf("PerfUtils_enter:error in getimeofday\n");
660 }
661 #endif
662 }
664 #ifdef PERF_UTILS_DEBUG_SUPPORT
665 printf("PerfUtils_enter: Leave\n");
666 #endif
667 return status;
668 }
670 /*
671 * ============= PerfUtils_exit ===============
672 * Record the exit timing for the registered function
673 */
674 int PerfUtils_exit(unsigned int fxnIndex)
675 {
676 int status = 0;
677 int noEntry = 0;
678 #ifdef USE_GPTIMER
679 unsigned int exitTime = *(timeStampUserSpace);
680 Perf_FunctionRecord *record = (perfRecordsUserSpace + fxnIndex);
681 #else
682 Perf_LocalRecord *record = (perfRecordsUserSpace + fxnIndex);
683 #endif
685 #ifdef PERF_UTILS_DEBUG_SUPPORT
686 printf("PerfUtils_exit: Enter\n");
687 #endif
689 noEntry = record->numEntries;
690 if(noEntry < MAX_ENTRIES_PER_FUNCTION) {
692 #ifdef USE_GPTIMER
693 record->exitTimes[record->numEntries] = exitTime;
694 #else
695 status = gettimeofday(&(record->exitTimes[noEntry]),NULL);
696 #endif
698 #if defined(PERF_UTILS_DEBUG_SUPPORT) && !defined(USE_GPTIMER)
699 printf("exit Timestamp sec [%d] usec [%d] \n",record->exitTimes[noEntry].tv_sec,
700 record->exitTimes[noEntry].tv_usec);
701 #endif
702 if (0 != status) {
703 printf("PerfUtils_enter:error in getimeofday\n");
704 }
706 record->numEntries++;
707 }
709 #ifdef PERF_UTILS_DEBUG_SUPPORT
710 printf("PerfUtils_exit: Leave\n");
711 #endif
713 return status;
714 }
716 static
717 void PerfUtils_printUserSpaceReport (void)
718 {
719 unsigned int i, j;
720 unsigned int sysClkFreq;
721 unsigned int enterTime, exitTime;
722 unsigned int totalTimeuSec, diff;
723 #if 0
724 FILE *fp;
725 #endif
726 #ifdef USE_GPTIMER
727 Perf_FunctionRecord *record;
728 sysClkFreq = sysClockFreq;
729 sysClkFreq = sysClkFreq/100000;
730 #else
731 Perf_LocalRecord *record;
732 #endif
733 #if 0
734 fp = fopen("Report.txt","w+");
736 if (NULL == fp){
737 printf("Opening file filed\n");
738 exit(0);
739 }
740 #endif
741 printf("============UserSpace report============\n");
743 for(j = 0; j < MAX_NUM_USERSPACE_RECORDS; j++) {
744 record = (perfRecordsUserSpace + j);
745 for(i = 0; i < record->numEntries; i++) {
746 if (0 == i) {
747 printf("%s\n",record->fxnName);
748 printf("clientproc %u\n",record->client_proc);
749 printf("serverproc %u\n",record->server_proc);
750 printf("msgsize %u\n",record->msg_size);
751 printf("count %u\n",record->numEntries);
752 totalTimeuSec = 0;
753 }
754 #ifdef USE_GPTIMER
755 enterTime = record->enterTimes[i];
756 exitTime = record->exitTimes[i];
757 #else
758 enterTime = ((record->enterTimes[i].tv_sec * 1000000) + record->enterTimes[i].tv_usec);
759 exitTime = ((record->exitTimes[i].tv_sec * 1000000) + record->exitTimes[i].tv_usec);
760 #endif
761 diff = (exitTime - enterTime);
762 #ifdef USE_GPTIMER
763 /* Converting to usecs */
764 totalTimeuSec += (diff * 10 / sysClkFreq);
765 printf ("> %s took %u us or period %u\n", record->fxnName, diff * 10 / sysClkFreq, diff);
766 #else
767 printf("record->enterTimes[i].tv_sec [%d] record->exitTimes[i].tv_sec [%d]\n",
768 record->enterTimes[i].tv_sec,record->exitTimes[i].tv_sec);
769 printf("record->enterTimes[i].tv_usec [%d] record->exitTimes[i].tv_usec [%d]\n",
770 record->enterTimes[i].tv_usec,record->exitTimes[i].tv_usec);
771 printf ("> %s took %u us\n", record->fxnName, diff);
772 #endif
774 }
775 if (record->numEntries > 0) {
776 printf("========================================\n");
777 printf("AVG time: %u us\n", totalTimeuSec / record->numEntries);
778 printf("========================================\n");
779 }
780 }
781 // fclose(fp);
782 printf("===========End of UserSpace report======\n");
783 }
786 /*
787 * ======== PerfUtils_printReport ========
788 * Print report to user
789 */
791 void PerfUtils_printReport (int printLevel)
792 {
793 if (printLevel == 1) {
794 PerfUtils_printUserSpaceReport ();
795 }
796 }