1 /* 2 * Copyright 2022 NXP 3 * SPDX-License-Identifier: Apache-2.0 4 */ 5 6 /* 7 * To be explicitly clear, the following set of functions 8 * cannot execute in place from flash and are instead 9 * relocated into internal SRAM. 10 */ 11 12 #include "fsl_power.h" 13 #include "flash_clock_setup.h" 14 15 #define FLEXSPI_DLL_LOCK_RETRY (10) 16 flash_deinit(FLEXSPI_Type * base)17static void flash_deinit(FLEXSPI_Type *base) 18 { 19 /* Wait until FLEXSPI is not busy */ 20 while (!((base->STS0 & FLEXSPI_STS0_ARBIDLE_MASK) && 21 (base->STS0 & FLEXSPI_STS0_SEQIDLE_MASK))) { 22 } 23 /* Disable module during the reset procedure */ 24 base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK; 25 } 26 flash_init(FLEXSPI_Type * base)27static void flash_init(FLEXSPI_Type *base) 28 { 29 uint32_t status; 30 uint32_t lastStatus; 31 uint32_t retry; 32 uint32_t mask = 0; 33 34 /* Enable FLEXSPI module */ 35 base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; 36 37 base->MCR0 |= FLEXSPI_MCR0_SWRESET_MASK; 38 while (base->MCR0 & FLEXSPI_MCR0_SWRESET_MASK) { 39 } 40 41 /* Need to wait DLL locked if DLL enabled */ 42 if (0U != (base->DLLCR[0] & FLEXSPI_DLLCR_DLLEN_MASK)) { 43 lastStatus = base->STS2; 44 retry = FLEXSPI_DLL_LOCK_RETRY; 45 /* Flash on port A */ 46 if (((base->FLSHCR0[0] & FLEXSPI_FLSHCR0_FLSHSZ_MASK) > 0) || 47 ((base->FLSHCR0[1] & FLEXSPI_FLSHCR0_FLSHSZ_MASK) > 0)) { 48 mask |= FLEXSPI_STS2_AREFLOCK_MASK | FLEXSPI_STS2_ASLVLOCK_MASK; 49 } 50 /* Flash on port B */ 51 if (((base->FLSHCR0[2] & FLEXSPI_FLSHCR0_FLSHSZ_MASK) > 0) || 52 ((base->FLSHCR0[3] & FLEXSPI_FLSHCR0_FLSHSZ_MASK) > 0)) { 53 mask |= FLEXSPI_STS2_BREFLOCK_MASK | FLEXSPI_STS2_BSLVLOCK_MASK; 54 } 55 /* Wait slave delay line locked and slave reference delay line locked. */ 56 do { 57 status = base->STS2; 58 if ((status & mask) == mask) { 59 /* Locked */ 60 retry = 100; 61 break; 62 } else if (status == lastStatus) { 63 /* Same delay cell number in calibration */ 64 retry--; 65 } else { 66 retry = FLEXSPI_DLL_LOCK_RETRY; 67 lastStatus = status; 68 } 69 } while (retry > 0); 70 /* According to ERR011377, need to delay at least 100 NOPs 71 * to ensure the DLL is locked. 72 */ 73 for (; retry > 0U; retry--) { 74 __NOP(); 75 } 76 } 77 } 78 flexspi_setup_clock(FLEXSPI_Type * base,uint32_t src,uint32_t divider)79void flexspi_setup_clock(FLEXSPI_Type *base, uint32_t src, uint32_t divider) 80 { 81 if (base == FLEXSPI) { 82 if ((CLKCTL0->FLEXSPIFCLKSEL != CLKCTL0_FLEXSPIFCLKSEL_SEL(src)) || 83 ((CLKCTL0->FLEXSPIFCLKDIV & CLKCTL0_FLEXSPIFCLKDIV_DIV_MASK) != 84 (divider - 1))) { 85 /* Always deinit FLEXSPI and init FLEXSPI for the flash to make sure the 86 * flash works correctly after the FLEXSPI root clock changed as the 87 * default FLEXSPI configuration may does not work for the new root 88 * clock frequency. 89 */ 90 flash_deinit(base); 91 92 /* Disable clock before changing clock source */ 93 CLKCTL0->PSCCTL0_CLR = CLKCTL0_PSCCTL0_CLR_FLEXSPI_OTFAD_CLK_MASK; 94 /* Update flexspi clock */ 95 CLKCTL0->FLEXSPIFCLKSEL = CLKCTL0_FLEXSPIFCLKSEL_SEL(src); 96 /* Reset the divider counter */ 97 CLKCTL0->FLEXSPIFCLKDIV |= CLKCTL0_FLEXSPIFCLKDIV_RESET_MASK; 98 CLKCTL0->FLEXSPIFCLKDIV = CLKCTL0_FLEXSPIFCLKDIV_DIV(divider - 1); 99 while ((CLKCTL0->FLEXSPIFCLKDIV) & CLKCTL0_FLEXSPIFCLKDIV_REQFLAG_MASK) { 100 } 101 /* Enable FLEXSPI clock again */ 102 CLKCTL0->PSCCTL0_SET = CLKCTL0_PSCCTL0_SET_FLEXSPI_OTFAD_CLK_MASK; 103 104 flash_init(base); 105 } 106 } else { 107 return; 108 } 109 } 110 111 /* This function is used to change FlexSPI clock to a stable source before clock 112 * sources(Such as PLL and Main clock) updating in case XIP (execute code on 113 * FLEXSPI memory.) 114 */ flexspi_clock_safe_config(void)115void flexspi_clock_safe_config(void) 116 { 117 /* Move FLEXSPI clock source from main clock to FRO192M / 2 to avoid instruction/data 118 * fetch issue in XIP when updating PLL and main clock. 119 */ 120 flexspi_setup_clock(FLEXSPI, 3U, 1U); 121 } 122