Merge pull request #1558 from antmicro/msieron/sdram-spd

liblitedram: SPD read improvements
This commit is contained in:
enjoy-digital 2023-01-10 09:40:44 +01:00 committed by GitHub
commit 0a36ad1f6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 194 additions and 16 deletions

View File

@ -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):

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */
}

View File

@ -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 */