Revision 5439779e hw/etraxfs_timer.c

b/hw/etraxfs_timer.c
24 24
#include <stdio.h>
25 25
#include <sys/time.h>
26 26
#include "hw.h"
27
#include "sysemu.h"
27 28
#include "qemu-timer.h"
28 29

  
29 30
#define D(x)
......
36 37
#define RW_TMR1_CTRL  0x18
37 38
#define R_TIME        0x38
38 39
#define RW_WD_CTRL    0x40
40
#define R_WD_STAT     0x44
39 41
#define RW_INTR_MASK  0x48
40 42
#define RW_ACK_INTR   0x4c
41 43
#define R_INTR        0x50
......
46 48
	qemu_irq *irq;
47 49
	target_phys_addr_t base;
48 50

  
49
	QEMUBH *bh;
50
	ptimer_state *ptimer;
51
	QEMUBH *bh_t0;
52
	QEMUBH *bh_t1;
53
	QEMUBH *bh_wd;
54
	ptimer_state *ptimer_t0;
55
	ptimer_state *ptimer_t1;
56
	ptimer_state *ptimer_wd;
51 57
	struct timeval last;
52 58

  
53 59
	/* Control registers.  */
......
59 65
	uint32_t r_tmr1_data;
60 66
	uint32_t rw_tmr1_ctrl;
61 67

  
68
	uint32_t rw_wd_ctrl;
69

  
62 70
	uint32_t rw_intr_mask;
63 71
	uint32_t rw_ack_intr;
64 72
	uint32_t r_intr;
......
114 122
}
115 123

  
116 124
#define TIMER_SLOWDOWN 1
117
static void update_ctrl(struct fs_timer_t *t)
125
static void update_ctrl(struct fs_timer_t *t, int tnum)
118 126
{
119 127
	unsigned int op;
120 128
	unsigned int freq;
121 129
	unsigned int freq_hz;
122 130
	unsigned int div;
131
	uint32_t ctrl;
132
	ptimer_state *timer;
133

  
134
	if (tnum == 0) {
135
		ctrl = t->rw_tmr0_ctrl;
136
		div = t->rw_tmr0_div;
137
		timer = t->ptimer_t0;
138
	} else {
139
		ctrl = t->rw_tmr1_ctrl;
140
		div = t->rw_tmr1_div;
141
		timer = t->ptimer_t1;
142
	}
143

  
123 144

  
124
	op = t->rw_tmr0_ctrl & 3;
125
	freq = t->rw_tmr0_ctrl >> 2;
145
	op = ctrl & 3;
146
	freq = ctrl >> 2;
126 147
	freq_hz = 32000000;
127 148

  
128 149
	switch (freq)
......
134 155
	case 4: freq_hz =  29493000; break;
135 156
	case 5: freq_hz =  32000000; break;
136 157
	case 6: freq_hz =  32768000; break;
137
	case 7: freq_hz = 100000000; break;
158
	case 7: freq_hz = 100001000; break;
138 159
	default:
139 160
		abort();
140 161
		break;
141 162
	}
142 163

  
143
	D(printf ("freq_hz=%d div=%d\n", freq_hz, t->rw_tmr0_div));
144
	div = t->rw_tmr0_div * TIMER_SLOWDOWN;
164
	D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
165
	div = div * TIMER_SLOWDOWN;
145 166
	div >>= 15;
146 167
	freq_hz >>= 15;
147
	ptimer_set_freq(t->ptimer, freq_hz);
148
	ptimer_set_limit(t->ptimer, div, 0);
168
	ptimer_set_freq(timer, freq_hz);
169
	ptimer_set_limit(timer, div, 0);
149 170

  
150 171
	switch (op)
151 172
	{
152 173
		case 0:
153 174
			/* Load.  */
154
			ptimer_set_limit(t->ptimer, div, 1);
155
			ptimer_run(t->ptimer, 1);
175
			ptimer_set_limit(timer, div, 1);
156 176
			break;
157 177
		case 1:
158 178
			/* Hold.  */
159
			ptimer_stop(t->ptimer);
179
			ptimer_stop(timer);
160 180
			break;
161 181
		case 2:
162 182
			/* Run.  */
163
			ptimer_run(t->ptimer, 0);
183
			ptimer_run(timer, 0);
164 184
			break;
165 185
		default:
166 186
			abort();
......
180 200
		qemu_irq_lower(t->irq[0]);
181 201
}
182 202

  
183
static void timer_hit(void *opaque)
203
static void timer0_hit(void *opaque)
184 204
{
185 205
	struct fs_timer_t *t = opaque;
186 206
	t->r_intr |= 1;
187 207
	timer_update_irq(t);
188 208
}
189 209

  
210
static void timer1_hit(void *opaque)
211
{
212
	struct fs_timer_t *t = opaque;
213
	t->r_intr |= 2;
214
	timer_update_irq(t);
215
}
216

  
217
static void watchdog_hit(void *opaque)
218
{
219
	qemu_system_reset_request();
220
}
221

  
222
static inline void timer_watchdog_update(struct fs_timer_t *t, uint32_t value)
223
{
224
	unsigned int wd_en = t->rw_wd_ctrl & (1 << 8);
225
	unsigned int wd_key = t->rw_wd_ctrl >> 9;
226
	unsigned int wd_cnt = t->rw_wd_ctrl & 511;
227
	unsigned int new_key = value >> 9 & ((1 << 7) - 1);
228
	unsigned int new_cmd = (value >> 8) & 1;
229

  
230
	/* If the watchdog is enabled, they written key must match the
231
	   complement of the previous.  */
232
	wd_key = ~wd_key & ((1 << 7) - 1);
233

  
234
	if (wd_en && wd_key != new_key)
235
		return;
236

  
237
	D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n", 
238
		 wd_en, new_key, wd_key, wd_cmd, wd_cnt));
