Merge pull request #1558 from antmicro/msieron/sdram-spd
liblitedram: SPD read improvements
This commit is contained in:
commit
0a36ad1f6d
|
@ -227,7 +227,8 @@ class Builder:
|
|||
from litedram.init import get_sdram_phy_c_header
|
||||
sdram_contents = get_sdram_phy_c_header(
|
||||
self.soc.sdram.controller.settings.phy,
|
||||
self.soc.sdram.controller.settings.timing)
|
||||
self.soc.sdram.controller.settings.timing,
|
||||
self.soc.sdram.controller.settings.geom)
|
||||
write_to_file(os.path.join(self.generated_dir, "sdram_phy.h"), sdram_contents)
|
||||
|
||||
def _generate_csr_map(self):
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <libbase/i2c.h>
|
||||
|
||||
#include <liblitedram/sdram.h>
|
||||
#include <liblitedram/sdram_spd.h>
|
||||
#include <liblitedram/bist.h>
|
||||
|
||||
#include "../command.h"
|
||||
|
@ -354,14 +355,11 @@ define_command(sdram_mr_write, sdram_mr_write_handler, "Write SDRAM Mode Registe
|
|||
*
|
||||
*/
|
||||
#ifdef CONFIG_HAS_I2C
|
||||
#define SPD_RW_PREAMBLE 0b1010
|
||||
#define SPD_RW_ADDR(a210) ((SPD_RW_PREAMBLE << 3) | ((a210) & 0b111))
|
||||
|
||||
static void sdram_spd_handler(int nb_params, char **params)
|
||||
{
|
||||
char *c;
|
||||
unsigned char spdaddr;
|
||||
unsigned char buf[256];
|
||||
unsigned char buf[SDRAM_SPD_SIZE];
|
||||
int len = sizeof(buf);
|
||||
bool send_stop = true;
|
||||
|
||||
|
@ -388,7 +386,7 @@ static void sdram_spd_handler(int nb_params, char **params)
|
|||
}
|
||||
}
|
||||
|
||||
if (!i2c_read(SPD_RW_ADDR(spdaddr), 0, buf, len, send_stop, 1)) {
|
||||
if (!sdram_read_spd(spdaddr, 0, buf, (uint16_t)len, send_stop)) {
|
||||
printf("Error when reading SPD EEPROM");
|
||||
return;
|
||||
}
|
||||
|
@ -400,7 +398,7 @@ static void sdram_spd_handler(int nb_params, char **params)
|
|||
int cmp_result;
|
||||
cmp_result = memcmp(buf, (void *) SPD_BASE, SPD_SIZE);
|
||||
if (cmp_result == 0) {
|
||||
printf("Memory conents matches the data used for gateware generation\n");
|
||||
printf("Memory contents matches the data used for gateware generation\n");
|
||||
} else {
|
||||
printf("\nWARNING: memory differs from the data used during gateware generation:\n");
|
||||
dump_bytes((void *) SPD_BASE, SPD_SIZE, 0);
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <libbase/i2c.h>
|
||||
|
||||
#include <liblitedram/sdram.h>
|
||||
#include <liblitedram/utils.h>
|
||||
|
||||
#include <libliteeth/udp.h>
|
||||
#include <libliteeth/mdio.h>
|
||||
|
@ -131,18 +132,28 @@ __attribute__((__used__)) int main(int i, char **c)
|
|||
(1 << (CONFIG_BUS_ADDRESS_WIDTH - 30)));
|
||||
printf("\e[1mCSR\e[0m:\t\t%d-bit data\n",
|
||||
CONFIG_CSR_DATA_WIDTH);
|
||||
printf("\e[1mROM\e[0m:\t\t%dKiB\n", ROM_SIZE/1024);
|
||||
printf("\e[1mSRAM\e[0m:\t\t%dKiB\n", SRAM_SIZE/1024);
|
||||
printf("\e[1mROM\e[0m:\t\t");
|
||||
print_size(ROM_SIZE);
|
||||
printf("\n");
|
||||
printf("\e[1mSRAM\e[0m:\t\t");
|
||||
print_size(SRAM_SIZE);
|
||||
printf("\n");
|
||||
#ifdef CONFIG_L2_SIZE
|
||||
printf("\e[1mL2\e[0m:\t\t%dKiB\n", CONFIG_L2_SIZE/1024);
|
||||
printf("\e[1mL2\e[0m:\t\t");
|
||||
print_size(CONFIG_L2_SIZE);
|
||||
printf("\n");
|
||||
#endif
|
||||
#ifdef CSR_SPIFLASH_CORE_BASE
|
||||
printf("\e[1mFLASH\e[0m:\t\t%dKiB\n", SPIFLASH_MODULE_TOTAL_SIZE/1024);
|
||||
printf("\e[1mFLASH\e[0m:\t\t");
|
||||
print_size(SPIFLASH_MODULE_TOTAL_SIZE);
|
||||
printf("\n");
|
||||
#endif
|
||||
#ifdef MAIN_RAM_SIZE
|
||||
#ifdef CSR_SDRAM_BASE
|
||||
printf("\e[1mSDRAM\e[0m:\t\t%dKiB %d-bit @ %dMT/s ",
|
||||
MAIN_RAM_SIZE/1024,
|
||||
uint64_t supported_memory = sdram_get_supported_memory();
|
||||
printf("\e[1mSDRAM\e[0m:\t\t");
|
||||
print_size(supported_memory);
|
||||
printf(" %d-bit @ %dMT/s ",
|
||||
sdram_get_databits(),
|
||||
sdram_get_freq()/1000000);
|
||||
printf("(CL-%d",
|
||||
|
@ -150,9 +161,10 @@ __attribute__((__used__)) int main(int i, char **c)
|
|||
if (sdram_get_cwl() != -1)
|
||||
printf(" CWL-%d", sdram_get_cwl());
|
||||
printf(")\n");
|
||||
#else
|
||||
printf("\e[1mMAIN-RAM\e[0m:\t%dKiB \n", MAIN_RAM_SIZE/1024);
|
||||
#endif
|
||||
printf("\e[1mMAIN-RAM\e[0m:\t");
|
||||
print_size(MAIN_RAM_SIZE);
|
||||
printf("\n");
|
||||
#endif
|
||||
printf("\n");
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
include ../include/generated/variables.mak
|
||||
include $(SOC_DIRECTORY)/software/common.mak
|
||||
|
||||
OBJECTS = sdram.o bist.o sdram_dbg.o
|
||||
OBJECTS = sdram.o bist.o sdram_dbg.o sdram_spd.o utils.o
|
||||
|
||||
all: liblitedram.a
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
// This file is Copyright (c) 2023 Antmicro <www.antmicro.com>
|
||||
// License: BSD
|
||||
|
||||
#include <liblitedram/sdram_spd.h>
|
||||
|
||||
#ifdef CONFIG_HAS_I2C
|
||||
|
||||
#if defined(SDRAM_PHY_DDR4)
|
||||
/*
|
||||
* In DDR4, addresses 0x36 (SPA0) and 0x37 (SPA1) are used to switch between two 256 byte pages.
|
||||
*/
|
||||
static bool sdram_select_spd_page(uint8_t page) {
|
||||
uint8_t i2c_addr;
|
||||
|
||||
if (page == 0) {
|
||||
i2c_addr = 0x36;
|
||||
} else if (page == 1) {
|
||||
i2c_addr = 0x37;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return i2c_poll(i2c_addr);
|
||||
}
|
||||
#else
|
||||
static bool sdram_select_spd_page(uint8_t page) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool sdram_read_spd(uint8_t spd, uint16_t addr, uint8_t *buf, uint16_t len, bool send_stop) {
|
||||
uint8_t page;
|
||||
uint16_t offset;
|
||||
uint16_t temp_len;
|
||||
bool temp_send_stop = false;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
while (addr < SDRAM_SPD_SIZE && len > 0) {
|
||||
page = addr / SDRAM_SPD_PAGE_SIZE;
|
||||
ok &= sdram_select_spd_page(page);
|
||||
|
||||
offset = addr % SDRAM_SPD_PAGE_SIZE;
|
||||
|
||||
temp_len = SDRAM_SPD_PAGE_SIZE - offset;
|
||||
if (temp_len >= len) {
|
||||
temp_send_stop = send_stop;
|
||||
temp_len = len;
|
||||
}
|
||||
|
||||
ok &= i2c_read(SPD_RW_ADDR(spd), offset, &buf[page * SDRAM_SPD_PAGE_SIZE], len, temp_send_stop, 1);
|
||||
len -= temp_len;
|
||||
addr += temp_len;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
#else /* no CONFIG_HAS_I2C */
|
||||
bool sdram_read_spd(uint8_t spd, uint16_t addr, uint8_t *buf, uint16_t len, bool send_stop) {
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_HAS_I2C */
|
|
@ -0,0 +1,30 @@
|
|||
// This file is Copyright (c) 2023 Antmicro <www.antmicro.com>
|
||||
// License: BSD
|
||||
|
||||
#ifndef __SDRAM_SPD_H
|
||||
#define __SDRAM_SPD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <libbase/i2c.h>
|
||||
#include <generated/sdram_phy.h>
|
||||
|
||||
#define SPD_RW_PREAMBLE 0b1010
|
||||
#define SPD_RW_ADDR(a210) ((SPD_RW_PREAMBLE << 3) | ((a210) & 0b111))
|
||||
|
||||
#if defined(SDRAM_PHY_DDR4)
|
||||
#define SDRAM_SPD_PAGES 2
|
||||
#define SDRAM_SPD_PAGE_SIZE 256
|
||||
#elif defined(SDRAM_PHY_DDR3)
|
||||
#define SDRAM_SPD_PAGES 1
|
||||
#define SDRAM_SPD_PAGE_SIZE 256
|
||||
#else
|
||||
#define SDRAM_SPD_PAGES 1
|
||||
#define SDRAM_SPD_PAGE_SIZE 128
|
||||
#endif
|
||||
|
||||
#define SDRAM_SPD_SIZE (SDRAM_SPD_PAGES * SDRAM_SPD_PAGE_SIZE)
|
||||
|
||||
bool sdram_read_spd(uint8_t spd, uint16_t addr, uint8_t *buf, uint16_t len, bool send_stop);
|
||||
|
||||
#endif /* __SDRAM_SPD_H */
|
|
@ -0,0 +1,61 @@
|
|||
// This file is Copyright (c) 2023 Antmicro <www.antmicro.com>
|
||||
// License: BSD
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <liblitedram/utils.h>
|
||||
#include <liblitedram/sdram_spd.h>
|
||||
|
||||
#include <libbase/i2c.h>
|
||||
|
||||
#include <generated/sdram_phy.h>
|
||||
|
||||
#define KIB 1024
|
||||
#define MIB (KIB*1024)
|
||||
#define GIB (MIB*1024)
|
||||
|
||||
void print_size(uint64_t size) {
|
||||
if (size < KIB)
|
||||
printf("%lluB", size);
|
||||
else if (size < MIB)
|
||||
printf("%llu.%lluKiB", size/KIB, (size/1 - KIB*(size/KIB))/(KIB/10));
|
||||
else if (size < GIB)
|
||||
printf("%llu.%lluMiB", size/MIB, (size/KIB - KIB*(size/MIB))/(KIB/10));
|
||||
else
|
||||
printf("%llu.%lluGiB", size/GIB, (size/MIB - KIB*(size/GIB))/(KIB/10));
|
||||
}
|
||||
|
||||
void print_progress(const char * header, uint64_t origin, uint64_t size)
|
||||
{
|
||||
printf("%s 0x%llx-0x%llx ", header, origin, origin + size);
|
||||
print_size(size);
|
||||
printf(" \r");
|
||||
}
|
||||
|
||||
uint64_t sdram_get_supported_memory(void) {
|
||||
#ifdef CONFIG_HAS_I2C
|
||||
|
||||
#if defined(SDRAM_PHY_DDR3) || defined(SDRAM_PHY_DDR4)
|
||||
uint8_t buf;
|
||||
|
||||
if (!sdram_read_spd(0x0, 4, &buf, 1, true)) {
|
||||
printf("Couldn't read SDRAM size from the SPD, defaulting to 256 MB.\n");
|
||||
return 256 << 20;
|
||||
}
|
||||
|
||||
/* minimal supported is 256 Mb */
|
||||
uint64_t single_die_capacity = 256 << 20;
|
||||
single_die_capacity <<= buf & 0x7;
|
||||
|
||||
/* convert from bits to bytes (divide by 8) */
|
||||
single_die_capacity >>= 3;
|
||||
|
||||
return SDRAM_PHY_MODULES * single_die_capacity;
|
||||
#else
|
||||
return SDRAM_PHY_SUPPORTED_MEMORY;
|
||||
#endif
|
||||
|
||||
#else /* no CONFIG_HAS_I2C */
|
||||
return SDRAM_PHY_SUPPORTED_MEMORY;
|
||||
#endif /* CONFIG_HAS_I2C */
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// This file is Copyright (c) 2023 Antmicro <www.antmicro.com>
|
||||
// License: BSD
|
||||
|
||||
#ifndef __SDRAM_UTILS_H
|
||||
#define __SDRAM_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void print_size(uint64_t size);
|
||||
void print_progress(const char * header, uint64_t origin, uint64_t size);
|
||||
|
||||
uint64_t sdram_get_supported_memory(void);
|
||||
|
||||
#endif /* __SDRAM_UTILS_H */
|
Loading…
Reference in New Issue