summaryrefslogtreecommitdiff
path: root/src/soc/intel/common/block
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/common/block')
-rw-r--r--src/soc/intel/common/block/smbus/smbuslib.c77
1 files changed, 73 insertions, 4 deletions
diff --git a/src/soc/intel/common/block/smbus/smbuslib.c b/src/soc/intel/common/block/smbus/smbuslib.c
index e2df73025f..0680ce2b8e 100644
--- a/src/soc/intel/common/block/smbus/smbuslib.c
+++ b/src/soc/intel/common/block/smbus/smbuslib.c
@@ -14,8 +14,10 @@
*/
#include <arch/io.h>
-#include <device/early_smbus.h>
+#include <console/console.h>
#include <device/smbus_def.h>
+#include <spd_bin.h>
+#include <string.h>
#include <timer.h>
#include "smbuslib.h"
@@ -176,17 +178,84 @@ int do_smbus_read_word(unsigned int smbus_base, u8 device, unsigned int address)
return data;
}
-u16 smbus_read_word(u8 addr, u8 offset)
+static u16 smbus_read_word(u8 addr, u8 offset)
{
return do_smbus_read_word(SMBUS_IO_BASE, addr, offset);
}
-u8 smbus_read_byte(u8 addr, u8 offset)
+static u8 smbus_read_byte(u8 addr, u8 offset)
{
return do_smbus_read_byte(SMBUS_IO_BASE, addr, offset);
}
-u8 smbus_write_byte(u8 addr, u8 offset, u8 value)
+static u8 smbus_write_byte(u8 addr, u8 offset, u8 value)
{
return do_smbus_write_byte(SMBUS_IO_BASE, addr, offset, value);
}
+
+static void update_spd_len(struct spd_block *blk)
+{
+ u8 i, j = 0;
+ for (i = 0 ; i < CONFIG_DIMM_MAX; i++)
+ if (blk->spd_array[i] != NULL)
+ j |= blk->spd_array[i][SPD_DRAM_TYPE];
+
+ /* If spd used is DDR4, then its length is 512 byte. */
+ if (j == SPD_DRAM_DDR4)
+ blk->len = SPD_PAGE_LEN_DDR4;
+ else
+ blk->len = SPD_PAGE_LEN;
+}
+
+static void smbus_read_spd(u8 *spd, u8 addr)
+{
+ u16 i;
+ u8 step = 1;
+
+ if (CONFIG(SPD_READ_BY_WORD))
+ step = sizeof(uint16_t);
+
+ for (i = 0; i < SPD_PAGE_LEN; i += step) {
+ if (CONFIG(SPD_READ_BY_WORD))
+ ((u16*)spd)[i / sizeof(uint16_t)] =
+ smbus_read_word(addr, i);
+ else
+ spd[i] = smbus_read_byte(addr, i);
+ }
+}
+
+static void get_spd(u8 *spd, u8 addr)
+{
+ if (smbus_read_byte(addr, 0) == 0xff) {
+ printk(BIOS_INFO, "No memory dimm at address %02X\n",
+ addr << 1);
+ /* Make sure spd is zeroed if dimm doesn't exist. */
+ memset(spd, 0, CONFIG_DIMM_SPD_SIZE);
+ return;
+ }
+ smbus_read_spd(spd, addr);
+
+ /* Check if module is DDR4, DDR4 spd is 512 byte. */
+ if (spd[SPD_DRAM_TYPE] == SPD_DRAM_DDR4 &&
+ CONFIG_DIMM_SPD_SIZE > SPD_PAGE_LEN) {
+ /* Switch to page 1 */
+ smbus_write_byte(SPD_PAGE_1, 0, 0);
+ smbus_read_spd(spd + SPD_PAGE_LEN, addr);
+ /* Restore to page 0 */
+ smbus_write_byte(SPD_PAGE_0, 0, 0);
+ }
+}
+
+static u8 spd_data[CONFIG_DIMM_MAX * CONFIG_DIMM_SPD_SIZE];
+
+void get_spd_smbus(struct spd_block *blk)
+{
+ u8 i;
+ for (i = 0 ; i < CONFIG_DIMM_MAX; i++) {
+ get_spd(&spd_data[i * CONFIG_DIMM_SPD_SIZE],
+ blk->addr_map[i]);
+ blk->spd_array[i] = &spd_data[i * CONFIG_DIMM_SPD_SIZE];
+ }
+
+ update_spd_len(blk);
+}