Fixes for wolfBoot Xilinx QSPI support.

pull/243/head
David Garske 2022-09-28 08:33:26 -04:00 committed by Daniele Lacamera
parent c346fab41b
commit 62c7cd296a
1 changed files with 119 additions and 21 deletions

View File

@ -47,8 +47,11 @@
/* QNX QSPI driver */ /* QNX QSPI driver */
#include <sys/siginfo.h> #include <sys/siginfo.h>
#include "xzynq_gqspi.h" #include "xzynq_gqspi.h"
#else
/* QSPI bare-metal */
#endif #endif
/* QSPI bare-metal driver */ /* QSPI bare-metal driver */
#define CORTEXA53_0_CPU_CLK_FREQ_HZ 1099989014 #define CORTEXA53_0_CPU_CLK_FREQ_HZ 1099989014
#define CORTEXA53_0_TIMESTAMP_CLK_FREQ 99998999 #define CORTEXA53_0_TIMESTAMP_CLK_FREQ 99998999
@ -186,7 +189,7 @@
#define GQPI_USE_4BYTE_ADDR 1 #define GQPI_USE_4BYTE_ADDR 1
#endif #endif
#ifndef GQSPI_DUMMY_READ #ifndef GQSPI_DUMMY_READ
#define GQSPI_DUMMY_READ 8 /* Number of dummy clock cycles for reads */ #define GQSPI_DUMMY_READ (8*8) /* Number of dummy clock cycles for reads */
#endif #endif
@ -210,6 +213,7 @@
/* Flash Commands */ /* Flash Commands */
#define WRITE_ENABLE_CMD 0x06U #define WRITE_ENABLE_CMD 0x06U
#define READ_SR_CMD 0x05U
#define WRITE_DISABLE_CMD 0x04U #define WRITE_DISABLE_CMD 0x04U
#define READ_ID_CMD 0x9FU #define READ_ID_CMD 0x9FU
#define MULTI_IO_READ_ID_CMD 0xAFU #define MULTI_IO_READ_ID_CMD 0xAFU
@ -238,6 +242,7 @@
#define RESET_ENABLE_CMD 0x66U #define RESET_ENABLE_CMD 0x66U
#define RESET_MEMORY_CMD 0x99U #define RESET_MEMORY_CMD 0x99U
#define WRITE_EN_MASK 0x02 /* 0=Write Enabled, 1=Disabled Write */
#define FLASH_READY_MASK 0x80 /* 0=Busy, 1=Ready */ #define FLASH_READY_MASK 0x80 /* 0=Busy, 1=Ready */
@ -262,6 +267,10 @@ typedef struct QspiDev {
static QspiDev_t mDev; static QspiDev_t mDev;
/* forward declarations */
static int qspi_wait_ready(QspiDev_t* dev);
static int qspi_status(QspiDev_t* dev, uint8_t* status);
static int qspi_wait_we(QspiDev_t* dev);
#ifdef TEST_FLASH #ifdef TEST_FLASH
static int test_flash(QspiDev_t* dev); static int test_flash(QspiDev_t* dev);
#endif #endif
@ -531,7 +540,7 @@ static int qspi_gen_fifo_write(uint32_t reg_genfifo)
return GQSPI_CODE_TIMEOUT; return GQSPI_CODE_TIMEOUT;
} }
#if defined(DEBUG_ZYNQ) && DEBUG_ZYNQ >= 2 #if defined(DEBUG_ZYNQ) && DEBUG_ZYNQ >= 3
wolfBoot_printf("FifoEntry=%08x\n", reg_genfifo); wolfBoot_printf("FifoEntry=%08x\n", reg_genfifo);
#endif #endif
GQSPI_GEN_FIFO = reg_genfifo; GQSPI_GEN_FIFO = reg_genfifo;
@ -646,8 +655,10 @@ static int qspi_transfer(QspiDev_t* pDev,
/* Submit general FIFO operation */ /* Submit general FIFO operation */
ret = qspi_gen_fifo_write(reg_genfifo); ret = qspi_gen_fifo_write(reg_genfifo);
if (ret != GQSPI_CODE_SUCCESS) if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
break; break;
}
/* offset size and buffer */ /* offset size and buffer */
xferSz--; xferSz--;
@ -679,11 +690,16 @@ static int qspi_transfer(QspiDev_t* pDev,
/* Submit general FIFO operation */ /* Submit general FIFO operation */
ret = qspi_gen_fifo_write(reg_genfifo); ret = qspi_gen_fifo_write(reg_genfifo);
if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
}
/* Fill FIFO */ /* Fill FIFO */
ret = gspi_fifo_tx(txData, xferSz); ret = gspi_fifo_tx(txData, xferSz);
if (ret != GQSPI_CODE_SUCCESS) if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
break; break;
}
/* offset size and buffer */ /* offset size and buffer */
txSz -= xferSz; txSz -= xferSz;
@ -731,11 +747,16 @@ static int qspi_transfer(QspiDev_t* pDev,
/* Submit general FIFO operation */ /* Submit general FIFO operation */
ret = qspi_gen_fifo_write(reg_genfifo); ret = qspi_gen_fifo_write(reg_genfifo);
if (ret != GQSPI_CODE_SUCCESS) if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
break; break;
}
/* Read FIFO */ /* Read FIFO */
ret = gspi_fifo_rx(rxData, xferSz, dummySz); ret = gspi_fifo_rx(rxData, xferSz-dummySz, dummySz);
if (ret != GQSPI_CODE_SUCCESS) {
wolfBoot_printf("on line %d: error %d\n", __LINE__, ret);
}
/* offset size and buffer */ /* offset size and buffer */
rxSz -= xferSz; rxSz -= xferSz;
@ -755,6 +776,9 @@ static int qspi_flash_read_id(QspiDev_t* dev, uint8_t* id, uint32_t idSz)
{ {
int ret; int ret;
uint8_t cmd[20]; /* size multiple of uint32_t */ uint8_t cmd[20]; /* size multiple of uint32_t */
uint8_t status;
memset(cmd, 0, sizeof(cmd));
cmd[0] = MULTI_IO_READ_ID_CMD; cmd[0] = MULTI_IO_READ_ID_CMD;
ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, cmd, sizeof(cmd), 0, ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, cmd, sizeof(cmd), 0,
GQSPI_GEN_FIFO_MODE_SPI); GQSPI_GEN_FIFO_MODE_SPI);
@ -768,6 +792,13 @@ static int qspi_flash_read_id(QspiDev_t* dev, uint8_t* id, uint32_t idSz)
idSz = sizeof(cmd); idSz = sizeof(cmd);
memcpy(id, cmd, idSz); memcpy(id, cmd, idSz);
} }
qspi_status(dev, &status);
if (status & WRITE_EN_MASK) {
wolfBoot_printf("Write disabled: status %02x\n", status);
ret = -1;
}
return ret; return ret;
} }
@ -775,17 +806,33 @@ static int qspi_write_enable(QspiDev_t* dev)
{ {
int ret; int ret;
uint8_t cmd[4]; /* size multiple of uint32_t */ uint8_t cmd[4]; /* size multiple of uint32_t */
uint8_t status;
memset(cmd, 0, sizeof(cmd)); memset(cmd, 0, sizeof(cmd));
cmd[0] = WRITE_DISABLE_CMD; cmd[0] = WRITE_ENABLE_CMD;
ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, NULL, 0, 0, ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, NULL, 0, 0,
GQSPI_GEN_FIFO_MODE_SPI); GQSPI_GEN_FIFO_MODE_SPI);
wolfBoot_printf("Write Enable: Ret %d\n", ret); wolfBoot_printf("Write Enable: Ret %d\n", ret);
ret = qspi_wait_ready(dev);
wolfBoot_printf("wait ready: Ret %d\n", ret);
ret = qspi_wait_we(dev);
wolfBoot_printf("wait we: Ret %d\n", ret);
qspi_status(dev, &status);
if ((status & WRITE_EN_MASK) == 0) {
wolfBoot_printf("status %02x\n", status);
ret = -1;
}
return ret; return ret;
} }
static int qspi_write_disable(QspiDev_t* dev) static int qspi_write_disable(QspiDev_t* dev)
{ {
int ret; int ret;
uint8_t cmd[4]; /* size multiple of uint32_t */ uint8_t cmd[4]; /* size multiple of uint32_t */
memset(cmd, 0, sizeof(cmd)); memset(cmd, 0, sizeof(cmd));
cmd[0] = WRITE_DISABLE_CMD; cmd[0] = WRITE_DISABLE_CMD;
ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, NULL, 0, 0, ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, NULL, 0, 0,
@ -798,6 +845,7 @@ static int qspi_flash_status(QspiDev_t* dev, uint8_t* status)
{ {
int ret; int ret;
uint8_t cmd[4]; /* size multiple of uint32_t */ uint8_t cmd[4]; /* size multiple of uint32_t */
memset(cmd, 0, sizeof(cmd)); memset(cmd, 0, sizeof(cmd));
cmd[0] = READ_FSR_CMD; cmd[0] = READ_FSR_CMD;
ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, cmd, 2, 0, ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, cmd, 2, 0,
@ -812,6 +860,25 @@ static int qspi_flash_status(QspiDev_t* dev, uint8_t* status)
return ret; return ret;
} }
static int qspi_status(QspiDev_t* dev, uint8_t* status)
{
int ret;
uint8_t cmd[4]; /* size multiple of uint32_t */
memset(cmd, 0, sizeof(cmd));
cmd[0] = READ_SR_CMD;
ret = qspi_transfer(&mDev, cmd, 1, NULL, 0, cmd, 2, 0,
GQSPI_GEN_FIFO_MODE_SPI);
wolfBoot_printf("Status: Ret %d Cmd %02x %02x\n", ret, cmd[0], cmd[1]);
if (ret == GQSPI_CODE_SUCCESS && status) {
if (dev->stripe) {
cmd[0] &= cmd[1];
}
*status = cmd[0];
}
return ret;
}
static int qspi_wait_ready(QspiDev_t* dev) static int qspi_wait_ready(QspiDev_t* dev)
{ {
int ret; int ret;
@ -831,13 +898,37 @@ static int qspi_wait_ready(QspiDev_t* dev)
return GQSPI_CODE_TIMEOUT; return GQSPI_CODE_TIMEOUT;
} }
static int qspi_wait_we(QspiDev_t* dev)
{
int ret;
uint32_t timeout;
uint8_t status = 0;
timeout = 0;
while (++timeout < QSPI_FLASH_READY_TRIES) {
ret = qspi_status(dev, &status);
if (ret == GQSPI_CODE_SUCCESS &&
(status & WRITE_EN_MASK)
) {
return ret;
}
}
wolfBoot_printf("Flash WE Timeout!\n");
return GQSPI_CODE_TIMEOUT;
}
#if GQPI_USE_4BYTE_ADDR == 1 #if GQPI_USE_4BYTE_ADDR == 1
static int qspi_enter_4byte_addr(QspiDev_t* dev) static int qspi_enter_4byte_addr(QspiDev_t* dev)
{ {
int ret; int ret;
uint8_t cmd[4]; /* size multiple of uint32_t */ uint8_t cmd[4]; /* size multiple of uint32_t */
memset(cmd, 0, sizeof(cmd)); memset(cmd, 0, sizeof(cmd));
cmd[0] = ENTER_4B_ADDR_MODE_CMD; cmd[0] = ENTER_4B_ADDR_MODE_CMD;
(void)qspi_wait_ready(&mDev); /* Wait for not busy */
ret = qspi_write_enable(&mDev); ret = qspi_write_enable(&mDev);
if (ret == GQSPI_CODE_SUCCESS) { if (ret == GQSPI_CODE_SUCCESS) {
ret = qspi_transfer(dev, cmd, 1, NULL, 0, NULL, 0, 0, ret = qspi_transfer(dev, cmd, 1, NULL, 0, NULL, 0, 0,
@ -854,6 +945,7 @@ static int qspi_exit_4byte_addr(QspiDev_t* dev)
{ {
int ret; int ret;
uint8_t cmd[4]; /* size multiple of uint32_t */ uint8_t cmd[4]; /* size multiple of uint32_t */
memset(cmd, 0, sizeof(cmd)); memset(cmd, 0, sizeof(cmd));
cmd[0] = EXIT_4B_ADDR_MODE_CMD; cmd[0] = EXIT_4B_ADDR_MODE_CMD;
ret = qspi_write_enable(&mDev); ret = qspi_write_enable(&mDev);
@ -1241,6 +1333,9 @@ static int test_flash(QspiDev_t* dev)
{ {
int ret; int ret;
uint32_t i; uint32_t i;
#ifndef USE_XQSPIPSU
uint8_t pageData[FLASH_PAGE_SIZE];
#endif
#ifndef TEST_FLASH_READONLY #ifndef TEST_FLASH_READONLY
/* Erase sector */ /* Erase sector */
@ -1260,13 +1355,16 @@ static int test_flash(QspiDev_t* dev)
ret = ext_flash_read(TEST_ADDRESS, pageData, sizeof(pageData)); ret = ext_flash_read(TEST_ADDRESS, pageData, sizeof(pageData));
wolfBoot_printf("Read Page: Ret %d\n", ret); wolfBoot_printf("Read Page: Ret %d\n", ret);
wolfBoot_printf("Checking...\n");
/* Check data */ /* Check data */
for (i=0; i<sizeof(pageData); i++) { for (i=0; i<sizeof(pageData); i++) {
wolfBoot_printf("check[%3d] %02x\n", i, pageData[i]);
if (pageData[i] != (i & 0xff)) { if (pageData[i] != (i & 0xff)) {
wolfBoot_printf("Check Data @ %d failed\n", i); wolfBoot_printf("Check Data @ %d failed\n", i);
return GQSPI_CODE_FAILED; return GQSPI_CODE_FAILED;
} }
} }
wolfBoot_printf("Flash Test Passed\n"); wolfBoot_printf("Flash Test Passed\n");
return ret; return ret;
} }