zephyr/drivers/clock_control/clock_control_mcux_syscon.c
Declan Snyder efdd8580ca soc: nxp: Flatten MCX SOCs
Turn MCX series into families.

Reasoning:
 1. The MCX SOCs are quite different from each other and having them all
    under one family in the HWMv2 hierarchy is fruitless because there
    are so many differences that it is confusing to try to introduce
    family-level code and configs since they would each only apply to a
    subset of the series. There is almost nothing that can be shared
    between all of them. Which is why there are comments in the MCX
    family files saying not to put anything in them. This is a technical
    waste.
 2. Therefore, turning all of them into families is almost 0 effort and
    makes sense. It will allow these different types of MCX to be
    further subdivided into series in the future as the MCX portfolio
    expands and such division will be necessary as new SOCs within each
    letter family are released.

Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
2025-07-19 13:25:29 -04:00

692 lines
17 KiB
C

/*
* Copyright 2020-2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT nxp_lpc_syscon
#include <errno.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h>
#include <soc.h>
#include <fsl_clock.h>
#define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(clock_control);
static int mcux_lpc_syscon_clock_control_on(const struct device *dev,
clock_control_subsys_t sub_system)
{
#if defined(CONFIG_CAN_MCUX_MCAN)
if ((uint32_t)sub_system == MCUX_MCAN_CLK) {
CLOCK_EnableClock(kCLOCK_Mcan);
}
#endif /* defined(CONFIG_CAN_MCUX_MCAN) */
#if defined(CONFIG_COUNTER_NXP_MRT)
if ((uint32_t)sub_system == MCUX_MRT_CLK) {
#if defined(CONFIG_SOC_FAMILY_LPC) || defined(CONFIG_SOC_SERIES_RW6XX) || \
defined(CONFIG_SOC_FAMILY_MCXN)
CLOCK_EnableClock(kCLOCK_Mrt);
#elif defined(CONFIG_SOC_FAMILY_NXP_IMXRT)
CLOCK_EnableClock(kCLOCK_Mrt0);
#endif
}
#if defined(CONFIG_SOC_SERIES_RW6XX)
if ((uint32_t)sub_system == MCUX_FREEMRT_CLK) {
CLOCK_EnableClock(kCLOCK_FreeMrt);
}
#endif
#endif /* defined(CONFIG_COUNTER_NXP_MRT) */
#if defined(CONFIG_MIPI_DBI_NXP_LCDIC)
if ((uint32_t)sub_system == MCUX_LCDIC_CLK) {
CLOCK_EnableClock(kCLOCK_Lcdic);
}
#endif
#if defined(CONFIG_PINCTRL_NXP_PORT)
switch ((uint32_t)sub_system) {
#if defined(CONFIG_SOC_FAMILY_MCXA)
case MCUX_PORT0_CLK:
CLOCK_EnableClock(kCLOCK_GatePORT0);
break;
case MCUX_PORT1_CLK:
CLOCK_EnableClock(kCLOCK_GatePORT1);
break;
case MCUX_PORT2_CLK:
CLOCK_EnableClock(kCLOCK_GatePORT2);
break;
case MCUX_PORT3_CLK:
CLOCK_EnableClock(kCLOCK_GatePORT3);
break;
#if (defined(FSL_FEATURE_SOC_PORT_COUNT) && (FSL_FEATURE_SOC_PORT_COUNT > 4))
case MCUX_PORT4_CLK:
CLOCK_EnableClock(kCLOCK_GatePORT4);
break;
#endif /* defined(FSL_FEATURE_SOC_PORT_COUNT) */
#else
case MCUX_PORT0_CLK:
CLOCK_EnableClock(kCLOCK_Port0);
break;
case MCUX_PORT1_CLK:
CLOCK_EnableClock(kCLOCK_Port1);
break;
case MCUX_PORT2_CLK:
CLOCK_EnableClock(kCLOCK_Port2);
break;
case MCUX_PORT3_CLK:
CLOCK_EnableClock(kCLOCK_Port3);
break;
case MCUX_PORT4_CLK:
CLOCK_EnableClock(kCLOCK_Port4);
break;
#endif /* defined(CONFIG_SOC_FAMILY_MCXA) */
default:
break;
}
#endif /* defined(CONFIG_PINCTRL_NXP_PORT) */
#ifdef CONFIG_ETH_NXP_ENET_QOS
if ((uint32_t)sub_system == MCUX_ENET_QOS_CLK) {
CLOCK_EnableClock(kCLOCK_Enet);
}
#endif
#if defined(CONFIG_CAN_MCUX_FLEXCAN)
switch ((uint32_t)sub_system) {
#if defined(CONFIG_SOC_FAMILY_MCXA)
case MCUX_FLEXCAN0_CLK:
CLOCK_EnableClock(kCLOCK_GateFLEXCAN0);
break;
#else
case MCUX_FLEXCAN0_CLK:
CLOCK_EnableClock(kCLOCK_Flexcan0);
break;
case MCUX_FLEXCAN1_CLK:
CLOCK_EnableClock(kCLOCK_Flexcan1);
break;
#endif /* defined(CONFIG_SOC_FAMILY_MCXA) */
default:
break;
}
#endif /* defined(CONFIG_CAN_MCUX_MCAN) */
#ifdef CONFIG_ETH_NXP_ENET
if ((uint32_t)sub_system == MCUX_ENET_CLK) {
#ifdef CONFIG_SOC_SERIES_RW6XX
CLOCK_EnableClock(kCLOCK_TddrMciEnetClk);
CLOCK_EnableClock(kCLOCK_EnetIpg);
CLOCK_EnableClock(kCLOCK_EnetIpgS);
#endif
}
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(rtc), okay)
#if defined(CONFIG_SOC_SERIES_IMXRT5XX) || defined(CONFIG_SOC_SERIES_IMXRT6XX)
CLOCK_EnableOsc32K(true);
#elif CONFIG_SOC_FAMILY_MCXN
/* 0x0 Clock Select Value Set IRTC to use FRO 16K Clk */
#if DT_PROP(DT_NODELABEL(rtc), clock_select) == 0x0
CLOCK_SetupClk16KClocking(kCLOCK_Clk16KToVbat | kCLOCK_Clk16KToMain);
/* 0x1 Clock Select Value Set IRTC to use Osc 32K Clk */
#elif DT_PROP(DT_NODELABEL(rtc), clock_select) == 0x1
CLOCK_SetupOsc32KClocking(kCLOCK_Osc32kToVbat | kCLOCK_Osc32kToMain);
#endif /* DT_PROP(DT_NODELABEL(rtc), clock_select) */
CLOCK_EnableClock(kCLOCK_Rtc0);
#endif /* CONFIG_SOC_FAMILY_MCXN */
#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(rtc), okay) */
return 0;
}
static int mcux_lpc_syscon_clock_control_off(const struct device *dev,
clock_control_subsys_t sub_system)
{
return 0;
}
static int mcux_lpc_syscon_clock_control_get_subsys_rate(const struct device *dev,
clock_control_subsys_t sub_system,
uint32_t *rate)
{
uint32_t clock_name = (uint32_t)sub_system;
switch (clock_name) {
#if defined(CONFIG_I2C_MCUX_FLEXCOMM) || defined(CONFIG_SPI_MCUX_FLEXCOMM) || \
defined(CONFIG_UART_MCUX_FLEXCOMM) || defined(CONFIG_I2S_MCUX_FLEXCOMM)
case MCUX_FLEXCOMM0_CLK:
*rate = CLOCK_GetFlexCommClkFreq(0);
break;
case MCUX_FLEXCOMM1_CLK:
*rate = CLOCK_GetFlexCommClkFreq(1);
break;
case MCUX_FLEXCOMM2_CLK:
*rate = CLOCK_GetFlexCommClkFreq(2);
break;
case MCUX_FLEXCOMM3_CLK:
*rate = CLOCK_GetFlexCommClkFreq(3);
break;
case MCUX_FLEXCOMM4_CLK:
*rate = CLOCK_GetFlexCommClkFreq(4);
break;
case MCUX_FLEXCOMM5_CLK:
*rate = CLOCK_GetFlexCommClkFreq(5);
break;
case MCUX_FLEXCOMM6_CLK:
*rate = CLOCK_GetFlexCommClkFreq(6);
break;
case MCUX_FLEXCOMM7_CLK:
*rate = CLOCK_GetFlexCommClkFreq(7);
break;
case MCUX_FLEXCOMM8_CLK:
*rate = CLOCK_GetFlexCommClkFreq(8);
break;
case MCUX_FLEXCOMM9_CLK:
*rate = CLOCK_GetFlexCommClkFreq(9);
break;
case MCUX_FLEXCOMM10_CLK:
*rate = CLOCK_GetFlexCommClkFreq(10);
break;
case MCUX_FLEXCOMM11_CLK:
*rate = CLOCK_GetFlexCommClkFreq(11);
break;
case MCUX_FLEXCOMM12_CLK:
*rate = CLOCK_GetFlexCommClkFreq(12);
break;
case MCUX_FLEXCOMM13_CLK:
*rate = CLOCK_GetFlexCommClkFreq(13);
break;
case MCUX_PMIC_I2C_CLK:
*rate = CLOCK_GetFlexCommClkFreq(15);
break;
case MCUX_HS_SPI_CLK:
#if defined(SYSCON_HSLSPICLKSEL_SEL_MASK)
*rate = CLOCK_GetHsLspiClkFreq();
#else
*rate = CLOCK_GetFlexCommClkFreq(14);
#endif
break;
case MCUX_HS_SPI1_CLK:
*rate = CLOCK_GetFlexCommClkFreq(16);
break;
#elif defined(CONFIG_NXP_LP_FLEXCOMM)
case MCUX_FLEXCOMM0_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(0);
break;
case MCUX_FLEXCOMM1_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(1);
break;
case MCUX_FLEXCOMM2_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(2);
break;
case MCUX_FLEXCOMM3_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(3);
break;
case MCUX_FLEXCOMM4_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(4);
break;
case MCUX_FLEXCOMM5_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(5);
break;
case MCUX_FLEXCOMM6_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(6);
break;
case MCUX_FLEXCOMM7_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(7);
break;
case MCUX_FLEXCOMM8_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(8);
break;
case MCUX_FLEXCOMM9_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(9);
break;
case MCUX_FLEXCOMM10_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(10);
break;
case MCUX_FLEXCOMM11_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(11);
break;
case MCUX_FLEXCOMM12_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(12);
break;
case MCUX_FLEXCOMM13_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(13);
break;
case MCUX_FLEXCOMM17_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(17);
break;
case MCUX_FLEXCOMM18_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(18);
break;
case MCUX_FLEXCOMM19_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(19);
break;
case MCUX_FLEXCOMM20_CLK:
*rate = CLOCK_GetLPFlexCommClkFreq(20);
break;
#endif
/* On RT7xx, flexcomm14 and 16 only can be LPSPI, flexcomm15 only can be I2C. */
#if defined(CONFIG_SOC_SERIES_IMXRT7XX) && defined(CONFIG_SOC_FAMILY_NXP_IMXRT)
case MCUX_LPSPI14_CLK:
*rate = CLOCK_GetLPSpiClkFreq(14);
break;
case MCUX_LPI2C15_CLK:
*rate = CLOCK_GetLPI2cClkFreq(15);
break;
case MCUX_LPSPI16_CLK:
*rate = CLOCK_GetLPSpiClkFreq(16);
break;
#endif
#if (defined(FSL_FEATURE_SOC_USDHC_COUNT) && FSL_FEATURE_SOC_USDHC_COUNT)
#if defined(CONFIG_SOC_FAMILY_MCXN)
case MCUX_USDHC1_CLK:
*rate = CLOCK_GetUsdhcClkFreq();
break;
#elif defined(CONFIG_SOC_SERIES_IMXRT7XX)
case MCUX_USDHC1_CLK:
*rate = CLOCK_GetUsdhcClkFreq(0);
break;
case MCUX_USDHC2_CLK:
*rate = CLOCK_GetUsdhcClkFreq(1);
break;
#else
case MCUX_USDHC1_CLK:
*rate = CLOCK_GetSdioClkFreq(0);
break;
case MCUX_USDHC2_CLK:
*rate = CLOCK_GetSdioClkFreq(1);
break;
#endif
#endif
#if (defined(FSL_FEATURE_SOC_SDIF_COUNT) && (FSL_FEATURE_SOC_SDIF_COUNT)) && CONFIG_MCUX_SDIF
case MCUX_SDIF_CLK:
*rate = CLOCK_GetSdioClkFreq();
break;
#endif
#if defined(CONFIG_CAN_MCUX_MCAN)
case MCUX_MCAN_CLK:
*rate = CLOCK_GetMCanClkFreq();
break;
#endif /* defined(CONFIG_CAN_MCUX_MCAN) */
#if defined(CONFIG_COUNTER_MCUX_CTIMER) || defined(CONFIG_PWM_MCUX_CTIMER)
case MCUX_CTIMER0_CLK:
*rate = CLOCK_GetCTimerClkFreq(0);
break;
case MCUX_CTIMER1_CLK:
*rate = CLOCK_GetCTimerClkFreq(1);
break;
case MCUX_CTIMER2_CLK:
*rate = CLOCK_GetCTimerClkFreq(2);
break;
case MCUX_CTIMER3_CLK:
*rate = CLOCK_GetCTimerClkFreq(3);
break;
case MCUX_CTIMER4_CLK:
*rate = CLOCK_GetCTimerClkFreq(4);
break;
case MCUX_CTIMER5_CLK:
*rate = CLOCK_GetCTimerClkFreq(5);
break;
case MCUX_CTIMER6_CLK:
*rate = CLOCK_GetCTimerClkFreq(6);
break;
case MCUX_CTIMER7_CLK:
*rate = CLOCK_GetCTimerClkFreq(7);
break;
#endif
#if defined(CONFIG_COUNTER_NXP_MRT)
case MCUX_MRT_CLK:
#if defined(CONFIG_SOC_SERIES_RW6XX)
case MCUX_FREEMRT_CLK:
#endif /* RW */
#endif /* MRT */
#if defined(CONFIG_PWM_MCUX_SCTIMER)
case MCUX_SCTIMER_CLK:
#endif
#ifdef CONFIG_SOC_SERIES_RW6XX
/* RW6XX uses core clock for SCTimer, not bus clock */
*rate = CLOCK_GetCoreSysClkFreq();
break;
#else
case MCUX_BUS_CLK:
*rate = CLOCK_GetFreq(kCLOCK_BusClk);
break;
#endif
#if defined(CONFIG_I3C_MCUX)
case MCUX_I3C_CLK:
#if CONFIG_SOC_FAMILY_MCXN
*rate = CLOCK_GetI3cClkFreq(0);
#elif CONFIG_SOC_FAMILY_MCXA
*rate = CLOCK_GetI3CFClkFreq();
#else
*rate = CLOCK_GetI3cClkFreq();
#endif
break;
#if (FSL_FEATURE_SOC_I3C_COUNT == 2)
case MCUX_I3C2_CLK:
#if CONFIG_SOC_FAMILY_MCXN
*rate = CLOCK_GetI3cClkFreq(1);
#else
*rate = CLOCK_GetI3cClkFreq();
#endif
break;
#endif
#endif /* CONFIG_I3C_MCUX */
#if defined(CONFIG_MIPI_DSI_MCUX_2L)
case MCUX_MIPI_DSI_DPHY_CLK:
*rate = CLOCK_GetMipiDphyClkFreq();
break;
case MCUX_MIPI_DSI_ESC_CLK:
*rate = CLOCK_GetMipiDphyEscTxClkFreq();
break;
case MCUX_LCDIF_PIXEL_CLK:
#if defined(CONFIG_SOC_SERIES_IMXRT7XX) && defined(CONFIG_SOC_FAMILY_NXP_IMXRT)
*rate = CLOCK_GetLcdifClkFreq();
#else
*rate = CLOCK_GetDcPixelClkFreq();
#endif
break;
#endif
#if defined(CONFIG_AUDIO_DMIC_MCUX)
case MCUX_DMIC_CLK:
*rate = CLOCK_GetDmicClkFreq();
break;
#endif
#if defined(CONFIG_MEMC_MCUX_FLEXSPI)
case MCUX_FLEXSPI_CLK:
#if (FSL_FEATURE_SOC_FLEXSPI_COUNT == 1)
*rate = CLOCK_GetFlexspiClkFreq();
#else
*rate = CLOCK_GetFlexspiClkFreq(0);
#endif
break;
#if (FSL_FEATURE_SOC_FLEXSPI_COUNT == 2)
case MCUX_FLEXSPI2_CLK:
*rate = CLOCK_GetFlexspiClkFreq(1);
break;
#endif
#endif /* CONFIG_MEMC_MCUX_FLEXSPI */
#if defined(CONFIG_I2S_MCUX_SAI)
#if defined(CONFIG_SOC_SERIES_IMXRT7XX)
case MCUX_SAI0_CLK:
case MCUX_SAI1_CLK:
case MCUX_SAI2_CLK:
*rate = CLOCK_GetSaiClkFreq();
break;
#else
case MCUX_SAI0_CLK:
#if (FSL_FEATURE_SOC_I2S_COUNT == 1)
*rate = CLOCK_GetSaiClkFreq();
#else
*rate = CLOCK_GetSaiClkFreq(0);
#endif
break;
#if (FSL_FEATURE_SOC_I2S_COUNT == 2)
case MCUX_SAI1_CLK:
*rate = CLOCK_GetSaiClkFreq(1);
break;
#endif
#endif /* CONFIG_SOC_SERIES_IMXRT7XX */
#endif /* CONFIG_I2S_MCUX_SAI */
#ifdef CONFIG_ETH_NXP_ENET_QOS
case MCUX_ENET_QOS_CLK:
*rate = CLOCK_GetFreq(kCLOCK_BusClk);
break;
#endif
#ifdef CONFIG_ETH_NXP_ENET
case MCUX_ENET_CLK:
#ifdef CONFIG_SOC_SERIES_RW6XX
*rate = CLOCK_GetTddrMciEnetClkFreq();
#endif
break;
#endif
#if defined(CONFIG_MIPI_DBI_NXP_LCDIC)
case MCUX_LCDIC_CLK:
*rate = CLOCK_GetLcdClkFreq();
break;
#endif
#if defined(CONFIG_ADC_MCUX_LPADC)
case MCUX_LPADC1_CLK:
#if (FSL_FEATURE_SOC_LPADC_COUNT == 1)
*rate = CLOCK_GetAdcClkFreq();
#else
*rate = CLOCK_GetAdcClkFreq(0);
#endif
break;
#if (FSL_FEATURE_SOC_LPADC_COUNT == 2)
case MCUX_LPADC2_CLK:
*rate = CLOCK_GetAdcClkFreq(1);
break;
#endif
#endif /* CONFIG_ADC_MCUX_LPADC */
#if defined(CONFIG_CAN_MCUX_FLEXCAN)
#if defined(CONFIG_SOC_FAMILY_MCXA)
case MCUX_FLEXCAN0_CLK:
*rate = CLOCK_GetFlexcanClkFreq();
break;
#else
case MCUX_FLEXCAN0_CLK:
*rate = CLOCK_GetFlexcanClkFreq(0);
break;
case MCUX_FLEXCAN1_CLK:
*rate = CLOCK_GetFlexcanClkFreq(1);
break;
#endif /* defined(CONFIG_SOC_FAMILY_MCXA) */
#endif /* defined(CONFIG_CAN_MCUX_FLEXCAN) */
#if defined(CONFIG_MCUX_FLEXIO)
case MCUX_FLEXIO0_CLK:
*rate = CLOCK_GetFlexioClkFreq();
break;
#endif /* defined(CONFIG_MCUX_FLEXIO) */
#if defined(CONFIG_I2S_MCUX_FLEXCOMM)
case MCUX_AUDIO_MCLK:
*rate = CLOCK_GetMclkClkFreq();
break;
#endif /* defined(CONFIG_I2S_MCUX_FLEXCOMM) */
#if (defined(CONFIG_UART_MCUX_LPUART) && CONFIG_SOC_FAMILY_MCXA)
case MCUX_LPUART0_CLK:
*rate = CLOCK_GetLpuartClkFreq(0);
break;
case MCUX_LPUART1_CLK:
*rate = CLOCK_GetLpuartClkFreq(1);
break;
case MCUX_LPUART2_CLK:
*rate = CLOCK_GetLpuartClkFreq(2);
break;
case MCUX_LPUART3_CLK:
*rate = CLOCK_GetLpuartClkFreq(3);
break;
case MCUX_LPUART4_CLK:
*rate = CLOCK_GetLpuartClkFreq(4);
break;
#endif /* defined(CONFIG_UART_MCUX_LPUART) */
#if (defined(CONFIG_I2C_MCUX_LPI2C) && CONFIG_SOC_FAMILY_MCXA)
#if (defined(FSL_FEATURE_SOC_LPI2C_COUNT) && (FSL_FEATURE_SOC_LPI2C_COUNT == 1))
case MCUX_LPI2C0_CLK:
*rate = CLOCK_GetLpi2cClkFreq();
break;
#else
case MCUX_LPI2C0_CLK:
*rate = CLOCK_GetLpi2cClkFreq(0);
break;
case MCUX_LPI2C1_CLK:
*rate = CLOCK_GetLpi2cClkFreq(1);
break;
case MCUX_LPI2C2_CLK:
*rate = CLOCK_GetLpi2cClkFreq(2);
break;
case MCUX_LPI2C3_CLK:
*rate = CLOCK_GetLpi2cClkFreq(3);
break;
#endif /* defined(FSL_FEATURE_SOC_LPI2C_COUNT) */
#endif /* defined(CONFIG_I2C_MCUX_LPI2C) */
#if defined(CONFIG_DT_HAS_NXP_XSPI_ENABLED)
case MCUX_XSPI0_CLK:
*rate = CLOCK_GetXspiClkFreq(0);
break;
case MCUX_XSPI1_CLK:
*rate = CLOCK_GetXspiClkFreq(1);
break;
case MCUX_XSPI2_CLK:
*rate = CLOCK_GetXspiClkFreq(2);
break;
#endif /* defined(CONFIG_DT_HAS_NXP_XSPI_ENABLED) */
#if (defined(CONFIG_SPI_NXP_LPSPI) && CONFIG_SOC_FAMILY_MCXA)
case MCUX_LPSPI0_CLK:
*rate = CLOCK_GetLpspiClkFreq(0);
break;
case MCUX_LPSPI1_CLK:
*rate = CLOCK_GetLpspiClkFreq(1);
break;
#endif /* defined(CONFIG_SPI_NXP_LPSPI) */
}
return 0;
}
#if defined(CONFIG_MEMC)
/*
* Weak implemenetation of flexspi_clock_set_freq- SOC implementations are
* expected to override this
*/
__weak int flexspi_clock_set_freq(uint32_t clock_name, uint32_t freq)
{
ARG_UNUSED(clock_name);
ARG_UNUSED(freq);
return -ENOTSUP;
}
#endif
/*
* 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
#define SYSCON_SET_FUNC_ATTR __ramfunc
#else
#define SYSCON_SET_FUNC_ATTR
#endif
static int SYSCON_SET_FUNC_ATTR mcux_lpc_syscon_clock_control_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 MCUX_FLEXSPI_CLK:
#if defined(CONFIG_MEMC)
/* 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
#if defined(CONFIG_MIPI_DBI_NXP_LCDIC)
case MCUX_LCDIC_CLK:
/* Set LCDIC clock div */
uint32_t root_rate = (CLOCK_GetLcdClkFreq() *
((CLKCTL0->LCDFCLKDIV & CLKCTL0_LCDFCLKDIV_DIV_MASK) + 1));
CLOCK_SetClkDiv(kCLOCK_DivLcdClk, (root_rate / clock_rate));
return 0;
#endif
default:
/* Silence unused variable warning */
ARG_UNUSED(clock_rate);
return -ENOTSUP;
}
}
static int mcux_lpc_syscon_clock_control_configure(const struct device *dev,
clock_control_subsys_t sub_system, void *data)
{
#ifdef CONFIG_SOC_SERIES_RW6XX
#define FLEXCOMM_LP_CLK_DECODE(n) (n & 0x80)
uint32_t clock_name = (uint32_t)sub_system;
int flexcomm_num = -1;
switch (clock_name) {
case MCUX_FLEXCOMM0_CLK:
case MCUX_FLEXCOMM0_LP_CLK:
flexcomm_num = 0;
break;
case MCUX_FLEXCOMM1_CLK:
case MCUX_FLEXCOMM1_LP_CLK:
flexcomm_num = 1;
break;
case MCUX_FLEXCOMM2_CLK:
case MCUX_FLEXCOMM2_LP_CLK:
flexcomm_num = 2;
break;
case MCUX_FLEXCOMM3_CLK:
case MCUX_FLEXCOMM3_LP_CLK:
flexcomm_num = 3;
break;
default:
return -ENOTSUP;
}
if (flexcomm_num >= 0) {
static uint32_t frgclksels[4];
static uint32_t frgctls[4];
if (FLEXCOMM_LP_CLK_DECODE(clock_name)) {
frgclksels[flexcomm_num] = CLKCTL1->FLEXCOMM[flexcomm_num].FRGCLKSEL;
frgctls[flexcomm_num] = CLKCTL1->FLEXCOMM[flexcomm_num].FRGCTL;
CLKCTL1->FLEXCOMM[flexcomm_num].FRGCLKSEL = 0;
CLKCTL1->FLEXCOMM[flexcomm_num].FRGCTL = 0;
} else {
CLKCTL1->FLEXCOMM[flexcomm_num].FRGCLKSEL = frgclksels[flexcomm_num];
CLKCTL1->FLEXCOMM[flexcomm_num].FRGCTL = frgctls[flexcomm_num];
}
}
#endif
return 0;
}
static DEVICE_API(clock_control, mcux_lpc_syscon_api) = {
.on = mcux_lpc_syscon_clock_control_on,
.off = mcux_lpc_syscon_clock_control_off,
.get_rate = mcux_lpc_syscon_clock_control_get_subsys_rate,
.set_rate = mcux_lpc_syscon_clock_control_set_subsys_rate,
.configure = mcux_lpc_syscon_clock_control_configure,
};
#define LPC_CLOCK_INIT(n) \
\
DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, NULL, PRE_KERNEL_1, \
CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &mcux_lpc_syscon_api);
DT_INST_FOREACH_STATUS_OKAY(LPC_CLOCK_INIT)