Commit fc4d47d9 authored by Peng Fan's avatar Peng Fan Committed by Jason Liu

MLK-15142-15 imx8m: add EVK board support

Add i.MX8M EVK board support.
The drivers are not switched to use driver model now.
SPL is used to initialize DDR Controller and DDR PHY, then
load u-boot.img from SD to DRAM.
ATF and PHY FW bin are included.
Signed-off-by: default avatarPeng Fan <peng.fan@nxp.com>
parent b901c1bb
......@@ -3,8 +3,20 @@ if ARCH_IMX8M
config IMX8M
bool
select ROM_UNIFIED_SECTIONS
choice
prompt "NXP i.MX8M board select"
optional
config TARGET_IMX8MQ_EVK
bool "imx8mq_evk"
select IMX8M
select SUPPORT_SPL
endchoice
config SYS_SOC
default "imx8m"
source "board/freescale/imx8mq_evk/Kconfig"
endif
File added
if TARGET_IMX8MQ_EVK
config SYS_BOARD
default "imx8mq_evk"
config SYS_VENDOR
default "freescale"
config SYS_CONFIG_NAME
default "imx8mq_evk"
endif
#
# Copyright 2016 Freescale Semiconductor
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += imx8m_evk.o
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
obj-y += ddr/lpddr4_pub_train_0608_simple.o ddr/train1d.o ddr/helper.o ddr/imem.o
endif
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <spl.h>
#include <asm/io.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/ddr_memory_map.h>
DECLARE_GLOBAL_DATA_PTR;
#define IMEM_LEN 32768//23400 //byte
#define DMEM_LEN 16384//1720 //byte
#define IMEM_OFFSET_ADDR 0x00050000
#define DMEM_OFFSET_ADDR 0x00054000
#define DDR_TRAIN_CODE_BASE_ADDR IP2APB_DDRPHY_IPS_BASE_ADDR(0)
char __firmware_imem_start[0] __attribute__((section(".__firmware_imem_start")));
char __firmware_imem_end[0] __attribute__((section(".__firmware_imem_end")));
char __firmware_dmem_start[0] __attribute__((section(".__firmware_dmem_start")));
char __firmware_dmem_end[0] __attribute__((section(".__firmware_dmem_end")));
void ddr4_load_train_code(void)
{
u32 tmp32, i;
u32 error = 0;
unsigned long pr_to32, pr_from32;
unsigned long imem_start = (unsigned long)&__firmware_imem_start;
unsigned long dmem_start = (unsigned long)&__firmware_dmem_start;
pr_from32 = imem_start;
pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * IMEM_OFFSET_ADDR;
for(i = 0x0; i < IMEM_LEN; ){
tmp32 = readl(pr_from32);
writew(tmp32 & 0x0000ffff, pr_to32);
pr_to32 += 4;
writew((tmp32 >> 16) & 0x0000ffff, pr_to32);
pr_to32 += 4;
pr_from32 += 4;
i += 4;
}
pr_from32 = dmem_start;
pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * DMEM_OFFSET_ADDR;
for(i = 0x0; i < DMEM_LEN;){
tmp32 = readl(pr_from32);
writew(tmp32 & 0x0000ffff, pr_to32);
pr_to32 += 4;
writew((tmp32 >> 16) & 0x0000ffff, pr_to32);
pr_to32 += 4;
pr_from32 += 4;
i += 4;
}
printf("check ddr4_pmu_train_imem code\n");
pr_from32 = imem_start;
pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * IMEM_OFFSET_ADDR;
for(i = 0x0; i < IMEM_LEN;){
tmp32 = (readw(pr_to32) & 0x0000ffff);
pr_to32 += 4;
tmp32 += ((readw(pr_to32) & 0x0000ffff) << 16);
if(tmp32 != readl(pr_from32)){
printf("%lx %lx\n", pr_from32, pr_to32);
error++;
}
pr_from32 += 4;
pr_to32 += 4;
i += 4;
}
if(error){
printf("check ddr4_pmu_train_imem code fail=%d\n",error);
}else{
printf("check ddr4_pmu_train_imem code pass\n");
}
printf("check ddr4_pmu_train_dmem code\n");
pr_from32 = dmem_start;
pr_to32 = DDR_TRAIN_CODE_BASE_ADDR + 4 * DMEM_OFFSET_ADDR;
for(i = 0x0; i < DMEM_LEN;){
tmp32 = (readw(pr_to32) & 0x0000ffff);
pr_to32 += 4;
tmp32 += ((readw(pr_to32) & 0x0000ffff) << 16);
if(tmp32 != readl(pr_from32)){
printf("%lx %lx\n", pr_from32, pr_to32);
error++;
}
pr_from32 += 4;
pr_to32 += 4;
i += 4;
}
if(error){
printf("check ddr4_pmu_train_dmem code fail=%d",error);
}else{
printf("check ddr4_pmu_train_dmem code pass\n");
}
}
.section .firmware_imem,#alloc
.incbin "lpddr4_pmu_train_imem.bin"
.section .firmware_dmem,#alloc
.incbin "lpddr4_pmu_train_dmem.bin"
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
void lpddr4_pub_train(void);
void ddr4_load_train_code(void);
void lpddr4_800M_cfg_phy(void);
extern void dram_pll_init(void);
static inline void reg32_write(unsigned long addr, u32 val)
{
writel(val, addr);
}
static inline uint32_t reg32_read(unsigned long addr)
{
return readl(addr);
}
static void inline dwc_ddrphy_apb_wr(unsigned long addr, u32 val)
{
writel(val, addr);
}
static inline void reg32setbit(unsigned long addr, u32 bit)
{
setbits_le32(addr, (1 << bit));
}
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/ddr_memory_map.h>
#include <asm/arch/clock.h>
#include "lpddr4.h"
#ifdef CONFIG_ENABLE_DDR_TRAINING_DEBUG
#define ddr_printf(args...) printf(args)
#else
#define ddr_printf(args...)
#endif
#include "wait_ddrphy_training_complete.c"
#ifndef SRC_DDRC_RCR_ADDR
#define SRC_DDRC_RCR_ADDR SRC_IPS_BASE_ADDR +0x1000
#endif
#ifndef DDR_CSD1_BASE_ADDR
#define DDR_CSD1_BASE_ADDR 0x40000000
#endif
#define SILICON_TRAIN
volatile unsigned int tmp, tmp_t, i;
void lpddr4_800MHz_cfg_umctl2(void)
{
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000304, 0x00000001);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000030, 0x00000001);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000000, 0x83080020);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000000, 0x83080020);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000064, 0x006180e0);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000064, 0x006180e0);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000d0, 0xc003061B);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000d0, 0xc003061B);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000d4, 0x009D0000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000d4, 0x009D0000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000d8, 0x0000fe05);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000d8, 0x0000fe05);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000dc, 0x00d4002d);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000dc, 0x00d4002d);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000e0, 0x00310008);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000e0, 0x00310008);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000e4, 0x00040009);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000e4, 0x00040009);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000e8, 0x0046004d);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000e8, 0x0046004d);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000ec, 0x0005004d);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000ec, 0x0005004d);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000f4, 0x00000979);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000000f4, 0x00000979);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000100, 0x1a203522);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000100, 0x1a203522);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000104, 0x00060630);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000104, 0x00060630);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000108, 0x070e1214);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000108, 0x070e1214);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x0000010c, 0x00b0c006);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x0000010c, 0x00b0c006);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000110, 0x0f04080f);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000110, 0x0f04080f);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000114, 0x0d0d0c0c);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000114, 0x0d0d0c0c);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000118, 0x01010007);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000118, 0x01010007);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x0000011c, 0x0000060a);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x0000011c, 0x0000060a);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000120, 0x01010101);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000120, 0x01010101);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000124, 0x40000008);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000124, 0x40000008);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000128, 0x00050d01);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000128, 0x00050d01);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x0000012c, 0x01010008);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x0000012c, 0x01010008);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000130, 0x00020000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000130, 0x00020000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000134, 0x18100002);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000134, 0x18100002);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000138, 0x00000dc2);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000138, 0x00000dc2);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x0000013c, 0x80000000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x0000013c, 0x80000000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000144, 0x00a00050);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000144, 0x00a00050);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000180, 0x53200018);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000180, 0x53200018);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000184, 0x02800070);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000184, 0x02800070);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000188, 0x00000000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000188, 0x00000000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000190, 0x0397820a);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000190, 0x0397820a);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000194, 0x00020103);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000194, 0x00020103);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001a0, 0xe0400018);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001a0, 0xe0400018);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001a4, 0x00df00e4);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001a4, 0x00df00e4);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001a8, 0x00000000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001a8, 0x00000000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001b0, 0x00000011);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001b0, 0x00000011);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001b4, 0x0000170a);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001b4, 0x0000170a);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001c0, 0x00000001);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001c0, 0x00000001);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001c4, 0x00000000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x000001c4, 0x00000000);
/* Address map is from MSB 29: r15, r14, cs, r13-r0, b2-b0, c9-c0 */
dwc_ddrphy_apb_wr(DDRC_ADDRMAP0(0), 0x00000015);
dwc_ddrphy_apb_wr(DDRC_ADDRMAP4(0), 0x00001F1F);
/* bank interleave */
dwc_ddrphy_apb_wr(DDRC_ADDRMAP1(0), 0x00080808);
dwc_ddrphy_apb_wr(DDRC_ADDRMAP5(0), 0x07070707);
dwc_ddrphy_apb_wr(DDRC_ADDRMAP6(0), 0x08080707);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000240, 0x020f0c54);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000240, 0x020f0c54);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000244, 0x00000000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000244, 0x00000000);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000490, 0x00000001);
dwc_ddrphy_apb_wr(DDRC_IPS_BASE_ADDR(0) + 0x00000490, 0x00000001);
}
void lpddr4_pub_train(void)
{
/* change the clock source of dram_apb_clk_root */
reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1),(0x7<<24)|(0x7<<16));
reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1),(0x4<<24)|(0x3<<16));
/* disable the clock gating */
reg32_write(0x303A00EC,0x0000ffff);
reg32setbit(0x303A00F8,5);
reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000);
dram_pll_init();
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
/* Configure uMCTL2's registers */
lpddr4_800MHz_cfg_umctl2();
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
reg32_write(DDRC_DBG1(0), 0x00000000);
tmp = reg32_read(DDRC_PWRCTL(0));
reg32_write(DDRC_PWRCTL(0), 0x000000a8);
/* reg32_write(DDRC_PWRCTL(0), 0x0000018a); */
reg32_write(DDRC_SWCTL(0), 0x00000000);
reg32_write(DDRC_DDR_SS_GPR0, 0x01);
reg32_write(DDRC_DFIMISC(0), 0x00000010);
/* Configure LPDDR4 PHY's registers */
lpddr4_800M_cfg_phy();
reg32_write(DDRC_RFSHCTL3(0), 0x00000000);
reg32_write(DDRC_SWCTL(0), 0x0000);
/*
* ------------------- 9 -------------------
* Set DFIMISC.dfi_init_start to 1
* -----------------------------------------
*/
reg32_write(DDRC_DFIMISC(0), 0x00000030);
reg32_write(DDRC_SWCTL(0), 0x0001);
/* wait DFISTAT.dfi_init_complete to 1 */
tmp_t = 0;
while(tmp_t==0){
tmp = reg32_read(DDRC_DFISTAT(0));
tmp_t = tmp & 0x01;
tmp = reg32_read(DDRC_MRSTAT(0));
}
reg32_write(DDRC_SWCTL(0), 0x0000);
/* clear DFIMISC.dfi_init_complete_en */
reg32_write(DDRC_DFIMISC(0), 0x00000010);
reg32_write(DDRC_DFIMISC(0), 0x00000011);
reg32_write(DDRC_PWRCTL(0), 0x00000088);
tmp = reg32_read(DDRC_CRCPARSTAT(0));
/*
* set SWCTL.sw_done to enable quasi-dynamic register
* programming outside reset.
*/
reg32_write(DDRC_SWCTL(0), 0x00000001);
/* wait SWSTAT.sw_done_ack to 1 */
while((reg32_read(DDRC_SWSTAT(0)) & 0x1) == 0)
;
/* wait STAT.operating_mode([1:0] for ddr3) to normal state */
while ((reg32_read(DDRC_STAT(0)) & 0x3) != 0x1)
;
reg32_write(DDRC_PWRCTL(0), 0x00000088);
/* reg32_write(DDRC_PWRCTL(0), 0x018a); */
tmp = reg32_read(DDRC_CRCPARSTAT(0));
/* enable port 0 */
reg32_write(DDRC_PCTRL_0(0), 0x00000001);
tmp = reg32_read(DDRC_CRCPARSTAT(0));
reg32_write(DDRC_RFSHCTL3(0), 0x00000000);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
static inline void poll_pmu_message_ready(void)
{
unsigned int reg;
do {
reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0004);
} while (reg & 0x1);
}
static inline void ack_pmu_message_recieve(void)
{
unsigned int reg;
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0031,0x0);
do {
reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0004);
} while (!(reg & 0x1));
reg32_write(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0031,0x1);
}
static inline unsigned int get_mail(void)
{
unsigned int reg;
poll_pmu_message_ready();
reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0032);
ack_pmu_message_recieve();
return reg;
}
static inline unsigned int get_stream_message(void)
{
unsigned int reg, reg2;
poll_pmu_message_ready();
reg = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0032);
reg2 = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0)+4*0xd0034);
reg2 = (reg2 << 16) | reg;
ack_pmu_message_recieve();
return reg2;
}
static inline void decode_major_message(unsigned int mail)
{
ddr_printf("[PMU Major message = 0x%08x]\n", mail);
}
static inline void decode_streaming_message(void)
{
unsigned int string_index, arg __maybe_unused;
int i = 0;
string_index = get_stream_message();
ddr_printf(" PMU String index = 0x%08x\n", string_index);
while (i < (string_index & 0xffff)){
arg = get_stream_message();
ddr_printf(" arg[%d] = 0x%08x\n", i, arg);
i++;
}
ddr_printf("\n");
}
void wait_ddrphy_training_complete(void)
{
unsigned int mail;
while (1) {
mail = get_mail();
decode_major_message(mail);
if (mail == 0x08) {
decode_streaming_message();
} else if (mail == 0x07) {
printf("Training PASS\n");
break;
} else if (mail == 0xff) {
printf("Training FAILED\n");
break;
}
}
}
/*
* Copyright 2016 Freescale Semiconductor, Inc.
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <malloc.h>
#include <errno.h>
#include <asm/io.h>
#include <miiphy.h>
#include <netdev.h>
#include <asm/imx-common/iomux-v3.h>
#include <asm-generic/gpio.h>
#include <fsl_esdhc.h>
#include <mmc.h>
#include <asm/arch/imx8mq_pins.h>
#include <asm/imx-common/gpio.h>
#include <asm/imx-common/mxc_i2c.h>
#include <asm/arch/clock.h>
#include <spl.h>
#include <power/pmic.h>
#include <power/pfuze100_pmic.h>
#include "../common/pfuze.h"
DECLARE_GLOBAL_DATA_PTR;
#define QSPI_PAD_CTRL (PAD_CTL_DSE2 | PAD_CTL_HYS)
#define USDHC_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | \
PAD_CTL_FSEL2)
#define UART_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_FSEL1)
#define I2C_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE)
#define ENET_PAD_CTRL (PAD_CTL_DSE7 | PAD_CTL_FSEL3)
#define ENET_PAD_CTRL_MII_MDIO (PAD_CTL_ODE | PAD_CTL_DSE3 | PAD_CTL_FSEL0)
#define ENET_PAD_CTRL_MII_MDC (PAD_CTL_DSE3 | PAD_CTL_FSEL0)
#define ENET_RX_PAD_CTRL (PAD_CTL_DSE7 | PAD_CTL_FSEL3)
#ifdef CONFIG_FSL_QSPI
static iomux_v3_cfg_t const qspi_pads[] = {
IMX8MQ_PAD_NAND_ALE__QSPI_A_SCLK | MUX_PAD_CTRL(QSPI_PAD_CTRL),
IMX8MQ_PAD_NAND_CE0_B__QSPI_A_SS0_B | MUX_PAD_CTRL(QSPI_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA00__QSPI_A_DATA0 | MUX_PAD_CTRL(QSPI_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA01__QSPI_A_DATA1 | MUX_PAD_CTRL(QSPI_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA02__QSPI_A_DATA2 | MUX_PAD_CTRL(QSPI_PAD_CTRL),
IMX8MQ_PAD_NAND_DATA03__QSPI_A_DATA3 | MUX_PAD_CTRL(QSPI_PAD_CTRL),
};
int board_qspi_init(void)
{
imx_iomux_v3_setup_multiple_pads(qspi_pads, ARRAY_SIZE(qspi_pads));
set_clk_qspi();
return 0;
}
#endif
static iomux_v3_cfg_t const uart_pads[] = {
IMX8MQ_PAD_UART1_RXD__UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MQ_PAD_UART1_TXD__UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
};
int board_early_init_f(void)
{
imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
return 0;
}
#ifdef CONFIG_BOARD_POSTCLK_INIT
int board_postclk_init(void)
{
/* TODO */
return 0;
}
#endif
int dram_init(void)
{
gd->ram_size = PHYS_SDRAM_SIZE;
return 0;
}
#ifdef CONFIG_OF_BOARD_SETUP
int ft_board_setup(void *blob, bd_t *bd)
{
return 0;
}
#endif
#define USDHC2_CD_GPIO IMX_GPIO_NR(2, 12)
#define USDHC1_PWR_GPIO IMX_GPIO_NR(2, 10)
#define USDHC2_PWR_GPIO IMX_GPIO_NR(2, 19)
int board_mmc_getcd(struct mmc *mmc)
{
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
int ret = 0;
switch (cfg->esdhc_base) {
case USDHC1_BASE_ADDR:
ret = 1;
break;
case USDHC2_BASE_ADDR:
ret = !gpio_get_value(USDHC2_CD_GPIO);
return ret;
}
return 1;
}
static iomux_v3_cfg_t const usdhc1_pads[] = {
IMX8MQ_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA4__USDHC1_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA5__USDHC1_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA6__USDHC1_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_DATA7__USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
IMX8MQ_PAD_SD1_RESET_B__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
static iomux_v3_cfg_t const usdhc2_pads[] = {
IMX8MQ_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
IMX8MQ_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
IMX8MQ_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
IMX8MQ_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
IMX8MQ_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0x16 */
IMX8MQ_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
IMX8MQ_PAD_SD2_CD_B__GPIO2_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL),
IMX8MQ_PAD_SD2_RESET_B__GPIO2_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
static struct fsl_esdhc_cfg usdhc_cfg[2] = {
{USDHC1_BASE_ADDR, 0, 8},
{USDHC2_BASE_ADDR, 0, 4},
};
int board_mmc_init(bd_t *bis)
{
int i, ret;
/*
* According to the board_mmc_init() the following map is done:
* (U-Boot device node) (Physical Port)
* mmc0 USDHC1
* mmc1 USDHC2
*/
for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
switch (i) {
case 0:
usdhc_cfg[0].sdhc_clk = mxc_get_clock(USDHC1_CLK_ROOT);
imx_iomux_v3_setup_multiple_pads(
usdhc1_pads, ARRAY_SIZE(usdhc1_pads));
gpio_request(USDHC1_PWR_GPIO, "usdhc1_reset");
gpio_direction_output(USDHC1_PWR_GPIO, 0);
udelay(500);
gpio_direction_output(USDHC1_PWR_GPIO, 1);
break;
case 1:
usdhc_cfg[1].sdhc_clk = mxc_get_clock(USDHC2_CLK_ROOT);
imx_iomux_v3_setup_multiple_pads(
usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
gpio_request(USDHC2_PWR_GPIO, "usdhc2_reset");
gpio_direction_output(USDHC2_PWR_GPIO, 0);
udelay(500);
gpio_direction_output(USDHC2_PWR_GPIO, 1);
break;
default:
printf("Warning: you configured more USDHC controllers"
"(%d) than supported by the board\n", i + 1);
return -EINVAL;
}
ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
if (ret)
return ret;
}
return 0;
}
#ifdef CONFIG_SYS_I2C_MXC
#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
struct i2c_pads_info i2c_pad_info1 = {
.scl = {
.i2c_mode = IMX8MQ_PAD_I2C1_SCL__I2C1_SCL | PC,
.gpio_mode = IMX8MQ_PAD_I2C1_SCL__GPIO5_IO14 | PC,
.gp = IMX_GPIO_NR(5, 14),
},
.sda = {
.i2c_mode = IMX8MQ_PAD_I2C1_SDA__I2C1_SDA | PC,
.gpio_mode = IMX8MQ_PAD_I2C1_SDA__GPIO5_IO15 | PC,
.gp = IMX_GPIO_NR(5, 15),
},
};
static struct i2c_pads_info i2c_pad_info2 = {
.scl = {