wolfBoot/hal/mpfs250.h

476 lines
19 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
/* 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)
/* 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_QSPI (1U << 19)
/* 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
/* UART base address table for per-hart access (LO addresses for M-mode) */
#ifndef __ASSEMBLER__
extern const unsigned long MSS_UART_BASE_ADDR[5];
#define UART_BASE_FOR_HART(hart) (MSS_UART_BASE_ADDR[(hart) < 5 ? (hart) : 0])
#endif /* __ASSEMBLER__ */
/* 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 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
/* 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
/* 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
int mpfs_wake_secondary_harts(void);
void secondary_hart_entry(unsigned long hartid, HLS_DATA* hls);
void uart_init_hart(unsigned long hartid);
void uart_write_hart(unsigned long hartid, const char* buf, unsigned int sz);
#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
#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 */