68 lines
1.6 KiB
C
68 lines
1.6 KiB
C
/*
|
|
* Copyright (c) 2023, NXP
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <fsl_clock.h>
|
|
#include <fsl_flexspi.h>
|
|
#include <soc.h>
|
|
#include <errno.h>
|
|
#include <zephyr/irq.h>
|
|
#include <zephyr/dt-bindings/clock/imx_ccm.h>
|
|
|
|
uint32_t flexspi_clock_set_freq(uint32_t clock_name, uint32_t rate)
|
|
{
|
|
uint8_t divider;
|
|
uint32_t root_rate;
|
|
FLEXSPI_Type *flexspi;
|
|
clock_div_t div_sel;
|
|
clock_ip_name_t clk_name;
|
|
|
|
switch (clock_name) {
|
|
case IMX_CCM_FLEXSPI_CLK:
|
|
/* Get clock root frequency */
|
|
root_rate = CLOCK_GetClockRootFreq(kCLOCK_FlexspiClkRoot) *
|
|
(CLOCK_GetDiv(kCLOCK_FlexspiDiv) + 1);
|
|
flexspi = (FLEXSPI_Type *)DT_REG_ADDR(DT_NODELABEL(flexspi));
|
|
div_sel = kCLOCK_FlexspiDiv;
|
|
clk_name = kCLOCK_FlexSpi;
|
|
break;
|
|
#if DT_NODE_HAS_STATUS(DT_NODELABEL(flexspi2), okay)
|
|
case IMX_CCM_FLEXSPI2_CLK:
|
|
/* Get clock root frequency */
|
|
root_rate = CLOCK_GetClockRootFreq(kCLOCK_Flexspi2ClkRoot) *
|
|
(CLOCK_GetDiv(kCLOCK_Flexspi2Div) + 1);
|
|
flexspi = (FLEXSPI_Type *)DT_REG_ADDR(DT_NODELABEL(flexspi2));
|
|
div_sel = kCLOCK_Flexspi2Div;
|
|
clk_name = kCLOCK_FlexSpi2;
|
|
break;
|
|
#endif
|
|
default:
|
|
return -ENOTSUP;
|
|
}
|
|
/* Select a divider based on root frequency.
|
|
* if we can't get an exact divider, round down
|
|
*/
|
|
divider = ((root_rate + (rate - 1)) / rate) - 1;
|
|
/* Cap divider to max value */
|
|
divider = MIN(divider, kCLOCK_FlexspiDivBy8);
|
|
|
|
while (FLEXSPI_GetBusIdleStatus(flexspi) == false) {
|
|
/* Spin */
|
|
}
|
|
FLEXSPI_Enable(flexspi, false);
|
|
|
|
CLOCK_DisableClock(clk_name);
|
|
|
|
CLOCK_SetDiv(div_sel, divider);
|
|
|
|
CLOCK_EnableClock(clk_name);
|
|
|
|
FLEXSPI_Enable(flexspi, true);
|
|
|
|
FLEXSPI_SoftwareReset(flexspi);
|
|
|
|
return 0;
|
|
}
|