1 /*
2  * Copyright 2022-2023 NXP
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <zephyr/devicetree.h>
7 #include "flexspi_clock_setup.h"
8 #ifdef CONFIG_MEMC
9 #include <fsl_flexspi.h>
10 #include <fsl_clock.h>
11 #endif
12 
13 #ifdef CONFIG_MEMC
14 /**
15  * @brief Set flexspi clock to given frequency
16  *
17  * This function differs from the above function in that it will not configure
18  * the FlexSPI with a new MUX source, only change the divider. This function
19  * is used by the clock control framework to set the clock frequency of
20  * the FlexSPI
21  */
flexspi_clock_set_freq(uint32_t clock_name,uint32_t rate)22 int __ramfunc flexspi_clock_set_freq(uint32_t clock_name, uint32_t rate)
23 {
24 	uint32_t root_rate;
25 	uint32_t divider;
26 
27 	(void)clock_name; /* Not used by this function */
28 
29 	/* Get the root clock rate: FlexSPI clock * divisor */
30 	root_rate = ((CLKCTL0->FLEXSPIFCLKDIV & CLKCTL0_FLEXSPIFCLKDIV_DIV_MASK) + 1) *
31 			CLOCK_GetFlexspiClkFreq();
32 
33 	/* Select a divider based on root frequency.
34 	 * if we can't get an exact divider, round down
35 	 */
36 	divider = ((root_rate + (rate - 1)) / rate) - 1;
37 	/* Cap divider to max value */
38 	divider = MIN(divider, CLKCTL0_FLEXSPIFCLKDIV_DIV_MASK);
39 
40 	while (FLEXSPI_GetBusIdleStatus(FLEXSPI) == false) {
41 		/* Spin */
42 	}
43 	FLEXSPI_Enable(FLEXSPI, false);
44 
45 	set_flexspi_clock(FLEXSPI, (CLKCTL0->FLEXSPIFCLKSEL &
46 			CLKCTL0_FLEXSPIFCLKSEL_SEL_MASK), (divider + 1));
47 
48 
49 	FLEXSPI_Enable(FLEXSPI, true);
50 
51 	FLEXSPI_SoftwareReset(FLEXSPI);
52 
53 	return 0;
54 }
55 #endif
56 
57 /**
58  * @brief Set flexspi clock
59  */
set_flexspi_clock(FLEXSPI_Type * base,uint32_t src,uint32_t divider)60 void __ramfunc set_flexspi_clock(FLEXSPI_Type *base, uint32_t src, uint32_t divider)
61 {
62 	CLKCTL0->FLEXSPIFCLKSEL = CLKCTL0_FLEXSPIFCLKSEL_SEL(src);
63 	CLKCTL0->FLEXSPIFCLKDIV |=
64 		CLKCTL0_FLEXSPIFCLKDIV_RESET_MASK; /* Reset the divider counter */
65 	CLKCTL0->FLEXSPIFCLKDIV = CLKCTL0_FLEXSPIFCLKDIV_DIV(divider - 1);
66 	while ((CLKCTL0->FLEXSPIFCLKDIV) & CLKCTL0_FLEXSPIFCLKDIV_REQFLAG_MASK) {
67 	}
68 }
69