|
35 | 35 | * \todo RTC support should be improved if RTC is enabled |
36 | 36 | */ |
37 | 37 | #include "arc_timer.h" |
| 38 | +#include "arc_exception.h" |
| 39 | + |
| 40 | +#define LPS_PREC 8 |
| 41 | + |
| 42 | +volatile uint64_t gl_loops_per_jiffy = 1; |
| 43 | +volatile uint32_t gl_count = 1; |
| 44 | + |
| 45 | + |
| 46 | + |
38 | 47 |
|
39 | 48 |
|
40 | 49 | /** |
@@ -363,3 +372,86 @@ void secure_timer_init(void) |
363 | 372 | } |
364 | 373 | #endif /* ARC_FEATURE_SEC_TIMER1_PRESENT && ARC_FEATURE_SEC_TIMER0_PRESENT */ |
365 | 374 |
|
| 375 | +/** |
| 376 | + * \brief provide US delay function |
| 377 | + * |
| 378 | + * \param[in] usecs US to delay |
| 379 | + */ |
| 380 | +void arc_delay_us(uint32_t usecs) |
| 381 | +{ |
| 382 | + __asm__ __volatile__( |
| 383 | + |
| 384 | + " .extern gl_loops_per_jiffy \n" |
| 385 | + " .extern gl_count \n" |
| 386 | + " cmp %0, 0 \n" |
| 387 | + " jeq 1f \n" |
| 388 | + " ld %%r1, [gl_loops_per_jiffy] \n" |
| 389 | + " mpy %%r1, %%r1, %0 \n" |
| 390 | + " ld %%r2, [gl_count] \n" |
| 391 | + " divu %%r1, %%r1, %%r2 \n" |
| 392 | + " .align 4 \n" |
| 393 | + " mov %%lp_count, %%r1 \n" |
| 394 | + " lp 1f \n" |
| 395 | + " nop \n" |
| 396 | + "1: \n" |
| 397 | + : |
| 398 | + : "r"(usecs) |
| 399 | + : "lp_count", "r1", "r2"); |
| 400 | +} |
| 401 | + |
| 402 | +/** |
| 403 | + * \brief calibrate delay |
| 404 | + * |
| 405 | + * \param[in] board cpu clock |
| 406 | + * \return loops_per_jiffy |
| 407 | + */ |
| 408 | +uint64_t timer_calibrate_delay(uint32_t cpu_clock) |
| 409 | +{ |
| 410 | + unsigned long loopbit; |
| 411 | + int lps_precision = LPS_PREC; |
| 412 | + volatile uint64_t loops_per_jiffy; |
| 413 | + uint32_t timer0_limit; |
| 414 | + uint32_t status; |
| 415 | + |
| 416 | + gl_loops_per_jiffy = 1; |
| 417 | + gl_count = 1; |
| 418 | + |
| 419 | + cpu_clock /= 1000; |
| 420 | + |
| 421 | + status = cpu_lock_save(); |
| 422 | + |
| 423 | + timer0_limit = _arc_aux_read(AUX_TIMER0_LIMIT); |
| 424 | + _arc_aux_write(AUX_TIMER0_LIMIT, 0xFFFFFFFF); |
| 425 | + |
| 426 | + loops_per_jiffy = (1 << 4); |
| 427 | + while ((loops_per_jiffy <<= 1) != 0) { |
| 428 | + |
| 429 | + _arc_aux_write(AUX_TIMER0_CNT, 0); |
| 430 | + arc_delay_us(loops_per_jiffy); |
| 431 | + if (_arc_aux_read(AUX_TIMER0_CNT) > cpu_clock) { |
| 432 | + break; |
| 433 | + } |
| 434 | + } |
| 435 | + |
| 436 | + loops_per_jiffy >>= 1; |
| 437 | + loopbit = loops_per_jiffy; |
| 438 | + while (lps_precision-- && (loopbit >>= 1)) { |
| 439 | + |
| 440 | + loops_per_jiffy |= loopbit; |
| 441 | + _arc_aux_write(AUX_TIMER0_CNT, 0); |
| 442 | + arc_delay_us(loops_per_jiffy); |
| 443 | + if (_arc_aux_read(AUX_TIMER0_CNT) > cpu_clock) { |
| 444 | + loops_per_jiffy &= ~loopbit; |
| 445 | + } |
| 446 | + } |
| 447 | + |
| 448 | + gl_loops_per_jiffy = loops_per_jiffy; |
| 449 | + gl_count = 1000; |
| 450 | + |
| 451 | + _arc_aux_write(AUX_TIMER0_CNT, 0); |
| 452 | + _arc_aux_write(AUX_TIMER0_LIMIT, timer0_limit); |
| 453 | + cpu_unlock_restore(status); |
| 454 | + |
| 455 | + return loops_per_jiffy; |
| 456 | +} |
| 457 | + |
0 commit comments