|
|
1.1 root 1: /*
2: * QEMU Sparc SLAVIO timer controller emulation
3: *
4: * Copyright (c) 2003-2005 Fabrice Bellard
1.1.1.4 root 5: *
1.1 root 6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
1.1.1.6 root 24:
1.1.1.4 root 25: #include "sun4m.h"
26: #include "qemu-timer.h"
1.1.1.6 root 27: #include "sysbus.h"
1.1.1.9 root 28: #include "trace.h"
1.1 root 29:
30: /*
31: * Registers of hardware timer in sun4m.
32: *
33: * This is the timer/counter part of chip STP2001 (Slave I/O), also
34: * produced as NCR89C105. See
35: * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
1.1.1.4 root 36: *
1.1 root 37: * The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
38: * are zero. Bit 31 is 1 when count has been reached.
39: *
1.1.1.2 root 40: * Per-CPU timers interrupt local CPU, system timer uses normal
41: * interrupt routing.
42: *
1.1 root 43: */
44:
1.1.1.4 root 45: #define MAX_CPUS 16
46:
1.1.1.7 root 47: typedef struct CPUTimerState {
1.1.1.4 root 48: qemu_irq irq;
49: ptimer_state *timer;
50: uint32_t count, counthigh, reached;
1.1.1.10! root 51: /* processor only */
1.1.1.5 root 52: uint32_t running;
1.1.1.10! root 53: uint64_t limit;
1.1.1.7 root 54: } CPUTimerState;
55:
56: typedef struct SLAVIO_TIMERState {
57: SysBusDevice busdev;
58: uint32_t num_cpus;
59: uint32_t cputimer_mode;
1.1.1.10! root 60: CPUTimerState cputimer[MAX_CPUS + 1];
1.1 root 61: } SLAVIO_TIMERState;
62:
1.1.1.7 root 63: typedef struct TimerContext {
64: SLAVIO_TIMERState *s;
65: unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
66: } TimerContext;
67:
1.1.1.4 root 68: #define SYS_TIMER_SIZE 0x14
69: #define CPU_TIMER_SIZE 0x10
70:
71: #define TIMER_LIMIT 0
72: #define TIMER_COUNTER 1
73: #define TIMER_COUNTER_NORST 2
74: #define TIMER_STATUS 3
75: #define TIMER_MODE 4
76:
77: #define TIMER_COUNT_MASK32 0xfffffe00
78: #define TIMER_LIMIT_MASK32 0x7fffffff
79: #define TIMER_MAX_COUNT64 0x7ffffffffffffe00ULL
80: #define TIMER_MAX_COUNT32 0x7ffffe00ULL
81: #define TIMER_REACHED 0x80000000
82: #define TIMER_PERIOD 500ULL // 500ns
1.1.1.8 root 83: #define LIMIT_TO_PERIODS(l) (((l) >> 9) - 1)
84: #define PERIODS_TO_LIMIT(l) (((l) + 1) << 9)
1.1.1.4 root 85:
1.1.1.7 root 86: static int slavio_timer_is_user(TimerContext *tc)
1.1.1.4 root 87: {
1.1.1.7 root 88: SLAVIO_TIMERState *s = tc->s;
89: unsigned int timer_index = tc->timer_index;
90:
91: return timer_index != 0 && (s->cputimer_mode & (1 << (timer_index - 1)));
1.1.1.4 root 92: }
1.1 root 93:
94: // Update count, set irq, update expire_time
1.1.1.4 root 95: // Convert from ptimer countdown units
1.1.1.7 root 96: static void slavio_timer_get_out(CPUTimerState *t)
1.1 root 97: {
1.1.1.4 root 98: uint64_t count, limit;
1.1 root 99:
1.1.1.7 root 100: if (t->limit == 0) { /* free-run system or processor counter */
1.1.1.4 root 101: limit = TIMER_MAX_COUNT32;
1.1.1.7 root 102: } else {
103: limit = t->limit;
104: }
105: count = limit - PERIODS_TO_LIMIT(ptimer_get_count(t->timer));
1.1 root 106:
1.1.1.9 root 107: trace_slavio_timer_get_out(t->limit, t->counthigh, t->count);
1.1.1.7 root 108: t->count = count & TIMER_COUNT_MASK32;
109: t->counthigh = count >> 32;
1.1 root 110: }
111:
112: // timer callback
113: static void slavio_timer_irq(void *opaque)
114: {
1.1.1.7 root 115: TimerContext *tc = opaque;
116: SLAVIO_TIMERState *s = tc->s;
117: CPUTimerState *t = &s->cputimer[tc->timer_index];
118:
119: slavio_timer_get_out(t);
1.1.1.9 root 120: trace_slavio_timer_irq(t->counthigh, t->count);
1.1.1.8 root 121: /* if limit is 0 (free-run), there will be no match */
122: if (t->limit != 0) {
123: t->reached = TIMER_REACHED;
124: }
125: /* there is no interrupt if user timer or free-run */
126: if (!slavio_timer_is_user(tc) && t->limit != 0) {
1.1.1.7 root 127: qemu_irq_raise(t->irq);
128: }
1.1 root 129: }
130:
131: static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
132: {
1.1.1.7 root 133: TimerContext *tc = opaque;
134: SLAVIO_TIMERState *s = tc->s;
1.1.1.4 root 135: uint32_t saddr, ret;
1.1.1.7 root 136: unsigned int timer_index = tc->timer_index;
137: CPUTimerState *t = &s->cputimer[timer_index];
1.1 root 138:
1.1.1.5 root 139: saddr = addr >> 2;
1.1 root 140: switch (saddr) {
1.1.1.4 root 141: case TIMER_LIMIT:
142: // read limit (system counter mode) or read most signifying
143: // part of counter (user mode)
1.1.1.7 root 144: if (slavio_timer_is_user(tc)) {
1.1.1.4 root 145: // read user timer MSW
1.1.1.7 root 146: slavio_timer_get_out(t);
147: ret = t->counthigh | t->reached;
1.1.1.4 root 148: } else {
149: // read limit
150: // clear irq
1.1.1.7 root 151: qemu_irq_lower(t->irq);
152: t->reached = 0;
153: ret = t->limit & TIMER_LIMIT_MASK32;
1.1.1.4 root 154: }
155: break;
156: case TIMER_COUNTER:
157: // read counter and reached bit (system mode) or read lsbits
158: // of counter (user mode)
1.1.1.7 root 159: slavio_timer_get_out(t);
160: if (slavio_timer_is_user(tc)) { // read user timer LSW
161: ret = t->count & TIMER_MAX_COUNT64;
162: } else { // read limit
163: ret = (t->count & TIMER_MAX_COUNT32) |
164: t->reached;
165: }
1.1.1.4 root 166: break;
167: case TIMER_STATUS:
168: // only available in processor counter/timer
169: // read start/stop status
1.1.1.7 root 170: if (timer_index > 0) {
171: ret = t->running;
172: } else {
173: ret = 0;
174: }
1.1.1.4 root 175: break;
176: case TIMER_MODE:
177: // only available in system counter
178: // read user/system mode
1.1.1.7 root 179: ret = s->cputimer_mode;
1.1.1.4 root 180: break;
1.1 root 181: default:
1.1.1.9 root 182: trace_slavio_timer_mem_readl_invalid(addr);
1.1.1.4 root 183: ret = 0;
184: break;
1.1 root 185: }
1.1.1.9 root 186: trace_slavio_timer_mem_readl(addr, ret);
1.1.1.4 root 187: return ret;
1.1 root 188: }
189:
1.1.1.4 root 190: static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
191: uint32_t val)
1.1 root 192: {
1.1.1.7 root 193: TimerContext *tc = opaque;
194: SLAVIO_TIMERState *s = tc->s;
1.1 root 195: uint32_t saddr;
1.1.1.7 root 196: unsigned int timer_index = tc->timer_index;
197: CPUTimerState *t = &s->cputimer[timer_index];
1.1 root 198:
1.1.1.9 root 199: trace_slavio_timer_mem_writel(addr, val);
1.1.1.5 root 200: saddr = addr >> 2;
1.1 root 201: switch (saddr) {
1.1.1.4 root 202: case TIMER_LIMIT:
1.1.1.7 root 203: if (slavio_timer_is_user(tc)) {
1.1.1.5 root 204: uint64_t count;
205:
1.1.1.4 root 206: // set user counter MSW, reset counter
1.1.1.7 root 207: t->limit = TIMER_MAX_COUNT64;
208: t->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
209: t->reached = 0;
210: count = ((uint64_t)t->counthigh << 32) | t->count;
1.1.1.9 root 211: trace_slavio_timer_mem_writel_limit(timer_index, count);
1.1.1.7 root 212: ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
1.1.1.4 root 213: } else {
214: // set limit, reset counter
1.1.1.7 root 215: qemu_irq_lower(t->irq);
216: t->limit = val & TIMER_MAX_COUNT32;
217: if (t->timer) {
218: if (t->limit == 0) { /* free-run */
219: ptimer_set_limit(t->timer,
1.1.1.5 root 220: LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
1.1.1.7 root 221: } else {
222: ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
223: }
1.1.1.4 root 224: }
225: }
226: break;
227: case TIMER_COUNTER:
1.1.1.7 root 228: if (slavio_timer_is_user(tc)) {
1.1.1.5 root 229: uint64_t count;
230:
1.1.1.4 root 231: // set user counter LSW, reset counter
1.1.1.7 root 232: t->limit = TIMER_MAX_COUNT64;
233: t->count = val & TIMER_MAX_COUNT64;
234: t->reached = 0;
235: count = ((uint64_t)t->counthigh) << 32 | t->count;
1.1.1.9 root 236: trace_slavio_timer_mem_writel_limit(timer_index, count);
1.1.1.7 root 237: ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
1.1.1.9 root 238: } else {
239: trace_slavio_timer_mem_writel_counter_invalid();
240: }
1.1.1.4 root 241: break;
242: case TIMER_COUNTER_NORST:
243: // set limit without resetting counter
1.1.1.7 root 244: t->limit = val & TIMER_MAX_COUNT32;
245: if (t->limit == 0) { /* free-run */
246: ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
247: } else {
248: ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
1.1.1.4 root 249: }
250: break;
251: case TIMER_STATUS:
1.1.1.7 root 252: if (slavio_timer_is_user(tc)) {
1.1.1.4 root 253: // start/stop user counter
1.1.1.7 root 254: if ((val & 1) && !t->running) {
1.1.1.9 root 255: trace_slavio_timer_mem_writel_status_start(timer_index);
1.1.1.7 root 256: ptimer_run(t->timer, 0);
257: t->running = 1;
258: } else if (!(val & 1) && t->running) {
1.1.1.9 root 259: trace_slavio_timer_mem_writel_status_stop(timer_index);
1.1.1.7 root 260: ptimer_stop(t->timer);
261: t->running = 0;
1.1.1.4 root 262: }
263: }
264: break;
265: case TIMER_MODE:
1.1.1.7 root 266: if (timer_index == 0) {
1.1.1.4 root 267: unsigned int i;
268:
1.1.1.7 root 269: for (i = 0; i < s->num_cpus; i++) {
1.1.1.5 root 270: unsigned int processor = 1 << i;
1.1.1.7 root 271: CPUTimerState *curr_timer = &s->cputimer[i + 1];
1.1.1.5 root 272:
273: // check for a change in timer mode for this processor
1.1.1.7 root 274: if ((val & processor) != (s->cputimer_mode & processor)) {
1.1.1.5 root 275: if (val & processor) { // counter -> user timer
1.1.1.7 root 276: qemu_irq_lower(curr_timer->irq);
1.1.1.5 root 277: // counters are always running
1.1.1.7 root 278: ptimer_stop(curr_timer->timer);
279: curr_timer->running = 0;
1.1.1.5 root 280: // user timer limit is always the same
1.1.1.7 root 281: curr_timer->limit = TIMER_MAX_COUNT64;
282: ptimer_set_limit(curr_timer->timer,
283: LIMIT_TO_PERIODS(curr_timer->limit),
1.1.1.5 root 284: 1);
285: // set this processors user timer bit in config
286: // register
1.1.1.7 root 287: s->cputimer_mode |= processor;
1.1.1.9 root 288: trace_slavio_timer_mem_writel_mode_user(timer_index);
1.1.1.5 root 289: } else { // user timer -> counter
290: // stop the user timer if it is running
1.1.1.7 root 291: if (curr_timer->running) {
292: ptimer_stop(curr_timer->timer);
293: }
1.1.1.5 root 294: // start the counter
1.1.1.7 root 295: ptimer_run(curr_timer->timer, 0);
296: curr_timer->running = 1;
1.1.1.5 root 297: // clear this processors user timer bit in config
298: // register
1.1.1.7 root 299: s->cputimer_mode &= ~processor;
1.1.1.9 root 300: trace_slavio_timer_mem_writel_mode_counter(timer_index);
1.1.1.5 root 301: }
1.1.1.4 root 302: }
303: }
1.1.1.7 root 304: } else {
1.1.1.9 root 305: trace_slavio_timer_mem_writel_mode_invalid();
1.1.1.7 root 306: }
1.1.1.4 root 307: break;
1.1 root 308: default:
1.1.1.9 root 309: trace_slavio_timer_mem_writel_invalid(addr);
1.1.1.4 root 310: break;
1.1 root 311: }
312: }
313:
1.1.1.7 root 314: static CPUReadMemoryFunc * const slavio_timer_mem_read[3] = {
1.1.1.4 root 315: NULL,
316: NULL,
1.1 root 317: slavio_timer_mem_readl,
318: };
319:
1.1.1.7 root 320: static CPUWriteMemoryFunc * const slavio_timer_mem_write[3] = {
1.1.1.4 root 321: NULL,
322: NULL,
1.1 root 323: slavio_timer_mem_writel,
324: };
325:
1.1.1.7 root 326: static const VMStateDescription vmstate_timer = {
327: .name ="timer",
328: .version_id = 3,
329: .minimum_version_id = 3,
330: .minimum_version_id_old = 3,
331: .fields = (VMStateField []) {
332: VMSTATE_UINT64(limit, CPUTimerState),
333: VMSTATE_UINT32(count, CPUTimerState),
334: VMSTATE_UINT32(counthigh, CPUTimerState),
335: VMSTATE_UINT32(reached, CPUTimerState),
336: VMSTATE_UINT32(running, CPUTimerState),
337: VMSTATE_PTIMER(timer, CPUTimerState),
338: VMSTATE_END_OF_LIST()
339: }
340: };
1.1 root 341:
1.1.1.7 root 342: static const VMStateDescription vmstate_slavio_timer = {
343: .name ="slavio_timer",
344: .version_id = 3,
345: .minimum_version_id = 3,
346: .minimum_version_id_old = 3,
347: .fields = (VMStateField []) {
348: VMSTATE_STRUCT_ARRAY(cputimer, SLAVIO_TIMERState, MAX_CPUS + 1, 3,
349: vmstate_timer, CPUTimerState),
350: VMSTATE_END_OF_LIST()
1.1.1.4 root 351: }
1.1.1.7 root 352: };
1.1 root 353:
1.1.1.7 root 354: static void slavio_timer_reset(DeviceState *d)
1.1.1.6 root 355: {
1.1.1.7 root 356: SLAVIO_TIMERState *s = container_of(d, SLAVIO_TIMERState, busdev.qdev);
357: unsigned int i;
358: CPUTimerState *curr_timer;
1.1.1.6 root 359:
1.1.1.7 root 360: for (i = 0; i <= MAX_CPUS; i++) {
361: curr_timer = &s->cputimer[i];
362: curr_timer->limit = 0;
363: curr_timer->count = 0;
364: curr_timer->reached = 0;
1.1.1.8 root 365: if (i <= s->num_cpus) {
1.1.1.7 root 366: ptimer_set_limit(curr_timer->timer,
367: LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
368: ptimer_run(curr_timer->timer, 0);
1.1.1.8 root 369: curr_timer->running = 1;
1.1.1.7 root 370: }
371: }
372: s->cputimer_mode = 0;
1.1.1.6 root 373: }
374:
1.1.1.7 root 375: static int slavio_timer_init1(SysBusDevice *dev)
1.1 root 376: {
1.1.1.6 root 377: int io;
378: SLAVIO_TIMERState *s = FROM_SYSBUS(SLAVIO_TIMERState, dev);
1.1.1.4 root 379: QEMUBH *bh;
380: unsigned int i;
1.1.1.7 root 381: TimerContext *tc;
1.1.1.4 root 382:
1.1.1.7 root 383: for (i = 0; i <= MAX_CPUS; i++) {
1.1.1.10! root 384: tc = g_malloc0(sizeof(TimerContext));
1.1.1.7 root 385: tc->s = s;
386: tc->timer_index = i;
387:
388: bh = qemu_bh_new(slavio_timer_irq, tc);
389: s->cputimer[i].timer = ptimer_init(bh);
390: ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
391:
392: io = cpu_register_io_memory(slavio_timer_mem_read,
1.1.1.9 root 393: slavio_timer_mem_write, tc,
394: DEVICE_NATIVE_ENDIAN);
1.1.1.7 root 395: if (i == 0) {
396: sysbus_init_mmio(dev, SYS_TIMER_SIZE, io);
397: } else {
398: sysbus_init_mmio(dev, CPU_TIMER_SIZE, io);
399: }
1.1.1.4 root 400:
1.1.1.7 root 401: sysbus_init_irq(dev, &s->cputimer[i].irq);
1.1.1.6 root 402: }
1.1.1.7 root 403:
404: return 0;
1.1.1.6 root 405: }
406:
407: static SysBusDeviceInfo slavio_timer_info = {
408: .init = slavio_timer_init1,
409: .qdev.name = "slavio_timer",
410: .qdev.size = sizeof(SLAVIO_TIMERState),
1.1.1.7 root 411: .qdev.vmsd = &vmstate_slavio_timer,
412: .qdev.reset = slavio_timer_reset,
1.1.1.6 root 413: .qdev.props = (Property[]) {
1.1.1.7 root 414: DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0),
415: DEFINE_PROP_END_OF_LIST(),
1.1.1.4 root 416: }
1.1.1.6 root 417: };
418:
419: static void slavio_timer_register_devices(void)
420: {
421: sysbus_register_withprop(&slavio_timer_info);
1.1 root 422: }
1.1.1.6 root 423:
424: device_init(slavio_timer_register_devices)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.