1    /*
     2     * Copyright (c) 2012, 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     *  ======== Timer.xdc ========
    34     */
    35    
    36    package ti.sysbios.family.arm.systimer;
    37    
    38    import xdc.rov.ViewInfo;
    39    
    40    import xdc.runtime.Error;
    41    import xdc.runtime.Types;
    42    
    43    import ti.sysbios.family.arm.gic.Hwi;
    44    import ti.sysbios.interfaces.ITimer;
    45    
    46    /*!
    47     *  ======== Timer ========
    48     *  Generic Timer Peripheral Manager for Arm v7A family prcoessors
    49     *
    50     *  Generic Timer is an optional extension to an ARM v7A or v7R processor
    51     *  implementation. Generic Timer provides a system counter that measures
    52     *  the passing of time in real-time. This system counter is in a always-on
    53     *  power domain. The system counter is guaranteed to be atleast 56-bits
    54     *  wide. The timer increments at a frequency typically in the range 1-50MHz.
    55     *  On OMAP5, the Generic Timers increment at a frequency of 6.144 MHz.
    56     *  This timer is guaranteed to have a roll-over time of no less than 
    57     *  40 years.
    58     *
    59     *  This module supports non-secure PL1 physical counter and virtual counter
    60     *  operating as 64-bit upcounters. The timer triggers when the appropriate
    61     *  counter reaches the programmed threshold value.
    62     *      Timer Triggered = ((Counter[63:0] - Threshold[63:0]) >= 0)
    63     *
    64     *  For more information please refer the Generic Timer section on pg. B8-1929
    65     *  of ARM Architecture TRM for v7-AR.
    66     *
    67     *  @p(html)
    68     *  <h3> Calling Context </h3>
    69     *  <table border="1" cellpadding="3">
    70     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
    71     *
    72     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    73     *    <!--                                                                                                                 -->
    74     *    <tr><td> {@link #getNumTimers}            </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    75     *    <tr><td> {@link #getStatus}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    76     *    <tr><td> {@link #Params_init}             </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    77     *    <tr><td> {@link #construct}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    78     *    <tr><td> {@link #create}                  </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    79     *    <tr><td> {@link #delete}                  </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    80     *    <tr><td> {@link #destruct}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    81     *    <tr><td> {@link #getCount}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    82     *    <tr><td> {@link #getCount64}              </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    83     *    <tr><td> {@link #getFreq}                 </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    84     *    <tr><td> {@link #getPeriod}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    85     *    <tr><td> {@link #getPeriod64}             </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    86     *    <tr><td> {@link #reconfig}                </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    87     *    <tr><td> {@link #setPeriod}               </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    88     *    <tr><td> {@link #setPeriod64}             </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    89     *    <tr><td> {@link #setPeriodMicroSecs}      </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    90     *    <tr><td> {@link #setPeriodMicroSecs64}    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    91     *    <tr><td> {@link #start}                   </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    92     *    <tr><td> {@link #stop}                    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
    93     *    <tr><td colspan="6"> Definitions: <br />
    94     *       <ul>
    95     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
    96     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
    97     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
    98     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
    99     *           <ul>
   100     *             <li> In your module startup after this module is started (e.g. Timer_Module_startupDone() returns TRUE). </li>
   101     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   102     *             <li> During main().</li>
   103     *             <li> During BIOS.startupFxns.</li>
   104     *           </ul>
   105     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   106     *           <ul>
   107     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   108     *             <li> In your module startup before this module is started (e.g. Timer_Module_startupDone() returns FALSE).</li>
   109     *           </ul>
   110     *       </ul>
   111     *    </td></tr>
   112     *
   113     *  </table>
   114     *  @p
   115     *
   116     */
   117    @InstanceFinalize       /* To cleanup */
   118    @InstanceInitError      /* To report unavailability of timer */
   119    @ModuleStartup          /* to configure static timers */
   120    
   121    module Timer inherits ti.sysbios.interfaces.ITimer
   122    {
   123        /*! 
   124         *  Max value of Timer period for PeriodType_COUNTS
   125         *
   126         *  The architecture guarantees the system counter is atleast
   127         *  56-bits wide. Therefore, this module limits the maximum
   128         *  count to the largest 56 bit number.
   129         */
   130        const UInt64 MAX_PERIOD = 0x00FFFFFFFFFFFFFF;
   131    
   132        /*! Number of timer peripherals on chip */
   133        const Int NUM_TIMER_DEVICES = 2;
   134    
   135        /*! override supportsDynamic - this Timer does support RunMode_DYNAMIC */
   136        override metaonly config Bool supportsDynamic = true;
   137    
   138        /*! @_nodoc */
   139        @XmlDtd
   140        metaonly struct BasicView {
   141            Ptr         halTimerHandle;
   142            String      label;
   143            UInt        id;
   144            String      startMode;
   145            String      runMode;
   146            String      period;
   147            String      periodType;
   148            UInt        intNum;
   149            String      tickFxn[];
   150            UArg        arg;  
   151            String      extFreq;
   152            String      hwiHandle;
   153            String      prevThreshold;
   154            String      nextThreshold;
   155        };
   156    
   157        /*! @_nodoc */
   158        metaonly struct ModuleView {
   159            String      availMask;      /* available 32-bit timer halves */
   160        }
   161    
   162        /*! @_nodoc */
   163        @Facet
   164        metaonly config ViewInfo.Instance rovViewInfo = 
   165            ViewInfo.create({
   166                viewMap: [
   167                [
   168                    'Basic',
   169                    {
   170                        type: ViewInfo.INSTANCE,
   171                        viewInitFxn: 'viewInitBasic',
   172                        structName: 'BasicView'
   173                    }
   174                ],
   175                [
   176                    'Module',
   177                    {
   178                        type: ViewInfo.MODULE,
   179                        viewInitFxn: 'viewInitModule',
   180                        structName: 'ModuleView'
   181                    }
   182                ],
   183                ]
   184            });
   185    
   186        /*! 
   187         *  Error raised when timer id specified is not supported.
   188         */
   189        config Error.Id E_invalidTimer  = 
   190            {msg: "E_invalidTimer: Invalid Timer Id %d"}; 
   191    
   192        /*! 
   193         *  Error raised when timer requested is in use
   194         */
   195        config Error.Id E_notAvailable  = 
   196            {msg: "E_notAvailable: Timer not available %d"}; 
   197    
   198        /*! 
   199         *  Error raised when Hwi Params has mask where self is turned on.
   200         *  
   201         *  This is not allowed because the timers on this platform do not 
   202         *  support one-shot mode and a stub is used to stop it.
   203         *  Another timer interrupt cannot go off when the ISR is running.
   204         */
   205        config Error.Id E_invalidHwiMask  = 
   206            {msg: "E_InvalidMask: Mask in hwiParams cannot enable self"}; 
   207    
   208        /*! 
   209         *  Error raised when period requested is not supported
   210         */
   211        config Error.Id E_cannotSupport  = 
   212            {msg: "E_cannotSupport: Timer cannot support requested period %d"}; 
   213    
   214        /*!
   215         *  ======== intNumDef ========
   216         *  A15 Generic Timer interrupt numbers
   217         * 
   218         *  Generic Timer Interrupts are forwarded to GIC's private peripheral 
   219         *  interrupts and have a architecture defined fixed mapping that should
   220         *  be same across all A15 variants.
   221         *
   222         *  Non-secure physical timer -> PPI2 or Interrupt #30
   223         *  Virtual timer             -> PPI4 or Interrupt #27
   224         */
   225        config UInt intNumDef[2];
   226    
   227        /*!
   228         *  ======== anyMask ========
   229         *  Available mask to be used when select = Timer_ANY
   230         */
   231        config UInt anyMask = 0x3;
   232    
   233        /*!
   234         *  ======== availMask ========
   235         *  Available mask tracks the available/free timer peripherals
   236         */
   237        config UInt availMask = 0x3;
   238    
   239        /*!
   240         *  ======== intFreq ========
   241         *  Default internal timer input clock frequency.
   242         */
   243        config Types.FreqHz intFreq = {lo: 6144000, hi: 0};
   244    
   245        /*!
   246         *  ======== oneShotStub ========
   247         *  @_nodoc
   248         *  This stub stops timer and disables its interrupt.
   249         *
   250         *  @param(arg)     Timer Handle.
   251         */
   252        @DirectCall
   253        Void oneShotStub(UArg arg);
   254    
   255        /*!
   256         *  ======== periodicStub ========
   257         *  @_nodoc
   258         *  Cortex-A15 Generic timer does not support periodic mode. This
   259         *  function re-loads the timer with the desired period.
   260         *
   261         *  @param(arg)     Timer Handle.
   262         */
   263        @DirectCall
   264        Void periodicStub(UArg arg);
   265    
   266        /*!
   267         *  ======== getHandle ========
   268         *  @_nodoc
   269         *  Used by TimestampProvider module to get hold of timer handle used by 
   270         *  Clock.
   271         *
   272         *  @param(id)      timer Id.
   273         */
   274        @DirectCall
   275        Handle getHandle(UInt id);
   276    
   277    instance:
   278    
   279        /*! Hwi Params for Hwi Object. Default is null.*/
   280        config Hwi.Params *hwiParams = null;
   281    
   282        /*!
   283         *  ======== period64 ========
   284         *  Period of a tick
   285         *
   286         *  The period can be specified in timer counts or microseconds and its
   287         *  default value is 0.
   288         *
   289         *  This timer implementation supports a max period of UInt64 timer
   290         *  counts.
   291         */
   292        config UInt64 period64 = 0;
   293    
   294        /*!
   295         *  ======== reconfig ========
   296         *  Used to modify static timer instances at runtime.
   297         *
   298         *  @param(timerParams)     timer Params
   299         *  @param(tickFxn)         functions that runs when timer expires.
   300         */
   301        @DirectCall
   302        Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
   303    
   304        /*!
   305         *  ======== setPeriod64 ========
   306         *  Set timer period specified in timer counts
   307         *
   308         *  Timer_setPeriod64() invokes Timer_stop() prior to setting the period
   309         *  and leaves the timer in the stopped state.
   310         *
   311         *  A15 architecture guarantees a minimum timer counter width of 56 bits.
   312         *  Therefore, the period should be limited to a value no greater than 
   313         *  0xFFFFFFFFFFFFFF.
   314         *
   315         *  To dynamically change the period of a timer you must
   316         *  protect against re-entrancy by disabling interrupts.
   317         *  Use the following call sequence to guarantee proper results:
   318         *
   319         *  @p(code)
   320         *  // disable interrupts if an interrupt could lead to
   321         *  // another call to Timer_start().
   322         *  key = Hwi_disable();
   323         *  Timer_setPeriod64(period);
   324         *  Timer_start();
   325         *  Hwi_restore(key);
   326         *  @p
   327         *
   328         *
   329         *  @a(side effects)
   330         *  Calls Timer_stop(), and disables the timer's interrupt.
   331         *
   332         *  @param(period)          64 bit period in timer counts
   333         */
   334         @DirectCall
   335         Void setPeriod64(UInt64 period);
   336    
   337        /*! 
   338         *  ======== setPeriodMicroSecs64 ========
   339         *  Set timer period specified in microseconds.
   340         *
   341         *  A best-effort method will be used to set the period register. 
   342         *  There might be a slight rounding error based on resolution of timer 
   343         *  period register. If the timer frequency cannot support the requested 
   344         *  period, i.e. the timer period register cannot support the requested 
   345         *  period, then this function returns false.
   346         *
   347         *  Timer_setPeriodMicroSecs() invokes Timer_stop() prior to setting 
   348         *  the period and leaves the timer in the stopped state. 
   349         *
   350         *  To dynamically change the period of a timer you must
   351         *  protect against re-entrancy by disabling interrupts.
   352         *  Use the following call sequence to guarantee proper results:
   353         *
   354         *  @p(code)
   355         *  // disable interrupts if an interrupt could lead to
   356         *  // another call to Timer_start().
   357         *  key = Hwi_disable();
   358         *  Timer_setPeriodMicroSecs(period);
   359         *  Timer_start();
   360         *  Hwi_restore(key);
   361         *  @p
   362         *
   363         *  @param(period)          period in microseconds
   364         */
   365        @DirectCall
   366        Bool setPeriodMicroSecs64(UInt64 microsecs);
   367    
   368        /*! 
   369         *  ======== getPeriod64 ========
   370         *  Get timer period in timer counts
   371         *
   372         *  @b(returns)     64 bit period in timer counts
   373         */
   374        @DirectCall
   375        UInt64 getPeriod64();
   376    
   377        /*!
   378         *  ======== getCount64 ========
   379         *  Read timer counter register
   380         *  
   381         *  @b(returns)     64 bit timer counter value
   382         */
   383        @DirectCall
   384        UInt64 getCount64();
   385    
   386    
   387    internal:   /* not for client use */
   388       
   389        /*!
   390         *  ======== startupNeeded ========
   391         *  Flag used to prevent misc code from being brought in
   392         *  un-necessarily
   393         */
   394        config UInt startupNeeded = false;
   395    
   396        /*
   397         *  ======== initDevice ========
   398         *  reset timer to its resting state
   399         */
   400        Void initDevice(Object *timer);
   401    
   402        /*
   403         *  ======== postInit ========
   404         *  finish initializing static and dynamic Timers
   405         */
   406        Int postInit(Object *timer, Error.Block *eb);
   407    
   408        /*
   409         *  ======== checkOverflow ========
   410         */
   411        Bool checkOverflow(UInt64 a, UInt64 b);
   412    
   413        /*!
   414         *  ======== readPhyCtrl ========
   415         *  @_nodoc
   416         *  Return PL1 Physical Timer Control register contents
   417         */
   418        UInt32 readPhyCtrl();
   419    
   420        /*!
   421         *  ======== readPhyCnt ========
   422         *  @_nodoc
   423         *  Return PL1 Physical Timer Count
   424         */
   425        Void readPhyCnt(UInt64 *timerCount);
   426    
   427        /*!
   428         *  ======== writePhyCtrl ========
   429         *  @_nodoc
   430         *  Write argument to PL1 Physical Timer Control register
   431         */
   432        Void writePhyCtrl(UInt32 arg0);
   433    
   434        /*!
   435         *  ======== writePhyCmpVal ========
   436         *  @_nodoc
   437         *  Write argument to PL1 Physical Timer CompareValue register
   438         */
   439        Void writePhyCmpVal(UInt64 *compareVal);
   440    
   441        /*!
   442         *  ======== readVirtCtrl ========
   443         *  @_nodoc
   444         *  Return Virtual Timer Control register contents
   445         */
   446        UInt32 readVirtCtrl();
   447    
   448        /*!
   449         *  ======== readVirtCnt ========
   450         *  @_nodoc
   451         *  Return Virtual Timer Count
   452         */
   453        Void readVirtCnt(UInt64 *timerCount);
   454    
   455        /*!
   456         *  ======== writeVirtCtrl ========
   457         *  @_nodoc
   458         *  Write argument to Virtual Timer Control register
   459         */
   460        Void writeVirtCtrl(UInt32 arg0);
   461    
   462        /*!
   463         *  ======== writeVirtCmpVal ========
   464         *  @_nodoc
   465         *  Write argument to Virtual Timer CompareValue register
   466         */
   467        Void writeVirtCmpVal(UInt64 *compareVal);
   468    
   469        struct Instance_State {
   470            Bool                staticInst;
   471            Int                 id;            
   472            ITimer.RunMode      runMode;    
   473            ITimer.StartMode    startMode;
   474            UInt64              period;     
   475            ITimer.PeriodType   periodType;    
   476            UInt                intNum;
   477            UArg                arg;  
   478            Hwi.FuncPtr         tickFxn;
   479            Types.FreqHz        extFreq;
   480            Hwi.Handle          hwi;
   481            UInt64              prevThreshold;
   482            UInt64              nextThreshold;
   483        }
   484    
   485        struct Module_State {
   486            UInt                availMask;  /* available peripherals */
   487            Handle              handles[];  /* array of handles based on id */
   488        }
   489    }