Commit cd1a3f6840e9f4b57860ee0d151347e6ade73d11

Authored by ths
1 parent 0d78f544

Stand-alone TMU emulation code, by Magnus Damm.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3269 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
@@ -476,6 +476,7 @@ CPPFLAGS += -DHAS_AUDIO @@ -476,6 +476,7 @@ CPPFLAGS += -DHAS_AUDIO
476 endif 476 endif
477 ifeq ($(TARGET_BASE_ARCH), sh4) 477 ifeq ($(TARGET_BASE_ARCH), sh4)
478 VL_OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o 478 VL_OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
  479 +VL_OBJS+= sh_timer.o ptimer.o
479 endif 480 endif
480 ifeq ($(TARGET_BASE_ARCH), m68k) 481 ifeq ($(TARGET_BASE_ARCH), m68k)
481 VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o 482 VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
hw/sh7750.c
@@ -64,13 +64,6 @@ typedef struct SH7750State { @@ -64,13 +64,6 @@ typedef struct SH7750State {
64 uint8_t scbrr2; 64 uint8_t scbrr2;
65 fifo serial2_receive_fifo; 65 fifo serial2_receive_fifo;
66 fifo serial2_transmit_fifo; 66 fifo serial2_transmit_fifo;
67 - /* Timers */  
68 - uint8_t tstr;  
69 - /* Timer 0 */  
70 - QEMUTimer *timer0;  
71 - uint16_t tcr0;  
72 - uint32_t tcor0;  
73 - uint32_t tcnt0;  
74 /* IO ports */ 67 /* IO ports */
75 uint16_t gpioic; 68 uint16_t gpioic;
76 uint32_t pctra; 69 uint32_t pctra;
@@ -88,83 +81,8 @@ typedef struct SH7750State { @@ -88,83 +81,8 @@ typedef struct SH7750State {
88 sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */ 81 sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */
89 /* Cache */ 82 /* Cache */
90 uint32_t ccr; 83 uint32_t ccr;
91 -} SH7750State;  
92 -  
93 -/**********************************************************************  
94 - Timers  
95 -**********************************************************************/  
96 -  
97 -/* XXXXX At this time, timer0 works in underflow only mode, that is  
98 - the value of tcnt0 is read at alarm computation time and cannot  
99 - be read back by the guest OS */  
100 -  
101 -static void start_timer0(SH7750State * s)  
102 -{  
103 - uint64_t now, next, prescaler;  
104 -  
105 - if ((s->tcr0 & 6) == 6) {  
106 - fprintf(stderr, "rtc clock for timer 0 not supported\n");  
107 - assert(0);  
108 - }  
109 84
110 - if ((s->tcr0 & 7) == 5) {  
111 - fprintf(stderr, "timer 0 configuration not supported\n");  
112 - assert(0);  
113 - }  
114 -  
115 - if ((s->tcr0 & 4) == 4)  
116 - prescaler = 1024;  
117 - else  
118 - prescaler = 4 << (s->tcr0 & 3);  
119 -  
120 - now = qemu_get_clock(vm_clock);  
121 - /* XXXXX */  
122 - next =  
123 - now + muldiv64(prescaler * s->tcnt0, ticks_per_sec,  
124 - s->periph_freq);  
125 - if (next == now)  
126 - next = now + 1;  
127 - fprintf(stderr, "now=%016" PRIx64 ", next=%016" PRIx64 "\n", now, next);  
128 - fprintf(stderr, "timer will underflow in %f seconds\n",  
129 - (float) (next - now) / (float) ticks_per_sec);  
130 -  
131 - qemu_mod_timer(s->timer0, next);  
132 -}  
133 -  
134 -static void timer_start_changed(SH7750State * s)  
135 -{  
136 - if (s->tstr & SH7750_TSTR_STR0) {  
137 - start_timer0(s);  
138 - } else {  
139 - fprintf(stderr, "timer 0 is stopped\n");  
140 - qemu_del_timer(s->timer0);  
141 - }  
142 -}  
143 -  
144 -static void timer0_cb(void *opaque)  
145 -{  
146 - SH7750State *s = opaque;  
147 -  
148 - s->tcnt0 = (uint32_t) 0; /* XXXXX */  
149 - if (--s->tcnt0 == (uint32_t) - 1) {  
150 - fprintf(stderr, "timer 0 underflow\n");  
151 - s->tcnt0 = s->tcor0;  
152 - s->tcr0 |= SH7750_TCR_UNF;  
153 - if (s->tcr0 & SH7750_TCR_UNIE) {  
154 - fprintf(stderr,  
155 - "interrupt generation for timer 0 not supported\n");  
156 - assert(0);  
157 - }  
158 - }  
159 - start_timer0(s);  
160 -}  
161 -  
162 -static void init_timers(SH7750State * s)  
163 -{  
164 - s->tcor0 = 0xffffffff;  
165 - s->tcnt0 = 0xffffffff;  
166 - s->timer0 = qemu_new_timer(vm_clock, &timer0_cb, s);  
167 -} 85 +} SH7750State;
168 86
169 /********************************************************************** 87 /**********************************************************************
170 First serial port 88 First serial port
@@ -581,8 +499,6 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr) @@ -581,8 +499,6 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
581 fprintf(stderr, 499 fprintf(stderr,
582 "Read access to refresh count register, incrementing\n"); 500 "Read access to refresh count register, incrementing\n");
583 return s->rfcr++; 501 return s->rfcr++;
584 - case SH7750_TCR0_A7:  
585 - return s->tcr0;  
586 case SH7750_SCLSR2_A7: 502 case SH7750_SCLSR2_A7:
587 /* Read and clear overflow bit */ 503 /* Read and clear overflow bit */
588 r = s->sclsr2; 504 r = s->sclsr2;
@@ -649,10 +565,6 @@ static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr, @@ -649,10 +565,6 @@ static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr,
649 case SH7750_SCBRR2_A7: 565 case SH7750_SCBRR2_A7:
650 s->scbrr2 = mem_value; 566 s->scbrr2 = mem_value;
651 return; 567 return;
652 - case SH7750_TSTR_A7:  
653 - s->tstr = mem_value;  
654 - timer_start_changed(s);  
655 - return;  
656 case SH7750_SCSCR1_A7: 568 case SH7750_SCSCR1_A7:
657 s->scscr1 = mem_value; 569 s->scscr1 = mem_value;
658 scscr1_changed(s); 570 scscr1_changed(s);
@@ -721,9 +633,6 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr, @@ -721,9 +633,6 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr,
721 case SH7750_SCSMR2_A7: 633 case SH7750_SCSMR2_A7:
722 s->scsmr2 = mem_value; 634 s->scsmr2 = mem_value;
723 return; 635 return;
724 - case SH7750_TCR0_A7:  
725 - s->tcr0 = mem_value;  
726 - return;  
727 case SH7750_GPIOIC_A7: 636 case SH7750_GPIOIC_A7:
728 s->gpioic = mem_value; 637 s->gpioic = mem_value;
729 if (mem_value != 0) { 638 if (mem_value != 0) {
@@ -768,9 +677,6 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr, @@ -768,9 +677,6 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
768 s->portpullupb = portpullup(mem_value); 677 s->portpullupb = portpullup(mem_value);
769 portb_changed(s, temp); 678 portb_changed(s, temp);
770 return; 679 return;
771 - case SH7750_TCNT0_A7:  
772 - s->tcnt0 = mem_value & 0xf;  
773 - return;  
774 case SH7750_MMUCR_A7: 680 case SH7750_MMUCR_A7:
775 s->cpu->mmucr = mem_value; 681 s->cpu->mmucr = mem_value;
776 return; 682 return;
@@ -828,7 +734,11 @@ SH7750State *sh7750_init(CPUSH4State * cpu) @@ -828,7 +734,11 @@ SH7750State *sh7750_init(CPUSH4State * cpu)
828 sh7750_mem_read, 734 sh7750_mem_read,
829 sh7750_mem_write, s); 735 sh7750_mem_write, s);
830 cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory); 736 cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory);
831 - init_timers(s);  
832 init_serial_ports(s); 737 init_serial_ports(s);
  738 +
  739 + tmu012_init(0x1fd80000,
  740 + TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
  741 + s->periph_freq);
  742 + tmu012_init(0x1e100000, 0, s->periph_freq);
