Commit 5439779e84e352f20ee2d3e26daec81292f1b59a
1 parent
2ea815ca
ETRAX: Allow boot from flash. Support the watchdog timer and resets through it.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4592 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
163 additions
and
82 deletions
hw/etraxfs.c
| ... | ... | @@ -32,25 +32,29 @@ |
| 32 | 32 | |
| 33 | 33 | #include "etraxfs_dma.h" |
| 34 | 34 | |
| 35 | -static void main_cpu_reset(void *opaque) | |
| 36 | -{ | |
| 37 | - CPUState *env = opaque; | |
| 38 | - cpu_reset(env); | |
| 39 | -} | |
| 40 | - | |
| 41 | 35 | /* Init functions for different blocks. */ |
| 42 | 36 | extern qemu_irq *etraxfs_pic_init(CPUState *env, target_phys_addr_t base); |
| 43 | 37 | void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, |
| 44 | - target_phys_addr_t base); | |
| 45 | -void *etraxfs_eth_init(NICInfo *nd, CPUState *env, | |
| 46 | - qemu_irq *irq, target_phys_addr_t base); | |
| 38 | + target_phys_addr_t base); | |
| 39 | +void *etraxfs_eth_init(NICInfo *nd, CPUState *env, | |
| 40 | + qemu_irq *irq, target_phys_addr_t base); | |
| 47 | 41 | void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr, |
| 48 | - target_phys_addr_t base); | |
| 42 | + target_phys_addr_t base); | |
| 49 | 43 | |
| 50 | 44 | #define FLASH_SIZE 0x2000000 |
| 51 | 45 | #define INTMEM_SIZE (128 * 1024) |
| 52 | 46 | |
| 53 | 47 | static void *etraxfs_dmac; |
| 48 | +static uint32_t bootstrap_pc; | |
| 49 | + | |
| 50 | +static void main_cpu_reset(void *opaque) | |
| 51 | +{ | |
| 52 | + CPUState *env = opaque; | |
| 53 | + cpu_reset(env); | |
| 54 | + | |
| 55 | + env->pregs[PR_CCS] &= ~I_FLAG; | |
| 56 | + env->pc = bootstrap_pc; | |
| 57 | +} | |
| 54 | 58 | |
| 55 | 59 | static |
| 56 | 60 | void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, |
| ... | ... | @@ -64,6 +68,7 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, |
| 64 | 68 | int kernel_size; |
| 65 | 69 | int i; |
| 66 | 70 | ram_addr_t phys_ram; |
| 71 | + ram_addr_t phys_flash; | |
| 67 | 72 | ram_addr_t phys_intmem; |
| 68 | 73 | |
| 69 | 74 | /* init CPUs */ |
| ... | ... | @@ -83,40 +88,42 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, |
| 83 | 88 | /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the |
| 84 | 89 | internal memory. Cached and uncached mappings. */ |
| 85 | 90 | phys_intmem = qemu_ram_alloc(INTMEM_SIZE); |
| 86 | - cpu_register_physical_memory(0xb8000000, INTMEM_SIZE, | |
| 87 | - phys_intmem | IO_MEM_RAM); | |
| 88 | - cpu_register_physical_memory(0x38000000, INTMEM_SIZE, | |
| 89 | - phys_intmem | IO_MEM_RAM); | |
| 90 | - | |
| 91 | - cpu_register_physical_memory(0, FLASH_SIZE, IO_MEM_ROM); | |
| 92 | - cpu_register_physical_memory(0x80000000, FLASH_SIZE, IO_MEM_ROM); | |
| 93 | - cpu_register_physical_memory(0x04000000, FLASH_SIZE, IO_MEM_ROM); | |
| 94 | - cpu_register_physical_memory(0x84000000, FLASH_SIZE, | |
| 95 | - 0x04000000 | IO_MEM_ROM); | |
| 96 | - i = drive_get_index(IF_PFLASH, 0, 0); | |
| 97 | - pflash_cfi02_register(0x80000000, qemu_ram_alloc(FLASH_SIZE), | |
| 98 | - drives_table[i].bdrv, (64 * 1024), | |
| 99 | - FLASH_SIZE >> 16, | |
| 100 | - 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa); | |
| 91 | + cpu_register_physical_memory(0xb8000000, INTMEM_SIZE, | |
| 92 | + phys_intmem | IO_MEM_RAM); | |
| 93 | + cpu_register_physical_memory(0x38000000, INTMEM_SIZE, | |
| 94 | + phys_intmem | IO_MEM_RAM); | |
| 95 | + | |
| 101 | 96 | |
| 97 | + phys_flash = qemu_ram_alloc(FLASH_SIZE); | |
| 98 | + i = drive_get_index(IF_PFLASH, 0, 0); | |
| 99 | + pflash_cfi02_register(0x80000000, phys_flash, | |
| 100 | + drives_table[i].bdrv, (64 * 1024), | |
| 101 | + FLASH_SIZE >> 16, | |
| 102 | + 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, | |
| 103 | + 0x555, 0x2aa); | |
| 104 | + pflash_cfi02_register(0x0, phys_flash, | |
| 105 | + drives_table[i].bdrv, (64 * 1024), | |
| 106 | + FLASH_SIZE >> 16, | |
| 107 | + 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, | |
| 108 | + 0x555, 0x2aa); | |
| 102 | 109 | pic = etraxfs_pic_init(env, 0xb001c000); |
| 103 | 110 | etraxfs_dmac = etraxfs_dmac_init(env, 0xb0000000, 10); |
| 104 | 111 | for (i = 0; i < 10; i++) { |
| 105 | - /* On ETRAX, odd numbered channels are inputs. */ | |
| 106 | - etraxfs_dmac_connect(etraxfs_dmac, i, pic + 7 + i, i & 1); | |
| 112 | + /* On ETRAX, odd numbered channels are inputs. */ | |
| 113 | + etraxfs_dmac_connect(etraxfs_dmac, i, pic + 7 + i, i & 1); | |
| 107 | 114 | } |
| 108 | 115 | |
| 109 | 116 | /* Add the two ethernet blocks. */ |
| 110 | 117 | eth[0] = etraxfs_eth_init(&nd_table[0], env, pic + 25, 0xb0034000); |
| 111 | 118 | if (nb_nics > 1) |
| 112 | - eth[1] = etraxfs_eth_init(&nd_table[1], env, pic + 26, 0xb0036000); | |
| 113 | - | |
| 119 | + eth[1] = etraxfs_eth_init(&nd_table[1], env, pic + 26, 0xb0036000); | |
| 120 | + | |
| 114 | 121 | /* The DMA Connector block is missing, hardwire things for now. */ |
| 115 | 122 | etraxfs_dmac_connect_client(etraxfs_dmac, 0, eth[0]); |
| 116 | 123 | etraxfs_dmac_connect_client(etraxfs_dmac, 1, eth[0] + 1); |
| 117 | 124 | if (eth[1]) { |
| 118 | - etraxfs_dmac_connect_client(etraxfs_dmac, 6, eth[1]); | |
| 119 | - etraxfs_dmac_connect_client(etraxfs_dmac, 7, eth[1] + 1); | |
| 125 | + etraxfs_dmac_connect_client(etraxfs_dmac, 6, eth[1]); | |
| 126 | + etraxfs_dmac_connect_client(etraxfs_dmac, 7, eth[1] + 1); | |
| 120 | 127 | } |
| 121 | 128 | |
| 122 | 129 | /* 2 timers. */ |
| ... | ... | @@ -124,40 +131,31 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, |
| 124 | 131 | etraxfs_timer_init(env, pic + 0x1b, 0xb005e000); |
| 125 | 132 | |
| 126 | 133 | for (i = 0; i < 4; i++) { |
| 127 | - if (serial_hds[i]) { | |
| 128 | - etraxfs_ser_init(env, pic + 0x14 + i, | |
| 129 | - serial_hds[i], 0xb0026000 + i * 0x2000); | |
| 130 | - } | |
| 134 | + if (serial_hds[i]) { | |
| 135 | + etraxfs_ser_init(env, pic + 0x14 + i, | |
| 136 | + serial_hds[i], 0xb0026000 + i * 0x2000); | |
| 137 | + } | |
| 131 | 138 | } |
| 132 | 139 | |
| 140 | + if (kernel_filename) { | |
| 133 | 141 | #if 1 |
| 134 | - /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis devboard | |
| 135 | - SDK. */ | |
| 136 | - kernel_size = load_elf(kernel_filename, 0, &env->pc, NULL, NULL); | |
| 142 | + /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis | |
| 143 | + devboard SDK. */ | |
| 144 | + kernel_size = load_elf(kernel_filename, 0, | |
| 145 | + &bootstrap_pc, NULL, NULL); | |
| 137 | 146 | #else |
| 138 | - /* Takes a kimage from the axis devboard SDK. */ | |
| 139 | - kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000); | |
| 140 | - env->pc = 0x40004000; | |
| 147 | + /* Takes a kimage from the axis devboard SDK. */ | |
| 148 | + kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000); | |
| 149 | + bootstrap_pc = 0x40004000; | |
| 150 | + /* magic for boot. */ | |
| 151 | + env->regs[8] = 0x56902387; | |
| 152 | + env->regs[9] = 0x40004000 + kernel_size; | |
| 141 | 153 | #endif |
| 142 | - /* magic for boot. */ | |
| 143 | - env->regs[8] = 0x56902387; | |
| 144 | - env->regs[9] = 0x40004000 + kernel_size; | |
| 145 | - | |
| 146 | - { | |
| 147 | - unsigned char *ptr = phys_ram_base + 0x4000; | |
| 148 | - int i; | |
| 149 | - for (i = 0; i < 8; i++) | |
| 150 | - { | |
| 151 | - printf ("%2.2x ", ptr[i]); | |
| 152 | - } | |
| 153 | - printf("\n"); | |
| 154 | 154 | } |
| 155 | + env->pc = bootstrap_pc; | |
| 155 | 156 | |
| 156 | 157 | printf ("pc =%x\n", env->pc); |
| 157 | 158 | printf ("ram size =%ld\n", ram_size); |
| 158 | - printf ("kernel name =%s\n", kernel_filename); | |
| 159 | - printf ("kernel size =%d\n", kernel_size); | |
| 160 | - printf ("cpu haltd =%d\n", env->halted); | |
| 161 | 159 | } |
| 162 | 160 | |
| 163 | 161 | void DMA_run(void) |
| ... | ... | @@ -169,5 +167,5 @@ QEMUMachine bareetraxfs_machine = { |
| 169 | 167 | "bareetraxfs", |
| 170 | 168 | "Bare ETRAX FS board", |
| 171 | 169 | bareetraxfs_init, |
| 172 | - 0x4000000, | |
| 170 | + 0x8000000, | |
| 173 | 171 | }; | ... | ... |
hw/etraxfs_timer.c
| ... | ... | @@ -24,6 +24,7 @@ |
| 24 | 24 | #include <stdio.h> |
| 25 | 25 | #include <sys/time.h> |
| 26 | 26 | #include "hw.h" |
| 27 | +#include "sysemu.h" | |
| 27 | 28 | #include "qemu-timer.h" |
| 28 | 29 | |
| 29 | 30 | #define D(x) |
| ... | ... | @@ -36,6 +37,7 @@ |
| 36 | 37 | #define RW_TMR1_CTRL 0x18 |
| 37 | 38 | #define R_TIME 0x38 |
| 38 | 39 | #define RW_WD_CTRL 0x40 |
| 40 | +#define R_WD_STAT 0x44 | |
| 39 | 41 | #define RW_INTR_MASK 0x48 |
| 40 | 42 | #define RW_ACK_INTR 0x4c |
| 41 | 43 | #define R_INTR 0x50 |
| ... | ... | @@ -46,8 +48,12 @@ struct fs_timer_t { |
| 46 | 48 | qemu_irq *irq; |
| 47 | 49 | target_phys_addr_t base; |
| 48 | 50 | |
| 49 | - QEMUBH *bh; | |
| 50 | - ptimer_state *ptimer; | |
| 51 | + QEMUBH *bh_t0; | |
| 52 | + QEMUBH *bh_t1; | |
| 53 | + QEMUBH *bh_wd; | |
| 54 | + ptimer_state *ptimer_t0; | |
| 55 | + ptimer_state *ptimer_t1; | |
| 56 | + ptimer_state *ptimer_wd; | |
| 51 | 57 | struct timeval last; |
| 52 | 58 | |
| 53 | 59 | /* Control registers. */ |
| ... | ... | @@ -59,6 +65,8 @@ struct fs_timer_t { |
| 59 | 65 | uint32_t r_tmr1_data; |
| 60 | 66 | uint32_t rw_tmr1_ctrl; |
| 61 | 67 | |
| 68 | + uint32_t rw_wd_ctrl; | |
| 69 | + | |
| 62 | 70 | uint32_t rw_intr_mask; |
| 63 | 71 | uint32_t rw_ack_intr; |
| 64 | 72 | uint32_t r_intr; |
| ... | ... | @@ -114,15 +122,28 @@ timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 114 | 122 | } |
| 115 | 123 | |
| 116 | 124 | #define TIMER_SLOWDOWN 1 |
| 117 | -static void update_ctrl(struct fs_timer_t *t) | |
| 125 | +static void update_ctrl(struct fs_timer_t *t, int tnum) | |
| 118 | 126 | { |
| 119 | 127 | unsigned int op; |
| 120 | 128 | unsigned int freq; |
| 121 | 129 | unsigned int freq_hz; |
| 122 | 130 | unsigned int div; |
| 131 | + uint32_t ctrl; | |
| 132 | + ptimer_state *timer; | |
| 133 | + | |
| 134 | + if (tnum == 0) { | |
| 135 | + ctrl = t->rw_tmr0_ctrl; | |
| 136 | + div = t->rw_tmr0_div; | |
| 137 | + timer = t->ptimer_t0; | |
| 138 | + } else { | |
| 139 | + ctrl = t->rw_tmr1_ctrl; | |
| 140 | + div = t->rw_tmr1_div; | |
| 141 | + timer = t->ptimer_t1; | |
| 142 | + } | |
| 143 | + | |
| 123 | 144 | |
| 124 | - op = t->rw_tmr0_ctrl & 3; | |
| 125 | - freq = t->rw_tmr0_ctrl >> 2; | |
| 145 | + op = ctrl & 3; | |
| 146 | + freq = ctrl >> 2; | |
| 126 | 147 | freq_hz = 32000000; |
| 127 | 148 | |
| 128 | 149 | switch (freq) |
| ... | ... | @@ -134,33 +155,32 @@ static void update_ctrl(struct fs_timer_t *t) |
| 134 | 155 | case 4: freq_hz = 29493000; break; |
| 135 | 156 | case 5: freq_hz = 32000000; break; |
| 136 | 157 | case 6: freq_hz = 32768000; break; |
| 137 | - case 7: freq_hz = 100000000; break; | |
| 158 | + case 7: freq_hz = 100001000; break; | |
| 138 | 159 | default: |
| 139 | 160 | abort(); |
| 140 | 161 | break; |
| 141 | 162 | } |
| 142 | 163 | |
| 143 | - D(printf ("freq_hz=%d div=%d\n", freq_hz, t->rw_tmr0_div)); | |
| 144 | - div = t->rw_tmr0_div * TIMER_SLOWDOWN; | |
| 164 | + D(printf ("freq_hz=%d div=%d\n", freq_hz, div)); | |
| 165 | + div = div * TIMER_SLOWDOWN; | |
| 145 | 166 | div >>= 15; |
| 146 | 167 | freq_hz >>= 15; |
| 147 | - ptimer_set_freq(t->ptimer, freq_hz); | |
| 148 | - ptimer_set_limit(t->ptimer, div, 0); | |
| 168 | + ptimer_set_freq(timer, freq_hz); | |
| 169 | + ptimer_set_limit(timer, div, 0); | |
| 149 | 170 | |
| 150 | 171 | switch (op) |
| 151 | 172 | { |
| 152 | 173 | case 0: |
| 153 | 174 | /* Load. */ |
| 154 | - ptimer_set_limit(t->ptimer, div, 1); | |
| 155 | - ptimer_run(t->ptimer, 1); | |
| 175 | + ptimer_set_limit(timer, div, 1); | |
| 156 | 176 | break; |
| 157 | 177 | case 1: |
| 158 | 178 | /* Hold. */ |
| 159 | - ptimer_stop(t->ptimer); | |
| 179 | + ptimer_stop(timer); | |
| 160 | 180 | break; |
| 161 | 181 | case 2: |
| 162 | 182 | /* Run. */ |
| 163 | - ptimer_run(t->ptimer, 0); | |
| 183 | + ptimer_run(timer, 0); | |
| 164 | 184 | break; |
| 165 | 185 | default: |
| 166 | 186 | abort(); |
| ... | ... | @@ -180,13 +200,55 @@ static void timer_update_irq(struct fs_timer_t *t) |
| 180 | 200 | qemu_irq_lower(t->irq[0]); |
| 181 | 201 | } |
| 182 | 202 | |
| 183 | -static void timer_hit(void *opaque) | |
| 203 | +static void timer0_hit(void *opaque) | |
| 184 | 204 | { |
| 185 | 205 | struct fs_timer_t *t = opaque; |
| 186 | 206 | t->r_intr |= 1; |
| 187 | 207 | timer_update_irq(t); |
| 188 | 208 | } |
| 189 | 209 | |
| 210 | +static void timer1_hit(void *opaque) | |
| 211 | +{ | |
| 212 | + struct fs_timer_t *t = opaque; | |
| 213 | + t->r_intr |= 2; | |
| 214 | + timer_update_irq(t); | |
| 215 | +} | |
| 216 | + | |
| 217 | +static void watchdog_hit(void *opaque) | |
| 218 | +{ | |
| 219 | + qemu_system_reset_request(); | |
| 220 | +} | |
| 221 | + | |
| 222 | +static inline void timer_watchdog_update(struct fs_timer_t *t, uint32_t value) | |
| 223 | +{ | |
| 224 | + unsigned int wd_en = t->rw_wd_ctrl & (1 << 8); | |
| 225 | + unsigned int wd_key = t->rw_wd_ctrl >> 9; | |
| 226 | + unsigned int wd_cnt = t->rw_wd_ctrl & 511; | |
| 227 | + unsigned int new_key = value >> 9 & ((1 << 7) - 1); | |
| 228 | + unsigned int new_cmd = (value >> 8) & 1; | |
| 229 | + | |
| 230 | + /* If the watchdog is enabled, they written key must match the | |
| 231 | + complement of the previous. */ | |
| 232 | + wd_key = ~wd_key & ((1 << 7) - 1); | |
| 233 | + | |
| 234 | + if (wd_en && wd_key != new_key) | |
| 235 | + return; | |
| 236 | + | |
| 237 | + D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n", | |
| 238 | + wd_en, new_key, wd_key, wd_cmd, wd_cnt)); | |
| 239 | + | |
| 240 | + ptimer_set_freq(t->ptimer_wd, 760); | |
| 241 | + if (wd_cnt == 0) | |
| 242 | + wd_cnt = 256; | |
| 243 | + ptimer_set_count(t->ptimer_wd, wd_cnt); | |
| 244 | + if (new_cmd) | |
| 245 | + ptimer_run(t->ptimer_wd, 1); | |
| 246 | + else | |
| 247 | + ptimer_stop(t->ptimer_wd); | |
| 248 | + | |
| 249 | + t->rw_wd_ctrl = value; | |
| 250 | +} | |
| 251 | + | |
| 190 | 252 | static void |
| 191 | 253 | timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 192 | 254 | { |
| ... | ... | @@ -203,13 +265,15 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 203 | 265 | case RW_TMR0_CTRL: |
| 204 | 266 | D(printf ("RW_TMR0_CTRL=%x\n", value)); |
| 205 | 267 | t->rw_tmr0_ctrl = value; |
| 206 | - update_ctrl(t); | |
| 268 | + update_ctrl(t, 0); | |
| 207 | 269 | break; |
| 208 | 270 | case RW_TMR1_DIV: |
| 209 | 271 | t->rw_tmr1_div = value; |
| 210 | 272 | break; |
| 211 | 273 | case RW_TMR1_CTRL: |
| 212 | 274 | D(printf ("RW_TMR1_CTRL=%x\n", value)); |
| 275 | + t->rw_tmr1_ctrl = value; | |
| 276 | + update_ctrl(t, 1); | |
| 213 | 277 | break; |
| 214 | 278 | case RW_INTR_MASK: |
| 215 | 279 | D(printf ("RW_INTR_MASK=%x\n", value)); |
| ... | ... | @@ -217,7 +281,7 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 217 | 281 | timer_update_irq(t); |
| 218 | 282 | break; |
| 219 | 283 | case RW_WD_CTRL: |
| 220 | - D(printf ("RW_WD_CTRL=%x\n", value)); | |
| 284 | + timer_watchdog_update(t, value); | |
| 221 | 285 | break; |
| 222 | 286 | case RW_ACK_INTR: |
| 223 | 287 | t->rw_ack_intr = value; |
| ... | ... | @@ -232,17 +296,30 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 232 | 296 | } |
| 233 | 297 | |
| 234 | 298 | static CPUReadMemoryFunc *timer_read[] = { |
| 235 | - &timer_rinvalid, | |
| 236 | - &timer_rinvalid, | |
| 237 | - &timer_readl, | |
| 299 | + &timer_rinvalid, | |
| 300 | + &timer_rinvalid, | |
| 301 | + &timer_readl, | |
| 238 | 302 | }; |
| 239 | 303 | |
| 240 | 304 | static CPUWriteMemoryFunc *timer_write[] = { |
| 241 | - &timer_winvalid, | |
| 242 | - &timer_winvalid, | |
| 243 | - &timer_writel, | |
| 305 | + &timer_winvalid, | |
| 306 | + &timer_winvalid, | |
| 307 | + &timer_writel, | |
| 244 | 308 | }; |
| 245 | 309 | |
| 310 | +static void etraxfs_timer_reset(void *opaque) | |
| 311 | +{ | |
| 312 | + struct fs_timer_t *t = opaque; | |
| 313 | + | |
| 314 | + ptimer_stop(t->ptimer_t0); | |
| 315 | + ptimer_stop(t->ptimer_t1); | |
| 316 | + ptimer_stop(t->ptimer_wd); | |
| 317 | + t->rw_wd_ctrl = 0; | |
| 318 | + t->r_intr = 0; | |
| 319 | + t->rw_intr_mask = 0; | |
| 320 | + qemu_irq_lower(t->irq[0]); | |
| 321 | +} | |
| 322 | + | |
| 246 | 323 | void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, |
| 247 | 324 | target_phys_addr_t base) |
| 248 | 325 | { |
| ... | ... | @@ -253,12 +330,18 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, |
| 253 | 330 | if (!t) |
| 254 | 331 | return; |
| 255 | 332 | |
| 256 | - t->bh = qemu_bh_new(timer_hit, t); | |
| 257 | - t->ptimer = ptimer_init(t->bh); | |
| 333 | + t->bh_t0 = qemu_bh_new(timer0_hit, t); | |
| 334 | + t->bh_t1 = qemu_bh_new(timer1_hit, t); | |
| 335 | + t->bh_wd = qemu_bh_new(watchdog_hit, t); | |
| 336 | + t->ptimer_t0 = ptimer_init(t->bh_t0); | |
| 337 | + t->ptimer_t1 = ptimer_init(t->bh_t1); | |
| 338 | + t->ptimer_wd = ptimer_init(t->bh_wd); | |
| 258 | 339 | t->irq = irqs; |
| 259 | 340 | t->env = env; |
| 260 | 341 | t->base = base; |
| 261 | 342 | |
| 262 | 343 | timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t); |
| 263 | 344 | cpu_register_physical_memory (base, 0x5c, timer_regs); |
| 345 | + | |
| 346 | + qemu_register_reset(etraxfs_timer_reset, t); | |
| 264 | 347 | } | ... | ... |