mimxrt/hal: Set the flexspi flash CLK frequency on boot.

The flash clock frequency may have been set to a different value by a
bootloader.  Set the frequency according to the configured value.  Use a
table of pre-calculated dividers to get the closest value for the flash
frequency, achieving for MIMXRT10xx:

  30 -> 30.85 MHz
  50 -> 49.65 MHz
  60 -> 60 MHz
  75 -> 75.13 MHz
  80 -> 80 MHz
  100 -> 99.31 Mhz
  133 -> 132.92 MHz
  166  -> 166.15 MHz

for MIMXRT1176:

  30 -> 31 MHz
  50 -> 52.8 MJz
  60 -> 58.7 MHz
  75 -> 75.4 MHz
  80 -> 75.4 MHz
  100 -> 105.6 MHz
  133 -> 132 MHz
  166 -> 176 MHz

Signed-off-by: robert-hh <robert@hammelrath.com>
This commit is contained in:
robert-hh
2025-02-04 18:17:47 +01:00
committed by Damien George
parent d40849d07d
commit 0a433a02e1
5 changed files with 95 additions and 8 deletions

View File

@@ -29,7 +29,8 @@
void flash_init(void) {
// Upload the custom flash configuration
// And fix the entry for PAGEPROGRAM_QUAD
flexspi_nor_update_lut();
// Update the flash CLK
flexspi_nor_update_lut_clk(MICROPY_HW_FLASH_CLK);
// Configure FLEXSPI IP FIFO access.
BOARD_FLEX_SPI->MCR0 &= ~(FLEXSPI_MCR0_ARDFEN_MASK);

View File

@@ -9,7 +9,7 @@
#include "fsl_clock.h"
#include "flexspi_hyper_flash.h"
void flexspi_nor_update_lut(void) {
void flexspi_nor_update_lut_clk(uint32_t freq_index) {
}
// Copy of a few (pseudo-)functions from fsl_clock.h, which were nor reliably

View File

@@ -47,7 +47,7 @@ extern flexspi_nor_config_t qspiflash_config;
status_t flexspi_nor_hyperflash_cfi(FLEXSPI_Type *base);
void flexspi_hyper_flash_init(void);
void flexspi_nor_update_lut(void);
void flexspi_nor_update_lut_clk(uint32_t freq_index);
status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address);
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, uint32_t size);

View File

