diff options
Diffstat (limited to 'hw/mips')
-rw-r--r-- | hw/mips/mips_malta.c | 133 |
1 files changed, 87 insertions, 46 deletions
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index a740f614f7..28c351d83d 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -149,7 +149,7 @@ struct _eeprom24c0x_t { typedef struct _eeprom24c0x_t eeprom24c0x_t; -static eeprom24c0x_t eeprom = { +static eeprom24c0x_t spd_eeprom = { .contents = { /* 00000000: */ 0x80,0x08,0xFF,0x0D,0x0A,0xFF,0x40,0x00, /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01, @@ -170,10 +170,10 @@ static eeprom24c0x_t eeprom = { }, }; -static void eeprom_generate(eeprom24c0x_t *eeprom, ram_addr_t ram_size) +static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size) { enum { SDR = 0x4, DDR2 = 0x8 } type; - uint8_t *spd = eeprom->contents; + uint8_t *spd = spd_eeprom.contents; uint8_t nbanks = 0; uint16_t density = 0; int i; @@ -218,71 +218,109 @@ static void eeprom_generate(eeprom24c0x_t *eeprom, ram_addr_t ram_size) for (i = 0; i < 63; i++) { spd[63] += spd[i]; } + + /* copy for SMBUS */ + memcpy(eeprom, spd, sizeof(spd_eeprom.contents)); +} + +static void generate_eeprom_serial(uint8_t *eeprom) +{ + int i, pos = 0; + uint8_t mac[6] = { 0x00 }; + uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 }; + + /* version */ + eeprom[pos++] = 0x01; + + /* count */ + eeprom[pos++] = 0x02; + + /* MAC address */ + eeprom[pos++] = 0x01; /* MAC */ + eeprom[pos++] = 0x06; /* length */ + memcpy(&eeprom[pos], mac, sizeof(mac)); + pos += sizeof(mac); + + /* serial number */ + eeprom[pos++] = 0x02; /* serial */ + eeprom[pos++] = 0x05; /* length */ + memcpy(&eeprom[pos], sn, sizeof(sn)); + pos += sizeof(sn); + + /* checksum */ + eeprom[pos] = 0; + for (i = 0; i < pos; i++) { + eeprom[pos] += eeprom[i]; + } } -static uint8_t eeprom24c0x_read(void) +static uint8_t eeprom24c0x_read(eeprom24c0x_t *eeprom) { logout("%u: scl = %u, sda = %u, data = 0x%02x\n", - eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data); - return eeprom.sda; + eeprom->tick, eeprom->scl, eeprom->sda, eeprom->data); + return eeprom->sda; } -static void eeprom24c0x_write(int scl, int sda) +static void eeprom24c0x_write(eeprom24c0x_t *eeprom, int scl, int sda) { - if (eeprom.scl && scl && (eeprom.sda != sda)) { + if (eeprom->scl && scl && (eeprom->sda != sda)) { logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n", - eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start"); + eeprom->tick, eeprom->scl, scl, eeprom->sda, sda, + sda ? "stop" : "start"); if (!sda) { - eeprom.tick = 1; - eeprom.command = 0; + eeprom->tick = 1; + eeprom->command = 0; } - } else if (eeprom.tick == 0 && !eeprom.ack) { + } else if (eeprom->tick == 0 && !eeprom->ack) { /* Waiting for start. */ logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n", - eeprom.tick, eeprom.scl, scl, eeprom.sda, sda); - } else if (!eeprom.scl && scl) { + eeprom->tick, eeprom->scl, scl, eeprom->sda, sda); + } else if (!eeprom->scl && scl) { logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n", - eeprom.tick, eeprom.scl, scl, eeprom.sda, sda); - if (eeprom.ack) { + eeprom->tick, eeprom->scl, scl, eeprom->sda, sda); + if (eeprom->ack) { logout("\ti2c ack bit = 0\n"); sda = 0; - eeprom.ack = 0; - } else if (eeprom.sda == sda) { + eeprom->ack = 0; + } else if (eeprom->sda == sda) { uint8_t bit = (sda != 0); logout("\ti2c bit = %d\n", bit); - if (eeprom.tick < 9) { - eeprom.command <<= 1; - eeprom.command += bit; - eeprom.tick++; - if (eeprom.tick == 9) { - logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write"); - eeprom.ack = 1; + if (eeprom->tick < 9) { + eeprom->command <<= 1; + eeprom->command += bit; + eeprom->tick++; + if (eeprom->tick == 9) { + logout("\tcommand 0x%04x, %s\n", eeprom->command, + bit ? "read" : "write"); + eeprom->ack = 1; } - } else if (eeprom.tick < 17) { - if (eeprom.command & 1) { - sda = ((eeprom.data & 0x80) != 0); + } else if (eeprom->tick < 17) { + if (eeprom->command & 1) { + sda = ((eeprom->data & 0x80) != 0); } - eeprom.address <<= 1; - eeprom.address += bit; - eeprom.tick++; - eeprom.data <<= 1; - if (eeprom.tick == 17) { - eeprom.data = eeprom.contents[eeprom.address]; - logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data); - eeprom.ack = 1; - eeprom.tick = 0; + eeprom->address <<= 1; + eeprom->address += bit; + eeprom->tick++; + eeprom->data <<= 1; + if (eeprom->tick == 17) { + eeprom->data = eeprom->contents[eeprom->address]; + logout("\taddress 0x%04x, data 0x%02x\n", + eeprom->address, eeprom->data); + eeprom->ack = 1; + eeprom->tick = 0; } - } else if (eeprom.tick >= 17) { + } else if (eeprom->tick >= 17) { sda = 0; } } else { logout("\tsda changed with raising scl\n"); } } else { - logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda); + logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom->tick, eeprom->scl, + scl, eeprom->sda, sda); } - eeprom.scl = scl; - eeprom.sda = sda; + eeprom->scl = scl; + eeprom->sda = sda; } static uint64_t malta_fpga_read(void *opaque, hwaddr addr, @@ -345,7 +383,7 @@ static uint64_t malta_fpga_read(void *opaque, hwaddr addr, /* I2CINP Register */ case 0x00b00: - val = ((s->i2cin & ~1) | eeprom24c0x_read()); + val = ((s->i2cin & ~1) | eeprom24c0x_read(&spd_eeprom)); break; /* I2COE Register */ @@ -441,7 +479,7 @@ static void malta_fpga_write(void *opaque, hwaddr addr, /* I2COUT Register */ case 0x00b10: - eeprom24c0x_write(val & 0x02, val & 0x01); + eeprom24c0x_write(&spd_eeprom, val & 0x02, val & 0x01); s->i2cout = val; break; @@ -846,6 +884,8 @@ void mips_malta_init(QEMUMachineInitArgs *args) MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1); target_long bios_size = FLASH_SIZE; + const size_t smbus_eeprom_size = 8 * 256; + uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size); int64_t kernel_entry; PCIBus *pci_bus; ISABus *isa_bus; @@ -914,7 +954,8 @@ void mips_malta_init(QEMUMachineInitArgs *args) memory_region_add_subregion(system_memory, 0, ram); /* generate SPD EEPROM data */ - eeprom_generate(&eeprom, ram_size); + generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size); + generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]); #ifdef TARGET_WORDS_BIGENDIAN be = 1; @@ -1035,8 +1076,8 @@ void mips_malta_init(QEMUMachineInitArgs *args) pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci"); smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100, isa_get_irq(NULL, 9), NULL, 0, NULL); - /* TODO: Populate SPD eeprom data. */ - smbus_eeprom_init(smbus, 8, NULL, 0); + smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size); + g_free(smbus_eeprom_buf); pit = pit_init(isa_bus, 0x40, 0, NULL); cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1); DMA_init(0, cpu_exit_irq); |