|
|
1.1 ! root 1: /* ! 2: * QEMU ETRAX System Emulator ! 3: * ! 4: * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB. ! 5: * ! 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: */ ! 24: #include <stdio.h> ! 25: #include <sys/time.h> ! 26: #include "hw.h" ! 27: #include "qemu-timer.h" ! 28: ! 29: void etrax_ack_irq(CPUState *env, uint32_t mask); ! 30: ! 31: #define R_TIME 0xb001e038 ! 32: #define RW_TMR0_DIV 0xb001e000 ! 33: #define R_TMR0_DATA 0xb001e004 ! 34: #define RW_TMR0_CTRL 0xb001e008 ! 35: #define RW_TMR1_DIV 0xb001e010 ! 36: #define R_TMR1_DATA 0xb001e014 ! 37: #define RW_TMR1_CTRL 0xb001e018 ! 38: ! 39: #define RW_INTR_MASK 0xb001e048 ! 40: #define RW_ACK_INTR 0xb001e04c ! 41: #define R_INTR 0xb001e050 ! 42: #define R_MASKED_INTR 0xb001e054 ! 43: ! 44: ! 45: uint32_t rw_intr_mask; ! 46: uint32_t rw_ack_intr; ! 47: uint32_t r_intr; ! 48: ! 49: struct fs_timer_t { ! 50: QEMUBH *bh; ! 51: unsigned int limit; ! 52: int scale; ! 53: ptimer_state *ptimer; ! 54: CPUState *env; ! 55: qemu_irq *irq; ! 56: uint32_t mask; ! 57: }; ! 58: ! 59: static struct fs_timer_t timer0; ! 60: ! 61: /* diff two timevals. Return a single int in us. */ ! 62: int diff_timeval_us(struct timeval *a, struct timeval *b) ! 63: { ! 64: int diff; ! 65: ! 66: /* assume these values are signed. */ ! 67: diff = (a->tv_sec - b->tv_sec) * 1000 * 1000; ! 68: diff += (a->tv_usec - b->tv_usec); ! 69: return diff; ! 70: } ! 71: ! 72: static uint32_t timer_readb (void *opaque, target_phys_addr_t addr) ! 73: { ! 74: CPUState *env = opaque; ! 75: uint32_t r = 0; ! 76: printf ("%s %x pc=%x\n", __func__, addr, env->pc); ! 77: return r; ! 78: } ! 79: static uint32_t timer_readw (void *opaque, target_phys_addr_t addr) ! 80: { ! 81: CPUState *env = opaque; ! 82: uint32_t r = 0; ! 83: printf ("%s %x pc=%x\n", __func__, addr, env->pc); ! 84: return r; ! 85: } ! 86: ! 87: static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) ! 88: { ! 89: CPUState *env = opaque; ! 90: uint32_t r = 0; ! 91: ! 92: switch (addr) { ! 93: case R_TMR0_DATA: ! 94: break; ! 95: case R_TMR1_DATA: ! 96: printf ("R_TMR1_DATA\n"); ! 97: break; ! 98: case R_TIME: ! 99: { ! 100: static struct timeval last; ! 101: struct timeval now; ! 102: gettimeofday(&now, NULL); ! 103: if (!(last.tv_sec == 0 && last.tv_usec == 0)) { ! 104: r = diff_timeval_us(&now, &last); ! 105: r *= 1000; /* convert to ns. */ ! 106: r++; /* make sure we increase for each call. */ ! 107: } ! 108: last = now; ! 109: break; ! 110: } ! 111: ! 112: case RW_INTR_MASK: ! 113: r = rw_intr_mask; ! 114: break; ! 115: case R_MASKED_INTR: ! 116: r = r_intr & rw_intr_mask; ! 117: break; ! 118: default: ! 119: printf ("%s %x p=%x\n", __func__, addr, env->pc); ! 120: break; ! 121: } ! 122: return r; ! 123: } ! 124: ! 125: static void ! 126: timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) ! 127: { ! 128: CPUState *env = opaque; ! 129: printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); ! 130: } ! 131: static void ! 132: timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value) ! 133: { ! 134: CPUState *env = opaque; ! 135: printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); ! 136: } ! 137: ! 138: static void write_ctrl(struct fs_timer_t *t, uint32_t v) ! 139: { ! 140: int op; ! 141: int freq; ! 142: int freq_hz; ! 143: ! 144: op = v & 3; ! 145: freq = v >> 2; ! 146: freq_hz = 32000000; ! 147: ! 148: switch (freq) ! 149: { ! 150: case 0: ! 151: case 1: ! 152: printf ("extern or disabled timer clock?\n"); ! 153: break; ! 154: case 4: freq_hz = 29493000; break; ! 155: case 5: freq_hz = 32000000; break; ! 156: case 6: freq_hz = 32768000; break; ! 157: case 7: freq_hz = 100000000; break; ! 158: default: ! 159: abort(); ! 160: break; ! 161: } ! 162: ! 163: printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit); ! 164: t->scale = 0; ! 165: if (t->limit > 2048) ! 166: { ! 167: t->scale = 2048; ! 168: ptimer_set_period(timer0.ptimer, freq_hz / t->scale); ! 169: } ! 170: ! 171: printf ("op=%d\n", op); ! 172: switch (op) ! 173: { ! 174: case 0: ! 175: printf ("limit=%d %d\n", t->limit, t->limit/t->scale); ! 176: ptimer_set_limit(t->ptimer, t->limit / t->scale, 1); ! 177: break; ! 178: case 1: ! 179: ptimer_stop(t->ptimer); ! 180: break; ! 181: case 2: ! 182: ptimer_run(t->ptimer, 0); ! 183: break; ! 184: default: ! 185: abort(); ! 186: break; ! 187: } ! 188: } ! 189: ! 190: static void timer_ack_irq(void) ! 191: { ! 192: if (!(r_intr & timer0.mask & rw_intr_mask)) { ! 193: qemu_irq_lower(timer0.irq[0]); ! 194: etrax_ack_irq(timer0.env, 1 << 0x1b); ! 195: } ! 196: } ! 197: ! 198: static void ! 199: timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) ! 200: { ! 201: CPUState *env = opaque; ! 202: printf ("%s %x %x pc=%x\n", ! 203: __func__, addr, value, env->pc); ! 204: switch (addr) ! 205: { ! 206: case RW_TMR0_DIV: ! 207: printf ("RW_TMR0_DIV=%x\n", value); ! 208: timer0.limit = value; ! 209: break; ! 210: case RW_TMR0_CTRL: ! 211: printf ("RW_TMR0_CTRL=%x\n", value); ! 212: write_ctrl(&timer0, value); ! 213: break; ! 214: case RW_TMR1_DIV: ! 215: printf ("RW_TMR1_DIV=%x\n", value); ! 216: break; ! 217: case RW_TMR1_CTRL: ! 218: printf ("RW_TMR1_CTRL=%x\n", value); ! 219: break; ! 220: case RW_INTR_MASK: ! 221: printf ("RW_INTR_MASK=%x\n", value); ! 222: rw_intr_mask = value; ! 223: break; ! 224: case RW_ACK_INTR: ! 225: r_intr &= ~value; ! 226: timer_ack_irq(); ! 227: break; ! 228: default: ! 229: printf ("%s %x %x pc=%x\n", ! 230: __func__, addr, value, env->pc); ! 231: break; ! 232: } ! 233: } ! 234: ! 235: static CPUReadMemoryFunc *timer_read[] = { ! 236: &timer_readb, ! 237: &timer_readw, ! 238: &timer_readl, ! 239: }; ! 240: ! 241: static CPUWriteMemoryFunc *timer_write[] = { ! 242: &timer_writeb, ! 243: &timer_writew, ! 244: &timer_writel, ! 245: }; ! 246: ! 247: static void timer_irq(void *opaque) ! 248: { ! 249: struct fs_timer_t *t = opaque; ! 250: ! 251: r_intr |= t->mask; ! 252: if (t->mask & rw_intr_mask) { ! 253: qemu_irq_raise(t->irq[0]); ! 254: } ! 255: } ! 256: ! 257: void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) ! 258: { ! 259: int timer_regs; ! 260: ! 261: timer0.bh = qemu_bh_new(timer_irq, &timer0); ! 262: timer0.ptimer = ptimer_init(timer0.bh); ! 263: timer0.irq = irqs + 0x1b; ! 264: timer0.mask = 1; ! 265: timer0.env = env; ! 266: ! 267: timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env); ! 268: cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs); ! 269: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.