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.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
118 @InstanceInitError
119 @ModuleStartup
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;
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:
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 398 399
400 Void initDevice(Object *timer);
401
402 403 404 405
406 Int postInit(Object *timer, Error.Block *eb);
407
408 409 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;
487 Handle handles[];
488 }
489 }