soc: nxp: Add MCXW71

Add MCXW71 SOC, which inherits some qualitiies
of kinetis heritage platforms.

Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
This commit is contained in:
Declan Snyder 2024-08-08 14:37:15 -05:00 committed by Maureen Helm
commit cbee39ef71
11 changed files with 333 additions and 1 deletions

View file

@ -0,0 +1,9 @@
# Copyright 2023 NXP
#
# SPDX-License-Identifier: Apache-2.0
zephyr_sources(soc.c mcxw71_platform_init.S)
zephyr_include_directories(.)
set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "")

16
soc/nxp/mcx/mcxw/Kconfig Normal file
View file

@ -0,0 +1,16 @@
# Copyright 2024 NXP
# SPDX-License-Identifier: Apache-2.0
config SOC_SERIES_MCXW
select ARM
select CPU_CORTEX_M33
select CPU_CORTEX_M_HAS_DWT
select ARM_TRUSTZONE_M
select CPU_CORTEX_M_HAS_SYSTICK
select CPU_HAS_FPU
select CPU_HAS_ARM_SAU
select CPU_HAS_ARM_MPU
select ARMV8_M_DSP
select HAS_MCUX
select PLATFORM_SPECIFIC_INIT
select CLOCK_CONTROL

View file

@ -0,0 +1,12 @@
# Copyright 2023-2024 NXP
# SPDX-License-Identifier: Apache-2.0
if SOC_SERIES_MCXW
config NUM_IRQS
default 76
config SYS_CLOCK_HW_CYCLES_PER_SEC
default 96000000 if CORTEX_M_SYSTICK
endif # SOC_SERIES_MCXW

View file

@ -0,0 +1,22 @@
# Copyright 2024 NXP
# SPDX-License-Identifier: Apache-2.0
config SOC_SERIES_MCXW
bool
select SOC_FAMILY_NXP_MCX
config SOC_SERIES
default "mcxw" if SOC_SERIES_MCXW
config SOC_MCXW716C
bool
select SOC_SERIES_MCXW
config SOC
default "mcxw716c" if SOC_MCXW716C
config SOC_PART_NUMBER_MCXW716CMFTA
bool
config SOC_PART_NUMBER
default "MCXW716CMFTA" if SOC_PART_NUMBER_MCXW716CMFTA

View file

@ -0,0 +1,25 @@
/*
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/devicetree.h>
m_sector_size = 0x2000;
m_flash_end = 0x000FFFFF;
m_fsl_prodInfo_size = m_sector_size;
m_fsl_prodInfo_start = m_flash_end - m_fsl_prodInfo_size + 1;
m_fsl_prodInfo_end = m_flash_end;
PROD_DATA_BASE_ADDR = m_fsl_prodInfo_start;
/*
* We perform all custom placement before including the generic linker file. This
* is done because calling this linker at the beginning will place some sections
* first, such as .noinit*, and this includes the rpmsg_sh_mem, which results
* in placing the rpmsg section in RAM instead of shared mem.
*/
#include <zephyr/arch/arm/cortex_m/scripts/linker.ld>

View file

@ -0,0 +1,59 @@
/*
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief MCXW71 Platform-Specific Initialization
*
* MCXW71 SOC reset code that initializes RAM
* to prevent ECC causing faults, and calls SystemInit
*/
#include <zephyr/toolchain.h>
#include <zephyr/linker/sections.h>
_ASM_FILE_PROLOGUE
#ifdef CONFIG_PLATFORM_SPECIFIC_INIT
GTEXT(z_arm_platform_init)
SECTION_SUBSEC_FUNC(TEXT,_reset_section,z_arm_platform_init)
.z_arm_platform_init:
ldr r0, =0x14000000
ldr r1, =.ram_init_ctcm01
bics r1, #0x10000000
cmp r0, r1
bcc .ram_init_done
.ram_init_ctcm01: /* Initialize ctcm01 */
ldr r0, =0x14000000
ldr r1, =0x14004000
ldr r2, =0
ldr r3, =0
ldr r4, =0
ldr r5, =0
.loop01:
stmia r0!, {r2 - r5}
cmp r0, r1
bcc .loop01
.ram_init_stcm012: /* Initialize stcm012 */
ldr r0, =0x30000000
ldr r1, =0x30010000
.loop012:
stmia r0!, {r2 - r5}
cmp r0, r1
bcc .loop012
.ram_init_stcm5:
ldr r0, =0x3001a000
ldr r1, =0x3001c000
.loop5: /* Initialize stcm5 */
stmia r0!, {r2 - r5}
cmp r0, r1
bcc .loop5
.ram_init_done:
b SystemInit
#endif /* CONFIG_PLATFORM_SPECIFIC_INIT */

