From bd03c496a13c597dfdd41debe75d8ce558a9332c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Thu, 5 Sep 2024 12:02:28 +0200 Subject: [PATCH] bios: add spiram MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add spiram in bios, so it can enable QPI. Signed-off-by: Fin Maaß --- litex/soc/software/bios/main.c | 7 ++ litex/soc/software/liblitespi/Makefile | 2 +- litex/soc/software/liblitespi/spiram.c | 147 +++++++++++++++++++++++++ litex/soc/software/liblitespi/spiram.h | 17 +++ 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 litex/soc/software/liblitespi/spiram.c create mode 100644 litex/soc/software/liblitespi/spiram.h diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 3a86cca36..a8f5ed0be 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -47,6 +47,7 @@ #include #include +#include #include #include @@ -186,6 +187,12 @@ __attribute__((__used__)) int main(int i, char **c) eth_init(); #endif + /* Initialize and test SPIRAM */ +#ifdef CSR_SPIRAM_CORE_BASE + spiram_init(); +#endif + printf("\n"); + /* Initialize and test DRAM */ #ifdef CSR_SDRAM_BASE sdr_ok = sdram_init(); diff --git a/litex/soc/software/liblitespi/Makefile b/litex/soc/software/liblitespi/Makefile index 74f0b131c..3c8d0c58a 100644 --- a/litex/soc/software/liblitespi/Makefile +++ b/litex/soc/software/liblitespi/Makefile @@ -1,7 +1,7 @@ include ../include/generated/variables.mak include $(SOC_DIRECTORY)/software/common.mak -OBJECTS=spiflash.o +OBJECTS=spiflash.o spiram.o all: liblitespi.a diff --git a/litex/soc/software/liblitespi/spiram.c b/litex/soc/software/liblitespi/spiram.c new file mode 100644 index 000000000..b5890f210 --- /dev/null +++ b/litex/soc/software/liblitespi/spiram.c @@ -0,0 +1,147 @@ +// Copyright (c) 2020 Antmicro +// Copyright (c) 2024 Fin Maaß +// License: BSD + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "spiram.h" + +//#define SPIRAM_DEBUG + +#if defined(CSR_SPIRAM_CORE_BASE) + +int spiram_freq_init(void) +{ + +#ifdef CSR_SPIRAM_PHY_CLK_DIVISOR_ADDR + + int data_errors = 0; + unsigned int lowest_div; + + lowest_div = spiram_phy_clk_divisor_read(); + + flush_cpu_dcache(); + flush_l2_cache(); + + while((data_errors == 0) && (lowest_div-- > 0)) { + spiram_phy_clk_divisor_write((uint32_t)lowest_div); + flush_cpu_dcache(); + flush_l2_cache(); + data_errors = memtest_data((unsigned int *) SPIRAM_BASE, min(SPIRAM_SIZE, MEMTEST_DATA_SIZE), 1, NULL); +#ifdef SPIRAM_DEBUG + printf("[DIV: %d]\n\r", lowest_div); +#endif + } + lowest_div++; + printf("SPI RAM clk configured to %d MHz\n", CONFIG_CLOCK_FREQUENCY/(2*(1+lowest_div)*1000000)); + + spiram_phy_clk_divisor_write(lowest_div); + +#else + + printf("SPI RAM clk configured to %ld MHz\n", SPIRAM_PHY_FREQUENCY/1000000); + +#endif + + return 0; +} + +void spiram_dummy_bits_setup(unsigned int dummy_bits) +{ + spiram_core_mmap_dummy_bits_write((uint32_t)dummy_bits); +#ifdef SPIRAM_DEBUG + printf("Dummy bits set to: %" PRIx32 "\n\r", spiram_core_mmap_dummy_bits_read()); +#endif +} + +#ifdef CSR_SPIRAM_CORE_MASTER_CS_ADDR + +static void spiram_len_mask_width_write(uint32_t len, uint32_t width, uint32_t mask) +{ + uint32_t tmp = len & ((1 << CSR_SPIRAM_CORE_MASTER_PHYCONFIG_LEN_SIZE) - 1); + uint32_t word = tmp << CSR_SPIRAM_CORE_MASTER_PHYCONFIG_LEN_OFFSET; + tmp = width & ((1 << CSR_SPIRAM_CORE_MASTER_PHYCONFIG_WIDTH_SIZE) - 1); + word |= tmp << CSR_SPIRAM_CORE_MASTER_PHYCONFIG_WIDTH_OFFSET; + tmp = mask & ((1 << CSR_SPIRAM_CORE_MASTER_PHYCONFIG_MASK_SIZE) - 1); + word |= tmp << CSR_SPIRAM_CORE_MASTER_PHYCONFIG_MASK_OFFSET; + spiram_core_master_phyconfig_write(word); +} + +static bool spiram_rx_ready(void) +{ + return (spiram_core_master_status_read() >> CSR_SPIRAM_CORE_MASTER_STATUS_RX_READY_OFFSET) & 1; +} + +static void spiram_master_write(uint32_t val, size_t len, size_t width, uint32_t mask) +{ + /* Be sure to empty RX queue before doing Xfer. */ + while (spiram_rx_ready()) + spiram_core_master_rxtx_read(); + + /* Configure Master */ + spiram_len_mask_width_write(8*len, width, mask); + + /* Set CS. */ + spiram_core_master_cs_write(1); + + /* Do Xfer. */ + spiram_core_master_rxtx_write(val); + while (!spiram_rx_ready()); + + /* Clear CS. */ + spiram_core_master_cs_write(0); +} + +#endif + +void spiram_memspeed(void) { + /* Test Sequential Read accesses */ + memspeed((unsigned int *) SPIRAM_BASE, 4096, 1, 0); + + /* Test Random Read accesses */ + memspeed((unsigned int *) SPIRAM_BASE, 4096, 1, 1); +} + +void spiram_init(void) +{ + printf("\nInitializing %s SPI RAM @0x%08lx...\n", SPIRAM_MODULE_NAME, SPIRAM_BASE); + +#ifdef SPIRAM_MODULE_DUMMY_BITS + spiram_dummy_bits_setup(SPIRAM_MODULE_DUMMY_BITS); +#endif + +#ifdef CSR_SPIRAM_CORE_MASTER_CS_ADDR + + /* Quad / QPI Configuration. */ +#ifdef SPIRAM_MODULE_QUAD_CAPABLE + printf("Enabling Quad mode...\n"); + spiram_master_write(0x00000006, 1, 1, 0x1); + spiram_master_write(0x00014307, 3, 1, 0x1); +#endif + +#ifdef SPIRAM_MODULE_QPI_CAPABLE + printf("Switching to QPI mode...\n"); + spiram_master_write(0x00000035, 1, 1, 0x1); +#endif + +#endif + +#ifndef SPIRAM_SKIP_FREQ_INIT + /* Clk frequency auto-calibration. */ + spiram_freq_init(); +#endif + + /* Test SPI RAM speed */ + spiram_memspeed(); +} + +#endif diff --git a/litex/soc/software/liblitespi/spiram.h b/litex/soc/software/liblitespi/spiram.h new file mode 100644 index 000000000..128c1aa55 --- /dev/null +++ b/litex/soc/software/liblitespi/spiram.h @@ -0,0 +1,17 @@ +#ifndef __LITESPI_SPIRAM_H +#define __LITESPI_SPIRAM_H + +#ifdef __cplusplus +extern "C" { +#endif + +int spiram_freq_init(void); +void spiram_dummy_bits_setup(unsigned int dummy_bits); +void spiram_memspeed(void); +void spiram_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LITESPI_SPIRAM_H */