root / hw / openrisc / cputimer.c @ f53f81e0
History | View | Annotate | Download (2.9 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 | 83c9f4ca | Paolo Bonzini | #include "hw/hw.h" |
23 | 1de7afc9 | Paolo Bonzini | #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 | d5155217 | Sebastian Macke | uint64_t now; |
34 | 99f575ed | Jia Liu | |
35 | 99f575ed | Jia Liu | if (!is_counting) {
|
36 | 99f575ed | Jia Liu | return;
|
37 | 99f575ed | Jia Liu | } |
38 | d5155217 | Sebastian Macke | now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); |
39 | 99f575ed | Jia Liu | cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ, |
40 | 99f575ed | Jia Liu | get_ticks_per_sec()); |
41 | 99f575ed | Jia Liu | last_clk = now; |
42 | d5155217 | Sebastian Macke | } |
43 | d5155217 | Sebastian Macke | |
44 | d5155217 | Sebastian Macke | void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
|
45 | d5155217 | Sebastian Macke | { |
46 | d5155217 | Sebastian Macke | uint32_t wait; |
47 | d5155217 | Sebastian Macke | uint64_t now, next; |
48 | d5155217 | Sebastian Macke | |
49 | d5155217 | Sebastian Macke | if (!is_counting) {
|
50 | d5155217 | Sebastian Macke | return;
|
51 | d5155217 | Sebastian Macke | } |
52 | d5155217 | Sebastian Macke | |
53 | d5155217 | Sebastian Macke | cpu_openrisc_count_update(cpu); |
54 | d5155217 | Sebastian Macke | now = last_clk; |
55 | 99f575ed | Jia Liu | |
56 | 99f575ed | Jia Liu | if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
|
57 | 99f575ed | Jia Liu | wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
|
58 | 99f575ed | Jia Liu | wait += cpu->env.ttmr & TTMR_TP; |
59 | 99f575ed | Jia Liu | } else {
|
60 | 99f575ed | Jia Liu | wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP); |
61 | 99f575ed | Jia Liu | } |
62 | 99f575ed | Jia Liu | next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ); |
63 | bc72ad67 | Alex Bligh | timer_mod(cpu->env.timer, next); |
64 | 99f575ed | Jia Liu | } |
65 | 99f575ed | Jia Liu | |
66 | 99f575ed | Jia Liu | void cpu_openrisc_count_start(OpenRISCCPU *cpu)
|
67 | 99f575ed | Jia Liu | { |
68 | 99f575ed | Jia Liu | is_counting = 1;
|
69 | 99f575ed | Jia Liu | cpu_openrisc_count_update(cpu); |
70 | 99f575ed | Jia Liu | } |
71 | 99f575ed | Jia Liu | |
72 | 99f575ed | Jia Liu | void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
|
73 | 99f575ed | Jia Liu | { |
74 | d5155217 | Sebastian Macke | timer_del(cpu->env.timer); |
75 | 99f575ed | Jia Liu | cpu_openrisc_count_update(cpu); |
76 | d5155217 | Sebastian Macke | is_counting = 0;
|
77 | 99f575ed | Jia Liu | } |
78 | 99f575ed | Jia Liu | |
79 | 99f575ed | Jia Liu | static void openrisc_timer_cb(void *opaque) |
80 | 99f575ed | Jia Liu | { |
81 | 99f575ed | Jia Liu | OpenRISCCPU *cpu = opaque; |
82 | 99f575ed | Jia Liu | |
83 | 99f575ed | Jia Liu | if ((cpu->env.ttmr & TTMR_IE) &&
|
84 | bc72ad67 | Alex Bligh | timer_expired(cpu->env.timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL))) { |
85 | 259186a7 | Andreas Färber | CPUState *cs = CPU(cpu); |
86 | 259186a7 | Andreas Färber | |
87 | 99f575ed | Jia Liu | cpu->env.ttmr |= TTMR_IP; |
88 | 259186a7 | Andreas Färber | cs->interrupt_request |= CPU_INTERRUPT_TIMER; |
89 | 99f575ed | Jia Liu | } |
90 | 99f575ed | Jia Liu | |
91 | 99f575ed | Jia Liu | switch (cpu->env.ttmr & TTMR_M) {
|
92 | 99f575ed | Jia Liu | case TIMER_NONE:
|
93 | 99f575ed | Jia Liu | break;
|
94 | 99f575ed | Jia Liu | case TIMER_INTR:
|
95 | 99f575ed | Jia Liu | cpu->env.ttcr = 0;
|
96 | 99f575ed | Jia Liu | break;
|
97 | 99f575ed | Jia Liu | case TIMER_SHOT:
|
98 | 99f575ed | Jia Liu | cpu_openrisc_count_stop(cpu); |
99 | 99f575ed | Jia Liu | break;
|
100 | 99f575ed | Jia Liu | case TIMER_CONT:
|
101 | 99f575ed | Jia Liu | break;
|
102 | 99f575ed | Jia Liu | } |
103 | d5155217 | Sebastian Macke | |
104 | d5155217 | Sebastian Macke | cpu_openrisc_timer_update(cpu); |
105 | 99f575ed | Jia Liu | } |
106 | 99f575ed | Jia Liu | |
107 | 99f575ed | Jia Liu | void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
|
108 | 99f575ed | Jia Liu | { |
109 | bc72ad67 | Alex Bligh | cpu->env.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &openrisc_timer_cb, cpu); |
110 | 99f575ed | Jia Liu | cpu->env.ttmr = 0x00000000;
|
111 | 99f575ed | Jia Liu | cpu->env.ttcr = 0x00000000;
|
112 | 99f575ed | Jia Liu | } |