]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - qnx/src/ipc3x_dev/perfutils/PerfUtils.c
Merge remote-tracking branch 'ramsey/ready' into 11_eng
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / perfutils / PerfUtils.c
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
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
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)
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;
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)
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         }
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)
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;
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)
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
382 /*
383  *============= PerfUtils_gptimerModuleConfig===========
384  * Configure the gptimer module for autoreload,prescalar
385  */
386 static
387 int PerfUtils_gptimerModuleConfig (Perf_GptimerConfig *gptimerConfig)
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;
476 /*
477  *========= PerfUtils_startGpTimer======
478  *          To start the gptimer
479  */
480 void PerfUtils_startGpTimer (int gpTimerNo)
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
493 /*======= PerfUtils_stopGpTimer=========
494  *        To  Stop the gptimer
495  */
497 void PerfUtils_stopGpTimer (int gpTimerNo)
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
513 /*
514  *============PerfUtils_selectClkSrc================
515  * Selecting the clock src  b/w 32Khz and system clock
516  */
517 static
518 int PerfUtils_selectClkSrc (int clkSrc)
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;
547 /*
548  * ========= PerfUtils_init ========
549  */
550 int PerfUtils_init()
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;
587 /*
588  * ========PerfUtils_destroy========
589  * To destroy the gptimer module
590  */
591 int PerfUtils_destroy (void)
593     int status = 0;
595     OsalDrv_ioUnmap((unsigned int)addrGptimerBaseReg, GPTIMER_MODULE_REGSET_SIZE);
597     return status;
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)
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
628 /*
629  * ============= PerfUtils_enter ============
630  * Record enter timing for the registered function
631  */
632 int PerfUtils_enter(unsigned int fxnIndex)
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;
670 /*
671  * ============= PerfUtils_exit ===============
672  * Record the exit timing for the registered function
673  */
674 int PerfUtils_exit(unsigned int fxnIndex)
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;
716 static
717 void PerfUtils_printUserSpaceReport (void)
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");
786 /*
787  * ======== PerfUtils_printReport ========
788  *          Print report to user
789  */
791 void PerfUtils_printReport (int printLevel)
793     if (printLevel == 1) {
794         PerfUtils_printUserSpaceReport ();
795     }