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