STM32 QSPI cleanups.

pull/264/head
David Garske 2022-12-21 14:06:31 -08:00
parent 5331f5ee23
commit c3cf21a81f
3 changed files with 71 additions and 65 deletions

View File

@ -218,6 +218,9 @@ int qspi_transfer(
mode = 0; /* no data */
}
/* Enable the QSPI peripheral */
QUADSPI_CR |= QUADSPI_CR_EN;
if (dsz > 0) {
QUADSPI_DLR = dsz-1;
}
@ -227,9 +230,6 @@ int qspi_transfer(
adsz = addrSz-1;
}
/* Enable the QSPI peripheral */
QUADSPI_CR |= QUADSPI_CR_EN;
/* Configure QSPI: CCR register with all communications parameters */
/* mode 1=1SPI, 2=2SPI, 3=4SPI */
QUADSPI_CCR = (
@ -303,9 +303,9 @@ void RAMFUNCTION spi_init(int polarity, int phase)
/* Setup clocks */
#ifdef QSPI_FLASH
/* Enable QUADSPI clock on HCLK3 (240MHz max) */
/* Select QUADSPI clock source */
RCC_D1CCIPR &= ~RCC_D1CCIPR_QSPISEL_MASK;
RCC_D1CCIPR |= RCC_D1CCIPR_QSPISEL(0);
RCC_D1CCIPR |= RCC_D1CCIPR_QSPISEL(QSPI_CLOCK_SEL);
AHB3_CLOCK_EN |= RCC_AHB3ENR_QSPIEN;
#endif
#ifdef SPI_FLASH
@ -333,16 +333,16 @@ void RAMFUNCTION spi_init(int polarity, int phase)
#ifdef QSPI_FLASH
/* Configure QSPI FIFO Threshold (1 byte) */
QUADSPI_CR &= ~QUADSPI_CR_FTHRES_MASK;
QUADSPI_CR |= QUADSPI_CR_FTHRES(1);
QUADSPI_CR |= QUADSPI_CR_FTHRES(4);
/* Wait till BUSY flag cleared */
while (QUADSPI_SR & QUADSPI_SR_BUSY) {};
/* Configure QSPI Clock Prescaler (240/X), Flash ID 0, Dual Flash=0,
/* Configure QSPI Clock Prescaler (64/X), Flash ID 0, Dual Flash=0,
* Sample Shift=None */
QUADSPI_CR &= ~(QUADSPI_CR_PRESCALER_MASK | QUADSPI_CR_FSEL |
QUADSPI_CR_DFM | QUADSPI_CR_SSHIFT);
QUADSPI_CR |= (QUADSPI_CR_PRESCALER(HCLK3_MHZ/QSPI_CLOCK_MHZ));
QUADSPI_CR |= (QUADSPI_CR_PRESCALER((QSPI_CLOCK_BASE/QSPI_CLOCK_MHZ)));
/* Configure QSPI Flash Size (16MB), CS High Time (1 clock) and
* Clock Mode (0) */

View File

@ -165,13 +165,25 @@
#define RCC_D1CCIPR (*(volatile uint32_t *)(RCC_BASE + 0x4C)) /* RM0433 - 8.7.19 (RCC_D1CCIPR) */
#define RCC_D1CCIPR_QSPISEL_MASK (0x3 << 4)
#define RCC_D1CCIPR_QSPISEL(sel) (((sel) & 0x3) << 4) /* 0=hclk3, 1=pll1_q_ck, 2=pll2_r_ck, 3=per_ck */
#define RCC_D1CCIPR_QSPISEL_HCLK3 0
#define RCC_D1CCIPR_QSPISEL_PLL1 1
#define RCC_D1CCIPR_QSPISEL_PLL2 2
#define RCC_D1CCIPR_QSPISEL_PERCK 3
#define AHB3_CLOCK_RST (*(volatile uint32_t *)(RCC_BASE + 0x7C)) /* RM0433 - 8.7.28 - RCC_AHB3RSTR */
#define AHB3_CLOCK_EN (*(volatile uint32_t *)(RCC_BASE + 0xD4)) /* RM0433 - 8.7.40 - RCC_AHB3ENR */
#define RCC_AHB3ENR_QSPIEN (1 << 14) /* QUADSPI and QUADSPI Delay clock enabled */
#define HCLK3_MHZ 240000000
#define HCLK3_MHZ 240000000
#define PERCK_MHZ 64000000
#ifndef QSPI_CLOCK_BASE
#define QSPI_CLOCK_BASE PERCK_MHZ
#endif
#ifndef QSPI_CLOCK_SEL
/* Enable QUADSPI clock on PER_CK (64MHz) */
#define QSPI_CLOCK_SEL RCC_D1CCIPR_QSPISEL_PERCK
#endif
#ifndef QSPI_CLOCK_MHZ
#define QSPI_CLOCK_MHZ 8000000
#define QSPI_CLOCK_MHZ 16000000
#endif
/* QSPI CLK PB2 */
@ -370,13 +382,14 @@
#define QUADSPI_CR_PRESCALER_MASK (0xFF << 24)
#define QUADSPI_CR_PRESCALER(pre) ((((pre)-1) & 0xFF) << 24) /* Clock prescaler: quadspi_ker_ck/pre+1 */
#define QUADSPI_CR_FTIE (1 << 13) /* FIFO threshold interrupt enable */
#define QUADSPI_CR_FTHRES_MASK (0xF << 8)
#define QUADSPI_CR_FTHRES(thr) ((((thr)-1) & 0xF) << 8) /* FIFO threshold level */
#define QUADSPI_CR_FSEL (0x1 << 7) /* 0=Flash 1 or 1=Flash 2 */
#define QUADSPI_CR_DFM (0x1 << 6) /* Dual-flash mode */
#define QUADSPI_CR_SSHIFT (0x1 << 4) /* Sample shift 1=1/2 cycle shift */
#define QUADSPI_CR_ABORT (0x1 << 1) /* Abort request */
#define QUADSPI_CR_EN (0x1 << 0) /* Enable the QUADSPI */
#define QUADSPI_CR_FTHRES(thr) ((((thr)-1) & 0x1F) << 8) /* FIFO threshold level */
#define QUADSPI_CR_FSEL (1 << 7) /* 0=Flash 1 or 1=Flash 2 */
#define QUADSPI_CR_DFM (1 << 6) /* Dual-flash mode */
#define QUADSPI_CR_SSHIFT (1 << 4) /* Sample shift 1=1/2 cycle shift */
#define QUADSPI_CR_ABORT (1 << 1) /* Abort request */
#define QUADSPI_CR_EN (1 << 0) /* Enable the QUADSPI */
#define QUADSPI_CCR_DDRM (1 << 31) /* Double data rate mode */
#define QUADSPI_CCR_DHHC (1 << 30) /* Delay the data output by 1/4 of the QUADSPI output clock cycle in DDR mode */
@ -410,6 +423,6 @@
#define QUADSPI_SR_TCF (1 << 1) /* Transfer complete flag - set in indirect mode when the programmed number of data has been transferred */
#define QUADSPI_SR_FTF (1 << 2) /* FIFO threshold flag */
#define QUADSPI_SR_BUSY (1 << 5) /* Busy - operation is on going when set */
#define QUADSPI_SR_BUSY (1 << 5) /* Busy - operation is ongoing when set */
#endif /* !SPI_DRV_STM32_H_INCLUDED */

View File

@ -52,7 +52,7 @@
#endif
#define FLASH_NUM_SECTORS (FLASH_DEVICE_SIZE/FLASH_SECTOR_SIZE)
/* QSPI Configuration */
/* QSPI Configuration - Use single/dual/quad mode for data transfers */
#ifndef QSPI_ADDR_MODE
#define QSPI_ADDR_MODE QSPI_ADDR_MODE_SPI
#endif
@ -60,7 +60,7 @@
#define QSPI_ADDR_SZ 3
#endif
#ifndef QSPI_DUMMY_READ
#define QSPI_DUMMY_READ (8) /* Number of dummy clock cycles for reads */
#define QSPI_DUMMY_READ 8 /* Number of dummy clock cycles for reads */
#endif
#ifndef QSPI_FLASH_READY_TRIES
#define QSPI_FLASH_READY_TRIES 1000
@ -135,7 +135,6 @@
/* forward declarations */
static int qspi_wait_ready(void);
static int qspi_status(uint8_t* status);
static int qspi_wait_we(void);
#ifdef TEST_FLASH
static int test_flash(void);
#endif
@ -168,18 +167,35 @@ static int qspi_flash_read_id(uint8_t* id, uint32_t idSz)
static int qspi_write_enable(void)
{
int ret;
uint32_t timeout;
uint8_t status = 0;
/* send write enable */
ret = qspi_transfer(WRITE_ENABLE_CMD, 0, 0, NULL, 0, NULL, 0, 0,
QSPI_ADDR_MODE_SPI);
#if defined(DEBUG_QSPI) && DEBUG_QSPI > 1
wolfBoot_printf("Write Enable: Ret %d\n", ret);
#endif
qspi_wait_ready();
/* wait until write enabled and not busy */
timeout = 0;
while (++timeout < QSPI_FLASH_READY_TRIES) {
ret = qspi_status(&status);
if (ret == 0 && (status & FLASH_SR_WRITE_EN)
&& (status & FLASH_SR_BUSY) == 0) {
break;
}
}
if (timeout >= QSPI_FLASH_READY_TRIES) {
#ifdef DEBUG_QSPI
wolfBoot_printf("Flash WE Timeout!\n");
#endif
return -1; /* timeout */
}
ret = qspi_wait_we();
#if defined(DEBUG_QSPI) && DEBUG_QSPI > 1
wolfBoot_printf("Write Enabled: %s\n", ret == 0 ? "yes" : "no");
wolfBoot_printf("Write Enabled: %s\n",
(status & FLASH_SR_WRITE_EN) ? "yes" : "no");
#endif
return ret;
@ -239,52 +255,33 @@ static int qspi_wait_ready(void)
return -1;
}
static int qspi_wait_we(void)
{
int ret;
uint32_t timeout;
uint8_t status = 0;
timeout = 0;
while (++timeout < QSPI_FLASH_READY_TRIES) {
ret = qspi_status(&status);
if (ret == 0 && (status & FLASH_SR_WRITE_EN)) {
return ret;
}
}
#ifdef DEBUG_QSPI
wolfBoot_printf("Flash WE Timeout!\n");
#endif
return -1;
}
#if QSPI_ADDR_MODE == QSPI_ADDR_MODE_QSPI
static int qspi_quad_enable(void)
{
int ret;
uint8_t data[4]; /* size multiple of uint32_t */
ret = qspi_write_enable();
if (ret == 0) {
memset(data, 0, sizeof(data));
ret = qspi_transfer(READ_SR2_CMD, 0, 0, NULL, 0, data, 1, 0,
QSPI_ADDR_MODE_SPI);
memset(data, 0, sizeof(data));
ret = qspi_transfer(READ_SR2_CMD, 0, 0, NULL, 0, data, 1, 0,
QSPI_ADDR_MODE_SPI);
#ifdef DEBUG_QSPI
wolfBoot_printf("Status Reg 2: Ret %d, 0x%x\n", ret, data[0]);
wolfBoot_printf("Status Reg 2: Ret %d, 0x%x\n", ret, data[0]);
#endif
if (ret == 0 && (data[0] & FLASH_SR2_QE) == 0) {
ret = qspi_write_enable();
if (ret == 0) {
if ((data[0] & FLASH_SR2_QE) == 0) {
data[0] |= FLASH_SR2_QE;
ret = qspi_transfer(WRITE_SR2_CMD, 0, 0, data, 1, NULL, 0, 0,
QSPI_ADDR_MODE_SPI);
memset(data, 0, sizeof(data));
data[0] |= FLASH_SR2_QE;
ret = qspi_transfer(WRITE_SR2_CMD, 0, 0, data, 1, NULL, 0, 0,
QSPI_ADDR_MODE_SPI);
#ifdef DEBUG_QSPI
wolfBoot_printf("Setting Quad Enable: Ret %d, SR2 0x%x\n",
ret, data[0]);
wolfBoot_printf("Setting Quad Enable: Ret %d, SR2 0x%x\n",
ret, data[0]);
#endif
}
qspi_wait_ready();
qspi_write_disable();
}
qspi_write_disable();
}
return ret;
}
@ -296,8 +293,7 @@ static int qspi_enter_4byte_addr(void)
int ret = qspi_write_enable();
if (ret == 0) {
ret = qspi_transfer(ENTER_4B_ADDR_MODE_CMD, 0, 0,
NULL, 0, NULL, 0,
0, QSPI_ADDR_MODE_SPI);
NULL, 0, NULL, 0, 0, QSPI_ADDR_MODE_SPI);
#ifdef DEBUG_QSPI
wolfBoot_printf("Enter 4-byte address mode: Ret %d\n", ret);
#endif
@ -313,8 +309,7 @@ static int qspi_exit_4byte_addr(void)
int ret = qspi_write_enable();
if (ret == 0) {
ret = qspi_transfer(EXIT_4B_ADDR_MODE_CMD, 0, 0,
NULL, 0, NULL, 0,
0, QSPI_ADDR_MODE_SPI);
NULL, 0, NULL, 0, 0, QSPI_ADDR_MODE_SPI);
#ifdef DEBUG_QSPI
wolfBoot_printf("Enter 4-byte address mode: Ret %d\n", ret);
#endif
@ -357,8 +352,7 @@ int spi_flash_sector_erase(uint32_t address)
if (ret == 0) {
/* ------ Erase Flash ------ */
ret = qspi_transfer(SEC_ERASE_CMD, address, QSPI_ADDR_SZ,
NULL, 0, NULL, 0,
0, QSPI_ADDR_MODE_SPI);
NULL, 0, NULL, 0, 0, QSPI_ADDR_MODE_SPI);
#ifdef DEBUG_QSPI
wolfBoot_printf("Flash Erase: Ret %d, Address 0x%x\n", ret, address);
#endif
@ -384,8 +378,7 @@ int spi_flash_read(uint32_t address, void *data, int len)
/* ------ Read Flash ------ */
ret = qspi_transfer(FLASH_READ_CMD, address, QSPI_ADDR_SZ,
NULL, 0, data, len,
QSPI_DUMMY_READ, QSPI_ADDR_MODE);
NULL, 0, data, len, QSPI_DUMMY_READ, QSPI_ADDR_MODE);
#ifdef DEBUG_QSPI
wolfBoot_printf("Flash Read: Ret %d, Address 0x%x, Len %d, Cmd 0x%x\n",
ret, address, len, FLASH_READ_CMD);