mirror of https://github.com/wolfSSL/wolfBoot.git
783 lines
33 KiB
C
783 lines
33 KiB
C
/* mpfs250.h
|
|
*
|
|
* Copyright (C) 2026 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfBoot.
|
|
*
|
|
* wolfBoot is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfBoot is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
#ifndef MPFS250_DEF_INCLUDED
|
|
#define MPFS250_DEF_INCLUDED
|
|
|
|
/* Generic RISC-V definitions are included at the end of this file
|
|
* (after PLIC_BASE is defined) to enable PLIC function declarations */
|
|
|
|
/* PolarFire SoC MPFS250T board specific configuration */
|
|
|
|
/* APB/AHB Peripheral Bus Clock Frequency (used for UART baud rate divisor)
|
|
* M-mode (out of reset, no PLL): 40 MHz
|
|
* S-mode (after HSS configures PLL): 150 MHz
|
|
*/
|
|
#ifndef MSS_APB_AHB_CLK
|
|
#ifdef WOLFBOOT_RISCV_MMODE
|
|
#define MSS_APB_AHB_CLK 40000000
|
|
#else
|
|
#define MSS_APB_AHB_CLK 150000000
|
|
#endif
|
|
#endif
|
|
|
|
/* CPU Core Clock Frequency (used for mcycle-based benchmarking)
|
|
* The E51 core runs at 2x the APB bus clock on reset.
|
|
* After HSS configures the PLL, CPU runs at 600 MHz. */
|
|
#ifndef MSS_CPU_CLK
|
|
#ifdef WOLFBOOT_RISCV_MMODE
|
|
#define MSS_CPU_CLK (MSS_APB_AHB_CLK * 2)
|
|
#else
|
|
#define MSS_CPU_CLK 600000000
|
|
#endif
|
|
#endif
|
|
|
|
/* E51 reset clock in MHz, used to seed mpfs_cpu_freq_mhz for udelay().
|
|
* Bumped to the Libero PLL rate after mss_pll_init() (see hal/mpfs250_ddr.c). */
|
|
#ifndef MPFS_CPU_FREQ_RESET_MHZ
|
|
#define MPFS_CPU_FREQ_RESET_MHZ 80U
|
|
#endif
|
|
|
|
/* Full-DDRC-reinit attempts in hal_init() (per-attempt failure rate ~30%). */
|
|
#ifndef MPFS_DDR_MAX_OUTER_RETRY
|
|
#define MPFS_DDR_MAX_OUTER_RETRY 6U
|
|
#endif
|
|
|
|
/* Hardware Base Address */
|
|
#define SYSREG_BASE 0x20002000
|
|
|
|
/* Write "0xDEAD" to cause a full MSS reset*/
|
|
#define SYSREG_MSS_RESET_CR (*((volatile uint32_t*)(SYSREG_BASE + 0x18)))
|
|
|
|
/* Peripheral Subblock Clock Control Register (offset 0x84) */
|
|
#define SYSREG_SUBBLK_CLOCK_CR (*((volatile uint32_t*)(SYSREG_BASE + 0x84)))
|
|
#define SYSREG_SUBBLK_CLOCK_CR_ENVM (1U << 0)
|
|
#define SYSREG_SUBBLK_CLOCK_CR_MMC (1U << 3)
|
|
#define SYSREG_SUBBLK_CLOCK_CR_QSPI (1U << 19)
|
|
|
|
/* Peripheral Soft Reset Control Register (offset 0x88) */
|
|
#define SYSREG_SOFT_RESET_CR (*((volatile uint32_t*)(SYSREG_BASE + 0x88)))
|
|
#define SYSREG_SOFT_RESET_CR_QSPI (1U << 19)
|
|
|
|
/* eNVM Control Register (offset 0xB8). Bits [5:0] set the AHB-to-eNVM
|
|
* clock divider (period = (value+1) * AHB period); bit 6 (clock-okay)
|
|
* latches once a new divider has taken effect. Must be reprogrammed for
|
|
* the faster AHB clock BEFORE the MSS PLL mux switch (HSS does this in
|
|
* mss_mux_post_mss_pll_config with LIBERO_SETTING_MSS_ENVM_CR). */
|
|
#define SYSREG_ENVM_CR (*((volatile uint32_t*)(SYSREG_BASE + 0xB8)))
|
|
#define SYSREG_ENVM_CR_CLOCK_OKAY (1U << 6)
|
|
|
|
/* MSS Peripheral control bits (shared by SUBBLK_CLOCK_CR and SOFT_RESET_CR) */
|
|
#define MSS_PERIPH_ENVM (1U << 0)
|
|
#define MSS_PERIPH_MMC (1U << 3)
|
|
#define MSS_PERIPH_MMUART0 (1U << 5)
|
|
#define MSS_PERIPH_MMUART1 (1U << 6)
|
|
#define MSS_PERIPH_MMUART2 (1U << 7)
|
|
#define MSS_PERIPH_MMUART3 (1U << 8)
|
|
#define MSS_PERIPH_MMUART4 (1U << 9)
|
|
#define MSS_PERIPH_SPI0 (1U << 10)
|
|
#define MSS_PERIPH_SPI1 (1U << 11)
|
|
#define MSS_PERIPH_QSPI (1U << 19)
|
|
#define MSS_PERIPH_GPIO0 (1U << 20)
|
|
#define MSS_PERIPH_GPIO1 (1U << 21)
|
|
#define MSS_PERIPH_GPIO2 (1U << 22)
|
|
#define MSS_PERIPH_DDRC (1U << 23)
|
|
#define MSS_PERIPH_ATHENA (1U << 28) /* Crypto hardware accelerator */
|
|
|
|
/* MSS Watchdog Timer (per-hart) */
|
|
#define MSS_WDT_E51_BASE 0x20001000UL
|
|
#define MSS_WDT_U54_1_BASE 0x20101000UL
|
|
#define MSS_WDT_U54_2_BASE 0x20103000UL
|
|
#define MSS_WDT_U54_3_BASE 0x20105000UL
|
|
#define MSS_WDT_U54_4_BASE 0x20107000UL
|
|
#define MSS_WDT_REFRESH(base) (*(volatile uint32_t*)((base) + 0x00))
|
|
#define MSS_WDT_CONTROL(base) (*(volatile uint32_t*)((base) + 0x04))
|
|
#define MSS_WDT_STATUS(base) (*(volatile uint32_t*)((base) + 0x08))
|
|
#define MSS_WDT_TIME(base) (*(volatile uint32_t*)((base) + 0x0C))
|
|
#define MSS_WDT_MVRP(base) (*(volatile uint32_t*)((base) + 0x10))
|
|
#define MSS_WDT_CTRL_ENABLE (1U << 0)
|
|
|
|
/* UART */
|
|
#define MSS_UART0_LO_BASE 0x20000000UL
|
|
#define MSS_UART1_LO_BASE 0x20100000UL
|
|
#define MSS_UART2_LO_BASE 0x20102000UL
|
|
#define MSS_UART3_LO_BASE 0x20104000UL
|
|
#define MSS_UART4_LO_BASE 0x20106000UL
|
|
|
|
#define MSS_UART0_HI_BASE 0x28000000UL
|
|
#define MSS_UART1_HI_BASE 0x28100000UL
|
|
#define MSS_UART2_HI_BASE 0x28102000UL
|
|
#define MSS_UART3_HI_BASE 0x28104000UL
|
|
#define MSS_UART4_HI_BASE 0x28106000UL
|
|
|
|
/* Debug UART port selection (0-4): M-mode defaults to UART0, S-mode to UART1 */
|
|
#ifndef DEBUG_UART_PORT
|
|
#ifdef WOLFBOOT_RISCV_MMODE
|
|
#define DEBUG_UART_PORT 0
|
|
#else
|
|
#define DEBUG_UART_PORT 1
|
|
#endif
|
|
#endif
|
|
|
|
/* Derive base address from port number */
|
|
#if DEBUG_UART_PORT == 0
|
|
#define DEBUG_UART_BASE MSS_UART0_LO_BASE
|
|
#elif DEBUG_UART_PORT == 1
|
|
#define DEBUG_UART_BASE MSS_UART1_LO_BASE
|
|
#elif DEBUG_UART_PORT == 2
|
|
#define DEBUG_UART_BASE MSS_UART2_LO_BASE
|
|
#elif DEBUG_UART_PORT == 3
|
|
#define DEBUG_UART_BASE MSS_UART3_LO_BASE
|
|
#elif DEBUG_UART_PORT == 4
|
|
#define DEBUG_UART_BASE MSS_UART4_LO_BASE
|
|
#else
|
|
#error "Invalid DEBUG_UART_PORT (must be 0-4)"
|
|
#endif
|
|
|
|
#define MMUART_RBR(base) *((volatile uint8_t*)((base)) + 0x00) /* Receiver buffer register */
|
|
#define MMUART_IER(base) *((volatile uint8_t*)((base)) + 0x04) /* Interrupt enable register */
|
|
#define MMUART_IIR(base) *((volatile uint8_t*)((base)) + 0x08) /* Interrupt ID register */
|
|
#define MMUART_LCR(base) *((volatile uint8_t*)((base)) + 0x0C) /* Line control register */
|
|
#define MMUART_MCR(base) *((volatile uint8_t*)((base)) + 0x10) /* Modem control register */
|
|
#define MMUART_LSR(base) *((volatile uint8_t*)((base)) + 0x14) /* Line status register */
|
|
#define MMUART_MM0(base) *((volatile uint8_t*)((base)) + 0x30) /* Mode register 0 */
|
|
#define MMUART_MM1(base) *((volatile uint8_t*)((base)) + 0x34) /* Mode register 1 */
|
|
#define MMUART_MM2(base) *((volatile uint8_t*)((base)) + 0x38) /* Mode register 2 */
|
|
#define MMUART_DFR(base) *((volatile uint8_t*)((base)) + 0x3C) /* Fractional divisor register */
|
|
#define MMUART_GFR(base) *((volatile uint8_t*)((base)) + 0x44) /* Global filter register */
|
|
#define MMUART_TTG(base) *((volatile uint8_t*)((base)) + 0x48) /* TX time guard register */
|
|
#define MMUART_RTO(base) *((volatile uint8_t*)((base)) + 0x4C) /* RX timeout register */
|
|
#define MMUART_DLR(base) *((volatile uint8_t*)((base)) + 0x80) /* Divisor latch LSB */
|
|
#define MMUART_DMR(base) *((volatile uint8_t*)((base)) + 0x84) /* Divisor latch MSB */
|
|
#define MMUART_THR(base) *((volatile uint8_t*)((base)) + 0x100) /* Transmitter holding register */
|
|
#define MMUART_FCR(base) *((volatile uint8_t*)((base)) + 0x104) /* FIFO control register */
|
|
|
|
|
|
/* LCR (Line Control Register) */
|
|
#define MSS_UART_DATA_8_BITS ((uint8_t)0x03)
|
|
#define MSS_UART_NO_PARITY ((uint8_t)0x00)
|
|
#define MSS_UART_ONE_STOP_BIT ((uint8_t)0x00)
|
|
|
|
/* LSR (Line Status Register) */
|
|
#define MSS_UART_DR ((uint8_t)0x01) /* Data ready */
|
|
#define MSS_UART_THRE ((uint8_t)0x20) /* Transmitter holding register empty */
|
|
#define MSS_UART_TEMT ((uint8_t)0x40) /* Transmitter empty (FIFO + shift register) */
|
|
|
|
#define ELIN_MASK (1U << 3) /* Enable LIN header detection */
|
|
#define EIRD_MASK (1U << 2) /* Enable IrDA modem */
|
|
#define EERR_MASK (1U << 0) /* Enable ERR / NACK during stop time */
|
|
|
|
#define RXRDY_TXRDYN_EN_MASK (1U << 0) /* Enable TXRDY and RXRDY signals */
|
|
#define CLEAR_RX_FIFO_MASK (1U << 1) /* Clear receiver FIFO */
|
|
#define CLEAR_TX_FIFO_MASK (1U << 2) /* Clear transmitter FIFO */
|
|
|
|
#define RTS_MASK (1U << 1) /* Request To Send */
|
|
#define LOOP_MASK (1U << 4) /* Local loopback */
|
|
#define RLOOP_MASK (1U << 5) /* Remote loopback & Automatic echo*/
|
|
|
|
#define E_MSB_RX_MASK (1U << 0) /* MSB / LSB first for receiver */
|
|
#define E_MSB_TX_MASK (1U << 1) /* MSB / LSB first for transmitter */
|
|
|
|
#define EAFM_MASK (1U << 1) /* Enable 9-bit address flag mode */
|
|
#define ETTG_MASK (1U << 5) /* Enable transmitter time guard */
|
|
#define ERTO_MASK (1U << 6) /* Enable receiver time-out */
|
|
#define ESWM_MASK (1U << 3) /* Enable single wire half-duplex mode */
|
|
#define EFBR_MASK (1U << 7) /* Enable fractional baud rate mode */
|
|
|
|
/* Line Control register bit masks */
|
|
#define SB_MASK (1U << 6) /* Set break */
|
|
#define DLAB_MASK (1U << 7) /* Divisor latch access bit */
|
|
|
|
/* ============================================================================
|
|
* EMMC/SD Card Controller (Cadence SD4HC)
|
|
* Base Address: 0x20008000
|
|
* ============================================================================ */
|
|
#define EMMC_SD_BASE 0x20008000UL
|
|
|
|
/* ============================================================================
|
|
* System Controller Mailbox
|
|
* Control Base: 0x37020000
|
|
* Mailbox RAM: 0x37020800
|
|
*
|
|
* Used for system services like reading the device serial number.
|
|
* ============================================================================ */
|
|
#define SCBCTRL_BASE 0x37020000UL
|
|
#define SCBMBOX_BASE 0x37020800UL
|
|
|
|
/* System Services Control and Status Register offsets (from SCBCTRL_BASE) */
|
|
#define SERVICES_CR_OFFSET 0x50u
|
|
#define SERVICES_SR_OFFSET 0x54u
|
|
|
|
/* Control Register bits */
|
|
#define SERVICES_CR_REQ_MASK 0x01u
|
|
#define SERVICES_CR_COMMAND_SHIFT 16
|
|
|
|
/* Status Register bits */
|
|
#define SERVICES_SR_BUSY_MASK 0x02u
|
|
#define SERVICES_SR_STATUS_SHIFT 16
|
|
|
|
/* System Service command opcodes */
|
|
#define SYS_SERV_CMD_SERIAL_NUMBER 0x00u
|
|
#define SYS_SERV_CMD_SPI_COPY 0x50u /* SCB mailbox SPI copy service */
|
|
|
|
/* Device serial number size in bytes */
|
|
#define DEVICE_SERIAL_NUMBER_SIZE 16
|
|
|
|
/* Timeout loop iteration counts (override at build time via CFLAGS) */
|
|
#ifndef MPFS_SCB_TIMEOUT
|
|
#define MPFS_SCB_TIMEOUT 10000 /* SCB mailbox polling */
|
|
#endif
|
|
#ifndef QSPI_TIMEOUT_TRIES
|
|
#define QSPI_TIMEOUT_TRIES 100000 /* QSPI controller/TX polling */
|
|
#endif
|
|
#ifndef QSPI_RX_TIMEOUT_TRIES
|
|
#define QSPI_RX_TIMEOUT_TRIES 1000000 /* QSPI RX polling (longer) */
|
|
#endif
|
|
|
|
/* System Controller register access */
|
|
#define SCBCTRL_REG(off) (*((volatile uint32_t*)(SCBCTRL_BASE + (off))))
|
|
#define SCBMBOX_REG(off) (*((volatile uint32_t*)(SCBMBOX_BASE + (off))))
|
|
#define SCBMBOX_BYTE(off) (*((volatile uint8_t*)(SCBMBOX_BASE + (off))))
|
|
|
|
/* System Controller Mailbox API */
|
|
#ifndef __ASSEMBLER__
|
|
int mpfs_scb_service_call(uint8_t opcode, const uint8_t *mb_data,
|
|
uint32_t mb_len, uint32_t timeout);
|
|
int mpfs_scb_read_mailbox(uint8_t *out, uint32_t len);
|
|
int mpfs_read_serial_number(uint8_t *serial);
|
|
#endif /* __ASSEMBLER__ */
|
|
|
|
/* Crypto Engine: Athena F5200 (200 MHz) */
|
|
#define ATHENA_BASE (SYSREG_BASE + 0x125000)
|
|
|
|
|
|
/* L2 Cache Controller (CACHE_CTRL @ 0x02010000) */
|
|
#define L2_CACHE_BASE 0x02010000UL
|
|
|
|
#define L2_CONFIG (*(volatile uint64_t*)(L2_CACHE_BASE + 0x000))
|
|
#define L2_WAY_ENABLE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x008))
|
|
#define L2_WAY_MASK_DMA (*(volatile uint64_t*)(L2_CACHE_BASE + 0x800))
|
|
#define L2_WAY_MASK_AXI4_PORT0 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x808))
|
|
#define L2_WAY_MASK_AXI4_PORT1 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x810))
|
|
#define L2_WAY_MASK_AXI4_PORT2 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x818))
|
|
#define L2_WAY_MASK_AXI4_PORT3 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x820))
|
|
#define L2_WAY_MASK_E51_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x828))
|
|
#define L2_WAY_MASK_E51_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x830))
|
|
#define L2_WAY_MASK_U54_1_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x838))
|
|
#define L2_WAY_MASK_U54_1_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x840))
|
|
#define L2_WAY_MASK_U54_2_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x848))
|
|
#define L2_WAY_MASK_U54_2_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x850))
|
|
#define L2_WAY_MASK_U54_3_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x858))
|
|
#define L2_WAY_MASK_U54_3_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x860))
|
|
#define L2_WAY_MASK_U54_4_DCACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x868))
|
|
#define L2_WAY_MASK_U54_4_ICACHE (*(volatile uint64_t*)(L2_CACHE_BASE + 0x870))
|
|
|
|
/* L2 Shutdown Control Register */
|
|
#define SYSREG_L2_SHUTDOWN_CR (*(volatile uint32_t*)(SYSREG_BASE + 0x174))
|
|
|
|
/* L2 Cache/Scratchpad constants */
|
|
#define L2_NUM_CACHE_WAYS 8 /* Ways 0-7 are cache */
|
|
#define L2_NUM_SCRATCH_WAYS 4 /* Ways 8-11 are scratchpad */
|
|
#define L2_WAY_BYTE_LENGTH 0x20000 /* 128KB per way */
|
|
#define L2_SCRATCH_BASE 0x0A000000UL
|
|
#define L2_SCRATCH_SIZE (L2_NUM_SCRATCH_WAYS * L2_WAY_BYTE_LENGTH)
|
|
|
|
#define L2_WAY_ENABLE_RESET 0x01
|
|
#define L2_WAY_ENABLE_ALL_CACHE 0xFF
|
|
#define L2_WAY_ENABLE_WITH_SCRATCH 0x0FFF
|
|
#define L2_WAY_MASK_CACHE_ONLY 0xFF
|
|
|
|
|
|
/* CLINT - Core Local Interruptor */
|
|
#ifndef CLINT_BASE
|
|
#define CLINT_BASE 0x02000000UL
|
|
#endif
|
|
|
|
/* RTC Clock Frequency (1 MHz after divisor) */
|
|
#define RTC_CLOCK_FREQ 1000000UL
|
|
|
|
/* In M-mode CLINT MTIME is not running without HSS; use mcycle (CPU clock) instead.
|
|
* In S-mode MTIME runs at 1 MHz (default RISCV_SMODE_TIMER_FREQ). */
|
|
#if defined(WOLFBOOT_RISCV_MMODE) && !defined(RISCV_SMODE_TIMER_FREQ)
|
|
#define RISCV_SMODE_TIMER_FREQ MSS_CPU_CLK
|
|
#endif
|
|
|
|
|
|
/* Hart Local Storage (HLS) - per-hart communication structure, 64 bytes at top of stack */
|
|
#define HLS_DEBUG_AREA_SIZE 64
|
|
|
|
#ifndef __ASSEMBLER__
|
|
typedef struct {
|
|
volatile uint32_t in_wfi_indicator; /* 0x00: Hart status indicator */
|
|
volatile uint32_t my_hart_id; /* 0x04: Hart ID */
|
|
volatile uint32_t shared_mem_marker; /* 0x08: Init marker */
|
|
volatile uint32_t shared_mem_status; /* 0x0C: Status */
|
|
volatile uint64_t* shared_mem; /* 0x10: Shared memory pointer */
|
|
volatile uint64_t reserved[5]; /* 0x18: Reserved/padding to 64 bytes */
|
|
} HLS_DATA; /* 64 bytes total */
|
|
#endif /* __ASSEMBLER__ */
|
|
|
|
#define HLS_MAIN_HART_STARTED 0x12344321UL
|
|
#define HLS_OTHER_HART_IN_WFI 0x12345678UL
|
|
|
|
/* DTIM address of the E51 "main hart started" gate flag polled by the
|
|
* parked secondary harts in boot_riscv_start.S. This must NOT live in
|
|
* L2-scratch (the legacy HLS location): cacheable stores to the
|
|
* scratchpad can be silently lost on dirty-line eviction, so whether the
|
|
* secondaries ever saw the flag depended on the image's cache-line
|
|
* layout (observed: a 304-byte text shift left harts 2-4 stuck in the
|
|
* eNVM gate until the kernel's HSM hart_start IPI, missing the kernel's
|
|
* 1s online window). The E51 DTIM is uncached and coherent for every
|
|
* hart. Keep clear of the SBI shared block (DTIM+0x00, src/riscv_sbi.c)
|
|
* and the hart-start mailboxes (DTIM+0x100, hal/mpfs250.c).
|
|
* No UL suffix: also used from assembly (boot_riscv_start.S). */
|
|
#define MPFS_DTIM_MAIN_STARTED_ADDR 0x010000F0
|
|
|
|
/* Number of harts on MPFS */
|
|
#define MPFS_NUM_HARTS 5
|
|
#define MPFS_FIRST_HART 0 /* E51 is hart 0 */
|
|
#define MPFS_FIRST_U54_HART 1 /* First U54 is hart 1 */
|
|
#define MPFS_LAST_U54_HART 4 /* Last U54 is hart 4 */
|
|
|
|
/* Stack configuration per hart */
|
|
#ifndef STACK_SIZE_PER_HART
|
|
#define STACK_SIZE_PER_HART 8192
|
|
#endif
|
|
|
|
/* Multi-hart function declarations */
|
|
#ifndef __ASSEMBLER__
|
|
#ifdef DEBUG_UART
|
|
void uart_init(void);
|
|
void uart_write(const char* buf, unsigned int sz);
|
|
#endif
|
|
#ifdef WOLFBOOT_RISCV_MMODE
|
|
void secondary_hart_entry(unsigned long hartid, HLS_DATA* hls);
|
|
#endif
|
|
#endif /* __ASSEMBLER__ */
|
|
|
|
|
|
|
|
/* PLIC - Platform-Level Interrupt Controller (base 0x0C000000, 64MB) */
|
|
#define PLIC_BASE 0x0C000000UL
|
|
#define PLIC_SIZE 0x04000000UL
|
|
#define PLIC_NUM_SOURCES 186
|
|
#define PLIC_NUM_HARTS 5
|
|
#define PLIC_NUM_CONTEXTS 10
|
|
#define OFFSET_TO_MSS_GLOBAL_INTS 13
|
|
|
|
#define PLIC_INT_MMC_MAIN 88
|
|
|
|
|
|
/* ============================================================================
|
|
* DDR Controller and PHY (LPDDR4) - Video Kit MPFS250T
|
|
*
|
|
* MPFS DDR subsystem consists of:
|
|
* - DDR Controller (DDRCFG_BASE @ 0x20080000) - timing, addressing, refresh
|
|
* - DDR PHY (CFG_DDR_SGMII_PHY @ 0x20007000) - physical interface, training
|
|
* - Segment registers for address translation
|
|
* - SCB PLLs for clock generation
|
|
*
|
|
* Video Kit memory: Micron MT53D512M32D2DS-053 LPDDR4 (2GB, x32 @ 1600 Mbps)
|
|
* ============================================================================ */
|
|
|
|
/* SCB Configuration Block (SCBCFG @ 0x37080000) */
|
|
#define SCBCFG_BASE 0x37080000UL
|
|
#define SCBCFG_TIMER (*(volatile uint32_t*)(SCBCFG_BASE + 0x08))
|
|
#define MSS_SCB_ACCESS_CONFIG 0x0008A080UL
|
|
|
|
/* DDR SGMII PHY Configuration (CFG_DDR_SGMII_PHY @ 0x20007000) */
|
|
#define CFG_DDR_SGMII_PHY_BASE 0x20007000UL
|
|
#define DDRPHY_STARTUP (*(volatile uint32_t*)(CFG_DDR_SGMII_PHY_BASE + 0x008))
|
|
#define DDRPHY_DYN_CNTL (*(volatile uint32_t*)(CFG_DDR_SGMII_PHY_BASE + 0xC1C))
|
|
#define DDRPHY_STARTUP_CONFIG 0x003F1F00UL
|
|
#define DDRPHY_DYN_CNTL_CONFIG 0x0000047FUL
|
|
|
|
/* DFI APB interface control (enables DDR PHY APB access) */
|
|
#define SYSREG_DFIAPB_CR (*(volatile uint32_t*)(SYSREG_BASE + 0x98))
|
|
|
|
/* L2 cache flush registers (used at boot for DDR coherency) */
|
|
#define L2_FLUSH64 (*(volatile uint64_t*)(L2_CACHE_BASE + 0x200))
|
|
#define L2_FLUSH32 (*(volatile uint32_t*)(L2_CACHE_BASE + 0x240))
|
|
|
|
/* DDR Base Addresses */
|
|
#define SYSREGSCB_BASE 0x20003000UL
|
|
#define DDRCFG_BASE 0x20080000UL /* DDR Controller CSR APB */
|
|
#define DDR_SEG_BASE 0x20005D00UL /* From HSS mss_seg.h */
|
|
|
|
/* SCB PLL Bases */
|
|
#define SCB_MSS_PLL_BASE 0x3E001000UL
|
|
#define SCB_DDR_PLL_BASE 0x3E010000UL
|
|
|
|
/* Clock Fabric Mux bases */
|
|
#define SCB_CFM_MSS_BASE 0x3E002000UL
|
|
#define SCB_CFM_SGMII_BASE 0x3E200000UL
|
|
|
|
/* DDR Bank Controller (NV map reset during VREF training) */
|
|
#define SCB_BANKCONT_DDR_BASE 0x3E020000UL
|
|
|
|
/* Register Access Macros */
|
|
#define SYSREG_REG(off) (*(volatile uint32_t*)(SYSREG_BASE + (off)))
|
|
#define SYSREGSCB_REG(off) (*(volatile uint32_t*)(SYSREGSCB_BASE + (off)))
|
|
#define DDRCFG_REG(off) (*(volatile uint32_t*)(DDRCFG_BASE + (off)))
|
|
#define DDRPHY_REG(off) (*(volatile uint32_t*)(CFG_DDR_SGMII_PHY_BASE + (off)))
|
|
#define DDR_BANKCONT_REG(off) (*(volatile uint32_t*)(SCB_BANKCONT_DDR_BASE + (off)))
|
|
#define DDR_SEG_REG(off) (*(volatile uint32_t*)(DDR_SEG_BASE + (off)))
|
|
#define SCBCFG_REG(off) (*(volatile uint32_t*)(SCBCFG_BASE + (off)))
|
|
#define MSS_PLL_REG(off) (*(volatile uint32_t*)(SCB_MSS_PLL_BASE + (off)))
|
|
#define DDR_PLL_REG(off) (*(volatile uint32_t*)(SCB_DDR_PLL_BASE + (off)))
|
|
#define CFM_MSS_REG(off) (*(volatile uint32_t*)(SCB_CFM_MSS_BASE + (off)))
|
|
#define CFM_SGMII_REG(off) (*(volatile uint32_t*)(SCB_CFM_SGMII_BASE + (off)))
|
|
|
|
/* SYSREG Offsets */
|
|
#define SYSREG_SUBBLK_CLOCK_CR_OFF 0x84
|
|
#define SYSREG_SOFT_RESET_CR_OFF 0x88
|
|
#define SYSREG_DFIAPB_CR_OFF 0x98
|
|
#define MSSIO_CONTROL_CR_OFF 0x1BC
|
|
|
|
/* PLL Register Offsets */
|
|
#define PLL_SOFT_RESET 0x000
|
|
#define PLL_CTRL 0x004
|
|
#define PLL_REF_FB 0x008
|
|
#define PLL_FRACN 0x00C
|
|
#define PLL_DIV_0_1 0x010
|
|
#define PLL_DIV_2_3 0x014
|
|
#define PLL_CTRL2 0x018
|
|
#define PLL_PHADJ 0x020
|
|
#define PLL_SSCG_0 0x024
|
|
#define PLL_SSCG_1 0x028
|
|
#define PLL_SSCG_2 0x02C
|
|
#define PLL_SSCG_3 0x030
|
|
|
|
/* PLL Control Bits */
|
|
#define PLL_POWERDOWN_B (1UL << 0)
|
|
#define PLL_LOCK_BIT (1UL << 25)
|
|
#define PLL_INIT_OUT_RESET 0x00000003UL
|
|
|
|
/* CFM Register Offsets */
|
|
#define CFM_BCLKMUX 0x004
|
|
#define CFM_PLL_CKMUX 0x008
|
|
#define CFM_MSSCLKMUX 0x00C
|
|
#define CFM_FMETER_ADDR 0x014
|
|
#define CFM_FMETER_DATAW 0x018
|
|
|
|
/* SGMII CFM Register Offsets (at SCB_CFM_SGMII_BASE 0x3E200000) */
|
|
#define CFM_SGMII_SOFT_RESET 0x000
|
|
#define CFM_SGMII_RFCKMUX 0x004 /* Routes refclk to DDR/SGMII PLLs */
|
|
#define CFM_SGMII_SGMII_CLKMUX 0x008
|
|
#define CFM_SGMII_SPARE0 0x00C
|
|
#define CFM_SGMII_CLK_XCVR 0x010
|
|
|
|
/* DDR PHY Register Offsets */
|
|
#define PHY_SOFT_RESET 0x000
|
|
#define PHY_MODE 0x004
|
|
#define PHY_STARTUP 0x008
|
|
#define PHY_PLL_CTRL_MAIN 0x084
|
|
#define PHY_DPC_BITS 0x184
|
|
#define PHY_BANK_STATUS 0x188
|
|
#define PHY_IOC_REG0 0x204
|
|
#define PHY_IOC_REG1 0x208
|
|
#define PHY_IOC_REG2 0x20C
|
|
#define PHY_IOC_REG3 0x210
|
|
#define PHY_IOC_REG6 0x21C /* Calibration reset/clock divider */
|
|
#define PHY_DYN_CNTL 0xC1C
|
|
#define PHY_SOFT_RESET_TIP 0x800
|
|
#define PHY_RANK_SELECT 0x804
|
|
#define PHY_LANE_SELECT 0x808 /* was wrongly named PHY_BCLK_SCLK */
|
|
/* The real BCLK/SCLK training answer is at 0x870 (bclksclk_answer).
|
|
* Old PHY_BCLK_SCLK at 0x808 was lane_select, so any printf of it
|
|
* was meaningless. */
|
|
#define PHY_BCLKSCLK_ANSWER 0x870
|
|
#define PHY_TRAINING_SKIP 0x80C
|
|
#define PHY_TRAINING_START 0x810
|
|
#define PHY_TRAINING_STATUS 0x814
|
|
#define PHY_TRAINING_RESET 0x818
|
|
#define PHY_TIP_CFG 0x828
|
|
#define PHY_TIP_CFG_PARAMS 0x8D0
|
|
#define PHY_EXPERT_MODE_EN 0x878
|
|
#define PHY_EXPERT_DLYCNT_MOVE0 0x87C
|
|
#define PHY_EXPERT_DLYCNT_MOVE1 0x880
|
|
#define PHY_EXPERT_DLYCNT_DIRECTION0 0x884
|
|
#define PHY_EXPERT_DLYCNT_DIR1 0x888
|
|
#define PHY_EXPERT_DLYCNT_LOAD0 0x88C
|
|
#define PHY_EXPERT_DLYCNT_LOAD1 0x890
|
|
#define PHY_EXPERT_DFI_STATUS_TO_SHIM 0x8CC
|
|
#define PHY_LANE_ALIGN_FIFO_CTRL 0x8D8
|
|
#define PHY_EXPERT_MV_RD_DLY 0x89C
|
|
#define PHY_EXPERT_DLYCNT_PAUSE 0x8A0
|
|
#define PHY_EXPERT_PLLCNT 0x8A4
|
|
#define PHY_EXPERT_DQ_READBACK 0x8A8
|
|
#define PHY_EXPERT_ADDCMD_READBACK 0x8AC /* Bits 13:12 = rx_bclksclk, 3:0 = rx_ck */
|
|
/* 0x8B0 is expert_read_gate_controls, NOT a DFI status register.
|
|
* Previous PHY_EXPERT_DFI_STATUS define here pointed writes
|
|
* (0x6/0x4/0x0 for DQ/DQS output delay setup) at the wrong register.
|
|
* The correct register is PHY_EXPERT_DFI_STATUS_TO_SHIM at 0x8CC. */
|
|
#define PHY_EXPERT_READ_GATE_CONTROLS 0x8B0
|
|
#define PHY_EXPERT_WRCALIB 0x8BC
|
|
#define PHY_RPC95_IBUFMD_ADDCMD 0x57C /* LPDDR4 Input Buffer Mode - ADDCMD */
|
|
#define PHY_RPC96_IBUFMD_CLK 0x580 /* LPDDR4 Input Buffer Mode - CLK */
|
|
#define PHY_RPC97_IBUFMD_DQ 0x584 /* LPDDR4 Input Buffer Mode - DQ */
|
|
#define PHY_RPC98_IBUFMD_DQS 0x588 /* LPDDR4 Input Buffer Mode - DQS */
|
|
#define PHY_RPC145 0x644 /* ADDCMD delay offset (A9 loopback) */
|
|
#define PHY_RPC147 0x64C /* DDR clock loopback delay */
|
|
#define PHY_RPC156 0x670
|
|
#define PHY_RPC166 0x698
|
|
#define PHY_RPC168 0x6A0 /* RX_MD_CLKN for LPDDR4 training */
|
|
#define PHY_RPC220 0x770
|
|
|
|
/* ODT (On-Die Termination) RPC registers */
|
|
#define PHY_RPC1_ODT 0x384 /* ODT_CA */
|
|
#define PHY_RPC2_ODT 0x388 /* ODT_CLK */
|
|
#define PHY_RPC3_ODT 0x38C /* ODT_DQ (0 for WRLVL, 3 normally) */
|
|
#define PHY_RPC4_ODT 0x390 /* ODT_DQS */
|
|
|
|
/* PVT calibration bits */
|
|
#define PVT_CALIB_START (1U << 0)
|
|
#define PVT_CALIB_LOCK (1U << 14)
|
|
#define PVT_CALIB_STATUS (1U << 2)
|
|
#define PVT_IOEN_OUT (1U << 4)
|
|
|
|
/* IOSCB IO Calibration DDR base (SCB space for PVT calibration) */
|
|
#define IOSCB_IO_CALIB_DDR_BASE 0x3E040000UL
|
|
#define IOSCB_IO_CALIB_DDR_REG(off) (*(volatile uint32_t*)(IOSCB_IO_CALIB_DDR_BASE + (off)))
|
|
#define IOSCB_SOFT_RESET 0x000
|
|
#define IOSCB_IOC_REG0 0x004
|
|
#define IOSCB_IOC_REG1 0x008
|
|
|
|
|
|
/* DDR Segment Register Offsets.
|
|
* SEG is a 256-byte-stride peripheral pair (mss_seg.h:54): seg_t has
|
|
* 8 x u32 control regs + 56 x u32 fill = 256 B. SEG[0] is at base
|
|
* (DDR_SEG_BASE = 0x20005D00); SEG[1] is at base + 0x100 (= 0x20005E00).
|
|
* Phase 3.10.3 (A) finding: wolfBoot previously put SEG1_X at offset
|
|
* 0x20-0x3C (overwriting unrelated registers), so the SEG1 cached/
|
|
* non-cached DDR address-mapping registers were never written --
|
|
* 0x80000000 stores faulted with cause=7 (store access fault). */
|
|
#define SEG0_0 0x00
|
|
#define SEG0_1 0x04
|
|
#define SEG0_2 0x08
|
|
#define SEG0_3 0x0C
|
|
#define SEG0_4 0x10
|
|
#define SEG0_5 0x14
|
|
#define SEG0_6 0x18
|
|
#define SEG0_BLOCKER 0x1C
|
|
#define SEG1_0 0x100
|
|
#define SEG1_1 0x104
|
|
#define SEG1_2 0x108
|
|
#define SEG1_3 0x10C
|
|
#define SEG1_4 0x110
|
|
#define SEG1_5 0x114
|
|
#define SEG1_6 0x118
|
|
#define SEG1_7 0x11C
|
|
|
|
/* DDR Memory Map */
|
|
#define DDR_BASE_CACHED 0x80000000UL /* Cached access */
|
|
#define DDR_BASE_NONCACHED 0xC0000000UL /* Non-cached access */
|
|
#define DDR_BASE_NONCACHED_WCB 0xD0000000UL /* Non-cached with write-combining */
|
|
#define DDR_SIZE 0x80000000UL /* 2GB (Video Kit) */
|
|
|
|
/* DDR Init return codes */
|
|
#define DDR_INIT_SUCCESS 0
|
|
#define DDR_INIT_TIMEOUT -1
|
|
#define DDR_INIT_TRAINING_FAIL -2
|
|
#define DDR_INIT_MEM_TEST_FAIL -3
|
|
|
|
|
|
/* ============================================================================
|
|
* Video Kit Clock/DDR Configuration
|
|
*
|
|
* The LIBERO_SETTING_* values come from a Libero/HSS-generated
|
|
* fpga_design_config.h for the target board. Set LIBERO_FPGA_CONFIG_DIR
|
|
* at build time to point at the directory containing fpga_design_config.h
|
|
* (see arch.mk and the polarfire_mpfs250_m.config example).
|
|
* ============================================================================ */
|
|
#ifdef MPFS_DDR_INIT
|
|
#include "fpga_design_config.h"
|
|
#endif
|
|
|
|
/* DDR function declarations */
|
|
#ifndef __ASSEMBLER__
|
|
#ifdef WOLFBOOT_RISCV_MMODE
|
|
int mpfs_ddr_init(unsigned int outer_retry);
|
|
void hal_uart_reinit(void);
|
|
|
|
/* Verbose DDR/PLL/PHY/training trace (build with -DDEBUG_DDR). Defined in
|
|
* the header so both hal/mpfs250.c (WDT/L2/text-verify dumps) and
|
|
* hal/mpfs250_ddr.c (the DDR driver) can use it. */
|
|
#ifdef DEBUG_DDR
|
|
# define DBG_DDR(_f_, ...) wolfBoot_printf(_f_, ##__VA_ARGS__)
|
|
#else
|
|
# define DBG_DDR(_f_, ...) do { } while (0)
|
|
#endif
|
|
|
|
/* Full system memory barrier (AXI/peripheral ordering). */
|
|
static inline void mb(void)
|
|
{
|
|
__asm__ volatile("fence iorw, iorw" ::: "memory");
|
|
}
|
|
|
|
/* mcycle-based microsecond busy delay. Defined in hal/mpfs250.c (it must
|
|
* exist in non-DDR M-mode builds too); read from hal/mpfs250_ddr.c. */
|
|
void udelay(uint32_t us);
|
|
|
|
/* CPU/APB clock rates, defined in hal/mpfs250.c (read by udelay() and the
|
|
* UART baud divisor in every M-mode build) and updated by mss_pll_init() in
|
|
* hal/mpfs250_ddr.c when the MSS PLL is raised. */
|
|
extern uint32_t mpfs_cpu_freq_mhz;
|
|
extern uint32_t mpfs_apb_clk_hz;
|
|
|
|
#ifdef MPFS_DDR_INIT
|
|
/* MSSIO IOMUX setup: defined in hal/mpfs250.c (alongside the SDHCI platform
|
|
* helpers) but called from nwc_init() in hal/mpfs250_ddr.c. */
|
|
void mpfs_iomux_init(void);
|
|
#endif
|
|
|
|
/* PDMA-based memcpy: src must be CPU-readable (L2 Scratch / LIM / DDR
|
|
* already loaded), dst is the destination AXI address. When dst is in
|
|
* the cached DDR window (top 4 bits = 0x8) the helper rewrites it to
|
|
* the non-cached alias (top 4 bits = 0xC) before kicking PDMA, since
|
|
* PDMA-via-non-cached is the only AXI write path that consistently
|
|
* lands in DDR on this board. Returns 0 on success, non-zero on
|
|
* timeout. */
|
|
int mpfs_pdma_memcpy(void *dst, const void *src, uint32_t bytes);
|
|
#endif
|
|
#endif /* __ASSEMBLER__ */
|
|
|
|
|
|
#ifdef EXT_FLASH
|
|
/* QSPI Flash Controller
|
|
*
|
|
* Two CoreQSPI v2 controllers with identical register layouts:
|
|
* SC QSPI (MPFS_SC_SPI=1, default): 0x37020100 -- fabric-connected flash
|
|
* MSS QSPI (MPFS_SC_SPI=0): 0x21000000 -- MSS QSPI pins
|
|
*/
|
|
|
|
/* QSPI Controller Base Address */
|
|
#ifndef QSPI_BASE
|
|
#ifdef MPFS_SC_SPI
|
|
#define QSPI_BASE 0x37020100u /* SC QSPI Controller (fabric-connected flash) */
|
|
#else
|
|
#define QSPI_BASE 0x21000000u /* MSS QSPI Controller (external flash) */
|
|
#endif
|
|
#endif
|
|
|
|
/* QSPI Register Offsets */
|
|
#define QSPI_CONTROL (*(volatile uint32_t *)(QSPI_BASE + 0x00))
|
|
#define QSPI_FRAMES (*(volatile uint32_t *)(QSPI_BASE + 0x04))
|
|
#define QSPI_IEN (*(volatile uint32_t *)(QSPI_BASE + 0x0C))
|
|
#define QSPI_STATUS (*(volatile uint32_t *)(QSPI_BASE + 0x10))
|
|
#define QSPI_DIRECT (*(volatile uint32_t *)(QSPI_BASE + 0x14))
|
|
#define QSPI_ADDRUP (*(volatile uint32_t *)(QSPI_BASE + 0x18))
|
|
#define QSPI_RX_DATA (*(volatile uint8_t *)(QSPI_BASE + 0x40))
|
|
#define QSPI_TX_DATA (*(volatile uint8_t *)(QSPI_BASE + 0x44))
|
|
#define QSPI_X4_RX_DATA (*(volatile uint32_t *)(QSPI_BASE + 0x48))
|
|
#define QSPI_X4_TX_DATA (*(volatile uint32_t *)(QSPI_BASE + 0x4C))
|
|
#define QSPI_FRAMESUP (*(volatile uint32_t *)(QSPI_BASE + 0x50))
|
|
|
|
/* QSPI Control Register Bits */
|
|
#define QSPI_CTRL_EN_OFFSET 0
|
|
#define QSPI_CTRL_XIP_OFFSET 2
|
|
#define QSPI_CTRL_XIPADDR_OFFSET 3
|
|
#define QSPI_CTRL_CLKIDLE_OFFSET 10
|
|
#define QSPI_CTRL_SAMPLE_OFFSET 11
|
|
#define QSPI_CTRL_QMODE0_OFFSET 13
|
|
#define QSPI_CTRL_QMODE12_OFFSET 14
|
|
#define QSPI_CTRL_FLAGSX4_OFFSET 16
|
|
#define QSPI_CTRL_CLKRATE_OFFSET 24
|
|
|
|
#define QSPI_CTRL_EN (1u << QSPI_CTRL_EN_OFFSET)
|
|
#define QSPI_CTRL_XIP (1u << QSPI_CTRL_XIP_OFFSET)
|
|
#define QSPI_CTRL_CLKIDLE (1u << QSPI_CTRL_CLKIDLE_OFFSET)
|
|
#define QSPI_CTRL_SAMPLE_SCK (0x0u << QSPI_CTRL_SAMPLE_OFFSET)
|
|
|
|
/* QSPI Frames Register Bits */
|
|
#define QSPI_FRAMES_TOTALBYTES_OFFSET 0
|
|
#define QSPI_FRAMES_CMDBYTES_OFFSET 16
|
|
#define QSPI_FRAMES_QSPI_OFFSET 25
|
|
#define QSPI_FRAMES_IDLE_OFFSET 26
|
|
#define QSPI_FRAMES_FBYTE_OFFSET 30
|
|
#define QSPI_FRAMES_FWORD_OFFSET 31
|
|
|
|
#define QSPI_FRAMES_TOTALBYTES_MASK (0xFFFFu << QSPI_FRAMES_TOTALBYTES_OFFSET)
|
|
#define QSPI_FRAMES_CMDBYTES_MASK (0x1FFu << QSPI_FRAMES_CMDBYTES_OFFSET)
|
|
#define QSPI_FRAMES_QSPI (1u << QSPI_FRAMES_QSPI_OFFSET)
|
|
#define QSPI_FRAMES_IDLE_MASK (0xFu << QSPI_FRAMES_IDLE_OFFSET)
|
|
|
|
/* QSPI Status Register Bits */
|
|
#define QSPI_STATUS_TXDONE (1u << 0)
|
|
#define QSPI_STATUS_RXDONE (1u << 1)
|
|
#define QSPI_STATUS_RXAVAIL (1u << 2)
|
|
#define QSPI_STATUS_TXAVAIL (1u << 3)
|
|
#define QSPI_STATUS_READY (1u << 7)
|
|
|
|
/* QSPI Clock Configuration */
|
|
#define QSPI_CLK_DIV_2 0x01u
|
|
#define QSPI_CLK_DIV_4 0x02u
|
|
#define QSPI_CLK_DIV_6 0x03u
|
|
#define QSPI_CLK_DIV_8 0x04u
|
|
#define QSPI_CLK_DIV_10 0x05u
|
|
#define QSPI_CLK_DIV_12 0x06u
|
|
#define QSPI_CLK_DIV_30 0x0Fu /* ~5 MHz from 150 MHz APB */
|
|
|
|
/* Micron MT25QL01G Flash Commands */
|
|
#define QSPI_CMD_READ_ID_OPCODE 0x9Fu /* JEDEC ID Read */
|
|
#define QSPI_CMD_MIO_READ_ID_OPCODE 0xAFu /* Multiple IO Read ID */
|
|
#define QSPI_CMD_READ_STATUS_OPCODE 0x05u /* Read Status Register */
|
|
#define QSPI_CMD_WRITE_ENABLE_OPCODE 0x06u /* Write Enable */
|
|
#define QSPI_CMD_WRITE_DISABLE_OPCODE 0x04u /* Write Disable */
|
|
#define QSPI_CMD_4BYTE_READ_OPCODE 0x13u /* 4-byte address read */
|
|
#define QSPI_CMD_4BYTE_FAST_READ_OPCODE 0x0Cu /* 4-byte fast read */
|
|
#define QSPI_CMD_4BYTE_QUAD_READ_OPCODE 0xECu /* 4-byte quad I/O read */
|
|
#define QSPI_CMD_4BYTE_PAGE_PROG_OPCODE 0x12u /* 4-byte page program */
|
|
#define QSPI_CMD_4BYTE_SECTOR_ERASE 0xDCu /* 4-byte 64KB sector erase */
|
|
#define QSPI_CMD_ENTER_4BYTE_MODE 0xB7u /* Enter 4-byte address mode */
|
|
#define QSPI_CMD_EXIT_4BYTE_MODE 0xE9u /* Exit 4-byte address mode */
|
|
|
|
/* Flash Geometry - Micron MT25QL01GBBB (128MB) */
|
|
#ifndef FLASH_DEVICE_SIZE
|
|
#define FLASH_DEVICE_SIZE (128 * 1024 * 1024) /* 128MB (1Gb) */
|
|
#endif
|
|
|
|
#ifndef FLASH_PAGE_SIZE
|
|
#define FLASH_PAGE_SIZE 256 /* 256 bytes */
|
|
#endif
|
|
|
|
#ifndef FLASH_SECTOR_SIZE
|
|
#define FLASH_SECTOR_SIZE (64 * 1024) /* 64KB sectors */
|
|
#endif
|
|
|
|
/* QSPI Transfer Modes */
|
|
#define QSPI_MODE_WRITE 0
|
|
#define QSPI_MODE_READ 1
|
|
|
|
/* I/O fence: ensure MMIO store reaches the peripheral before the next read.
|
|
* Required on RISC-V RVWMO to prevent stale TXAVAIL reads after TX writes. */
|
|
#define QSPI_IO_FENCE() __asm__ __volatile__("fence iorw, iorw" ::: "memory")
|
|
|
|
/* Function declarations for QSPI (when EXT_FLASH enabled) */
|
|
#ifndef __ASSEMBLER__
|
|
int qspi_init(void);
|
|
#endif /* __ASSEMBLER__ */
|
|
|
|
#endif /* EXT_FLASH */
|
|
|
|
|
|
#endif /* MPFS250_DEF_INCLUDED */
|