239

  
240
	ptimer_set_freq(t->ptimer_wd, 760);
241
	if (wd_cnt == 0)
242
		wd_cnt = 256;
243
	ptimer_set_count(t->ptimer_wd, wd_cnt);
244
	if (new_cmd)
245
		ptimer_run(t->ptimer_wd, 1);
246
	else
247
		ptimer_stop(t->ptimer_wd);
248

  
249
	t->rw_wd_ctrl = value;
250
}
251

  
190 252
static void
191 253
timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
192 254
{
......
203 265
		case RW_TMR0_CTRL:
204 266
			D(printf ("RW_TMR0_CTRL=%x\n", value));
205 267
			t->rw_tmr0_ctrl = value;
206
			update_ctrl(t);
268
			update_ctrl(t, 0);
207 269
			break;
208 270
		case RW_TMR1_DIV:
209 271
			t->rw_tmr1_div = value;
210 272
			break;
211 273
		case RW_TMR1_CTRL:
212 274
			D(printf ("RW_TMR1_CTRL=%x\n", value));
275
			t->rw_tmr1_ctrl = value;
276
			update_ctrl(t, 1);
213 277
			break;
214 278
		case RW_INTR_MASK:
215 279
			D(printf ("RW_INTR_MASK=%x\n", value));
......
217 281
			timer_update_irq(t);
218 282
			break;
219 283
		case RW_WD_CTRL:
220
			D(printf ("RW_WD_CTRL=%x\n", value));
284
			timer_watchdog_update(t, value);
221 285
			break;
222 286
		case RW_ACK_INTR:
223 287
			t->rw_ack_intr = value;
......
232 296
}
233 297

  
234 298
static CPUReadMemoryFunc *timer_read[] = {
235
    &timer_rinvalid,
236
    &timer_rinvalid,
237
    &timer_readl,
299
	&timer_rinvalid,
300
	&timer_rinvalid,
301
	&timer_readl,
238 302
};
239 303

  
240 304
static CPUWriteMemoryFunc *timer_write[] = {
241
    &timer_winvalid,
242
    &timer_winvalid,
243
    &timer_writel,
305
	&timer_winvalid,
306
	&timer_winvalid,
307
	&timer_writel,
244 308
};
245 309

  
310
static void etraxfs_timer_reset(void *opaque)
311
{
312
	struct fs_timer_t *t = opaque;
313

  
314
	ptimer_stop(t->ptimer_t0);
315
	ptimer_stop(t->ptimer_t1);
316
	ptimer_stop(t->ptimer_wd);
317
	t->rw_wd_ctrl = 0;
318
	t->r_intr = 0;
319
	t->rw_intr_mask = 0;
320
	qemu_irq_lower(t->irq[0]);
321
}
322

  
246 323
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, 
247 324
			target_phys_addr_t base)
248 325
{
......
253 330
	if (!t)
254 331
		return;
255 332

  
256
	t->bh = qemu_bh_new(timer_hit, t);
257
	t->ptimer = ptimer_init(t->bh);
333
	t->bh_t0 = qemu_bh_new(timer0_hit, t);
334
	t->bh_t1 = qemu_bh_new(timer1_hit, t);
335
	t->bh_wd = qemu_bh_new(watchdog_hit, t);
336
	t->ptimer_t0 = ptimer_init(t->bh_t0);
337
	t->ptimer_t1 = ptimer_init(t->bh_t1);
338
	t->ptimer_wd = ptimer_init(t->bh_wd);
258 339
	t->irq = irqs;
259 340
	t->env = env;
260 341
	t->base = base;
261 342

  
262 343
	timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t);
263 344
	cpu_register_physical_memory (base, 0x5c, timer_regs);
345

  
346
	qemu_register_reset(etraxfs_timer_reset, t);
264 347
}

Also available in: Unified diff