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 <jukka.laitinen@tii.ae>
This commit is contained in:
Jukka Laitinen 2026-09-01 15:16:12 +03:00 • committed by Xiang Xiao
parent f6aa5c115e
commit d4a3d255a4
10 changed files with 1282 additions and 3 deletions

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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"

View file

@ -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);
}

View file

@ -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 */

View file

@ -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)
}