2 * QEMU OpenRISC timer support
4 * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5 * Zhizhou Zhang <etouzh@gmail.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 #include "qemu/timer.h"
25 #define TIMER_FREQ (20 * 1000 * 1000) /* 20MHz */
27 /* The time when TTCR changes */
28 static uint64_t last_clk
;
29 static int is_counting
;
31 void cpu_openrisc_count_update(OpenRISCCPU
*cpu
)
36 now
= qemu_get_clock_ns(vm_clock
);
38 qemu_del_timer(cpu
->env
.timer
);
43 cpu
->env
.ttcr
+= (uint32_t)muldiv64(now
- last_clk
, TIMER_FREQ
,
47 if ((cpu
->env
.ttmr
& TTMR_TP
) <= (cpu
->env
.ttcr
& TTMR_TP
)) {
48 wait
= TTMR_TP
- (cpu
->env
.ttcr
& TTMR_TP
) + 1;
49 wait
+= cpu
->env
.ttmr
& TTMR_TP
;
51 wait
= (cpu
->env
.ttmr
& TTMR_TP
) - (cpu
->env
.ttcr
& TTMR_TP
);
54 next
= now
+ muldiv64(wait
, get_ticks_per_sec(), TIMER_FREQ
);
55 qemu_mod_timer(cpu
->env
.timer
, next
);
58 void cpu_openrisc_count_start(OpenRISCCPU
*cpu
)
61 cpu_openrisc_count_update(cpu
);
64 void cpu_openrisc_count_stop(OpenRISCCPU
*cpu
)
67 cpu_openrisc_count_update(cpu
);
70 static void openrisc_timer_cb(void *opaque
)
72 OpenRISCCPU
*cpu
= opaque
;
74 if ((cpu
->env
.ttmr
& TTMR_IE
) &&
75 qemu_timer_expired(cpu
->env
.timer
, qemu_get_clock_ns(vm_clock
))) {
76 CPUState
*cs
= CPU(cpu
);
78 cpu
->env
.ttmr
|= TTMR_IP
;
79 cs
->interrupt_request
|= CPU_INTERRUPT_TIMER
;
82 switch (cpu
->env
.ttmr
& TTMR_M
) {
87 cpu_openrisc_count_start(cpu
);
90 cpu_openrisc_count_stop(cpu
);
93 cpu_openrisc_count_start(cpu
);
98 void cpu_openrisc_clock_init(OpenRISCCPU
*cpu
)
100 cpu
->env
.timer
= qemu_new_timer_ns(vm_clock
, &openrisc_timer_cb
, cpu
);
101 cpu
->env
.ttmr
= 0x00000000;
102 cpu
->env
.ttcr
= 0x00000000;