View file

@ -0,0 +1,7 @@
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/pinctrl/pinctrl_soc_kinetis_common.h>

166
soc/nxp/mcx/mcxw/soc.c Normal file
View file

@ -0,0 +1,166 @@
/*
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/arch/cpu.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/linker/sections.h>
#include <soc.h>
#include <fsl_ccm32k.h>
#include <fsl_common.h>
#include <fsl_clock.h>
extern uint32_t SystemCoreClock;
static ALWAYS_INLINE void clock_init(void)
{
/* Unlock Reference Clock Status Registers to allow writes */
CLOCK_UnlockFircControlStatusReg();
CLOCK_UnlockSircControlStatusReg();
CLOCK_UnlockRoscControlStatusReg();
CLOCK_UnlockSysOscControlStatusReg();
/*
* Configuration for the 32 kHz Oscillator module
* Internal capatitor bank is required in order to use the more stable OSC32K source
*/
ccm32k_osc_config_t ccm32k_osc_config = {
.coarseAdjustment = kCCM32K_OscCoarseAdjustmentRange0, /* ESR_Range0 */
.enableInternalCapBank = true, /* Internal capacitance bank is enabled */
.xtalCap = kCCM32K_OscXtal8pFCap, /* 8 pF */
.extalCap = kCCM32K_OscExtal8pFCap, /* 8 pF */
};
/* Enable OSC32K */
CCM32K_Set32kOscConfig(CCM32K, kCCM32K_Enable32kHzCrystalOsc, &ccm32k_osc_config);
/* Disable ROSC Monitor, because switching the source would generate an expected error */
CLOCK_SetRoscMonitorMode(kSCG_RoscMonitorDisable);
/* Select the Real Time Clock (RTC) source as OSC32K */
CCM32K_SelectClockSource(CCM32K, kCCM32K_ClockSourceSelectOsc32k);
/* Wait for RTC Oscillator to be Valid */
while (!CLOCK_IsRoscValid())
;
/* Re-enable monitor */
CLOCK_SetRoscMonitorMode(kSCG_RoscMonitorInt);
/* Disable the FRO32K to save power */
CCM32K_Enable32kFro(CCM32K, false);
/* Configuration to set FIRC to maximum frequency */
scg_firc_config_t scg_firc_config = {
.enableMode = kSCG_FircEnable, /* Fast IRC is enabled */
.range = kSCG_FircRange96M, /* 96 Mhz FIRC clock selected */
.trimConfig = NULL,
};
scg_sys_clk_config_t sys_clk_safe_config_source = {
.divSlow = (uint32_t)kSCG_SysClkDivBy4,
.divCore = (uint32_t)kSCG_SysClkDivBy1,
.src = (uint32_t)kSCG_SysClkSrcSirc,
};
CLOCK_SetRunModeSysClkConfig(&sys_clk_safe_config_source);
scg_sys_clk_config_t cur_config;
do {
CLOCK_GetCurSysClkConfig(&cur_config);
} while (cur_config.src != sys_clk_safe_config_source.src);
(void)CLOCK_InitFirc(&scg_firc_config);
scg_sys_clk_config_t sys_clk_config = {
.divSlow = (uint32_t)kSCG_SysClkDivBy4, /* Slow Clock Divider: divided by 4 */
.divBus = (uint32_t)kSCG_SysClkDivBy1, /* Bus Clock Divider: divided by 1 */
.divCore = (uint32_t)kSCG_SysClkDivBy1, /* Core Clock Divider: divided by 1 */
.src = (uint32_t)kSCG_SysClkSrcFirc, /* Select Fast IRC as System Clock */
};
CLOCK_SetRunModeSysClkConfig(&sys_clk_config);
/* Wait for clock source switch to finish */
do {
CLOCK_GetCurSysClkConfig(&cur_config);
} while (cur_config.src != sys_clk_config.src);
SystemCoreClock = 96000000U;
/* OSC-RF / System Oscillator Configuration */
scg_sosc_config_t sosc_config = {
.freq = 32000U,
.monitorMode = kSCG_SysOscMonitorDisable,
.enableMode = kSCG_SoscEnable,
};
/* Init OSC-RF / SOSC */
(void)CLOCK_InitSysOsc(&sosc_config);
CLOCK_SetXtal0Freq(sosc_config.freq);
/* Slow internal reference clock (SIRC) configuration */
scg_sirc_config_t sirc_config = {
.enableMode = kSCG_SircDisableInSleep,
};
/* Init SIRC */
(void)CLOCK_InitSirc(&sirc_config);
/* Attach Clocks */
CLOCK_SetIpSrc(kCLOCK_Lpuart0, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrc(kCLOCK_Lpuart1, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrc(kCLOCK_Lpspi0, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrc(kCLOCK_Lpspi1, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrc(kCLOCK_Can0, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrc(kCLOCK_Tpm0, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrc(kCLOCK_Tpm1, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrc(kCLOCK_Lpi2c0, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrcDiv(kCLOCK_Lpi2c0, kSCG_SysClkDivBy16);
CLOCK_SetIpSrc(kCLOCK_Lpi2c1, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrcDiv(kCLOCK_Lpi2c1, kSCG_SysClkDivBy16);
/* Ungate clocks if the peripheral is enabled in devicetree */
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpuart0), nxp_lpc_lpuart, okay))
CLOCK_EnableClock(kCLOCK_Lpuart0);
#endif
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpuart1), nxp_lpc_lpuart, okay))
CLOCK_EnableClock(kCLOCK_Lpuart1);
#endif
}
static void vbat_init(void)
{
VBAT_Type *base = (VBAT_Type *)DT_REG_ADDR(DT_NODELABEL(vbat));
/* Write 1 to Clear POR detect status bit.
*
* Clearing this bit is acknowledement
* that software has recognized a power on reset.
*
* This avoids also niche issues with NVIC read/write
* when searching for available interrupt lines.
*/
base->STATUSA |= VBAT_STATUSA_POR_DET_MASK;
};
static int nxp_mcxw71_init(void)
{
unsigned int oldLevel; /* old interrupt lock level */
/* disable interrupts */
oldLevel = irq_lock();
/* Initialize system clock to 40 MHz */
clock_init();
/* Smart power switch initialization */
vbat_init();
/* restore interrupt state */
irq_unlock(oldLevel);
return 0;
}
SYS_INIT(nxp_mcxw71_init, PRE_KERNEL_1, 0);

13
soc/nxp/mcx/mcxw/soc.h Normal file
View file

@ -0,0 +1,13 @@
/*
* Copyright 2023 NXP
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SOC__H_
#define _SOC__H_
#include <fsl_port.h>
#define PORT_MUX_GPIO kPORT_MuxAsGpio
#endif /* _SOC__H_ */

View file

@ -17,6 +17,9 @@ family:
- name: mcxa
socs:
- name: mcxa156
- name: mcxw
socs:
- name: mcxw716c
runners:
run_once:
'--erase':

View file

@ -198,7 +198,7 @@ manifest:
groups:
- hal
- name: hal_nxp
revision: 17aac63df44266c4ea0e111c731ca7664fe51e70
revision: f4e26fad2cfd8b8e8988e835a28667573ed072cf
path: modules/hal/nxp
groups:
- hal