1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34
35
36 package ti.sysbios.family.arm.v8a;
37
38 import xdc.rov.ViewInfo;
39
40 import xdc.runtime.Error;
41 import xdc.runtime.Types;
42
43 import ti.sysbios.family.arm.gicv3.Hwi;
44 import ti.sysbios.interfaces.ITimer;
45
46 /*!
47 * ======== Timer ========
48 * Generic Timer Peripheral Manager for Arm v8A family prcoessors
49 *
50 * Generic Timer is an optional extension to an ARM v8A 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 of ARM
65 * Architecture TRM for v8-A.
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
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;
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 * A53 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 ARMv8A device 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 * ARMv8A 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 295 296 297 298 299
300 config Bool vlabErrata = false;
301
302 instance:
303
304 /*! Hwi Params for Hwi Object. Default is null.*/
305 config Hwi.Params *hwiParams = null;
306
307 /*!
308 * ======== period64 ========
309 * Period of a tick
310 *
311 * The period can be specified in timer counts or microseconds and its
312 * default value is 0.
313 *
314 * This timer implementation supports a max period of UInt64 timer
315 * counts.
316 */
317 config UInt64 period64 = 0;
318
319 /*!
320 * ======== reconfig ========
321 * Used to modify static timer instances at runtime.
322 *
323 * @param(timerParams) timer Params
324 * @param(tickFxn) functions that runs when timer expires.
325 */
326 Void reconfig(FuncPtr tickFxn, const Params *timerParams, Error.Block *eb);
327
328 /*!
329 * ======== setPeriod64 ========
330 * Set timer period specified in timer counts
331 *
332 * Timer_setPeriod64() invokes Timer_stop() prior to setting the period
333 * and leaves the timer in the stopped state.
334 *
335 * A15 architecture guarantees a minimum timer counter width of 56 bits.
336 * Therefore, the period should be limited to a value no greater than
337 * 0xFFFFFFFFFFFFFF.
338 *
339 * To dynamically change the period of a timer you must
340 * protect against re-entrancy by disabling interrupts.
341 * Use the following call sequence to guarantee proper results:
342 *
343 * @p(code)
344 * // disable interrupts if an interrupt could lead to
345 * // another call to Timer_start().
346 * key = Hwi_disable();
347 * Timer_setPeriod64(period);
348 * Timer_start();
349 * Hwi_restore(key);
350 * @p
351 *
352 *
353 * @a(side effects)
354 * Calls Timer_stop(), and disables the timer's interrupt.
355 *
356 * @param(period) 64 bit period in timer counts
357 */
358 Void setPeriod64(UInt64 period);
359
360 /*!
361 * ======== setPeriodMicroSecs64 ========
362 * Set timer period specified in microseconds.
363 *
364 * A best-effort method will be used to set the period register.
365 * There might be a slight rounding error based on resolution of timer
366 * period register. If the timer frequency cannot support the requested
367 * period, i.e. the timer period register cannot support the requested
368 * period, then this function returns false.
369 *
370 * Timer_setPeriodMicroSecs() invokes Timer_stop() prior to setting
371 * the period and leaves the timer in the stopped state.
372 *
373 * To dynamically change the period of a timer you must
374 * protect against re-entrancy by disabling interrupts.
375 * Use the following call sequence to guarantee proper results:
376 *
377 * @p(code)
378 * // disable interrupts if an interrupt could lead to
379 * // another call to Timer_start().
380 * key = Hwi_disable();
381 * Timer_setPeriodMicroSecs(period);
382 * Timer_start();
383 * Hwi_restore(key);
384 * @p
385 *
386 * @param(period) period in microseconds
387 */
388 Bool setPeriodMicroSecs64(UInt64 microsecs);
389
390 /*!
391 * ======== getPeriod64 ========
392 * Get timer period in timer counts
393 *
394 * @b(returns) 64 bit period in timer counts
395 */
396 UInt64 getPeriod64();
397
398 /*!
399 * ======== getCount64 ========
400 * Read timer counter register
401 *
402 * @b(returns) 64 bit timer counter value
403 */
404 UInt64 getCount64();
405
406 internal:
407
408 /*!
409 * ======== startupNeeded ========
410 * Flag used to prevent misc code from being brought in
411 * un-necessarily
412 */
413 config UInt startupNeeded = false;
414
415 416 417 418
419 Void initDevice(Object *timer);
420
421 422 423 424
425 Int postInit(Object *timer, Error.Block *eb);
426
427 428 429
430 Bool checkOverflow(UInt64 a, UInt64 b);
431
432 /*!
433 * ======== readPhyCtrl ========
434 * @_nodoc
435 * Return PL1 Physical Timer Control register contents
436 */
437 UInt32 readPhyCtrl();
438
439 /*!
440 * ======== readPhyCnt ========
441 * @_nodoc
442 * Return PL1 Physical Timer Count
443 */
444 Void readPhyCnt(UInt64 *timerCount);
445
446 /*!
447 * ======== writePhyCtrl ========
448 * @_nodoc
449 * Write argument to PL1 Physical Timer Control register
450 */
451 Void writePhyCtrl(UInt32 arg0);
452
453 /*!
454 * ======== writePhyCmpVal ========
455 * @_nodoc
456 * Write argument to PL1 Physical Timer CompareValue register
457 */
458 Void writePhyCmpVal(UInt64 *compareVal);
459
460 /*!
461 * ======== readVirtCtrl ========
462 * @_nodoc
463 * Return Virtual Timer Control register contents
464 */
465 UInt32 readVirtCtrl();
466
467 /*!
468 * ======== readVirtCnt ========
469 * @_nodoc
470 * Return Virtual Timer Count
471 */
472 Void readVirtCnt(UInt64 *timerCount);
473
474 /*!
475 * ======== tickReconfigSmp ========
476 */
477 Void tickReconfigSmp(UArg arg);
478
479 /*!
480 * ======== writeVirtCtrl ========
481 * @_nodoc
482 * Write argument to Virtual Timer Control register
483 */
484 Void writeVirtCtrl(UInt32 arg0);
485
486 /*!
487 * ======== writeVirtCmpVal ========
488 * @_nodoc
489 * Write argument to Virtual Timer CompareValue register
490 */
491 Void writeVirtCmpVal(UInt64 *compareVal);
492
493 struct Instance_State {
494 Bool staticInst;
495 Int id;
496 ITimer.RunMode runMode;
497 ITimer.StartMode startMode;
498 UInt64 period;
499 ITimer.PeriodType periodType;
500 UInt intNum;
501 UArg arg;
502 Hwi.FuncPtr tickFxn;
503 Types.FreqHz extFreq;
504 Hwi.Handle hwi;
505 UInt64 prevThreshold;
506 UInt64 nextThreshold;
507 UInt64 savedCurrCount;
508 }
509
510 struct Module_State {
511 UInt availMask;
512 Handle handles[];
513 }
514 }