1:
2:
3:
4:
5:
6:
7:
8: #include "hw.h"
9: #include "mcf.h"
10: #include "qemu-timer.h"
11: #include "sysemu.h"
12: #include "net.h"
13: #include "boards.h"
14:
15: #define SYS_FREQ 66000000
16:
17: #define PCSR_EN 0x0001
18: #define PCSR_RLD 0x0002
19: #define PCSR_PIF 0x0004
20: #define PCSR_PIE 0x0008
21: #define PCSR_OVW 0x0010
22: #define PCSR_DBG 0x0020
23: #define PCSR_DOZE 0x0040
24: #define PCSR_PRE_SHIFT 8
25: #define PCSR_PRE_MASK 0x0f00
26:
27: typedef struct {
28: qemu_irq irq;
29: ptimer_state *timer;
30: uint16_t pcsr;
31: uint16_t pmr;
32: uint16_t pcntr;
33: } m5208_timer_state;
34:
35: static void m5208_timer_update(m5208_timer_state *s)
36: {
37: if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF))
38: qemu_irq_raise(s->irq);
39: else
40: qemu_irq_lower(s->irq);
41: }
42:
43: static void m5208_timer_write(m5208_timer_state *s, int offset,
44: uint32_t value)
45: {
46: int prescale;
47: int limit;
48: switch (offset) {
49: case 0:
50:
51: if (value & PCSR_PIF) {
52: s->pcsr &= ~PCSR_PIF;
53: value &= ~PCSR_PIF;
54: }
55:
56: if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) {
57: s->pcsr = value;
58: m5208_timer_update(s);
59: return;
60: }
61:
62: if (s->pcsr & PCSR_EN)
63: ptimer_stop(s->timer);
64:
65: s->pcsr = value;
66:
67: prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT);
68: ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale);
69: if (s->pcsr & PCSR_RLD)
70: limit = s->pmr;
71: else
72: limit = 0xffff;
73: ptimer_set_limit(s->timer, limit, 0);
74:
75: if (s->pcsr & PCSR_EN)
76: ptimer_run(s->timer, 0);
77: break;
78: case 2:
79: s->pmr = value;
80: s->pcsr &= ~PCSR_PIF;
81: if ((s->pcsr & PCSR_RLD) == 0) {
82: if (s->pcsr & PCSR_OVW)
83: ptimer_set_count(s->timer, value);
84: } else {
85: ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
86: }
87: break;
88: case 4:
89: break;
90: default:
91:
92: abort();
93: }
94: m5208_timer_update(s);
95: }
96:
97: static void m5208_timer_trigger(void *opaque)
98: {
99: m5208_timer_state *s = (m5208_timer_state *)opaque;
100: s->pcsr |= PCSR_PIF;
101: m5208_timer_update(s);
102: }
103:
104: typedef struct {
105: m5208_timer_state timer[2];
106: } m5208_sys_state;
107:
108: static uint32_t m5208_sys_read(void *opaque, target_phys_addr_t addr)
109: {
110: m5208_sys_state *s = (m5208_sys_state *)opaque;
111: switch (addr) {
112:
113: case 0xfc080000:
114: return s->timer[0].pcsr;
115: case 0xfc080002:
116: return s->timer[0].pmr;
117: case 0xfc080004:
118: return ptimer_get_count(s->timer[0].timer);
119:
120: case 0xfc084000:
121: return s->timer[1].pcsr;
122: case 0xfc084002:
123: return s->timer[1].pmr;
124: case 0xfc084004:
125: return ptimer_get_count(s->timer[1].timer);
126:
127:
128: case 0xfc0a8110:
129: {
130: int n;
131: for (n = 0; n < 32; n++) {
132: if (ram_size < (2u << n))
133: break;
134: }
135: return (n - 1) | 0x40000000;
136: }
137: case 0xfc0a8114:
138: return 0;
139:
140: default:
141: cpu_abort(cpu_single_env, "m5208_sys_read: Bad offset 0x%x\n",
142: (int)addr);
143: return 0;
144: }
145: }
146:
147: static void m5208_sys_write(void *opaque, target_phys_addr_t addr,
148: uint32_t value)
149: {
150: m5208_sys_state *s = (m5208_sys_state *)opaque;
151: switch (addr) {
152:
153: case 0xfc080000:
154: case 0xfc080002:
155: case 0xfc080004:
156: m5208_timer_write(&s->timer[0], addr & 0xf, value);
157: return;
158:
159: case 0xfc084000:
160: case 0xfc084002:
161: case 0xfc084004:
162: m5208_timer_write(&s->timer[1], addr & 0xf, value);
163: return;
164: default:
165: cpu_abort(cpu_single_env, "m5208_sys_write: Bad offset 0x%x\n",
166: (int)addr);
167: break;
168: }
169: }
170:
171: static CPUReadMemoryFunc *m5208_sys_readfn[] = {
172: m5208_sys_read,
173: m5208_sys_read,
174: m5208_sys_read
175: };
176:
177: static CPUWriteMemoryFunc *m5208_sys_writefn[] = {
178: m5208_sys_write,
179: m5208_sys_write,
180: m5208_sys_write
181: };
182:
183: static void mcf5208_sys_init(qemu_irq *pic)
184: {
185: int iomemtype;
186: m5208_sys_state *s;
187: QEMUBH *bh;
188: int i;
189:
190: s = (m5208_sys_state *)qemu_mallocz(sizeof(m5208_sys_state));
191: iomemtype = cpu_register_io_memory(0, m5208_sys_readfn,
192: m5208_sys_writefn, s);
193:
194: cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype);
195:
196: for (i = 0; i < 2; i++) {
197: bh = qemu_bh_new(m5208_timer_trigger, &s->timer[i]);
198: s->timer[i].timer = ptimer_init(bh);
199: cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000,
200: iomemtype);
201: s->timer[i].irq = pic[4 + i];
202: }
203: }
204:
205: static void mcf5208evb_init(int ram_size, int vga_ram_size,
206: const char *boot_device, DisplayState *ds,
207: const char *kernel_filename, const char *kernel_cmdline,
208: const char *initrd_filename, const char *cpu_model)
209: {
210: CPUState *env;
211: int kernel_size;
212: uint64_t elf_entry;
213: target_ulong entry;
214: qemu_irq *pic;
215:
216: if (!cpu_model)
217: cpu_model = "m5208";
218: env = cpu_init(cpu_model);
219: if (!env) {
220: fprintf(stderr, "Unable to find m68k CPU definition\n");
221: exit(1);
222: }
223:
224:
225: env->vbr = 0;
226:
227:
228:
229: cpu_register_physical_memory(0x40000000, ram_size,
230: qemu_ram_alloc(ram_size) | IO_MEM_RAM);
231:
232:
233: cpu_register_physical_memory(0x80000000, 16384,
234: qemu_ram_alloc(16384) | IO_MEM_RAM);
235:
236:
237: pic = mcf_intc_init(0xfc048000, env);
238:
239: mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]);
240: mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
241: mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
242:
243: mcf5208_sys_init(pic);
244:
245: if (nb_nics > 1) {
246: fprintf(stderr, "Too many NICs\n");
247: exit(1);
248: }
249: if (nd_table[0].vlan) {
250: if (nd_table[0].model == NULL
251: || strcmp(nd_table[0].model, "mcf_fec") == 0) {
252: mcf_fec_init(&nd_table[0], 0xfc030000, pic + 36);
253: } else if (strcmp(nd_table[0].model, "?") == 0) {
254: fprintf(stderr, "qemu: Supported NICs: mcf_fec\n");
255: exit (1);
256: } else {
257: fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
258: exit (1);
259: }
260: }
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285: if (!kernel_filename) {
286: fprintf(stderr, "Kernel image must be specified\n");
287: exit(1);
288: }
289:
290: kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
291: entry = elf_entry;
292: if (kernel_size < 0) {
293: kernel_size = load_uboot(kernel_filename, &entry, NULL);
294: }
295: if (kernel_size < 0) {
296: kernel_size = load_image(kernel_filename, phys_ram_base);
297: entry = 0x20000000;
298: }
299: if (kernel_size < 0) {
300: fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
301: exit(1);
302: }
303:
304: env->pc = entry;
305: }
306:
307: QEMUMachine mcf5208evb_machine = {
308: "mcf5208evb",
309: "MCF5206EVB",
310: mcf5208evb_init,
311: };