Loading hw/etraxfs.c +55 −57 Original line number Diff line number Diff line Loading @@ -32,12 +32,6 @@ #include "etraxfs_dma.h" static void main_cpu_reset(void *opaque) { CPUState *env = opaque; cpu_reset(env); } /* Init functions for different blocks. */ extern qemu_irq *etraxfs_pic_init(CPUState *env, target_phys_addr_t base); void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, Loading @@ -51,6 +45,16 @@ void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr, #define INTMEM_SIZE (128 * 1024) static void *etraxfs_dmac; static uint32_t bootstrap_pc; static void main_cpu_reset(void *opaque) { CPUState *env = opaque; cpu_reset(env); env->pregs[PR_CCS] &= ~I_FLAG; env->pc = bootstrap_pc; } static void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, Loading @@ -64,6 +68,7 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, int kernel_size; int i; ram_addr_t phys_ram; ram_addr_t phys_flash; ram_addr_t phys_intmem; /* init CPUs */ Loading @@ -88,17 +93,19 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, cpu_register_physical_memory(0x38000000, INTMEM_SIZE, phys_intmem | IO_MEM_RAM); cpu_register_physical_memory(0, FLASH_SIZE, IO_MEM_ROM); cpu_register_physical_memory(0x80000000, FLASH_SIZE, IO_MEM_ROM); cpu_register_physical_memory(0x04000000, FLASH_SIZE, IO_MEM_ROM); cpu_register_physical_memory(0x84000000, FLASH_SIZE, 0x04000000 | IO_MEM_ROM); phys_flash = qemu_ram_alloc(FLASH_SIZE); i = drive_get_index(IF_PFLASH, 0, 0); pflash_cfi02_register(0x80000000, qemu_ram_alloc(FLASH_SIZE), pflash_cfi02_register(0x80000000, phys_flash, drives_table[i].bdrv, (64 * 1024), FLASH_SIZE >> 16, 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa); 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa); pflash_cfi02_register(0x0, phys_flash, drives_table[i].bdrv, (64 * 1024), FLASH_SIZE >> 16, 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa); pic = etraxfs_pic_init(env, 0xb001c000); etraxfs_dmac = etraxfs_dmac_init(env, 0xb0000000, 10); for (i = 0; i < 10; i++) { Loading Loading @@ -130,34 +137,25 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, } } if (kernel_filename) { #if 1 /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis devboard SDK. */ kernel_size = load_elf(kernel_filename, 0, &env->pc, NULL, NULL); /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis devboard SDK. */ kernel_size = load_elf(kernel_filename, 0, &bootstrap_pc, NULL, NULL); #else /* Takes a kimage from the axis devboard SDK. */ kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000); env->pc = 0x40004000; #endif bootstrap_pc = 0x40004000; /* magic for boot. */ env->regs[8] = 0x56902387; env->regs[9] = 0x40004000 + kernel_size; { unsigned char *ptr = phys_ram_base + 0x4000; int i; for (i = 0; i < 8; i++) { printf ("%2.2x ", ptr[i]); } printf("\n"); #endif } env->pc = bootstrap_pc; printf ("pc =%x\n", env->pc); printf ("ram size =%ld\n", ram_size); printf ("kernel name =%s\n", kernel_filename); printf ("kernel size =%d\n", kernel_size); printf ("cpu haltd =%d\n", env->halted); } void DMA_run(void) Loading @@ -169,5 +167,5 @@ QEMUMachine bareetraxfs_machine = { "bareetraxfs", "Bare ETRAX FS board", bareetraxfs_init, 0x4000000, 0x8000000, }; hw/etraxfs_timer.c +108 −25 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <stdio.h> #include <sys/time.h> #include "hw.h" #include "sysemu.h" #include "qemu-timer.h" #define D(x) Loading @@ -36,6 +37,7 @@ #define RW_TMR1_CTRL 0x18 #define R_TIME 0x38 #define RW_WD_CTRL 0x40 #define R_WD_STAT 0x44 #define RW_INTR_MASK 0x48 #define RW_ACK_INTR 0x4c #define R_INTR 0x50 Loading @@ -46,8 +48,12 @@ struct fs_timer_t { qemu_irq *irq; target_phys_addr_t base; QEMUBH *bh; ptimer_state *ptimer; QEMUBH *bh_t0; QEMUBH *bh_t1; QEMUBH *bh_wd; ptimer_state *ptimer_t0; ptimer_state *ptimer_t1; ptimer_state *ptimer_wd; struct timeval last; /* Control registers. */ Loading @@ -59,6 +65,8 @@ struct fs_timer_t { uint32_t r_tmr1_data; uint32_t rw_tmr1_ctrl; uint32_t rw_wd_ctrl; uint32_t rw_intr_mask; uint32_t rw_ack_intr; uint32_t r_intr; Loading Loading @@ -114,15 +122,28 @@ timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) } #define TIMER_SLOWDOWN 1 static void update_ctrl(struct fs_timer_t *t) static void update_ctrl(struct fs_timer_t *t, int tnum) { unsigned int op; unsigned int freq; unsigned int freq_hz; unsigned int div; uint32_t ctrl; ptimer_state *timer; if (tnum == 0) { ctrl = t->rw_tmr0_ctrl; div = t->rw_tmr0_div; timer = t->ptimer_t0; } else { ctrl = t->rw_tmr1_ctrl; div = t->rw_tmr1_div; timer = t->ptimer_t1; } op = t->rw_tmr0_ctrl & 3; freq = t->rw_tmr0_ctrl >> 2; op = ctrl & 3; freq = ctrl >> 2; freq_hz = 32000000; switch (freq) Loading @@ -134,33 +155,32 @@ static void update_ctrl(struct fs_timer_t *t) case 4: freq_hz = 29493000; break; case 5: freq_hz = 32000000; break; case 6: freq_hz = 32768000; break; case 7: freq_hz = 100000000; break; case 7: freq_hz = 100001000; break; default: abort(); break; } D(printf ("freq_hz=%d div=%d\n", freq_hz, t->rw_tmr0_div)); div = t->rw_tmr0_div * TIMER_SLOWDOWN; D(printf ("freq_hz=%d div=%d\n", freq_hz, div)); div = div * TIMER_SLOWDOWN; div >>= 15; freq_hz >>= 15; ptimer_set_freq(t->ptimer, freq_hz); ptimer_set_limit(t->ptimer, div, 0); ptimer_set_freq(timer, freq_hz); ptimer_set_limit(timer, div, 0); switch (op) { case 0: /* Load. */ ptimer_set_limit(t->ptimer, div, 1); ptimer_run(t->ptimer, 1); ptimer_set_limit(timer, div, 1); break; case 1: /* Hold. */ ptimer_stop(t->ptimer); ptimer_stop(timer); break; case 2: /* Run. */ ptimer_run(t->ptimer, 0); ptimer_run(timer, 0); break; default: abort(); Loading @@ -180,13 +200,55 @@ static void timer_update_irq(struct fs_timer_t *t) qemu_irq_lower(t->irq[0]); } static void timer_hit(void *opaque) static void timer0_hit(void *opaque) { struct fs_timer_t *t = opaque; t->r_intr |= 1; timer_update_irq(t); } static void timer1_hit(void *opaque) { struct fs_timer_t *t = opaque; t->r_intr |= 2; timer_update_irq(t); } static void watchdog_hit(void *opaque) { qemu_system_reset_request(); } static inline void timer_watchdog_update(struct fs_timer_t *t, uint32_t value) { unsigned int wd_en = t->rw_wd_ctrl & (1 << 8); unsigned int wd_key = t->rw_wd_ctrl >> 9; unsigned int wd_cnt = t->rw_wd_ctrl & 511; unsigned int new_key = value >> 9 & ((1 << 7) - 1); unsigned int new_cmd = (value >> 8) & 1; /* If the watchdog is enabled, they written key must match the complement of the previous. */ wd_key = ~wd_key & ((1 << 7) - 1); if (wd_en && wd_key != new_key) return; D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n", wd_en, new_key, wd_key, wd_cmd, wd_cnt)); ptimer_set_freq(t->ptimer_wd, 760); if (wd_cnt == 0) wd_cnt = 256; ptimer_set_count(t->ptimer_wd, wd_cnt); if (new_cmd) ptimer_run(t->ptimer_wd, 1); else ptimer_stop(t->ptimer_wd); t->rw_wd_ctrl = value; } static void timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { Loading @@ -203,13 +265,15 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) case RW_TMR0_CTRL: D(printf ("RW_TMR0_CTRL=%x\n", value)); t->rw_tmr0_ctrl = value; update_ctrl(t); update_ctrl(t, 0); break; case RW_TMR1_DIV: t->rw_tmr1_div = value; break; case RW_TMR1_CTRL: D(printf ("RW_TMR1_CTRL=%x\n", value)); t->rw_tmr1_ctrl = value; update_ctrl(t, 1); break; case RW_INTR_MASK: D(printf ("RW_INTR_MASK=%x\n", value)); Loading @@ -217,7 +281,7 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) timer_update_irq(t); break; case RW_WD_CTRL: D(printf ("RW_WD_CTRL=%x\n", value)); timer_watchdog_update(t, value); break; case RW_ACK_INTR: t->rw_ack_intr = value; Loading @@ -243,6 +307,19 @@ static CPUWriteMemoryFunc *timer_write[] = { &timer_writel, }; static void etraxfs_timer_reset(void *opaque) { struct fs_timer_t *t = opaque; ptimer_stop(t->ptimer_t0); ptimer_stop(t->ptimer_t1); ptimer_stop(t->ptimer_wd); t->rw_wd_ctrl = 0; t->r_intr = 0; t->rw_intr_mask = 0; qemu_irq_lower(t->irq[0]); } void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, target_phys_addr_t base) { Loading @@ -253,12 +330,18 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, if (!t) return; t->bh = qemu_bh_new(timer_hit, t); t->ptimer = ptimer_init(t->bh); t->bh_t0 = qemu_bh_new(timer0_hit, t); t->bh_t1 = qemu_bh_new(timer1_hit, t); t->bh_wd = qemu_bh_new(watchdog_hit, t); t->ptimer_t0 = ptimer_init(t->bh_t0); t->ptimer_t1 = ptimer_init(t->bh_t1); t->ptimer_wd = ptimer_init(t->bh_wd); t->irq = irqs; t->env = env; t->base = base; timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t); cpu_register_physical_memory (base, 0x5c, timer_regs); qemu_register_reset(etraxfs_timer_reset, t); } Loading
hw/etraxfs.c +55 −57 Original line number Diff line number Diff line Loading @@ -32,12 +32,6 @@ #include "etraxfs_dma.h" static void main_cpu_reset(void *opaque) { CPUState *env = opaque; cpu_reset(env); } /* Init functions for different blocks. */ extern qemu_irq *etraxfs_pic_init(CPUState *env, target_phys_addr_t base); void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, Loading @@ -51,6 +45,16 @@ void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr, #define INTMEM_SIZE (128 * 1024) static void *etraxfs_dmac; static uint32_t bootstrap_pc; static void main_cpu_reset(void *opaque) { CPUState *env = opaque; cpu_reset(env); env->pregs[PR_CCS] &= ~I_FLAG; env->pc = bootstrap_pc; } static void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, Loading @@ -64,6 +68,7 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, int kernel_size; int i; ram_addr_t phys_ram; ram_addr_t phys_flash; ram_addr_t phys_intmem; /* init CPUs */ Loading @@ -88,17 +93,19 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, cpu_register_physical_memory(0x38000000, INTMEM_SIZE, phys_intmem | IO_MEM_RAM); cpu_register_physical_memory(0, FLASH_SIZE, IO_MEM_ROM); cpu_register_physical_memory(0x80000000, FLASH_SIZE, IO_MEM_ROM); cpu_register_physical_memory(0x04000000, FLASH_SIZE, IO_MEM_ROM); cpu_register_physical_memory(0x84000000, FLASH_SIZE, 0x04000000 | IO_MEM_ROM); phys_flash = qemu_ram_alloc(FLASH_SIZE); i = drive_get_index(IF_PFLASH, 0, 0); pflash_cfi02_register(0x80000000, qemu_ram_alloc(FLASH_SIZE), pflash_cfi02_register(0x80000000, phys_flash, drives_table[i].bdrv, (64 * 1024), FLASH_SIZE >> 16, 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa); 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa); pflash_cfi02_register(0x0, phys_flash, drives_table[i].bdrv, (64 * 1024), FLASH_SIZE >> 16, 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa); pic = etraxfs_pic_init(env, 0xb001c000); etraxfs_dmac = etraxfs_dmac_init(env, 0xb0000000, 10); for (i = 0; i < 10; i++) { Loading Loading @@ -130,34 +137,25 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, } } if (kernel_filename) { #if 1 /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis devboard SDK. */ kernel_size = load_elf(kernel_filename, 0, &env->pc, NULL, NULL); /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis devboard SDK. */ kernel_size = load_elf(kernel_filename, 0, &bootstrap_pc, NULL, NULL); #else /* Takes a kimage from the axis devboard SDK. */ kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000); env->pc = 0x40004000; #endif bootstrap_pc = 0x40004000; /* magic for boot. */ env->regs[8] = 0x56902387; env->regs[9] = 0x40004000 + kernel_size; { unsigned char *ptr = phys_ram_base + 0x4000; int i; for (i = 0; i < 8; i++) { printf ("%2.2x ", ptr[i]); } printf("\n"); #endif } env->pc = bootstrap_pc; printf ("pc =%x\n", env->pc); printf ("ram size =%ld\n", ram_size); printf ("kernel name =%s\n", kernel_filename); printf ("kernel size =%d\n", kernel_size); printf ("cpu haltd =%d\n", env->halted); } void DMA_run(void) Loading @@ -169,5 +167,5 @@ QEMUMachine bareetraxfs_machine = { "bareetraxfs", "Bare ETRAX FS board", bareetraxfs_init, 0x4000000, 0x8000000, };
hw/etraxfs_timer.c +108 −25 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <stdio.h> #include <sys/time.h> #include "hw.h" #include "sysemu.h" #include "qemu-timer.h" #define D(x) Loading @@ -36,6 +37,7 @@ #define RW_TMR1_CTRL 0x18 #define R_TIME 0x38 #define RW_WD_CTRL 0x40 #define R_WD_STAT 0x44 #define RW_INTR_MASK 0x48 #define RW_ACK_INTR 0x4c #define R_INTR 0x50 Loading @@ -46,8 +48,12 @@ struct fs_timer_t { qemu_irq *irq; target_phys_addr_t base; QEMUBH *bh; ptimer_state *ptimer; QEMUBH *bh_t0; QEMUBH *bh_t1; QEMUBH *bh_wd; ptimer_state *ptimer_t0; ptimer_state *ptimer_t1; ptimer_state *ptimer_wd; struct timeval last; /* Control registers. */ Loading @@ -59,6 +65,8 @@ struct fs_timer_t { uint32_t r_tmr1_data; uint32_t rw_tmr1_ctrl; uint32_t rw_wd_ctrl; uint32_t rw_intr_mask; uint32_t rw_ack_intr; uint32_t r_intr; Loading Loading @@ -114,15 +122,28 @@ timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) } #define TIMER_SLOWDOWN 1 static void update_ctrl(struct fs_timer_t *t) static void update_ctrl(struct fs_timer_t *t, int tnum) { unsigned int op; unsigned int freq; unsigned int freq_hz; unsigned int div; uint32_t ctrl; ptimer_state *timer; if (tnum == 0) { ctrl = t->rw_tmr0_ctrl; div = t->rw_tmr0_div; timer = t->ptimer_t0; } else { ctrl = t->rw_tmr1_ctrl; div = t->rw_tmr1_div; timer = t->ptimer_t1; } op = t->rw_tmr0_ctrl & 3; freq = t->rw_tmr0_ctrl >> 2; op = ctrl & 3; freq = ctrl >> 2; freq_hz = 32000000; switch (freq) Loading @@ -134,33 +155,32 @@ static void update_ctrl(struct fs_timer_t *t) case 4: freq_hz = 29493000; break; case 5: freq_hz = 32000000; break; case 6: freq_hz = 32768000; break; case 7: freq_hz = 100000000; break; case 7: freq_hz = 100001000; break; default: abort(); break; } D(printf ("freq_hz=%d div=%d\n", freq_hz, t->rw_tmr0_div)); div = t->rw_tmr0_div * TIMER_SLOWDOWN; D(printf ("freq_hz=%d div=%d\n", freq_hz, div)); div = div * TIMER_SLOWDOWN; div >>= 15; freq_hz >>= 15; ptimer_set_freq(t->ptimer, freq_hz); ptimer_set_limit(t->ptimer, div, 0); ptimer_set_freq(timer, freq_hz); ptimer_set_limit(timer, div, 0); switch (op) { case 0: /* Load. */ ptimer_set_limit(t->ptimer, div, 1); ptimer_run(t->ptimer, 1); ptimer_set_limit(timer, div, 1); break; case 1: /* Hold. */ ptimer_stop(t->ptimer); ptimer_stop(timer); break; case 2: /* Run. */ ptimer_run(t->ptimer, 0); ptimer_run(timer, 0); break; default: abort(); Loading @@ -180,13 +200,55 @@ static void timer_update_irq(struct fs_timer_t *t) qemu_irq_lower(t->irq[0]); } static void timer_hit(void *opaque) static void timer0_hit(void *opaque) { struct fs_timer_t *t = opaque; t->r_intr |= 1; timer_update_irq(t); } static void timer1_hit(void *opaque) { struct fs_timer_t *t = opaque; t->r_intr |= 2; timer_update_irq(t); } static void watchdog_hit(void *opaque) { qemu_system_reset_request(); } static inline void timer_watchdog_update(struct fs_timer_t *t, uint32_t value) { unsigned int wd_en = t->rw_wd_ctrl & (1 << 8); unsigned int wd_key = t->rw_wd_ctrl >> 9; unsigned int wd_cnt = t->rw_wd_ctrl & 511; unsigned int new_key = value >> 9 & ((1 << 7) - 1); unsigned int new_cmd = (value >> 8) & 1; /* If the watchdog is enabled, they written key must match the complement of the previous. */ wd_key = ~wd_key & ((1 << 7) - 1); if (wd_en && wd_key != new_key) return; D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n", wd_en, new_key, wd_key, wd_cmd, wd_cnt)); ptimer_set_freq(t->ptimer_wd, 760); if (wd_cnt == 0) wd_cnt = 256; ptimer_set_count(t->ptimer_wd, wd_cnt); if (new_cmd) ptimer_run(t->ptimer_wd, 1); else ptimer_stop(t->ptimer_wd); t->rw_wd_ctrl = value; } static void timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { Loading @@ -203,13 +265,15 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) case RW_TMR0_CTRL: D(printf ("RW_TMR0_CTRL=%x\n", value)); t->rw_tmr0_ctrl = value; update_ctrl(t); update_ctrl(t, 0); break; case RW_TMR1_DIV: t->rw_tmr1_div = value; break; case RW_TMR1_CTRL: D(printf ("RW_TMR1_CTRL=%x\n", value)); t->rw_tmr1_ctrl = value; update_ctrl(t, 1); break; case RW_INTR_MASK: D(printf ("RW_INTR_MASK=%x\n", value)); Loading @@ -217,7 +281,7 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) timer_update_irq(t); break; case RW_WD_CTRL: D(printf ("RW_WD_CTRL=%x\n", value)); timer_watchdog_update(t, value); break; case RW_ACK_INTR: t->rw_ack_intr = value; Loading @@ -243,6 +307,19 @@ static CPUWriteMemoryFunc *timer_write[] = { &timer_writel, }; static void etraxfs_timer_reset(void *opaque) { struct fs_timer_t *t = opaque; ptimer_stop(t->ptimer_t0); ptimer_stop(t->ptimer_t1); ptimer_stop(t->ptimer_wd); t->rw_wd_ctrl = 0; t->r_intr = 0; t->rw_intr_mask = 0; qemu_irq_lower(t->irq[0]); } void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, target_phys_addr_t base) { Loading @@ -253,12 +330,18 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, if (!t) return; t->bh = qemu_bh_new(timer_hit, t); t->ptimer = ptimer_init(t->bh); t->bh_t0 = qemu_bh_new(timer0_hit, t); t->bh_t1 = qemu_bh_new(timer1_hit, t); t->bh_wd = qemu_bh_new(watchdog_hit, t); t->ptimer_t0 = ptimer_init(t->bh_t0); t->ptimer_t1 = ptimer_init(t->bh_t1); t->ptimer_wd = ptimer_init(t->bh_wd); t->irq = irqs; t->env = env; t->base = base; timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t); cpu_register_physical_memory (base, 0x5c, timer_regs); qemu_register_reset(etraxfs_timer_reset, t); }