13fffc223Sths /* 23fffc223Sths * QEMU SMBus EEPROM device 33fffc223Sths * 43fffc223Sths * Copyright (c) 2007 Arastra, Inc. 53fffc223Sths * 63fffc223Sths * Permission is hereby granted, free of charge, to any person obtaining a copy 73fffc223Sths * of this software and associated documentation files (the "Software"), to deal 83fffc223Sths * in the Software without restriction, including without limitation the rights 93fffc223Sths * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 103fffc223Sths * copies of the Software, and to permit persons to whom the Software is 113fffc223Sths * furnished to do so, subject to the following conditions: 123fffc223Sths * 133fffc223Sths * The above copyright notice and this permission notice shall be included in 143fffc223Sths * all copies or substantial portions of the Software. 153fffc223Sths * 163fffc223Sths * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 173fffc223Sths * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 183fffc223Sths * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 193fffc223Sths * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 203fffc223Sths * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 213fffc223Sths * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 223fffc223Sths * THE SOFTWARE. 233fffc223Sths */ 243fffc223Sths 250430891cSPeter Maydell #include "qemu/osdep.h" 26b296b664SBALATON Zoltan #include "qemu/units.h" 27b296b664SBALATON Zoltan #include "qapi/error.h" 28fd9df33fSCorey Minyard #include "hw/boards.h" 290d09e41aSPaolo Bonzini #include "hw/i2c/i2c.h" 3093198b6cSCorey Minyard #include "hw/i2c/smbus_slave.h" 31a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 32d6454270SMarkus Armbruster #include "migration/vmstate.h" 3393198b6cSCorey Minyard #include "hw/i2c/smbus_eeprom.h" 343fffc223Sths 353fffc223Sths //#define DEBUG 363fffc223Sths 37b398a924SCorey Minyard #define TYPE_SMBUS_EEPROM "smbus-eeprom" 38b398a924SCorey Minyard 39b398a924SCorey Minyard #define SMBUS_EEPROM(obj) \ 40b398a924SCorey Minyard OBJECT_CHECK(SMBusEEPROMDevice, (obj), TYPE_SMBUS_EEPROM) 41b398a924SCorey Minyard 420cf487e5SCorey Minyard #define SMBUS_EEPROM_SIZE 256 430cf487e5SCorey Minyard 443fffc223Sths typedef struct SMBusEEPROMDevice { 451ea96673SPaul Brook SMBusDevice smbusdev; 46fd9df33fSCorey Minyard uint8_t data[SMBUS_EEPROM_SIZE]; 47*b9751d20SMarc-André Lureau uint8_t *init_data; 483fffc223Sths uint8_t offset; 49fd9df33fSCorey Minyard bool accessed; 503fffc223Sths } SMBusEEPROMDevice; 513fffc223Sths 523fffc223Sths static uint8_t eeprom_receive_byte(SMBusDevice *dev) 533fffc223Sths { 54b398a924SCorey Minyard SMBusEEPROMDevice *eeprom = SMBUS_EEPROM(dev); 55bf2782d7SGerd Hoffmann uint8_t *data = eeprom->data; 56bf2782d7SGerd Hoffmann uint8_t val = data[eeprom->offset++]; 578b38e532SCorey Minyard 58fd9df33fSCorey Minyard eeprom->accessed = true; 593fffc223Sths #ifdef DEBUG 60ab7d9131Sbalrog printf("eeprom_receive_byte: addr=0x%02x val=0x%02x\n", 61ab7d9131Sbalrog dev->i2c.address, val); 623fffc223Sths #endif 633fffc223Sths return val; 643fffc223Sths } 653fffc223Sths 669cf27d74SCorey Minyard static int eeprom_write_data(SMBusDevice *dev, uint8_t *buf, uint8_t len) 673fffc223Sths { 68b398a924SCorey Minyard SMBusEEPROMDevice *eeprom = SMBUS_EEPROM(dev); 699cf27d74SCorey Minyard uint8_t *data = eeprom->data; 709cf27d74SCorey Minyard 71fd9df33fSCorey Minyard eeprom->accessed = true; 723fffc223Sths #ifdef DEBUG 73ab7d9131Sbalrog printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n", 749cf27d74SCorey Minyard dev->i2c.address, buf[0], buf[1]); 753fffc223Sths #endif 769cf27d74SCorey Minyard /* len is guaranteed to be > 0 */ 779cf27d74SCorey Minyard eeprom->offset = buf[0]; 789cf27d74SCorey Minyard buf++; 799cf27d74SCorey Minyard len--; 809cf27d74SCorey Minyard 819cf27d74SCorey Minyard for (; len > 0; len--) { 829cf27d74SCorey Minyard data[eeprom->offset] = *buf++; 830cf487e5SCorey Minyard eeprom->offset = (eeprom->offset + 1) % SMBUS_EEPROM_SIZE; 843fffc223Sths } 853fffc223Sths 869cf27d74SCorey Minyard return 0; 879cf27d74SCorey Minyard } 889cf27d74SCorey Minyard 89fd9df33fSCorey Minyard static bool smbus_eeprom_vmstate_needed(void *opaque) 90fd9df33fSCorey Minyard { 91fd9df33fSCorey Minyard MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); 92fd9df33fSCorey Minyard SMBusEEPROMDevice *eeprom = opaque; 93fd9df33fSCorey Minyard 94fd9df33fSCorey Minyard return (eeprom->accessed || smbus_vmstate_needed(&eeprom->smbusdev)) && 95fd9df33fSCorey Minyard !mc->smbus_no_migration_support; 96fd9df33fSCorey Minyard } 97fd9df33fSCorey Minyard 98fd9df33fSCorey Minyard static const VMStateDescription vmstate_smbus_eeprom = { 99fd9df33fSCorey Minyard .name = "smbus-eeprom", 100fd9df33fSCorey Minyard .version_id = 1, 101fd9df33fSCorey Minyard .minimum_version_id = 1, 102fd9df33fSCorey Minyard .needed = smbus_eeprom_vmstate_needed, 103fd9df33fSCorey Minyard .fields = (VMStateField[]) { 104fd9df33fSCorey Minyard VMSTATE_SMBUS_DEVICE(smbusdev, SMBusEEPROMDevice), 105fd9df33fSCorey Minyard VMSTATE_UINT8_ARRAY(data, SMBusEEPROMDevice, SMBUS_EEPROM_SIZE), 106fd9df33fSCorey Minyard VMSTATE_UINT8(offset, SMBusEEPROMDevice), 107fd9df33fSCorey Minyard VMSTATE_BOOL(accessed, SMBusEEPROMDevice), 108fd9df33fSCorey Minyard VMSTATE_END_OF_LIST() 109fd9df33fSCorey Minyard } 110fd9df33fSCorey Minyard }; 111fd9df33fSCorey Minyard 1121042b22dSCorey Minyard /* 1131042b22dSCorey Minyard * Reset the EEPROM contents to the initial state on a reset. This 1141042b22dSCorey Minyard * isn't really how an EEPROM works, of course, but the general 1151042b22dSCorey Minyard * principle of QEMU is to restore function on reset to what it would 1161042b22dSCorey Minyard * be if QEMU was stopped and started. 1171042b22dSCorey Minyard * 1181042b22dSCorey Minyard * The proper thing to do would be to have a backing blockdev to hold 1191042b22dSCorey Minyard * the contents and restore that on startup, and not do this on reset. 1201042b22dSCorey Minyard * But until that time, act as if we had been stopped and restarted. 1211042b22dSCorey Minyard */ 1221042b22dSCorey Minyard static void smbus_eeprom_reset(DeviceState *dev) 1233fffc223Sths { 124b398a924SCorey Minyard SMBusEEPROMDevice *eeprom = SMBUS_EEPROM(dev); 1250ff596d0Spbrook 126fd9df33fSCorey Minyard memcpy(eeprom->data, eeprom->init_data, SMBUS_EEPROM_SIZE); 1273fffc223Sths eeprom->offset = 0; 1283fffc223Sths } 1291ea96673SPaul Brook 1301042b22dSCorey Minyard static void smbus_eeprom_realize(DeviceState *dev, Error **errp) 1311042b22dSCorey Minyard { 132*b9751d20SMarc-André Lureau SMBusEEPROMDevice *eeprom = SMBUS_EEPROM(dev); 1331042b22dSCorey Minyard 134*b9751d20SMarc-André Lureau smbus_eeprom_reset(dev); 135*b9751d20SMarc-André Lureau if (eeprom->init_data == NULL) { 136*b9751d20SMarc-André Lureau error_setg(errp, "init_data cannot be NULL"); 137*b9751d20SMarc-André Lureau } 138*b9751d20SMarc-André Lureau } 13939bffca2SAnthony Liguori 140b5ea9327SAnthony Liguori static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data) 141b5ea9327SAnthony Liguori { 14239bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 143b5ea9327SAnthony Liguori SMBusDeviceClass *sc = SMBUS_DEVICE_CLASS(klass); 144b5ea9327SAnthony Liguori 14519473e51SPhilippe Mathieu-Daudé dc->realize = smbus_eeprom_realize; 1461042b22dSCorey Minyard dc->reset = smbus_eeprom_reset; 147b5ea9327SAnthony Liguori sc->receive_byte = eeprom_receive_byte; 148b5ea9327SAnthony Liguori sc->write_data = eeprom_write_data; 149fd9df33fSCorey Minyard dc->vmsd = &vmstate_smbus_eeprom; 150*b9751d20SMarc-André Lureau /* Reason: init_data */ 151e90f2a8cSEduardo Habkost dc->user_creatable = false; 152b5ea9327SAnthony Liguori } 153b5ea9327SAnthony Liguori 1548c43a6f0SAndreas Färber static const TypeInfo smbus_eeprom_info = { 155b398a924SCorey Minyard .name = TYPE_SMBUS_EEPROM, 15639bffca2SAnthony Liguori .parent = TYPE_SMBUS_DEVICE, 15739bffca2SAnthony Liguori .instance_size = sizeof(SMBusEEPROMDevice), 158b5ea9327SAnthony Liguori .class_init = smbus_eeprom_class_initfn, 1591ea96673SPaul Brook }; 1601ea96673SPaul Brook 16183f7d43aSAndreas Färber static void smbus_eeprom_register_types(void) 1621ea96673SPaul Brook { 16339bffca2SAnthony Liguori type_register_static(&smbus_eeprom_info); 1641ea96673SPaul Brook } 1651ea96673SPaul Brook 16683f7d43aSAndreas Färber type_init(smbus_eeprom_register_types) 167a88df0b9SIsaku Yamahata 168e2224214SCédric Le Goater void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf) 169e2224214SCédric Le Goater { 170e2224214SCédric Le Goater DeviceState *dev; 171e2224214SCédric Le Goater 172b398a924SCorey Minyard dev = qdev_create((BusState *) smbus, TYPE_SMBUS_EEPROM); 173e2224214SCédric Le Goater qdev_prop_set_uint8(dev, "address", address); 174*b9751d20SMarc-André Lureau /* FIXME: use an array of byte or block backend property? */ 175*b9751d20SMarc-André Lureau SMBUS_EEPROM(dev)->init_data = eeprom_buf; 176e2224214SCédric Le Goater qdev_init_nofail(dev); 177e2224214SCédric Le Goater } 178e2224214SCédric Le Goater 179a5c82852SAndreas Färber void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, 180a88df0b9SIsaku Yamahata const uint8_t *eeprom_spd, int eeprom_spd_size) 181a88df0b9SIsaku Yamahata { 182a88df0b9SIsaku Yamahata int i; 1830cf487e5SCorey Minyard /* XXX: make this persistent */ 184c203d451SCorey Minyard 185c203d451SCorey Minyard assert(nb_eeprom <= 8); 1860cf487e5SCorey Minyard uint8_t *eeprom_buf = g_malloc0(8 * SMBUS_EEPROM_SIZE); 187a88df0b9SIsaku Yamahata if (eeprom_spd_size > 0) { 188a88df0b9SIsaku Yamahata memcpy(eeprom_buf, eeprom_spd, eeprom_spd_size); 189a88df0b9SIsaku Yamahata } 190a88df0b9SIsaku Yamahata 191a88df0b9SIsaku Yamahata for (i = 0; i < nb_eeprom; i++) { 1920cf487e5SCorey Minyard smbus_eeprom_init_one(smbus, 0x50 + i, 1930cf487e5SCorey Minyard eeprom_buf + (i * SMBUS_EEPROM_SIZE)); 194a88df0b9SIsaku Yamahata } 195a88df0b9SIsaku Yamahata } 196b296b664SBALATON Zoltan 197b296b664SBALATON Zoltan /* Generate SDRAM SPD EEPROM data describing a module of type and size */ 198b296b664SBALATON Zoltan uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size, 199b296b664SBALATON Zoltan Error **errp) 200b296b664SBALATON Zoltan { 201b296b664SBALATON Zoltan uint8_t *spd; 202b296b664SBALATON Zoltan uint8_t nbanks; 203b296b664SBALATON Zoltan uint16_t density; 204b296b664SBALATON Zoltan uint32_t size; 205b296b664SBALATON Zoltan int min_log2, max_log2, sz_log2; 206b296b664SBALATON Zoltan int i; 207b296b664SBALATON Zoltan 208b296b664SBALATON Zoltan switch (type) { 209b296b664SBALATON Zoltan case SDR: 210b296b664SBALATON Zoltan min_log2 = 2; 211b296b664SBALATON Zoltan max_log2 = 9; 212b296b664SBALATON Zoltan break; 213b296b664SBALATON Zoltan case DDR: 214b296b664SBALATON Zoltan min_log2 = 5; 215b296b664SBALATON Zoltan max_log2 = 12; 216b296b664SBALATON Zoltan break; 217b296b664SBALATON Zoltan case DDR2: 218b296b664SBALATON Zoltan min_log2 = 7; 219b296b664SBALATON Zoltan max_log2 = 14; 220b296b664SBALATON Zoltan break; 221b296b664SBALATON Zoltan default: 222b296b664SBALATON Zoltan g_assert_not_reached(); 223b296b664SBALATON Zoltan } 224b296b664SBALATON Zoltan size = ram_size >> 20; /* work in terms of megabytes */ 225b296b664SBALATON Zoltan if (size < 4) { 226b296b664SBALATON Zoltan error_setg(errp, "SDRAM size is too small"); 227b296b664SBALATON Zoltan return NULL; 228b296b664SBALATON Zoltan } 229b296b664SBALATON Zoltan sz_log2 = 31 - clz32(size); 230b296b664SBALATON Zoltan size = 1U << sz_log2; 231b296b664SBALATON Zoltan if (ram_size > size * MiB) { 232b296b664SBALATON Zoltan error_setg(errp, "SDRAM size 0x"RAM_ADDR_FMT" is not a power of 2, " 233b296b664SBALATON Zoltan "truncating to %u MB", ram_size, size); 234b296b664SBALATON Zoltan } 235b296b664SBALATON Zoltan if (sz_log2 < min_log2) { 236b296b664SBALATON Zoltan error_setg(errp, 237b296b664SBALATON Zoltan "Memory size is too small for SDRAM type, adjusting type"); 238b296b664SBALATON Zoltan if (size >= 32) { 239b296b664SBALATON Zoltan type = DDR; 240b296b664SBALATON Zoltan min_log2 = 5; 241b296b664SBALATON Zoltan max_log2 = 12; 242b296b664SBALATON Zoltan } else { 243b296b664SBALATON Zoltan type = SDR; 244b296b664SBALATON Zoltan min_log2 = 2; 245b296b664SBALATON Zoltan max_log2 = 9; 246b296b664SBALATON Zoltan } 247b296b664SBALATON Zoltan } 248b296b664SBALATON Zoltan 249b296b664SBALATON Zoltan nbanks = 1; 250b296b664SBALATON Zoltan while (sz_log2 > max_log2 && nbanks < 8) { 251b296b664SBALATON Zoltan sz_log2--; 252b296b664SBALATON Zoltan nbanks++; 253b296b664SBALATON Zoltan } 254b296b664SBALATON Zoltan 255b296b664SBALATON Zoltan if (size > (1ULL << sz_log2) * nbanks) { 256b296b664SBALATON Zoltan error_setg(errp, "Memory size is too big for SDRAM, truncating"); 257b296b664SBALATON Zoltan } 258b296b664SBALATON Zoltan 259b296b664SBALATON Zoltan /* split to 2 banks if possible to avoid a bug in MIPS Malta firmware */ 260b296b664SBALATON Zoltan if (nbanks == 1 && sz_log2 > min_log2) { 261b296b664SBALATON Zoltan sz_log2--; 262b296b664SBALATON Zoltan nbanks++; 263b296b664SBALATON Zoltan } 264b296b664SBALATON Zoltan 265b296b664SBALATON Zoltan density = 1ULL << (sz_log2 - 2); 266b296b664SBALATON Zoltan switch (type) { 267b296b664SBALATON Zoltan case DDR2: 268b296b664SBALATON Zoltan density = (density & 0xe0) | (density >> 8 & 0x1f); 269b296b664SBALATON Zoltan break; 270b296b664SBALATON Zoltan case DDR: 271b296b664SBALATON Zoltan density = (density & 0xf8) | (density >> 8 & 0x07); 272b296b664SBALATON Zoltan break; 273b296b664SBALATON Zoltan case SDR: 274b296b664SBALATON Zoltan default: 275b296b664SBALATON Zoltan density &= 0xff; 276b296b664SBALATON Zoltan break; 277b296b664SBALATON Zoltan } 278b296b664SBALATON Zoltan 279b296b664SBALATON Zoltan spd = g_malloc0(256); 280b296b664SBALATON Zoltan spd[0] = 128; /* data bytes in EEPROM */ 281b296b664SBALATON Zoltan spd[1] = 8; /* log2 size of EEPROM */ 282b296b664SBALATON Zoltan spd[2] = type; 283b296b664SBALATON Zoltan spd[3] = 13; /* row address bits */ 284b296b664SBALATON Zoltan spd[4] = 10; /* column address bits */ 285b296b664SBALATON Zoltan spd[5] = (type == DDR2 ? nbanks - 1 : nbanks); 286b296b664SBALATON Zoltan spd[6] = 64; /* module data width */ 287b296b664SBALATON Zoltan /* reserved / data width high */ 288b296b664SBALATON Zoltan spd[8] = 4; /* interface voltage level */ 289b296b664SBALATON Zoltan spd[9] = 0x25; /* highest CAS latency */ 290b296b664SBALATON Zoltan spd[10] = 1; /* access time */ 291b296b664SBALATON Zoltan /* DIMM configuration 0 = non-ECC */ 292b296b664SBALATON Zoltan spd[12] = 0x82; /* refresh requirements */ 293b296b664SBALATON Zoltan spd[13] = 8; /* primary SDRAM width */ 294b296b664SBALATON Zoltan /* ECC SDRAM width */ 295b296b664SBALATON Zoltan spd[15] = (type == DDR2 ? 0 : 1); /* reserved / delay for random col rd */ 296b296b664SBALATON Zoltan spd[16] = 12; /* burst lengths supported */ 297b296b664SBALATON Zoltan spd[17] = 4; /* banks per SDRAM device */ 298b296b664SBALATON Zoltan spd[18] = 12; /* ~CAS latencies supported */ 299b296b664SBALATON Zoltan spd[19] = (type == DDR2 ? 0 : 1); /* reserved / ~CS latencies supported */ 300b296b664SBALATON Zoltan spd[20] = 2; /* DIMM type / ~WE latencies */ 301b296b664SBALATON Zoltan /* module features */ 302b296b664SBALATON Zoltan /* memory chip features */ 303b296b664SBALATON Zoltan spd[23] = 0x12; /* clock cycle time @ medium CAS latency */ 304b296b664SBALATON Zoltan /* data access time */ 305b296b664SBALATON Zoltan /* clock cycle time @ short CAS latency */ 306b296b664SBALATON Zoltan /* data access time */ 307b296b664SBALATON Zoltan spd[27] = 20; /* min. row precharge time */ 308b296b664SBALATON Zoltan spd[28] = 15; /* min. row active row delay */ 309b296b664SBALATON Zoltan spd[29] = 20; /* min. ~RAS to ~CAS delay */ 310b296b664SBALATON Zoltan spd[30] = 45; /* min. active to precharge time */ 311b296b664SBALATON Zoltan spd[31] = density; 312b296b664SBALATON Zoltan spd[32] = 20; /* addr/cmd setup time */ 313b296b664SBALATON Zoltan spd[33] = 8; /* addr/cmd hold time */ 314b296b664SBALATON Zoltan spd[34] = 20; /* data input setup time */ 315b296b664SBALATON Zoltan spd[35] = 8; /* data input hold time */ 316b296b664SBALATON Zoltan 317b296b664SBALATON Zoltan /* checksum */ 318b296b664SBALATON Zoltan for (i = 0; i < 63; i++) { 319b296b664SBALATON Zoltan spd[63] += spd[i]; 320b296b664SBALATON Zoltan } 321b296b664SBALATON Zoltan return spd; 322b296b664SBALATON Zoltan } 323