static void dump_spd_data(void) { int dimm, offset, regs; unsigned int val; for (dimm = 0; dimm < 8; dimm++) { print_debug("SPD Data for DIMM "); print_debug_hex8(dimm); print_debug("\n"); val = get_spd_data(dimm, 0); if (val == 0xff) { regs = 256; } else if (val == 0x80) { regs = 128; } else { print_debug("No DIMM present\n"); regs = 0; } for (offset = 0; offset < regs; offset++) { print_debug(" Offset "); print_debug_hex8(offset); print_debug(" = 0x"); print_debug_hex8(get_spd_data(dimm, offset)); print_debug("\n"); } } }
static void dump_spd_data(const struct mem_controller *ctrl) { int dimm, offset, regs; unsigned int val; for (dimm = 0; dimm < DIMM_SOCKETS; dimm++) { print_debug("SPD Data for DIMM "); print_debug_hex8(dimm); print_debug("\n"); val = get_spd_data(ctrl, dimm, 0); if (val == 0xff) { regs = 256; } else if (val == 0x80) { regs = 128; } else { print_debug("No DIMM present\n"); regs = 0; } for (offset = 0; offset < regs; offset++) { print_debug(" Offset "); print_debug_hex8(offset); print_debug(" = 0x"); print_debug_hex8(get_spd_data(ctrl, dimm, offset)); print_debug("\n"); } } }
static void dump_spd_data(void) { int dimm, offset, regs; unsigned int val; for (dimm = 0; dimm < 8; dimm++) { printk(BIOS_DEBUG, "SPD Data for DIMM %02x\n", dimm); val = get_spd_data(dimm, 0); if (val == 0xff) { regs = 256; } else if (val == 0x80) { regs = 128; } else { printk(BIOS_DEBUG, "No DIMM present\n"); regs = 0; } for (offset = 0; offset < regs; offset++) printk(BIOS_DEBUG, " Offset %02x = 0x%02x\n", offset, get_spd_data(dimm, offset)); } }
CB_STATUS GetSPDData(u8 Slot, u8 Length, u8 *Buf) { // CB_STATUS Status = CB_NOT_READY; u8 Val, i; if (1 > Length || NULL == Buf) return CB_INVALID_PARAMETER; for (i = 0; i < Length; i++) { Val = get_spd_data(ctrl.channel0[Slot], i); *(Buf + i) = Val; } return CB_SUCCESS; }
static void dump_spd_data(const struct mem_controller *ctrl) { int dimm, offset, regs; unsigned int val; for (dimm = 0; dimm < DIMM_SOCKETS; dimm++) { printk(BIOS_DEBUG, "SPD Data for DIMM %02x\n", dimm); val = get_spd_data(ctrl, dimm, 0); if (val == 0xff) { regs = 256; } else if (val == 0x80) { regs = 128; } else { printk(BIOS_DEBUG, "No DIMM present\n"); regs = 0; } for (offset = 0; offset < regs; offset++) { printk(BIOS_DEBUG, " Offset %02x = 0x%02x\n", offset, get_spd_data(ctrl, dimm, offset)); } } }
/** * A fixup for some systems that need time for the SMBus to "warm up". This is * needed on some VT823x based systems, where the SMBus spurts out bad data for * a short time after power on. This has been seen on the VIA Epia series and * Jetway J7F2-series. It reads the ID byte from SMBus, looking for * known-good data from a slot/address. Exits on either good data or a timeout. * * TODO: This should probably go into some global file, but one would need to * be created just for it. If some other chip needs/wants it, we can * worry about it then. * * @param mem_ctrl The memory controller and SMBus addresses. */ void smbus_fixup(const struct mem_controller *mem_ctrl) { int i, ram_slots, current_slot = 0; u8 result = 0; ram_slots = ARRAY_SIZE(mem_ctrl->channel0); if (!ram_slots) { printk(BIOS_ERR, "smbus_fixup() thinks there are no RAM slots!\n"); return; } DEBUG("Waiting for SMBus to warm up"); /* * Bad SPD data should be either 0 or 0xff, but YMMV. So we look for * the ID bytes of SDRAM, DDR, DDR2, and DDR3 (and anything in between). * VT8237R has only been seen on DDR and DDR2 based systems, so far. */ for (i = 0; (i < SMBUS_TIMEOUT && ((result < SPD_MEMORY_TYPE_SDRAM) || (result > SPD_MEMORY_TYPE_SDRAM_DDR3))); i++) { if (current_slot > ram_slots) current_slot = 0; result = get_spd_data(mem_ctrl->channel0[current_slot], SPD_MEMORY_TYPE); current_slot++; DEBUG("."); } if (i >= SMBUS_TIMEOUT) printk(BIOS_ERR, "SMBus timed out while warming up\n"); else DEBUG("Done\n"); }
/* * Get SPD data and set RANK presence map. * * Sockets0,1 is Channel A / Sockets2,3 is Channel B. * * Socket0 SPD device address 0x50 / socket1 SPD device address 0x51 * Socket2 SPD device address 0x52 / socket3 SPD device address 0x53 */ CB_STATUS GetInfoFromSPD(DRAM_SYS_ATTR *DramAttr) { CB_STATUS Status; u8 *pSPDDataBuf; u8 ModuleDataWidth, ChipWidth, RankNum, LoadNum, Sockets, i; BOOLEAN bFind; /* FIXME: We don't have/want BOOLEAN. */ bFind = FALSE; /* FIXME: We don't have/want FALSE. */ Status = CB_DEVICE_ERROR; for (Sockets = 0; Sockets < MAX_SOCKETS; Sockets++) { pSPDDataBuf = DramAttr->DimmInfo[Sockets].SPDDataBuf; pSPDDataBuf[SPD_MEMORY_TYPE] = get_spd_data(ctrl.channel0[Sockets], SPD_MEMORY_TYPE); if (pSPDDataBuf[SPD_MEMORY_TYPE] == 0) { Status = CB_NOT_READY; } else { Status = GetSPDData(Sockets, SPD_DATA_SIZE, pSPDDataBuf); PRINT_DEBUG_MEM("SPD : \r"); for (i = 0; i < SPD_DATA_SIZE; i++) { PRINT_DEBUG_MEM(" "); PRINT_DEBUG_MEM_HEX8(pSPDDataBuf[i]); } } if (CB_SUCCESS == Status) { /* * If DRAM controller detected type not same as the * type got from SPD, there are ERROR. */ if (pSPDDataBuf[SPD_MEMORY_TYPE] != DramAttr->DramType) { Status = CB_DEVICE_ERROR; /* memory int error */ PRINT_DEBUG_MEM("Memory Device ERROR: DRAM " "controller detected type != " "type got from SPD\r"); break; } DramAttr->DimmInfo[Sockets].bPresence = TRUE; /* Calculate load number (chips number). */ ModuleDataWidth = (u8) (DramAttr-> DimmInfo[Sockets].SPDDataBuf [SPD_SDRAM_MOD_DATA_WIDTH + 1]); ModuleDataWidth = (u8) (ModuleDataWidth << 8); ModuleDataWidth |= (u8) (DramAttr-> DimmInfo[Sockets].SPDDataBuf [SPD_SDRAM_MOD_DATA_WIDTH]); ChipWidth = (u8) ((DramAttr-> DimmInfo[Sockets].SPDDataBuf [SPD_SDRAM_WIDTH]) & 0x7F); LoadNum = (u8) (ModuleDataWidth / ChipWidth); /* Set the RANK map. */ /* Get bit0,1, the most number of supported RANK is 2. */ RankNum = (u8) (pSPDDataBuf[SPD_SDRAM_DIMM_RANKS] & 0x3); if (RAMTYPE_SDRAMDDR2 == DramAttr->DramType) /* * For DDR bit[0,1]: 01->1 RANK, 10->2 RANK * For DDR2 bit[0,1]: 00->1 RANK, 01->2 RANK */ RankNum++; /* Every DIMM have 1 or 2 ranks. */ if (RankNum != 2 && RankNum != 1) { Status = CB_DEVICE_ERROR; PRINT_DEBUG_MEM("Memory Device ERROR: Number " "of RANK not supported!\r"); break; } if (Sockets < 2) { /* Sockets0,1 is channel A */ DramAttr->RankNumChA = (u8) (DramAttr->RankNumChA + RankNum); DramAttr->DimmNumChA++; DramAttr->LoadNumChA = (u8) (DramAttr->LoadNumChA * LoadNum * RankNum); } else { /* Sockets2,3 is channel B */ DramAttr->RankNumChB = (u8) (DramAttr->RankNumChB + RankNum); DramAttr->DimmNumChB++; DramAttr->LoadNumChB = (u8) (DramAttr->LoadNumChB * LoadNum * RankNum);; } RankNum |= 1; /* Set rank map. */ DramAttr->RankPresentMap |= (RankNum << (Sockets * 2)); bFind = TRUE; } } PRINT_DEBUG_MEM("Rank Present Map:"); PRINT_DEBUG_MEM_HEX8(DramAttr->RankPresentMap); PRINT_DEBUG_MEM("\r"); if (bFind) Status = CB_SUCCESS; return Status; }