@@ -38,6 +38,9 @@
#include "flexspi_nor_flash.h"
#include "flexspi_flash_config.h"
bool flash_busy_status_pol = 0;
bool flash_busy_status_offset = 0;
uint32_t LUT_pageprogram_quad[4] = {
// 10 Page Program - quad mode
FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32, RADDR_SDR, FLEXSPI_1PAD, 24),
@@ -54,16 +57,100 @@ uint32_t LUT_write_status[4] = {
FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler
};
void flexspi_nor_update_lut(void) {
#if defined(MIMXRT117x_SERIES)
static uint8_t div_table_mhz[] = {
17, // Entry 0 is out of range
17, // 30 -> 31 MHz
10, // 50 -> 52.8 MHz
9, // 60 -> 58.7 MHz
7, // 75 -> 75.4 MHz
7, // 80 -> 75.4 MHz
5, // 100 -> 105.6 Mhz
4, // 133 -> 132 MHz
3 // 166 -> 176 MHz
};
#else
typedef struct _ps_div_t {
uint8_t pfd480_div;
uint8_t podf_div;
} ps_div_t;
static ps_div_t div_table_mhz[] = {
{ 35, 8 }, // Entry 0 is out of range
{ 35, 8 }, // 30 -> 30.85 MHz
{ 29, 6 }, // 50 -> 49.65 MHz
{ 18, 8 }, // 60 -> 60 MHz
{ 23, 5 }, // 75 -> 75.13 MHz
{ 18, 6 }, // 80 -> 80 MHz
{ 17, 5 }, // 100 -> 191 Mhz
{ 13, 5 }, // 133 -> 132.92 MHz
{ 13, 4 } // 166 -> 166.15 MHz
};
#endif
__attribute__((section(".ram_functions"))) void flexspi_nor_update_lut_clk(uint32_t freq_index) {
// Create a local copy of the LookupTable. Modify the entry for WRITESTATUSREG
// Add an entry for PAGEPROGRAM_QUAD.
uint32_t lookuptable_copy[64];
memcpy(lookuptable_copy, (const uint32_t *)&qspiflash_config.memConfig.lookupTable, 64 * sizeof(uint32_t));
// write WRITESTATUSREG code to entry 10
// write local WRITESTATUSREG code to index 4
memcpy(&lookuptable_copy[NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG * 4],
LUT_write_status, 4 * sizeof(uint32_t));
// write PAGEPROGRAM_QUAD code to entry 10
// write local PAGEPROGRAM_QUAD code to index 10
memcpy(&lookuptable_copy[NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD * 4],
LUT_pageprogram_quad, 4 * sizeof(uint32_t));
// Update the LookupTable.
FLEXSPI_UpdateLUT(BOARD_FLEX_SPI, 0, lookuptable_copy, 64);
__DSB();
__ISB();
__disable_irq();
SCB_DisableDCache();
#if defined(MIMXRT117x_SERIES)
volatile uint8_t pll2_div = div_table_mhz[freq_index] - 1;
while (!FLEXSPI_GetBusIdleStatus(BOARD_FLEX_SPI)) {
}
FLEXSPI_Enable(BOARD_FLEX_SPI, false);
// Disable FlexSPI clock
// Flexspi is clocked by PLL2. Only the divider can be changed.
CCM->LPCG[kCLOCK_Flexspi1].DIRECT = ((uint32_t)kCLOCK_Off & CCM_LPCG_DIRECT_ON_MASK);
// Change the PLL divider
CCM->CLOCK_ROOT[kCLOCK_Root_Flexspi1].CONTROL = (CCM->CLOCK_ROOT[kCLOCK_Root_Flexspi1].CONTROL & ~CCM_CLOCK_ROOT_CONTROL_DIV_MASK) |
CCM_CLOCK_ROOT_CONTROL_DIV(pll2_div);
// Re-enable FlexSPI clock
CCM->LPCG[kCLOCK_Flexspi1].DIRECT = ((uint32_t)kCLOCK_On & CCM_LPCG_DIRECT_ON_MASK);
#else
volatile uint8_t pfd480_div = div_table_mhz[freq_index].pfd480_div;
volatile uint8_t podf_div = div_table_mhz[freq_index].podf_div - 1;
while (!FLEXSPI_GetBusIdleStatus(BOARD_FLEX_SPI)) {
}
FLEXSPI_Enable(BOARD_FLEX_SPI, false);
// Disable FlexSPI clock
CCM->CCGR6 &= ~CCM_CCGR6_CG5_MASK;
// Changing the clock is OK now.
// Change the PFD
CCM_ANALOG->PFD_480 = (CCM_ANALOG->PFD_480 & ~CCM_ANALOG_PFD_480_TOG_PFD0_FRAC_MASK) | CCM_ANALOG_PFD_480_TOG_PFD0_FRAC(pfd480_div);
// Change the flexspi divider
CCM->CSCMR1 = (CCM->CSCMR1 & ~CCM_CSCMR1_FLEXSPI_PODF_MASK) | CCM_CSCMR1_FLEXSPI_PODF(podf_div);
// Re-enable FlexSPI
CCM->CCGR6 |= CCM_CCGR6_CG5_MASK;
#endif
FLEXSPI_Enable(BOARD_FLEX_SPI, true);
FLEXSPI_SoftwareReset(BOARD_FLEX_SPI);
while (!FLEXSPI_GetBusIdleStatus(BOARD_FLEX_SPI)) {
}
SCB_EnableDCache();
__enable_irq();
}
void flexspi_nor_reset(FLEXSPI_Type *base) __attribute__((section(".ram_functions")));

View File

@@ -45,8 +45,7 @@
extern flexspi_nor_config_t qspiflash_config;
status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId);
status_t flexspi_nor_init(void);
void flexspi_nor_update_lut(void);
void flexspi_nor_update_lut_clk(uint32_t freq_index);
status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base);
status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address);