Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/clock_control/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SI32_AHB clock_cont
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SI32_APB clock_control_si32_apb.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SMARTBOND clock_control_smartbond.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NUMAKER_SCC clock_control_numaker_scc.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NXP_MC_CGM clock_control_nxp_mc_cgm.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NXP_S32 clock_control_nxp_s32.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RENESAS_RA_CGC clock_control_renesas_ra_cgc.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RENESAS_RX_ROOT clock_control_renesas_rx_root_cgc.c)
Expand Down
2 changes: 2 additions & 0 deletions drivers/clock_control/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ source "drivers/clock_control/Kconfig.smartbond"

source "drivers/clock_control/Kconfig.numaker"

source "drivers/clock_control/Kconfig.nxp_mc_cgm"

source "drivers/clock_control/Kconfig.nxp_s32"

source "drivers/clock_control/Kconfig.agilex5"
Expand Down
9 changes: 9 additions & 0 deletions drivers/clock_control/Kconfig.nxp_mc_cgm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright 2025 NXP
# SPDX-License-Identifier: Apache-2.0

config CLOCK_CONTROL_NXP_MC_CGM
bool "NXP MC_CGM clock driver"
default y
depends on DT_HAS_NXP_MC_CGM_ENABLED
help
Enable support for NXP MC_CGM clock driver.
314 changes: 314 additions & 0 deletions drivers/clock_control/clock_control_nxp_mc_cgm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
/*
* Copyright 2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT nxp_mc_cgm

#include <errno.h>
#include <zephyr/drivers/clock_control/nxp_clock_control.h>
#include <fsl_clock.h>

#define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(clock_control);

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(fxosc), nxp_fxosc, okay)
const fxosc_config_t fxosc_config = {.freqHz = NXP_FXOSC_FREQ,
.workMode = NXP_FXOSC_WORKMODE,
.startupDelay = NXP_FXOSC_DELAY,
.overdriveProtect = NXP_FXOSC_OVERDRIVE};
#endif

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), nxp_plldig, okay)
const pll_config_t pll_config = {.workMode = NXP_PLL_WORKMODE,
.preDiv = NXP_PLL_PREDIV, /* PLL input clock predivider: 2 */
.postDiv = NXP_PLL_POSTDIV,
.multiplier = NXP_PLL_MULTIPLIER,
.fracLoopDiv = NXP_PLL_FRACLOOPDIV,
.stepSize = NXP_PLL_STEPSIZE,
.stepNum = NXP_PLL_STEPNUM,
.accuracy = NXP_PLL_ACCURACY,
.outDiv = NXP_PLL_OUTDIV_POINTER};
#endif

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(mc_cgm), nxp_mc_cgm, okay)
const clock_pcfs_config_t pcfs_config = {.maxAllowableIDDchange = NXP_PLL_MAXIDOCHANGE,
.stepDuration = NXP_PLL_STEPDURATION,
.clkSrcFreq = NXP_PLL_CLKSRCFREQ};
#endif

