Implementation of pinmux of usdhc depends on board design. Usdhc driver could change pinmux according to SD mode, SoC should provide API for this. Board pinmux should register its pinmux function to SoC. Signed-off-by: Jun Yang <jun.yang@nxp.com>
280 lines
6.7 KiB
C
280 lines
6.7 KiB
C
/*
|
|
* Copyright (c) 2017,2018, NXP
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <kernel.h>
|
|
#include <device.h>
|
|
#include <init.h>
|
|
#include <soc.h>
|
|
#include <linker/sections.h>
|
|
#include <fsl_clock.h>
|
|
#include <arch/cpu.h>
|
|
#include <cortex_m/exc.h>
|
|
#include <fsl_flexspi_nor_boot.h>
|
|
#if CONFIG_USB_DC_NXP_EHCI
|
|
#include "usb_phy.h"
|
|
#include "usb_dc_mcux.h"
|
|
#endif
|
|
|
|
#ifdef CONFIG_INIT_ARM_PLL
|
|
/* ARM PLL configuration for RUN mode */
|
|
const clock_arm_pll_config_t armPllConfig = {
|
|
.loopDivider = 100U
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_INIT_SYS_PLL
|
|
/* SYS PLL configuration for RUN mode */
|
|
const clock_sys_pll_config_t sysPllConfig = {
|
|
.loopDivider = 1U
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_INIT_USB1_PLL
|
|
/* USB1 PLL configuration for RUN mode */
|
|
const clock_usb_pll_config_t usb1PllConfig = {
|
|
.loopDivider = 0U
|
|
};
|
|
#endif
|
|
|
|
#if CONFIG_USB_DC_NXP_EHCI
|
|
/* USB PHY condfiguration */
|
|
#define BOARD_USB_PHY_D_CAL (0x0CU)
|
|
#define BOARD_USB_PHY_TXCAL45DP (0x06U)
|
|
#define BOARD_USB_PHY_TXCAL45DM (0x06U)
|
|
#endif
|
|
|
|
#ifdef CONFIG_INIT_ENET_PLL
|
|
/* ENET PLL configuration for RUN mode */
|
|
const clock_enet_pll_config_t ethPllConfig = {
|
|
#if defined(CONFIG_SOC_MIMXRT1021) || defined(CONFIG_SOC_MIMXRT1015)
|
|
.enableClkOutput500M = true,
|
|
#endif
|
|
#ifdef CONFIG_ETH_MCUX
|
|
.enableClkOutput = true,
|
|
#endif
|
|
.enableClkOutput25M = false,
|
|
.loopDivider = 1,
|
|
};
|
|
#endif
|
|
|
|
#if CONFIG_USB_DC_NXP_EHCI
|
|
usb_phy_config_struct_t usbPhyConfig = {
|
|
BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_INIT_VIDEO_PLL
|
|
const clock_video_pll_config_t videoPllConfig = {
|
|
.loopDivider = 31,
|
|
.postDivider = 8,
|
|
.numerator = 0,
|
|
.denominator = 0,
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_NXP_IMX_RT_BOOT_HEADER
|
|
const __imx_boot_data_section BOOT_DATA_T boot_data = {
|
|
.start = CONFIG_FLASH_BASE_ADDRESS,
|
|
.size = CONFIG_FLASH_SIZE,
|
|
.plugin = PLUGIN_FLAG,
|
|
.placeholder = 0xFFFFFFFF,
|
|
};
|
|
|
|
const __imx_boot_ivt_section ivt image_vector_table = {
|
|
.hdr = IVT_HEADER,
|
|
.entry = CONFIG_FLASH_BASE_ADDRESS + CONFIG_TEXT_SECTION_OFFSET,
|
|
.reserved1 = IVT_RSVD,
|
|
#ifdef CONFIG_DEVICE_CONFIGURATION_DATA
|
|
.dcd = (uint32_t) dcd_data,
|
|
#else
|
|
.dcd = (uint32_t) NULL,
|
|
#endif
|
|
.boot_data = (uint32_t) &boot_data,
|
|
.self = (uint32_t) &image_vector_table,
|
|
.csf = (uint32_t)CSF_ADDRESS,
|
|
.reserved2 = IVT_RSVD,
|
|
};
|
|
#endif
|
|
|
|
/**
|
|
*
|
|
* @brief Initialize the system clock
|
|
*
|
|
* @return N/A
|
|
*
|
|
*/
|
|
static ALWAYS_INLINE void clkInit(void)
|
|
{
|
|
/* Boot ROM did initialize the XTAL, here we only sets external XTAL
|
|
* OSC freq
|
|
*/
|
|
CLOCK_SetXtalFreq(24000000U);
|
|
CLOCK_SetRtcXtalFreq(32768U);
|
|
|
|
/* Set PERIPH_CLK2 MUX to OSC */
|
|
CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 0x1);
|
|
|
|
/* Set PERIPH_CLK MUX to PERIPH_CLK2 */
|
|
CLOCK_SetMux(kCLOCK_PeriphMux, 0x1);
|
|
|
|
/* Setting the VDD_SOC to 1.5V. It is necessary to config AHB to 600Mhz
|
|
*/
|
|
DCDC->REG3 = (DCDC->REG3 & (~DCDC_REG3_TRG_MASK)) | DCDC_REG3_TRG(0x12);
|
|
/* Waiting for DCDC_STS_DC_OK bit is asserted */
|
|
while (DCDC_REG0_STS_DC_OK_MASK !=
|
|
(DCDC_REG0_STS_DC_OK_MASK & DCDC->REG0)) {
|
|
;
|
|
}
|
|
|
|
#ifdef CONFIG_INIT_ARM_PLL
|
|
CLOCK_InitArmPll(&armPllConfig); /* Configure ARM PLL to 1200M */
|
|
#endif
|
|
#ifdef CONFIG_INIT_SYS_PLL
|
|
CLOCK_InitSysPll(&sysPllConfig); /* Configure SYS PLL to 528M */
|
|
#endif
|
|
#ifdef CONFIG_INIT_USB1_PLL
|
|
CLOCK_InitUsb1Pll(&usb1PllConfig); /* Configure USB1 PLL to 480M */
|
|
#endif
|
|
#ifdef CONFIG_INIT_ENET_PLL
|
|
CLOCK_InitEnetPll(ðPllConfig);
|
|
#endif
|
|
#ifdef CONFIG_INIT_VIDEO_PLL
|
|
CLOCK_InitVideoPll(&videoPllConfig);
|
|
#endif
|
|
|
|
CLOCK_SetDiv(kCLOCK_ArmDiv, CONFIG_ARM_DIV); /* Set ARM PODF */
|
|
CLOCK_SetDiv(kCLOCK_AhbDiv, CONFIG_AHB_DIV); /* Set AHB PODF */
|
|
CLOCK_SetDiv(kCLOCK_IpgDiv, CONFIG_IPG_DIV); /* Set IPG PODF */
|
|
|
|
/* Set PRE_PERIPH_CLK to PLL1, 1200M */
|
|
CLOCK_SetMux(kCLOCK_PrePeriphMux, 0x3);
|
|
|
|
/* Set PERIPH_CLK MUX to PRE_PERIPH_CLK */
|
|
CLOCK_SetMux(kCLOCK_PeriphMux, 0x0);
|
|
|
|
#ifdef CONFIG_UART_MCUX_LPUART
|
|
/* Configure UART divider to default */
|
|
CLOCK_SetMux(kCLOCK_UartMux, 0); /* Set UART source to PLL3 80M */
|
|
CLOCK_SetDiv(kCLOCK_UartDiv, 0); /* Set UART divider to 1 */
|
|
#endif
|
|
|
|
#ifdef CONFIG_I2C_MCUX_LPI2C
|
|
CLOCK_SetMux(kCLOCK_Lpi2cMux, 0); /* Set I2C source as USB1 PLL 480M */
|
|
CLOCK_SetDiv(kCLOCK_Lpi2cDiv, 5); /* Set I2C divider to 6 */
|
|
#endif
|
|
|
|
#ifdef CONFIG_SPI_MCUX_LPSPI
|
|
CLOCK_SetMux(kCLOCK_LpspiMux, 1); /* Set SPI source to USB1 PFD0 720M */
|
|
CLOCK_SetDiv(kCLOCK_LpspiDiv, 7); /* Set SPI divider to 8 */
|
|
#endif
|
|
|
|
#ifdef CONFIG_DISPLAY_MCUX_ELCDIF
|
|
CLOCK_SetMux(kCLOCK_LcdifPreMux, 2);
|
|
CLOCK_SetDiv(kCLOCK_LcdifPreDiv, 4);
|
|
CLOCK_SetDiv(kCLOCK_LcdifDiv, 1);
|
|
#endif
|
|
|
|
#if CONFIG_USB_DC_NXP_EHCI
|
|
CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usb480M,
|
|
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
|
|
CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M,
|
|
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
|
|
USB_EhciPhyInit(kUSB_ControllerEhci0, CPU_XTAL_CLK_HZ, &usbPhyConfig);
|
|
#endif
|
|
|
|
/* Keep the system clock running so SYSTICK can wake up the system from
|
|
* wfi.
|
|
*/
|
|
CLOCK_SetMode(kCLOCK_ModeRun);
|
|
|
|
}
|
|
|
|
#if defined(CONFIG_DISK_ACCESS_USDHC1) || \
|
|
defined(CONFIG_DISK_ACCESS_USDHC2)
|
|
|
|
/* Usdhc driver needs to re-configure pinmux
|
|
* Pinmux depends on board design.
|
|
* From the perspective of Usdhc driver,
|
|
* it can't access board specific function.
|
|
* So SoC provides this for board to register
|
|
* its usdhc pinmux and for usdhc to access
|
|
* pinmux.
|
|
*/
|
|
|
|
static usdhc_pin_cfg_cb g_usdhc_pin_cfg_cb;
|
|
|
|
void imxrt_usdhc_pinmux_cb_register(usdhc_pin_cfg_cb cb)
|
|
{
|
|
g_usdhc_pin_cfg_cb = cb;
|
|
}
|
|
|
|
void imxrt_usdhc_pinmux(u16_t nusdhc, bool init,
|
|
u32_t speed, u32_t strength)
|
|
{
|
|
if (g_usdhc_pin_cfg_cb)
|
|
g_usdhc_pin_cfg_cb(nusdhc, init,
|
|
speed, strength);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
*
|
|
* @brief Perform basic hardware initialization
|
|
*
|
|
* Initialize the interrupt controller device drivers.
|
|
* Also initialize the timer device driver, if required.
|
|
*
|
|
* @return 0
|
|
*/
|
|
|
|
static int imxrt_init(struct device *arg)
|
|
{
|
|
ARG_UNUSED(arg);
|
|
|
|
unsigned int oldLevel; /* old interrupt lock level */
|
|
|
|
/* disable interrupts */
|
|
oldLevel = irq_lock();
|
|
|
|
/* Watchdog disable */
|
|
if ((WDOG1->WCR & WDOG_WCR_WDE_MASK) != 0) {
|
|
WDOG1->WCR &= ~WDOG_WCR_WDE_MASK;
|
|
}
|
|
|
|
if ((WDOG2->WCR & WDOG_WCR_WDE_MASK) != 0) {
|
|
WDOG2->WCR &= ~WDOG_WCR_WDE_MASK;
|
|
}
|
|
|
|
RTWDOG->CNT = 0xD928C520U; /* 0xD928C520U is the update key */
|
|
RTWDOG->TOVAL = 0xFFFF;
|
|
RTWDOG->CS = (uint32_t) ((RTWDOG->CS) & ~RTWDOG_CS_EN_MASK)
|
|
| RTWDOG_CS_UPDATE_MASK;
|
|
|
|
/* Disable Systick which might be enabled by bootrom */
|
|
if ((SysTick->CTRL & SysTick_CTRL_ENABLE_Msk) != 0) {
|
|
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
|
|
}
|
|
|
|
SCB_EnableICache();
|
|
if ((SCB->CCR & SCB_CCR_DC_Msk) == 0) {
|
|
SCB_EnableDCache();
|
|
}
|
|
|
|
/* Initialize system clock */
|
|
clkInit();
|
|
|
|
/*
|
|
* install default handler that simply resets the CPU
|
|
* if configured in the kernel, NOP otherwise
|
|
*/
|
|
NMI_INIT();
|
|
|
|
/* restore interrupt state */
|
|
irq_unlock(oldLevel);
|
|
return 0;
|
|
}
|
|
|
|
SYS_INIT(imxrt_init, PRE_KERNEL_1, 0);
|