This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit d4a3d255a4d1ae5d68213ca3de01be2bc2bd8b38 Author: Jukka Laitinen <[email protected]> AuthorDate: Tue Sep 1 15:16:12 2026 +0300 arch/arm/src/imxrt: Add the clock configuration for iMXRT118x Port the ccm / clock configuration from iMX93 to iMXRT118x. Register definitions are generated from RM using AI Assisted-by: Claude Code:claude-opus-4-7 Signed-off-by: Jukka Laitinen <[email protected]> --- arch/arm/src/imxrt/CMakeLists.txt | 4 +- arch/arm/src/imxrt/Kconfig | 8 + arch/arm/src/imxrt/Make.defs | 4 +- arch/arm/src/imxrt/hardware/imxrt_ccm.h | 2 + arch/arm/src/imxrt/hardware/imxrt_dcdc.h | 40 ++ arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ccm.h | 495 ++++++++++++++++++ arch/arm/src/imxrt/imxrt_clockconfig.h | 4 +- arch/arm/src/imxrt/imxrt_clockconfig_ver3.c | 566 +++++++++++++++++++++ arch/arm/src/imxrt/imxrt_clockconfig_ver3.h | 149 ++++++ arch/arm/src/imxrt/imxrt_periphclks.h | 13 + 10 files changed, 1282 insertions(+), 3 deletions(-) diff --git a/arch/arm/src/imxrt/CMakeLists.txt b/arch/arm/src/imxrt/CMakeLists.txt index 9db635e40b0..97d6de363ee 100644 --- a/arch/arm/src/imxrt/CMakeLists.txt +++ b/arch/arm/src/imxrt/CMakeLists.txt @@ -45,7 +45,9 @@ list( # Configuration-dependent i.MX RT files -if(CONFIG_IMXRT_CLOCKCONFIG_VER2) +if(CONFIG_IMXRT_CLOCKCONFIG_VER3) + list(APPEND SRCS imxrt_clockconfig_ver3.c) +elseif(CONFIG_IMXRT_CLOCKCONFIG_VER2) list(APPEND SRCS imxrt_clockconfig_ver2.c imxrt_pmu.c) else() list(APPEND SRCS imxrt_clockconfig_ver1.c) diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig index 54b88f9b130..572038e2b58 100644 --- a/arch/arm/src/imxrt/Kconfig +++ b/arch/arm/src/imxrt/Kconfig @@ -232,6 +232,7 @@ config ARCH_FAMILY_IMXRT118x select IMXRT_HAVE_LPUART10 select IMXRT_HAVE_LPUART11 select IMXRT_HAVE_LPUART12 + select IMXRT_CLOCKCONFIG_VER3 ---help--- i.MX RT1180 dual-core Crossover Processors (Cortex-M33 + Cortex-M7). @@ -403,6 +404,13 @@ config IMXRT_CLOCKCONFIG_VER2 bool default n +config IMXRT_CLOCKCONFIG_VER3 + bool + default n + ---help--- + Selects the RT118x-family clock configuration + (arch/arm/src/imxrt/imxrt_clockconfig_ver3.c). + config IMXRT_IOMUX_VER2 bool default n diff --git a/arch/arm/src/imxrt/Make.defs b/arch/arm/src/imxrt/Make.defs index 5004a0d8fda..48a80b806eb 100644 --- a/arch/arm/src/imxrt/Make.defs +++ b/arch/arm/src/imxrt/Make.defs @@ -40,7 +40,9 @@ CHIP_CSRCS += imxrt_xbar.c imxrt_ocotp.c imxrt_lowputc.c # Configuration-dependent i.MX RT files -ifeq ($(CONFIG_IMXRT_CLOCKCONFIG_VER2),y) +ifeq ($(CONFIG_IMXRT_CLOCKCONFIG_VER3),y) +CHIP_CSRCS += imxrt_clockconfig_ver3.c +else ifeq ($(CONFIG_IMXRT_CLOCKCONFIG_VER2),y) CHIP_CSRCS += imxrt_clockconfig_ver2.c imxrt_pmu.c else CHIP_CSRCS += imxrt_clockconfig_ver1.c diff --git a/arch/arm/src/imxrt/hardware/imxrt_ccm.h b/arch/arm/src/imxrt/hardware/imxrt_ccm.h index e09544f02a2..4775c73c7b3 100644 --- a/arch/arm/src/imxrt/hardware/imxrt_ccm.h +++ b/arch/arm/src/imxrt/hardware/imxrt_ccm.h @@ -38,6 +38,8 @@ # include "hardware/rt106x/imxrt106x_ccm.h" #elif defined(CONFIG_ARCH_FAMILY_IMXRT117x) # include "hardware/rt117x/imxrt117x_ccm.h" +#elif defined(CONFIG_ARCH_FAMILY_IMXRT118x) +# include "hardware/rt118x/imxrt118x_ccm.h" #else # error Unrecognized i.MX RT architecture #endif diff --git a/arch/arm/src/imxrt/hardware/imxrt_dcdc.h b/arch/arm/src/imxrt/hardware/imxrt_dcdc.h index 2569b4f05f2..e7ef6a1bf93 100644 --- a/arch/arm/src/imxrt/hardware/imxrt_dcdc.h +++ b/arch/arm/src/imxrt/hardware/imxrt_dcdc.h @@ -136,4 +136,44 @@ #define DCDC_REG3_DISABLE_STEP (1 << 30) /* Bit 30: Disable stepping */ /* Bit 31: Reserved */ +#ifdef CONFIG_ARCH_FAMILY_IMXRT118x + +/* i.MX RT118x adds per-core target control registers (IMXRT1180RM Rev. 10 + * sec. 22.7.1.11 / 22.7.1.13). Both cores share a single VDD1P0 rail: the + * DCDC applies the *higher* of the TRG_SW_0 and TRG_SW_1 voltage targets, + * so a core that needs the higher voltage must raise both. + */ + +#define IMXRT_DCDC_TRG_SW_0_OFFSET 0x0024 /* Target SW control, CORE 0 */ +#define IMXRT_DCDC_TRG_SW_1_OFFSET 0x0034 /* Target SW control, CORE 1 */ +#define IMXRT_DCDC_CURRENT_TRG_OFFSET 0x0018 /* Arbitrated target in use */ + +#define IMXRT_DCDC_TRG_SW_0 (IMXRT_DCDC_BASE + IMXRT_DCDC_TRG_SW_0_OFFSET) +#define IMXRT_DCDC_TRG_SW_1 (IMXRT_DCDC_BASE + IMXRT_DCDC_TRG_SW_1_OFFSET) +#define IMXRT_DCDC_CURRENT_TRG (IMXRT_DCDC_BASE + IMXRT_DCDC_CURRENT_TRG_OFFSET) + +/* TRG_SW_0 / TRG_SW_1 (reset value 0010_0C10h) */ + +#define DCDC_TRG_SW_VDD1P0CTRL_TRG_SHIFT (0) /* Bits 0-4: VDD1P0 run mode target */ +#define DCDC_TRG_SW_VDD1P0CTRL_TRG_MASK (0x1f << DCDC_TRG_SW_VDD1P0CTRL_TRG_SHIFT) +# define DCDC_TRG_SW_VDD1P0CTRL_TRG(n) ((uint32_t)(n) << DCDC_TRG_SW_VDD1P0CTRL_TRG_SHIFT) +#define DCDC_TRG_SW_VDD1P8CTRL_TRG_SHIFT (8) /* Bits 8-12: VDD1P8 run mode target */ +#define DCDC_TRG_SW_VDD1P8CTRL_TRG_MASK (0x1f << DCDC_TRG_SW_VDD1P8CTRL_TRG_SHIFT) +#define DCDC_TRG_SW_VDD1P0CTRL_LP_TRG_SHIFT (16) /* Bits 16-20: VDD1P0 low power target */ +#define DCDC_TRG_SW_VDD1P0CTRL_LP_TRG_MASK (0x1f << DCDC_TRG_SW_VDD1P0CTRL_LP_TRG_SHIFT) +#define DCDC_TRG_SW_LP_EN_1P0 (1 << 31) /* Bit 31: Low power enable */ + +/* CURRENT_TRG: arbitrated target actually applied by the DCDC analog */ + +#define DCDC_CURRENT_TRG_VDD1P0CTRL_TRG_SHIFT (0) /* Bits 0-4 */ +#define DCDC_CURRENT_TRG_VDD1P0CTRL_TRG_MASK (0x1f << DCDC_CURRENT_TRG_VDD1P0CTRL_TRG_SHIFT) +#define DCDC_CURRENT_TRG_DCDC_UPDATING (1 << 15) /* Bit 15: change in progress */ + +/* VDD1P0 target encoding: 25 mV per step, 0x00 = 0.6 V, 0x10 = 1.0 V */ + +#define DCDC_1P0_TARGET_1P000V (0x10) +#define DCDC_1P0_TARGET_1P125V (0x15) /* HSRUN / OverDrive */ + +#endif /* CONFIG_ARCH_FAMILY_IMXRT118x */ + #endif /* __ARCH_ARM_SRC_IMXRT_HARDWARE_IMXRT_DCDC_H */ diff --git a/arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ccm.h b/arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ccm.h new file mode 100644 index 00000000000..8928c5e5826 --- /dev/null +++ b/arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ccm.h @@ -0,0 +1,495 @@ +/**************************************************************************** + * arch/arm/src/imxrt/hardware/rt118x/imxrt118x_ccm.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_IMXRT_HARDWARE_RT118X_IMXRT118X_CCM_H +#define __ARCH_ARM_SRC_IMXRT_HARDWARE_RT118X_IMXRT118X_CCM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "hardware/imxrt_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets *********************************************************/ + +#define IMXRT_CCM_CR_CTRL_OFFSET(n) (0x0000 + ((n) << 7)) +#define IMXRT_CCM_CR_CTRL_SET_OFFSET(n) (0x0004 + ((n) << 7)) +#define IMXRT_CCM_CR_CTRL_CLR_OFFSET(n) (0x0008 + ((n) << 7)) +#define IMXRT_CCM_CR_CTRL_TOG_OFFSET(n) (0x000c + ((n) << 7)) +#define IMXRT_CCM_CR_STAT0_OFFSET(n) (0x0020 + ((n) << 7)) +#define IMXRT_CCM_CR_AUTH_OFFSET(n) (0x0030 + ((n) << 7)) + +#define IMXRT_CCM_LPCG_DIR_OFFSET(n) (0x8000 + ((n) << 6)) +#define IMXRT_CCM_LPCG_STAT0_OFFSET(n) (0x8020 + ((n) << 6)) +#define IMXRT_CCM_LPCG_AUTH_OFFSET(n) (0x8030 + ((n) << 6)) + +/* Register addresses *******************************************************/ + +#define IMXRT_CCM_CR_CTRL(n) \ + (IMXRT_CCM_BASE + IMXRT_CCM_CR_CTRL_OFFSET(n)) +#define IMXRT_CCM_CR_CTRL_SET(n) \ + (IMXRT_CCM_BASE + IMXRT_CCM_CR_CTRL_SET_OFFSET(n)) +#define IMXRT_CCM_CR_CTRL_CLR(n) \ + (IMXRT_CCM_BASE + IMXRT_CCM_CR_CTRL_CLR_OFFSET(n)) +#define IMXRT_CCM_CR_CTRL_TOG(n) \ + (IMXRT_CCM_BASE + IMXRT_CCM_CR_CTRL_TOG_OFFSET(n)) +#define IMXRT_CCM_CR_STAT0(n) \ + (IMXRT_CCM_BASE + IMXRT_CCM_CR_STAT0_OFFSET(n)) +#define IMXRT_CCM_CR_AUTH(n) \ + (IMXRT_CCM_BASE + IMXRT_CCM_CR_AUTH_OFFSET(n)) + +#define IMXRT_CCM_LPCG_DIR(n) \ + (IMXRT_CCM_BASE + IMXRT_CCM_LPCG_DIR_OFFSET(n)) +#define IMXRT_CCM_LPCG_STAT0(n) \ + (IMXRT_CCM_BASE + IMXRT_CCM_LPCG_STAT0_OFFSET(n)) +#define IMXRT_CCM_LPCG_AUTH(n) \ + (IMXRT_CCM_BASE + IMXRT_CCM_LPCG_AUTH_OFFSET(n)) + +/* Register bit definitions *************************************************/ + +/* Clock root control (CLOCK_ROOTn_CONTROL) */ + +#define CCM_CR_CTRL_DIV_SHIFT (0) +#define CCM_CR_CTRL_DIV_MASK (0xff << CCM_CR_CTRL_DIV_SHIFT) +# define CCM_CR_CTRL_DIV(n) (((n) - 1) << CCM_CR_CTRL_DIV_SHIFT) +#define CCM_CR_CTRL_MUX_SHIFT (8) +#define CCM_CR_CTRL_MUX_MASK (0x03 << CCM_CR_CTRL_MUX_SHIFT) +# define CCM_CR_CTRL_MUX_SRCSEL(n) ((n) << CCM_CR_CTRL_MUX_SHIFT) +#define CCM_CR_CTRL_OFF (1 << 24) + +/* Clock root working status (CLOCK_ROOTn_STATUS0) */ + +#define CCM_CR_STAT0_DIV_SHIFT (0) +#define CCM_CR_STAT0_DIV_MASK (0xff << CCM_CR_STAT0_DIV_SHIFT) +#define CCM_CR_STAT0_MUX_SHIFT (8) +#define CCM_CR_STAT0_MUX_MASK (0x03 << CCM_CR_STAT0_MUX_SHIFT) +#define CCM_CR_STAT0_OFF (1 << 24) +#define CCM_CR_STAT0_SLICE_BUSY (1 << 28) +#define CCM_CR_STAT0_CHANGING (1 << 31) + +/* Clock root access control (CLOCK_ROOTn_AUTHEN) */ + +#define CCM_CR_AUTH_TZ_USER (1u << 8) +#define CCM_CR_AUTH_TZ_NS (1u << 9) +#define CCM_CR_AUTH_LOCK_TZ (1u << 11) +#define CCM_CR_AUTH_LOCK_LIST (1u << 15) +#define CCM_CR_AUTH_WHITE_LIST_SHIFT (16) +#define CCM_CR_AUTH_WHITE_LIST_MASK (0xffffu << \ + CCM_CR_AUTH_WHITE_LIST_SHIFT) +# define CCM_CR_AUTH_DOMAIN(n) (1u << \ + (CCM_CR_AUTH_WHITE_LIST_SHIFT + (n))) + +/* Low-power clock gate (LPCGn_DIRECT / LPCGn_STATUS0) */ + +#define CCM_LPCG_DIR_ON (1 << 0) +#define CCM_LPCG_STAT0_ON (1 << 0) + +/* Clock roots (IMXRT1180RM Ch. 20, extracted from NXP MCUXpresso SDK + * clock_root_t enumeration). + */ + +#define CCM_CR_M7 (0) +#define CCM_CR_M33 (1) +#define CCM_CR_EDGELOCK (2) +#define CCM_CR_BUS_AON (3) +#define CCM_CR_BUS_WAKEUP (4) +#define CCM_CR_WAKEUP_AXI (5) +#define CCM_CR_SWO_TRACE (6) +#define CCM_CR_M33_SYSTICK (7) +#define CCM_CR_M7_SYSTICK (8) +#define CCM_CR_FLEXIO1 (9) +#define CCM_CR_FLEXIO2 (10) +#define CCM_CR_LPIT3 (11) +#define CCM_CR_LPTIMER1 (12) +#define CCM_CR_LPTIMER2 (13) +#define CCM_CR_LPTIMER3 (14) +#define CCM_CR_TPM2 (15) +#define CCM_CR_TPM4 (16) +#define CCM_CR_TPM5 (17) +#define CCM_CR_TPM6 (18) +#define CCM_CR_GPT1 (19) +#define CCM_CR_GPT2 (20) +#define CCM_CR_FLEXSPI1 (21) +#define CCM_CR_FLEXSPI2 (22) +#define CCM_CR_FLEXSPI_SLV (23) +#define CCM_CR_CAN1 (24) +#define CCM_CR_CAN2 (25) +#define CCM_CR_CAN3 (26) +#define CCM_CR_LPUART0102 (27) +#define CCM_CR_LPUART0304 (28) +#define CCM_CR_LPUART0506 (29) +#define CCM_CR_LPUART0708 (30) +#define CCM_CR_LPUART0910 (31) +#define CCM_CR_LPUART1112 (32) +#define CCM_CR_LPI2C0102 (33) +#define CCM_CR_LPI2C0304 (34) +#define CCM_CR_LPI2C0506 (35) +#define CCM_CR_LPSPI0102 (36) +#define CCM_CR_LPSPI0304 (37) +#define CCM_CR_LPSPI0506 (38) + +/* On RT1180 the LPUART / LPI2C / LPSPI clock roots are shared between + * pairs of instances. Per-instance aliases keep source code that names + * individual LPUART1..12, LPI2C1..6 or LPSPI1..6 roots compatible with + * both RT117x and RT118x. + */ + +#define CCM_CR_LPUART1 CCM_CR_LPUART0102 +#define CCM_CR_LPUART2 CCM_CR_LPUART0102 +#define CCM_CR_LPUART3 CCM_CR_LPUART0304 +#define CCM_CR_LPUART4 CCM_CR_LPUART0304 +#define CCM_CR_LPUART5 CCM_CR_LPUART0506 +#define CCM_CR_LPUART6 CCM_CR_LPUART0506 +#define CCM_CR_LPUART7 CCM_CR_LPUART0708 +#define CCM_CR_LPUART8 CCM_CR_LPUART0708 +#define CCM_CR_LPUART9 CCM_CR_LPUART0910 +#define CCM_CR_LPUART10 CCM_CR_LPUART0910 +#define CCM_CR_LPUART11 CCM_CR_LPUART1112 +#define CCM_CR_LPUART12 CCM_CR_LPUART1112 + +#define CCM_CR_LPI2C1 CCM_CR_LPI2C0102 +#define CCM_CR_LPI2C2 CCM_CR_LPI2C0102 +#define CCM_CR_LPI2C3 CCM_CR_LPI2C0304 +#define CCM_CR_LPI2C4 CCM_CR_LPI2C0304 +#define CCM_CR_LPI2C5 CCM_CR_LPI2C0506 +#define CCM_CR_LPI2C6 CCM_CR_LPI2C0506 + +#define CCM_CR_LPSPI1 CCM_CR_LPSPI0102 +#define CCM_CR_LPSPI2 CCM_CR_LPSPI0102 +#define CCM_CR_LPSPI3 CCM_CR_LPSPI0304 +#define CCM_CR_LPSPI4 CCM_CR_LPSPI0304 +#define CCM_CR_LPSPI5 CCM_CR_LPSPI0506 +#define CCM_CR_LPSPI6 CCM_CR_LPSPI0506 +#define CCM_CR_I3C1 (39) +#define CCM_CR_I3C2 (40) +#define CCM_CR_USDHC1 (41) +#define CCM_CR_USDHC2 (42) +#define CCM_CR_SEMC (43) +#define CCM_CR_ADC1 (44) +#define CCM_CR_ADC2 (45) +#define CCM_CR_ACMP (46) +#define CCM_CR_ECAT (47) +#define CCM_CR_ENET (48) +#define CCM_CR_TMR_1588 (49) +#define CCM_CR_NETC (50) +#define CCM_CR_MAC0 (51) +#define CCM_CR_MAC1 (52) +#define CCM_CR_MAC2 (53) +#define CCM_CR_MAC3 (54) +#define CCM_CR_MAC4 (55) +#define CCM_CR_SERDES0 (56) +#define CCM_CR_SERDES1 (57) +#define CCM_CR_SERDES2 (58) +#define CCM_CR_SERDES0_1G (59) +#define CCM_CR_SERDES1_1G (60) +#define CCM_CR_SERDES2_1G (61) +#define CCM_CR_XCELBUSX (62) +#define CCM_CR_XRIOCU4 (63) +#define CCM_CR_MCTRL (64) +#define CCM_CR_SAI1 (65) +#define CCM_CR_SAI2 (66) +#define CCM_CR_SAI3 (67) +#define CCM_CR_SAI4 (68) +#define CCM_CR_SPDIF (69) +#define CCM_CR_ASRC (70) +#define CCM_CR_MIC (71) +#define CCM_CR_CKO1 (72) +#define CCM_CR_CKO2 (73) + +/* Low-power clock gates (IMXRT1180RM Ch. 20, extracted from NXP MCUXpresso + * SDK clock_lpcg_t enumeration). + */ + +#define CCM_LPCG_M7 (0) +#define CCM_LPCG_M33 (1) +#define CCM_LPCG_EDGELOCK (2) +#define CCM_LPCG_SIM_AON (3) +#define CCM_LPCG_SIM_WAKEUP (4) +#define CCM_LPCG_SIM_MEGA (5) +#define CCM_LPCG_SIM_R (6) +#define CCM_LPCG_ANADIG (7) +#define CCM_LPCG_DCDC (8) +#define CCM_LPCG_SRC (9) +#define CCM_LPCG_CCM (10) +#define CCM_LPCG_GPC (11) +#define CCM_LPCG_ADC1 (12) +#define CCM_LPCG_ADC2 (13) +#define CCM_LPCG_DAC (14) +#define CCM_LPCG_ACMP1 (15) +#define CCM_LPCG_ACMP2 (16) +#define CCM_LPCG_ACMP3 (17) +#define CCM_LPCG_ACMP4 (18) +#define CCM_LPCG_WDOG1 (19) +#define CCM_LPCG_WDOG2 (20) +#define CCM_LPCG_WDOG3 (21) +#define CCM_LPCG_WDOG4 (22) +#define CCM_LPCG_WDOG5 (23) +#define CCM_LPCG_EWM0 (24) +#define CCM_LPCG_SEMA1 (25) +#define CCM_LPCG_SEMA2 (26) +#define CCM_LPCG_MU_A (27) +#define CCM_LPCG_MU_B (28) +#define CCM_LPCG_EDMA3 (29) +#define CCM_LPCG_EDMA4 (30) +#define CCM_LPCG_ROMCP (31) +#define CCM_LPCG_OCRAM1 (32) +#define CCM_LPCG_OCRAM2 (33) +#define CCM_LPCG_FLEXSPI1 (34) +#define CCM_LPCG_FLEXSPI2 (35) +#define CCM_LPCG_FLEXSPI_SLV (36) +#define CCM_LPCG_TRDC (37) +#define CCM_LPCG_OCOTP (38) +#define CCM_LPCG_SEMC (39) +#define CCM_LPCG_IEE (40) +#define CCM_LPCG_CSTRACE (41) +#define CCM_LPCG_CSSWO (42) +#define CCM_LPCG_IOMUXC1 (43) +#define CCM_LPCG_IOMUXC2 (44) +#define CCM_LPCG_GPIO1 (45) +#define CCM_LPCG_GPIO2 (46) +#define CCM_LPCG_GPIO3 (47) +#define CCM_LPCG_GPIO4 (48) +#define CCM_LPCG_GPIO5 (49) +#define CCM_LPCG_GPIO6 (50) +#define CCM_LPCG_FLEXIO1 (51) +#define CCM_LPCG_FLEXIO2 (52) +#define CCM_LPCG_LPIT1 (53) +#define CCM_LPCG_LPIT2 (54) +#define CCM_LPCG_LPIT3 (55) +#define CCM_LPCG_LPTMR1 (56) +#define CCM_LPCG_LPTMR2 (57) +#define CCM_LPCG_LPTMR3 (58) +#define CCM_LPCG_TPM1 (59) +#define CCM_LPCG_TPM2 (60) +#define CCM_LPCG_TPM3 (61) +#define CCM_LPCG_TPM4 (62) +#define CCM_LPCG_TPM5 (63) +#define CCM_LPCG_TPM6 (64) +#define CCM_LPCG_QTIMER1 (65) +#define CCM_LPCG_QTIMER2 (66) +#define CCM_LPCG_QTIMER3 (67) +#define CCM_LPCG_QTIMER4 (68) +#define CCM_LPCG_QTIMER5 (69) +#define CCM_LPCG_QTIMER6 (70) +#define CCM_LPCG_QTIMER7 (71) +#define CCM_LPCG_QTIMER8 (72) +#define CCM_LPCG_GPT1 (73) +#define CCM_LPCG_GPT2 (74) +#define CCM_LPCG_SYSCOUNT (75) +#define CCM_LPCG_CAN1 (76) +#define CCM_LPCG_CAN2 (77) +#define CCM_LPCG_CAN3 (78) +#define CCM_LPCG_LPUART1 (79) +#define CCM_LPCG_LPUART2 (80) +#define CCM_LPCG_LPUART3 (81) +#define CCM_LPCG_LPUART4 (82) +#define CCM_LPCG_LPUART5 (83) +#define CCM_LPCG_LPUART6 (84) +#define CCM_LPCG_LPUART7 (85) +#define CCM_LPCG_LPUART8 (86) +#define CCM_LPCG_LPUART9 (87) +#define CCM_LPCG_LPUART10 (88) +#define CCM_LPCG_LPUART11 (89) +#define CCM_LPCG_LPUART12 (90) +#define CCM_LPCG_LPI2C1 (91) +#define CCM_LPCG_LPI2C2 (92) +#define CCM_LPCG_LPI2C3 (93) +#define CCM_LPCG_LPI2C4 (94) +#define CCM_LPCG_LPI2C5 (95) +#define CCM_LPCG_LPI2C6 (96) +#define CCM_LPCG_LPSPI1 (97) +#define CCM_LPCG_LPSPI2 (98) +#define CCM_LPCG_LPSPI3 (99) +#define CCM_LPCG_LPSPI4 (100) +#define CCM_LPCG_LPSPI5 (101) +#define CCM_LPCG_LPSPI6 (102) +#define CCM_LPCG_I3C1 (103) +#define CCM_LPCG_I3C2 (104) +#define CCM_LPCG_USDHC1 (105) +#define CCM_LPCG_USDHC2 (106) +#define CCM_LPCG_USB (107) +#define CCM_LPCG_SINC1 (108) +#define CCM_LPCG_SINC2 (109) +#define CCM_LPCG_SINC3 (110) +#define CCM_LPCG_XBAR1 (111) +#define CCM_LPCG_XBAR2 (112) +#define CCM_LPCG_XBAR3 (113) +#define CCM_LPCG_AOI1 (114) +#define CCM_LPCG_AOI2 (115) +#define CCM_LPCG_AOI3 (116) +#define CCM_LPCG_AOI4 (117) +#define CCM_LPCG_ENC1 (118) +#define CCM_LPCG_ENC2 (119) +#define CCM_LPCG_ENC3 (120) +#define CCM_LPCG_ENC4 (121) +#define CCM_LPCG_KPP (122) +#define CCM_LPCG_PWM1 (123) +#define CCM_LPCG_PWM2 (124) +#define CCM_LPCG_PWM3 (125) +#define CCM_LPCG_PWM4 (126) +#define CCM_LPCG_ECAT (127) +#define CCM_LPCG_NETC (128) +#define CCM_LPCG_SERDES1 (129) +#define CCM_LPCG_SERDES2 (130) +#define CCM_LPCG_SERDES3 (131) +#define CCM_LPCG_XCELBUSX (132) +#define CCM_LPCG_XRIOCU4 (133) +#define CCM_LPCG_SPTP (134) +#define CCM_LPCG_MCTRL (135) +#define CCM_LPCG_SAI1 (136) +#define CCM_LPCG_SAI2 (137) +#define CCM_LPCG_SAI3 (138) +#define CCM_LPCG_SAI4 (139) +#define CCM_LPCG_SPDIF (140) +#define CCM_LPCG_ASRC (141) +#define CCM_LPCG_PDM (142) +#define CCM_LPCG_VREF (143) +#define CCM_LPCG_BIST (144) +#define CCM_LPCG_SSI_W2M7 (145) +#define CCM_LPCG_SSI_M72W (146) +#define CCM_LPCG_SSI_W2AO (147) +#define CCM_LPCG_SSI_AO2W (148) + +/* Counts */ + +#define ROOT_MUX_MAX (4) +#define CCM_CR_COUNT (74) +#define CCM_LPCG_COUNT (149) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Clock source names used by the g_ccm_root_mux[] LUT and consumed by + * imxrt_get_clock() to return each source's frequency. The M33 boot ROM + * has already brought up ARM_PLL, SYS_PLL1/2/3 and their PFDs; NuttX only + * reads their frequencies (see imxrt_clockconfig_ver3.c). + */ + +enum ccm_clock_name_e +{ + OSC_RC_24M = 0, + OSC_RC_400M = 1, + OSC_24M = 2, + ARM_PLL_OUT = 3, + SYS_PLL1_OUT = 4, + SYS_PLL1_DIV2 = 5, + SYS_PLL1_DIV5 = 6, + SYS_PLL2_OUT = 7, + SYS_PLL2_PFD0 = 8, + SYS_PLL2_PFD1 = 9, + SYS_PLL2_PFD2 = 10, + SYS_PLL2_PFD3 = 11, + SYS_PLL3_OUT = 12, + SYS_PLL3_DIV2 = 13, + SYS_PLL3_PFD0 = 14, + SYS_PLL3_PFD1 = 15, + SYS_PLL3_PFD2 = 16, + SYS_PLL3_PFD3 = 17, + AUDIO_PLL_OUT = 18, +}; + +/* LUT mapping root -> { MUX 0, MUX 1, MUX 2, MUX 3 } clock sources. */ + +static const int g_ccm_root_mux[CCM_CR_COUNT][ROOT_MUX_MAX] = +{ + { OSC_RC_24M, OSC_RC_400M, ARM_PLL_OUT, SYS_PLL3_OUT }, /* M7 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_OUT, ARM_PLL_OUT }, /* M33 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_OUT, SYS_PLL2_PFD1 }, /* Edgelock */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL2_OUT, SYS_PLL3_PFD2 }, /* Bus_Aon */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL2_OUT, SYS_PLL3_PFD1 }, /* Bus_Wakeup */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_OUT, SYS_PLL2_PFD1 }, /* Wakeup_Axi */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL1_DIV5 }, /* Swo_Trace */ + { OSC_RC_24M, OSC_RC_400M, OSC_24M, SYS_PLL3_DIV2 }, /* M33_Systick */ + { OSC_RC_24M, OSC_RC_400M, OSC_24M, SYS_PLL3_DIV2 }, /* M7_Systick */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL1_DIV5 }, /* Flexio1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL1_DIV5 }, /* Flexio2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpit3 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lptimer1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lptimer2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lptimer3 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Tpm2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Tpm4 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Tpm5 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Tpm6 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Gpt1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Gpt2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_PFD0, SYS_PLL2_PFD0 }, /* Flexspi1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_PFD2, SYS_PLL2_PFD1 }, /* Flexspi2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL2_OUT, SYS_PLL1_OUT }, /* Flexspi_Slv */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_OUT, OSC_24M }, /* Can1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_OUT, OSC_24M }, /* Can2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_OUT, OSC_24M }, /* Can3 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpuart0102 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpuart0304 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpuart0506 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpuart0708 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpuart0910 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpuart1112 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpi2c0102 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpi2c0304 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Lpi2c0506 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_PFD1, SYS_PLL2_OUT }, /* Lpspi0102 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_PFD1, SYS_PLL2_OUT }, /* Lpspi0304 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_PFD1, SYS_PLL2_OUT }, /* Lpspi0506 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* I3c1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* I3c2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL2_PFD2, SYS_PLL1_DIV5 }, /* Usdhc1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL2_PFD2, SYS_PLL1_DIV5 }, /* Usdhc2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_OUT, SYS_PLL2_PFD0 }, /* Semc */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Adc1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL2_PFD3 }, /* Adc2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_OUT, SYS_PLL2_PFD3 }, /* Acmp */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Ecat */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Enet */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_OUT, SYS_PLL2_PFD3 }, /* Tmr_1588 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_PFD3, SYS_PLL2_PFD1 }, /* Netc */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Mac0 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Mac1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Mac2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Mac3 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Mac4 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Serdes0 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Serdes1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV2, SYS_PLL1_DIV5 }, /* Serdes2 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_OUT, AUDIO_PLL_OUT }, /* Serdes0_1G */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_OUT, AUDIO_PLL_OUT }, /* Serdes1_1G */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_OUT, AUDIO_PLL_OUT }, /* Serdes2_1G */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_OUT, SYS_PLL3_PFD1 }, /* Xcelbusx */ + { OSC_RC_24M, OSC_RC_400M, OSC_24M, SYS_PLL3_DIV2 }, /* Xriocu4 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV5, AUDIO_PLL_OUT }, /* Mctrl */ + { OSC_RC_24M, OSC_RC_400M, AUDIO_PLL_OUT, SYS_PLL3_PFD2 }, /* Sai1 */ + { OSC_RC_24M, OSC_RC_400M, AUDIO_PLL_OUT, SYS_PLL3_PFD2 }, /* Sai2 */ + { OSC_RC_24M, OSC_RC_400M, AUDIO_PLL_OUT, SYS_PLL3_PFD2 }, /* Sai3 */ + { OSC_RC_24M, OSC_RC_400M, AUDIO_PLL_OUT, SYS_PLL3_PFD2 }, /* Sai4 */ + { OSC_RC_24M, OSC_RC_400M, AUDIO_PLL_OUT, SYS_PLL3_PFD2 }, /* Spdif */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_OUT, AUDIO_PLL_OUT }, /* Asrc */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, AUDIO_PLL_OUT }, /* Mic */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL3_DIV2, SYS_PLL1_DIV2 }, /* Cko1 */ + { OSC_RC_24M, OSC_RC_400M, SYS_PLL1_DIV5, ARM_PLL_OUT }, /* Cko2 */ +}; + +#endif /* __ARCH_ARM_SRC_IMXRT_HARDWARE_RT118X_IMXRT118X_CCM_H */ diff --git a/arch/arm/src/imxrt/imxrt_clockconfig.h b/arch/arm/src/imxrt/imxrt_clockconfig.h index 1e5bb748854..47b76bce7d1 100644 --- a/arch/arm/src/imxrt/imxrt_clockconfig.h +++ b/arch/arm/src/imxrt/imxrt_clockconfig.h @@ -33,7 +33,9 @@ * hence we use a VER2 driver for clockconfig */ -#ifdef CONFIG_IMXRT_CLOCKCONFIG_VER2 +#ifdef CONFIG_IMXRT_CLOCKCONFIG_VER3 +#include "imxrt_clockconfig_ver3.h" +#elif defined(CONFIG_IMXRT_CLOCKCONFIG_VER2) #include "imxrt_clockconfig_ver2.h" #else #include "imxrt_clockconfig_ver1.h" diff --git a/arch/arm/src/imxrt/imxrt_clockconfig_ver3.c b/arch/arm/src/imxrt/imxrt_clockconfig_ver3.c new file mode 100644 index 00000000000..fdcc3de6087 --- /dev/null +++ b/arch/arm/src/imxrt/imxrt_clockconfig_ver3.c @@ -0,0 +1,566 @@ +/**************************************************************************** + * arch/arm/src/imxrt/imxrt_clockconfig_ver3.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> + +#include <arch/board/board.h> +#include <arch/barriers.h> + +#include "arm_internal.h" +#include "hardware/imxrt_memorymap.h" +#include "hardware/imxrt_dcdc.h" +#include "hardware/rt118x/imxrt118x_anadig.h" +#include "hardware/rt118x/imxrt118x_ccm.h" +#include "hardware/rt118x/imxrt118x_gpc.h" +#include "imxrt_clockconfig_ver3.h" +#ifdef CONFIG_IMXRT_ELE +# include "imxrt118x_ele.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Fixed clock source frequencies programmed by the Cortex-M33 boot ROM + * before the M7 is released. NuttX does not reprogram these PLLs, so + * their frequencies are treated as static constants; if a future use + * case needs to reconfigure the PLLs, extend imxrt_get_clock() to read + * the ANADIG registers instead. + */ + +#define IMXRT_OSC_24M_HZ (24000000u) +#define IMXRT_OSC_RC_24M_HZ (24000000u) +#define IMXRT_OSC_RC_400M_HZ (400000000u) +#define IMXRT_ARM_PLL_HZ (798000000u) +#define IMXRT_SYS_PLL1_HZ (1000000000u) +#define IMXRT_SYS_PLL2_HZ (528000000u) +#define IMXRT_SYS_PLL3_HZ (480000000u) + +/* Standard PFD fractions used by the boot ROM (IMXRT1180RM Ch. 20.5 default + * configuration). Output = (PLL * 18) / frac. + */ + +#define IMXRT_SYS_PLL2_PFD0_HZ (352000000u) /* frac = 27 */ +#define IMXRT_SYS_PLL2_PFD1_HZ (594000000u) /* frac = 16 */ +#define IMXRT_SYS_PLL2_PFD2_HZ (396000000u) /* frac = 24 */ +#define IMXRT_SYS_PLL2_PFD3_HZ (297000000u) /* frac = 32 */ +#define IMXRT_SYS_PLL3_PFD0_HZ (664615384u) /* frac = 13 */ +#define IMXRT_SYS_PLL3_PFD1_HZ (508235294u) /* frac = 17 */ +#define IMXRT_SYS_PLL3_PFD2_HZ (392727272u) /* frac = 22 */ +#define IMXRT_SYS_PLL3_PFD3_HZ (392727272u) /* frac = 22 */ + +/* ARM_PLL loop divider for 798 MHz with post_div = 2: + * + * Fout = 24 MHz * 133 / (2 * 2) = 798 MHz + */ + +#define ARM_PLL_DIV_SELECT (133) + +/* Analog settling delays, expressed as NOP spins because no timer exists + * this early. The M33 still runs from OSC_RC_400M/2 (200 MHz), so one + * iteration is roughly 5 ns; both values are generously rounded up. + */ + +#define PLL_LDO_SETTLE_SPINS (1000) /* SDK uses 1 us */ +#define ARM_PLL_SETTLE_SPINS (25000) /* SDK uses 30 us */ +#define DCDC_SETTLE_SPINS (100000) /* ~123 us of 32 kHz clock */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_ARCH_CHIP_MIMXRT1189CVM8C_CM33 + +/**************************************************************************** + * Name: imxrt_spin + * + * Description: + * Crude busy delay for the analog settling times required during clock + * bring-up. The OS timer is not running this early and the core clock + * is still OSC_RC_400M/2, so this is expressed in loop iterations rather + * than microseconds. + * + ****************************************************************************/ + +static void imxrt_spin(int spins) +{ + int i; + + for (i = 0; i < spins; i++) + { + __asm__ __volatile__("nop"); + } +} + +/**************************************************************************** + * Name: imxrt_set_core_voltage + * + * Description: + * Program the VDD1P0 run-mode target of the on-chip DCDC. + * + * Both cores share a single VDD1P0 rail. The DCDC arbitrates TRG_SW_0 + * and TRG_SW_1 and applies the higher of the two targets + * (IMXRT1180RM Rev. 10 sec. 22.7.1.8), so both must be programmed for + * the new target to take effect. + * + * Input Parameters: + * target - VDD1P0CTRL_TRG encoding, 25 mV per step from 0.6 V. + * + ****************************************************************************/ + +static void imxrt_set_core_voltage(uint32_t target) +{ + uint32_t regval; + +#ifdef CONFIG_IMXRT_ELE + /* Guard the DCDC target change with the EdgeLock Enclave voltage-change + * handshake. + */ + + imxrt118x_ele_voltage_change_start(); +#endif + + regval = getreg32(IMXRT_DCDC_TRG_SW_0); + regval &= ~DCDC_TRG_SW_VDD1P0CTRL_TRG_MASK; + regval |= DCDC_TRG_SW_VDD1P0CTRL_TRG(target); + putreg32(regval, IMXRT_DCDC_TRG_SW_0); + + regval = getreg32(IMXRT_DCDC_TRG_SW_1); + regval &= ~DCDC_TRG_SW_VDD1P0CTRL_TRG_MASK; + regval |= DCDC_TRG_SW_VDD1P0CTRL_TRG(target); + putreg32(regval, IMXRT_DCDC_TRG_SW_1); + +#ifdef CONFIG_IMXRT_ELE + /* Remove the GDET isolation. Must be issued within 50 ms of START and + * with no other ELE command in between (only DCDC register writes above). + */ + + imxrt118x_ele_voltage_change_finish(); +#endif + + /* Wait for the regulator to reach the new target. CURRENT_TRG + * [DCDC_UPDATING] must not be used for this: RM sec. 22.7.1.5 states it + * can stay asserted for seconds and is intended for debug only. The + * supply status is REG0[STS_DC_OK], which is synchronised to the 32 kHz + * clock and settles within ~4 of its cycles (~123 us), so allow the + * request to reach the analog before sampling it. + */ + + imxrt_spin(DCDC_SETTLE_SPINS); + + while ((getreg32(IMXRT_DCDC_REG0) & DCDC_REG0_STS_DC_OK) == 0); +} + +/**************************************************************************** + * Name: imxrt_enable_pll_ldo + * + * Description: + * Enable the PHY LDO that supplies the PLLs. It must be up and stable + * before ARM_PLL is powered on. + * + ****************************************************************************/ + +static void imxrt_enable_pll_ldo(void) +{ + uint32_t regval; + + regval = PHY_LDO_CTRL0_LINREG_OUTPUT_TRG(0x10) | PHY_LDO_CTRL0_LINREG_EN; + + if (getreg32(IMXRT_PHY_LDO_CTRL0_RW) != regval) + { + /* Bring the regulator up with its current limiter armed ... */ + + putreg32(regval | PHY_LDO_CTRL0_LINREG_ILIMIT_EN, + IMXRT_PHY_LDO_CTRL0_RW); + imxrt_spin(PLL_LDO_SETTLE_SPINS); + + /* ... then drop the limiter once stable, which lowers ARM PLL jitter + * at cold temperature. + */ + + putreg32(regval, IMXRT_PHY_LDO_CTRL0_RW); + } +} + +/**************************************************************************** + * Name: imxrt_init_arm_pll + * + * Description: + * Bring up ARM_PLL at 798 MHz. + * + * Fout = 24 MHz * DIV_SELECT / (2 * post_div) + * = 24 MHz * 133 / (2 * 2) + * = 798 MHz + * + * This is the maximum supported ARM_PLL output. It clocks the M7 + * directly and gives the M33 266 MHz through its integer divider. + * + * The RM's ARM_PLL_CTRL description refers to a "PLL Enable Sequence" + * topic for the HOLD_RING_OFF handling, but no such section exists in + * Rev. 10 and no hold time is given. NXP's own CLOCK_InitArmPll() does + * not use HOLD_RING_OFF on this PLL at all, so follow that: configure + * the dividers while gated, power up, allow the analog to settle, then + * wait for lock. + * + ****************************************************************************/ + +static void imxrt_init_arm_pll(void) +{ + uint32_t regval; + + imxrt_enable_pll_ldo(); + + regval = ANADIG_PLL_ARM_DIV_SELECT(ARM_PLL_DIV_SELECT) | + ANADIG_PLL_ARM_POST_DIV_SEL(ANADIG_PLL_ARM_POST_DIV_2); + + /* Power the PLL down before touching the dividers, keeping the output + * gated so that nothing sees an intermediate frequency. + */ + + putreg32(regval | ANADIG_PLL_ARM_GATE, IMXRT_ANADIG_PLL_ARM_CTRL); + + /* Apply the configuration and power up, still gated. */ + + putreg32(regval | ANADIG_PLL_ARM_GATE | ANADIG_PLL_ARM_POWERUP, + IMXRT_ANADIG_PLL_ARM_CTRL); + + UP_DSB(); + UP_ISB(); + + imxrt_spin(ARM_PLL_SETTLE_SPINS); + + while ((getreg32(IMXRT_ANADIG_PLL_ARM_CTRL) & + ANADIG_PLL_ARM_STABLE) == 0); + + /* Locked: enable the clock and ungate the output. */ + + putreg32(regval | ANADIG_PLL_ARM_POWERUP | ANADIG_PLL_ARM_ENABLE_CLK, + IMXRT_ANADIG_PLL_ARM_CTRL); +} + +#endif /* CONFIG_ARCH_CHIP_MIMXRT1189CVM8C_CM33 */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imxrt_ccm_configure_root_clock + ****************************************************************************/ + +int imxrt_ccm_configure_root_clock(int root, int src, uint32_t div) +{ + uint32_t auth; + uint32_t regval; + uint32_t newval; + int i; + + if (root >= CCM_CR_COUNT || div == 0 || div > 256) + { + return -EINVAL; + } + + auth = getreg32(IMXRT_CCM_CR_AUTH(root)); + + if ((auth & CCM_CR_AUTH_DOMAIN(BOARD_CCM_DOMAIN_ID)) == 0) + { + return -EINVAL; + } + + /* Find the mux index that selects the requested source. */ + + for (i = 0; i < ROOT_MUX_MAX; i++) + { + if (g_ccm_root_mux[root][i] == src) + { + break; + } + } + + if (i == ROOT_MUX_MAX) + { + return -EINVAL; + } + + regval = getreg32(IMXRT_CCM_CR_CTRL(root)); + newval = regval & ~(CCM_CR_CTRL_MUX_MASK | CCM_CR_CTRL_DIV_MASK); + newval |= CCM_CR_CTRL_MUX_SRCSEL(i) | CCM_CR_CTRL_DIV(div); + + /* Do not reconfigure a root that already has the requested settings. */ + + if (newval == regval) + { + return OK; + } + + putreg32(newval, IMXRT_CCM_CR_CTRL(root)); + + while (getreg32(IMXRT_CCM_CR_STAT0(root)) & CCM_CR_STAT0_CHANGING); + + return OK; +} + +/**************************************************************************** + * Name: imxrt_ccm_gate_on + ****************************************************************************/ + +int imxrt_ccm_gate_on(int gate, bool enabled) +{ + uint32_t value; + + if (gate >= CCM_LPCG_COUNT) + { + return -EINVAL; + } + + value = enabled ? CCM_LPCG_DIR_ON : 0u; + putreg32(value, IMXRT_CCM_LPCG_DIR(gate)); + + while ((getreg32(IMXRT_CCM_LPCG_STAT0(gate)) & CCM_LPCG_STAT0_ON) != + value); + + return OK; +} + +/**************************************************************************** + * Name: imxrt_periphclk_configure + * + * Description: + * Thin wrapper that lets legacy callers pass CCM_LPCG_DIR_ON / + * CCM_LPCG_DIR_OFF as the second argument. + * + ****************************************************************************/ + +void imxrt_periphclk_configure(unsigned int index, unsigned int value) +{ + imxrt_ccm_gate_on((int)index, (value & CCM_LPCG_DIR_ON) != 0); +} + +/**************************************************************************** + * Name: imxrt_get_clock + ****************************************************************************/ + +int imxrt_get_clock(int clkname, uint32_t *frequency) +{ + switch (clkname) + { + case OSC_RC_24M: + *frequency = IMXRT_OSC_RC_24M_HZ; + break; + + case OSC_RC_400M: + *frequency = IMXRT_OSC_RC_400M_HZ; + break; + + case OSC_24M: + *frequency = IMXRT_OSC_24M_HZ; + break; + + case ARM_PLL_OUT: + *frequency = IMXRT_ARM_PLL_HZ; + break; + + case SYS_PLL1_OUT: + *frequency = IMXRT_SYS_PLL1_HZ; + break; + + case SYS_PLL1_DIV2: + *frequency = IMXRT_SYS_PLL1_HZ / 2; + break; + + case SYS_PLL1_DIV5: + *frequency = IMXRT_SYS_PLL1_HZ / 5; + break; + + case SYS_PLL2_OUT: + *frequency = IMXRT_SYS_PLL2_HZ; + break; + + case SYS_PLL2_PFD0: + *frequency = IMXRT_SYS_PLL2_PFD0_HZ; + break; + + case SYS_PLL2_PFD1: + *frequency = IMXRT_SYS_PLL2_PFD1_HZ; + break; + + case SYS_PLL2_PFD2: + *frequency = IMXRT_SYS_PLL2_PFD2_HZ; + break; + + case SYS_PLL2_PFD3: + *frequency = IMXRT_SYS_PLL2_PFD3_HZ; + break; + + case SYS_PLL3_OUT: + *frequency = IMXRT_SYS_PLL3_HZ; + break; + + case SYS_PLL3_DIV2: + *frequency = IMXRT_SYS_PLL3_HZ / 2; + break; + + case SYS_PLL3_PFD0: + *frequency = IMXRT_SYS_PLL3_PFD0_HZ; + break; + + case SYS_PLL3_PFD1: + *frequency = IMXRT_SYS_PLL3_PFD1_HZ; + break; + + case SYS_PLL3_PFD2: + *frequency = IMXRT_SYS_PLL3_PFD2_HZ; + break; + + case SYS_PLL3_PFD3: + *frequency = IMXRT_SYS_PLL3_PFD3_HZ; + break; + + case AUDIO_PLL_OUT: + *frequency = 0; + break; + + default: + return -ENODEV; + } + + return OK; +} + +/**************************************************************************** + * Name: imxrt_get_rootclock + ****************************************************************************/ + +int imxrt_get_rootclock(uint32_t clkroot, uint32_t *frequency) +{ + uint32_t reg; + uint32_t mux; + uint32_t div; + int clkname; + + if (clkroot >= CCM_CR_COUNT) + { + return -ENODEV; + } + + reg = getreg32(IMXRT_CCM_CR_CTRL(clkroot)); + + if ((reg & CCM_CR_CTRL_OFF) != 0) + { + *frequency = 0; + return OK; + } + + mux = (reg & CCM_CR_CTRL_MUX_MASK) >> CCM_CR_CTRL_MUX_SHIFT; + clkname = g_ccm_root_mux[clkroot][mux]; + imxrt_get_clock(clkname, frequency); + div = ((reg & CCM_CR_CTRL_DIV_MASK) >> CCM_CR_CTRL_DIV_SHIFT) + 1; + *frequency = *frequency / div; + + return OK; +} + +/**************************************************************************** + * Name: imxrt_clockconfig + * + * Description: + * Called to initialize the i.MX RT. This does whatever setup is needed to + * put the SoC in a usable state. The Cortex-M33 boot ROM has already + * started essential PLLs and set the FlexSPI1 clock, so only the roots + * required by NuttX are configured here. CCM_CR_FLEXSPI1 and its LPCG + * MUST NOT be touched while executing XIP from FlexSPI1. + * + ****************************************************************************/ + +void imxrt_clockconfig(void) +{ +#ifdef CONFIG_ARCH_CHIP_MIMXRT1189CVM8C_CM33 + /* Raise VDD1P0 to the HSRUN (OverDrive) level. Both cores share this + * rail and the M33 is the boot core, so it does this on behalf of both. + * + * Forward body bias is deliberately not enabled here. Per RM sec. + * 19.3.3 and 24.3.2.3.3.2 FBB is implemented in the Cortex-M7 platform + * only; the well-bias power switch it turns on belongs to the M7 domain. + * It is enabled by the bootloader as part of releasing the M7. + */ + + imxrt_set_core_voltage(DCDC_1P0_TARGET_1P125V); + + /* Configure ARM_PLL and the M33 root here. The M7 root and M7-specific + * power setup are owned by the bootloader. The M7 must not touch + * ARM_PLL or the M33 root when it later executes this function. + */ + + imxrt_init_arm_pll(); + + /* M33 core clock: ARM_PLL (798 MHz) / 3 = 266 MHz. */ + + imxrt_ccm_configure_root_clock(CCM_CR_M33, ARM_PLL_OUT, 3); + + /* Root1 belongs exclusively to the M33 domain. LOCK_LIST makes this + * ownership immutable until the next system reset. + */ + + putreg32(CCM_CR_AUTH_DOMAIN(BOARD_CCM_DOMAIN_ID) | + CCM_CR_AUTH_LOCK_LIST, + IMXRT_CCM_CR_AUTH(CCM_CR_M33)); + +#endif + +#ifdef CONFIG_ARCH_CHIP_MIMXRT1189CVM8C_CM33 + /* Keep both CPU cores in RUN during WFI so core exceptions such as + * SysTick can wake them without requiring a GPC wakeup source. + */ + + modifyreg32(IMXRT_GPC_CM33_MODE_CTRL, + GPC_CM_MODE_CTRL_TARGET_MASK, + GPC_CM_MODE_CTRL_TARGET(GPC_CM_MODE_TARGET_RUN)); + modifyreg32(IMXRT_GPC_CM_MISC(0), + GPC_CM_MISC_SLEEP_HOLD_EN, 0); +#endif + + /* AON bus (LPUART1/2 pclk): SYS_PLL2 (528 MHz) / 4 = 132 MHz */ + + imxrt_ccm_configure_root_clock(CCM_CR_BUS_AON, SYS_PLL2_OUT, 4); + + /* M7 SysTick reference: 24 MHz / 240 = 100 kHz */ + + imxrt_ccm_configure_root_clock(CCM_CR_M7_SYSTICK, OSC_24M, 240); + + /* LPUART1/2 functional clock: SYS_PLL3_DIV2 (240 MHz) / 10 = 24 MHz */ + + imxrt_ccm_configure_root_clock(CCM_CR_LPUART0102, SYS_PLL3_DIV2, 10); + + /* Turn on the LPCGs used by the minimal port */ + + imxrt_ccm_gate_on(CCM_LPCG_IOMUXC1, true); + imxrt_ccm_gate_on(CCM_LPCG_IOMUXC2, true); + imxrt_ccm_gate_on(CCM_LPCG_LPUART1, true); +} diff --git a/arch/arm/src/imxrt/imxrt_clockconfig_ver3.h b/arch/arm/src/imxrt/imxrt_clockconfig_ver3.h new file mode 100644 index 00000000000..4b1b8c4a38a --- /dev/null +++ b/arch/arm/src/imxrt/imxrt_clockconfig_ver3.h @@ -0,0 +1,149 @@ +/**************************************************************************** + * arch/arm/src/imxrt/imxrt_clockconfig_ver3.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_IMXRT_IMXRT_CLOCKCONFIG_VER3_H +#define __ARCH_ARM_SRC_IMXRT_IMXRT_CLOCKCONFIG_VER3_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdbool.h> +#include <stdint.h> + +#include "hardware/rt118x/imxrt118x_ccm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* LPCG helpers so the shared code can enable/disable peripheral clock gates + * with the same names as on other i.MX RT families. + */ + +#define imxrt_clockall_lpuart1() imxrt_ccm_gate_on(CCM_LPCG_LPUART1, true) +#define imxrt_clockall_lpuart2() imxrt_ccm_gate_on(CCM_LPCG_LPUART2, true) +#define imxrt_clockall_lpuart3() imxrt_ccm_gate_on(CCM_LPCG_LPUART3, true) +#define imxrt_clockall_lpuart4() imxrt_ccm_gate_on(CCM_LPCG_LPUART4, true) +#define imxrt_clockall_lpuart5() imxrt_ccm_gate_on(CCM_LPCG_LPUART5, true) +#define imxrt_clockall_lpuart6() imxrt_ccm_gate_on(CCM_LPCG_LPUART6, true) +#define imxrt_clockall_lpuart7() imxrt_ccm_gate_on(CCM_LPCG_LPUART7, true) +#define imxrt_clockall_lpuart8() imxrt_ccm_gate_on(CCM_LPCG_LPUART8, true) +#define imxrt_clockall_lpuart9() imxrt_ccm_gate_on(CCM_LPCG_LPUART9, true) +#define imxrt_clockall_lpuart10() imxrt_ccm_gate_on(CCM_LPCG_LPUART10, true) +#define imxrt_clockall_lpuart11() imxrt_ccm_gate_on(CCM_LPCG_LPUART11, true) +#define imxrt_clockall_lpuart12() imxrt_ccm_gate_on(CCM_LPCG_LPUART12, true) + +#define imxrt_clockall_xbar1() imxrt_ccm_gate_on(CCM_LPCG_XBAR1, true) +#define imxrt_clockall_xbar2() imxrt_ccm_gate_on(CCM_LPCG_XBAR2, true) +#define imxrt_clockall_xbar3() imxrt_ccm_gate_on(CCM_LPCG_XBAR3, true) + +#define imxrt_clockall_gpio1() imxrt_ccm_gate_on(CCM_LPCG_GPIO1, true) +#define imxrt_clockall_gpio2() imxrt_ccm_gate_on(CCM_LPCG_GPIO2, true) +#define imxrt_clockall_gpio3() imxrt_ccm_gate_on(CCM_LPCG_GPIO3, true) +#define imxrt_clockall_gpio4() imxrt_ccm_gate_on(CCM_LPCG_GPIO4, true) +#define imxrt_clockall_gpio5() imxrt_ccm_gate_on(CCM_LPCG_GPIO5, true) +#define imxrt_clockall_gpio6() imxrt_ccm_gate_on(CCM_LPCG_GPIO6, true) + +#define imxrt_clockall_ocotp_ctrl() imxrt_ccm_gate_on(CCM_LPCG_OCOTP, true) + +#define imxrt_clockall_gpt_bus() imxrt_ccm_gate_on(CCM_LPCG_GPT1, true) +#define imxrt_clockall_gpt2_bus() imxrt_ccm_gate_on(CCM_LPCG_GPT2, true) + +#define imxrt_clockall_pwm1() imxrt_ccm_gate_on(CCM_LPCG_PWM1, true) +#define imxrt_clockall_pwm2() imxrt_ccm_gate_on(CCM_LPCG_PWM2, true) +#define imxrt_clockall_pwm3() imxrt_ccm_gate_on(CCM_LPCG_PWM3, true) +#define imxrt_clockall_pwm4() imxrt_ccm_gate_on(CCM_LPCG_PWM4, true) + +#define imxrt_clockall_lpi2c1() imxrt_ccm_gate_on(CCM_LPCG_LPI2C1, true) +#define imxrt_clockall_lpi2c2() imxrt_ccm_gate_on(CCM_LPCG_LPI2C2, true) +#define imxrt_clockall_lpi2c3() imxrt_ccm_gate_on(CCM_LPCG_LPI2C3, true) +#define imxrt_clockall_lpi2c4() imxrt_ccm_gate_on(CCM_LPCG_LPI2C4, true) +#define imxrt_clockall_lpi2c5() imxrt_ccm_gate_on(CCM_LPCG_LPI2C5, true) +#define imxrt_clockall_lpi2c6() imxrt_ccm_gate_on(CCM_LPCG_LPI2C6, true) + +#define imxrt_clockoff_lpi2c1() imxrt_ccm_gate_on(CCM_LPCG_LPI2C1, false) +#define imxrt_clockoff_lpi2c2() imxrt_ccm_gate_on(CCM_LPCG_LPI2C2, false) +#define imxrt_clockoff_lpi2c3() imxrt_ccm_gate_on(CCM_LPCG_LPI2C3, false) +#define imxrt_clockoff_lpi2c4() imxrt_ccm_gate_on(CCM_LPCG_LPI2C4, false) +#define imxrt_clockoff_lpi2c5() imxrt_ccm_gate_on(CCM_LPCG_LPI2C5, false) +#define imxrt_clockoff_lpi2c6() imxrt_ccm_gate_on(CCM_LPCG_LPI2C6, false) + +#define imxrt_clockall_lpspi1() imxrt_ccm_gate_on(CCM_LPCG_LPSPI1, true) +#define imxrt_clockall_lpspi2() imxrt_ccm_gate_on(CCM_LPCG_LPSPI2, true) +#define imxrt_clockall_lpspi3() imxrt_ccm_gate_on(CCM_LPCG_LPSPI3, true) +#define imxrt_clockall_lpspi4() imxrt_ccm_gate_on(CCM_LPCG_LPSPI4, true) +#define imxrt_clockall_lpspi5() imxrt_ccm_gate_on(CCM_LPCG_LPSPI5, true) +#define imxrt_clockall_lpspi6() imxrt_ccm_gate_on(CCM_LPCG_LPSPI6, true) + +#define imxrt_clockoff_lpspi1() imxrt_ccm_gate_on(CCM_LPCG_LPSPI1, false) +#define imxrt_clockoff_lpspi2() imxrt_ccm_gate_on(CCM_LPCG_LPSPI2, false) +#define imxrt_clockoff_lpspi3() imxrt_ccm_gate_on(CCM_LPCG_LPSPI3, false) +#define imxrt_clockoff_lpspi4() imxrt_ccm_gate_on(CCM_LPCG_LPSPI4, false) +#define imxrt_clockoff_lpspi5() imxrt_ccm_gate_on(CCM_LPCG_LPSPI5, false) +#define imxrt_clockoff_lpspi6() imxrt_ccm_gate_on(CCM_LPCG_LPSPI6, false) + +#define imxrt_clockall_usboh3() imxrt_ccm_gate_on(CCM_LPCG_USB, true) +#define imxrt_clockoff_usboh3() imxrt_ccm_gate_on(CCM_LPCG_USB, false) +#define imxrt_clockrun_usboh3() imxrt_ccm_gate_on(CCM_LPCG_USB, true) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Initialise the RT1180 clock tree. */ + +void imxrt_clockconfig(void); + +/* Program a clock root's MUX + DIV using a clock source name from + * ccm_clock_name_e. Returns OK, or -EINVAL if the (root, src) pair is + * not valid. + */ + +int imxrt_ccm_configure_root_clock(int root, int src, uint32_t div); + +/* Enable or disable a low-power clock gate (LPCG). */ + +int imxrt_ccm_gate_on(int gate, bool enabled); + +/* Compatibility shim for existing callers that use CCM_LPCG_DIR_ON / + * CCM_LPCG_DIR_OFF as the value argument. + */ + +void imxrt_periphclk_configure(unsigned int index, unsigned int value); + +/* Return the frequency in Hz of the named clock source (OSC / PLL / PFD) + * or zero if unknown. + */ + +int imxrt_get_clock(int clkname, uint32_t *frequency); + +/* Return the frequency in Hz of the selected clock root (after MUX and + * DIV are applied). Signature matches RT117x's imxrt_get_rootclock() so + * that shared drivers do not need to distinguish between families. + */ + +int imxrt_get_rootclock(uint32_t clkroot, uint32_t *frequency); + +#endif /* __ARCH_ARM_SRC_IMXRT_IMXRT_CLOCKCONFIG_VER3_H */ diff --git a/arch/arm/src/imxrt/imxrt_periphclks.h b/arch/arm/src/imxrt/imxrt_periphclks.h index 55f3c9d61e0..d8aaaeb354b 100644 --- a/arch/arm/src/imxrt/imxrt_periphclks.h +++ b/arch/arm/src/imxrt/imxrt_periphclks.h @@ -29,6 +29,17 @@ #include <nuttx/config.h> #include <stdint.h> + +#ifdef CONFIG_IMXRT_CLOCKCONFIG_VER3 + +/* CCM v2 with per-peripheral LPCG registers: LPUART clock helpers are + * declared in imxrt_clockconfig_ver3.h. + */ + +#include "imxrt_clockconfig_ver3.h" + +#else + #include "hardware/imxrt_ccm.h" /**************************************************************************** @@ -590,6 +601,8 @@ void imxrt_periphclk_configure(uintptr_t regaddr, unsigned int index, #endif +#endif /* !CONFIG_ARCH_FAMILY_IMXRT118x */ + #undef EXTERN #if defined(__cplusplus) }
