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_rev2.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 clock_name_t root; 17 uint32_t root_rate; 18 FLEXSPI_Type *flexspi; 19 clock_root_t flexspi_clk; 20 clock_ip_name_t clk_gate; 21 uint32_t divider; 22 23 switch (clock_name) { 24 case IMX_CCM_FLEXSPI_CLK: 25 flexspi_clk = kCLOCK_Root_Flexspi1; 26 flexspi = (FLEXSPI_Type *)DT_REG_ADDR(DT_NODELABEL(flexspi)); 27 clk_gate = kCLOCK_Flexspi1; 28 break; 29 case IMX_CCM_FLEXSPI2_CLK: 30 flexspi_clk = kCLOCK_Root_Flexspi2; 31 flexspi = (FLEXSPI_Type *)DT_REG_ADDR(DT_NODELABEL(flexspi2)); 32 clk_gate = kCLOCK_Flexspi2; 33 break; 34 default: 35 return -ENOTSUP; 36 } 37 root = CLOCK_GetRootClockSource(flexspi_clk, 38 CLOCK_GetRootClockMux(flexspi_clk)); 39 /* Get clock root frequency */ 40 root_rate = CLOCK_GetFreq(root); 41 /* Select a divider based on root clock frequency. We round the 42 * divider up, so that the resulting clock frequency is lower than 43 * requested when we can't output the exact requested frequency 44 */ 45 divider = ((root_rate + (rate - 1)) / rate); 46 /* Cap divider to max value */ 47 divider = MIN(divider, CCM_CLOCK_ROOT_CONTROL_DIV_MASK); 48 49 while (FLEXSPI_GetBusIdleStatus(flexspi) == false) { 50 /* Spin */ 51 } 52 FLEXSPI_Enable(flexspi, false); 53 54 CLOCK_DisableClock(clk_gate); 55 56 CLOCK_SetRootClockDiv(flexspi_clk, divider); 57 58 CLOCK_EnableClock(clk_gate); 59 60 FLEXSPI_Enable(flexspi, true); 61 62 FLEXSPI_SoftwareReset(flexspi); 63 64 return 0; 65 } 66