Skip to content

Commit

Permalink
sam460ex: Clean up SPD EEPROM creation
Browse files Browse the repository at this point in the history
Get rid of code from MIPS Malta board used to create SPD EEPROM data
(parts of which was not even needed for sam460ex) and use the generic
spd_data_generate() function to simplify this.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
  • Loading branch information
zbalaton authored and dgibson committed Feb 4, 2019
1 parent b296b66 commit 08fd991
Showing 1 changed file with 20 additions and 153 deletions.
173 changes: 20 additions & 153 deletions hw/ppc/sam460ex.c
Expand Up @@ -2,7 +2,7 @@
* QEMU aCube Sam460ex board emulation
*
* Copyright (c) 2012 François Revol
* Copyright (c) 2016-2018 BALATON Zoltan
* Copyright (c) 2016-2019 BALATON Zoltan
*
* This file is derived from hw/ppc440_bamboo.c,
* the copyright for that material belongs to the original owners.
Expand Down Expand Up @@ -87,135 +87,6 @@ struct boot_info {
uint32_t entry;
};

/*****************************************************************************/
/* SPD eeprom content from mips_malta.c */

struct _eeprom24c0x_t {
uint8_t tick;
uint8_t address;
uint8_t command;
uint8_t ack;
uint8_t scl;
uint8_t sda;
uint8_t data;
uint8_t contents[256];
};

typedef struct _eeprom24c0x_t eeprom24c0x_t;

static eeprom24c0x_t spd_eeprom = {
.contents = {
/* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00,
/* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01,
/* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
/* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF,
/* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00,
/* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0,
/* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4,
},
};

static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
{
enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type;
uint8_t *spd = spd_eeprom.contents;
uint8_t nbanks = 0;
uint16_t density = 0;
int i;

/* work in terms of MB */
ram_size /= MiB;

while ((ram_size >= 4) && (nbanks <= 2)) {
int sz_log2 = MIN(31 - clz32(ram_size), 14);
nbanks++;
density |= 1 << (sz_log2 - 2);
ram_size -= 1 << sz_log2;
}

/* split to 2 banks if possible */
if ((nbanks == 1) && (density > 1)) {
nbanks++;
density >>= 1;
}

if (density & 0xff00) {
density = (density & 0xe0) | ((density >> 8) & 0x1f);
type = DDR2;
} else if (!(density & 0x1f)) {
type = DDR2;
} else {
type = SDR;
}

if (ram_size) {
warn_report("SPD cannot represent final " RAM_ADDR_FMT "MB"
" of SDRAM", ram_size);
}

/* fill in SPD memory information */
spd[2] = type;
spd[5] = nbanks;
spd[31] = density;

/* XXX: this is totally random */
spd[9] = 0x10; /* CAS tcyc */
spd[18] = 0x20; /* CAS bit */
spd[23] = 0x10; /* CAS tcyc */
spd[25] = 0x10; /* CAS tcyc */

/* checksum */
spd[63] = 0;
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 int sam460ex_load_uboot(void)
{
DriveInfo *dinfo;
Expand Down Expand Up @@ -393,24 +264,23 @@ static void sam460ex_init(MachineState *machine)
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
hwaddr ram_bases[SDRAM_NR_BANKS];
hwaddr ram_sizes[SDRAM_NR_BANKS];
hwaddr ram_bases[SDRAM_NR_BANKS] = {0};
hwaddr ram_sizes[SDRAM_NR_BANKS] = {0};
MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
qemu_irq *irqs, *uic[4];
PCIBus *pci_bus;
PowerPCCPU *cpu;
CPUPPCState *env;
PPC4xxI2CState *i2c[2];
I2CBus *i2c;
hwaddr entry = UBOOT_ENTRY;
hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
target_long initrd_size = 0;
DeviceState *dev;
SysBusDevice *sbdev;
int success;
int i;
struct boot_info *boot_info;
const size_t smbus_eeprom_size = 8 * 256;
uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
uint8_t *spd_data;
Error *err = NULL;
int success;

cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
env = &cpu->env;
Expand Down Expand Up @@ -439,8 +309,6 @@ static void sam460ex_init(MachineState *machine)
uic[3] = ppcuic_init(env, &uic[0][16], 0xf0, 0, 1);

/* SDRAM controller */
memset(ram_bases, 0, sizeof(ram_bases));
memset(ram_sizes, 0, sizeof(ram_sizes));
/* put all RAM on first bank because board has one slot
* and firmware only checks that */
machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size, 1,
Expand All @@ -451,23 +319,22 @@ static void sam460ex_init(MachineState *machine)
ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
ram_bases, ram_sizes, 1);

/* generate SPD EEPROM data */
for (i = 0; i < SDRAM_NR_BANKS; i++) {
generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
}
generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);

/* IIC controllers */
/* IIC controllers and devices */
dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
i2c[0] = PPC4xx_I2C(dev);
object_property_set_bool(OBJECT(dev), true, "realized", NULL);
smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size);
g_free(smbus_eeprom_buf);
i2c_create_slave(i2c[0]->bus, "m41t80", 0x68);
i2c = PPC4xx_I2C(dev)->bus;
/* SPD EEPROM on RAM module */
spd_data = spd_data_generate(DDR2, ram_sizes[0], &err);
if (err) {
warn_report_err(err);
}
if (spd_data) {
spd_data[20] = 4; /* SO-DIMM module */
smbus_eeprom_init_one(i2c, 0x50, spd_data);
}
/* RTC */
i2c_create_slave(i2c, "m41t80", 0x68);

dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
i2c[1] = PPC4xx_I2C(dev);

/* External bus controller */
ppc405_ebc_init(env);
Expand Down

0 comments on commit 08fd991

Please sign in to comment.