static int mc_cgm_clock_control_on(const struct device *dev, clock_control_subsys_t sub_system)
{
#if defined(CONFIG_CAN_MCUX_FLEXCAN)
switch ((uint32_t)sub_system) {
case MCUX_FLEXCAN0_CLK:
CLOCK_EnableClock(kCLOCK_Flexcan0);
break;
case MCUX_FLEXCAN1_CLK:
CLOCK_EnableClock(kCLOCK_Flexcan1);
break;
case MCUX_FLEXCAN2_CLK:
CLOCK_EnableClock(kCLOCK_Flexcan2);
break;
case MCUX_FLEXCAN3_CLK:
CLOCK_EnableClock(kCLOCK_Flexcan3);
break;
case MCUX_FLEXCAN4_CLK:
CLOCK_EnableClock(kCLOCK_Flexcan4);
break;
case MCUX_FLEXCAN5_CLK:
CLOCK_EnableClock(kCLOCK_Flexcan5);
break;
default:
break;
}
#endif /* defined(CONFIG_CAN_MCUX_MCAN) */

#if defined(CONFIG_UART_MCUX_LPUART)
switch ((uint32_t)sub_system) {
case MCUX_LPUART0_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart0);
break;
case MCUX_LPUART1_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart1);
break;
case MCUX_LPUART2_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart2);
break;
case MCUX_LPUART3_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart3);
break;
case MCUX_LPUART4_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart4);
break;
case MCUX_LPUART5_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart5);
break;
case MCUX_LPUART6_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart6);
break;
case MCUX_LPUART7_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart7);
break;
case MCUX_LPUART8_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart8);
break;
case MCUX_LPUART9_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart9);
break;
case MCUX_LPUART10_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart10);
break;
case MCUX_LPUART11_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart11);
break;
case MCUX_LPUART12_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart12);
break;
case MCUX_LPUART13_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart13);
break;
case MCUX_LPUART14_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart14);
break;
case MCUX_LPUART15_CLK:
CLOCK_EnableClock(kCLOCK_Lpuart15);
break;
default:
break;
}
#endif /* defined(CONFIG_UART_MCUX_LPUART) */

#if defined(CONFIG_SPI_NXP_LPSPI)
switch ((uint32_t)sub_system) {
case MCUX_LPSPI0_CLK:
CLOCK_EnableClock(kCLOCK_Lpspi0);
break;
case MCUX_LPSPI1_CLK:
CLOCK_EnableClock(kCLOCK_Lpspi1);
break;
case MCUX_LPSPI2_CLK:
CLOCK_EnableClock(kCLOCK_Lpspi2);
break;
case MCUX_LPSPI3_CLK:
CLOCK_EnableClock(kCLOCK_Lpspi3);
break;
case MCUX_LPSPI4_CLK:
CLOCK_EnableClock(kCLOCK_Lpspi4);
break;
case MCUX_LPSPI5_CLK:
CLOCK_EnableClock(kCLOCK_Lpspi5);
break;
default:
break;
}
#endif /* defined(CONFIG_SPI_NXP_LPSPI) */

#if defined(CONFIG_I2C_MCUX_LPI2C)
switch ((uint32_t)sub_system) {
case MCUX_LPI2C0_CLK:
CLOCK_EnableClock(kCLOCK_Lpi2c0);
break;
case MCUX_LPI2C1_CLK:
CLOCK_EnableClock(kCLOCK_Lpi2c1);
break;
default:
break;
}
#endif /* defined(CONFIG_I2C_MCUX_LPI2C) */

return 0;
}

static int mc_cgm_clock_control_off(const struct device *dev, clock_control_subsys_t sub_system)
{
return 0;
}

static int mc_cgm_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_UART_MCUX_LPUART)
case MCUX_LPUART0_CLK:
case MCUX_LPUART8_CLK:
*rate = CLOCK_GetAipsPlatClkFreq();
break;
case MCUX_LPUART1_CLK:
case MCUX_LPUART2_CLK:
case MCUX_LPUART3_CLK:
case MCUX_LPUART4_CLK:
case MCUX_LPUART5_CLK:
case MCUX_LPUART6_CLK:
case MCUX_LPUART7_CLK:
case MCUX_LPUART9_CLK:
case MCUX_LPUART10_CLK:
case MCUX_LPUART11_CLK:
case MCUX_LPUART12_CLK:
case MCUX_LPUART13_CLK:
case MCUX_LPUART14_CLK:
case MCUX_LPUART15_CLK:
*rate = CLOCK_GetAipsSlowClkFreq();
break;
#endif /* defined(CONFIG_UART_MCUX_LPUART) */

#if defined(CONFIG_SPI_NXP_LPSPI)
case MCUX_LPSPI0_CLK:
*rate = CLOCK_GetAipsPlatClkFreq();
break;
case MCUX_LPSPI1_CLK:
case MCUX_LPSPI2_CLK:
case MCUX_LPSPI3_CLK:
case MCUX_LPSPI4_CLK:
case MCUX_LPSPI5_CLK:
*rate = CLOCK_GetAipsSlowClkFreq();
break;
#endif /* defined(CONFIG_SPI_NXP_LPSPI) */

