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:
parent
f81113e948
commit
a10fee2d5e
3 changed files with 112 additions and 0 deletions
|
@ -132,6 +132,14 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev,
|
||||||
*rate = 393216000 / divider;
|
*rate = 393216000 / divider;
|
||||||
|
|
||||||
return 0;
|
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
|
#endif
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -144,10 +152,46 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev,
|
||||||
return 0;
|
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 = {
|
static const struct clock_control_driver_api mcux_ccm_driver_api = {
|
||||||
.on = mcux_ccm_on,
|
.on = mcux_ccm_on,
|
||||||
.off = mcux_ccm_off,
|
.off = mcux_ccm_off,
|
||||||
.get_rate = mcux_ccm_get_subsys_rate,
|
.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,
|
DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, PRE_KERNEL_1,
|
||||||
|
|
|
@ -35,6 +35,14 @@ if (CONFIG_SOC_SERIES_IMX_RT10XX AND CONFIG_MEMC_MCUX_FLEXSPI)
|
||||||
endif()
|
endif()
|
||||||
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)
|
if (CONFIG_PM AND CONFIG_SOC_SERIES_IMX_RT10XX)
|
||||||
zephyr_sources(power_rt10xx.c)
|
zephyr_sources(power_rt10xx.c)
|
||||||
zephyr_code_relocate(FILES power_rt10xx.c LOCATION ITCM_TEXT)
|
zephyr_code_relocate(FILES power_rt10xx.c LOCATION ITCM_TEXT)
|
||||||
|
|
60
soc/arm/nxp_imx/rt/flexspi_rt11xx.c
Normal file
60
soc/arm/nxp_imx/rt/flexspi_rt11xx.c
Normal 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;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue