Added QSPI DMA support.

pull/532/head
David Garske 2024-12-10 17:15:34 -08:00 committed by Daniele Lacamera
parent acb9d832eb
commit 7205820afa
7 changed files with 225 additions and 83 deletions

View File

@ -80,6 +80,9 @@ static int qspi_wait_we(QspiDev_t* dev);
static int test_ext_flash(QspiDev_t* dev);
#endif
/* asm function */
extern void flush_dcache_range(unsigned long start, unsigned long stop);
#ifdef DEBUG_UART
void uart_init(void)
{
@ -293,9 +296,23 @@ static inline int qspi_isr_wait(uint32_t wait_mask, uint32_t wait_val)
}
return 0;
}
#ifdef GQSPI_DMA
static inline int qspi_dmaisr_wait(uint32_t wait_mask, uint32_t wait_val)
{
uint32_t timeout = 0;
while ((GQSPIDMA_ISR & wait_mask) == wait_val &&
++timeout < GQSPI_TIMEOUT_TRIES);
if (timeout == GQSPI_TIMEOUT_TRIES) {
return -1;
}
return 0;
}
#endif
static int qspi_gen_fifo_write(uint32_t reg_genfifo)
{
uint32_t reg_cfg;
/* wait until the gen FIFO is not full to write */
if (qspi_isr_wait(GQSPI_IXR_GEN_FIFO_NOT_FULL, 0)) {
return GQSPI_CODE_TIMEOUT;
@ -317,6 +334,17 @@ static int gspi_fifo_tx(const uint8_t* data, uint32_t sz)
return GQSPI_CODE_TIMEOUT;
}
#if defined(DEBUG_ZYNQ) && DEBUG_ZYNQ >= 3
uint32_t txSz = sz;
if (txSz > GQSPI_FIFO_WORD_SZ)
txSz = GQSPI_FIFO_WORD_SZ;
memcpy(&tmp32, data, txSz);
GQSPI_TXD = tmp32;
wolfBoot_printf("TXD=%08x\n", tmp32);
sz -= txSz;
data += txSz;
#else
/* Write data */
if (sz >= 4) {
GQSPI_TXD = *(uint32_t*)data;
@ -329,23 +357,32 @@ static int gspi_fifo_tx(const uint8_t* data, uint32_t sz)
GQSPI_TXD = tmp32;
sz = 0;
}
#endif
}
return GQSPI_CODE_SUCCESS;
}
static int gspi_fifo_rx(uint8_t* data, uint32_t sz, uint32_t discardSz)
#ifndef GQSPI_DMA
static int gspi_fifo_rx(uint8_t* data, uint32_t sz)
{
uint32_t tmp32;
while (sz > 0) {
/* Wait for RX FIFO not empty */
if (qspi_isr_wait(GQSPI_IXR_RX_FIFO_NOT_EMPTY, 0)) {
return GQSPI_CODE_TIMEOUT;
}
if (discardSz >= GQSPI_FIFO_WORD_SZ) {
tmp32 = GQSPI_RXD; /* discard */
discardSz -= GQSPI_FIFO_WORD_SZ;
continue;
}
#if defined(DEBUG_ZYNQ) && DEBUG_ZYNQ >= 3
uint32_t rxSz = sz;
if (rxSz > GQSPI_FIFO_WORD_SZ)
rxSz = GQSPI_FIFO_WORD_SZ;
tmp32 = GQSPI_RXD;
memcpy(data, &tmp32, rxSz);
wolfBoot_printf("RXD=%08x\n", tmp32);
sz -= rxSz;
data += rxSz;
#else
if (sz >= 4) {
*(uint32_t*)data = GQSPI_RXD;
data += 4;
@ -356,9 +393,11 @@ static int gspi_fifo_rx(uint8_t* data, uint32_t sz, uint32_t discardSz)
memcpy(data, &tmp32, sz);
sz = 0;
}
#endif
}
return GQSPI_CODE_SUCCESS;
}
#endif
static int qspi_cs(QspiDev_t* pDev, int csAssert)
{
@ -374,6 +413,33 @@ static int qspi_cs(QspiDev_t* pDev, int csAssert)
return qspi_gen_fifo_write(reg_genfifo);
}
static uint32_t qspi_calc_exp(uint32_t xferSz, uint32_t* reg_genfifo)
{
uint32_t expval = 8;
*reg_genfifo &= ~(GQSPI_GEN_FIFO_IMM_MASK | GQSPI_GEN_FIFO_EXP_MASK);
if (xferSz > GQSPI_GEN_FIFO_IMM_MASK) {
/* Use exponent mode */
while (1) {
if (xferSz & (1 << expval)) {
*reg_genfifo |= GQSPI_GEN_FIFO_EXP_MASK;
*reg_genfifo |= GQSPI_GEN_FIFO_IMM(expval); /* IMM is exponent */
xferSz = (1 << expval);
break;
}
expval++;
}
}
else {
/* Use length mode */
*reg_genfifo |= GQSPI_GEN_FIFO_IMM(xferSz); /* IMM is length */
}
return xferSz;
}
#ifdef GQSPI_DMA
static uint8_t XALIGNED(QQSPI_DMA_ALIGN) dmatmp[GQSPI_DMA_TMPSZ];
#endif
static int qspi_transfer(QspiDev_t* pDev,
const uint8_t* cmdData, uint32_t cmdSz,
const uint8_t* txData, uint32_t txSz,
@ -382,7 +448,9 @@ static int qspi_transfer(QspiDev_t* pDev,
{
int ret = GQSPI_CODE_SUCCESS;
uint32_t reg_genfifo, xferSz;
#ifdef GQSPI_DMA
uint8_t* dmarxptr = NULL;
#endif
GQSPI_EN = 1; /* Enable device */
qspi_cs(pDev, 1); /* Select slave */
@ -395,14 +463,14 @@ static int qspi_transfer(QspiDev_t* pDev,
xferSz = cmdSz;
while (ret == GQSPI_CODE_SUCCESS && cmdData && xferSz > 0) {
/* Enable TX and send command inline */
reg_genfifo |= GQSPI_GEN_FIFO_TX;
reg_genfifo &= ~(GQSPI_GEN_FIFO_RX | GQSPI_GEN_FIFO_IMM_MASK);
reg_genfifo |= GQSPI_GEN_FIFO_TX;
reg_genfifo |= GQSPI_GEN_FIFO_IMM(*cmdData); /* IMM is data */
/* Submit general FIFO operation */
ret = qspi_gen_fifo_write(reg_genfifo);
if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
wolfBoot_printf("zynq.c:%d (error %d)\n", __LINE__, ret);
break;
}
@ -411,39 +479,28 @@ static int qspi_transfer(QspiDev_t* pDev,
cmdData++;
}
/* Set desired data mode and stripe */
/* Set desired data mode */
reg_genfifo |= (mode & GQSPI_GEN_FIFO_MODE_MASK);
reg_genfifo |= (pDev->stripe & GQSPI_GEN_FIFO_STRIPE);
/* TX Data */
while (ret == GQSPI_CODE_SUCCESS && txData && txSz > 0) {
xferSz = txSz;
/* Enable TX */
reg_genfifo &= ~(GQSPI_GEN_FIFO_RX | GQSPI_GEN_FIFO_IMM_MASK |
GQSPI_GEN_FIFO_EXP_MASK);
reg_genfifo |= (GQSPI_GEN_FIFO_TX | GQSPI_GEN_FIFO_DATA_XFER);
if (xferSz > GQSPI_GEN_FIFO_IMM_MASK) {
/* Use exponent mode */
xferSz = 256; /* 2 ^ 8 = 256 */
reg_genfifo |= GQSPI_GEN_FIFO_EXP_MASK;
reg_genfifo |= GQSPI_GEN_FIFO_IMM(8); /* IMM is exponent */
}
else {
reg_genfifo |= GQSPI_GEN_FIFO_IMM(xferSz); /* IMM is length */
}
reg_genfifo |= (pDev->stripe & GQSPI_GEN_FIFO_STRIPE);
xferSz = qspi_calc_exp(txSz, &reg_genfifo);
/* Submit general FIFO operation */
ret = qspi_gen_fifo_write(reg_genfifo);
if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
wolfBoot_printf("zynq.c:%d (error %d)\n", __LINE__, ret);
}
/* Fill FIFO */
ret = gspi_fifo_tx(txData, xferSz);
if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
wolfBoot_printf("zynq.c:%d (error %d)\n", __LINE__, ret);
break;
}
@ -454,60 +511,77 @@ static int qspi_transfer(QspiDev_t* pDev,
/* Dummy operations */
if (ret == GQSPI_CODE_SUCCESS && dummySz) {
/* Send dummy clocks (Disable TX & RX) */
/* Send dummy clocks (Disable TX & RX), do not set stripe */
reg_genfifo &= ~(GQSPI_GEN_FIFO_TX | GQSPI_GEN_FIFO_RX |
GQSPI_GEN_FIFO_IMM_MASK | GQSPI_GEN_FIFO_EXP_MASK);
GQSPI_GEN_FIFO_IMM_MASK | GQSPI_GEN_FIFO_EXP_MASK |
GQSPI_GEN_FIFO_STRIPE);
reg_genfifo |= GQSPI_GEN_FIFO_DATA_XFER;
/* IMM is number of dummy clock cycles */
reg_genfifo |= GQSPI_GEN_FIFO_IMM(dummySz);
ret = qspi_gen_fifo_write(reg_genfifo); /* Submit FIFO Dummy Op */
if (rxSz > 0) {
/* Convert dummy bits to bytes */
dummySz = (dummySz + 7) / 8;
/* Adjust rxSz for dummy bytes */
rxSz += dummySz;
/* round up by FIFO Word Size */
rxSz = (((rxSz + GQSPI_FIFO_WORD_SZ - 1) / GQSPI_FIFO_WORD_SZ) *
GQSPI_FIFO_WORD_SZ);
}
}
/* RX Data */
while (ret == GQSPI_CODE_SUCCESS && rxData && rxSz > 0) {
xferSz = rxSz;
/* Enable RX */
reg_genfifo &= ~(GQSPI_GEN_FIFO_TX | GQSPI_GEN_FIFO_IMM_MASK |
GQSPI_GEN_FIFO_EXP_MASK);
reg_genfifo |= (GQSPI_GEN_FIFO_RX | GQSPI_GEN_FIFO_DATA_XFER);
reg_genfifo |= (pDev->stripe & GQSPI_GEN_FIFO_STRIPE);
if (xferSz > GQSPI_GEN_FIFO_IMM_MASK) {
/* Use exponent mode */
xferSz = 256; /* 2 ^ 8 = 256 */
reg_genfifo |= GQSPI_GEN_FIFO_EXP_MASK;
reg_genfifo |= GQSPI_GEN_FIFO_IMM(8); /* IMM is exponent */
}
else {
reg_genfifo |= GQSPI_GEN_FIFO_IMM(xferSz); /* IMM is length */
xferSz = rxSz;
#ifdef GQSPI_DMA
/* if xferSz or rxData is not QQSPI_DMA_ALIGN aligned use tmp */
dmarxptr = rxData;
if ((rxSz & (QQSPI_DMA_ALIGN-1)) ||
(((size_t)rxData) & (QQSPI_DMA_ALIGN-1))) {
dmarxptr = (uint8_t*)dmatmp;
/* round up */
xferSz = ((xferSz + (QQSPI_DMA_ALIGN-1)) & ~(QQSPI_DMA_ALIGN-1));
if (xferSz > (uint32_t)sizeof(dmatmp)) {
xferSz = (uint32_t)sizeof(dmatmp);
}
}
GQSPIDMA_DST = (unsigned long)dmarxptr;
GQSPIDMA_SIZE = xferSz;
GQSPIDMA_IER = GQSPIDMA_ISR_ALL_MASK;
flush_dcache_range((unsigned long)dmarxptr,
(unsigned long)dmarxptr + xferSz);
#endif
xferSz = qspi_calc_exp(xferSz, &reg_genfifo);
/* Submit general FIFO operation */
ret = qspi_gen_fifo_write(reg_genfifo);
if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
wolfBoot_printf("zynq.c:%d (error %d)\n", __LINE__, ret);
break;
}
#ifndef GQSPI_DMA
/* Read FIFO */
ret = gspi_fifo_rx(rxData, xferSz-dummySz, dummySz);
ret = gspi_fifo_rx(rxData, xferSz);
if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
wolfBoot_printf("zynq.c:%d (error %d)\n", __LINE__, ret);
}
#else
/* Wait for DMA done */
if (qspi_dmaisr_wait(GQSPIDMA_ISR_DONE, 0)) {
return GQSPI_CODE_TIMEOUT;
}
GQSPIDMA_ISR = GQSPIDMA_ISR_DONE;
/* adjust xfer sz */
if (xferSz > rxSz)
xferSz = rxSz;
/* copy result if not aligned */
if (dmarxptr != rxData) {
memcpy(rxData, dmarxptr, xferSz);
}
#endif
/* offset size and buffer */
rxSz -= xferSz;
rxData += (xferSz - dummySz);
dummySz = 0; /* only first RX */
rxData += xferSz;
}
qspi_cs(pDev, 0); /* Deselect Slave */
@ -524,7 +598,7 @@ static int qspi_flash_read_id(QspiDev_t* dev, uint8_t* id, uint32_t idSz)
uint8_t status = 0;
memset(cmd, 0, sizeof(cmd));
cmd[0] = MULTI_IO_READ_ID_CMD;
cmd[0] = READ_ID_CMD;
ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, cmd, sizeof(cmd), 0,
GQSPI_GEN_FIFO_MODE_SPI);
@ -775,11 +849,11 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
/* Clear and disable interrupts */
reg_isr = GQSPI_ISR;
GQSPI_ISR |= GQSPI_ISR_WR_TO_CLR_MASK; /* Clear poll timeout counter interrupt */
reg_cfg = QSPIDMA_DST_I_STS;
QSPIDMA_DST_I_STS = reg_cfg; /* clear all active interrupts */
QSPIDMA_DST_STS |= QSPIDMA_DST_STS_WTC; /* mark outstanding DMA's done */
reg_cfg = GQSPIDMA_ISR;
GQSPIDMA_ISR = reg_cfg; /* clear all active interrupts */
GQSPIDMA_STS |= GQSPIDMA_STS_WTC; /* mark outstanding DMA's done */
GQSPI_IDR = GQSPI_IXR_ALL_MASK; /* disable interrupts */
QSPIDMA_DST_I_STS = QSPIDMA_DST_I_STS_ALL_MASK; /* disable interrupts */
GQSPIDMA_ISR = GQSPIDMA_ISR_ALL_MASK; /* disable interrupts */
/* Reset FIFOs */
if (GQSPI_ISR & GQSPI_IXR_RX_FIFO_EMPTY) {
GQSPI_FIFO_CTRL |= (GQSPI_FIFO_CTRL_RST_TX_FIFO | GQSPI_FIFO_CTRL_RST_RX_FIFO);
@ -791,10 +865,14 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
GQSPI_EN = 0; /* Disable device */
/* Initialize clock divisor, write protect hold and start mode */
#ifdef GQSPI_DMA
reg_cfg = GQSPI_CFG_MODE_EN_DMA; /* Use DMA Transfer Mode */
#else
reg_cfg = GQSPI_CFG_MODE_EN_IO; /* Use I/O Transfer Mode */
reg_cfg |= GQSPI_CFG_START_GEN_FIFO; /* Auto start GFIFO cmd execution */
#endif
reg_cfg |= GQSPI_CFG_BAUD_RATE_DIV(GQSPI_CLK_DIV); /* Clock Divider */
reg_cfg |= GQSPI_CFG_WP_HOLD; /* Use WP Hold */
reg_cfg |= GQSPI_CFG_START_GEN_FIFO; /* Start GFIFO command execution */
reg_cfg &= ~(GQSPI_CFG_CLK_POL | GQSPI_CFG_CLK_PH); /* Use POL=0,PH=0 */
GQSPI_CFG = reg_cfg;
@ -803,30 +881,31 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
* the clock and data tap delays bypassed. */
IOU_TAPDLY_BYPASS |= IOU_TAPDLY_BYPASS_LQSPI_RX;
GQSPI_LPBK_DLY_ADJ = 0;
QSPI_DATA_DLY_ADJ = 0;
GQSPI_DATA_DLY_ADJ = 0;
#elif GQSPI_CLK_DIV >= 1 /* 300/4=75MHz */
/* At 100 MHz, the Quad-SPI controller should be in clock loopback mode
* with the clock tap delay bypassed, but the data tap delay enabled. */
IOU_TAPDLY_BYPASS |= IOU_TAPDLY_BYPASS_LQSPI_RX;
GQSPI_LPBK_DLY_ADJ = GQSPI_LPBK_DLY_ADJ_USE_LPBK;
QSPI_DATA_DLY_ADJ = QSPI_DATA_DLY_ADJ_USE_DATA_DLY | QSPI_DATA_DLY_ADJ_DATA_DLY_ADJ(2);
GQSPI_DATA_DLY_ADJ = (GQSPI_DATA_DLY_ADJ_USE_DATA_DLY |
GQSPI_DATA_DLY_ADJ_DATA_DLY_ADJ(2));
#else
/* At 150 MHz, only the generic controller can be used.
* The generic controller should be in clock loopback mode and the clock
* tap delay enabled, but the data tap delay disabled. */
IOU_TAPDLY_BYPASS = 0;
GQSPI_LPBK_DLY_ADJ = GQSPI_LPBK_DLY_ADJ_USE_LPBK;
QSPI_DATA_DLY_ADJ = 0;
GQSPI_DATA_DLY_ADJ = 0;
#endif
/* Initialize hardware parameters for Threshold and Interrupts */
GQSPI_TX_THRESH = 1;
GQSPI_RX_THRESH = 1;
GQSPI_GF_THRESH = 16;
GQSPI_GF_THRESH = 31;
/* Reset DMA */
QSPIDMA_DST_CTRL = QSPIDMA_DST_CTRL_DEF;
QSPIDMA_DST_CTRL2 = QSPIDMA_DST_CTRL2_DEF;
GQSPIDMA_CTRL = GQSPIDMA_CTRL_DEF;
GQSPIDMA_CTRL2 = GQSPIDMA_CTRL2_DEF;
/* Interrupts unmask and enable */
GQSPI_IMR = GQSPI_IXR_ALL_MASK;

View File

@ -85,18 +85,25 @@
#define GQSPI_POLL_CFG (*((volatile uint32_t*)(QSPI_BASE + 0x154))) /* poll configuration register */
#define GQSPI_P_TIMEOUT (*((volatile uint32_t*)(QSPI_BASE + 0x158))) /* poll timeout register. */
#define GQSPI_XFER_STS (*((volatile uint32_t*)(QSPI_BASE + 0x15C))) /* transfer status register. */
#define QSPI_DATA_DLY_ADJ (*((volatile uint32_t*)(QSPI_BASE + 0x1F8))) /* adjusting the internal receive data delay for read data capturing */
#define GQSPI_DATA_DLY_ADJ (*((volatile uint32_t*)(QSPI_BASE + 0x1F8))) /* adjusting the internal receive data delay for read data capturing */
#define GQSPI_MOD_ID (*((volatile uint32_t*)(QSPI_BASE + 0x1FC)))
#define QSPIDMA_DST_STS (*((volatile uint32_t*)(QSPI_BASE + 0x808)))
#define QSPIDMA_DST_CTRL (*((volatile uint32_t*)(QSPI_BASE + 0x80C)))
#define QSPIDMA_DST_I_STS (*((volatile uint32_t*)(QSPI_BASE + 0x814)))
#define QSPIDMA_DST_CTRL2 (*((volatile uint32_t*)(QSPI_BASE + 0x824)))
/* DMA Registers */
#define GQSPIDMA_DST (*((volatile uint32_t*)(QSPI_BASE + 0x800))) /* Destination memory address for DMA stream -> memory data transfer */
#define GQSPIDMA_DST_MSB (*((volatile uint32_t*)(QSPI_BASE + 0x828))) /* Destination memory address (MSBs) for DMA stream -> memory data transfer */
#define GQSPIDMA_SIZE (*((volatile uint32_t*)(QSPI_BASE + 0x804))) /* DMA transfer payload for DMA stream -> memory data transfer */
#define GQSPIDMA_STS (*((volatile uint32_t*)(QSPI_BASE + 0x808))) /* General DST DMA status */
#define GQSPIDMA_CTRL (*((volatile uint32_t*)(QSPI_BASE + 0x80C))) /* General DST DMA control */
#define GQSPIDMA_ISR (*((volatile uint32_t*)(QSPI_BASE + 0x814))) /* DST DMA interrupt status register */
#define GQSPIDMA_IER (*((volatile uint32_t*)(QSPI_BASE + 0x818))) /* DST DMA interrupt enable */
#define GQSPIDMA_IDR (*((volatile uint32_t*)(QSPI_BASE + 0x81C))) /* DST DMA interrupt disable */
#define GQSPIDMA_IMR (*((volatile uint32_t*)(QSPI_BASE + 0x820))) /* DST DMA interrupt mask */
#define GQSPIDMA_CTRL2 (*((volatile uint32_t*)(QSPI_BASE + 0x824))) /* General DST DMA control register 2 */
#define GQSPI_LPBK_DLY_ADJ_USE_LPBK (1UL << 5)
#define GQSPI_LPBK_DLY_ADJ_DIV0(x) (((x) & 0x7) << 0)
#define GQSPI_LPBK_DLY_ADJ_DLY1(x) (((x) & 0x3) << 3)
#define QSPI_DATA_DLY_ADJ_USE_DATA_DLY (1UL << 31)
#define QSPI_DATA_DLY_ADJ_DATA_DLY_ADJ(x) (((x) & 0x7) << 28)
#define GQSPI_DATA_DLY_ADJ_USE_DATA_DLY (1UL << 31)
#define GQSPI_DATA_DLY_ADJ_DATA_DLY_ADJ(x) (((x) & 0x7) << 28)
/* GQSPI Registers */
/* GQSPI_CFG: Configuration registers */
@ -166,15 +173,16 @@
#define GQSPI_FIFO_CTRL_RST_TX_FIFO (1UL << 1)
#define GQSPI_FIFO_CTRL_RST_RX_FIFO (1UL << 2)
/* QSPIDMA_DST_CTRL */
#define QSPIDMA_DST_CTRL_DEF 0x403FFA00UL
#define QSPIDMA_DST_CTRL2_DEF 0x081BFFF8UL
/* GQSPIDMA_CTRL */
#define GQSPIDMA_CTRL_DEF 0x403FFA00UL
#define GQSPIDMA_CTRL2_DEF 0x081BFFF8UL
/* QSPIDMA_DST_STS */
#define QSPIDMA_DST_STS_WTC 0xE000U
/* GQSPIDMA_STS */
#define GQSPIDMA_STS_WTC 0xE000U
/* QSPIDMA_DST_I_STS */
#define QSPIDMA_DST_I_STS_ALL_MASK 0xFEU
/* GQSPIDMA_ISR */
#define GQSPIDMA_ISR_DONE 0x02
#define GQSPIDMA_ISR_ALL_MASK 0xFEU
/* QSPI Configuration (bare-metal only) */
#ifndef GQSPI_CLK_DIV
@ -182,6 +190,16 @@
#endif
#define GQSPI_CS_ASSERT_CLOCKS 5 /* CS Setup Time (tCSS) - num of clock cycles foes in IMM */
#define GQSPI_FIFO_WORD_SZ 4
#define QQSPI_DMA_ALIGN 64 /* L1 cache size */
#ifndef GQSPI_DMA_TMPSZ
/* Use larger of WOLFBOOT_SHA_BLOCK_SIZE or IMAGE_HEADER_SIZE */
#if defined(WOLFBOOT_SHA_BLOCK_SIZE) && \
WOLFBOOT_SHA_BLOCK_SIZE > IMAGE_HEADER_SIZE
#define GQSPI_DMA_TMPSZ WOLFBOOT_SHA_BLOCK_SIZE
#else
#define GQSPI_DMA_TMPSZ IMAGE_HEADER_SIZE
#endif
#endif
#define GQSPI_TIMEOUT_TRIES 100000
#define QSPI_FLASH_READY_TRIES 1000
@ -196,7 +214,7 @@
#define GQPI_USE_4BYTE_ADDR 1
#endif
#ifndef GQSPI_DUMMY_READ
#define GQSPI_DUMMY_READ (8*8) /* Number of dummy clock cycles for reads */
#define GQSPI_DUMMY_READ (8) /* Number of dummy clock cycles for reads */
#endif

View File

@ -74,6 +74,22 @@ int wolfBot_get_dts_size(void *dts_addr);
# endif
#endif
/* Helpers for memory alignment */
#ifndef XALIGNED
#if defined(__GNUC__) || defined(__llvm__) || \
defined(__IAR_SYSTEMS_ICC__)
#define XALIGNED(x) __attribute__ ( (aligned (x)))
#elif defined(__KEIL__)
#define XALIGNED(x) __align(x)
#elif defined(_MSC_VER)
/* disable align warning, we want alignment ! */
#pragma warning(disable: 4324)
#define XALIGNED(x) __declspec (align (x))
#else
#define XALIGNED(x) /* null expansion */
#endif
#endif
#ifndef WOLFBOOT_FLAGS_INVERT
#define SECT_FLAG_NEW 0x0F

View File

@ -69,7 +69,7 @@ void boot_entry_C(void)
#ifdef MMU
int __attribute((weak)) hal_dts_fixup(void* dts_addr)
int WEAKFUNCTION hal_dts_fixup(void* dts_addr)
{
(void)dts_addr;
return 0;

View File

@ -461,6 +461,34 @@ invalidatecaches_next_level:
invalidatecaches_end:
ret
/*
* void flush_dcache_range(start, end)
*
* clean & invalidate data cache in the range
*
* x0: start address
* x1: end address
*/
.global flush_dcache_range
flush_dcache_range:
mrs x3, ctr_el0
lsr x3, x3, #16
and x3, x3, #0xf
mov x2, #4
lsl x2, x2, x3 /* cache line size */
/* x2 <- minimal cache line size in cache system */
sub x3, x2, #1
bic x0, x0, x3
1: dc civac, x0 /* clean & invalidate data or unified cache */
add x0, x0, x2
cmp x0, x1
b.lo 1b
dsb sy
ret
/*
* Below is the static translation page table required by MMU for Cortex-A53.
* The translation table is flat mapped (input address = output address) with

View File

@ -101,12 +101,12 @@ void set_law(uint8_t idx, uint32_t addr_h, uint32_t addr_l, uint32_t trgt_id,
(void)get32(LAWAR(idx));
}
void __attribute((weak)) hal_early_init(void)
void WEAKFUNCTION hal_early_init(void)
{
}
#ifdef MMU
int __attribute((weak)) hal_dts_fixup(void* dts_addr)
int WEAKFUNCTION hal_dts_fixup(void* dts_addr)
{
(void)dts_addr;
return 0;

View File

@ -33,6 +33,7 @@
#include "wolfboot/wolfboot.h"
#include "keystore.h"
#include "target.h"
#include "image.h"
#ifdef SECURE_PKCS11
#include "wcs/user_settings.h"
@ -797,7 +798,7 @@ void _exit (int status)
while (1) {} /* Make sure we hang here */
}
__attribute__((weak)) int _read(int file, char *ptr, int len)
int WEAKFUNCTION _read(int file, char *ptr, int len)
{
(void)file;
int DataIdx;