drivers: clock_control: ccm_rev2: add support for reclocking FlexSPI

Add support for reclocking flexspi in ccm_rev2 driver. Clock update
functions are provided for the RT11xx.

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
Daniel DeGrasse 2023-08-24 14:55:30 -05:00 committed by Carles Cufí
parent f81113e948
commit a10fee2d5e
3 changed files with 112 additions and 0 deletions

View file

@ -132,6 +132,14 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev,
*rate = 393216000 / divider;
return 0;
#endif
#ifdef CONFIG_MEMC_MCUX_FLEXSPI
case IMX_CCM_FLEXSPI_CLK:
clock_root = kCLOCK_Root_Flexspi1;
break;
case IMX_CCM_FLEXSPI2_CLK:
clock_root = kCLOCK_Root_Flexspi2;
break;
#endif
default:
return -EINVAL;
@ -144,10 +152,46 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev,
return 0;
}
/*
* Since this function is used to reclock the FlexSPI when running in
* XIP, it must be located in RAM when MEMC driver is enabled.
*/
#ifdef CONFIG_MEMC_MCUX_FLEXSPI
#define CCM_SET_FUNC_ATTR __ramfunc
#else
#define CCM_SET_FUNC_ATTR
#endif
static int CCM_SET_FUNC_ATTR mcux_ccm_set_subsys_rate(const struct device *dev,
clock_control_subsys_t subsys,
clock_control_subsys_rate_t rate)
{
uint32_t clock_name = (uintptr_t)subsys;
uint32_t clock_rate = (uintptr_t)rate;
switch (clock_name) {
case IMX_CCM_FLEXSPI_CLK:
__fallthrough;
case IMX_CCM_FLEXSPI2_CLK:
#if defined(CONFIG_SOC_SERIES_IMX_RT11XX) && defined(CONFIG_MEMC_MCUX_FLEXSPI)
/* The SOC is using the FlexSPI for XIP. Therefore,
* the FlexSPI itself must be managed within the function,
* which is SOC specific.
*/
return flexspi_clock_set_freq(clock_name, clock_rate);
#endif
default:
/* Silence unused variable warning */
ARG_UNUSED(clock_rate);
return -ENOTSUP;
}
}
static const struct clock_control_driver_api mcux_ccm_driver_api = {
.on = mcux_ccm_on,
.off = mcux_ccm_off,
.get_rate = mcux_ccm_get_subsys_rate,
.set_rate = mcux_ccm_set_subsys_rate,
};
DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, PRE_KERNEL_1,

View file

@ -35,6 +35,14 @@ if (CONFIG_SOC_SERIES_IMX_RT10XX AND CONFIG_MEMC_MCUX_FLEXSPI)
endif()
endif ()
if (CONFIG_SOC_SERIES_IMX_RT11XX AND CONFIG_MEMC_MCUX_FLEXSPI)
zephyr_sources(flexspi_rt11xx.c)
if (CONFIG_FLASH_MCUX_FLEXSPI_XIP)
zephyr_code_relocate(FILES flexspi_rt11xx.c LOCATION ITCM_TEXT)
endif()
endif ()
if (CONFIG_PM AND CONFIG_SOC_SERIES_IMX_RT10XX)
zephyr_sources(power_rt10xx.c)
zephyr_code_relocate(FILES power_rt10xx.c LOCATION ITCM_TEXT)

View file

@ -0,0 +1,60 @@
/*
* 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_rev2.h>
uint32_t flexspi_clock_set_freq(uint32_t clock_name, uint32_t rate)
{
clock_name_t root;
uint32_t root_rate;
FLEXSPI_Type *flexspi;
clock_root_t flexspi_clk;
clock_ip_name_t clk_gate;
uint32_t divider;
switch (clock_name) {
case IMX_CCM_FLEXSPI_CLK:
flexspi_clk = kCLOCK_Root_Flexspi1;
flexspi = (FLEXSPI_Type *)DT_REG_ADDR(DT_NODELABEL(flexspi));
clk_gate = kCLOCK_Flexspi1;
break;
case IMX_CCM_FLEXSPI2_CLK:
flexspi_clk = kCLOCK_Root_Flexspi2;
flexspi = (FLEXSPI_Type *)DT_REG_ADDR(DT_NODELABEL(flexspi2));
clk_gate = kCLOCK_Flexspi2;
break;
default:
return -ENOTSUP;
}
root = CLOCK_GetRootClockSource(flexspi_clk,
CLOCK_GetRootClockMux(flexspi_clk));
/* Get clock root frequency */
root_rate = CLOCK_GetFreq(root);
/* Select a divider based on root frequency */
divider = MIN((root_rate / rate), CCM_CLOCK_ROOT_CONTROL_DIV_MASK);
while (FLEXSPI_GetBusIdleStatus(flexspi) == false) {
/* Spin */
}
FLEXSPI_Enable(flexspi, false);
CLOCK_DisableClock(clk_gate);
CLOCK_SetRootClockDiv(flexspi_clk, divider);
CLOCK_EnableClock(clk_gate);
FLEXSPI_Enable(flexspi, true);
FLEXSPI_SoftwareReset(flexspi);
return 0;
}