1 /* 2 * Copyright (c) 2023, NXP 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <fsl_clock.h> 8 #include <fsl_flexspi.h> 9 #include <soc.h> 10 #include <errno.h> 11 #include <zephyr/irq.h> 12 #include <zephyr/dt-bindings/clock/imx_ccm.h> 13 flexspi_clock_set_freq(uint32_t clock_name,uint32_t rate)14uint32_t flexspi_clock_set_freq(uint32_t clock_name, uint32_t rate) 15 { 16 uint8_t divider; 17 uint32_t root_rate; 18 FLEXSPI_Type *flexspi; 19 clock_div_t div_sel; 20 clock_ip_name_t clk_name; 21 22 switch (clock_name) { 23 case IMX_CCM_FLEXSPI_CLK: 24 /* Get clock root frequency */ 25 root_rate = CLOCK_GetClockRootFreq(kCLOCK_FlexspiClkRoot) * 26 (CLOCK_GetDiv(kCLOCK_FlexspiDiv) + 1); 27 flexspi = (FLEXSPI_Type *)DT_REG_ADDR(DT_NODELABEL(flexspi)); 28 div_sel = kCLOCK_FlexspiDiv; 29 clk_name = kCLOCK_FlexSpi; 30 break; 31 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(flexspi2)) 32 case IMX_CCM_FLEXSPI2_CLK: 33 /* Get clock root frequency */ 34 root_rate = CLOCK_GetClockRootFreq(kCLOCK_Flexspi2ClkRoot) * 35 (CLOCK_GetDiv(kCLOCK_Flexspi2Div) + 1); 36 flexspi = (FLEXSPI_Type *)DT_REG_ADDR(DT_NODELABEL(flexspi2)); 37 div_sel = kCLOCK_Flexspi2Div; 38 clk_name = kCLOCK_FlexSpi2; 39 break; 40 #endif 41 default: 42 return -ENOTSUP; 43 } 44 /* Select a divider based on root frequency. 45 * if we can't get an exact divider, round down 46 */ 47 divider = ((root_rate + (rate - 1)) / rate) - 1; 48 /* Cap divider to max value */ 49 divider = MIN(divider, kCLOCK_FlexspiDivBy8); 50 51 while (FLEXSPI_GetBusIdleStatus(flexspi) == false) { 52 /* Spin */ 53 } 54 FLEXSPI_Enable(flexspi, false); 55 56 CLOCK_DisableClock(clk_name); 57 58 CLOCK_SetDiv(div_sel, divider); 59 60 CLOCK_EnableClock(clk_name); 61 62 FLEXSPI_Enable(flexspi, true); 63 64 FLEXSPI_SoftwareReset(flexspi); 65 66 return 0; 67 } 68