1    /*
     2     * Copyright (c) 2014, 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    @ModuleStartup          /* to configure static timers */
   118    @InstanceInitStatic
   119    
   120    module Timer inherits ti.sysbios.interfaces.ITimer
   121    {
   122        /*! 
   123         *  Max value of Timer period for PeriodType_COUNTS
   124         *
   125         *  The architecture guarantees the system counter is atleast
   126         *  56-bits wide. Therefore, this module limits the maximum
   127         *  count to the largest 56 bit number.
   128         */
   129        const UInt64 MAX_PERIOD = 0x00FFFFFFFFFFFFFF;
   130    
   131        /*! Number of timer peripherals on chip */
   132        const Int NUM_TIMER_DEVICES = 2;
   133    
   134        /*! override supportsDynamic - this Timer does support RunMode_DYNAMIC */
   135        override metaonly config Bool supportsDynamic = true;
   136    
   137        /*! @_nodoc */
   138        @XmlDtd
   139        metaonly struct BasicView {
   140            Ptr         halTimerHandle;
   141            String      label;
   142            UInt        id;
   143            String      startMode;
   144            String      runMode;
   145            String      period;
   146            String      periodType;
   147            UInt        intNum;
   148            String      tickFxn[];
   149            UArg        arg;  
   150            String      extFreq;
   151            String      hwiHandle;
   152            String      prevThreshold;
   153            String      nextThreshold;
   154        };
   155    
   156        /*! @_nodoc */
   157        metaonly struct ModuleView {
   158            String      availMask;      /* available 32-bit timer halves */
   159        }
   160    
   161        /*! @_nodoc */
   162        @Facet
   163        metaonly config ViewInfo.Instance rovViewInfo = 
   164            ViewInfo.create({
   165                viewMap: [
   166                [
   167                    'Basic',
   168                    {
   169                        type: ViewInfo.INSTANCE,
   170                        viewInitFxn: 'viewInitBasic',
   171                        structName: 'BasicView'
   172                    }
   173                ],
   174                [
   175                    'Module',
   176                    {
   177                        type: ViewInfo.MODULE,
   178                        viewInitFxn: 'viewInitModule',
   179                        structName: 'ModuleView'
   180                    }
   181                ],
   182                ]
   183            });
   184    
   185        /*! 
   186         *  Error raised when timer id specified is not supported.
   187         */
   188        config Error.Id E_invalidTimer  = 
   189            {msg: "E_invalidTimer: Invalid Timer Id %d"}; 
   190    
   191        /*! 
   192         *  Error raised when timer requested is in use
   193         */
   194        config Error.Id E_notAvailable  = 
   195            {msg: "E_notAvailable: Timer not available %d"}; 
   196    
   197        /*! 
   198         *  Error raised when Hwi Params has mask where self is turned on.
   199         *  
   200         *  This is not allowed because the timers on this platform do not 
   201         *  support one-shot mode and a stub is used to stop it.
   202         *  Another timer interrupt cannot go off when the ISR is running.
   203         */
   204        config Error.Id E_invalidHwiMask  = 
   205            {msg: "E_InvalidMask: Mask in hwiParams cannot enable self"}; 
   206    
   207        /*! 
   208         *  Error raised when period requested is not supported
   209         */
   210        config Error.Id E_cannotSupport  = 
   211            {msg: "E_cannotSupport: Timer cannot support requested period %d"}; 
   212    
   213        /*!
   214         *  ======== intNumDef ========
   215         *  A15 Generic Timer interrupt numbers
   216         * 
   217         *  Generic Timer Interrupts are forwarded to GIC's private peripheral 
   218         *  interrupts and have a architecture defined fixed mapping that should
   219         *  be same across all A15 variants.
   220         *
   221         *  Non-secure physical timer -> PPI2 or Interrupt #30
   222         *  Virtual timer             -> PPI4 or Interrupt #27
   223         */
   224        config UInt intNumDef[2];
   225    
   226        /*!
   227         *  ======== anyMask ========
   228         *  Available mask to be used when select = Timer_ANY
   229         */
   230        config UInt anyMask = 0x3;
   231    
   232        /*!
   233         *  ======== availMask ========
   234         *  Available mask tracks the available/free timer peripherals
   235         */
   236        config UInt availMask = 0x3;
   237    
   238        /*!
   239         *  ======== intFreq ========
   240         *  Default internal timer input clock frequency.
   241         *
   242         *  @a(NOTE)
   243         *  On OMAP5x, DRA7x and ADAS devices, the Generic Timer
   244         *  operates at a fixed frequency of 6144000 Hz.
   245         *
   246         *  On Keystone 2 devices, the Genric Timer operates at
   247         *  Main PLL frequency /6. The default internal timer
   248         *  input frequency for Keystone 2 devices is 20480000 Hz
   249         *  which is derived from the Main PLL bypass clock fequency
   250         *  of 122.88 MHz. If the Main PLL is initialized to a different
   251         *  frequency then this config param should be updated accordigly.
   252         *
   253         *  For instance, if Main PLL frequency is configured to be 614.4 MHz,
   254         *  the Timer operates at 102.4 MHz and Timer.intFreq should be set to
   255         *  this value.
   256         *
   257         *  @p(code)
   258         *  var Timer = xdc.useModule('ti.sysbios.family.arm.systimer.Timer');
   259         *  Timer.intFreq.lo = 102400000; // = (Main PLL freq / 6)
   260         *  Timer.intFreq.hi = 0;
   261         *  @p
   262         */
   263        config Types.FreqHz intFreq;
   264    
   265        /*!
   266         *  ======== oneShotStub ========
   267         *  @_nodoc
   268         *  This stub stops timer and disables its interrupt.
   269         *
   270         *  @param(arg)     Timer Handle.
   271         */
   272        Void oneShotStub(UArg arg);
   273    
   274        /*!
   275         *  ======== periodicStub ========
   276         *  @_nodoc
   277         *  Cortex-A15 Generic timer does not support periodic mode. This
   278         *  function re-loads the timer with the desired period.
   279         *
   280         *  @param(arg)     Timer Handle.
   281         */
   282        Void periodicStub(UArg arg);
   283    
   284        /*!
   285         *  ======== getHandle ========
   286         *  @_nodoc
   287         *  Used by TimestampProvider module to get hold of timer handle used by 
   288         *  Clock.
   289         *
   290         *  @param(id)      timer Id.
   291         */
   292        Handle getHandle(UInt id);
   293    
   294    instance:
   295    
   296        /*! Hwi Params for Hwi Object. Default is null.*/
   297        config Hwi.Params *hwiParams = null;
   298    
   299        /*!
   300         *  ======== period64 ========
   301         *  Period of a tick
   302         *
   303         *  The period can be specified in timer counts or microseconds and its
   304         *  default value is 0.
   305         *
   306         *  This timer implementation supports a max period of UInt64 timer
   307         *  counts.
   308         */
   309        config UInt64 period64 = 0;
   310    
   311        /*!
   312         *  ======== reconfig ========
   313         *  Used to modify static timer instances at runtime.
   314         *
   315         *  @param(timerParams)     timer Params
   316         *  @param(tickFxn)         functions that runs when timer expires.
   317         */
   318        Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
   319    
   320        /*!
   321         *  ======== setPeriod64 ========
   322         *  Set timer period specified in timer counts
   323         *
   324         *  Timer_setPeriod64() invokes Timer_stop() prior to setting the period
   325         *  and leaves the timer in the stopped state.
   326         *
   327         *  A15 architecture guarantees a minimum timer counter width of 56 bits.
   328         *  Therefore, the period should be limited to a value no greater than 
   329         *  0xFFFFFFFFFFFFFF.
   330         *
   331         *  To dynamically change the period of a timer you must
   332         *  protect against re-entrancy by disabling interrupts.
   333         *  Use the following call sequence to guarantee proper results:
   334         *
   335         *  @p(code)
   336         *  // disable interrupts if an interrupt could lead to
   337         *  // another call to Timer_start().
   338         *  key = Hwi_disable();
   339         *  Timer_setPeriod64(period);
   340         *  Timer_start();
   341         *  Hwi_restore(key);
   342         *  @p
   343         *
   344         *
   345         *  @a(side effects)
   346         *  Calls Timer_stop(), and disables the timer's interrupt.
   347         *
   348         *  @param(period)          64 bit period in timer counts
   349         */
   350         Void setPeriod64(UInt64 period);
   351    
   352        /*! 
   353         *  ======== setPeriodMicroSecs64 ========
   354         *  Set timer period specified in microseconds.
   355         *
   356         *  A best-effort method will be used to set the period register. 
   357         *  There might be a slight rounding error based on resolution of timer 
   358         *  period register. If the timer frequency cannot support the requested 
   359         *  period, i.e. the timer period register cannot support the requested 
   360         *  period, then this function returns false.
   361         *
   362         *  Timer_setPeriodMicroSecs() invokes Timer_stop() prior to setting 
   363         *  the period and leaves the timer in the stopped state. 
   364         *
   365         *  To dynamically change the period of a timer you must
   366         *  protect against re-entrancy by disabling interrupts.
   367         *  Use the following call sequence to guarantee proper results:
   368         *
   369         *  @p(code)
   370         *  // disable interrupts if an interrupt could lead to
   371         *  // another call to Timer_start().
   372         *  key = Hwi_disable();
   373         *  Timer_setPeriodMicroSecs(period);
   374         *  Timer_start();
   375         *  Hwi_restore(key);
   376         *  @p
   377         *
   378         *  @param(period)          period in microseconds
   379         */
   380        Bool setPeriodMicroSecs64(UInt64 microsecs);
   381    
   382        /*! 
   383         *  ======== getPeriod64 ========
   384         *  Get timer period in timer counts
   385         *
   386         *  @b(returns)     64 bit period in timer counts
   387         */
   388        UInt64 getPeriod64();
   389    
   390        /*!
   391         *  ======== getCount64 ========
   392         *  Read timer counter register
   393         *  
   394         *  @b(returns)     64 bit timer counter value
   395         */
   396        UInt64 getCount64();
   397    
   398    
   399    internal:   /* not for client use */
   400       
   401        /*!
   402         *  ======== startupNeeded ========
   403         *  Flag used to prevent misc code from being brought in
   404         *  un-necessarily
   405         */
   406        config UInt startupNeeded = false;
   407    
   408        /*
   409         *  ======== initDevice ========
   410         *  reset timer to its resting state
   411         */
   412        Void initDevice(Object *timer);
   413    
   414        /*
   415         *  ======== postInit ========
   416         *  finish initializing static and dynamic Timers
   417         */
   418        Int postInit(Object *timer, Error.Block *eb);
   419    
   420        /*
   421         *  ======== checkOverflow ========
   422         */
   423        Bool checkOverflow(UInt64 a, UInt64 b);
   424    
   425        /*!
   426         *  ======== readPhyCtrl ========
   427         *  @_nodoc
   428         *  Return PL1 Physical Timer Control register contents
   429         */
   430        UInt32 readPhyCtrl();
   431    
   432        /*!
   433         *  ======== readPhyCnt ========
   434         *  @_nodoc
   435         *  Return PL1 Physical Timer Count
   436         */
   437        Void readPhyCnt(UInt64 *timerCount);
   438    
   439        /*!
   440         *  ======== writePhyCtrl ========
   441         *  @_nodoc
   442         *  Write argument to PL1 Physical Timer Control register
   443         */
   444        Void writePhyCtrl(UInt32 arg0);
   445    
   446        /*!
   447         *  ======== writePhyCmpVal ========
   448         *  @_nodoc
   449         *  Write argument to PL1 Physical Timer CompareValue register
   450         */
   451        Void writePhyCmpVal(UInt64 *compareVal);
   452    
   453        /*!
   454         *  ======== readVirtCtrl ========
   455         *  @_nodoc
   456         *  Return Virtual Timer Control register contents
   457         */
   458        UInt32 readVirtCtrl();
   459    
   460        /*!
   461         *  ======== readVirtCnt ========
   462         *  @_nodoc
   463         *  Return Virtual Timer Count
   464         */
   465        Void readVirtCnt(UInt64 *timerCount);
   466    
   467        /*!
   468         *  ======== tickReconfigSmp ========
   469         */
   470        Void tickReconfigSmp(UArg arg);
   471    
   472        /*!
   473         *  ======== writeVirtCtrl ========
   474         *  @_nodoc
   475         *  Write argument to Virtual Timer Control register
   476         */
   477        Void writeVirtCtrl(UInt32 arg0);
   478    
   479        /*!
   480         *  ======== writeVirtCmpVal ========
   481         *  @_nodoc
   482         *  Write argument to Virtual Timer CompareValue register
   483         */
   484        Void writeVirtCmpVal(UInt64 *compareVal);
   485    
   486        struct Instance_State {
   487            Bool                staticInst;
   488            Int                 id;            
   489            ITimer.RunMode      runMode;    
   490            ITimer.StartMode    startMode;
   491            UInt64              period;     
   492            ITimer.PeriodType   periodType;    
   493            UInt                intNum;
   494            UArg                arg;  
   495            Hwi.FuncPtr         tickFxn;
   496            Types.FreqHz        extFreq;
   497            Hwi.Handle          hwi;
   498            UInt64              prevThreshold;
   499            UInt64              nextThreshold;
   500            UInt64              savedCurrCount;
   501        }
   502    
   503        struct Module_State {
   504            UInt                availMask;  /* available peripherals */
   505            Handle              handles[];  /* array of handles based on id */
   506        }
   507    }