#if defined(CONFIG_I2C_MCUX_LPI2C)
case MCUX_LPI2C0_CLK:
case MCUX_LPI2C1_CLK:
*rate = CLOCK_GetAipsSlowClkFreq();
break;
#endif /* defined(CONFIG_I2C_MCUX_LPI2C) */

#if defined(CONFIG_CAN_MCUX_FLEXCAN)
case MCUX_FLEXCAN0_CLK:
*rate = CLOCK_GetFlexcanPeClkFreq(0);
break;
case MCUX_FLEXCAN1_CLK:
*rate = CLOCK_GetFlexcanPeClkFreq(1);
break;
case MCUX_FLEXCAN2_CLK:
*rate = CLOCK_GetFlexcanPeClkFreq(2);
break;
case MCUX_FLEXCAN3_CLK:
*rate = CLOCK_GetFlexcanPeClkFreq(3);
break;
case MCUX_FLEXCAN4_CLK:
*rate = CLOCK_GetFlexcanPeClkFreq(4);
break;
case MCUX_FLEXCAN5_CLK:
*rate = CLOCK_GetFlexcanPeClkFreq(5);
break;
#endif /* defined(CONFIG_CAN_MCUX_FLEXCAN) */
}
return 0;
}

static int mc_cgm_init(const struct device *dev)
{
#if defined(FSL_FEATURE_PMC_HAS_LAST_MILE_REGULATOR) && (FSL_FEATURE_PMC_HAS_LAST_MILE_REGULATOR)
/* Enables PMC last mile regulator before enable PLL. */
if ((PMC->LVSC & PMC_LVSC_LVD15S_MASK) != 0U) {
/* External bipolar junction transistor is connected between external voltage and
* V15 input pin.
*/
PMC->CONFIG |= PMC_CONFIG_LMBCTLEN_MASK;
}
while ((PMC->LVSC & PMC_LVSC_LVD15S_MASK) != 0U) {
}
PMC->CONFIG |= PMC_CONFIG_LMEN_MASK;
while ((PMC->CONFIG & PMC_CONFIG_LMSTAT_MASK) == 0u) {
}
#endif /* FSL_FEATURE_PMC_HAS_LAST_MILE_REGULATOR */

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(firc), nxp_firc, okay)
/* Switch the FIRC_DIV_SEL to the desired diveder. */
CLOCK_SetFircDiv(NXP_FIRC_DIV);
/* Disable FIRC in standby mode. */
CLOCK_DisableFircInStandbyMode();
#endif

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(sirc), nxp_sirc, okay)
/* Disable SIRC in standby mode. */
CLOCK_DisableSircInStandbyMode();
#endif

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(fxosc), nxp_fxosc, okay)
/* Enable FXOSC. */
CLOCK_InitFxosc(&fxosc_config);
#endif

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), nxp_plldig, okay)
/* Enable PLL. */
CLOCK_InitPll(&pll_config);
#endif

#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(mc_cgm), nxp_mc_cgm, okay)
CLOCK_SelectSafeClock(kFIRC_CLK_to_MUX0);
/* Configure MUX_0_CSC dividers */
CLOCK_SetClkMux0DivTriggerType(KCLOCK_CommonTriggerUpdate);
CLOCK_SetClkDiv(kCLOCK_DivCoreClk, NXP_PLL_MUX_0_DC_0_DIV);
CLOCK_SetClkDiv(kCLOCK_DivAipsPlatClk, NXP_PLL_MUX_0_DC_1_DIV);
CLOCK_SetClkDiv(kCLOCK_DivAipsSlowClk, NXP_PLL_MUX_0_DC_2_DIV);
CLOCK_SetClkDiv(kCLOCK_DivHseClk, NXP_PLL_MUX_0_DC_3_DIV);
CLOCK_SetClkDiv(kCLOCK_DivDcmClk, NXP_PLL_MUX_0_DC_4_DIV);
#ifdef MC_CGM_MUX_0_DC_5_DIV_MASK
CLOCK_SetClkDiv(kCLOCK_DivLbistClk, NXP_PLL_MUX_0_DC_5_DIV);
#endif
#ifdef MC_CGM_MUX_0_DC_6_DIV_MASK
CLOCK_SetClkDiv(kCLOCK_DivQspiClk, NXP_PLL_MUX_0_DC_6_DIV);
#endif
CLOCK_CommonTriggerClkMux0DivUpdate();
CLOCK_ProgressiveClockFrequencySwitch(kPLL_PHI0_CLK_to_MUX0, &pcfs_config);
#endif

