|
|
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.11! root 27: #include "ptimer.h"
1.1.1.6 root 28: #include "sysbus.h"
1.1.1.9 root 29: #include "trace.h"
1.1 root 30:
31: /*
32: * Registers of hardware timer in sun4m.
33: *
34: * This is the timer/counter part of chip STP2001 (Slave I/O), also
35: * produced as NCR89C105. See
36: * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
1.1.1.4 root 37: *
1.1 root 38: * The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
39: * are zero. Bit 31 is 1 when count has been reached.
40: *
1.1.1.2 root 41: * Per-CPU timers interrupt local CPU, system timer uses normal
42: * interrupt routing.
43: *
1.1 root 44: */
45:
1.1.1.4 root 46: #define MAX_CPUS 16
47:
1.1.1.7 root 48: typedef struct CPUTimerState {
1.1.1.4 root 49: qemu_irq irq;
50: ptimer_state *timer;
51: uint32_t count, counthigh, reached;
1.1.1.10 root 52: /* processor only */
1.1.1.5 root 53: uint32_t running;
1.1.1.10 root 54: uint64_t limit;
1.1.1.7 root 55: } CPUTimerState;
56:
57: typedef struct SLAVIO_TIMERState {
58: SysBusDevice busdev;
59: uint32_t num_cpus;
60: uint32_t cputimer_mode;
1.1.1.10 root 61: CPUTimerState cputimer[MAX_CPUS + 1];
1.1 root 62: } SLAVIO_TIMERState;
63:
1.1.1.7 root 64: typedef struct TimerContext {
1.1.1.11! root 65: MemoryRegion iomem;
1.1.1.7 root 66: SLAVIO_TIMERState *s;
67: unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
68: } TimerContext;
69:
1.1.1.4 root 70: #define SYS_TIMER_SIZE 0x14
71: #define CPU_TIMER_SIZE 0x10
72:
73: #define TIMER_LIMIT 0
74: #define TIMER_COUNTER 1
75: #define TIMER_COUNTER_NORST 2
76: #define TIMER_STATUS 3
77: #define TIMER_MODE 4
78:
79: #define TIMER_COUNT_MASK32 0xfffffe00
80: #define TIMER_LIMIT_MASK32 0x7fffffff
81: #define TIMER_MAX_COUNT64 0x7ffffffffffffe00ULL
82: #define TIMER_MAX_COUNT32 0x7ffffe00ULL
83: #define TIMER_REACHED 0x80000000
84: #define TIMER_PERIOD 500ULL // 500ns
1.1.1.8 root 85: #define LIMIT_TO_PERIODS(l) (((l) >> 9) - 1)
86: #define PERIODS_TO_LIMIT(l) (((l) + 1) << 9)
1.1.1.4 root 87:
1.1.1.7 root 88: static int slavio_timer_is_user(TimerContext *tc)
1.1.1.4 root 89: {
1.1.1.7 root 90: SLAVIO_TIMERState *s = tc->s;
91: unsigned int timer_index = tc->timer_index;
92:
93: return timer_index != 0 && (s->cputimer_mode & (1 << (timer_index - 1)));
1.1.1.4 root 94: }
1.1 root 95:
96: // Update count, set irq, update expire_time
1.1.1.4 root 97: // Convert from ptimer countdown units
1.1.1.7 root 98: static void slavio_timer_get_out(CPUTimerState *t)
1.1 root 99: {
1.1.1.4 root 100: uint64_t count, limit;
1.1 root 101:
1.1.1.7 root 102: if (t->limit == 0) { /* free-run system or processor counter */
1.1.1.4 root 103: limit = TIMER_MAX_COUNT32;
1.1.1.7 root 104: } else {
105: limit = t->limit;
106: }
107: count = limit - PERIODS_TO_LIMIT(ptimer_get_count(t->timer));
1.1 root 108:
1.1.1.9 root 109: trace_slavio_timer_get_out(t->limit, t->counthigh, t->count);
1.1.1.7 root 110: t->count = count & TIMER_COUNT_MASK32;
111: t->counthigh = count >> 32;
1.1 root 112: }
113:
114: // timer callback
115: static void slavio_timer_irq(void *opaque)
116: {
1.1.1.7 root 117: TimerContext *tc = opaque;
118: SLAVIO_TIMERState *s = tc->s;
119: CPUTimerState *t = &s->cputimer[tc->timer_index];
120:
121: slavio_timer_get_out(t);
1.1.1.9 root 122: trace_slavio_timer_irq(t->counthigh, t->count);
1.1.1.8 root 123: /* if limit is 0 (free-run), there will be no match */
124: if (t->limit != 0) {
125: t->reached = TIMER_REACHED;
126: }
127: /* there is no interrupt if user timer or free-run */
128: if (!slavio_timer_is_user(tc) && t->limit != 0) {
1.1.1.7 root 129: qemu_irq_raise(t->irq);
130: }
1.1 root 131: }
132:
1.1.1.11! root 133: static uint64_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr,
! 134: unsigned size)
1.1 root 135: {
1.1.1.7 root 136: TimerContext *tc = opaque;
137: SLAVIO_TIMERState *s = tc->s;
1.1.1.4 root 138: uint32_t saddr, ret;
1.1.1.7 root 139: unsigned int timer_index = tc->timer_index;
140: CPUTimerState *t = &s->cputimer[timer_index];
1.1 root 141:
1.1.1.5 root 142: saddr = addr >> 2;
1.1 root 143: switch (saddr) {
1.1.1.4 root 144: case TIMER_LIMIT:
145: // read limit (system counter mode) or read most signifying
146: // part of counter (user mode)
1.1.1.7 root 147: if (slavio_timer_is_user(tc)) {
1.1.1.4 root 148: // read user timer MSW
1.1.1.7 root 149: slavio_timer_get_out(t);
150: ret = t->counthigh | t->reached;
1.1.1.4 root 151: } else {
152: // read limit
153: // clear irq
1.1.1.7 root 154: qemu_irq_lower(t->irq);
155: t->reached = 0;
156: ret = t->limit & TIMER_LIMIT_MASK32;
1.1.1.4 root 157: }
158: break;
159: case TIMER_COUNTER:
160: // read counter and reached bit (system mode) or read lsbits
161: // of counter (user mode)
1.1.1.7 root 162: slavio_timer_get_out(t);
163: if (slavio_timer_is_user(tc)) { // read user timer LSW
164: ret = t->count & TIMER_MAX_COUNT64;
165: } else { // read limit
166: ret = (t->count & TIMER_MAX_COUNT32) |
167: t->reached;
168: }
1.1.1.4 root 169: break;
170: case TIMER_STATUS:
171: // only available in processor counter/timer
172: // read start/stop status
1.1.1.7 root 173: if (timer_index > 0) {
174: ret = t->running;
175: } else {
176: ret = 0;
177: }
1.1.1.4 root 178: break;
179: case TIMER_MODE:
180: // only available in system counter
181: // read user/system mode
1.1.1.7 root 182: ret = s->cputimer_mode;
1.1.1.4 root 183: break;
1.1 root 184: default:
1.1.1.9 root 185: trace_slavio_timer_mem_readl_invalid(addr);
1.1.1.4 root 186: ret = 0;
187: break;
1.1 root 188: }
1.1.1.9 root 189: trace_slavio_timer_mem_readl(addr, ret);
1.1.1.4 root 190: return ret;
1.1 root 191: }
192:
1.1.1.4 root 193: static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
1.1.1.11! root 194: uint64_t val, unsigned size)
1.1 root 195: {
1.1.1.7 root 196: TimerContext *tc = opaque;
197: SLAVIO_TIMERState *s = tc->s;
1.1 root 198: uint32_t saddr;
1.1.1.7 root 199: unsigned int timer_index = tc->timer_index;
200: CPUTimerState *t = &s->cputimer[timer_index];
1.1 root 201:
1.1.1.9 root 202: trace_slavio_timer_mem_writel(addr, val);
1.1.1.5 root 203: saddr = addr >> 2;
1.1 root 204: switch (saddr) {
1.1.1.4 root 205: case TIMER_LIMIT:
1.1.1.7 root 206: if (slavio_timer_is_user(tc)) {
1.1.1.5 root 207: uint64_t count;
208:
1.1.1.4 root 209: // set user counter MSW, reset counter
1.1.1.7 root 210: t->limit = TIMER_MAX_COUNT64;
211: t->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
212: t->reached = 0;
213: count = ((uint64_t)t->counthigh << 32) | t->count;
1.1.1.9 root 214: trace_slavio_timer_mem_writel_limit(timer_index, count);
1.1.1.7 root 215: ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
1.1.1.4 root 216: } else {
217: // set limit, reset counter
1.1.1.7 root 218: qemu_irq_lower(t->irq);
219: t->limit = val & TIMER_MAX_COUNT32;
220: if (t->timer) {
221: if (t->limit == 0) { /* free-run */
222: ptimer_set_limit(t->timer,
1.1.1.5 root 223: LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
1.1.1.7 root 224: } else {
225: ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
226: }
1.1.1.4 root 227: }
228: }
229: break;
230: case TIMER_COUNTER:
1.1.1.7 root 231: if (slavio_timer_is_user(tc)) {
1.1.1.5 root 232: uint64_t count;
233:
1.1.1.4 root 234: // set user counter LSW, reset counter
1.1.1.7 root 235: t->limit = TIMER_MAX_COUNT64;
236: t->count = val & TIMER_MAX_COUNT64;
237: t->reached = 0;
238: count = ((uint64_t)t->counthigh) << 32 | t->count;
1.1.1.9 root 239: trace_slavio_timer_mem_writel_limit(timer_index, count);
1.1.1.7 root 240: ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
1.1.1.9 root 241: } else {
242: trace_slavio_timer_mem_writel_counter_invalid();
243: }
1.1.1.4 root 244: break;
245: case TIMER_COUNTER_NORST:
246: // set limit without resetting counter
1.1.1.7 root 247: t->limit = val & TIMER_MAX_COUNT32;
248: if (t->limit == 0) { /* free-run */
249: ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
250: } else {
251: ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
1.1.1.4 root 252: }
253: break;
254: case TIMER_STATUS:
1.1.1.7 root 255: if (slavio_timer_is_user(tc)) {
1.1.1.4 root 256: // start/stop user counter
1.1.1.7 root 257: if ((val & 1) && !t->running) {
1.1.1.9 root 258: trace_slavio_timer_mem_writel_status_start(timer_index);
1.1.1.7 root 259: ptimer_run(t->timer, 0);
260: t->running = 1;
261: } else if (!(val & 1) && t->running) {
1.1.1.9 root 262: trace_slavio_timer_mem_writel_status_stop(timer_index);
1.1.1.7 root 263: ptimer_stop(t->timer);
264: t->running = 0;
1.1.1.4 root 265: }
266: }
267: break;
268: case TIMER_MODE:
1.1.1.7 root 269: if (timer_index == 0) {
1.1.1.4 root 270: unsigned int i;
271:
1.1.1.7 root 272: for (i = 0; i < s->num_cpus; i++) {
1.1.1.5 root 273: unsigned int processor = 1 << i;
1.1.1.7 root 274: CPUTimerState *curr_timer = &s->cputimer[i + 1];
1.1.1.5 root 275:
276: // check for a change in timer mode for this processor
1.1.1.7 root 277: if ((val & processor) != (s->cputimer_mode & processor)) {
1.1.1.5 root 278: if (val & processor) { // counter -> user timer
1.1.1.7 root 279: qemu_irq_lower(curr_timer->irq);
1.1.1.5 root 280: // counters are always running
1.1.1.7 root 281: ptimer_stop(curr_timer->timer);
282: curr_timer->running = 0;
1.1.1.5 root 283: // user timer limit is always the same
1.1.1.7 root 284: curr_timer->limit = TIMER_MAX_COUNT64;
285: ptimer_set_limit(curr_timer->timer,
286: LIMIT_TO_PERIODS(curr_timer->limit),
1.1.1.5 root 287: 1);
288: // set this processors user timer bit in config
289: // register
1.1.1.7 root 290: s->cputimer_mode |= processor;
1.1.1.9 root 291: trace_slavio_timer_mem_writel_mode_user(timer_index);
1.1.1.5 root 292: } else { // user timer -> counter
293: // stop the user timer if it is running
1.1.1.7 root 294: if (curr_timer->running) {
295: ptimer_stop(curr_timer->timer);
296: }
1.1.1.5 root 297: // start the counter
1.1.1.7 root 298: ptimer_run(curr_timer->timer, 0);
299: curr_timer->running = 1;
1.1.1.5 root 300: // clear this processors user timer bit in config
301: // register
1.1.1.7 root 302: s->cputimer_mode &= ~processor;
1.1.1.9 root 303: trace_slavio_timer_mem_writel_mode_counter(timer_index);
1.1.1.5 root 304: }
1.1.1.4 root 305: }
306: }
1.1.1.7 root 307: } else {
1.1.1.9 root 308: trace_slavio_timer_mem_writel_mode_invalid();
1.1.1.7 root 309: }
1.1.1.4 root 310: break;
1.1 root 311: default:
1.1.1.9 root 312: trace_slavio_timer_mem_writel_invalid(addr);
1.1.1.4 root 313: break;
1.1 root 314: }
315: }
316:
1.1.1.11! root 317: static const MemoryRegionOps slavio_timer_mem_ops = {
! 318: .read = slavio_timer_mem_readl,
! 319: .write = slavio_timer_mem_writel,
! 320: .endianness = DEVICE_NATIVE_ENDIAN,
! 321: .valid = {
! 322: .min_access_size = 4,
! 323: .max_access_size = 4,
! 324: },
1.1 root 325: };
326:
1.1.1.7 root 327: static const VMStateDescription vmstate_timer = {
328: .name ="timer",
329: .version_id = 3,
330: .minimum_version_id = 3,
331: .minimum_version_id_old = 3,
332: .fields = (VMStateField []) {
333: VMSTATE_UINT64(limit, CPUTimerState),
334: VMSTATE_UINT32(count, CPUTimerState),
335: VMSTATE_UINT32(counthigh, CPUTimerState),
336: VMSTATE_UINT32(reached, CPUTimerState),
337: VMSTATE_UINT32(running, CPUTimerState),
338: VMSTATE_PTIMER(timer, CPUTimerState),
339: VMSTATE_END_OF_LIST()
340: }
341: };
1.1 root 342:
1.1.1.7 root 343: static const VMStateDescription vmstate_slavio_timer = {
344: .name ="slavio_timer",
345: .version_id = 3,
346: .minimum_version_id = 3,
347: .minimum_version_id_old = 3,
348: .fields = (VMStateField []) {
349: VMSTATE_STRUCT_ARRAY(cputimer, SLAVIO_TIMERState, MAX_CPUS + 1, 3,
350: vmstate_timer, CPUTimerState),
351: VMSTATE_END_OF_LIST()
1.1.1.4 root 352: }
1.1.1.7 root 353: };
1.1 root 354:
1.1.1.7 root 355: static void slavio_timer_reset(DeviceState *d)
1.1.1.6 root 356: {
1.1.1.7 root 357: SLAVIO_TIMERState *s = container_of(d, SLAVIO_TIMERState, busdev.qdev);
358: unsigned int i;
359: CPUTimerState *curr_timer;
1.1.1.6 root 360:
1.1.1.7 root 361: for (i = 0; i <= MAX_CPUS; i++) {
362: curr_timer = &s->cputimer[i];
363: curr_timer->limit = 0;
364: curr_timer->count = 0;
365: curr_timer->reached = 0;
1.1.1.8 root 366: if (i <= s->num_cpus) {
1.1.1.7 root 367: ptimer_set_limit(curr_timer->timer,
368: LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
369: ptimer_run(curr_timer->timer, 0);
1.1.1.8 root 370: curr_timer->running = 1;
1.1.1.7 root 371: }
372: }
373: s->cputimer_mode = 0;
1.1.1.6 root 374: }
375:
1.1.1.7 root 376: static int slavio_timer_init1(SysBusDevice *dev)
1.1 root 377: {
1.1.1.6 root 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.11! root 384: uint64_t size;
! 385: char timer_name[20];
! 386:
1.1.1.10 root 387: tc = g_malloc0(sizeof(TimerContext));
1.1.1.7 root 388: tc->s = s;
389: tc->timer_index = i;
390:
391: bh = qemu_bh_new(slavio_timer_irq, tc);
392: s->cputimer[i].timer = ptimer_init(bh);
393: ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
394:
1.1.1.11! root 395: size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
! 396: snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
! 397: memory_region_init_io(&tc->iomem, &slavio_timer_mem_ops, tc,
! 398: timer_name, size);
! 399: sysbus_init_mmio(dev, &tc->iomem);
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:
1.1.1.11! root 407: static Property slavio_timer_properties[] = {
! 408: DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0),
! 409: DEFINE_PROP_END_OF_LIST(),
! 410: };
! 411:
! 412: static void slavio_timer_class_init(ObjectClass *klass, void *data)
! 413: {
! 414: DeviceClass *dc = DEVICE_CLASS(klass);
! 415: SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
! 416:
! 417: k->init = slavio_timer_init1;
! 418: dc->reset = slavio_timer_reset;
! 419: dc->vmsd = &vmstate_slavio_timer;
! 420: dc->props = slavio_timer_properties;
! 421: }
! 422:
! 423: static TypeInfo slavio_timer_info = {
! 424: .name = "slavio_timer",
! 425: .parent = TYPE_SYS_BUS_DEVICE,
! 426: .instance_size = sizeof(SLAVIO_TIMERState),
! 427: .class_init = slavio_timer_class_init,
1.1.1.6 root 428: };
429:
1.1.1.11! root 430: static void slavio_timer_register_types(void)
1.1.1.6 root 431: {
1.1.1.11! root 432: type_register_static(&slavio_timer_info);
1.1 root 433: }
1.1.1.6 root 434:
1.1.1.11! root 435: type_init(slavio_timer_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.