mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
Merge pull request #1881 from motec-research/spiflash_fixes
Spiflash fixes for issues exposed by sys_clk = 200MHz and L2 cache
This commit is contained in:
commit
be23467cb1
4 changed files with 29 additions and 14 deletions
|
@ -66,9 +66,13 @@ class OpenFPGALoader(GenericProgrammer):
|
||||||
|
|
||||||
# Handle kwargs for specific, less common cases.
|
# Handle kwargs for specific, less common cases.
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
cmd.append(f"--{key}")
|
cmd.append(f"--{key.replace('_', '-')}")
|
||||||
if value is not None:
|
if value is not None:
|
||||||
cmd.append(str(value))
|
cmd.append(str(value))
|
||||||
|
|
||||||
# Execute Command.
|
# Execute Command.
|
||||||
self.call(cmd)
|
try:
|
||||||
|
self.call(cmd)
|
||||||
|
except OSError as e:
|
||||||
|
print(' '.join(cmd))
|
||||||
|
raise
|
||||||
|
|
|
@ -1879,22 +1879,25 @@ class LiteXSoC(SoC):
|
||||||
self.add_constant("ETH_PHY_NO_RESET") # Disable reset from BIOS to avoid disabling Hardware Interface.
|
self.add_constant("ETH_PHY_NO_RESET") # Disable reset from BIOS to avoid disabling Hardware Interface.
|
||||||
|
|
||||||
# Add SPI Flash --------------------------------------------------------------------------------
|
# Add SPI Flash --------------------------------------------------------------------------------
|
||||||
def add_spi_flash(self, name="spiflash", mode="4x", clk_freq=None, module=None, phy=None, rate="1:1", software_debug=False, **kwargs):
|
def add_spi_flash(self, name="spiflash", mode="4x", clk_freq=20e6, module=None, phy=None, rate="1:1", software_debug=False, **kwargs):
|
||||||
# Imports.
|
# Imports.
|
||||||
from litespi import LiteSPI
|
from litespi import LiteSPI
|
||||||
from litespi.phy.generic import LiteSPIPHY
|
from litespi.phy.generic import LiteSPIPHY
|
||||||
from litespi.opcodes import SpiNorFlashOpCodes
|
from litespi.opcodes import SpiNorFlashOpCodes
|
||||||
|
import math
|
||||||
|
|
||||||
# Checks/Parameters.
|
# Checks/Parameters.
|
||||||
assert mode in ["1x", "4x"]
|
assert mode in ["1x", "4x"]
|
||||||
if clk_freq is None: clk_freq = self.sys_clk_freq
|
# From LiteSPIClkGen: clk_freq will be ``sys_clk_freq/(2*(1+div))``.
|
||||||
|
default_divisor = math.ceil(self.sys_clk_freq/(clk_freq*2))-1
|
||||||
|
clk_freq = int(self.sys_clk_freq/(2*(1+default_divisor)))
|
||||||
|
|
||||||
# PHY.
|
# PHY.
|
||||||
spiflash_phy = phy
|
spiflash_phy = phy
|
||||||
if spiflash_phy is None:
|
if spiflash_phy is None:
|
||||||
self.check_if_exists(f"{name}_phy")
|
self.check_if_exists(f"{name}_phy")
|
||||||
spiflash_pads = self.platform.request(name if mode == "1x" else name + mode)
|
spiflash_pads = self.platform.request(name if mode == "1x" else name + mode)
|
||||||
spiflash_phy = LiteSPIPHY(spiflash_pads, module, device=self.platform.device, default_divisor=int(self.sys_clk_freq/clk_freq), rate=rate)
|
spiflash_phy = LiteSPIPHY(spiflash_pads, module, device=self.platform.device, default_divisor=default_divisor, rate=rate)
|
||||||
self.add_module(name=f"{name}_phy", module=spiflash_phy)
|
self.add_module(name=f"{name}_phy", module=spiflash_phy)
|
||||||
|
|
||||||
# Core.
|
# Core.
|
||||||
|
@ -1909,10 +1912,11 @@ class LiteXSoC(SoC):
|
||||||
self.add_constant(f"{name}_MODULE_NAME", module.name.upper())
|
self.add_constant(f"{name}_MODULE_NAME", module.name.upper())
|
||||||
self.add_constant(f"{name}_MODULE_TOTAL_SIZE", module.total_size)
|
self.add_constant(f"{name}_MODULE_TOTAL_SIZE", module.total_size)
|
||||||
self.add_constant(f"{name}_MODULE_PAGE_SIZE", module.page_size)
|
self.add_constant(f"{name}_MODULE_PAGE_SIZE", module.page_size)
|
||||||
if SpiNorFlashOpCodes.READ_1_1_4 in module.supported_opcodes:
|
if mode in [ "4x" ]:
|
||||||
self.add_constant(f"{name}_MODULE_QUAD_CAPABLE")
|
if SpiNorFlashOpCodes.READ_1_1_4 in module.supported_opcodes:
|
||||||
if SpiNorFlashOpCodes.READ_4_4_4 in module.supported_opcodes:
|
self.add_constant(f"{name}_MODULE_QUAD_CAPABLE")
|
||||||
self.add_constant(f"{name}_MODULE_QPI_CAPABLE")
|
if SpiNorFlashOpCodes.READ_4_4_4 in module.supported_opcodes:
|
||||||
|
self.add_constant(f"{name}_MODULE_QPI_CAPABLE")
|
||||||
if software_debug:
|
if software_debug:
|
||||||
self.add_constant(f"{name}_DEBUG")
|
self.add_constant(f"{name}_DEBUG")
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,8 @@ static void crc_handler(int nb_params, char **params)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_cpu_dcache();
|
||||||
|
flush_l2_cache();
|
||||||
printf("CRC32: %08x", crc32((unsigned char *)addr, length));
|
printf("CRC32: %08x", crc32((unsigned char *)addr, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
|
// This file is Copyright (c) 2020 Antmicro <www.antmicro.com>
|
||||||
// License: BSD
|
// License: BSD
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -25,6 +26,8 @@ int spiflash_freq_init(void)
|
||||||
unsigned int lowest_div, crc, crc_test;
|
unsigned int lowest_div, crc, crc_test;
|
||||||
|
|
||||||
lowest_div = spiflash_phy_clk_divisor_read();
|
lowest_div = spiflash_phy_clk_divisor_read();
|
||||||
|
flush_cpu_dcache();
|
||||||
|
flush_l2_cache();
|
||||||
crc = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE);
|
crc = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE);
|
||||||
crc_test = crc;
|
crc_test = crc;
|
||||||
|
|
||||||
|
@ -40,19 +43,21 @@ int spiflash_freq_init(void)
|
||||||
|
|
||||||
while((crc == crc_test) && (lowest_div-- > 0)) {
|
while((crc == crc_test) && (lowest_div-- > 0)) {
|
||||||
spiflash_phy_clk_divisor_write((uint32_t)lowest_div);
|
spiflash_phy_clk_divisor_write((uint32_t)lowest_div);
|
||||||
|
flush_cpu_dcache();
|
||||||
|
flush_l2_cache();
|
||||||
crc_test = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE);
|
crc_test = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE);
|
||||||
#ifdef SPIFLASH_DEBUG
|
#ifdef SPIFLASH_DEBUG
|
||||||
printf("[DIV: %d] %08x\n\r", lowest_div, crc_test);
|
printf("[DIV: %d] %08x\n\r", lowest_div, crc_test);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
lowest_div++;
|
lowest_div++;
|
||||||
printf("SPI Flash clk configured to %d MHz\n", (SPIFLASH_PHY_FREQUENCY/(2*(1 + lowest_div)))/1000000);
|
printf("SPI Flash clk configured to %d MHz\n", CONFIG_CLOCK_FREQUENCY/(2*(1+lowest_div)*1000000));
|
||||||
|
|
||||||
spiflash_phy_clk_divisor_write(lowest_div);
|
spiflash_phy_clk_divisor_write(lowest_div);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
printf("SPI Flash clk configured to %ld MHz\n", (unsigned long)(SPIFLASH_PHY_FREQUENCY/1e6));
|
printf("SPI Flash clk configured to %ld MHz\n", SPIFLASH_PHY_FREQUENCY/1000000);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -63,7 +68,7 @@ void spiflash_dummy_bits_setup(unsigned int dummy_bits)
|
||||||
{
|
{
|
||||||
spiflash_core_mmap_dummy_bits_write((uint32_t)dummy_bits);
|
spiflash_core_mmap_dummy_bits_write((uint32_t)dummy_bits);
|
||||||
#ifdef SPIFLASH_DEBUG
|
#ifdef SPIFLASH_DEBUG
|
||||||
printf("Dummy bits set to: %d\n\r", spiflash_core_mmap_dummy_bits_read());
|
printf("Dummy bits set to: %" PRIx32 "\n\r", spiflash_core_mmap_dummy_bits_read());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +112,7 @@ static uint32_t transfer_byte(uint8_t b)
|
||||||
return spiflash_core_master_rxtx_read();
|
return spiflash_core_master_rxtx_read();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void transfer_cmd(uint8_t *bs, uint8_t *resp, int len)
|
static void transfer_cmd(volatile uint8_t *bs, volatile uint8_t *resp, int len)
|
||||||
{
|
{
|
||||||
spiflash_core_master_phyconfig_len_write(8);
|
spiflash_core_master_phyconfig_len_write(8);
|
||||||
spiflash_core_master_phyconfig_width_write(1);
|
spiflash_core_master_phyconfig_width_write(1);
|
||||||
|
@ -170,7 +175,7 @@ static void page_program(uint32_t addr, uint8_t *data, int len)
|
||||||
w_buf[1] = addr>>16;
|
w_buf[1] = addr>>16;
|
||||||
w_buf[2] = addr>>8;
|
w_buf[2] = addr>>8;
|
||||||
w_buf[3] = addr>>0;
|
w_buf[3] = addr>>0;
|
||||||
memcpy(w_buf+4, data, len);
|
memcpy((void *)w_buf+4, (void *)data, len);
|
||||||
transfer_cmd(w_buf, r_buf, len+4);
|
transfer_cmd(w_buf, r_buf, len+4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue