mips_malta: generate SMBUS EEPROM data
[qemu.git] / hw / mips / mips_malta.c
blob28c351d83d1a0563d3e976d732763add226e408a
1 /*
2 * QEMU Malta board support
4 * Copyright (c) 2006 Aurelien Jarno
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
25 #include "hw/hw.h"
26 #include "hw/i386/pc.h"
27 #include "hw/char/serial.h"
28 #include "hw/block/fdc.h"
29 #include "net/net.h"
30 #include "hw/boards.h"
31 #include "hw/i2c/smbus.h"
32 #include "block/block.h"
33 #include "hw/block/flash.h"
34 #include "hw/mips/mips.h"
35 #include "hw/mips/cpudevs.h"
36 #include "hw/pci/pci.h"
37 #include "sysemu/char.h"
38 #include "sysemu/sysemu.h"
39 #include "sysemu/arch_init.h"
40 #include "qemu/log.h"
41 #include "hw/mips/bios.h"
42 #include "hw/ide.h"
43 #include "hw/loader.h"
44 #include "elf.h"
45 #include "hw/timer/mc146818rtc.h"
46 #include "hw/timer/i8254.h"
47 #include "sysemu/blockdev.h"
48 #include "exec/address-spaces.h"
49 #include "hw/sysbus.h" /* SysBusDevice */
50 #include "qemu/host-utils.h"
52 //#define DEBUG_BOARD_INIT
54 #define ENVP_ADDR 0x80002000l
55 #define ENVP_NB_ENTRIES 16
56 #define ENVP_ENTRY_SIZE 256
58 /* Hardware addresses */
59 #define FLASH_ADDRESS 0x1e000000ULL
60 #define FPGA_ADDRESS 0x1f000000ULL
61 #define RESET_ADDRESS 0x1fc00000ULL
63 #define FLASH_SIZE 0x400000
65 #define MAX_IDE_BUS 2
67 typedef struct {
68 MemoryRegion iomem;
69 MemoryRegion iomem_lo; /* 0 - 0x900 */
70 MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
71 uint32_t leds;
72 uint32_t brk;
73 uint32_t gpout;
74 uint32_t i2cin;
75 uint32_t i2coe;
76 uint32_t i2cout;
77 uint32_t i2csel;
78 CharDriverState *display;
79 char display_text[9];
80 SerialState *uart;
81 } MaltaFPGAState;
83 #define TYPE_MIPS_MALTA "mips-malta"
84 #define MIPS_MALTA(obj) OBJECT_CHECK(MaltaState, (obj), TYPE_MIPS_MALTA)
86 typedef struct {
87 SysBusDevice parent_obj;
89 qemu_irq *i8259;
90 } MaltaState;
92 static ISADevice *pit;
94 static struct _loaderparams {
95 int ram_size;
96 const char *kernel_filename;
97 const char *kernel_cmdline;
98 const char *initrd_filename;
99 } loaderparams;
101 /* Malta FPGA */
102 static void malta_fpga_update_display(void *opaque)
104 char leds_text[9];
105 int i;
106 MaltaFPGAState *s = opaque;
108 for (i = 7 ; i >= 0 ; i--) {
109 if (s->leds & (1 << i))
110 leds_text[i] = '#';
111 else
112 leds_text[i] = ' ';
114 leds_text[8] = '\0';
116 qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
117 qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
121 * EEPROM 24C01 / 24C02 emulation.
123 * Emulation for serial EEPROMs:
124 * 24C01 - 1024 bit (128 x 8)
125 * 24C02 - 2048 bit (256 x 8)
127 * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
130 //~ #define DEBUG
132 #if defined(DEBUG)
133 # define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
134 #else
135 # define logout(fmt, ...) ((void)0)
136 #endif
138 struct _eeprom24c0x_t {
139 uint8_t tick;
140 uint8_t address;
141 uint8_t command;
142 uint8_t ack;
143 uint8_t scl;
144 uint8_t sda;
145 uint8_t data;
146 //~ uint16_t size;
147 uint8_t contents[256];
150 typedef struct _eeprom24c0x_t eeprom24c0x_t;
152 static eeprom24c0x_t spd_eeprom = {
153 .contents = {
154 /* 00000000: */ 0x80,0x08,0xFF,0x0D,0x0A,0xFF,0x40,0x00,
155 /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
156 /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x00,0x00,
157 /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0xFF,
158 /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
159 /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
160 /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
161 /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
162 /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
163 /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
164 /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
165 /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
166 /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
167 /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
168 /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
169 /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
173 static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
175 enum { SDR = 0x4, DDR2 = 0x8 } type;
176 uint8_t *spd = spd_eeprom.contents;
177 uint8_t nbanks = 0;
178 uint16_t density = 0;
179 int i;
181 /* work in terms of MB */
182 ram_size >>= 20;
184 while ((ram_size >= 4) && (nbanks <= 2)) {
185 int sz_log2 = MIN(31 - clz32(ram_size), 14);
186 nbanks++;
187 density |= 1 << (sz_log2 - 2);
188 ram_size -= 1 << sz_log2;
191 /* split to 2 banks if possible */
192 if ((nbanks == 1) && (density > 1)) {
193 nbanks++;
194 density >>= 1;
197 if (density & 0xff00) {
198 density = (density & 0xe0) | ((density >> 8) & 0x1f);
199 type = DDR2;
200 } else if (!(density & 0x1f)) {
201 type = DDR2;
202 } else {
203 type = SDR;
206 if (ram_size) {
207 fprintf(stderr, "Warning: SPD cannot represent final %dMB"
208 " of SDRAM\n", (int)ram_size);
211 /* fill in SPD memory information */
212 spd[2] = type;
213 spd[5] = nbanks;
214 spd[31] = density;
216 /* checksum */
217 spd[63] = 0;
218 for (i = 0; i < 63; i++) {
219 spd[63] += spd[i];
222 /* copy for SMBUS */
223 memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
226 static void generate_eeprom_serial(uint8_t *eeprom)
228 int i, pos = 0;
229 uint8_t mac[6] = { 0x00 };
230 uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
232 /* version */
233 eeprom[pos++] = 0x01;
235 /* count */
236 eeprom[pos++] = 0x02;
238 /* MAC address */
239 eeprom[pos++] = 0x01; /* MAC */
240 eeprom[pos++] = 0x06; /* length */
241 memcpy(&eeprom[pos], mac, sizeof(mac));
242 pos += sizeof(mac);
244 /* serial number */
245 eeprom[pos++] = 0x02; /* serial */
246 eeprom[pos++] = 0x05; /* length */
247 memcpy(&eeprom[pos], sn, sizeof(sn));
248 pos += sizeof(sn);
250 /* checksum */
251 eeprom[pos] = 0;
252 for (i = 0; i < pos; i++) {
253 eeprom[pos] += eeprom[i];
257 static uint8_t eeprom24c0x_read(eeprom24c0x_t *eeprom)
259 logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
260 eeprom->tick, eeprom->scl, eeprom->sda, eeprom->data);
261 return eeprom->sda;
264 static void eeprom24c0x_write(eeprom24c0x_t *eeprom, int scl, int sda)
266 if (eeprom->scl && scl && (eeprom->sda != sda)) {
267 logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
268 eeprom->tick, eeprom->scl, scl, eeprom->sda, sda,
269 sda ? "stop" : "start");
270 if (!sda) {
271 eeprom->tick = 1;
272 eeprom->command = 0;
274 } else if (eeprom->tick == 0 && !eeprom->ack) {
275 /* Waiting for start. */
276 logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
277 eeprom->tick, eeprom->scl, scl, eeprom->sda, sda);
278 } else if (!eeprom->scl && scl) {
279 logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
280 eeprom->tick, eeprom->scl, scl, eeprom->sda, sda);
281 if (eeprom->ack) {
282 logout("\ti2c ack bit = 0\n");
283 sda = 0;
284 eeprom->ack = 0;
285 } else if (eeprom->sda == sda) {
286 uint8_t bit = (sda != 0);
287 logout("\ti2c bit = %d\n", bit);
288 if (eeprom->tick < 9) {
289 eeprom->command <<= 1;
290 eeprom->command += bit;
291 eeprom->tick++;
292 if (eeprom->tick == 9) {
293 logout("\tcommand 0x%04x, %s\n", eeprom->command,
294 bit ? "read" : "write");
295 eeprom->ack = 1;
297 } else if (eeprom->tick < 17) {
298 if (eeprom->command & 1) {
299 sda = ((eeprom->data & 0x80) != 0);
301 eeprom->address <<= 1;
302 eeprom->address += bit;
303 eeprom->tick++;
304 eeprom->data <<= 1;
305 if (eeprom->tick == 17) {
306 eeprom->data = eeprom->contents[eeprom->address];
307 logout("\taddress 0x%04x, data 0x%02x\n",
308 eeprom->address, eeprom->data);
309 eeprom->ack = 1;
310 eeprom->tick = 0;
312 } else if (eeprom->tick >= 17) {
313 sda = 0;
315 } else {
316 logout("\tsda changed with raising scl\n");
318 } else {
319 logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom->tick, eeprom->scl,
320 scl, eeprom->sda, sda);
322 eeprom->scl = scl;
323 eeprom->sda = sda;
326 static uint64_t malta_fpga_read(void *opaque, hwaddr addr,
327 unsigned size)
329 MaltaFPGAState *s = opaque;
330 uint32_t val = 0;
331 uint32_t saddr;
333 saddr = (addr & 0xfffff);
335 switch (saddr) {
337 /* SWITCH Register */
338 case 0x00200:
339 val = 0x00000000; /* All switches closed */
340 break;
342 /* STATUS Register */
343 case 0x00208:
344 #ifdef TARGET_WORDS_BIGENDIAN
345 val = 0x00000012;
346 #else
347 val = 0x00000010;
348 #endif
349 break;
351 /* JMPRS Register */
352 case 0x00210:
353 val = 0x00;
354 break;
356 /* LEDBAR Register */
357 case 0x00408:
358 val = s->leds;
359 break;
361 /* BRKRES Register */
362 case 0x00508:
363 val = s->brk;
364 break;
366 /* UART Registers are handled directly by the serial device */
368 /* GPOUT Register */
369 case 0x00a00:
370 val = s->gpout;
371 break;
373 /* XXX: implement a real I2C controller */
375 /* GPINP Register */
376 case 0x00a08:
377 /* IN = OUT until a real I2C control is implemented */
378 if (s->i2csel)
379 val = s->i2cout;
380 else
381 val = 0x00;
382 break;
384 /* I2CINP Register */
385 case 0x00b00:
386 val = ((s->i2cin & ~1) | eeprom24c0x_read(&spd_eeprom));
387 break;
389 /* I2COE Register */
390 case 0x00b08:
391 val = s->i2coe;
392 break;
394 /* I2COUT Register */
395 case 0x00b10:
396 val = s->i2cout;
397 break;
399 /* I2CSEL Register */
400 case 0x00b18:
401 val = s->i2csel;
402 break;
404 default:
405 #if 0
406 printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
407 addr);
408 #endif
409 break;
411 return val;
414 static void malta_fpga_write(void *opaque, hwaddr addr,
415 uint64_t val, unsigned size)
417 MaltaFPGAState *s = opaque;
418 uint32_t saddr;
420 saddr = (addr & 0xfffff);
422 switch (saddr) {
424 /* SWITCH Register */
425 case 0x00200:
426 break;
428 /* JMPRS Register */
429 case 0x00210:
430 break;
432 /* LEDBAR Register */
433 case 0x00408:
434 s->leds = val & 0xff;
435 malta_fpga_update_display(s);
436 break;
438 /* ASCIIWORD Register */
439 case 0x00410:
440 snprintf(s->display_text, 9, "%08X", (uint32_t)val);
441 malta_fpga_update_display(s);
442 break;
444 /* ASCIIPOS0 to ASCIIPOS7 Registers */
445 case 0x00418:
446 case 0x00420:
447 case 0x00428:
448 case 0x00430:
449 case 0x00438:
450 case 0x00440:
451 case 0x00448:
452 case 0x00450:
453 s->display_text[(saddr - 0x00418) >> 3] = (char) val;
454 malta_fpga_update_display(s);
455 break;
457 /* SOFTRES Register */
458 case 0x00500:
459 if (val == 0x42)
460 qemu_system_reset_request ();
461 break;
463 /* BRKRES Register */
464 case 0x00508:
465 s->brk = val & 0xff;
466 break;
468 /* UART Registers are handled directly by the serial device */
470 /* GPOUT Register */
471 case 0x00a00:
472 s->gpout = val & 0xff;
473 break;
475 /* I2COE Register */
476 case 0x00b08:
477 s->i2coe = val & 0x03;
478 break;
480 /* I2COUT Register */
481 case 0x00b10:
482 eeprom24c0x_write(&spd_eeprom, val & 0x02, val & 0x01);
483 s->i2cout = val;
484 break;
486 /* I2CSEL Register */
487 case 0x00b18:
488 s->i2csel = val & 0x01;
489 break;
491 default:
492 #if 0
493 printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
494 addr);
495 #endif
496 break;
500 static const MemoryRegionOps malta_fpga_ops = {
501 .read = malta_fpga_read,
502 .write = malta_fpga_write,
503 .endianness = DEVICE_NATIVE_ENDIAN,
506 static void malta_fpga_reset(void *opaque)
508 MaltaFPGAState *s = opaque;
510 s->leds = 0x00;
511 s->brk = 0x0a;
512 s->gpout = 0x00;
513 s->i2cin = 0x3;
514 s->i2coe = 0x0;
515 s->i2cout = 0x3;
516 s->i2csel = 0x1;
518 s->display_text[8] = '\0';
519 snprintf(s->display_text, 9, " ");
522 static void malta_fpga_led_init(CharDriverState *chr)
524 qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
525 qemu_chr_fe_printf(chr, "+--------+\r\n");
526 qemu_chr_fe_printf(chr, "+ +\r\n");
527 qemu_chr_fe_printf(chr, "+--------+\r\n");
528 qemu_chr_fe_printf(chr, "\n");
529 qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
530 qemu_chr_fe_printf(chr, "+--------+\r\n");
531 qemu_chr_fe_printf(chr, "+ +\r\n");
532 qemu_chr_fe_printf(chr, "+--------+\r\n");
535 static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
536 hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
538 MaltaFPGAState *s;
540 s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
542 memory_region_init_io(&s->iomem, NULL, &malta_fpga_ops, s,
543 "malta-fpga", 0x100000);
544 memory_region_init_alias(&s->iomem_lo, NULL, "malta-fpga",
545 &s->iomem, 0, 0x900);
546 memory_region_init_alias(&s->iomem_hi, NULL, "malta-fpga",
547 &s->iomem, 0xa00, 0x10000-0xa00);
549 memory_region_add_subregion(address_space, base, &s->iomem_lo);
550 memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
552 s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
554 s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
555 230400, uart_chr, DEVICE_NATIVE_ENDIAN);
557 malta_fpga_reset(s);
558 qemu_register_reset(malta_fpga_reset, s);
560 return s;
563 /* Network support */
564 static void network_init(PCIBus *pci_bus)
566 int i;
568 for(i = 0; i < nb_nics; i++) {
569 NICInfo *nd = &nd_table[i];
570 const char *default_devaddr = NULL;
572 if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
573 /* The malta board has a PCNet card using PCI SLOT 11 */
574 default_devaddr = "0b";
576 pci_nic_init_nofail(nd, pci_bus, "pcnet", default_devaddr);
580 /* ROM and pseudo bootloader
582 The following code implements a very very simple bootloader. It first
583 loads the registers a0 to a3 to the values expected by the OS, and
584 then jump at the kernel address.
586 The bootloader should pass the locations of the kernel arguments and
587 environment variables tables. Those tables contain the 32-bit address
588 of NULL terminated strings. The environment variables table should be
589 terminated by a NULL address.
591 For a simpler implementation, the number of kernel arguments is fixed
592 to two (the name of the kernel and the command line), and the two
593 tables are actually the same one.
595 The registers a0 to a3 should contain the following values:
596 a0 - number of kernel arguments
597 a1 - 32-bit address of the kernel arguments table
598 a2 - 32-bit address of the environment variables table
599 a3 - RAM size in bytes
602 static void write_bootloader (CPUMIPSState *env, uint8_t *base,
603 int64_t kernel_entry)
605 uint32_t *p;
607 /* Small bootloader */
608 p = (uint32_t *)base;
609 stl_raw(p++, 0x0bf00160); /* j 0x1fc00580 */
610 stl_raw(p++, 0x00000000); /* nop */
612 /* YAMON service vector */
613 stl_raw(base + 0x500, 0xbfc00580); /* start: */
614 stl_raw(base + 0x504, 0xbfc0083c); /* print_count: */
615 stl_raw(base + 0x520, 0xbfc00580); /* start: */
616 stl_raw(base + 0x52c, 0xbfc00800); /* flush_cache: */
617 stl_raw(base + 0x534, 0xbfc00808); /* print: */
618 stl_raw(base + 0x538, 0xbfc00800); /* reg_cpu_isr: */
619 stl_raw(base + 0x53c, 0xbfc00800); /* unred_cpu_isr: */
620 stl_raw(base + 0x540, 0xbfc00800); /* reg_ic_isr: */
621 stl_raw(base + 0x544, 0xbfc00800); /* unred_ic_isr: */
622 stl_raw(base + 0x548, 0xbfc00800); /* reg_esr: */
623 stl_raw(base + 0x54c, 0xbfc00800); /* unreg_esr: */
624 stl_raw(base + 0x550, 0xbfc00800); /* getchar: */
625 stl_raw(base + 0x554, 0xbfc00800); /* syscon_read: */
628 /* Second part of the bootloader */
629 p = (uint32_t *) (base + 0x580);
630 stl_raw(p++, 0x24040002); /* addiu a0, zero, 2 */
631 stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
632 stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff)); /* ori sp, sp, low(ENVP_ADDR) */
633 stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
634 stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a1, low(ENVP_ADDR) */
635 stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
636 stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
637 stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* lui a3, high(ram_size) */
638 stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); /* ori a3, a3, low(ram_size) */
640 /* Load BAR registers as done by YAMON */
641 stl_raw(p++, 0x3c09b400); /* lui t1, 0xb400 */
643 #ifdef TARGET_WORDS_BIGENDIAN
644 stl_raw(p++, 0x3c08df00); /* lui t0, 0xdf00 */
645 #else
646 stl_raw(p++, 0x340800df); /* ori t0, r0, 0x00df */
647 #endif
648 stl_raw(p++, 0xad280068); /* sw t0, 0x0068(t1) */
650 stl_raw(p++, 0x3c09bbe0); /* lui t1, 0xbbe0 */
652 #ifdef TARGET_WORDS_BIGENDIAN
653 stl_raw(p++, 0x3c08c000); /* lui t0, 0xc000 */
654 #else
655 stl_raw(p++, 0x340800c0); /* ori t0, r0, 0x00c0 */
656 #endif
657 stl_raw(p++, 0xad280048); /* sw t0, 0x0048(t1) */
658 #ifdef TARGET_WORDS_BIGENDIAN
659 stl_raw(p++, 0x3c084000); /* lui t0, 0x4000 */
660 #else
661 stl_raw(p++, 0x34080040); /* ori t0, r0, 0x0040 */
662 #endif
663 stl_raw(p++, 0xad280050); /* sw t0, 0x0050(t1) */
665 #ifdef TARGET_WORDS_BIGENDIAN
666 stl_raw(p++, 0x3c088000); /* lui t0, 0x8000 */
667 #else
668 stl_raw(p++, 0x34080080); /* ori t0, r0, 0x0080 */
669 #endif
670 stl_raw(p++, 0xad280058); /* sw t0, 0x0058(t1) */
671 #ifdef TARGET_WORDS_BIGENDIAN
672 stl_raw(p++, 0x3c083f00); /* lui t0, 0x3f00 */
673 #else
674 stl_raw(p++, 0x3408003f); /* ori t0, r0, 0x003f */
675 #endif
676 stl_raw(p++, 0xad280060); /* sw t0, 0x0060(t1) */
678 #ifdef TARGET_WORDS_BIGENDIAN
679 stl_raw(p++, 0x3c08c100); /* lui t0, 0xc100 */
680 #else
681 stl_raw(p++, 0x340800c1); /* ori t0, r0, 0x00c1 */
682 #endif
683 stl_raw(p++, 0xad280080); /* sw t0, 0x0080(t1) */
684 #ifdef TARGET_WORDS_BIGENDIAN
685 stl_raw(p++, 0x3c085e00); /* lui t0, 0x5e00 */
686 #else
687 stl_raw(p++, 0x3408005e); /* ori t0, r0, 0x005e */
688 #endif
689 stl_raw(p++, 0xad280088); /* sw t0, 0x0088(t1) */
691 /* Jump to kernel code */
692 stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff)); /* lui ra, high(kernel_entry) */
693 stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff)); /* ori ra, ra, low(kernel_entry) */
694 stl_raw(p++, 0x03e00008); /* jr ra */
695 stl_raw(p++, 0x00000000); /* nop */
697 /* YAMON subroutines */
698 p = (uint32_t *) (base + 0x800);
699 stl_raw(p++, 0x03e00008); /* jr ra */
700 stl_raw(p++, 0x24020000); /* li v0,0 */
701 /* 808 YAMON print */
702 stl_raw(p++, 0x03e06821); /* move t5,ra */
703 stl_raw(p++, 0x00805821); /* move t3,a0 */
704 stl_raw(p++, 0x00a05021); /* move t2,a1 */
705 stl_raw(p++, 0x91440000); /* lbu a0,0(t2) */
706 stl_raw(p++, 0x254a0001); /* addiu t2,t2,1 */
707 stl_raw(p++, 0x10800005); /* beqz a0,834 */
708 stl_raw(p++, 0x00000000); /* nop */
709 stl_raw(p++, 0x0ff0021c); /* jal 870 */
710 stl_raw(p++, 0x00000000); /* nop */
711 stl_raw(p++, 0x08000205); /* j 814 */
712 stl_raw(p++, 0x00000000); /* nop */
713 stl_raw(p++, 0x01a00008); /* jr t5 */
714 stl_raw(p++, 0x01602021); /* move a0,t3 */
715 /* 0x83c YAMON print_count */
716 stl_raw(p++, 0x03e06821); /* move t5,ra */
717 stl_raw(p++, 0x00805821); /* move t3,a0 */
718 stl_raw(p++, 0x00a05021); /* move t2,a1 */
719 stl_raw(p++, 0x00c06021); /* move t4,a2 */
720 stl_raw(p++, 0x91440000); /* lbu a0,0(t2) */
721 stl_raw(p++, 0x0ff0021c); /* jal 870 */
722 stl_raw(p++, 0x00000000); /* nop */
723 stl_raw(p++, 0x254a0001); /* addiu t2,t2,1 */
724 stl_raw(p++, 0x258cffff); /* addiu t4,t4,-1 */
725 stl_raw(p++, 0x1580fffa); /* bnez t4,84c */
726 stl_raw(p++, 0x00000000); /* nop */
727 stl_raw(p++, 0x01a00008); /* jr t5 */
728 stl_raw(p++, 0x01602021); /* move a0,t3 */
729 /* 0x870 */
730 stl_raw(p++, 0x3c08b800); /* lui t0,0xb400 */
731 stl_raw(p++, 0x350803f8); /* ori t0,t0,0x3f8 */
732 stl_raw(p++, 0x91090005); /* lbu t1,5(t0) */
733 stl_raw(p++, 0x00000000); /* nop */
734 stl_raw(p++, 0x31290040); /* andi t1,t1,0x40 */
735 stl_raw(p++, 0x1120fffc); /* beqz t1,878 <outch+0x8> */
736 stl_raw(p++, 0x00000000); /* nop */
737 stl_raw(p++, 0x03e00008); /* jr ra */
738 stl_raw(p++, 0xa1040000); /* sb a0,0(t0) */
742 static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
743 const char *string, ...)
745 va_list ap;
746 int32_t table_addr;
748 if (index >= ENVP_NB_ENTRIES)
749 return;
751 if (string == NULL) {
752 prom_buf[index] = 0;
753 return;
756 table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
757 prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
759 va_start(ap, string);
760 vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
761 va_end(ap);
764 /* Kernel */
765 static int64_t load_kernel (void)
767 int64_t kernel_entry, kernel_high;
768 long initrd_size;
769 ram_addr_t initrd_offset;
770 int big_endian;
771 uint32_t *prom_buf;
772 long prom_size;
773 int prom_index = 0;
775 #ifdef TARGET_WORDS_BIGENDIAN
776 big_endian = 1;
777 #else
778 big_endian = 0;
779 #endif
781 if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
782 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
783 big_endian, ELF_MACHINE, 1) < 0) {
784 fprintf(stderr, "qemu: could not load kernel '%s'\n",
785 loaderparams.kernel_filename);
786 exit(1);
789 /* load initrd */
790 initrd_size = 0;
791 initrd_offset = 0;
792 if (loaderparams.initrd_filename) {
793 initrd_size = get_image_size (loaderparams.initrd_filename);
794 if (initrd_size > 0) {
795 initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
796 if (initrd_offset + initrd_size > ram_size) {
797 fprintf(stderr,
798 "qemu: memory too small for initial ram disk '%s'\n",
799 loaderparams.initrd_filename);
800 exit(1);
802 initrd_size = load_image_targphys(loaderparams.initrd_filename,
803 initrd_offset,
804 ram_size - initrd_offset);
806 if (initrd_size == (target_ulong) -1) {
807 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
808 loaderparams.initrd_filename);
809 exit(1);
813 /* Setup prom parameters. */
814 prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
815 prom_buf = g_malloc(prom_size);
817 prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
818 if (initrd_size > 0) {
819 prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
820 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
821 loaderparams.kernel_cmdline);
822 } else {
823 prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
826 prom_set(prom_buf, prom_index++, "memsize");
827 prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
828 prom_set(prom_buf, prom_index++, "modetty0");
829 prom_set(prom_buf, prom_index++, "38400n8r");
830 prom_set(prom_buf, prom_index++, NULL);
832 rom_add_blob_fixed("prom", prom_buf, prom_size,
833 cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
835 return kernel_entry;
838 static void malta_mips_config(MIPSCPU *cpu)
840 CPUMIPSState *env = &cpu->env;
841 CPUState *cs = CPU(cpu);
843 env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
844 ((smp_cpus * cs->nr_threads - 1) << CP0MVPC0_PTC);
847 static void main_cpu_reset(void *opaque)
849 MIPSCPU *cpu = opaque;
850 CPUMIPSState *env = &cpu->env;
852 cpu_reset(CPU(cpu));
854 /* The bootloader does not need to be rewritten as it is located in a
855 read only location. The kernel location and the arguments table
856 location does not change. */
857 if (loaderparams.kernel_filename) {
858 env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
861 malta_mips_config(cpu);
864 static void cpu_request_exit(void *opaque, int irq, int level)
866 CPUState *cpu = current_cpu;
868 if (cpu && level) {
869 cpu_exit(cpu);
873 static
874 void mips_malta_init(QEMUMachineInitArgs *args)
876 ram_addr_t ram_size = args->ram_size;
877 const char *cpu_model = args->cpu_model;
878 const char *kernel_filename = args->kernel_filename;
879 const char *kernel_cmdline = args->kernel_cmdline;
880 const char *initrd_filename = args->initrd_filename;
881 char *filename;
882 pflash_t *fl;
883 MemoryRegion *system_memory = get_system_memory();
884 MemoryRegion *ram = g_new(MemoryRegion, 1);
885 MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1);
886 target_long bios_size = FLASH_SIZE;
887 const size_t smbus_eeprom_size = 8 * 256;
888 uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
889 int64_t kernel_entry;
890 PCIBus *pci_bus;
891 ISABus *isa_bus;
892 MIPSCPU *cpu;
893 CPUMIPSState *env;
894 qemu_irq *isa_irq;
895 qemu_irq *cpu_exit_irq;
896 int piix4_devfn;
897 i2c_bus *smbus;
898 int i;
899 DriveInfo *dinfo;
900 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
901 DriveInfo *fd[MAX_FD];
902 int fl_idx = 0;
903 int fl_sectors = bios_size >> 16;
904 int be;
906 DeviceState *dev = qdev_create(NULL, TYPE_MIPS_MALTA);
907 MaltaState *s = MIPS_MALTA(dev);
909 qdev_init_nofail(dev);
911 /* Make sure the first 3 serial ports are associated with a device. */
912 for(i = 0; i < 3; i++) {
913 if (!serial_hds[i]) {
914 char label[32];
915 snprintf(label, sizeof(label), "serial%d", i);
916 serial_hds[i] = qemu_chr_new(label, "null", NULL);
920 /* init CPUs */
921 if (cpu_model == NULL) {
922 #ifdef TARGET_MIPS64
923 cpu_model = "20Kc";
924 #else
925 cpu_model = "24Kf";
926 #endif
929 for (i = 0; i < smp_cpus; i++) {
930 cpu = cpu_mips_init(cpu_model);
931 if (cpu == NULL) {
932 fprintf(stderr, "Unable to find CPU definition\n");
933 exit(1);
935 env = &cpu->env;
937 /* Init internal devices */
938 cpu_mips_irq_init_cpu(env);
939 cpu_mips_clock_init(env);
940 qemu_register_reset(main_cpu_reset, cpu);
942 cpu = MIPS_CPU(first_cpu);
943 env = &cpu->env;
945 /* allocate RAM */
946 if (ram_size > (256 << 20)) {
947 fprintf(stderr,
948 "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
949 ((unsigned int)ram_size / (1 << 20)));
950 exit(1);
952 memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size);
953 vmstate_register_ram_global(ram);
954 memory_region_add_subregion(system_memory, 0, ram);
956 /* generate SPD EEPROM data */
957 generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size);
958 generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
960 #ifdef TARGET_WORDS_BIGENDIAN
961 be = 1;
962 #else
963 be = 0;
964 #endif
965 /* FPGA */
966 /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */
967 malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[4], serial_hds[2]);
969 /* Load firmware in flash / BIOS. */
970 dinfo = drive_get(IF_PFLASH, 0, fl_idx);
971 #ifdef DEBUG_BOARD_INIT
972 if (dinfo) {
973 printf("Register parallel flash %d size " TARGET_FMT_lx " at "
974 "addr %08llx '%s' %x\n",
975 fl_idx, bios_size, FLASH_ADDRESS,
976 bdrv_get_device_name(dinfo->bdrv), fl_sectors);
978 #endif
979 fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
980 BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
981 65536, fl_sectors,
982 4, 0x0000, 0x0000, 0x0000, 0x0000, be);
983 bios = pflash_cfi01_get_memory(fl);
984 fl_idx++;
985 if (kernel_filename) {
986 /* Write a small bootloader to the flash location. */
987 loaderparams.ram_size = ram_size;
988 loaderparams.kernel_filename = kernel_filename;
989 loaderparams.kernel_cmdline = kernel_cmdline;
990 loaderparams.initrd_filename = initrd_filename;
991 kernel_entry = load_kernel();
992 write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
993 } else {
994 /* Load firmware from flash. */
995 if (!dinfo) {
996 /* Load a BIOS image. */
997 if (bios_name == NULL) {
998 bios_name = BIOS_FILENAME;
1000 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
1001 if (filename) {
1002 bios_size = load_image_targphys(filename, FLASH_ADDRESS,
1003 BIOS_SIZE);
1004 g_free(filename);
1005 } else {
1006 bios_size = -1;
1008 if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
1009 fprintf(stderr,
1010 "qemu: Warning, could not load MIPS bios '%s', and no -kernel argument was specified\n",
1011 bios_name);
1014 /* In little endian mode the 32bit words in the bios are swapped,
1015 a neat trick which allows bi-endian firmware. */
1016 #ifndef TARGET_WORDS_BIGENDIAN
1018 uint32_t *end, *addr = rom_ptr(FLASH_ADDRESS);
1019 if (!addr) {
1020 addr = memory_region_get_ram_ptr(bios);
1022 end = (void *)addr + MIN(bios_size, 0x3e0000);
1023 while (addr < end) {
1024 bswap32s(addr);
1025 addr++;
1028 #endif
1032 * Map the BIOS at a 2nd physical location, as on the real board.
1033 * Copy it so that we can patch in the MIPS revision, which cannot be
1034 * handled by an overlapping region as the resulting ROM code subpage
1035 * regions are not executable.
1037 memory_region_init_ram(bios_copy, NULL, "bios.1fc", BIOS_SIZE);
1038 if (!rom_copy(memory_region_get_ram_ptr(bios_copy),
1039 FLASH_ADDRESS, bios_size)) {
1040 memcpy(memory_region_get_ram_ptr(bios_copy),
1041 memory_region_get_ram_ptr(bios), bios_size);
1043 memory_region_set_readonly(bios_copy, true);
1044 memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_copy);
1046 /* Board ID = 0x420 (Malta Board with CoreLV) */
1047 stl_p(memory_region_get_ram_ptr(bios_copy) + 0x10, 0x00000420);
1049 /* Init internal devices */
1050 cpu_mips_irq_init_cpu(env);
1051 cpu_mips_clock_init(env);
1054 * We have a circular dependency problem: pci_bus depends on isa_irq,
1055 * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
1056 * on piix4, and piix4 depends on pci_bus. To stop the cycle we have
1057 * qemu_irq_proxy() adds an extra bit of indirection, allowing us
1058 * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
1060 isa_irq = qemu_irq_proxy(&s->i8259, 16);
1062 /* Northbridge */
1063 pci_bus = gt64120_register(isa_irq);
1065 /* Southbridge */
1066 ide_drive_get(hd, MAX_IDE_BUS);
1068 piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
1070 /* Interrupt controller */
1071 /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
1072 s->i8259 = i8259_init(isa_bus, env->irq[2]);
1074 isa_bus_irqs(isa_bus, s->i8259);
1075 pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
1076 pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
1077 smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
1078 isa_get_irq(NULL, 9), NULL, 0, NULL);
1079 smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size);
1080 g_free(smbus_eeprom_buf);
1081 pit = pit_init(isa_bus, 0x40, 0, NULL);
1082 cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
1083 DMA_init(0, cpu_exit_irq);
1085 /* Super I/O */
1086 isa_create_simple(isa_bus, "i8042");
1088 rtc_init(isa_bus, 2000, NULL);
1089 serial_isa_init(isa_bus, 0, serial_hds[0]);
1090 serial_isa_init(isa_bus, 1, serial_hds[1]);
1091 if (parallel_hds[0])
1092 parallel_init(isa_bus, 0, parallel_hds[0]);
1093 for(i = 0; i < MAX_FD; i++) {
1094 fd[i] = drive_get(IF_FLOPPY, 0, i);
1096 fdctrl_init_isa(isa_bus, fd);
1098 /* Network card */
1099 network_init(pci_bus);
1101 /* Optional PCI video card */
1102 pci_vga_init(pci_bus);
1105 static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
1107 return 0;
1110 static void mips_malta_class_init(ObjectClass *klass, void *data)
1112 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
1114 k->init = mips_malta_sysbus_device_init;
1117 static const TypeInfo mips_malta_device = {
1118 .name = TYPE_MIPS_MALTA,
1119 .parent = TYPE_SYS_BUS_DEVICE,
1120 .instance_size = sizeof(MaltaState),
1121 .class_init = mips_malta_class_init,
1124 static QEMUMachine mips_malta_machine = {
1125 .name = "malta",
1126 .desc = "MIPS Malta Core LV",
1127 .init = mips_malta_init,
1128 .max_cpus = 16,
1129 .is_default = 1,
1130 DEFAULT_MACHINE_OPTIONS,
1133 static void mips_malta_register_types(void)
1135 type_register_static(&mips_malta_device);
1138 static void mips_malta_machine_init(void)
1140 qemu_register_machine(&mips_malta_machine);
1143 type_init(mips_malta_register_types)
1144 machine_init(mips_malta_machine_init);