Revision cd1a3f68 hw/sh7750.c

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
}

Also available in: Unified diff