833 return s; 743 return s;
834 } 744 }
hw/sh7750_regnames.c
@@ -42,18 +42,6 @@ static regname_t regnames[] = { @@ -42,18 +42,6 @@ static regname_t regnames[] = {
42 REGNAME(SH7750_RMONAR_A7) 42 REGNAME(SH7750_RMONAR_A7)
43 REGNAME(SH7750_RCR1_A7) 43 REGNAME(SH7750_RCR1_A7)
44 REGNAME(SH7750_RCR2_A7) 44 REGNAME(SH7750_RCR2_A7)
45 - REGNAME(SH7750_TOCR_A7)  
46 - REGNAME(SH7750_TSTR_A7)  
47 - REGNAME(SH7750_TCOR0_A7)  
48 - REGNAME(SH7750_TCOR1_A7)  
49 - REGNAME(SH7750_TCOR2_A7)  
50 - REGNAME(SH7750_TCNT0_A7)  
51 - REGNAME(SH7750_TCNT1_A7)  
52 - REGNAME(SH7750_TCNT2_A7)  
53 - REGNAME(SH7750_TCR0_A7)  
54 - REGNAME(SH7750_TCR1_A7)  
55 - REGNAME(SH7750_TCR2_A7)  
56 - REGNAME(SH7750_TCPR2_A7)  
57 REGNAME(SH7750_BCR1_A7) 45 REGNAME(SH7750_BCR1_A7)
58 REGNAME(SH7750_BCR2_A7) 46 REGNAME(SH7750_BCR2_A7)
59 REGNAME(SH7750_WCR1_A7) 47 REGNAME(SH7750_WCR1_A7)
hw/sh7750_regs.h
@@ -524,94 +524,6 @@ @@ -524,94 +524,6 @@
524 year counters are stopped 524 year counters are stopped
525 1 - sec, min, hr, day-of-week, month, 525 1 - sec, min, hr, day-of-week, month,
526 year counters operate normally */ 526 year counters operate normally */
527 -  
528 -  
529 -/*  
530 - * Timer Unit (TMU)  
531 - */  
532 -/* Timer Output Control Register (byte) - TOCR */  
533 -#define SH7750_TOCR_REGOFS 0xD80000 /* offset */  
534 -#define SH7750_TOCR SH7750_P4_REG32(SH7750_TOCR_REGOFS)  
535 -#define SH7750_TOCR_A7 SH7750_A7_REG32(SH7750_TOCR_REGOFS)  
536 -#define SH7750_TOCR_TCOE 0x01 /* Timer Clock Pin Control:  
537 - 0 - TCLK is used as external clock  
538 - input or input capture control  
539 - 1 - TCLK is used as on-chip RTC  
540 - output clock pin */  
541 -  
542 -/* Timer Start Register (byte) - TSTR */  
543 -#define SH7750_TSTR_REGOFS 0xD80004 /* offset */  
544 -#define SH7750_TSTR SH7750_P4_REG32(SH7750_TSTR_REGOFS)  
545 -#define SH7750_TSTR_A7 SH7750_A7_REG32(SH7750_TSTR_REGOFS)  
546 -#define SH7750_TSTR_STR2 0x04 /* TCNT2 performs count operations */  
547 -#define SH7750_TSTR_STR1 0x02 /* TCNT1 performs count operations */  
548 -#define SH7750_TSTR_STR0 0x01 /* TCNT0 performs count operations */  
549 -#define SH7750_TSTR_STR(n) (1 << (n))  
550 -  
551 -/* Timer Constant Register - TCOR0, TCOR1, TCOR2 */  
552 -#define SH7750_TCOR_REGOFS(n) (0xD80008 + ((n)*12)) /* offset */  
553 -#define SH7750_TCOR(n) SH7750_P4_REG32(SH7750_TCOR_REGOFS(n))  
554 -#define SH7750_TCOR_A7(n) SH7750_A7_REG32(SH7750_TCOR_REGOFS(n))  
555 -#define SH7750_TCOR0 SH7750_TCOR(0)  
556 -#define SH7750_TCOR1 SH7750_TCOR(1)  
557 -#define SH7750_TCOR2 SH7750_TCOR(2)  
558 -#define SH7750_TCOR0_A7 SH7750_TCOR_A7(0)  
559 -#define SH7750_TCOR1_A7 SH7750_TCOR_A7(1)  
560 -#define SH7750_TCOR2_A7 SH7750_TCOR_A7(2)  
561 -  
562 -/* Timer Counter Register - TCNT0, TCNT1, TCNT2 */  
563 -#define SH7750_TCNT_REGOFS(n) (0xD8000C + ((n)*12)) /* offset */  
564 -#define SH7750_TCNT(n) SH7750_P4_REG32(SH7750_TCNT_REGOFS(n))  
565 -#define SH7750_TCNT_A7(n) SH7750_A7_REG32(SH7750_TCNT_REGOFS(n))  
566 -#define SH7750_TCNT0 SH7750_TCNT(0)  
567 -#define SH7750_TCNT1 SH7750_TCNT(1)  
568 -#define SH7750_TCNT2 SH7750_TCNT(2)  
569 -#define SH7750_TCNT0_A7 SH7750_TCNT_A7(0)  
570 -#define SH7750_TCNT1_A7 SH7750_TCNT_A7(1)  
571 -#define SH7750_TCNT2_A7 SH7750_TCNT_A7(2)  
572 -  
573 -/* Timer Control Register (half) - TCR0, TCR1, TCR2 */  
574 -#define SH7750_TCR_REGOFS(n) (0xD80010 + ((n)*12)) /* offset */  
575 -#define SH7750_TCR(n) SH7750_P4_REG32(SH7750_TCR_REGOFS(n))  
576 -#define SH7750_TCR_A7(n) SH7750_A7_REG32(SH7750_TCR_REGOFS(n))  
577 -#define SH7750_TCR0 SH7750_TCR(0)  
578 -#define SH7750_TCR1 SH7750_TCR(1)  
579 -#define SH7750_TCR2 SH7750_TCR(2)  
580 -#define SH7750_TCR0_A7 SH7750_TCR_A7(0)  
581 -#define SH7750_TCR1_A7 SH7750_TCR_A7(1)  
582 -#define SH7750_TCR2_A7 SH7750_TCR_A7(2)  
583 -  
584 -#define SH7750_TCR2_ICPF 0x200 /* Input Capture Interrupt Flag  
585 - (1 - input capture has occured) */  
586 -#define SH7750_TCR_UNF 0x100 /* Underflow flag */  
587 -#define SH7750_TCR2_ICPE 0x0C0 /* Input Capture Control: */  
588 -#define SH7750_TCR2_ICPE_DIS 0x000 /* Input Capture function is not used */  
589 -#define SH7750_TCR2_ICPE_NOINT 0x080 /* Input Capture function is used, but  
590 - input capture interrupt is not  
591 - enabled */  
592 -#define SH7750_TCR2_ICPE_INT 0x0C0 /* Input Capture function is used,  
593 - input capture interrupt enabled */  
594 -#define SH7750_TCR_UNIE 0x020 /* Underflow Interrupt Control  
595 - (1 - underflow interrupt enabled) */  
596 -#define SH7750_TCR_CKEG 0x018 /* Clock Edge selection: */  
597 -#define SH7750_TCR_CKEG_RAISE 0x000 /* Count/capture on rising edge */  
598 -#define SH7750_TCR_CKEG_FALL 0x008 /* Count/capture on falling edge */  
599 -#define SH7750_TCR_CKEG_BOTH 0x018 /* Count/capture on both rising and  
600 - falling edges */  
601 -#define SH7750_TCR_TPSC 0x007 /* Timer prescaler */  
602 -#define SH7750_TCR_TPSC_DIV4 0x000 /* Counts on peripheral clock/4 */  
603 -#define SH7750_TCR_TPSC_DIV16 0x001 /* Counts on peripheral clock/16 */  
604 -#define SH7750_TCR_TPSC_DIV64 0x002 /* Counts on peripheral clock/64 */  
605 -#define SH7750_TCR_TPSC_DIV256 0x003 /* Counts on peripheral clock/256 */  
606 -#define SH7750_TCR_TPSC_DIV1024 0x004 /* Counts on peripheral clock/1024 */  
607 -#define SH7750_TCR_TPSC_RTC 0x006 /* Counts on on-chip RTC output clk */  
608 -#define SH7750_TCR_TPSC_EXT 0x007 /* Counts on external clock */  
609 -  
610 -/* Input Capture Register (read-only) - TCPR2 */  
611 -#define SH7750_TCPR2_REGOFS 0xD8002C /* offset */  
612 -#define SH7750_TCPR2 SH7750_P4_REG32(SH7750_TCPR2_REGOFS)  
613 -#define SH7750_TCPR2_A7 SH7750_A7_REG32(SH7750_TCPR2_REGOFS)  
614 -  
615 /* 527 /*
616 * Bus State Controller - BSC 528 * Bus State Controller - BSC
617 */ 529 */
hw/sh_timer.c 0 โ†’ 100644
  1 +/*
  2 + * SuperH Timer modules.
  3 + *
  4 + * Copyright (c) 2007 Magnus Damm
  5 + * Based on arm_timer.c by Paul Brook
  6 + * Copyright (c) 2005-2006 CodeSourcery.
  7 + *
  8 + * This code is licenced under the GPL.
  9 + */
  10 +
  11 +#include "vl.h"
  12 +
  13 +//#define DEBUG_TIMER
  14 +
  15 +#define TIMER_TCR_TPSC (7 << 0)
  16 +#define TIMER_TCR_CKEG (3 << 3)
  17 +#define TIMER_TCR_UNIE (1 << 5)
  18 +#define TIMER_TCR_ICPE (3 << 6)
  19 +#define TIMER_TCR_UNF (1 << 8)
  20 +#define TIMER_TCR_ICPF (1 << 9)
  21 +#define TIMER_TCR_RESERVED (0x3f << 10)
  22 +
  23 +#define TIMER_FEAT_CAPT (1 << 0)
  24 +#define TIMER_FEAT_EXTCLK (1 << 1)
  25 +
  26 +typedef struct {
  27 + ptimer_state *timer;
  28 + uint32_t tcnt;
  29 + uint32_t tcor;
  30 + uint32_t tcr;
  31 + uint32_t tcpr;
  32 + int freq;
  33 + int int_level;
  34 + int feat;
  35 + int enabled;
  36 + qemu_irq irq;
  37 +} sh_timer_state;
  38 +
  39 +/* Check all active timers, and schedule the next timer interrupt. */
  40 +
  41 +static void sh_timer_update(sh_timer_state *s)
  42 +{
  43 +#if 0 /* not yet */
  44 + /* Update interrupts. */
  45 + if (s->int_level && (s->tcr & TIMER_TCR_UNIE)) {
  46 + qemu_irq_raise(s->irq);
  47 + } else {
  48 + qemu_irq_lower(s->irq);
  49 + }
  50 +#endif
  51 +}
  52 +
  53 +uint32_t sh_timer_read(void *opaque, target_phys_addr_t offset)
  54 +{
  55 + sh_timer_state *s = (sh_timer_state *)opaque;
  56 +
  57 + switch (offset >> 2) {
  58 + case 0:
  59 + return s->tcor;
  60 + case 1:
  61 + return ptimer_get_count(s->timer);
  62 + case 2:
  63 + return s->tcr | (s->int_level ? TIMER_TCR_UNF : 0);
  64 + case 3:
  65 + if (s->feat & TIMER_FEAT_CAPT)
  66 + return s->tcpr;
  67 + default:
  68 + cpu_abort (cpu_single_env, "sh_timer_read: Bad offset %x\n",
  69 + (int)offset);
  70 + return 0;
  71 + }
  72 +}
  73 +
  74 +static void sh_timer_write(void *opaque, target_phys_addr_t offset,
  75 + uint32_t value)
  76 +{
  77 + sh_timer_state *s = (sh_timer_state *)opaque;
  78 + int freq;
  79 +
  80 + switch (offset >> 2) {
  81 + case 0:
  82 + s->tcor = value;
  83 + ptimer_set_limit(s->timer, s->tcor, 0);
  84 + break;
  85 + case 1:
  86 + s->tcnt = value;
  87 + ptimer_set_count(s->timer, s->tcnt);
  88 + break;
  89 + case 2:
  90 + if (s->enabled) {
  91 + /* Pause the timer if it is running. This may cause some
  92 + inaccuracy dure to rounding, but avoids a whole lot of other
  93 + messyness. */
  94 + ptimer_stop(s->timer);
  95 + }
  96 + freq = s->freq;
  97 + /* ??? Need to recalculate expiry time after changing divisor. */
  98 + switch (value & TIMER_TCR_TPSC) {
  99 + case 0: freq >>= 2; break;
  100 + case 1: freq >>= 4; break;
  101 + case 2: freq >>= 6; break;
  102 + case 3: freq >>= 8; break;
  103 + case 4: freq >>= 10; break;
  104 + case 6:
  105 + case 7: if (s->feat & TIMER_FEAT_EXTCLK) break;
  106 + default: cpu_abort (cpu_single_env,
  107 + "sh_timer_write: Reserved TPSC value\n"); break;
  108 + }
  109 + switch ((value & TIMER_TCR_CKEG) >> 3) {
  110 + case 0: break;
  111 + case 1:
  112 + case 2:
  113 + case 3: if (s->feat & TIMER_FEAT_EXTCLK) break;
  114 + default: cpu_abort (cpu_single_env,
  115 + "sh_timer_write: Reserved CKEG value\n"); break;
  116 + }
  117 + switch ((value & TIMER_TCR_ICPE) >> 6) {
  118 + case 0: break;
  119 + case 2:
  120 + case 3: if (s->feat & TIMER_FEAT_CAPT) break;
  121 + default: cpu_abort (cpu_single_env,
  122 + "sh_timer_write: Reserved ICPE value\n"); break;
  123 + }
  124 + if ((value & TIMER_TCR_UNF) == 0)
  125 + s->int_level = 0;
  126 +
  127 + value &= ~TIMER_TCR_UNF;
  128 +
  129 + if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT)))
  130 + cpu_abort (cpu_single_env,
  131 + "sh_timer_write: Reserved ICPF value\n");
  132 +
  133 + value &= ~TIMER_TCR_ICPF; /* capture not supported */
  134 +
  135 + if (value & TIMER_TCR_RESERVED)
  136 + cpu_abort (cpu_single_env,
  137 + "sh_timer_write: Reserved TCR bits set\n");
  138 + s->tcr = value;
  139 + ptimer_set_limit(s->timer, s->tcor, 0);
  140 + ptimer_set_freq(s->timer, freq);
  141 + if (s->enabled) {
  142 + /* Restart the timer if still enabled. */
  143 + ptimer_run(s->timer, 0);
  144 + }
  145 + break;
  146 + case 3:
  147 + if (s->feat & TIMER_FEAT_CAPT) {
  148 + s->tcpr = value;
  149 + break;
  150 + }
  151 + default:
  152 + cpu_abort (cpu_single_env, "sh_timer_write: Bad offset %x\n",
  153 + (int)offset);
  154 + }
  155 + sh_timer_update(s);
  156 +}
  157 +
  158 +static void sh_timer_start_stop(void *opaque, int enable)
  159 +{
  160 + sh_timer_state *s = (sh_timer_state *)opaque;
  161 +
  162 +#ifdef DEBUG_TIMER
  163 + printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled);
  164 +#endif
  165 +
  166 + if (s->enabled && !enable) {
  167 + ptimer_stop(s->timer);
  168 + }
  169 + if (!s->enabled && enable) {
  170 + ptimer_run(s->timer, 0);
  171 + }
  172 + s->enabled = !!enable;
  173 +
  174 +#ifdef DEBUG_TIMER
  175 + printf("sh_timer_start_stop done %d\n", s->enabled);
  176 +#endif
  177 +}
  178 +
  179 +static void sh_timer_tick(void *opaque)
  180 +{
  181 + sh_timer_state *s = (sh_timer_state *)opaque;
  182 + s->int_level = s->enabled;
  183 + sh_timer_update(s);
  184 +}
  185 +
  186 +static void *sh_timer_init(uint32_t freq, int feat)
  187 +{
  188 + sh_timer_state *s;
  189 + QEMUBH *bh;
  190 +
  191 + s = (sh_timer_state *)qemu_mallocz(sizeof(sh_timer_state));
  192 + s->freq = freq;
  193 + s->feat = feat;
  194 + s->tcor = 0xffffffff;
  195 + s->tcnt = 0xffffffff;
  196 + s->tcpr = 0xdeadbeef;
  197 + s->tcor = 0;
  198 + s->enabled = 0;
  199 +
  200 + bh = qemu_bh_new(sh_timer_tick, s);
  201 + s->timer = ptimer_init(bh);
  202 + /* ??? Save/restore. */
  203 + return s;
  204 +}
  205 +
  206 +typedef struct {
  207 + void *timer[3];
  208 + int level[3];
  209 + uint32_t tocr;
  210 + uint32_t tstr;
  211 + target_phys_addr_t base;
  212 + int feat;
  213 +} tmu012_state;
  214 +
  215 +static uint32_t tmu012_read(void *opaque, target_phys_addr_t offset)
  216 +{
  217 + tmu012_state *s = (tmu012_state *)opaque;
  218 +
  219 +#ifdef DEBUG_TIMER
  220 + printf("tmu012_read 0x%lx\n", (unsigned long) offset);
  221 +#endif
  222 + offset -= s->base;
  223 +
  224 + if (offset >= 0x20) {
  225 + if (!(s->feat & TMU012_FEAT_3CHAN))
  226 + cpu_abort (cpu_single_env, "tmu012_write: Bad channel offset %x\n",
  227 + (int)offset);
  228 + return sh_timer_read(s->timer[2], offset - 0x20);
  229 + }
  230 +
  231 + if (offset >= 0x14)
  232 + return sh_timer_read(s->timer[1], offset - 0x14);
  233 +
  234 + if (offset >= 0x08)
  235 + return sh_timer_read(s->timer[0], offset - 0x08);
  236 +
  237 + if (offset == 4)
  238 + return s->tstr;
  239 +
  240 + if ((s->feat & TMU012_FEAT_TOCR) && offset == 0)
  241 + return s->tocr;
  242 +
  243 + cpu_abort (cpu_single_env, "tmu012_write: Bad offset %x\n",
  244 + (int)offset);
  245 + return 0;
  246 +}
  247 +
  248 +static void tmu012_write(void *opaque, target_phys_addr_t offset,
  249 + uint32_t value)
  250 +{
  251 + tmu012_state *s = (tmu012_state *)opaque;
  252 +
  253 +#ifdef DEBUG_TIMER
  254 + printf("tmu012_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
  255 +#endif
  256 + offset -= s->base;
  257 +
  258 + if (offset >= 0x20) {
  259 + if (!(s->feat & TMU012_FEAT_3CHAN))
  260 + cpu_abort (cpu_single_env, "tmu012_write: Bad channel offset %x\n",
  261 + (int)offset);
  262 + sh_timer_write(s->timer[2], offset - 0x20, value);
  263 + return;
  264 + }
  265 +
  266 + if (offset >= 0x14) {
  267 + sh_timer_write(s->timer[1], offset - 0x14, value);
  268 + return;
  269 + }
  270 +
  271 + if (offset >= 0x08) {
  272 + sh_timer_write(s->timer[0], offset - 0x08, value);
  273 + return;
  274 + }
  275 +
  276 + if (offset == 4) {
  277 + sh_timer_start_stop(s->timer[0], value & (1 << 0));
  278 + sh_timer_start_stop(s->timer[1], value & (1 << 1));
  279 + if (s->feat & TMU012_FEAT_3CHAN)
  280 + sh_timer_start_stop(s->timer[2], value & (1 << 2));
  281 + else
  282 + if (value & (1 << 2))
  283 + cpu_abort (cpu_single_env, "tmu012_write: Bad channel\n");
  284 +
  285 + s->tstr = value;
  286 + return;
  287 + }
  288 +
  289 + if ((s->feat & TMU012_FEAT_TOCR) && offset == 0) {
  290 + s->tocr = value & (1 << 0);
  291 + }
  292 +}
  293 +
  294 +static CPUReadMemoryFunc *tmu012_readfn[] = {
  295 + tmu012_read,
  296 + tmu012_read,
  297 + tmu012_read
  298 +};
  299 +
  300 +static CPUWriteMemoryFunc *tmu012_writefn[] = {
  301 + tmu012_write,
  302 + tmu012_write,
  303 + tmu012_write
  304 +};
  305 +
  306 +void tmu012_init(uint32_t base, int feat, uint32_t freq)
  307 +{
  308 + int iomemtype;
  309 + tmu012_state *s;
  310 + int timer_feat = (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0;
  311 +
  312 + s = (tmu012_state *)qemu_mallocz(sizeof(tmu012_state));
  313 + s->base = base;
  314 + s->feat = feat;
  315 + s->timer[0] = sh_timer_init(freq, timer_feat);
  316 + s->timer[1] = sh_timer_init(freq, timer_feat);
  317 + if (feat & TMU012_FEAT_3CHAN)
  318 + s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT);
  319 + iomemtype = cpu_register_io_memory(0, tmu012_readfn,
  320 + tmu012_writefn, s);
  321 + cpu_register_physical_memory(base, 0x00001000, iomemtype);
  322 + /* ??? Save/restore. */
  323 +}
@@ -1517,6 +1517,12 @@ typedef struct { @@ -1517,6 +1517,12 @@ typedef struct {
1517 1517
1518 int sh7750_register_io_device(struct SH7750State *s, 1518 int sh7750_register_io_device(struct SH7750State *s,
1519 sh7750_io_device * device); 1519 sh7750_io_device * device);
  1520 +/* sh_timer.c */
  1521 +#define TMU012_FEAT_TOCR (1 << 0)
  1522 +#define TMU012_FEAT_3CHAN (1 << 1)
  1523 +#define TMU012_FEAT_EXTCLK (1 << 2)
  1524 +void tmu012_init(uint32_t base, int feat, uint32_t freq);
  1525 +
1520 /* tc58128.c */ 1526 /* tc58128.c */
1521 int tc58128_init(struct SH7750State *s, char *zone1, char *zone2); 1527 int tc58128_init(struct SH7750State *s, char *zone1, char *zone2);
1522 1528