1 /* 2 * Copyright (c) 2014 Travis Geiselbrecht 3 * 4 * Use of this source code is governed by a MIT-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/MIT 7 */ 8 #include <lk/debug.h> 9 #include <sys/types.h> 10 #include <lk/err.h> 11 #include <stdio.h> 12 #include <assert.h> 13 #include <lk/trace.h> 14 #include <kernel/thread.h> 15 #include <platform.h> 16 #include <platform/interrupts.h> 17 #include <platform/timer.h> 18 #include <platform/zynq.h> 19 #include "platform_p.h" 20 21 /* unused, arm_cortex_a9_timer does timer duty */ 22 23 #if 0 24 /* driver for Cadence triple timer counter (TTC) */ 25 26 #define LOCAL_TRACE 0 27 28 #define TIMREG(reg) (*REG32(TTC0_BASE + (reg))) 29 #define TIMREG16(reg) (*REG16(TTC0_BASE + (reg))) 30 #define TIMREG8(reg) (*REG8(TTC0_BASE + (reg))) 31 32 #define CLK_CTRL(n) (0x00 + (n) * 4) 33 #define CNT_CTRL(n) (0x0c + (n) * 4) 34 #define CNT_VAL(n) (0x18 + (n) * 4) 35 #define INTERVAL_VAL(n) (0x24 + (n) * 4) 36 #define MATCH_1(n) (0x30 + (n) * 4) 37 #define MATCH_2(n) (0x3c + (n) * 4) 38 #define MATCH_3(n) (0x48 + (n) * 4) 39 #define ISR(n) (0x54 + (n) * 4) 40 #define IEN(n) (0x60 + (n) * 4) 41 #define EVT_CTRL(n) (0x6c + (n) * 4) 42 #define EVT(n) (0x78 + (n) * 4) 43 44 static platform_timer_callback t_callback; 45 46 static volatile uint ticks = 0; 47 static lk_time_t periodic_interval; 48 49 status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval) { 50 enter_critical_section(); 51 52 LTRACEF("callback %p, arg %p, interval %lu\n", callback, arg, interval); 53 54 t_callback = callback; 55 56 periodic_interval = interval; 57 58 uint32_t ticks = periodic_interval * 1000; /* timer is running close to 1Mhz */ 59 ASSERT(ticks <= 0xffff); 60 61 TIMREG(IEN(0)) = (1<<0); // interval interrupt 62 TIMREG(INTERVAL_VAL(0)) = ticks; 63 TIMREG(CNT_CTRL(0)) = (1<<5) | (1<<4) | (1<<1); // no wave, reset, interval mode 64 65 unmask_interrupt(TTC0_A_INT); 66 67 exit_critical_section(); 68 69 return NO_ERROR; 70 } 71 72 lk_bigtime_t current_time_hires(void) { 73 lk_bigtime_t time; 74 75 time = ticks * periodic_interval * 1000ULL; 76 77 return time; 78 } 79 80 lk_time_t current_time(void) { 81 lk_time_t time; 82 83 time = ticks * periodic_interval; 84 85 return time; 86 } 87 88 static enum handler_return platform_tick(void *arg) { 89 ticks++; 90 91 volatile uint32_t hole = TIMREG(ISR(0)); // ack the irq 92 93 if (t_callback) { 94 return t_callback(arg, current_time()); 95 } else { 96 return INT_NO_RESCHEDULE; 97 } 98 } 99 100 void platform_init_timer(void) { 101 /* disable timers */ 102 TIMREG(CNT_CTRL(0)) = 0x1; 103 TIMREG(CNT_CTRL(1)) = 0x1; 104 TIMREG(CNT_CTRL(2)) = 0x1; 105 106 TIMREG(CLK_CTRL(0)) = (6 << 1) | 1; // prescale 133Mhz/(2^7) == 1039062Hz (close to 1Mhz) 107 108 register_int_handler(TTC0_A_INT, &platform_tick, NULL); 109 register_int_handler(TTC0_B_INT, &platform_tick, NULL); 110 register_int_handler(TTC0_C_INT, &platform_tick, NULL); 111 } 112 #endif 113