From e2c5b5810f663c69003ce844f067b5393370d24f Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 4 May 2022 12:44:33 +0100 Subject: [PATCH] add tercel speed-up but missing id for arty a7 at the moment --- coldboot/Makefile | 6 +- coldboot/coldboot.c | 50 +----- coldboot/micron_n25q_flash.h | 29 ++++ coldboot/tercel.c | 288 +++++++++++++++++++++++++++++++++++ coldboot/tercel_spi.h | 68 +++++++++ src/ls2.py | 6 +- 6 files changed, 401 insertions(+), 46 deletions(-) create mode 100644 coldboot/micron_n25q_flash.h create mode 100644 coldboot/tercel.c create mode 100644 coldboot/tercel_spi.h diff --git a/coldboot/Makefile b/coldboot/Makefile index 6b5d26f..da80dc8 100644 --- a/coldboot/Makefile +++ b/coldboot/Makefile @@ -59,8 +59,10 @@ calibration.o: ../libgram/src/calibration.c powerpc.lds: powerpc.lds.S $(CC) $(CFLAGS) -P -E powerpc.lds.S -o powerpc.lds -coldboot.elf: coldboot.o head.o ../lib/console.o $(GRAMOBJS) powerpc.lds - $(LD) $(LDFLAGS) -o $@ coldboot.o head.o ../lib/console.o $(GRAMOBJS) +OBJS := coldboot.o tercel.o head.o ../lib/console.o $(GRAMOBJS) + +coldboot.elf: $(OBJS) powerpc.lds + $(LD) $(LDFLAGS) -o $@ $(OBJS) coldboot.bin: coldboot.elf $(OBJCOPY) -O binary $^ $@ diff --git a/coldboot/coldboot.c b/coldboot/coldboot.c index 6c7b8cc..e5d97a1 100644 --- a/coldboot/coldboot.c +++ b/coldboot/coldboot.c @@ -92,47 +92,8 @@ void isr(void) { } -// WARNING -// KESTREL SPECIFIC -#define TERCEL_SPI_REG_SYS_PHY_CFG1 0x10 -#define TERCEL_SPI_REG_SYS_FLASH_CFG5 0x24 -#define TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK 0xff -#define TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT 0 -#define TERCEL_SPI_FLASH_EN_MULTCYC_READ_MASK 0x1 -#define TERCEL_SPI_FLASH_EN_MULTCYC_READ_SHIFT 0 -static inline uint32_t read_tercel_register(uint8_t reg) -{ - return readl((unsigned long)(SPI_FCTRL_BASE+reg)); -} - -static inline void write_tercel_register(uint8_t reg, uint32_t value) -{ - writel(value, (unsigned long)(SPI_FCTRL_BASE+reg)); -} - -// TODO: need to use this -// https://gitlab.raptorengineering.com/kestrel-collaboration/kestrel-firmware/bare-metal-firmware/-/blob/master/main.c#L2328 - -/* this is a "level 1" speed-up, which gets an initial improvement of 10-50x - * over the default speed (which is a scant 100 bytes per second). - */ -static void crank_up_qspi_level1(void) -{ - // WARNING: KESTREL SPECIFIC - // Set SPI clock cycle divider to 1 - uint32_t dword; - dword = read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1); - dword &= ~(TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK << - TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT); - dword |= ((1 & TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK) << - TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT); - write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1, dword); - // Enable read merging - dword = read_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5); - dword |= (TERCEL_SPI_FLASH_EN_MULTCYC_READ_MASK << - TERCEL_SPI_FLASH_EN_MULTCYC_READ_SHIFT); - write_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5, dword); -} +extern void crank_up_qspi_level1(void); +extern int host_spi_flash_init(void); static bool fl_read(void *dst, uint32_t offset, uint32_t size) { @@ -270,6 +231,8 @@ int main(void) { if (ftr & SYS_REG_INFO_HAS_SPI_FLASH) { // speed up the QSPI to at least a sane level crank_up_qspi_level1(); + // run at saner level + host_spi_flash_init(); puts("SPI Offset: "); spi_offs = readl(SYSCON_BASE + SYS_REG_SPI_INFO); @@ -299,7 +262,7 @@ int main(void) { //volatile uint8_t *qspi_bytes = (uint8_t*)spi_offs; // let's not, eh? writel(0xDEAF0123, (unsigned long)&(qspi[0])); // tmp = readl((unsigned long)&(qspi[0])); - for (int i=0;i<2;i++) { + for (int i=0;i<10;i++) { tmp = readl((unsigned long)&(qspi[i])); uart_writeuint32(tmp); puts(" "); @@ -555,7 +518,8 @@ int main(void) { volatile uint32_t *mem = (uint32_t*)0x1000000; fl_read(mem, // destination in RAM 0x600000, // offset into QSPI - 0x1000000); // length - shorter (testing) 0x8000); + 0x8000); // length - shorter (testing) 0x8000); + //0x1000000); // length puts("dump mem\n"); for (int i=0;i<256;i++) { tmp = readl((unsigned long)&(mem[i])); diff --git a/coldboot/micron_n25q_flash.h b/coldboot/micron_n25q_flash.h new file mode 100644 index 0000000..66712c8 --- /dev/null +++ b/coldboot/micron_n25q_flash.h @@ -0,0 +1,29 @@ +// © 2020 Raptor Engineering, LLC +// +// Released under the terms of the GPL v3 +// See the LICENSE file for full details + +uint32_t micron_n25q_spi_device_ids[] = { 0x20ba2010, 0x20ba2110 }; + +const char *micron_n25q_spi_device_names[] = { "Micron N25Q 512Mb", "Micron N25Q 1024Mb" }; + +#define MICRON_N25Q_SPI_FAST_READ_DUMMY_CLOCK_CYCLES 10 + +#define MICRON_N25Q_SPI_3BA_SPI_READ_CMD 0x03 +#define MICRON_N25Q_SPI_4BA_SPI_READ_CMD 0x13 + +// NOTE: QSPI mode unavailable for single read, use Write Disable command as plaecholder +#define MICRON_N25Q_SPI_3BA_QSPI_READ_CMD 0x04 +#define MICRON_N25Q_SPI_4BA_QSPI_READ_CMD 0x04 + +#define MICRON_N25Q_SPI_3BA_SPI_FAST_READ_CMD 0x0b +#define MICRON_N25Q_SPI_4BA_SPI_FAST_READ_CMD 0x0c +#define MICRON_N25Q_SPI_3BA_QSPI_FAST_READ_CMD 0xeb +#define MICRON_N25Q_SPI_4BA_QSPI_FAST_READ_CMD 0xec + +// NOTE: The same command code is used for both QSPI 3BA and QSPI 4BA extended quad input writes, thus the device must be placed in either 3BA or 4BA mode prior +// to issuing PAGE PROGRAM +#define MICRON_N25Q_SPI_3BA_SPI_PAGE_PROGRAM_CMD 0x02 +#define MICRON_N25Q_SPI_4BA_SPI_PAGE_PROGRAM_CMD 0x12 +#define MICRON_N25Q_SPI_3BA_QSPI_PAGE_PROGRAM_CMD 0x38 +#define MICRON_N25Q_SPI_4BA_QSPI_PAGE_PROGRAM_CMD 0x38 diff --git a/coldboot/tercel.c b/coldboot/tercel.c new file mode 100644 index 0000000..e17f763 --- /dev/null +++ b/coldboot/tercel.c @@ -0,0 +1,288 @@ +// Copyright (C) 2020 - 2021 Raptor Engineering, LLC +// +// Released under the terms of the GPL v3 +// See the LICENSE file for full details + +#include +#include + +#include "console.h" +#include "microwatt_soc.h" +#include "io.h" + +#include +#include + +#include "micron_n25q_flash.h" +#include "tercel_spi.h" + +#define ALLOW_SPI_QUAD_MODE 1 + +static inline uint8_t read_tercel_reg8(uint8_t reg) +{ + return readb((unsigned long)(SPI_FCTRL_BASE+reg)); +} + +static inline void write_tercel_reg8(uint8_t reg, uint8_t value) +{ + writeb(value, (unsigned long)(SPI_FCTRL_BASE+reg)); +} + +static inline uint32_t read_tercel_register(uint8_t reg) +{ + return readl((unsigned long)(SPI_FCTRL_BASE+reg)); +} + +static inline void write_tercel_register(uint8_t reg, uint32_t value) +{ + writel(value, (unsigned long)(SPI_FCTRL_BASE+reg)); +} + +static uint32_t read_host_spi_flash_id(void) +{ + uint32_t flash_id = 0; + + // Set user mode + write_tercel_register(TERCEL_SPI_REG_SYS_CORE_CTL1, + read_tercel_register(TERCEL_SPI_REG_SYS_CORE_CTL1) | + (TERCEL_SPI_ENABLE_USER_MODE_MASK << TERCEL_SPI_ENABLE_USER_MODE_SHIFT)); + + // Send Flash ID command + write_tercel_reg8(0, 0x9e); + + // Read response + flash_id = (flash_id << 8) | read_tercel_reg8(0); + flash_id = (flash_id << 8) | read_tercel_reg8(0); + flash_id = (flash_id << 8) | read_tercel_reg8(0); + flash_id = (flash_id << 8) | read_tercel_reg8(0); + + // Clear user mode + write_tercel_register(TERCEL_SPI_REG_SYS_CORE_CTL1, + read_tercel_register(TERCEL_SPI_REG_SYS_CORE_CTL1) & + ~(TERCEL_SPI_ENABLE_USER_MODE_MASK << + TERCEL_SPI_ENABLE_USER_MODE_SHIFT)); + + return flash_id; +} + + +/* this is a "level 1" speed-up, which gets an initial improvement of 10-50x + * over the default speed (which is a scant 100 bytes per second). + */ +void crank_up_qspi_level1(void) +{ + // WARNING: KESTREL SPECIFIC + // Set SPI clock cycle divider to 1 + uint32_t dword; + dword = read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1); + dword &= ~(TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK << + TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT); + dword |= ((1 & TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK) << + TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT); + write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1, dword); + // Enable read merging + dword = read_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5); + dword |= (TERCEL_SPI_FLASH_EN_MULTCYC_READ_MASK << + TERCEL_SPI_FLASH_EN_MULTCYC_READ_SHIFT); + write_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5, dword); +} + +extern void uart_writeuint32(uint32_t val); + +// level 2 speedup +int host_spi_flash_init(void) +{ + int i; + uint32_t dword; + uint32_t flash_device_id; + + if ((read_tercel_register(TERCEL_SPI_REG_DEVICE_ID_HIGH) != + TERCEL_SPI_DEVICE_ID_HIGH) || + (read_tercel_register(TERCEL_SPI_REG_DEVICE_ID_LOW) != + TERCEL_SPI_DEVICE_ID_LOW)) + { + return -1; + } + + uint32_t tercel_version; + tercel_version = read_tercel_register(TERCEL_SPI_REG_DEVICE_VERSION); + puts("Raptor Tercel SPI master found, device version "); + uart_writeuint32((tercel_version >> TERCEL_SPI_VERSION_MAJOR_SHIFT) & + TERCEL_SPI_VERSION_MAJOR_MASK); + uart_writeuint32((tercel_version >> TERCEL_SPI_VERSION_MINOR_SHIFT) & + TERCEL_SPI_VERSION_MINOR_MASK); + uart_writeuint32((tercel_version >> TERCEL_SPI_VERSION_PATCH_SHIFT) & + TERCEL_SPI_VERSION_PATCH_MASK); + puts("\n"); + + flash_device_id = read_host_spi_flash_id(); + puts("Flash ID "); + uart_writeuint32(flash_device_id); + puts("\n"); + for (i = 0; i < (sizeof(micron_n25q_spi_device_ids) / + sizeof(micron_n25q_spi_device_ids[0])); i++) + { + if (flash_device_id == micron_n25q_spi_device_ids[i]) + { + puts(micron_n25q_spi_device_names[i]); + puts(" Flash device detected, configuring\n"); + + // Set up Flash-specific commands + dword = 0; + dword |= (MICRON_N25Q_SPI_4BA_QSPI_READ_CMD + & TERCEL_SPI_4BA_QSPI_CMD_MASK) << + TERCEL_SPI_4BA_QSPI_CMD_SHIFT; + dword |= (MICRON_N25Q_SPI_3BA_QSPI_READ_CMD + & TERCEL_SPI_3BA_QSPI_CMD_MASK) << + TERCEL_SPI_3BA_QSPI_CMD_SHIFT; + dword |= (MICRON_N25Q_SPI_4BA_SPI_READ_CMD & + TERCEL_SPI_4BA_SPI_CMD_MASK) << + TERCEL_SPI_4BA_SPI_CMD_SHIFT; + dword |= (MICRON_N25Q_SPI_3BA_SPI_READ_CMD & + TERCEL_SPI_3BA_SPI_CMD_MASK) << + TERCEL_SPI_3BA_SPI_CMD_SHIFT; + write_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG1, dword); + + dword = 0; + dword |= (MICRON_N25Q_SPI_4BA_QSPI_FAST_READ_CMD + & TERCEL_SPI_4BA_QSPI_CMD_MASK) << + TERCEL_SPI_4BA_QSPI_CMD_SHIFT; + dword |= (MICRON_N25Q_SPI_3BA_QSPI_FAST_READ_CMD + & TERCEL_SPI_3BA_QSPI_CMD_MASK) << + TERCEL_SPI_3BA_QSPI_CMD_SHIFT; + dword |= (MICRON_N25Q_SPI_4BA_SPI_FAST_READ_CMD & + TERCEL_SPI_4BA_SPI_CMD_MASK) << + TERCEL_SPI_4BA_SPI_CMD_SHIFT; + dword |= (MICRON_N25Q_SPI_3BA_SPI_FAST_READ_CMD & + TERCEL_SPI_3BA_SPI_CMD_MASK) << + TERCEL_SPI_3BA_SPI_CMD_SHIFT; + write_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG2, dword); + + dword = 0; + dword |= (MICRON_N25Q_SPI_4BA_QSPI_PAGE_PROGRAM_CMD + & TERCEL_SPI_4BA_QSPI_CMD_MASK) << + TERCEL_SPI_4BA_QSPI_CMD_SHIFT; + dword |= (MICRON_N25Q_SPI_3BA_QSPI_PAGE_PROGRAM_CMD + & TERCEL_SPI_3BA_QSPI_CMD_MASK) << + TERCEL_SPI_3BA_QSPI_CMD_SHIFT; + dword |= (MICRON_N25Q_SPI_4BA_SPI_PAGE_PROGRAM_CMD & + TERCEL_SPI_4BA_SPI_CMD_MASK) << + TERCEL_SPI_4BA_SPI_CMD_SHIFT; + dword |= (MICRON_N25Q_SPI_3BA_SPI_PAGE_PROGRAM_CMD & + TERCEL_SPI_3BA_SPI_CMD_MASK) << + TERCEL_SPI_3BA_SPI_CMD_SHIFT; + write_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG3, dword); + + // Enable extended QSPI read/write operations + dword = read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1); + dword |= TERCEL_SPI_PHY_QSPI_EXT_READ_EN_MASK << + TERCEL_SPI_PHY_QSPI_EXT_READ_EN_SHIFT; + dword |= TERCEL_SPI_PHY_QSPI_EXT_WRITE_EN_MASK << + TERCEL_SPI_PHY_QSPI_EXT_WRITE_EN_SHIFT; + write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1, dword); + + break; + } + } + + // Set SPI core to automatic mode + write_tercel_register(TERCEL_SPI_REG_SYS_CORE_CTL1, + read_tercel_register(TERCEL_SPI_REG_SYS_CORE_CTL1) & + ~(TERCEL_SPI_ENABLE_USER_MODE_MASK << + TERCEL_SPI_ENABLE_USER_MODE_SHIFT)); + + // Set extra CS delay cycle count to 0 + dword = read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1); + dword &= ~(TERCEL_SPI_PHY_CS_EXTRA_IDLE_CYC_MASK << + TERCEL_SPI_PHY_CS_EXTRA_IDLE_CYC_SHIFT); + dword |= ((0 & TERCEL_SPI_PHY_CS_EXTRA_IDLE_CYC_MASK) << + TERCEL_SPI_PHY_CS_EXTRA_IDLE_CYC_SHIFT); + write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1, dword); + + // Set maximum CS assert cycle count to 10000 + dword = read_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG4); + dword &= ~(TERCEL_SPI_FLASH_CS_EN_LIMIT_CYC_MASK << + TERCEL_SPI_FLASH_CS_EN_LIMIT_CYC_SHIFT); + dword |= ((10000 & TERCEL_SPI_FLASH_CS_EN_LIMIT_CYC_MASK) << + TERCEL_SPI_FLASH_CS_EN_LIMIT_CYC_SHIFT); + write_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG4, dword); + + // Set SPI fast read dummy cycles to + // MICRON_N25Q_SPI_FAST_READ_DUMMY_CLOCK_CYCLES + dword = read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1); + dword &= ~(TERCEL_SPI_PHY_DUMMY_CYCLES_MASK << + TERCEL_SPI_PHY_DUMMY_CYCLES_SHIFT); + dword |= ((MICRON_N25Q_SPI_FAST_READ_DUMMY_CLOCK_CYCLES + & TERCEL_SPI_PHY_DUMMY_CYCLES_MASK) << + TERCEL_SPI_PHY_DUMMY_CYCLES_SHIFT); + write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1, dword); + + // Enable SPI fast read functionality + dword = read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1); + dword &= ~(TERCEL_SPI_PHY_FAST_READ_ENABLE_MASK << + TERCEL_SPI_PHY_FAST_READ_ENABLE_SHIFT); + dword |= ((1 & TERCEL_SPI_PHY_FAST_READ_ENABLE_MASK) << + TERCEL_SPI_PHY_FAST_READ_ENABLE_SHIFT); + write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1, dword); + + // Set SPI controller to 4BA mode + dword = read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1); + dword &= ~(TERCEL_SPI_PHY_4BA_ENABLE_MASK << + TERCEL_SPI_PHY_4BA_ENABLE_SHIFT); + dword |= ((TERCEL_SPI_PHY_4BA_MODE & TERCEL_SPI_PHY_4BA_ENABLE_MASK) + << TERCEL_SPI_PHY_4BA_ENABLE_SHIFT); + write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1, dword); + +#if (ALLOW_SPI_QUAD_MODE) + // Set SPI controller to QSPI mode + dword = read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1); + dword &= ~(TERCEL_SPI_PHY_IO_TYPE_MASK << TERCEL_SPI_PHY_IO_TYPE_SHIFT); + dword |= ((TERCEL_SPI_PHY_IO_TYPE_QUAD & TERCEL_SPI_PHY_IO_TYPE_MASK) + << TERCEL_SPI_PHY_IO_TYPE_SHIFT); + write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1, dword); +#endif + + // Set SPI clock cycle divider to 5 + dword = read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1); + dword &= ~(TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK << + TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT); + dword |= ((5 & TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK) << + TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT); + write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1, dword); + + // Calculate and dump configured SPI clock speed + uint8_t spi_divisor = + (read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1) + >> TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT) & + TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK; + spi_divisor = (spi_divisor + 1) * 2; + uint8_t spi_dummy_cycles = + (read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1) + >> TERCEL_SPI_PHY_DUMMY_CYCLES_SHIFT) & + TERCEL_SPI_PHY_DUMMY_CYCLES_MASK; + puts("Flash controller frequency "); + uart_writeuint32((read_tercel_register(TERCEL_SPI_REG_SYS_CLK_FREQ) / + spi_divisor) / 1000000); + puts("\nbus frequency "); + uart_writeuint32(read_tercel_register(TERCEL_SPI_REG_SYS_CLK_FREQ) / + 1000000); + puts("\ndummy cycles"); + uart_writeuint32(spi_dummy_cycles); + puts("\n"); + + // Enable read merging + write_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5, + read_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5) | + (TERCEL_SPI_FLASH_EN_MULTCYC_READ_MASK << + TERCEL_SPI_FLASH_EN_MULTCYC_READ_SHIFT)); + + // Enable write merging + write_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5, + read_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5) + | + (TERCEL_SPI_FLASH_EN_MULTCYC_WRITE_MASK << + TERCEL_SPI_FLASH_EN_MULTCYC_WRITE_SHIFT)); + + return 0; +} + diff --git a/coldboot/tercel_spi.h b/coldboot/tercel_spi.h new file mode 100644 index 0000000..bd4a9d5 --- /dev/null +++ b/coldboot/tercel_spi.h @@ -0,0 +1,68 @@ +// © 2020 Raptor Engineering, LLC +// +// Released under the terms of the GPL v3 +// See the LICENSE file for full details + +#define TERCEL_SPI_REG_DEVICE_ID_HIGH 0x0 +#define TERCEL_SPI_REG_DEVICE_ID_LOW 0x4 +#define TERCEL_SPI_REG_DEVICE_VERSION 0x8 +#define TERCEL_SPI_REG_SYS_CLK_FREQ 0xc +#define TERCEL_SPI_REG_SYS_PHY_CFG1 0x10 +#define TERCEL_SPI_REG_SYS_FLASH_CFG1 0x14 +#define TERCEL_SPI_REG_SYS_FLASH_CFG2 0x18 +#define TERCEL_SPI_REG_SYS_FLASH_CFG3 0x1c +#define TERCEL_SPI_REG_SYS_FLASH_CFG4 0x20 +#define TERCEL_SPI_REG_SYS_FLASH_CFG5 0x24 +#define TERCEL_SPI_REG_SYS_CORE_CTL1 0x28 +#define TERCEL_SPI_REG_SYS_CORE_DATA1 0x2c + +#define TERCEL_SPI_DEVICE_ID_HIGH 0x7c525054 +#define TERCEL_SPI_DEVICE_ID_LOW 0x5350494d + +#define TERCEL_SPI_VERSION_MAJOR_MASK 0xffff +#define TERCEL_SPI_VERSION_MAJOR_SHIFT 16 +#define TERCEL_SPI_VERSION_MINOR_MASK 0xff +#define TERCEL_SPI_VERSION_MINOR_SHIFT 8 +#define TERCEL_SPI_VERSION_PATCH_MASK 0xff +#define TERCEL_SPI_VERSION_PATCH_SHIFT 0 + +#define TERCEL_SPI_ENABLE_USER_MODE_MASK 0x1 +#define TERCEL_SPI_ENABLE_USER_MODE_SHIFT 0x0 +#define TERCEL_SPI_PHY_DUMMY_CYCLES_MASK 0xff +#define TERCEL_SPI_PHY_DUMMY_CYCLES_SHIFT 8 +#define TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK 0xff +#define TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT 0 +#define TERCEL_SPI_PHY_IO_TYPE_MASK 0x3 +#define TERCEL_SPI_PHY_IO_TYPE_SHIFT 16 +#define TERCEL_SPI_PHY_4BA_ENABLE_MASK 0x1 +#define TERCEL_SPI_PHY_4BA_ENABLE_SHIFT 18 +#define TERCEL_SPI_PHY_FAST_READ_ENABLE_MASK 0x1 +#define TERCEL_SPI_PHY_FAST_READ_ENABLE_SHIFT 19 +#define TERCEL_SPI_PHY_QSPI_EXT_READ_EN_MASK 0x1 +#define TERCEL_SPI_PHY_QSPI_EXT_READ_EN_SHIFT 20 +#define TERCEL_SPI_PHY_QSPI_EXT_WRITE_EN_MASK 0x1 +#define TERCEL_SPI_PHY_QSPI_EXT_WRITE_EN_SHIFT 21 +#define TERCEL_SPI_PHY_CS_EXTRA_IDLE_CYC_MASK 0xff +#define TERCEL_SPI_PHY_CS_EXTRA_IDLE_CYC_SHIFT 24 +#define TERCEL_SPI_FLASH_EN_MULTCYC_WRITE_MASK 0x1 +#define TERCEL_SPI_FLASH_EN_MULTCYC_WRITE_SHIFT 1 +#define TERCEL_SPI_FLASH_EN_MULTCYC_READ_MASK 0x1 +#define TERCEL_SPI_FLASH_EN_MULTCYC_READ_SHIFT 0 +#define TERCEL_SPI_FLASH_CS_EN_LIMIT_CYC_MASK 0xffffffff +#define TERCEL_SPI_FLASH_CS_EN_LIMIT_CYC_SHIFT 0 + +#define TERCEL_SPI_3BA_SPI_CMD_MASK 0xff +#define TERCEL_SPI_3BA_SPI_CMD_SHIFT 0 +#define TERCEL_SPI_4BA_SPI_CMD_MASK 0xff +#define TERCEL_SPI_4BA_SPI_CMD_SHIFT 8 +#define TERCEL_SPI_3BA_QSPI_CMD_MASK 0xff +#define TERCEL_SPI_3BA_QSPI_CMD_SHIFT 16 +#define TERCEL_SPI_4BA_QSPI_CMD_MASK 0xff +#define TERCEL_SPI_4BA_QSPI_CMD_SHIFT 24 + +#define TERCEL_SPI_PHY_IO_TYPE_SINGLE 0x0 +#define TERCEL_SPI_PHY_IO_TYPE_QUAD 0x2 + +#define TERCEL_SPI_PHY_3BA_MODE 0x0 +#define TERCEL_SPI_PHY_4BA_MODE 0x1 + diff --git a/src/ls2.py b/src/ls2.py index 53c3792..db1cf37 100644 --- a/src/ls2.py +++ b/src/ls2.py @@ -871,7 +871,7 @@ def build_platform(fpga, firmware): clk_freq = 50e6 dram_clk_freq = 100e6 if fpga == 'arty_a7': - clk_freq = 24e6 # urrr "working" with the QSPI core (25 mhz does not) + clk_freq = 23.0e6 # urrr "working" with the QSPI core (25 mhz does not) if fpga == 'ulx3s': clk_freq = 40.0e6 if fpga == 'orangecrab': @@ -1104,6 +1104,10 @@ def build_platform(fpga, firmware): #os.environ['NMIGEN_synth_opts'] = '-abc9' os.environ['NMIGEN_synth_opts'] = '-nowidelut' + if toolchain == 'yosys_nextpnr': + # add --seed 2 to arty a7 compile-time options + os.environ['NMIGEN_nextpnr_opts'] = '--seed 6' + if platform is not None: # build and upload it if fpga == 'isim': -- 2.30.2