317 lines
11 KiB
C
317 lines
11 KiB
C
/*
|
|
* Copyright 2022-2024 NXP
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/arch/cpu.h>
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/drivers/uart.h>
|
|
#include <zephyr/init.h>
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/linker/sections.h>
|
|
#include <zephyr/sys/util_macro.h>
|
|
|
|
#include <cortex_m/exception.h>
|
|
#include <fsl_power.h>
|
|
#include <fsl_clock.h>
|
|
#include <fsl_common.h>
|
|
#include <fsl_device_registers.h>
|
|
#include "soc.h"
|
|
#include "flexspi_clock_setup.h"
|
|
#include "fsl_ocotp.h"
|
|
#ifdef CONFIG_NXP_RW6XX_BOOT_HEADER
|
|
extern char z_main_stack[];
|
|
extern char _flash_used[];
|
|
|
|
extern void z_arm_reset(void);
|
|
extern void z_arm_nmi(void);
|
|
extern void z_arm_hard_fault(void);
|
|
extern void z_arm_mpu_fault(void);
|
|
extern void z_arm_bus_fault(void);
|
|
extern void z_arm_usage_fault(void);
|
|
extern void z_arm_secure_fault(void);
|
|
extern void z_arm_svc(void);
|
|
extern void z_arm_debug_monitor(void);
|
|
extern void z_arm_pendsv(void);
|
|
extern void sys_clock_isr(void);
|
|
extern void z_arm_exc_spurious(void);
|
|
|
|
__imx_boot_ivt_section void (*const image_vector_table[])(void) = {
|
|
(void (*)())(z_main_stack + CONFIG_MAIN_STACK_SIZE), /* 0x00 */
|
|
z_arm_reset, /* 0x04 */
|
|
z_arm_nmi, /* 0x08 */
|
|
z_arm_hard_fault, /* 0x0C */
|
|
z_arm_mpu_fault, /* 0x10 */
|
|
z_arm_bus_fault, /* 0x14 */
|
|
z_arm_usage_fault, /* 0x18 */
|
|
#if defined(CONFIG_ARM_SECURE_FIRMWARE)
|
|
z_arm_secure_fault, /* 0x1C */
|
|
#else
|
|
z_arm_exc_spurious,
|
|
#endif /* CONFIG_ARM_SECURE_FIRMWARE */
|
|
(void (*)())_flash_used, /* 0x20, imageLength. */
|
|
0, /* 0x24, imageType (Plain Image) */
|
|
0, /* 0x28, authBlockOffset/crcChecksum */
|
|
z_arm_svc, /* 0x2C */
|
|
z_arm_debug_monitor, /* 0x30 */
|
|
(void (*)())image_vector_table, /* 0x34, imageLoadAddress. */
|
|
z_arm_pendsv, /* 0x38 */
|
|
#if defined(CONFIG_SYS_CLOCK_EXISTS) && defined(CONFIG_CORTEX_M_SYSTICK_INSTALL_ISR)
|
|
sys_clock_isr, /* 0x3C */
|
|
#else
|
|
z_arm_exc_spurious,
|
|
#endif
|
|
};
|
|
#endif /* CONFIG_NXP_RW6XX_BOOT_HEADER */
|
|
|
|
const clock_avpll_config_t avpll_config = {
|
|
.ch1Freq = kCLOCK_AvPllChFreq12p288m,
|
|
.ch2Freq = kCLOCK_AvPllChFreq64m,
|
|
.enableCali = true
|
|
};
|
|
|
|
/**
|
|
* @brief Initialize the system clocks and peripheral clocks
|
|
*
|
|
* This function is called from the power management code as the
|
|
* clock needs to be re-initialized on exit from Standby mode. Hence
|
|
* this function is relocated to RAM.
|
|
*/
|
|
__ramfunc void clock_init(void)
|
|
{
|
|
POWER_DisableGDetVSensors();
|
|
|
|
if ((PMU->CAU_SLP_CTRL & PMU_CAU_SLP_CTRL_SOC_SLP_RDY_MASK) == 0U) {
|
|
/* LPOSC not enabled, enable it */
|
|
CLOCK_EnableClock(kCLOCK_RefClkCauSlp);
|
|
}
|
|
if ((SYSCTL2->SOURCE_CLK_GATE & SYSCTL2_SOURCE_CLK_GATE_REFCLK_SYS_CG_MASK) != 0U) {
|
|
/* REFCLK_SYS not enabled, enable it */
|
|
CLOCK_EnableClock(kCLOCK_RefClkSys);
|
|
}
|
|
|
|
/* Initialize T3 clocks and t3pll_mci_48_60m_irc configured to 48.3MHz */
|
|
CLOCK_InitT3RefClk(kCLOCK_T3MciIrc48m);
|
|
/* Enable FFRO */
|
|
CLOCK_EnableClock(kCLOCK_T3PllMciIrcClk);
|
|
/* Enable T3 256M clock and SFRO */
|
|
CLOCK_EnableClock(kCLOCK_T3PllMci256mClk);
|
|
|
|
/* Move FLEXSPI clock source to T3 256m / 4 to avoid instruction/data fetch issue in XIP
|
|
* when updating PLL and main clock.
|
|
*/
|
|
set_flexspi_clock(FLEXSPI, 6U, 4U);
|
|
|
|
/* First let M33 run on SOSC */
|
|
CLOCK_AttachClk(kSYSOSC_to_MAIN_CLK);
|
|
CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1);
|
|
|
|
/* tcpu_mci_clk configured to 260MHz, tcpu_mci_flexspi_clk 312MHz. */
|
|
CLOCK_InitTcpuRefClk(3120000000UL, kCLOCK_TcpuFlexspiDiv10);
|
|
/* Enable tcpu_mci_clk 260MHz. Keep tcpu_mci_flexspi_clk gated. */
|
|
CLOCK_EnableClock(kCLOCK_TcpuMciClk);
|
|
|
|
/* tddr_mci_flexspi_clk 320MHz */
|
|
CLOCK_InitTddrRefClk(kCLOCK_TddrFlexspiDiv10);
|
|
CLOCK_EnableClock(kCLOCK_TddrMciFlexspiClk); /* 320MHz */
|
|
|
|
/* Enable AUX0 PLL to 260 MHz */
|
|
CLOCK_SetClkDiv(kCLOCK_DivAux0PllClk, 1U);
|
|
|
|
/* Init AVPLL and enable both channels */
|
|
CLOCK_InitAvPll(&avpll_config);
|
|
CLOCK_SetClkDiv(kCLOCK_DivAudioPllClk, 1U);
|
|
|
|
/* Configure MainPll to 260MHz, then let CM33 run on Main PLL. */
|
|
CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1U);
|
|
CLOCK_SetClkDiv(kCLOCK_DivMainPllClk, 1U);
|
|
CLOCK_AttachClk(kMAIN_PLL_to_MAIN_CLK);
|
|
|
|
/* Set SYSTICKFCLKDIV divider to value 1 */
|
|
CLOCK_SetClkDiv(kCLOCK_DivSystickClk, 1U);
|
|
CLOCK_AttachClk(kSYSTICK_DIV_to_SYSTICK_CLK);
|
|
|
|
/* Set PLL FRG clock to 20MHz. */
|
|
CLOCK_SetClkDiv(kCLOCK_DivPllFrgClk, 13U);
|
|
|
|
/* Call function set_flexspi_clock() to set flexspi clock source to aux0_pll_clk in XIP. */
|
|
set_flexspi_clock(FLEXSPI, 2U, 2U);
|
|
|
|
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(os_timer), nxp_os_timer, okay)
|
|
CLOCK_AttachClk(kLPOSC_to_OSTIMER_CLK);
|
|
#endif
|
|
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(wwdt), nxp_lpc_wwdt, okay))
|
|
CLOCK_AttachClk(kLPOSC_to_WDT0_CLK);
|
|
#else
|
|
/* Allowed to select none if not being used for watchdog to
|
|
* reduce power
|
|
*/
|
|
CLOCK_AttachClk(kNONE_to_WDT0_CLK);
|
|
#endif
|
|
|
|
#if defined(CONFIG_ADC_MCUX_GAU) || defined(CONFIG_DAC_MCUX_GAU)
|
|
/* Attack clock for GAU and reset */
|
|
CLOCK_AttachClk(kMAIN_CLK_to_GAU_CLK);
|
|
CLOCK_SetClkDiv(kCLOCK_DivGauClk, 1U);
|
|
CLOCK_EnableClock(kCLOCK_Gau);
|
|
RESET_PeripheralReset(kGAU_RST_SHIFT_RSTn);
|
|
#endif /* GAU */
|
|
|
|
/* Any flexcomm can be USART */
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_usart, okay)) && CONFIG_SERIAL
|
|
CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){0, kCLOCK_FrgPllDiv, 255, 0});
|
|
CLOCK_AttachClk(kFRG_to_FLEXCOMM0);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm1), nxp_lpc_usart, okay)) && CONFIG_SERIAL
|
|
CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){1, kCLOCK_FrgPllDiv, 255, 0});
|
|
CLOCK_AttachClk(kFRG_to_FLEXCOMM1);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm2), nxp_lpc_usart, okay)) && CONFIG_SERIAL
|
|
CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){2, kCLOCK_FrgPllDiv, 255, 0});
|
|
CLOCK_AttachClk(kFRG_to_FLEXCOMM2);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm3), nxp_lpc_usart, okay)) && CONFIG_SERIAL
|
|
CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){3, kCLOCK_FrgPllDiv, 255, 0});
|
|
CLOCK_AttachClk(kFRG_to_FLEXCOMM3);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm14), nxp_lpc_usart, okay)) && CONFIG_SERIAL
|
|
CLOCK_SetFRGClock(&(const clock_frg_clk_config_t){14, kCLOCK_FrgPllDiv, 255, 0});
|
|
CLOCK_AttachClk(kFRG_to_FLEXCOMM14);
|
|
#endif
|
|
|
|
/* Any flexcomm can be I2C */
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_i2c, okay)) && CONFIG_I2C
|
|
CLOCK_AttachClk(kSFRO_to_FLEXCOMM0);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm1), nxp_lpc_i2c, okay)) && CONFIG_I2C
|
|
CLOCK_AttachClk(kSFRO_to_FLEXCOMM1);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm2), nxp_lpc_i2c, okay)) && CONFIG_I2C
|
|
CLOCK_AttachClk(kSFRO_to_FLEXCOMM2);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm3), nxp_lpc_i2c, okay)) && CONFIG_I2C
|
|
CLOCK_AttachClk(kSFRO_to_FLEXCOMM3);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm14), nxp_lpc_i2c, okay)) && CONFIG_I2C
|
|
CLOCK_AttachClk(kSFRO_to_FLEXCOMM14);
|
|
#endif
|
|
|
|
/* Clock flexcomms when used as SPI */
|
|
#ifdef CONFIG_SPI
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm0), nxp_lpc_spi, okay))
|
|
/* Set up Flexcomm0 FRG to clock at 260 MHz from main clock */
|
|
const clock_frg_clk_config_t flexcomm0_frg = {0, kCLOCK_FrgMainClk, 255, 0};
|
|
|
|
CLOCK_SetFRGClock(&flexcomm0_frg);
|
|
CLOCK_AttachClk(kFRG_to_FLEXCOMM0);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm1), nxp_lpc_spi, okay))
|
|
CLOCK_AttachClk(kSFRO_to_FLEXCOMM1);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm2), nxp_lpc_spi, okay))
|
|
CLOCK_AttachClk(kSFRO_to_FLEXCOMM2);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm3), nxp_lpc_spi, okay))
|
|
CLOCK_AttachClk(kSFRO_to_FLEXCOMM3);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm14), nxp_lpc_spi, okay))
|
|
CLOCK_AttachClk(kSFRO_to_FLEXCOMM14);
|
|
#endif
|
|
#endif /* CONFIG_SPI */
|
|
|
|
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dmic0)) && CONFIG_AUDIO_DMIC_MCUX
|
|
/* Clock DMIC from Audio PLL. PLL output is sourced from AVPLL
|
|
* channel 1, which is clocked at 12.288 MHz. We can divide this
|
|
* by 4 to achieve the desired DMIC bit clk of 3.072 MHz
|
|
*/
|
|
CLOCK_AttachClk(kAUDIO_PLL_to_DMIC_CLK);
|
|
CLOCK_SetClkDiv(kCLOCK_DivDmicClk, 4);
|
|
#endif
|
|
|
|
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(lcdic)) && CONFIG_MIPI_DBI_NXP_LCDIC
|
|
CLOCK_AttachClk(kMAIN_CLK_to_LCD_CLK);
|
|
RESET_PeripheralReset(kLCDIC_RST_SHIFT_RSTn);
|
|
#endif
|
|
|
|
#ifdef CONFIG_COUNTER_MCUX_CTIMER
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ctimer0), nxp_lpc_ctimer, okay))
|
|
CLOCK_AttachClk(kSFRO_to_CTIMER0);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ctimer1), nxp_lpc_ctimer, okay))
|
|
CLOCK_AttachClk(kSFRO_to_CTIMER1);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ctimer2), nxp_lpc_ctimer, okay))
|
|
CLOCK_AttachClk(kSFRO_to_CTIMER2);
|
|
#endif
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(ctimer3), nxp_lpc_ctimer, okay))
|
|
CLOCK_AttachClk(kSFRO_to_CTIMER3);
|
|
#endif
|
|
#endif /* CONFIG_COUNTER_MCUX_CTIMER */
|
|
|
|
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(usb_otg)) && CONFIG_USB_DC_NXP_EHCI
|
|
/* Enable system xtal from Analog */
|
|
SYSCTL2->ANA_GRP_CTRL |= SYSCTL2_ANA_GRP_CTRL_PU_AG_MASK;
|
|
/* reset USB */
|
|
RESET_PeripheralReset(kUSB_RST_SHIFT_RSTn);
|
|
/* enable usb clock */
|
|
CLOCK_EnableClock(kCLOCK_Usb);
|
|
/* enable usb phy clock */
|
|
CLOCK_EnableUsbhsPhyClock();
|
|
#endif
|
|
|
|
#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(enet)) && CONFIG_NET_L2_ETHERNET
|
|
RESET_PeripheralReset(kENET_IPG_RST_SHIFT_RSTn);
|
|
RESET_PeripheralReset(kENET_IPG_S_RST_SHIFT_RSTn);
|
|
#endif
|
|
|
|
}
|
|
|
|
extern void nxp_rw6xx_power_init(void);
|
|
/**
|
|
*
|
|
* @brief Perform basic hardware initialization
|
|
*
|
|
* Initialize the interrupt controller device drivers.
|
|
* Also initialize the timer device driver, if required.
|
|
*/
|
|
|
|
void soc_early_init_hook(void)
|
|
{
|
|
#if (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(wwdt), nxp_lpc_wwdt, okay))
|
|
POWER_EnableResetSource(kPOWER_ResetSourceWdt);
|
|
#endif
|
|
|
|
#if DT_NODE_HAS_PROP(DT_NODELABEL(pmu), reset_causes_en)
|
|
#define PMU_RESET_CAUSES_ \
|
|
DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(pmu), reset_causes_en, DT_PROP_BY_IDX, (|))
|
|
#define PMU_RESET_CAUSES \
|
|
COND_CODE_0(IS_EMPTY(PMU_RESET_CAUSES_), (PMU_RESET_CAUSES_), (0))
|
|
#define WDT_RESET \
|
|
COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(wwdt), (kPOWER_ResetSourceWdt), (0))
|
|
#define RESET_CAUSES \
|
|
(PMU_RESET_CAUSES | WDT_RESET)
|
|
#else
|
|
#define RESET_CAUSES 0
|
|
#endif
|
|
|
|
POWER_EnableResetSource(RESET_CAUSES);
|
|
|
|
/* Initialize clock */
|
|
clock_init();
|
|
|
|
#if defined(CONFIG_ADC_MCUX_GAU) || defined(CONFIG_DAC_MCUX_GAU)
|
|
POWER_PowerOnGau();
|
|
#endif
|
|
#if CONFIG_PM
|
|
nxp_rw6xx_power_init();
|
|
#endif
|
|
}
|
|
|
|
void soc_reset_hook(void)
|
|
{
|
|
/* This is provided by the SDK */
|
|
SystemInit();
|
|
}
|