root / hw / openrisc_timer.c @ bc927e48
History | View | Annotate | Download (2.8 kB)
1 | 99f575ed | Jia Liu | /*
|
---|---|---|---|
2 | 99f575ed | Jia Liu | * QEMU OpenRISC timer support
|
3 | 99f575ed | Jia Liu | *
|
4 | 99f575ed | Jia Liu | * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
|
5 | 99f575ed | Jia Liu | * Zhizhou Zhang <etouzh@gmail.com>
|
6 | 99f575ed | Jia Liu | *
|
7 | 99f575ed | Jia Liu | * This library is free software; you can redistribute it and/or
|
8 | 99f575ed | Jia Liu | * modify it under the terms of the GNU Lesser General Public
|
9 | 99f575ed | Jia Liu | * License as published by the Free Software Foundation; either
|
10 | 99f575ed | Jia Liu | * version 2 of the License, or (at your option) any later version.
|
11 | 99f575ed | Jia Liu | *
|
12 | 99f575ed | Jia Liu | * This library is distributed in the hope that it will be useful,
|
13 | 99f575ed | Jia Liu | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | 99f575ed | Jia Liu | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 | 99f575ed | Jia Liu | * Lesser General Public License for more details.
|
16 | 99f575ed | Jia Liu | *
|
17 | 99f575ed | Jia Liu | * You should have received a copy of the GNU Lesser General Public
|
18 | 99f575ed | Jia Liu | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
19 | 99f575ed | Jia Liu | */
|
20 | 99f575ed | Jia Liu | |
21 | 99f575ed | Jia Liu | #include "cpu.h" |
22 | 99f575ed | Jia Liu | #include "hw.h" |
23 | 99f575ed | Jia Liu | #include "qemu-timer.h" |
24 | 99f575ed | Jia Liu | |
25 | 99f575ed | Jia Liu | #define TIMER_FREQ (20 * 1000 * 1000) /* 20MHz */ |
26 | 99f575ed | Jia Liu | |
27 | 99f575ed | Jia Liu | /* The time when TTCR changes */
|
28 | 99f575ed | Jia Liu | static uint64_t last_clk;
|
29 | 99f575ed | Jia Liu | static int is_counting; |
30 | 99f575ed | Jia Liu | |
31 | 99f575ed | Jia Liu | void cpu_openrisc_count_update(OpenRISCCPU *cpu)
|
32 | 99f575ed | Jia Liu | { |
33 | 99f575ed | Jia Liu | uint64_t now, next; |
34 | 99f575ed | Jia Liu | uint32_t wait; |
35 | 99f575ed | Jia Liu | |
36 | 99f575ed | Jia Liu | now = qemu_get_clock_ns(vm_clock); |
37 | 99f575ed | Jia Liu | if (!is_counting) {
|
38 | 99f575ed | Jia Liu | qemu_del_timer(cpu->env.timer); |
39 | 99f575ed | Jia Liu | last_clk = now; |
40 | 99f575ed | Jia Liu | return;
|
41 | 99f575ed | Jia Liu | } |
42 | 99f575ed | Jia Liu | |
43 | 99f575ed | Jia Liu | cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ, |
44 | 99f575ed | Jia Liu | get_ticks_per_sec()); |
45 | 99f575ed | Jia Liu | last_clk = now; |
46 | 99f575ed | Jia Liu | |
47 | 99f575ed | Jia Liu | if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
|
48 | 99f575ed | Jia Liu | wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
|
49 | 99f575ed | Jia Liu | wait += cpu->env.ttmr & TTMR_TP; |
50 | 99f575ed | Jia Liu | } else {
|
51 | 99f575ed | Jia Liu | wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP); |
52 | 99f575ed | Jia Liu | } |
53 | 99f575ed | Jia Liu | |
54 | 99f575ed | Jia Liu | next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ); |
55 | 99f575ed | Jia Liu | qemu_mod_timer(cpu->env.timer, next); |
56 | 99f575ed | Jia Liu | } |
57 | 99f575ed | Jia Liu | |
58 | 99f575ed | Jia Liu | void cpu_openrisc_count_start(OpenRISCCPU *cpu)
|
59 | 99f575ed | Jia Liu | { |
60 | 99f575ed | Jia Liu | is_counting = 1;
|
61 | 99f575ed | Jia Liu | cpu_openrisc_count_update(cpu); |
62 | 99f575ed | Jia Liu | } |
63 | 99f575ed | Jia Liu | |
64 | 99f575ed | Jia Liu | void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
|
65 | 99f575ed | Jia Liu | { |
66 | 99f575ed | Jia Liu | is_counting = 0;
|
67 | 99f575ed | Jia Liu | cpu_openrisc_count_update(cpu); |
68 | 99f575ed | Jia Liu | } |
69 | 99f575ed | Jia Liu | |
70 | 99f575ed | Jia Liu | static void openrisc_timer_cb(void *opaque) |
71 | 99f575ed | Jia Liu | { |
72 | 99f575ed | Jia Liu | OpenRISCCPU *cpu = opaque; |
73 | 99f575ed | Jia Liu | |
74 | 99f575ed | Jia Liu | if ((cpu->env.ttmr & TTMR_IE) &&
|
75 | 99f575ed | Jia Liu | qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) { |
76 | 99f575ed | Jia Liu | cpu->env.ttmr |= TTMR_IP; |
77 | 99f575ed | Jia Liu | cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER; |
78 | 99f575ed | Jia Liu | } |
79 | 99f575ed | Jia Liu | |
80 | 99f575ed | Jia Liu | switch (cpu->env.ttmr & TTMR_M) {
|
81 | 99f575ed | Jia Liu | case TIMER_NONE:
|
82 | 99f575ed | Jia Liu | break;
|
83 | 99f575ed | Jia Liu | case TIMER_INTR:
|
84 | 99f575ed | Jia Liu | cpu->env.ttcr = 0;
|
85 | 99f575ed | Jia Liu | cpu_openrisc_count_start(cpu); |
86 | 99f575ed | Jia Liu | break;
|
87 | 99f575ed | Jia Liu | case TIMER_SHOT:
|
88 | 99f575ed | Jia Liu | cpu_openrisc_count_stop(cpu); |
89 | 99f575ed | Jia Liu | break;
|
90 | 99f575ed | Jia Liu | case TIMER_CONT:
|
91 | 99f575ed | Jia Liu | cpu_openrisc_count_start(cpu); |
92 | 99f575ed | Jia Liu | break;
|
93 | 99f575ed | Jia Liu | } |
94 | 99f575ed | Jia Liu | } |
95 | 99f575ed | Jia Liu | |
96 | 99f575ed | Jia Liu | void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
|
97 | 99f575ed | Jia Liu | { |
98 | 99f575ed | Jia Liu | cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu); |
99 | 99f575ed | Jia Liu | cpu->env.ttmr = 0x00000000;
|
100 | 99f575ed | Jia Liu | cpu->env.ttcr = 0x00000000;
|
101 | 99f575ed | Jia Liu | } |