Revision cd1a3f68

b/Makefile.target
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
b/hw/sh7750.c
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 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 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 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 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 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 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
}
b/hw/sh7750_regnames.c
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)
b/hw/sh7750_regs.h
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
 */
b/hw/sh_timer.c
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
}
b/vl.h
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

  

Also available in: Unified diff