/* Set SystemCoreClock variable. */
SystemCoreClockUpdate();

return 0;
}

static DEVICE_API(clock_control, mcux_mcxe31x_clock_api) = {
.on = mc_cgm_clock_control_on,
.off = mc_cgm_clock_control_off,
.get_rate = mc_cgm_get_subsys_rate,
};

DEVICE_DT_INST_DEFINE(0, mc_cgm_init, NULL, NULL, NULL, PRE_KERNEL_1,
CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &mcux_mcxe31x_clock_api);
2 changes: 1 addition & 1 deletion drivers/interrupt_controller/Kconfig.nxp_siul2
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ if NXP_SIUL2_EIRQ
config NXP_SIUL2_EIRQ_EXT_INTERRUPTS_MAX
int
default 8 if SOC_SERIES_S32ZE
default 32 if SOC_SERIES_S32K3
default 32 if SOC_SERIES_S32K3 || SOC_SERIES_MCXE31X
help
Number of SIUL2 external interrupts per controller. This is a SoC
integration option.
Expand Down
9 changes: 8 additions & 1 deletion drivers/interrupt_controller/intc_nxp_siul2_eirq.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,20 @@
#define SIUL2_IFER0 0x28
/* SIUL2 Interrupt Filter Maximum Counter Register */
#define SIUL2_IFMCR(n) (0x30 + 0x4 * (n))
#ifndef SIUL2_IFMCR_MAXCNT_MASK
#define SIUL2_IFMCR_MAXCNT_MASK GENMASK(3, 0)
#endif
#ifndef SIUL2_IFMCR_MAXCNT
#define SIUL2_IFMCR_MAXCNT(v) FIELD_PREP(SIUL2_IFMCR_MAXCNT_MASK, (v))
#endif
/* SIUL2 Interrupt Filter Clock Prescaler Register */
#define SIUL2_IFCPR 0xb0
#ifndef SIUL2_IFCPR_IFCP_MASK
#define SIUL2_IFCPR_IFCP_MASK GENMASK(3, 0)
#endif
#ifndef SIUL2_IFCPR_IFCP
#define SIUL2_IFCPR_IFCP(v) FIELD_PREP(SIUL2_IFCPR_IFCP_MASK, (v))

#endif
/* Handy accessors */
#define REG_READ(r) sys_read32(config->base + (r))
#define REG_WRITE(r, v) sys_write32((v), config->base + (r))
Expand Down
3 changes: 2 additions & 1 deletion drivers/pinctrl/Kconfig.nxp_siul2
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
config PINCTRL_NXP_SIUL2
bool "Pin controller driver for NXP SIUL2"
default y
depends on DT_HAS_NXP_S32ZE_SIUL2_PINCTRL_ENABLED || DT_HAS_NXP_S32K3_SIUL2_PINCTRL_ENABLED
depends on DT_HAS_NXP_S32ZE_SIUL2_PINCTRL_ENABLED || DT_HAS_NXP_S32K3_SIUL2_PINCTRL_ENABLED || \
DT_HAS_NXP_MCXE31X_SIUL2_PINCTRL_ENABLED
help
Enable pin controller driver for NXP SIUL2.
Loading