1    /*
     2     * Copyright (c) 2013, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     */
    32    /*
    33     *  ======== Pmu.xdc ========
    34     *
    35     */
    36    
    37    package ti.sysbios.family.arm.v7a;
    38    
    39    import xdc.rov.ViewInfo;
    40    import xdc.runtime.Assert;
    41    
    42    import ti.sysbios.hal.Hwi;
    43    
    44    /*!
    45     *  ======== Pmu ========
    46     *  ARM Performance Monitoring Unit module
    47     *
    48     *  This module manages the performance monitor unit's counters on ARM v7A
    49     *  processors. This module does not manage the cycle counter. The cycle
    50     *  counter is managed by the Timestamp module on most ARM cores.
    51     *
    52     *  The following is an example of how to configure one of the Pmu counters
    53     *  to count L2 cache access events on a Cortex-A15 processor:
    54     *
    55     *  C source file:
    56     *  @p(code)
    57     *  #include <ti/sysbios/family/arm/v7a/Pmu.h>
    58     *
    59     *  Int main(Int argc, char *argv[])
    60     *  {
    61     *      // Set L2 cache access as the event type for event counter 0.
    62     *      // The event number corresponding to each event type can be determined
    63     *      // using the Cortex-A15 reference manual.
    64     *      Pmu_configureCounter(0, 0x16, FALSE);
    65     *
    66     *      // Reset the count
    67     *      Pmu_resetCount(0);
    68     *
    69     *      // Start the counter
    70     *      Pmu_startCounter(0);
    71     *
    72     *      // code
    73     *      ...
    74     *
    75     *      // Stop the counter
    76     *      Pmu_stopCounter(0);
    77     *
    78     *      // Read and print the count
    79     *      System_printf("L2 access count: %d\n", Pmu_getCount(0));
    80     *
    81     *      return 0;
    82     *  }
    83     *  @p
    84     *
    85     *  *.cfg file:
    86     *  @p(code)
    87     *  var Pmu = xdc.useModule('ti.sysbios.family.arm.v7a.Pmu');
    88     *  @p
    89     *
    90     *  @p(html)
    91     *  <h3> Calling Context </h3>
    92     *  <table border="1" cellpadding="3">
    93     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
    94     *    </colgroup>
    95     *
    96     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
    97     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    98     *    <!--                               -->
    99     *    <tr><td> {@link #configureCounter}    </td><td>   Y    </td>
   100     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   101     *    <tr><td> {@link #clearOverflowStatus}       </td><td>   Y    </td>
   102     *    <td>   Y   </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   103     *    <tr><td> {@link #disableInterrupt}       </td><td>   Y    </td>
   104     *    <td>   Y   </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   105     *    <tr><td> {@link #enableInterrupt}       </td><td>   Y    </td>
   106     *    <td>   Y   </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   107     *    <tr><td> {@link #getCount}       </td><td>   Y    </td><td>   Y   </td>
   108     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   109     *    <tr><td> {@link #getOverflowStatus}       </td><td>   Y    </td>
   110     *    <td>   Y   </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   111     *    <tr><td> {@link #resetCount}    </td><td>   Y    </td><td>   Y    </td>
   112     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   113     *    <tr><td> {@link #setCount}    </td><td>   Y    </td><td>   Y    </td>
   114     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   115     *    <tr><td> {@link #setInterruptFunc}    </td><td>   Y    </td>
   116     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   117     *    <tr><td> {@link #startCounter}    </td><td>   Y    </td><td>   Y    </td>
   118     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   119     *    <tr><td> {@link #stopCounter}    </td><td>   Y    </td><td>   Y    </td>
   120     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   121     *    <tr><td colspan="6"> Definitions: <br />
   122     *       <ul>
   123     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   124     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   125     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   126     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   127     *           <ul>
   128     *             <li> In your module startup after this module is started
   129     *   (e.g. PerfMonitor_Module_startupDone() returns TRUE). </li>
   130     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   131     *             <li> During main().</li>
   132     *             <li> During BIOS.startupFxns.</li>
   133     *           </ul>
   134     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   135     *           <ul>
   136     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   137     *             <li> In your module startup before this module is started
   138     *   (e.g. Cache_Module_startupDone() returns FALSE).</li>
   139     *           </ul>
   140     *       </ul>
   141     *    </td></tr>
   142     *
   143     *  </table>
   144     *  @p
   145     */
   146    
   147    @ModuleStartup
   148    @DirectCall
   149    module Pmu
   150    {
   151        /*!
   152         *  ======== intNum ========
   153         *  A Hwi is created for the interrupt number 'pmuIntNum'
   154         *
   155         *  pmuIntNum specifies the interrupt number that is connected to the
   156         *  nPMUIRQ signal from the PMU module.
   157         */
   158        config UInt intNum = (~0);
   159    
   160        /*! Pmu interrupt handler function type definition. */
   161        typedef Void (*IntHandlerFuncPtr)(UArg);
   162    
   163        /*!
   164         *  ======== ModView ========
   165         *  @_nodoc
   166         */
   167        metaonly struct PmuInfoView {
   168            UInt    numEventCounters;   /* Number of event counters implemented
   169                                           in Hardware */
   170        };
   171    
   172        /*!
   173         *  ======== rovViewInfo ========
   174         *  @_nodoc
   175         */
   176        @Facet
   177        metaonly config ViewInfo.Instance rovViewInfo =
   178            ViewInfo.create({
   179                viewMap: [
   180                    ['Pmu Info',  { type: ViewInfo.MODULE_DATA,
   181                                    viewInitFxn: 'viewInitPmuInfo',
   182                                    structName: 'PmuInfoView'}],
   183               ]
   184            });
   185    
   186        /*!
   187         *  ======== A_badIntNum ========
   188         *  Assert raised when module cannot determine PMU interrupt number
   189         *  for the given target/platform and the user is not providing the
   190         *  interrupt number using intNum config param.
   191         */
   192        config xdc.runtime.Assert.Id A_badIntNum  = {
   193            msg: "A_badIntNum: Set PMU interrupt number using Pmu.intNum config param."
   194        };
   195    
   196        /*!
   197         *  ======== A_invalidCounterId ========
   198         *  Assert raised when invalid PMU counter Id passed.
   199         */
   200        config xdc.runtime.Assert.Id A_invalidCounterId  = {
   201            msg: "A_invalidCounterId: Invalid PMU counter Id passed."
   202        };
   203    
   204        /*!
   205         *  ======== interruptFunc ========
   206         *  PMU overflow interrupt callback function pointer
   207         *
   208         *  When a counter overflow interrupt occurs, the registered
   209         *  callback function is called with the contents of the Overflow
   210         *  Flag Status Register passed as an argument. The overflow
   211         *  status flag can be used to determine which counter generated
   212         *  the interrupt when multiple counters are running with
   213         *  overflow interrupt enabled.
   214         */
   215        metaonly config IntHandlerFuncPtr interruptFunc = null;
   216    
   217        /*!
   218         *  ======== setInterruptFunc ========
   219         *  Set callback function
   220         *
   221         *  When a counter overflow interrupt occurs, the registered
   222         *  callback function is called with the contents of the Overflow
   223         *  Flag Status Register passed as an argument. The overflow
   224         *  status flag can be used to determine which counter generated
   225         *  the interrupt when multiple counters are running with
   226         *  overflow interrupt enabled.
   227         *
   228         *  Setting the callback function through this API overrides
   229         *  the callback function set through {@link #interruptFunc} config param.
   230         *
   231         *  @param(interruptFunc)       Callback function
   232         */
   233        Void setInterruptFunc(IntHandlerFuncPtr interruptFunc);
   234    
   235        /*!
   236         *  ======== startCounter ========
   237         *  Start an event counter
   238         *
   239         *  @param(counterId)       Event counter Id
   240         */
   241        Void startCounter(UInt counterId);
   242    
   243        /*!
   244         *  ======== stopCounter ========
   245         *  Stop an event counter
   246         *
   247         *  @param(counterId)       Event counter Id
   248         */
   249        Void stopCounter(UInt counterId);
   250    
   251        /*!
   252         *  ======== resetCount ========
   253         *  Reset the event counter's count to 0
   254         *
   255         *  @param(counterId)       Event counter Id
   256         */
   257        Void resetCount(UInt counterId);
   258    
   259        /*!
   260         *  ======== setCount ========
   261         *  Set the event counter's count to counterVal.
   262         *
   263         *  @param(counterId)       Event counter Id
   264         *  @param(counterVal)      Counter value to set
   265         */
   266        Void setCount(UInt counterId, UInt32 counterVal);
   267    
   268        /*!
   269         *  ======== configureCounter ========
   270         *  Set the event type for an event counter and enable/disable
   271         *  interrupt generation on a counter overflow
   272         *
   273         *  This function disables/stops the counter, sets the new event type,
   274         *  enables/disables interrupt generation and then re-enables the
   275         *  counter if it was enabled before.
   276         *
   277         *  Please refer the device's Technical Reference Manual for a list of
   278         *  supported event types and their corresponding event numbers.
   279         *
   280         *  @param(counterId)       Event counter Id
   281         *  @param(eventNum)        Event number
   282         *  @param(interruptEnable) Enable/Disable Interrupt generation
   283         */
   284        Void configureCounter(UInt counterId, UInt eventNum, Bool interruptEnable);
   285    
   286        /*!
   287         *  ======== enableInterrupt ========
   288         *  Enable interrupt generation on a counter overflow
   289         *
   290         *  @param(counterId)       Event counter Id
   291         */
   292        Void enableInterrupt(UInt counterId);
   293    
   294        /*!
   295         *  ======== disableInterrupt ========
   296         *  Disable interrupt generation on a counter overflow
   297         *
   298         *  @param(counterId)       Event counter Id
   299         */
   300        Void disableInterrupt(UInt counterId);
   301    
   302        /*!
   303         *  ======== clearOverflowStatus ========
   304         *  Clear overflow status flag
   305         *
   306         *  @param(counterId)       Event counter Id
   307         */
   308        Void clearOverflowStatus(UInt counterId);
   309    
   310        /*!
   311         *  ======== getCount ========
   312         *  Read the event count
   313         *
   314         *  @param(counterId)       Event counter Id
   315         *  @b(returns)             Event count
   316         */
   317        UInt32 getCount(UInt counterId);
   318    
   319        /*!
   320         *  ======== getNumCounters ========
   321         *  Reads and returns the number of event counters
   322         *  implemented in HW.
   323         */
   324        UInt getNumCounters();
   325    
   326        /*!
   327         *  ======== getOverflowStatus ========
   328         *  Returns a boolean indicating status of overflow flag
   329         *
   330         *  @param(counterId)       Event counter Id
   331         *  @b(returns)             Overflow status
   332         */
   333        Bool getOverflowStatus(UInt counterId);
   334    
   335        /*!
   336         *  @_nodoc
   337         *  ======== getEnabled ========
   338         *  Get the bit mask of counter enable.
   339         */
   340        UInt32 getEnabled();
   341    
   342        /*!
   343         *  @_nodoc
   344         *  ======== startCounterI ========
   345         *  Internal inline asm implementation.
   346         */
   347        Void startCounterI(UInt counterId);
   348    
   349        /*!
   350         *  @_nodoc
   351         *  ======== stopCounterI ========
   352         *  Internal inline asm implementation.
   353         */
   354        Void stopCounterI(UInt counterId);
   355    
   356        /*!
   357         *  @_nodoc
   358         *  ======== resetCountI ========
   359         *  Internal inline asm implementation.
   360         */
   361        Void resetCountI(UInt counterId);
   362    
   363        /*!
   364         *  @_nodoc
   365         *  ======== setCountI ========
   366         *  Internal inline asm implementation.
   367         */
   368        Void setCountI(UInt counterId, UInt32 counterVal);
   369    
   370        /*!
   371         *  @_nodoc
   372         *  ======== enableInterrupt ========
   373         *  Internal inline asm implementation.
   374         */
   375        Void enableInterruptI(UInt counterId);
   376    
   377        /*!
   378         *  @_nodoc
   379         *  ======== disableInterrupt ========
   380         *  Internal inline asm implementation.
   381         */
   382        Void disableInterruptI(UInt counterId);
   383    
   384        /*!
   385         *  @_nodoc
   386         *  ======== clearOverflowStatusI ========
   387         *  Internal inline asm implementation.
   388         */
   389        Void clearOverflowStatusI(UInt counterId);
   390    
   391        /*!
   392         *  @_nodoc
   393         *  ======== getCountI ========
   394         *  Internal inline asm implementation.
   395         */
   396        UInt32 getCountI(UInt counterId);
   397    
   398        /*!
   399         *  @_nodoc
   400         *  ======== getOverflowStatus ========
   401         *  Internal inline asm implementation.
   402         */
   403        UInt32 getOverflowStatusI(UInt counterId);
   404    
   405    internal:
   406    
   407        /*
   408         *  ======== configureCounterI ========
   409         *  Internal inline asm implementation.
   410         */
   411        Void configureCounterI(UInt counterId, UInt eventNum);
   412    
   413        /*
   414         *  ======== clearOverflowStatusReg ========
   415         *  Write to Overflow Flag Status Clear register.
   416         */
   417        Void clearOverflowStatusReg(UInt32 clearMask);
   418    
   419        /*
   420         *  ======== getOverflowStatusReg ========
   421         *  Read Overflow Flag Status Clear register.
   422         */
   423        UInt32 getOverflowStatusReg();
   424    
   425        /*
   426         *  ======== initCounters ========
   427         *  Disables interrupt request generation for all event counters, clears
   428         *  the overflow status flag, resets and enables all event counters.
   429         *
   430         *  This function is called during module startup.
   431         */
   432        Void initCounters(UInt32 counterMask);
   433    
   434        /*
   435         *  ======== interruptHandler ========
   436         *  Pmu interrupt handler function.
   437         */
   438        Void interruptHandler(UArg arg);
   439    
   440        struct Module_State {
   441            UInt                    numCounters;    /* Number of event counters
   442                                                       implemented in Hardware */
   443            Hwi.Handle              hwiHandle;
   444            IntHandlerFuncPtr       interruptFunc;
   445        }
   446    }