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 476 endif
477 477 ifeq ($(TARGET_BASE_ARCH), sh4)
478 478 VL_OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
  479 +VL_OBJS+= sh_timer.o ptimer.o
479 480 endif
480 481 ifeq ($(TARGET_BASE_ARCH), m68k)
481 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 64 uint8_t scbrr2;
65 65 fifo serial2_receive_fifo;
66 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 67 /* IO ports */
75 68 uint16_t gpioic;
76 69 uint32_t pctra;
... ... @@ -88,83 +81,8 @@ typedef struct SH7750State {
88 81 sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */
89 82 /* Cache */
90 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 88 First serial port
... ... @@ -581,8 +499,6 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
581 499 fprintf(stderr,
582 500 "Read access to refresh count register, incrementing\n");
583 501 return s->rfcr++;
584   - case SH7750_TCR0_A7:
585   - return s->tcr0;
586 502 case SH7750_SCLSR2_A7:
587 503 /* Read and clear overflow bit */
588 504 r = s->sclsr2;
... ... @@ -649,10 +565,6 @@ static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr,
649 565 case SH7750_SCBRR2_A7:
650 566 s->scbrr2 = mem_value;
651 567 return;
652   - case SH7750_TSTR_A7:
653   - s->tstr = mem_value;
654   - timer_start_changed(s);
655   - return;
656 568 case SH7750_SCSCR1_A7:
657 569 s->scscr1 = mem_value;
658 570 scscr1_changed(s);
... ... @@ -721,9 +633,6 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr,
721 633 case SH7750_SCSMR2_A7:
722 634 s->scsmr2 = mem_value;
723 635 return;
724   - case SH7750_TCR0_A7:
725   - s->tcr0 = mem_value;
726   - return;
727 636 case SH7750_GPIOIC_A7:
728 637 s->gpioic = mem_value;
729 638 if (mem_value != 0) {
... ... @@ -768,9 +677,6 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
768 677 s->portpullupb = portpullup(mem_value);
769 678 portb_changed(s, temp);
770 679 return;
771   - case SH7750_TCNT0_A7:
772   - s->tcnt0 = mem_value & 0xf;
773   - return;
774 680 case SH7750_MMUCR_A7:
775 681 s->cpu->mmucr = mem_value;
776 682 return;
... ... @@ -828,7 +734,11 @@ SH7750State *sh7750_init(CPUSH4State * cpu)
828 734 sh7750_mem_read,
829 735 sh7750_mem_write, s);
830 736 cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory);
831   - init_timers(s);
832 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 743 return s;
834 744 }
... ...
hw/sh7750_regnames.c
... ... @@ -42,18 +42,6 @@ static regname_t regnames[] = {
42 42 REGNAME(SH7750_RMONAR_A7)
43 43 REGNAME(SH7750_RCR1_A7)
44 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 45 REGNAME(SH7750_BCR1_A7)
58 46 REGNAME(SH7750_BCR2_A7)
59 47 REGNAME(SH7750_WCR1_A7)
... ...
hw/sh7750_regs.h
... ... @@ -524,94 +524,6 @@
524 524 year counters are stopped
525 525 1 - sec, min, hr, day-of-week, month,
526 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 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 1517  
1518 1518 int sh7750_register_io_device(struct SH7750State *s,
1519 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 1526 /* tc58128.c */
1521 1527 int tc58128_init(struct SH7750State *s, char *zone1, char *zone2);
1522 1528  
... ...