├── Makefile ├── iMX8M ├── README ├── lib │ └── ddr_memory_map.h ├── mkimage_fit_atf.sh ├── mkimage_imx8.c ├── print_fit_hab.sh └── soc.mak ├── iMX8QM ├── expand_c_define.sh ├── imx8qm_dcd.cfg ├── imx8qm_dcd_1.6GHz.cfg ├── imx8qm_dcd_800MHz.cfg ├── lib │ ├── ddr_phy_mem_map.h │ └── ddrc_mem_map.h └── soc.mak ├── iMX8QX ├── imx8qx_dcd_1.2GHz.cfg ├── imx8qx_dcd_16bit_1.2GHz.cfg ├── imx8qx_ddr3_dcd_1066MHz_ecc.cfg ├── imx8qx_ddr3_dcd_800MHz.cfg ├── imx8qx_ddr3_dcd_800MHz_ecc.cfg ├── imx8qx_ddr3_dcd_933MHz.cfg ├── imx8qx_ddr3_dcd_933MHz_ecc.cfg ├── lib │ ├── ddr_phy_mem_map.h │ └── ddrc_mem_map.h └── soc.mak ├── iMX8dv ├── COPYING ├── imx8dv_dcd.cfg ├── mkimage_imx8.c └── soc.mak └── src ├── imx8qm.c ├── imx8qx.c ├── mkimage_common.h └── mkimage_imx8.c /Makefile: -------------------------------------------------------------------------------- 1 | 2 | MKIMG = $(PWD)/mkimage_imx8 3 | CC = gcc 4 | CFLAGS ?= -g -O2 -Wall -std=c99 -static 5 | INCLUDE += $(CURR_DIR)/src 6 | 7 | SRCS = src/imx8qm.c src/imx8qx.c src/mkimage_imx8.c 8 | 9 | ifeq ($(SOC), iMX8M) 10 | DTBS ?= fsl-imx8mq-evk.dtb 11 | EXTRAS := dtbs=$(DTBS) 12 | endif 13 | 14 | vpath $(INCLUDE) 15 | 16 | .PHONY: clean all bin 17 | 18 | .DEFAULT: 19 | @$(MAKE) -s --no-print-directory bin 20 | @$(MAKE) ${EXTRAS} --no-print-directory -C $(SOC) -f soc.mak $@ 21 | 22 | #print out usage as the default target 23 | all: $(MKIMG) help 24 | 25 | clean: 26 | @rm -f $(MKIMG) 27 | @rm -f src/build_info.h 28 | @$(MAKE) --no-print-directory -C iMX8QM -f soc.mak clean 29 | @$(MAKE) --no-print-directory -C iMX8QX -f soc.mak clean 30 | @$(MAKE) --no-print-directory -C iMX8M -f soc.mak clean 31 | @$(MAKE) --no-print-directory -C iMX8dv -f soc.mak clean 32 | 33 | $(MKIMG): buildinfo $(SRCS) 34 | @echo "Compiling mkimage_imx8" 35 | $(CC) $(CFLAGS) $(SRCS) -o $(MKIMG) -I src 36 | 37 | bin: $(MKIMG) 38 | 39 | buildinfo: 40 | @echo -n '#define MKIMAGE_COMMIT 0x' > src/build_info.h 41 | @git rev-parse --short=8 HEAD >> src/build_info.h 42 | @echo '' >> src/build_info.h 43 | 44 | help: 45 | @echo $(CURR_DIR) 46 | @echo "usage ${MAKE} SOC= [TARGET]" 47 | @echo "i.e. ${MAKE} SOC=iMX8QX flash_dcd" 48 | @echo "Common Targets:" 49 | @echo 50 | @echo "Parts with SCU" 51 | @echo " flash_scfw - Only boot SCU" 52 | @echo " flash_dcd - SCU + AP cluster with DCDs" 53 | @echo " flash - SCU + AP (no DCD)" 54 | @echo " flash_flexspi - SCU + AP (FlexSPI device) " 55 | @echo " flash_cm4_0 - SCU + M4_0 w/ DCDs " 56 | @echo " flash_all - SCU + AP + M4 + SCD + CSF(AP & SCU) w/ DCDs" 57 | @echo "" 58 | @echo "Parts w/o SCU" 59 | @echo " flash_hdmi_spl_uboot - HDMI FW + u-boot spl" 60 | @echo " flash_hdmi_spl_uboot_tee - HDMI FW + u-boot spl w/ tee" 61 | @echo " flash_spl_uboot - u-boot spl" 62 | @echo " flash_spl_uboot_tee - u-boot spl w/tee" 63 | @echo 64 | @echo "Typical flash cmd: dd if=iMX8QM/flash.bin of=/dev/ bs=1k seek=33" 65 | @echo 66 | 67 | -------------------------------------------------------------------------------- /iMX8M/README: -------------------------------------------------------------------------------- 1 | Build Guide 2 | 3 | imx-mkimage is used to combine input images and generate final boot image with appropriate IVT set. 4 | Before building the boot image, need to prepare the input images first: 5 | 6 | 1. DDR PHY firmware images (Mandatory, used for all targets) 7 | Files: lpddr4_pmu_train_imem.bin and lpddr4_pmu_train_dmem.bin 8 | Git: ssh://git@sw-stash.freescale.net/imx/linux-firmware-imx.git 9 | Directory: firmware/ddr/synopsys 10 | 11 | 2. u-boot and SPL images (Mandatory, used for all targets) 12 | Files: u-boot.bin and u-boot-spl.bin 13 | Git: ssh://git@sw-stash.freescale.net/imx/uboot-imx.git 14 | Directory: ./u-boot.bin and spl/u-boot-spl.bin 15 | Build command: make imx8mq_evk_defconfig; make 16 | 17 | 3. ATF image (Mandatory, used for all targets) 18 | File: bl31.bin 19 | Git: ssh://git@sw-stash.freescale.net/imx/arm-trusted-firmware.git 20 | Directory: build/imx8mq/release 21 | Build command: make PLAT=imx8mq 22 | 23 | 4. HDMI firmware image (flash_hdmi_spl_uboot and flash_hdmi_spl_uboot_tee) 24 | File: hdmi_imx8m.bin 25 | Git: ssh://git@sw-stash.freescale.net/imx/linux-firmware-imx.git 26 | Directory: firmware/hdmi/cadence 27 | 28 | 5. Optee image (flash_hdmi_spl_uboot_tee and flash_spl_uboot_tee) 29 | File: tee.bin 30 | Git: ssh://git@sw-stash.freescale.net/imx/imx-optee-os.git 31 | -------------------------------------------------------------------------------- /iMX8M/mkimage_fit_atf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # script to generate FIT image source for i.MX8MQ boards with 4 | # ARM Trusted Firmware and multiple device trees (given on the command line) 5 | # 6 | # usage: $0 [ [&2 12 | exit 0 13 | else 14 | echo "bl31.bin size: " >&2 15 | ls -lct bl31.bin | awk '{print $5}' >&2 16 | fi 17 | 18 | BL32="tee.bin" 19 | 20 | if [ ! -f $BL32 ]; then 21 | BL32=/dev/null 22 | else 23 | echo "Building with TEE support, make sure your bl31 is compiled with spd. If you do not want tee, please delete tee.bin" >&2 24 | echo "tee.bin size: " >&2 25 | ls -lct tee.bin | awk '{print $5}' >&2 26 | fi 27 | 28 | BL33="u-boot-nodtb.bin" 29 | 30 | if [ ! -f $BL33 ]; then 31 | echo "ERROR: $BL33 file NOT found" >&2 32 | exit 0 33 | else 34 | 35 | echo "u-boot-nodtb.bin size: " >&2 36 | ls -lct u-boot-nodtb.bin | awk '{print $5}' >&2 37 | fi 38 | 39 | for dtname in $* 40 | do 41 | echo "$dtname size: " >&2 42 | ls -lct $dtname | awk '{print $5}' >&2 43 | done 44 | 45 | 46 | cat << __HEADER_EOF 47 | /dts-v1/; 48 | 49 | / { 50 | description = "Configuration to load ATF before U-Boot"; 51 | 52 | images { 53 | uboot@1 { 54 | description = "U-Boot (64-bit)"; 55 | data = /incbin/("$BL33"); 56 | type = "standalone"; 57 | arch = "arm64"; 58 | compression = "none"; 59 | load = <0x40200000>; 60 | }; 61 | atf@1 { 62 | description = "ARM Trusted Firmware"; 63 | data = /incbin/("$BL31"); 64 | type = "firmware"; 65 | arch = "arm64"; 66 | compression = "none"; 67 | load = <0x00910000>; 68 | entry = <0x00910000>; 69 | }; 70 | __HEADER_EOF 71 | 72 | if [ -f $BL32 ]; then 73 | cat << __HEADER_EOF 74 | tee@1 { 75 | description = "TEE firmware"; 76 | data = /incbin/("$BL32"); 77 | type = "firmware"; 78 | arch = "arm64"; 79 | compression = "none"; 80 | load = <0xfe000000>; 81 | entry = <0xfe000000>; 82 | }; 83 | __HEADER_EOF 84 | fi 85 | 86 | cnt=1 87 | for dtname in $* 88 | do 89 | cat << __FDT_IMAGE_EOF 90 | fdt@$cnt { 91 | description = "$(basename $dtname .dtb)"; 92 | data = /incbin/("$dtname"); 93 | type = "flat_dt"; 94 | compression = "none"; 95 | }; 96 | __FDT_IMAGE_EOF 97 | cnt=$((cnt+1)) 98 | done 99 | 100 | cat << __CONF_HEADER_EOF 101 | }; 102 | configurations { 103 | default = "config@1"; 104 | 105 | __CONF_HEADER_EOF 106 | 107 | cnt=1 108 | for dtname in $* 109 | do 110 | if [ -f $BL32 ]; then 111 | cat << __CONF_SECTION_EOF 112 | config@$cnt { 113 | description = "$(basename $dtname .dtb)"; 114 | firmware = "uboot@1"; 115 | loadables = "atf@1", "tee@1"; 116 | fdt = "fdt@$cnt"; 117 | }; 118 | __CONF_SECTION_EOF 119 | else 120 | cat << __CONF_SECTION1_EOF 121 | config@$cnt { 122 | description = "$(basename $dtname .dtb)"; 123 | firmware = "uboot@1"; 124 | loadables = "atf@1"; 125 | fdt = "fdt@$cnt"; 126 | }; 127 | __CONF_SECTION1_EOF 128 | fi 129 | cnt=$((cnt+1)) 130 | done 131 | 132 | cat << __ITS_EOF 133 | }; 134 | }; 135 | __ITS_EOF 136 | -------------------------------------------------------------------------------- /iMX8M/print_fit_hab.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BL32="tee.bin" 4 | 5 | let fit_off=$1 6 | 7 | # We dd flash.bin to 33KB "0x8400" offset, so need minus 0x8400 8 | let uboot_sign_off=$((fit_off - 0x8400 + 0x3000)) 9 | let uboot_size=$(stat --printf="%s" u-boot-nodtb.bin) 10 | let uboot_load_addr=0x40200000 11 | 12 | let atf_sign_off=$((uboot_sign_off + uboot_size)) 13 | let atf_load_addr=0x910000 14 | let atf_size=$(stat --printf="%s" bl31.bin) 15 | 16 | if [ ! -f $BL32 ]; then 17 | let tee_size=0x0 18 | let tee_sign_off=$((atf_sign_off + atf_size)) 19 | else 20 | let tee_size=$(stat --printf="%s" tee.bin) 21 | 22 | let tee_sign_off=$((atf_sign_off + atf_size)) 23 | let tee_load_addr=0xfe000000 24 | fi 25 | 26 | let last_sign_off=$((tee_sign_off + tee_size)) 27 | let last_size=$((tee_size)) 28 | let last_load_addr=$((uboot_load_addr + uboot_size)) 29 | 30 | uboot_size=`printf "0x%X" ${uboot_size}` 31 | uboot_sign_off=`printf "0x%X" ${uboot_sign_off}` 32 | uboot_load_addr=`printf "0x%X" ${uboot_load_addr}` 33 | 34 | tee_size=`printf "0x%X" ${tee_size}` 35 | tee_sign_off=`printf "0x%X" ${tee_sign_off}` 36 | tee_load_addr=`printf "0x%X" ${tee_load_addr}` 37 | 38 | atf_size=`printf "0x%X" ${atf_size}` 39 | atf_sign_off=`printf "0x%X" ${atf_sign_off}` 40 | atf_load_addr=`printf "0x%X" ${atf_load_addr}` 41 | 42 | echo ${uboot_load_addr} ${uboot_sign_off} ${uboot_size} 43 | echo ${atf_load_addr} ${atf_sign_off} ${atf_size} 44 | 45 | if [ ${tee_size} != 0 ] 46 | then 47 | echo ${tee_load_addr} ${tee_sign_off} ${tee_size} 48 | fi 49 | 50 | cnt=0 51 | for dtname in $* 52 | do 53 | if [ ${cnt} != 0 ] 54 | then 55 | let fdt${cnt}_size=$(stat --printf="%s" $dtname) 56 | 57 | let fdt${cnt}_sign_off=$((last_sign_off)) 58 | let fdt${cnt}_load_addr=$((last_load_addr)) 59 | let last_size=$((fdt${cnt}_size)) 60 | 61 | fdt_size=`printf "0x%X" ${last_size}` 62 | fdt_sign_off=`printf "0x%X" ${last_sign_off}` 63 | fdt_load_addr=`printf "0x%X" ${last_load_addr}` 64 | 65 | let last_sign_off=$((last_sign_off + fdt${cnt}_size)) 66 | let last_load_addr=$((last_load_addr + fdt${cnt}_size)) 67 | 68 | echo ${fdt_load_addr} ${fdt_sign_off} ${fdt_size} 69 | fi 70 | 71 | cnt=$((cnt+1)) 72 | done 73 | -------------------------------------------------------------------------------- /iMX8M/soc.mak: -------------------------------------------------------------------------------- 1 | MKIMG = mkimage_imx8 2 | OUTIMG = flash.bin 3 | DCD_CFG_SRC = imx8mq_dcd.cfg 4 | DCD_CFG = imx8mq_dcd.cfg.tmp 5 | 6 | CC ?= gcc 7 | CFLAGS ?= -O2 -Wall -std=c99 -static 8 | INCLUDE = ./lib 9 | 10 | $(MKIMG): mkimage_imx8.c 11 | @echo "Compiling mkimage_imx8" 12 | $(CC) $(CFLAGS) mkimage_imx8.c -o $(MKIMG) -lz 13 | 14 | $(DCD_CFG): $(DCD_CFG_SRC) 15 | @echo "Converting iMX8M DCD file" 16 | $(CC) -E -Wp,-MD,.imx8mq_dcd.cfg.cfgtmp.d -nostdinc -Iinclude -I$(INCLUDE) -x c -o $(DCD_CFG) $(DCD_CFG_SRC) 17 | 18 | u-boot-spl-lpddr4.bin: u-boot-spl.bin lpddr4_pmu_train_1d_imem.bin lpddr4_pmu_train_1d_dmem.bin lpddr4_pmu_train_2d_imem.bin lpddr4_pmu_train_2d_dmem.bin 19 | @objcopy -I binary -O binary --pad-to 0x8000 --gap-fill=0x0 lpddr4_pmu_train_1d_imem.bin lpddr4_pmu_train_1d_imem_pad.bin 20 | @objcopy -I binary -O binary --pad-to 0x4000 --gap-fill=0x0 lpddr4_pmu_train_1d_dmem.bin lpddr4_pmu_train_1d_dmem_pad.bin 21 | @objcopy -I binary -O binary --pad-to 0x8000 --gap-fill=0x0 lpddr4_pmu_train_2d_imem.bin lpddr4_pmu_train_2d_imem_pad.bin 22 | @cat lpddr4_pmu_train_1d_imem_pad.bin lpddr4_pmu_train_1d_dmem_pad.bin > lpddr4_pmu_train_1d_fw.bin 23 | @cat lpddr4_pmu_train_2d_imem_pad.bin lpddr4_pmu_train_2d_dmem.bin > lpddr4_pmu_train_2d_fw.bin 24 | @cat u-boot-spl.bin lpddr4_pmu_train_1d_fw.bin lpddr4_pmu_train_2d_fw.bin > $@ 25 | @rm -f lpddr4_pmu_train_1d_fw.bin lpddr4_pmu_train_2d_fw.bin lpddr4_pmu_train_1d_imem_pad.bin lpddr4_pmu_train_1d_dmem_pad.bin lpddr4_pmu_train_2d_imem_pad.bin 26 | 27 | u-boot-spl-ddr4.bin: u-boot-spl.bin ddr4_imem_1d.bin ddr4_dmem_1d.bin ddr4_imem_2d.bin ddr4_dmem_2d.bin 28 | @objcopy -I binary -O binary --pad-to 0x8000 --gap-fill=0x0 ddr4_imem_1d.bin ddr4_imem_1d_pad.bin 29 | @objcopy -I binary -O binary --pad-to 0x4000 --gap-fill=0x0 ddr4_dmem_1d.bin ddr4_dmem_1d_pad.bin 30 | @objcopy -I binary -O binary --pad-to 0x8000 --gap-fill=0x0 ddr4_imem_2d.bin ddr4_imem_2d_pad.bin 31 | @cat ddr4_imem_1d_pad.bin ddr4_dmem_1d_pad.bin > ddr4_1d_fw.bin 32 | @cat ddr4_imem_2d_pad.bin ddr4_dmem_2d.bin > ddr4_2d_fw.bin 33 | @cat u-boot-spl.bin ddr4_1d_fw.bin ddr4_2d_fw.bin > $@ 34 | @rm -f ddr4_1d_fw.bin ddr4_2d_fw.bin ddr4_imem_1d_pad.bin ddr4_dmem_1d_pad.bin ddr4_imem_2d_pad.bin 35 | 36 | u-boot-spl-ddr3l.bin: u-boot-spl.bin ddr3_imem_1d.bin ddr3_dmem_1d.bin 37 | @objcopy -I binary -O binary --pad-to 0x8000 --gap-fill=0x0 ddr3_imem_1d.bin ddr3_imem_1d.bin_pad.bin 38 | @cat ddr3_imem_1d.bin_pad.bin ddr3_dmem_1d.bin > ddr3_pmu_train_fw.bin 39 | @cat u-boot-spl.bin ddr3_pmu_train_fw.bin > $@ 40 | @rm -f ddr3_pmu_train_fw.bin ddr3_imem_1d.bin_pad.bin 41 | 42 | u-boot-atf.bin: u-boot.bin bl31.bin 43 | @cp bl31.bin $@ 44 | @dd if=u-boot.bin of=$@ bs=1K seek=128 45 | 46 | u-boot-atf-tee.bin: u-boot.bin bl31.bin tee.bin 47 | @cp bl31.bin $@ 48 | @dd if=tee.bin of=$@ bs=1K seek=128 49 | @dd if=u-boot.bin of=$@ bs=1M seek=1 50 | 51 | .PHONY: clean 52 | clean: 53 | @rm -f $(MKIMG) $(DCD_CFG) .imx8mq_dcd.cfg.cfgtmp.d u-boot-atf.bin u-boot-atf-tee.bin u-boot-spl-lpddr4.bin u-boot-lpddr4.itb u-boot.its u-boot-ddr3l.itb u-boot-ddr3l.its u-boot-spl-ddr3l.bin u-boot-ddr4.itb u-boot-ddr4.its u-boot-spl-ddr4.bin $(OUTIMG) 54 | 55 | u-boot-%.itb: $(dtbs) 56 | ./mkimage_fit_atf.sh $(dtbs) > u-boot.its 57 | ./mkimage_uboot -E -p 0x3000 -f u-boot.its $@ 58 | @rm -f u-boot.its 59 | 60 | flash_lpddr4: $(MKIMG) signed_hdmi_imx8m.bin u-boot-spl-lpddr4.bin u-boot-lpddr4.itb 61 | ./mkimage_imx8 -fit -signed_hdmi signed_hdmi_imx8m.bin -loader u-boot-spl-lpddr4.bin 0x7E1000 -second_loader u-boot-lpddr4.itb 0x40200000 0x60000 -out $(OUTIMG) 62 | 63 | flash_ddr3l: $(MKIMG) signed_hdmi_imx8m.bin u-boot-spl-ddr3l.bin u-boot-ddr3l.itb 64 | ./mkimage_imx8 -fit -signed_hdmi signed_hdmi_imx8m.bin -loader u-boot-spl-ddr3l.bin 0x7E1000 -second_loader u-boot-ddr3l.itb 0x40200000 0x60000 -out $(OUTIMG) 65 | 66 | flash_ddr4: $(MKIMG) signed_hdmi_imx8m.bin u-boot-spl-ddr4.bin u-boot-ddr4.itb 67 | ./mkimage_imx8 -fit -signed_hdmi signed_hdmi_imx8m.bin -loader u-boot-spl-ddr4.bin 0x7E1000 -second_loader u-boot-ddr4.itb 0x40200000 0x60000 -out $(OUTIMG) 68 | 69 | flash_lpddr4_no_hdmi: $(MKIMG) u-boot-spl-lpddr4.bin u-boot-lpddr4.itb 70 | ./mkimage_imx8 -fit -loader u-boot-spl-lpddr4.bin 0x7E1000 -second_loader u-boot-lpddr4.itb 0x40200000 0x60000 -out $(OUTIMG) 71 | 72 | flash_ddr3l_no_hdmi: $(MKIMG) u-boot-spl-ddr3l.bin u-boot-ddr3l.itb 73 | ./mkimage_imx8 -fit -loader u-boot-spl-ddr3l.bin 0x7E1000 -second_loader u-boot-ddr3l.itb 0x40200000 0x60000 -out $(OUTIMG) 74 | 75 | flash_ddr4_no_hdmi: $(MKIMG) u-boot-spl-ddr4.bin u-boot-ddr4.itb 76 | ./mkimage_imx8 -fit -loader u-boot-spl-ddr4.bin 0x7E1000 -second_loader u-boot-ddr4.itb 0x40200000 0x60000 -out $(OUTIMG) 77 | 78 | flash_hdmi_spl_uboot: flash_lpddr4 79 | flash_ddr3l_hdmi_spl_uboot: flash_ddr3l 80 | flash_ddr4_hdmi_spl_uboot: flash_ddr4 81 | flash_lpddr4_hdmi_spl_uboot: flash_lpddr4 82 | 83 | flash_spl_uboot: flash_lpddr4_no_hdmi 84 | flash_ddr3l_spl_uboot: flash_ddr3l_no_hdmi 85 | flash_ddr4_spl_uboot: flash_ddr4_no_hdmi 86 | flash_lpddr4_spl_uboot: flash_lpddr4_no_hdmi 87 | 88 | print_fit_hab: u-boot-nodtb.bin bl31.bin $(dtbs) 89 | ./print_fit_hab.sh 0x60000 $(dtbs) 90 | 91 | #flash_dcd_uboot: $(MKIMG) $(DCD_CFG) u-boot-atf.bin 92 | # ./mkimage_imx8 -dcd $(DCD_CFG) -loader u-boot-atf.bin 0x40001000 -out $(OUTIMG) 93 | 94 | #flash_plugin: $(MKIMG) plugin.bin u-boot-spl-for-plugin.bin 95 | # ./mkimage_imx8 -plugin plugin.bin 0x912800 -loader u-boot-spl-for-plugin.bin 0x7F0000 -out $(OUTIMG) 96 | -------------------------------------------------------------------------------- /iMX8QM/expand_c_define.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #################################################################### 4 | # 5 | # Copyright (c) 2017 NXP 6 | # All rights reserved. 7 | # 8 | #################################################################### 9 | 10 | # usage: 11 | # cat ../../imx-sc-firmware/firmware/platform/board/mx8qm_val/ddrc/ddrc_mem_map.h | ./expand_c_define.sh > ddrc_mem_map.h 12 | # cat ../../imx-sc-firmware/firmware/platform/board/mx8qm_val/ddrc/ddr_phy_mem_map.h | ./expand_c_define.sh > ddr_phy_mem_map.h 13 | 14 | # This script parses a register mapping file from imx-sc-firmware (C header 15 | # file with register base addresse and register offset definitions). 16 | # 17 | # This script evaluates an arithmetic expression to get the register 18 | # addresses for iMX8QM. 19 | # Its creates new C #define for each instance of the DDR (#0, #1). 20 | # 21 | # This script parses a C header file like: 22 | # '#define DDRC_MSTR(X) REG32(DDRC_BASE_ADDR(X) + 0x00)' 23 | # and converts it to (last arithmetic expression is evaluated) 24 | # '#define DDRC_MSTR_0 0x5c000000' 25 | # '#define DDRC_MSTR_1 0x5c100000' 26 | 27 | # search for the register map BASE_ADDR definition 28 | # Search for a line like: 29 | # #define DDR_PHY_BASE_ADDR(X) 0x5c000000 + ((X * 0x100000) + 0x10000) 30 | base_found=0 31 | while IFS= read -r line 32 | do 33 | echo "$line" 34 | base_addr_name=$(echo "$line" | sed -n -e "s/^#define *\([^ ]*_BASE_ADDR(X)\) *\(.*\)/\1/p") 35 | #base_addr_expr="$(echo $line | sed -n -e 's/^#define *\([^ ]*_BASE_ADDR(X)\) *\(.*\)/\2/p')" 36 | base_addr_expr=$(echo "$line" | sed -n -e 's/^#define *\([^ ]*_BASE_ADDR(X)\) *\(.*\)$/\2/p') 37 | #echo "$base_addr_expr" 38 | if [ "${base_addr_name}X" != "X" ] 39 | then 40 | base_found=1 41 | break 42 | fi 43 | done 44 | 45 | # find register definitions and evaluate register addresses 46 | # For example the following line: 47 | # #define DDRC_MSTR(X) REG32(DDRC_BASE_ADDR(X) + 0x00) 48 | # is expanded to: 49 | # #define DDRC_MSTR_0 0x5c000000 50 | # #define DDRC_MSTR_1 0x5c100000 51 | 52 | while IFS= read -r line 53 | do 54 | echo "$line" 55 | # substitute BASE_ADDR(X) with the macro value 56 | line=$(echo "$line" | sed -n -e "s/${base_addr_name}/${base_addr_expr}/p") 57 | # extract register name and arithmetic expression 58 | reg_name=$(echo "$line" | sed -n -e "s/^#define *\([^(]*\)(X)[[:space:]]*REG32(\(.*\))$/\1/p") 59 | reg_value=$(echo "$line" | sed -n -e "s/^#define *\([^(]*\)(X)[[:space:]]*REG32(\(.*\))$/\2/p") 60 | #echo "$reg_name" "$reg_value" 61 | if [ "${reg_name}X" != "X" ] 62 | then 63 | # enumerate X from 0 to the number of DDR 64 | for instance in 0 1 65 | do 66 | tmp=$(echo "$reg_value" | sed -n -e "s/(X/(${instance}/p") 67 | printf "#define %-23s 0x%x\n" "${reg_name}_${instance}" $(($tmp)) 68 | done 69 | fi 70 | done 71 | 72 | exit 0 73 | -------------------------------------------------------------------------------- /iMX8QM/soc.mak: -------------------------------------------------------------------------------- 1 | MKIMG = ../mkimage_imx8 2 | #DCD_CFG_SRC = imx8qm_dcd_800MHz.cfg 3 | #DCD_CFG_SRC = imx8qm_dcd_1.2GHz.cfg 4 | DCD_CFG_SRC = imx8qm_dcd_1.6GHz.cfg 5 | 6 | DCD_CFG = imx8qm_dcd.cfg.tmp 7 | 8 | CC ?= gcc 9 | INCLUDE = ./lib 10 | 11 | #set default DDR_training to be in DCDs 12 | 13 | DDR_TRAIN ?= 1 14 | WGET = /usr/bin/wget 15 | N ?= latest 16 | SERVER=http://yb2.am.freescale.net 17 | DIR = build-output/Linux_IMX_MX8/$(N)/common_bsp 18 | 19 | ifneq ($(wildcard /usr/bin/rename.ul),) 20 | RENAME = rename.ul 21 | else 22 | RENAME = rename 23 | endif 24 | 25 | 26 | $(DCD_CFG): FORCE 27 | @echo "Converting iMX8 DCD file" 28 | $(CC) -E -Wp,-MD,.imx8qm_dcd.cfg.cfgtmp.d -nostdinc -Iinclude -I$(INCLUDE) -DDDR_TRAIN_IN_DCD=$(DDR_TRAIN) -x c -o $(DCD_CFG) $(DCD_CFG_SRC) 29 | 30 | FORCE: 31 | 32 | u-boot-atf.bin: u-boot.bin bl31.bin 33 | @cp bl31.bin u-boot-atf.bin 34 | ./$(MKIMG) -commit > head.hash 35 | @cat u-boot.bin head.hash > u-boot-hash.bin 36 | @dd if=u-boot-hash.bin of=u-boot-atf.bin bs=1K seek=128 37 | @if [ ! -d "hdmitxfw.bin" ]; then \ 38 | cp u-boot-atf.bin u-boot-atf-b.bin; \ 39 | objcopy -I binary -O binary --pad-to 0x20000 --gap-fill=0x0 hdmitxfw.bin hdmitxfw-pad.bin; \ 40 | cat u-boot-atf.bin hdmitxfw-pad.bin > u-boot-atf-hdmi.bin; \ 41 | cp u-boot-atf-hdmi.bin u-boot-atf.bin; \ 42 | fi 43 | 44 | .PHONY: clean 45 | clean: 46 | @rm -f $(DCD_CFG) .imx8_dcd.cfg.cfgtmp.d 47 | 48 | flash_scfw: $(MKIMG) scfw_tcm.bin 49 | ./$(MKIMG) -soc QM -c -scfw scfw_tcm.bin -out flash.bin 50 | 51 | flash_dcd: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 52 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a53 0x80000000 -out flash.bin 53 | 54 | flash: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 55 | ./$(MKIMG) -soc QM -c -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a53 0x80000000 -out flash.bin 56 | 57 | flash_early: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 58 | ./$(MKIMG) -soc QM -c -flags 0x00400000 -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a53 0x80000000 -out flash.bin 59 | 60 | flash_flexspi: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 61 | ./$(MKIMG) -soc QM -c -dev flexspi -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a53 0x80000000 -out flash.bin 62 | 63 | flash_ca72: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 64 | ./$(MKIMG) -soc QM -c -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a72 0x80000000 -out flash.bin 65 | 66 | flash_multi_cores: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m40_tcm.bin m41_tcm.bin u-boot-atf.bin 67 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m40_tcm.bin 0 0x34FE0000 -m4 m41_tcm.bin 1 0x38FE0000 -c -ap u-boot-atf.bin a53 0x80000000 -out flash.bin 68 | 69 | flash_cm4_0: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m4_image.bin 70 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m4_image.bin 0 0x34FE0000 -out flash.bin 71 | 72 | flash_cm4_1: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m4_image.bin 73 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m4_image.bin 1 0x38FE0000 -out flash.bin 74 | 75 | flash_m4s_tcm: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m40_tcm.bin m41_tcm.bin 76 | ./$(MKIMG) -soc QM -c -scfw scfw_tcm.bin -m4 m40_tcm.bin 0 0x34FE0000 -m4 m41_tcm.bin 1 0x38FE0000 -out flash.bin 77 | 78 | flash_all: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m4_image.bin u-boot-atf.bin scd.bin csf.bin csf_ap.bin 79 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m4_image.bin 0 0x34FE0000 -csf csf.bin -scd scd.bin -c -ap u-boot-atf.bin a53 0x80000000 -csf csf_ap.bin -out flash.bin 80 | 81 | flash_ca72_ddrstress: $(MKIMG) scfw_tcm.bin mx8qm_ddr_stress_test.bin 82 | ./$(MKIMG) -soc QM -c -flags 0x00800000 -scfw scfw_tcm.bin -c -ap mx8qm_ddr_stress_test.bin a72 0x00112000 -out flash.bin 83 | 84 | flash_ca53_ddrstress: $(MKIMG) scfw_tcm.bin mx8qm_ddr_stress_test.bin 85 | ./$(MKIMG) -soc QM -c -flags 0x00800000 -scfw scfw_tcm.bin -c -ap mx8qm_ddr_stress_test.bin a53 0x00112000 -out flash.bin 86 | 87 | flash_ca72_ddrstress_dcd: $(MKIMG) $(DCD_CFG) scfw_tcm.bin mx8qm_ddr_stress_test.bin 88 | ./$(MKIMG) -soc QM -c -flags 0x00800000 -dcd $(DCD_CFG) -scfw scfw_tcm.bin -c -ap mx8qm_ddr_stress_test.bin a72 0x00112000 -out flash.bin 89 | 90 | flash_ca53_ddrstress_dcd: $(MKIMG) $(DCD_CFG) scfw_tcm.bin mx8qm_ddr_stress_test.bin 91 | ./$(MKIMG) -soc QM -c -flags 0x00800000 -dcd $(DCD_CFG) -scfw scfw_tcm.bin -c -ap mx8qm_ddr_stress_test.bin a53 0x00112000 -out flash.bin 92 | 93 | flash_cm4_01_ddr: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m40_ddr.bin m41_ddr.bin 94 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m40_ddr.bin 0 0x88000000 -m4 m41_ddr.bin 1 0x88800000 -out flash.bin 95 | 96 | flash_m4_tcm_ddr: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m4_image.bin m41_ddr.bin 97 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m4_image.bin 0 0x34FE0000 -m4 m41_ddr.bin 1 0x88800000 -out flash.bin 98 | 99 | flash_cm4_1_ddr: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m41_ddr.bin 100 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m41_ddr.bin 1 0x88800000 -out flash.bin 101 | 102 | flash_fastboot: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 103 | ./$(MKIMG) -soc QM -dev emmc_fast -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m4_image.bin 0 0x34fe0000 -ap u-boot-atf.bin a53 0x80000000 -out flash.bin 104 | 105 | flash_aprom_ddr: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin aprom_ddr.bin csf_ap.bin 106 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -ap aprom_ddr.bin a53 0x80000000 -c -ap u-boot-atf.bin a53 0x90000000 -csf csf_ap.bin -out flash.bin 107 | 108 | flash_aprom_ddr_unsigned: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin aprom_ddr.bin csf_ap.bin 109 | ./$(MKIMG) -soc QM -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -ap aprom_ddr.bin a53 0x80000000 -c -ap u-boot-atf.bin a53 0x90000000 -out flash.bin 110 | 111 | 112 | nightly : 113 | @rm -rf boot 114 | @$(WGET) -q $(SERVER)/$(DIR)/imx-boot/imx-boot-tools/imx8qm/mx8qm-scfw-tcm.bin -O scfw_tcm.bin 115 | @$(WGET) -q $(SERVER)/$(DIR)/imx-boot/imx-boot-tools/imx8qm/bl31-imx8qm.bin -O bl31.bin 116 | @$(WGET) -q $(SERVER)/$(DIR)/imx-boot/imx-boot-tools/imx8qm/u-boot-imx8qmlpddr4arm2.bin-sd -O u-boot.bin 117 | @$(WGET) -qr -nd -l1 -np $(SERVER)/$(DIR) -P boot -A "Image-fsl-imx8qm-*.dtb" 118 | @$(WGET) -q $(SERVER)/$(DIR)/Image-imx8_all.bin -O Image 119 | @mv -f Image boot 120 | @$(RENAME) "Image-" "" boot/*.dtb 121 | 122 | -------------------------------------------------------------------------------- /iMX8QX/imx8qx_dcd_1.2GHz.cfg: -------------------------------------------------------------------------------- 1 | #define __ASSEMBLY__ 2 | 3 | #include 4 | #include 5 | 6 | /* 7 | * Device Configuration Data (DCD) 8 | * 9 | * Each entry must have the format: 10 | * Addr-type Address Value 11 | * 12 | * where: 13 | * Addr-type register length (1,2 or 4 bytes) 14 | * Address absolute address of the register 15 | * value value to be stored in the register 16 | */ 17 | 18 | #ifndef SCFW_DCD 19 | /* For 1200MHz DDR, DRC 600MHz operation */ 20 | DATA 4 0xff190000 0x00000CC8 /* DRC0 bringup */ 21 | #else 22 | /* Set the DRC rate to 1.2GHz. */ 23 | uint32_t rate2 = SC_600MHZ; 24 | pm_set_clock_rate(SC_PT, SC_R_DRC_0, SC_PM_CLK_MISC0, &rate2); 25 | #endif 26 | 27 | DATA 4 0x41C80208 0x1 28 | 29 | DATA 4 0x41C80040 0xb 30 | 31 | DATA 4 0x41C80204 0x1 32 | 33 | /* DRAM 0 controller configuration begin */ 34 | DATA 4 DDRC_MSTR_0 0xC3080020 // Set LPDDR4, BL = 16 and active ranks 35 | DATA 4 DDRC_RFSHTMG_0 0x004800A9 // tREFI, tRFC 36 | DATA 4 DDRC_INIT0_0 0x4003049A // pre_cke = 2ms is too long - LPDDR4 model hacked for 20us 37 | DATA 4 DDRC_INIT1_0 0x007A0000 // dram_rstn - LPDDR4 model hacked for 20us; 38 | DATA 4 DDRC_INIT3_0 0x00440024 // MR1=0x54: nWR=30 BL=16; MR2=0x2d: RL=28 WL=14 39 | //DATA 4 DDRC_INIT4_0 0x00310000 // MR3, MR13 40 | DATA 4 DDRC_INIT4_0 0x00F10000 // MR3=0xF1: DBI-WR=DBI-RD=1, PU-CAL=VDDQ/3 PDDS=RZQ/6, MR13 41 | //DATA 4 DDRC_RANKCTL_0 0x0000075f // diff_rank_wr_gap, diff_rank_rd_gap, max_rank_rd 42 | DATA 4 DDRC_RANKCTL_0 0x0000066f // diff_rank_wr_gap, diff_rank_rd_gap, max_rank_rd, waiting for SNPS feedback 43 | DATA 4 DDRC_DRAMTMG0_0 0x1619141a // wr2pr, tFAW, tRASmax, tRASmin 44 | DATA 4 DDRC_DRAMTMG1_0 0x00050527 // tXP, rd2pre, tRC 45 | //DATA 4 DDRC_DRAMTMG2_0 0x060c1011 // WL, RL, rd2wr, wr2rd 46 | DATA 4 DDRC_DRAMTMG2_0 0x060E1111 // WL, RL (DBI enabled, 28), rd2wr, wr2rd 47 | DATA 4 DDRC_DRAMTMG3_0 0x0090900a // tmrw, tmrd, tmod 48 | DATA 4 DDRC_DRAMTMG4_0 0x0c04070c // trcd, tccd, trrd, trp 49 | DATA 4 DDRC_DRAMTMG5_0 0x02040a05 // tCKCKEH, tCKCKEL, tckesr, tcke 50 | DATA 4 DDRC_DRAMTMG6_0 0x02020006 // tckdpde, tckdpdx, tckcsx 51 | DATA 4 DDRC_DRAMTMG7_0 0x00000401 // tckpde, tckpdx 52 | DATA 4 DDRC_DRAMTMG12_0 0x00020510 // tCMDCKE, tCKEHCMD (=tXP?) 53 | DATA 4 DDRC_DRAMTMG13_0 0x0b100002 // tODTLoff, tCCDMW, tPPD 54 | DATA 4 DDRC_DRAMTMG14_0 0x000000ae // txsr 55 | DATA 4 DDRC_ZQCTL0_0 0x425b0013 // tZQCAL, tZQLAT 56 | 57 | DATA 4 DDRC_ZQCTL1_0 0x01f00100 // tZQReset, tzq_short_interval 58 | 59 | //DATA 4 DDRC_DFITMG0_0 0x0495820a // dfi_t_ctrl_delay, dfi_t_rddata_en, dfi_tphy_wrdata, dfi_tphy_wrlat 60 | DATA 4 DDRC_DFITMG0_0 0x0499820a // dfi_t_ctrl_delay, dfi_t_rddata_en RL=28 with DBI enabled, dfi_tphy_wrdata, dfi_tphy_wrlat 61 | DATA 4 DDRC_DFITMG1_0 0x00070303 // dfi_t_wrdata_delay, dfi_t_dram_clk_disable, dfi_t_dram_clk_enable 62 | //DATA 4 DDRC_DFITMG2_0 0x00001308 // dfi_tphy_rdcslat, dfi_tphy_wrcslat 63 | DATA 4 DDRC_DFITMG2_0 0x00001708 // dfi_tphy_rdcslat RL=28 with DBI enabled, dfi_tphy_wrcslat 64 | DATA 4 DDRC_DFIMISC_0 0x00000005 // dfi_data_cs_polarity 65 | DATA 4 DDRC_DFIUPD0_0 0x00400003 // Disable the automatic dfi_ctrlupd_req generation 66 | DATA 4 DDRC_DFIUPD1_0 0x008000A0 // dfi_ctrlupd_req generation interval generation (min and max) 67 | DATA 4 DDRC_DFIUPD2_0 0x80000000 // dfi_phyupd_en 68 | 69 | DATA 4 DDRC_ADDRMAP0_0 0x00000015 // addrmap_cs_bit0 70 | DATA 4 DDRC_ADDRMAP4_0 0x00001F1F // addrmap_col_b10 and addrmap_col_b11 set to de-activated 71 | 72 | DATA 4 DDRC_ADDRMAP1_0 0x00080808 // addrmap_bank_b2, addrmap_bank_b1, addrmap_bank_b0 73 | DATA 4 DDRC_ADDRMAP5_0 0x07070707 // addrmap_row_b11, addrmap_row_b10_b2, addrmap_row_b1, addrmap_row_b0 74 | DATA 4 DDRC_ADDRMAP6_0 0x48080707 // addrmap_row_b15, addrmap_row_b14, addrmap_row_b13, addrmap_row_b12 75 | 76 | DATA 4 DDRC_DBICTL_0 0x00000007 // rd_dbi_en=wr_dbi_en=dm_en=1 77 | 78 | DATA 4 DDRC_ODTMAP_0 0x00002211 // rank[3:0]_wr_odt, rank[3:0]_wr_odt 79 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable port 0 80 | DATA 4 DDRC_HWLPCTL_0 0x0FFF0003 //Enable Hardware idle period - 96 * 32 DFI clk cycles 81 | 82 | //Enables DFI Low Power interface 83 | DATA 4 DDRC_DFILPCFG0_0 0x07009100 // dfi_lp_en_sr=1, dfi_lp_wakeup_sr=0x9 84 | 85 | DATA 4 DDRC_DFITMG0_SHADOW_0 0x00808000 86 | 87 | DATA 4 DDRC_PWRCTL_0 0x10A 88 | DATA 4 DDRC_PWRTMG_0 0xFF201F 89 | 90 | DATA 4 0x41C80208 0x1 91 | 92 | DATA 4 0x41C80040 0xf 93 | 94 | DATA 4 0x41C80204 0x1 95 | 96 | //------------------------------------------- 97 | // Configure registers for PHY initialization 98 | // Timings are computed for a PHY at 800MHz (DRAM at 1600MHz) 99 | //-------------------------------=------------ 100 | 101 | // Set-up DRAM Configuration Register 102 | DATA 4 DDR_PHY_DCR_0 0x0000040D // LPDDR4 selection with 8 bank 103 | 104 | // Set-up byte and bit swapping registers 105 | DATA 4 DDR_PHY_PGCR8_0 0x000F000A // Set BSWAPMSB='b1001 (byte 0 and 1 are swapped) 106 | DATA 4 DDR_PHY_DX0DQMAP0_0 0x00061032 // DQ bit 0/1/2/3/4 remapping 107 | DATA 4 DDR_PHY_DX0DQMAP1_0 0x00004578 // DQ bit 5/6/7 and DM remapping 108 | DATA 4 DDR_PHY_DX1DQMAP0_0 0x00071032 // DQ bit 0/1/2/3/4 remapping 109 | DATA 4 DDR_PHY_DX1DQMAP1_0 0x00004685 // DQ bit 5/6/7 and DM remapping 110 | DATA 4 DDR_PHY_DX2DQMAP0_0 0x00016578 // DQ bit 0/1/2/3/4 remapping 111 | DATA 4 DDR_PHY_DX2DQMAP1_0 0x00004203 // DQ bit 5/6/7 and DM remapping 112 | DATA 4 DDR_PHY_DX3DQMAP0_0 0x00015867 // DQ bit 0/1/2/3/4 remapping 113 | DATA 4 DDR_PHY_DX3DQMAP1_0 0x00004320 // DQ bit 5/6/7 and DM remapping 114 | DATA 4 DDR_PHY_CATR0_0 0x00141032 // Only for LPDDR3 but used here to know how LPDDR4 bytes are connected to PHY 115 | DATA 4 DDR_PHY_CATR1_0 0x0013AAAA // Only for LPDDR3 but used here to know how LPDDR4 bytes are connected to PHY 116 | 117 | // Set-up PHY General Configuration Register 118 | // PGCR1,4,5,6,7 are untouched 119 | SET_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=1 (no uMCTL2 commands can go to memory) 120 | DATA 4 DDR_PHY_PGCR0_0 0x87001E00 // Set ADCP=1 (Address Copy) 121 | DATA 4 DDR_PHY_PGCR2_0 0x00F0A190 // Set tREFPRD (9*3.904us - 600) 122 | DATA 4 DDR_PHY_PGCR3_0 0x050A1080 // CKEN/CKNEN toggling and polarity 123 | 124 | // Set-up PHY Timing Register 125 | // PTR2 is untouched 126 | DATA 4 DDR_PHY_PTR0_0 0x4B025810 // tPLLPD, tPLLGS, tPHYRST 127 | DATA 4 DDR_PHY_PTR1_0 0x3AA01520 // tPLLLOCK reduced to 4.3us, tPLLRST=9us 128 | 129 | // Set-up PLL Control Register 130 | DATA 4 DDR_PHY_PLLCR0_0 0x000E0000 // FREQSEL=0 131 | DATA 4 DDR_PHY_DX8SLbPLLCR0_0 0x000E0000 132 | 133 | // Set-up Impedance Control Register 134 | DATA 4 DDR_PHY_ZQCR_0 0x008A2C58 // Set ODT_MODE=0b10(LPDDR4 stype pullup) 135 | 136 | // ZPROG_DRAM_ODT and ZPROG_HOST_ODT = 60ohm 137 | //DATA 4 DDR_PHY_ZQ0PR0_0 0x0B7BB // comment is wrong => PU_DRV_ADJUST 3b001 = Adjust calibrated drive strength by 2/8 to obtain 1.25x of original strength 138 | //DATA 4 DDR_PHY_ZQ1PR0_0 0x0B7BB 139 | //DATA 4 DDR_PHY_ZQ2PR0_0 0x0B7BB 140 | //DATA 4 DDR_PHY_ZQ3PR0_0 0x0B7BB 141 | DATA 4 DDR_PHY_ZQ0PR0_0 0x1B7BB // PU_DRV_ADJUST 3b001 = Adjust calibrated drive strength by 2/8 to obtain 1.25x of original strength 142 | DATA 4 DDR_PHY_ZQ1PR0_0 0x1B7BB 143 | DATA 4 DDR_PHY_ZQ2PR0_0 0x1B7BB 144 | DATA 4 DDR_PHY_ZQ3PR0_0 0x1B7BB 145 | 146 | 147 | // Set-up PHY Initialization Register 148 | DATA 4 DDR_PHY_PIR_0 0x32 149 | 150 | // Launch initialization (set bit 0) 151 | DATA 4 DDR_PHY_PIR_0 0x33 152 | 153 | //------------------------------------------- 154 | // Configure registers for DRAM initialization 155 | //------------------------------------------- 156 | 157 | // Set-up Mode Register 158 | // MR0, MR3, MR4, MR5 MR6 are untouched 159 | DATA 4 DDR_PHY_MR1_0 0x44 // Set BL, WR-PRE, nWR=24, RPST 160 | DATA 4 DDR_PHY_MR2_0 0x24 // Set RL=14/WL=8 161 | //DATA 4 DDR_PHY_MR3_0 0x31 // Set drive strength (40 Ohms by default) 162 | DATA 4 DDR_PHY_MR3_0 0xF1 // Set drive strength (40 Ohms by default), DBI_RD=DBI_WR=1 163 | DATA 4 DDR_PHY_MR11_0 0x05 // Set CA ODT=Disable DQ_ODT=RZQ/5 164 | DATA 4 DDR_PHY_MR22_0 0x15 // Set ODTE-CS=1 (overrides ODT_CA for CS1 as CS not shared between ranks), SoC ODT = RZQ/5 165 | 166 | /* LPDDR4 mode register writes for CA and DQ VREF settings; range=1, 27.2% */ 167 | DATA 4 DDR_PHY_MR12_0 0x48 168 | DATA 4 DDR_PHY_MR14_0 0x48 169 | 170 | // Set-up DRAM Timing Parameters Register 171 | // DTPR6 is untouched 172 | DATA 4 DDR_PHY_DTPR0_0 0x0d331a09 // tRRD, tRAS, tRP, tRTP 173 | DATA 4 DDR_PHY_DTPR1_0 0x28310411 // tWLMRD, tFAW, tODTUP, tMRD 174 | DATA 4 DDR_PHY_DTPR2_0 0x006a615a // tRTW, tRTODT, tCMDCKE, tCKE, tVRCG, tXS 175 | DATA 4 DDR_PHY_DTPR3_0 0x01800501 // tODX, tCCD, tDLLK, tDQSCKmax, tDQSCK (FIXME double check tDLLK) 176 | DATA 4 DDR_PHY_DTPR4_0 0x01512b0D // tRFC, tWLO, tXP 177 | DATA 4 DDR_PHY_DTPR5_0 0x194c160d // tRC, tRCD, tWTR 178 | 179 | // Set-up PHY Timing Register 180 | DATA 4 DDR_PHY_PTR3_0 0x00249F80 // tDINIT0 - 2ms 181 | DATA 4 DDR_PHY_PTR4_0 0x00000970 // tDINIT1 (2000ns) 182 | DATA 4 DDR_PHY_PTR5_0 0x0003A9A0 // tDINIT2 - normally 200us but memory model hacked to 20us 183 | DATA 4 DDR_PHY_PTR6_0 0x027004B5 // tDINIT4 (30ns), tDINIT3 (1us) 184 | 185 | // RDIMMGCR0-2 RDIMMGCR0-4?? 186 | 187 | // Set-up DATX8 Common Configuration Register 188 | // DXCCR is untouched 189 | 190 | // Set-up DDR System General Configuration Register 191 | // DSGCR is untouched 192 | 193 | // Set-up ODT Configuration Register 194 | // DDR ODT_CA signal is tied at boundary of DDR. Thus no need to drive it dynamically. 195 | DATA 4 DDR_PHY_RANKIDR_0 1 // Select rank 1 to write 196 | DATA 4 DDR_PHY_ODTCR_0 0x00000000 // ODT of rank1 disabled 197 | DATA 4 DDR_PHY_RANKIDR_0 0 // Select rank 0 to write 198 | DATA 4 DDR_PHY_ODTCR_0 0x00000000 // ODT of rank0 disabled 199 | 200 | // Set-up Anti-Aging Control Register 201 | // AACR is untouched 202 | 203 | // Set-up Data Training Address Register 204 | // DTAR0-3 are untouched 205 | // !! DTAR3 is not described in spec !! 206 | 207 | // Set-up AC I/O Configuration Register 208 | // ACIOCR1-4 are untouched 209 | DATA 4 DDR_PHY_ACIOCR0_0 0x30070800 // PNUM2 (i.e.LPDDR4) selection [10:11] = 0x2 210 | DATA 4 DDR_PHY_ACIOCR5_0 0x09000000 // I/O mode = LPDDR4 211 | // Due to address copy set A[13] (=cke_B[0]) and A[15] (=cke_B[1]) outputs as always ON. 212 | DATA 4 DDR_PHY_ACIOCR1_0 0x44000000 213 | 214 | // IOVCR0-1, DXnGCR0-4??, CALBYP 215 | 216 | // Set-up VREF Training Control Registers 217 | DATA 4 DDR_PHY_VTCR0_0 0xF0032019 // CK1, CK0 218 | DATA 4 DDR_PHY_VTCR1_0 0x07F00193 // HVIO=1, SHREN=1, SHRNK=0 219 | 220 | // Set-up DATX8 General Configuration Registers 221 | // DXnGCR0-3 are untouched 222 | DATA 4 DDR_PHY_PGCR5_0 0x01010004 223 | DATA 4 DDR_PHY_PGCR6_0 0x00033200 // Enable CSN Bit Delay VT Compensation (AC already enabled by default) + drift limit 224 | 225 | // Set-up DATX8 General Configuration Registers 226 | DATA 4 DDR_PHY_DX0GCR5_0 0x09092020 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 227 | DATA 4 DDR_PHY_DX1GCR5_0 0x09092020 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 228 | DATA 4 DDR_PHY_DX2GCR5_0 0x09092020 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 229 | DATA 4 DDR_PHY_DX3GCR5_0 0x09092020 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 230 | DATA 4 DDR_PHY_DX0GCR4_0 0x0E00BF3C // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 231 | DATA 4 DDR_PHY_DX1GCR4_0 0x0E00BF3C // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 232 | DATA 4 DDR_PHY_DX2GCR4_0 0x0E00BF3C // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 233 | DATA 4 DDR_PHY_DX3GCR4_0 0x0E00BF3C // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 234 | 235 | // Set-up DATX8 DX Control Register 2 236 | // PREOEX=2.5tCK (0.5 more than MR1), POSOEX=1tCK (0.5 more than in MR3), LPWAKEUP_THRSH=0xA 237 | DATA 4 DDR_PHY_DX8SLbDXCTL2_0 0x001C1400 238 | 239 | //Enable PHY PLL to go into power down on DFI low power request 240 | DATA 4 DDR_PHY_PGCR4_0 0x001900A1 241 | 242 | // Set-up DATX8 IO Control Register 243 | DATA 4 DDR_PHY_DX8SLbIOCR_0 0x79000000 // I/O mode = LPDDR4 244 | 245 | #if DDR_TRAIN_IN_DCD 246 | 247 | // Wait for bit 0 of PGSR0 to be '1' 248 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 249 | 250 | // Launch DRAM initialization 251 | DATA 4 DDR_PHY_PIR_0 0x180 252 | DATA 4 DDR_PHY_PIR_0 0x181 253 | 254 | // Wait for bit 0 of PGSR0 to be '1' 255 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 256 | 257 | // Launch a second time DRAM initialization due to following Synopsys PHY bug: 258 | // Title: "PUB does not program LPDDR4 DRAM MR22 prior to running DRAM ZQ calibration" 259 | // Workaround: "Run DRAM Initialization twice" 260 | DATA 4 DDR_PHY_PIR_0 0x100 261 | DATA 4 DDR_PHY_PIR_0 0x101 262 | 263 | // Wait for bit 0 of PGSR0 to be '1' 264 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 265 | 266 | // Set-up Data Training Configuration Register 267 | // Note that DTCR0.RFSHDT are set to 0x0 as a workaround for PHY bug (Synopsys 268 | // case 9001045655: Design limitation in LPDDR4 mode: REFRESH must be disabled during DQS2DQ training). 269 | // (FYI avoiding refresh during training leads to Denali error (CUMULATIVE_REFRESH_POSTPONE_EXCEEDS_MAX_ALLOWED). 270 | DATA 4 DDR_PHY_DTCR0_0 0x000071CF // Set DTRPTN to 0xF. RFSHDT=0 271 | DATA 4 DDR_PHY_DTCR1_0 0x00030236 // Set RANKEN=3 272 | 273 | CLR_BIT 4 DDR_PHY_DX4GCR1_0 0xFF 274 | 275 | /* -- Write leveling */ 276 | DATA 4 DDR_PHY_PIR_0 0x00000200 277 | DATA 4 DDR_PHY_PIR_0 0x00000201 278 | 279 | // Wait for bit 0 of PGSR0 to be '1' 280 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 281 | // Check that no error occured 282 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00200000 283 | 284 | // -- Read DQS training 285 | // Set DQS/DQSn glitch suppression resistor for training 286 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x012240F7 287 | 288 | /* Launch training for DRC_0 */ 289 | DATA 4 DDR_PHY_PIR_0 0x00000400 290 | DATA 4 DDR_PHY_PIR_0 0x00000401 291 | 292 | // Wait for bit 0 of PGSR0 to be '1' 293 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 294 | // Check that no error occured 295 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00400000 296 | 297 | /* Remove DQS/DQSn glitch suppression resistor */ 298 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x01224000 299 | 300 | /* DQS2DQ training, Write leveling, Deskew and eye trainings */ 301 | DATA 4 DDR_PHY_PIR_0 0x0010F800 302 | DATA 4 DDR_PHY_PIR_0 0x0010F801 303 | 304 | // Wait for bit 0 of PGSR0 to be '1' 305 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 306 | 307 | /* VREF training for DRC_0 */ 308 | DATA 4 DDR_PHY_PIR_0 0x00020000 309 | DATA 4 DDR_PHY_PIR_0 0x00020001 310 | 311 | // Wait for bit 0 of PGSR0 to be '1' 312 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 313 | // Check that no error occured 314 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00080000 315 | 316 | //Re-allow uMCTL2 to send commands to DDR 317 | CLR_BIT 4 DDR_PHY_PGCR1_0 0x00020000 318 | 319 | //DQS Drift Registers 320 | CLR_BIT 4 DDR_PHY_DX0GCR3_0 0x08000000 321 | CLR_BIT 4 DDR_PHY_DX1GCR3_0 0x08000000 322 | CLR_BIT 4 DDR_PHY_DX2GCR3_0 0x08000000 323 | CLR_BIT 4 DDR_PHY_DX3GCR3_0 0x08000000 324 | DATA 4 DDR_PHY_DQSDR0_0 0x20188004 325 | //DATA 4 DDR_PHY_DQSDR1_0 0xA8770100 326 | //DATA 4 DDR_PHY_DQSDR2_0 0x00062000 327 | DATA 4 DDR_PHY_DQSDR1_0 0xA8AA0000 // SNPS recommendation 328 | DATA 4 DDR_PHY_DQSDR2_0 0x00070200 // SNPS recommendation 329 | 330 | //Check that controller is ready to operate 331 | CHECK_BITS_SET 4 DDRC_STAT_0 0x1 332 | #endif 333 | -------------------------------------------------------------------------------- /iMX8QX/imx8qx_dcd_16bit_1.2GHz.cfg: -------------------------------------------------------------------------------- 1 | #define __ASSEMBLY__ 2 | 3 | #include 4 | #include 5 | 6 | /* 7 | * Device Configuration Data (DCD) 8 | * 9 | * Each entry must have the format: 10 | * Addr-type Address Value 11 | * 12 | * where: 13 | * Addr-type register length (1,2 or 4 bytes) 14 | * Address absolute address of the register 15 | * value value to be stored in the register 16 | */ 17 | 18 | #ifndef SCFW_DCD 19 | /* For 1200MHz DDR, DRC 600MHz operation */ 20 | DATA 4 0xff190000 0x00000CC8 /* DRC0 bringup */ 21 | #else 22 | /* Set the DRC rate to 1.2GHz. */ 23 | uint32_t rate2 = SC_600MHZ; 24 | pm_set_clock_rate(SC_PT, SC_R_DRC_0, SC_PM_CLK_MISC0, &rate2); 25 | #endif 26 | 27 | DATA 4 0x41C80208 0x1 28 | 29 | DATA 4 0x41C80040 0xb 30 | 31 | DATA 4 0x41C80204 0x1 32 | 33 | /* DRAM 0 controller configuration begin */ 34 | DATA 4 DDRC_MSTR_0 0xC3081020 // Set LPDDR4, BL = 16 and active ranks 35 | DATA 4 DDRC_RFSHTMG_0 0x004800A9 // tREFI, tRFC 36 | DATA 4 DDRC_INIT0_0 0x4003049A // pre_cke = 2ms is too long - LPDDR4 model hacked for 20us 37 | DATA 4 DDRC_INIT1_0 0x007A0000 // dram_rstn - LPDDR4 model hacked for 20us; 38 | DATA 4 DDRC_INIT3_0 0x00440024 // MR1=0x54: nWR=30 BL=16; MR2=0x2d: RL=28 WL=14 39 | //DATA 4 DDRC_INIT4_0 0x00310000 // MR3, MR13 40 | DATA 4 DDRC_INIT4_0 0x00F10000 // MR3=0xF1: DBI-WR=DBI-RD=1, PU-CAL=VDDQ/3 PDDS=RZQ/6, MR13 41 | //DATA 4 DDRC_RANKCTL_0 0x0000075f // diff_rank_wr_gap, diff_rank_rd_gap, max_rank_rd 42 | DATA 4 DDRC_RANKCTL_0 0x0000066f // diff_rank_wr_gap, diff_rank_rd_gap, max_rank_rd, waiting for SNPS feedback 43 | DATA 4 DDRC_DRAMTMG0_0 0x1619141a // wr2pr, tFAW, tRASmax, tRASmin 44 | DATA 4 DDRC_DRAMTMG1_0 0x00050527 // tXP, rd2pre, tRC 45 | //DATA 4 DDRC_DRAMTMG2_0 0x060c1011 // WL, RL, rd2wr, wr2rd 46 | DATA 4 DDRC_DRAMTMG2_0 0x060E1111 // WL, RL (DBI enabled, 28), rd2wr, wr2rd 47 | DATA 4 DDRC_DRAMTMG3_0 0x0090900a // tmrw, tmrd, tmod 48 | DATA 4 DDRC_DRAMTMG4_0 0x0c04070c // trcd, tccd, trrd, trp 49 | DATA 4 DDRC_DRAMTMG5_0 0x02040a05 // tCKCKEH, tCKCKEL, tckesr, tcke 50 | DATA 4 DDRC_DRAMTMG6_0 0x02020006 // tckdpde, tckdpdx, tckcsx 51 | DATA 4 DDRC_DRAMTMG7_0 0x00000401 // tckpde, tckpdx 52 | DATA 4 DDRC_DRAMTMG12_0 0x00020510 // tCMDCKE, tCKEHCMD (=tXP?) 53 | DATA 4 DDRC_DRAMTMG13_0 0x0b100002 // tODTLoff, tCCDMW, tPPD 54 | DATA 4 DDRC_DRAMTMG14_0 0x000000ae // txsr 55 | DATA 4 DDRC_ZQCTL0_0 0x025b0013 // tZQCAL, tZQLAT 56 | 57 | DATA 4 DDRC_ZQCTL1_0 0x01f00100 // tZQReset, tzq_short_interval 58 | 59 | //DATA 4 DDRC_DFITMG0_0 0x0495820a // dfi_t_ctrl_delay, dfi_t_rddata_en, dfi_tphy_wrdata, dfi_tphy_wrlat 60 | DATA 4 DDRC_DFITMG0_0 0x0499820a // dfi_t_ctrl_delay, dfi_t_rddata_en RL=28 with DBI enabled, dfi_tphy_wrdata, dfi_tphy_wrlat 61 | DATA 4 DDRC_DFITMG1_0 0x00070303 // dfi_t_wrdata_delay, dfi_t_dram_clk_disable, dfi_t_dram_clk_enable 62 | //DATA 4 DDRC_DFITMG2_0 0x00001308 // dfi_tphy_rdcslat, dfi_tphy_wrcslat 63 | DATA 4 DDRC_DFITMG2_0 0x00001708 // dfi_tphy_rdcslat RL=28 with DBI enabled, dfi_tphy_wrcslat 64 | DATA 4 DDRC_DFIMISC_0 0x00000005 // dfi_data_cs_polarity 65 | DATA 4 DDRC_DFIUPD0_0 0x00400003 // Disable the automatic dfi_ctrlupd_req generation 66 | DATA 4 DDRC_DFIUPD1_0 0x008000A0 // dfi_ctrlupd_req generation interval generation (min and max) 67 | DATA 4 DDRC_DFIUPD2_0 0x80000000 // dfi_phyupd_en 68 | 69 | DATA 4 DDRC_ADDRMAP0_0 0x00000014 // addrmap_cs_bit0 70 | DATA 4 DDRC_ADDRMAP4_0 0x00001F1F // addrmap_col_b10 and addrmap_col_b11 set to de-activated 71 | 72 | DATA 4 DDRC_ADDRMAP1_0 0x00070707 // addrmap_bank_b2, addrmap_bank_b1, addrmap_bank_b0 73 | DATA 4 DDRC_ADDRMAP5_0 0x06060606 // addrmap_row_b11, addrmap_row_b10_b2, addrmap_row_b1, addrmap_row_b0 74 | DATA 4 DDRC_ADDRMAP6_0 0x07070606 // addrmap_row_b15, addrmap_row_b14, addrmap_row_b13, addrmap_row_b12 75 | 76 | DATA 4 DDRC_DBICTL_0 0x00000007 // rd_dbi_en=wr_dbi_en=dm_en=1 77 | 78 | DATA 4 DDRC_ODTMAP_0 0x00002211 // rank[3:0]_wr_odt, rank[3:0]_wr_odt 79 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable port 0 80 | 81 | DATA 4 DDRC_DFITMG0_SHADOW_0 0x00808000 82 | 83 | DATA 4 DDRC_PWRCTL_0 0x10D 84 | 85 | DATA 4 0x41C80208 0x1 86 | 87 | DATA 4 0x41C80040 0xf 88 | 89 | DATA 4 0x41C80204 0x1 90 | 91 | //------------------------------------------- 92 | // Configure registers for PHY initialization 93 | // Timings are computed for a PHY at 800MHz (DRAM at 1600MHz) 94 | //-------------------------------=------------ 95 | 96 | // Set-up DRAM Configuration Register 97 | DATA 4 DDR_PHY_DCR_0 0x0000040D // LPDDR4 selection with 8 bank 98 | 99 | // Set-up byte and bit swapping registers 100 | DATA 4 DDR_PHY_PGCR8_0 0x000F000A // Set BSWAPMSB='b1001 (byte 0 and 1 are swapped) 101 | DATA 4 DDR_PHY_DX0DQMAP0_0 0x00061032 // DQ bit 0/1/2/3/4 remapping 102 | DATA 4 DDR_PHY_DX0DQMAP1_0 0x00004578 // DQ bit 5/6/7 and DM remapping 103 | DATA 4 DDR_PHY_DX1DQMAP0_0 0x00071032 // DQ bit 0/1/2/3/4 remapping 104 | DATA 4 DDR_PHY_DX1DQMAP1_0 0x00004685 // DQ bit 5/6/7 and DM remapping 105 | DATA 4 DDR_PHY_DX2DQMAP0_0 0x00016578 // DQ bit 0/1/2/3/4 remapping 106 | DATA 4 DDR_PHY_DX2DQMAP1_0 0x00004203 // DQ bit 5/6/7 and DM remapping 107 | DATA 4 DDR_PHY_DX3DQMAP0_0 0x00015867 // DQ bit 0/1/2/3/4 remapping 108 | DATA 4 DDR_PHY_DX3DQMAP1_0 0x00004320 // DQ bit 5/6/7 and DM remapping 109 | DATA 4 DDR_PHY_CATR0_0 0x00141032 // Only for LPDDR3 but used here to know how LPDDR4 bytes are connected to PHY 110 | DATA 4 DDR_PHY_CATR1_0 0x0013AAAA // Only for LPDDR3 but used here to know how LPDDR4 bytes are connected to PHY 111 | 112 | // Set-up PHY General Configuration Register 113 | // PGCR1,4,5,6,7 are untouched 114 | SET_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=1 (no uMCTL2 commands can go to memory) 115 | DATA 4 DDR_PHY_PGCR0_0 0x07001E00 // Set ADCP=1 (Address Copy) 116 | CLR_BIT 4 DDR_PHY_DX2GCR1_0 0x000000FF 117 | CLR_BIT 4 DDR_PHY_DX3GCR1_0 0x000000FF 118 | DATA 4 DDR_PHY_PGCR2_0 0x00F0A190 // Set tREFPRD (9*3.904us - 600) 119 | DATA 4 DDR_PHY_PGCR3_0 0x050A1080 // CKEN/CKNEN toggling and polarity 120 | 121 | // Set-up PHY Timing Register 122 | // PTR2 is untouched 123 | DATA 4 DDR_PHY_PTR0_0 0x4B025810 // tPLLPD, tPLLGS, tPHYRST 124 | DATA 4 DDR_PHY_PTR1_0 0x3AA01520 // tPLLLOCK reduced to 4.3us, tPLLRST=9us 125 | 126 | // Set-up PLL Control Register 127 | DATA 4 DDR_PHY_PLLCR0_0 0x000E0000 // FREQSEL=0 128 | DATA 4 DDR_PHY_DX8SLbPLLCR0_0 0x000E0000 129 | 130 | // Set-up Impedance Control Register 131 | DATA 4 DDR_PHY_ZQCR_0 0x008A2C58 // Set ODT_MODE=0b10(LPDDR4 stype pullup) 132 | 133 | // ZPROG_DRAM_ODT and ZPROG_HOST_ODT = 60ohm 134 | //DATA 4 DDR_PHY_ZQ0PR0_0 0x0B7BB // comment is wrong => PU_DRV_ADJUST 3b001 = Adjust calibrated drive strength by 2/8 to obtain 1.25x of original strength 135 | //DATA 4 DDR_PHY_ZQ1PR0_0 0x0B7BB 136 | //DATA 4 DDR_PHY_ZQ2PR0_0 0x0B7BB 137 | //DATA 4 DDR_PHY_ZQ3PR0_0 0x0B7BB 138 | DATA 4 DDR_PHY_ZQ0PR0_0 0x1B7BB // PU_DRV_ADJUST 3b001 = Adjust calibrated drive strength by 2/8 to obtain 1.25x of original strength 139 | DATA 4 DDR_PHY_ZQ1PR0_0 0x1B7BB 140 | DATA 4 DDR_PHY_ZQ2PR0_0 0x1B7BB 141 | DATA 4 DDR_PHY_ZQ3PR0_0 0x1B7BB 142 | 143 | 144 | // Set-up PHY Initialization Register 145 | DATA 4 DDR_PHY_PIR_0 0x32 146 | 147 | // Launch initialization (set bit 0) 148 | DATA 4 DDR_PHY_PIR_0 0x33 149 | 150 | //------------------------------------------- 151 | // Configure registers for DRAM initialization 152 | //------------------------------------------- 153 | 154 | // Set-up Mode Register 155 | // MR0, MR3, MR4, MR5 MR6 are untouched 156 | DATA 4 DDR_PHY_MR1_0 0x44 // Set BL, WR-PRE, nWR=24, RPST 157 | DATA 4 DDR_PHY_MR2_0 0x24 // Set RL=14/WL=8 158 | //DATA 4 DDR_PHY_MR3_0 0x31 // Set drive strength (40 Ohms by default) 159 | DATA 4 DDR_PHY_MR3_0 0xF1 // Set drive strength (40 Ohms by default), DBI_RD=DBI_WR=1 160 | DATA 4 DDR_PHY_MR11_0 0x05 // Set CA ODT=Disable DQ_ODT=RZQ/5 161 | DATA 4 DDR_PHY_MR22_0 0x15 // Set ODTE-CS=1 (overrides ODT_CA for CS1 as CS not shared between ranks), SoC ODT = RZQ/5 162 | 163 | /* LPDDR4 mode register writes for CA and DQ VREF settings; range=1, 27.2% */ 164 | DATA 4 DDR_PHY_MR12_0 0x48 165 | DATA 4 DDR_PHY_MR14_0 0x48 166 | 167 | // Set-up DRAM Timing Parameters Register 168 | // DTPR6 is untouched 169 | DATA 4 DDR_PHY_DTPR0_0 0x0d331a09 // tRRD, tRAS, tRP, tRTP 170 | DATA 4 DDR_PHY_DTPR1_0 0x28310411 // tWLMRD, tFAW, tODTUP, tMRD 171 | DATA 4 DDR_PHY_DTPR2_0 0x006a615a // tRTW, tRTODT, tCMDCKE, tCKE, tVRCG, tXS 172 | DATA 4 DDR_PHY_DTPR3_0 0x01800501 // tODX, tCCD, tDLLK, tDQSCKmax, tDQSCK (FIXME double check tDLLK) 173 | DATA 4 DDR_PHY_DTPR4_0 0x01512b0D // tRFC, tWLO, tXP 174 | DATA 4 DDR_PHY_DTPR5_0 0x194c160d // tRC, tRCD, tWTR 175 | 176 | // Set-up PHY Timing Register 177 | DATA 4 DDR_PHY_PTR3_0 0x00249F80 // tDINIT0 - 2ms 178 | DATA 4 DDR_PHY_PTR4_0 0x00000970 // tDINIT1 (2000ns) 179 | DATA 4 DDR_PHY_PTR5_0 0x0003A9A0 // tDINIT2 - normally 200us but memory model hacked to 20us 180 | DATA 4 DDR_PHY_PTR6_0 0x027004B5 // tDINIT4 (30ns), tDINIT3 (1us) 181 | 182 | // RDIMMGCR0-2 RDIMMGCR0-4?? 183 | 184 | // Set-up DATX8 Common Configuration Register 185 | // DXCCR is untouched 186 | 187 | // Set-up DDR System General Configuration Register 188 | // DSGCR is untouched 189 | 190 | // Set-up ODT Configuration Register 191 | // DDR ODT_CA signal is tied at boundary of DDR. Thus no need to drive it dynamically. 192 | DATA 4 DDR_PHY_RANKIDR_0 1 // Select rank 1 to write 193 | DATA 4 DDR_PHY_ODTCR_0 0x00000000 // ODT of rank1 disabled 194 | DATA 4 DDR_PHY_RANKIDR_0 0 // Select rank 0 to write 195 | DATA 4 DDR_PHY_ODTCR_0 0x00000000 // ODT of rank0 disabled 196 | 197 | // Set-up Anti-Aging Control Register 198 | // AACR is untouched 199 | 200 | // Set-up Data Training Address Register 201 | // DTAR0-3 are untouched 202 | // !! DTAR3 is not described in spec !! 203 | 204 | // Set-up AC I/O Configuration Register 205 | // ACIOCR1-4 are untouched 206 | DATA 4 DDR_PHY_ACIOCR0_0 0x30070800 // PNUM2 (i.e.LPDDR4) selection [10:11] = 0x2 207 | DATA 4 DDR_PHY_ACIOCR5_0 0x09000000 // I/O mode = LPDDR4 208 | // Due to address copy set A[13] (=cke_B[0]) and A[15] (=cke_B[1]) outputs as always ON. 209 | DATA 4 DDR_PHY_ACIOCR1_0 0x44000000 210 | 211 | // IOVCR0-1, DXnGCR0-4??, CALBYP 212 | 213 | // Set-up VREF Training Control Registers 214 | DATA 4 DDR_PHY_VTCR0_0 0xF0032019 // CK1, CK0 215 | DATA 4 DDR_PHY_VTCR1_0 0x07F00193 // HVIO=1, SHREN=1, SHRNK=0 216 | 217 | // Set-up DATX8 General Configuration Registers 218 | // DXnGCR0-4 are untouched 219 | DATA 4 DDR_PHY_PGCR5_0 0x01010004 220 | DATA 4 DDR_PHY_PGCR6_0 0x00033200 // Enable CSN Bit Delay VT Compensation (AC already enabled by default) + drift limit 221 | 222 | // Set-up DATX8 General Configuration Registers 223 | DATA 4 DDR_PHY_DX0GCR5_0 0x09092020 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 224 | DATA 4 DDR_PHY_DX1GCR5_0 0x09092020 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 225 | DATA 4 DDR_PHY_DX2GCR5_0 0x09092020 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 226 | DATA 4 DDR_PHY_DX3GCR5_0 0x09092020 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 227 | DATA 4 DDR_PHY_DX0GCR4_0 0x0E00BF3C // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 228 | DATA 4 DDR_PHY_DX1GCR4_0 0x0E00BF3C // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 229 | DATA 4 DDR_PHY_DX2GCR4_0 0x0E00BF3C // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 230 | DATA 4 DDR_PHY_DX3GCR4_0 0x0E00BF3C // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 231 | 232 | // Set-up DATX8 DX Control Register 2 233 | // PREOEX=2.5tCK (0.5 more than MR1), POSOEX=1tCK (0.5 more than in MR3), LPWAKEUP_THRSH=0xA 234 | DATA 4 DDR_PHY_DX8SLbDXCTL2_0 0x001C1400 235 | 236 | // Set-up DATX8 IO Control Register 237 | DATA 4 DDR_PHY_DX8SLbIOCR_0 0x79000000 // I/O mode = LPDDR4 238 | 239 | #if 1 240 | /* DDR training is performed in FW, remove here */ 241 | 242 | // Wait for bit 0 of PGSR0 to be '1' 243 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 244 | // Check that no error occured 245 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 246 | 247 | // Launch DRAM initialization 248 | DATA 4 DDR_PHY_PIR_0 0x180 249 | DATA 4 DDR_PHY_PIR_0 0x181 250 | 251 | // Wait for bit 0 of PGSR0 to be '1' 252 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 253 | // Check that no error occured 254 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 255 | 256 | // Launch a second time DRAM initialization due to following Synopsys PHY bug: 257 | // Title: "PUB does not program LPDDR4 DRAM MR22 prior to running DRAM ZQ calibration" 258 | // Workaround: "Run DRAM Initialization twice" 259 | DATA 4 DDR_PHY_PIR_0 0x100 260 | DATA 4 DDR_PHY_PIR_0 0x101 261 | 262 | // Wait for bit 0 of PGSR0 to be '1' 263 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 264 | // Check that no error occured 265 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 266 | 267 | // Set-up Data Training Configuration Register 268 | // Note that DTCR0.RFSHDT are set to 0x0 as a workaround for PHY bug (Synopsys 269 | // case 9001045655: Design limitation in LPDDR4 mode: REFRESH must be disabled during DQS2DQ training). 270 | // (FYI avoiding refresh during training leads to Denali error (CUMULATIVE_REFRESH_POSTPONE_EXCEEDS_MAX_ALLOWED). 271 | DATA 4 DDR_PHY_DTCR0_0 0x000071CF // Set DTRPTN to 0xF. RFSHDT=0 272 | DATA 4 DDR_PHY_DTCR1_0 0x00030236 // Set RANKEN=3 273 | 274 | CLR_BIT 4 DDR_PHY_DX4GCR1_0 0xFF 275 | 276 | /* -- Write leveling */ 277 | DATA 4 DDR_PHY_PIR_0 0x00000200 278 | DATA 4 DDR_PHY_PIR_0 0x00000201 279 | 280 | // Wait for bit 0 of PGSR0 to be '1' 281 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 282 | // Check that no error occured 283 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00200000 284 | 285 | // -- Read DQS training 286 | // Set DQS/DQSn glitch suppression resistor for training 287 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x012640F7 288 | 289 | /* Launch training for DRC_0 */ 290 | DATA 4 DDR_PHY_PIR_0 0x00000400 291 | DATA 4 DDR_PHY_PIR_0 0x00000401 292 | 293 | // Wait for bit 0 of PGSR0 to be '1' 294 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 295 | // Check that no error occured 296 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00400000 297 | 298 | /* Remove DQS/DQSn glitch suppression resistor */ 299 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x01264000 300 | 301 | /* DQS2DQ training, Write leveling, Deskew and eye trainings */ 302 | DATA 4 DDR_PHY_PIR_0 0x0010F800 303 | DATA 4 DDR_PHY_PIR_0 0x0010F801 304 | 305 | // Wait for bit 0 of PGSR0 to be '1' 306 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 307 | // Check that no error occured 308 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 309 | 310 | /* VREF training for DRC_0 */ 311 | DATA 4 DDR_PHY_PIR_0 0x00020000 312 | DATA 4 DDR_PHY_PIR_0 0x00020001 313 | 314 | // Wait for bit 0 of PGSR0 to be '1' 315 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 316 | // Check that no error occured 317 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00080000 318 | 319 | //Re-allow uMCTL2 to send commands to DDR 320 | CLR_BIT 4 DDR_PHY_PGCR1_0 0x00020000 321 | 322 | SET_BIT 4 DDR_PHY_DX8SL1PLLCR0_0 0x20000000 323 | SET_BIT 4 DDR_PHY_DX8SL2PLLCR0_0 0x20000000 324 | 325 | //DQS Drift Registers 326 | CLR_BIT 4 DDR_PHY_DX0GCR3_0 0x08000000 327 | CLR_BIT 4 DDR_PHY_DX1GCR3_0 0x08000000 328 | CLR_BIT 4 DDR_PHY_DX2GCR3_0 0x08000000 329 | CLR_BIT 4 DDR_PHY_DX3GCR3_0 0x08000000 330 | DATA 4 DDR_PHY_DQSDR0_0 0x20188005 331 | //DATA 4 DDR_PHY_DQSDR1_0 0xA8770100 332 | //DATA 4 DDR_PHY_DQSDR2_0 0x00062000 333 | DATA 4 DDR_PHY_DQSDR1_0 0xA8AA0000 // SNPS recommendation 334 | DATA 4 DDR_PHY_DQSDR2_0 0x00070200 // SNPS recommendation 335 | 336 | //Check that controller is ready to operate 337 | CHECK_BITS_SET 4 DDRC_STAT_0 0x1 338 | #endif 339 | -------------------------------------------------------------------------------- /iMX8QX/imx8qx_ddr3_dcd_1066MHz_ecc.cfg: -------------------------------------------------------------------------------- 1 | #define __ASSEMBLY__ 2 | 3 | #include 4 | #include 5 | 6 | /* 7 | * Device Configuration Data (DCD) 8 | * 9 | * Each entry must have the format: 10 | * Addr-type Address Value 11 | * 12 | * where: 13 | * Addr-type register length (1,2 or 4 bytes) 14 | * Address absolute address of the register 15 | * value value to be stored in the register 16 | */ 17 | 18 | #ifndef SCFW_DCD 19 | // Set DRAM clock frequency for the following operation: 1066MHz 20 | DATA 4 0xff190000 0x00000CB1 /* DRC0 bringup */ 21 | #else 22 | /* Set the DRC rate to achieve a DRAM rate as close as possible to 1066MHz. */ 23 | uint32_t rate2 = 531000000; 24 | pm_set_clock_rate(SC_PT, SC_R_DRC_0, SC_PM_CLK_MISC0, &rate2); 25 | #endif 26 | 27 | DATA 4 0x41C80208 0x1 28 | DATA 4 0x41C80040 0xb // Assert uMCTL2 core reset 29 | DATA 4 0x41C80204 0x1 // Start functional clocks. 30 | 31 | /* DRAM 0 controller configuration begin */ 32 | DATA 4 DDRC_MSTR_0 0x81040001 // Set DDR3l, BL = 16 and active ranks 33 | DATA 4 DDRC_RFSHTMG_0 0x0082008B // tREFI, tRFC 34 | DATA 4 DDRC_INIT0_0 0x40030106 // pre_cke 35 | DATA 4 DDRC_INIT1_0 0x006A0000 // dram_rstn 36 | DATA 4 DDRC_INIT3_0 0x00240006 // MR0, MR1 37 | DATA 4 DDRC_INIT4_0 0x00280000 // MR2, MR3 38 | DATA 4 DDRC_INIT5_0 0x000C0000 // ZQINIT 39 | DATA 4 DDRC_RANKCTL_0 0x0000072F // diff_rank_wr_gap, diff_rank_rd_gap, max_rank_rd 40 | DATA 4 DDRC_DRAMTMG0_0 0x0F132412 // wr2pr, tFAW, tRASmax, tRASmin 41 | DATA 4 DDRC_DRAMTMG1_0 0x000D0419 // tXP, rd2pre, tRC 42 | DATA 4 DDRC_DRAMTMG2_0 0x0507060B // WL, RL, rd2wr, wr2rd 43 | DATA 4 DDRC_DRAMTMG3_0 0x00002008 // T_MOD, T_MRD 44 | DATA 4 DDRC_DRAMTMG4_0 0x07020408 // trcd, tccd, trrd, trp 45 | DATA 4 DDRC_DRAMTMG5_0 0x06060403 // tCKCKEH, tCKCKEL, tckesr, tcke 46 | DATA 4 DDRC_DRAMTMG8_0 0x03030906 // tckdpde, tckdpdx, tckcsx 47 | DATA 4 DDRC_ZQCTL0_0 0x40AB002B // tZQCAL, tZQLAT 48 | DATA 4 DDRC_ZQCTL1_0 0x02000083 // tZQReset, tzq_short_interval 49 | DATA 4 DDRC_DFITMG0_0 0x048A8207 50 | DATA 4 DDRC_DFITMG1_0 0x00060303 // dfi_t_wrdata_delay, dfi_t_dram_clk_disable, dfi_t_dram_clk_enable 51 | DATA 4 DDRC_DFITMG2_0 0x00000805 52 | DATA 4 DDRC_DFIMISC_0 0x00000001 // dfi_data_cs_polarity 53 | DATA 4 DDRC_DFIUPD0_0 0xE0400018 // Disable the automatic dfi_ctrlupd_req generation 54 | DATA 4 DDRC_DFIUPD1_0 0x001A0057 // dfi_ctrlupd_req generation interval generation (min and max) 55 | DATA 4 DDRC_DFIUPD2_0 0x80000000 // dfi_phyupd_en 56 | DATA 4 DDRC_ADDRMAP0_0 0x0000001F // addrmap_cs_bit0 57 | DATA 4 DDRC_ADDRMAP3_0 0x00000000 // addrmap_col_b9, addrmap_col_b8, addrmap_col_b7, addrmap_col_b6 58 | DATA 4 DDRC_ADDRMAP4_0 0x00001F1F // addrmap_col_b10 and addrmap_col_b11 set to de-activated 59 | DATA 4 DDRC_ADDRMAP1_0 0x00080808 // addrmap_bank_b2, addrmap_bank_b1, addrmap_bank_b0 60 | DATA 4 DDRC_ADDRMAP5_0 0x07070707 // addrmap_row_b11, addrmap_row_b10_b2, addrmap_row_b1, addrmap_row_b0 61 | DATA 4 DDRC_ADDRMAP6_0 0x0F070707 // addrmap_row_b15, addrmap_row_b14, addrmap_row_b13, addrmap_row_b12 62 | DATA 4 DDRC_ECCCFG0_0 0x044FFFC4 // ecc support (uncommented when ECC is enabled) 63 | 64 | DATA 4 DDRC_ODTCFG_0 0x06000610 65 | DATA 4 DDRC_ODTMAP_0 0x00000001 // rank[3:0]_wr_odt, rank[3:0]_wr_odt 66 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable port 0 67 | 68 | DATA 4 DDRC_DFITMG0_SHADOW_0 0x00808000 69 | 70 | DATA 4 DDRC_PWRCTL_0 0x00000000 71 | 72 | DATA 4 0x41c80208 0x1 73 | DATA 4 0x41c80040 0xf 74 | DATA 4 0x41c80204 0x1 75 | 76 | //------------------------------------------- 77 | // Configure registers for PHY initialization 78 | // Timings are computed for 1066MHz DRAM operation 79 | //-------------------------------------------- 80 | // Set-up DRAM Configuration Register 81 | DATA 4 DDR_PHY_DCR_0 0x0000040B // DDR3 selection with 8 bank 82 | // Set-up byte and bit swapping registers 83 | DATA 4 DDR_PHY_DX0DQMAP0_0 0x00071628 // DQ bit 0/1/2/3/4 remapping 84 | DATA 4 DDR_PHY_DX0DQMAP1_0 0x00004053 // DQ bit 5/6/7 and DM remapping 85 | DATA 4 DDR_PHY_DX1DQMAP0_0 0x00073826 // DQ bit 0/1/2/3/4 remapping 86 | DATA 4 DDR_PHY_DX1DQMAP1_0 0x00004150 // DQ bit 5/6/7 and DM remapping 87 | DATA 4 DDR_PHY_DX2DQMAP0_0 0x00053608 // DQ bit 0/1/2/3/4 remapping 88 | DATA 4 DDR_PHY_DX2DQMAP1_0 0x00004271 // DQ bit 5/6/7 and DM remapping 89 | DATA 4 DDR_PHY_DX3DQMAP0_0 0x00053826 // DQ bit 0/1/2/3/4 remapping 90 | DATA 4 DDR_PHY_DX3DQMAP1_0 0x00004170 // DQ bit 5/6/7 and DM remapping 91 | DATA 4 DDR_PHY_DX4DQMAP0_0 0x00005281 // DQ bit 0/1/2/3/4 remapping 92 | DATA 4 DDR_PHY_DX4DQMAP1_0 0x00004736 // DQ bit 5/6/7 and DM remapping 93 | // Set-up PHY General Configuration Register 94 | // PGCR1,4,5,6,7 are untouched 95 | SET_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=1 (no uMCTL2 commands can go to memory) 96 | DATA 4 DDR_PHY_PGCR0_0 0x07001E00 // Set ADCP=1 (Address Copy) 97 | DATA 4 DDR_PHY_PGCR2_0 0x00F1024C // Set tREFPRD 98 | DATA 4 DDR_PHY_PGCR3_0 0x050A1080 // CKEN/CKNEN toggling and polarity 99 | // Set-up PHY Timing Register 100 | // PTR2 is untouched 101 | DATA 4 DDR_PHY_PTR0_0 0x42C21550 // tPLLPD, tPLLGS, tPHYRST 102 | DATA 4 DDR_PHY_PTR1_0 0x340F12BE // tPLLLOCK, tPLLRST 103 | // Set-up PLL Control Register 104 | DATA 4 DDR_PHY_PLLCR0_0 0x011C0000 105 | DATA 4 DDR_PHY_DX8SLbPLLCR0_0 0x011C0000 106 | // Set-up Impedance Control Register 107 | DATA 4 DDR_PHY_ZQCR_0 0x008A2858 // Set ODT_MODE=0b10(DDR3 stype pullup) 108 | // ZPROG_DRAM_ODT and ZPROG_HOST_ODT 109 | DATA 4 DDR_PHY_ZQ0PR0_0 0x77BB // Optimal setting based on factory testing 110 | DATA 4 DDR_PHY_ZQ1PR0_0 0x77BB // Optimal setting based on factory testing 111 | // Set-up PHY Initialization Register 112 | DATA 4 DDR_PHY_PIR_0 0x72 113 | // Launch initialization (set bit 0) 114 | DATA 4 DDR_PHY_PIR_0 0x73 115 | 116 | 117 | //------------------------------------------- 118 | // Configure registers for DRAM initialization 119 | //------------------------------------------- 120 | // Set-up Mode Register 121 | // MR0, MR3, MR4, MR5 MR6 are untouched 122 | DATA 4 DDR_PHY_MR0_0 0x00000024 123 | DATA 4 DDR_PHY_MR1_0 0x00000006 124 | DATA 4 DDR_PHY_MR2_0 0x00000028 125 | DATA 4 DDR_PHY_MR3_0 0x00000000 126 | 127 | // Set-up DRAM Timing Parameters Register 128 | // DTPR6 is untouched 129 | DATA 4 DDR_PHY_DTPR0_0 0x07240E08 // tRRD, tRAS, tRP, tRTP 130 | DATA 4 DDR_PHY_DTPR1_0 0x28260400 // tWLMRD, tFAW, tODTUP, tMRD 131 | DATA 4 DDR_PHY_DTPR2_0 0x01060200 // tRTW, tRTODT, tCMDCKE, tCKE, tVRCG, tXS 132 | DATA 4 DDR_PHY_DTPR3_0 0x02000000 // tODX, tCCD, tDLLK, tDQSCKmax, tDQSCK (FIXME double check tDLLK) 133 | DATA 4 DDR_PHY_DTPR4_0 0x01160C1A // tRFC, tWLO, tXP 134 | DATA 4 DDR_PHY_DTPR5_0 0x00320E09 // tRC, tRCD, tWTR 135 | // Set-up PHY Timing Register 136 | DATA 4 DDR_PHY_PTR3_0 0x0008223A // tDINIT0 137 | DATA 4 DDR_PHY_PTR4_0 0x00000116 // tDINIT1 138 | DATA 4 DDR_PHY_PTR5_0 0x000340E4 // tDINIT2 139 | DATA 4 DDR_PHY_PTR6_0 0x0400042C // tDINIT4, tDINIT3 140 | 141 | 142 | // Set-up ODT Configuration Register 143 | // DDR ODT_CA signal is tied at boundary of DDR. Thus no need to drive it dynamically. 144 | DATA 4 DDR_PHY_RANKIDR_0 0x00000000 // Select rank 0 to write 145 | DATA 4 DDR_PHY_ODTCR_0 0x00010000 // ODT of rank1 disabled 146 | 147 | 148 | // Set-up AC I/O Configuration Register 149 | // ACIOCR1-4 are untouched 150 | DATA 4 DDR_PHY_ACIOCR0_0 0x30070400 // PNUM2 (i.e.DDR3) selection [10:11] = 0x2 151 | DATA 4 DDR_PHY_ACIOCR5_0 0x00000000 // I/O mode = DDR3 152 | DATA 4 DDR_PHY_IOVCR0_0 0x03000000 153 | // Set-up DATX8 General Configuration Registers 154 | // DXnGCR0-4 are untouched 155 | DATA 4 DDR_PHY_PGCR5_0 0x01010004 156 | // Set-up DATX8 General Configuration Registers 157 | DATA 4 DDR_PHY_DX0GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 158 | DATA 4 DDR_PHY_DX1GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 159 | DATA 4 DDR_PHY_DX2GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 160 | DATA 4 DDR_PHY_DX3GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 161 | DATA 4 DDR_PHY_DX4GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 162 | DATA 4 DDR_PHY_DX0GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 163 | DATA 4 DDR_PHY_DX1GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 164 | DATA 4 DDR_PHY_DX2GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 165 | DATA 4 DDR_PHY_DX3GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 166 | DATA 4 DDR_PHY_DX4GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 167 | // Set-up DATX8 DX Control Register 2 168 | // PREOEX=2.5tCK (0.5 more than MR1), POSOEX=1tCK (0.5 more than in MR3), LPWAKEUP_THRSH=0xA 169 | DATA 4 DDR_PHY_DX8SLbDXCTL2_0 0x001C1400 170 | // Set-up DATX8 IO Control Register 171 | DATA 4 DDR_PHY_DX8SLbIOCR_0 0x00000000 // I/O mode = DDR3 172 | 173 | #if DDR_TRAIN_IN_DCD 174 | // Wait PHY initialization end then launch DRAM initialization 175 | // Wait for bit 0 of PGSR0 to be '1' 176 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 177 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 // Check that no error occured 178 | 179 | // Launch DRAM 0 initialization (set bit 0) 180 | DATA 4 DDR_PHY_PIR_0 0x180 181 | DATA 4 DDR_PHY_PIR_0 0x181 182 | 183 | // DRAM 0 initialization end 184 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 185 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 186 | 187 | //---------------------------------------------------------------// 188 | // DATA training 189 | //---------------------------------------------------------------// 190 | // Set-up Data Training Configuration Register 191 | // Note that DTCR0.RFSHDT are set to 0x0 as a workaround for PHY bug (Synopsys 192 | // case 9001045655: Design limitation in DDR3 mode: REFRESH must be disabled during DQS2DQ training). 193 | // (FYI avoiding refresh during training leads to Denali error (CUMULATIVE_REFRESH_POSTPONE_EXCEEDS_MAX_ALLOWED). 194 | DATA 4 DDR_PHY_DTCR0_0 0x800031CF // Set DTRPTN to 0x7. RFSHDT=0 195 | DATA 4 DDR_PHY_DTCR1_0 0x00010237 // Set RANKEN=3 196 | 197 | // CLR_BIT 4 DDR_PHY_DX4GCR1_0 0xFF // disable byte 4 (this line is commented out when ECC is enabled) 198 | 199 | // Launch Write leveling 200 | DATA 4 DDR_PHY_PIR_0 0x200 201 | DATA 4 DDR_PHY_PIR_0 0x201 202 | // Wait Write leveling to complete 203 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 204 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00200000 205 | 206 | // Set DQS/DQSn glitch suppression resistor for training PHY0 207 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x012640F7 208 | // Launch Read DQS training 209 | DATA 4 DDR_PHY_PIR_0 0x400 210 | DATA 4 DDR_PHY_PIR_0 0x401 211 | // Wait Read DQS training to complete PHY0 212 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 213 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00400000 214 | // Remove DQS/DQSn glitch suppression resistor PHY0 215 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x01264000 216 | 217 | // DQS2DQ training, Write leveling, Deskew and eye trainings 218 | DATA 4 DDR_PHY_PIR_0 0x0000F800 219 | DATA 4 DDR_PHY_PIR_0 0x0000F801 220 | // Wait for training to complete 221 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 222 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 223 | 224 | //Re-allow uMCTL2 to send commands to DDR 225 | CLR_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=0, PUBMODE=0 226 | 227 | //Check that controller is ready to operate 228 | CHECK_BITS_SET 4 DDRC_STAT_0 0x1 229 | 230 | #endif 231 | 232 | // ECC Support (the following lines are uncommented when ECC is enabled) 233 | DATA 4 DDRC_PCTRL_0_0 0x00000000 // Disable Port 0 234 | DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_mode = 1 235 | DATA 4 DDRC_SBRWDATA0_0 0x55AA55AA // SBRWDATA0 = 55AA55AA 236 | DATA 4 DDRC_SBRCTL_0 0x00000015 // Scrub_en = 1 237 | CHECK_BITS_SET 4 DDRC_SBRSTAT_0 0x2 // Wait for Scrub done 238 | CHECK_BITS_CLR 4 DDRC_SBRSTAT_0 0x1 // Wait for Scrub done 239 | DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_en = 0 240 | DATA 4 DDRC_SBRCTL_0 0x00000110 // Scrub_interval = 1 241 | DATA 4 DDRC_SBRCTL_0 0x00000111 // Scrub_en = 1 242 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable Port 0 243 | 244 | -------------------------------------------------------------------------------- /iMX8QX/imx8qx_ddr3_dcd_800MHz.cfg: -------------------------------------------------------------------------------- 1 | #define __ASSEMBLY__ 2 | 3 | #include 4 | #include 5 | 6 | /* 7 | * Device Configuration Data (DCD) 8 | * 9 | * Each entry must have the format: 10 | * Addr-type Address Value 11 | * 12 | * where: 13 | * Addr-type register length (1,2 or 4 bytes) 14 | * Address absolute address of the register 15 | * value value to be stored in the register 16 | */ 17 | 18 | #ifndef SCFW_DCD 19 | /* For 800MHz DDR, DRC 400MHz operation */ 20 | //DATA 4 0xff190000 0x00000C84 /* DRC0 bringup */ 21 | DATA 4 0xff190000 0x00000C85 /* DRC0 bringup */ 22 | #else 23 | /* Set the DRC rate to 400MHz, the PHY PLL will double this for the DRAM rate. */ 24 | uint32_t rate2 = SC_400MHZ; 25 | pm_set_clock_rate(SC_PT, SC_R_DRC_0, SC_PM_CLK_MISC0, &rate2); 26 | #endif 27 | 28 | DATA 4 0x41C80208 0x1 29 | DATA 4 0x41C80040 0xb // Assert uMCTL2 core reset 30 | DATA 4 0x41C80204 0x1 // Start functional clocks. 31 | 32 | /* DRAM 0 controller configuration begin */ 33 | DATA 4 DDRC_MSTR_0 0x81040001 // Set DDR3l, BL = 16 and active ranks 34 | DATA 4 DDRC_RFSHTMG_0 0x0081008B // tREFI, tRFC 35 | DATA 4 DDRC_INIT0_0 0x40030002 // pre_cke = 2ms is too long - DDR3 model hacked for 20us 36 | DATA 4 DDRC_INIT1_0 0x00690000 // dram_rstn - DDR3 model hacked for 20us; 37 | DATA 4 DDRC_INIT3_0 0x00240006 // MR0, MR1 38 | DATA 4 DDRC_INIT4_0 0x00280000 // MR2, MR3 39 | DATA 4 DDRC_INIT5_0 0x0009000F // ZQINIT 40 | DATA 4 DDRC_RANKCTL_0 0x0000072F // diff_rank_wr_gap, diff_rank_rd_gap, max_rank_rd 41 | DATA 4 DDRC_DRAMTMG0_0 0x0F132412 // wr2pr, tFAW, tRASmax, tRASmin 42 | DATA 4 DDRC_DRAMTMG1_0 0x000D0419 // tXP, rd2pre, tRC 43 | DATA 4 DDRC_DRAMTMG2_0 0x0507090B // WL, RL, rd2wr, wr2rd 44 | DATA 4 DDRC_DRAMTMG3_0 0x00002008 // T_MOD, T_MRD 45 | DATA 4 DDRC_DRAMTMG4_0 0x07020408 // trcd, tccd, trrd, trp 46 | DATA 4 DDRC_DRAMTMG5_0 0x0B0B0403 // tCKCKEH, tCKCKEL, tckesr, tcke 47 | DATA 4 DDRC_DRAMTMG8_0 0x04043D07 // tckdpde, tckdpdx, tckcsx 48 | DATA 4 DDRC_ZQCTL0_0 0x40AB002B // tZQCAL, tZQLAT 49 | DATA 4 DDRC_ZQCTL1_0 0x15500083 // tZQReset, tzq_short_interval 50 | DATA 4 DDRC_DFITMG0_0 0x048A8207 51 | DATA 4 DDRC_DFITMG1_0 0x00060303 // dfi_t_wrdata_delay, dfi_t_dram_clk_disable, dfi_t_dram_clk_enable 52 | DATA 4 DDRC_DFITMG2_0 0x00000805 53 | DATA 4 DDRC_DFIMISC_0 0x00000001 // dfi_data_cs_polarity 54 | DATA 4 DDRC_DFIUPD0_0 0xE0400018 // Disable the automatic dfi_ctrlupd_req generation 55 | DATA 4 DDRC_DFIUPD1_0 0x001A0057 // dfi_ctrlupd_req generation interval generation (min and max) 56 | DATA 4 DDRC_DFIUPD2_0 0x80000000 // dfi_phyupd_en 57 | DATA 4 DDRC_ADDRMAP0_0 0x0000001F // addrmap_cs_bit0 58 | DATA 4 DDRC_ADDRMAP3_0 0x00000000 // addrmap_col_b9, addrmap_col_b8, addrmap_col_b7, addrmap_col_b6 59 | DATA 4 DDRC_ADDRMAP4_0 0x00001F1F // addrmap_col_b10 and addrmap_col_b11 set to de-activated 60 | DATA 4 DDRC_ADDRMAP1_0 0x00080808 // addrmap_bank_b2, addrmap_bank_b1, addrmap_bank_b0 61 | DATA 4 DDRC_ADDRMAP5_0 0x07070707 // addrmap_row_b11, addrmap_row_b10_b2, addrmap_row_b1, addrmap_row_b0 62 | DATA 4 DDRC_ADDRMAP6_0 0x0F070707 // addrmap_row_b15, addrmap_row_b14, addrmap_row_b13, addrmap_row_b12 63 | //DATA 4 DDRC_ECCCFG0 0x044FFFC4 // ecc support 64 | //DATA 4 DDRC_DBICTL_0 0x00000007 // rd_dbi_en=wr_dbi_en=dm_en=1 65 | DATA 4 DDRC_ODTCFG_0 0x06000610 66 | DATA 4 DDRC_ODTMAP_0 0x00000001 // rank[3:0]_wr_odt, rank[3:0]_wr_odt 67 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable port 0 68 | 69 | DATA 4 DDRC_DFITMG0_SHADOW_0 0x00808000 70 | 71 | //DATA 4 DDRC_PWRCTL_0 0x0000000B 72 | 73 | DATA 4 0x41c80208 0x1 74 | DATA 4 0x41c80040 0xf 75 | DATA 4 0x41c80204 0x1 76 | 77 | //------------------------------------------- 78 | // Configure registers for PHY initialization 79 | // Timings are computed for 800MHz DRAM operation 80 | //-------------------------------------------- 81 | // Set-up DRAM Configuration Register 82 | DATA 4 DDR_PHY_DCR_0 0x0000040B // DDR3 selection with 8 bank 83 | // Set-up byte and bit swapping registers 84 | DATA 4 DDR_PHY_DX0DQMAP0_0 0x00061032 // DQ bit 0/1/2/3/4 remapping 85 | DATA 4 DDR_PHY_DX0DQMAP1_0 0x00004578 // DQ bit 5/6/7 and DM remapping 86 | DATA 4 DDR_PHY_DX1DQMAP0_0 0x00071032 // DQ bit 0/1/2/3/4 remapping 87 | DATA 4 DDR_PHY_DX1DQMAP1_0 0x00004685 // DQ bit 5/6/7 and DM remapping 88 | DATA 4 DDR_PHY_DX2DQMAP0_0 0x00016578 // DQ bit 0/1/2/3/4 remapping 89 | DATA 4 DDR_PHY_DX2DQMAP1_0 0x00004203 // DQ bit 5/6/7 and DM remapping 90 | DATA 4 DDR_PHY_DX3DQMAP0_0 0x00015867 // DQ bit 0/1/2/3/4 remapping 91 | DATA 4 DDR_PHY_DX3DQMAP1_0 0x00004320 // DQ bit 5/6/7 and DM remapping 92 | DATA 4 DDR_PHY_DX4DQMAP0_0 0x00015867 // DQ bit 0/1/2/3/4 remapping 93 | DATA 4 DDR_PHY_DX4DQMAP1_0 0x00004320 // DQ bit 5/6/7 and DM remapping 94 | // Set-up PHY General Configuration Register 95 | // PGCR1,4,5,6,7 are untouched 96 | SET_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=1 (no uMCTL2 commands can go to memory) and WDQSEXT=1 97 | DATA 4 DDR_PHY_PGCR0_0 0x07001E00 // Set ADCP=1 (Address Copy) 98 | DATA 4 DDR_PHY_PGCR2_0 0x00F030C0 // Set tREFPRD (9*3.904us - 600) 99 | DATA 4 DDR_PHY_PGCR3_0 0x050A1080 // CKEN/CKNEN toggling and polarity 100 | // Set-up PHY Timing Register 101 | // PTR2 is untouched 102 | DATA 4 DDR_PHY_PTR0_0 0x42C21590 // tPLLPD, tPLLGS, tPHYRST 103 | DATA 4 DDR_PHY_PTR1_0 0x341E12C8 // tPLLLOCK reduced to 4.3us, tPLLRST=9us 104 | // Set-up PLL Control Register 105 | DATA 4 DDR_PHY_PLLCR0_0 0x011C0000 106 | DATA 4 DDR_PHY_DX8SLbPLLCR0_0 0x011C0000 107 | // Set-up Impedance Control Register 108 | DATA 4 DDR_PHY_ZQCR_0 0x008A2858 // Set ODT_MODE=0b10(DDR3 stype pullup) 109 | // ZPROG_DRAM_ODT and ZPROG_HOST_ODT 110 | DATA 4 DDR_PHY_ZQ0PR0_0 0x77BB // Optimal setting based on factory testing 111 | DATA 4 DDR_PHY_ZQ1PR0_0 0x77BB // Optimal setting based on factory testing 112 | // Set-up PHY Initialization Register 113 | DATA 4 DDR_PHY_PIR_0 0x72 114 | // Launch initialization (set bit 0) 115 | DATA 4 DDR_PHY_PIR_0 0x73 116 | 117 | 118 | //------------------------------------------- 119 | // Configure registers for DRAM initialization 120 | //------------------------------------------- 121 | // Set-up Mode Register 122 | // MR0, MR3, MR4, MR5 MR6 are untouched 123 | DATA 4 DDR_PHY_MR0_0 0x0024 // Set BL, WR-PRE, nWR, RPST 124 | DATA 4 DDR_PHY_MR1_0 0x0006 // Set RL, WL 125 | DATA 4 DDR_PHY_MR2_0 0x0028 // Set drive strength 126 | DATA 4 DDR_PHY_MR3_0 0x0000 127 | 128 | // Set-up DRAM Timing Parameters Register 129 | // DTPR6 is untouched 130 | DATA 4 DDR_PHY_DTPR0_0 0x08250E09 // tRRD, tRAS, tRP, tRTP 131 | DATA 4 DDR_PHY_DTPR1_0 0x28260500 // tWLMRD, tFAW, tODTUP, tMRD 132 | DATA 4 DDR_PHY_DTPR2_0 0x01060200 // tRTW, tRTODT, tCMDCKE, tCKE, tVRCG, tXS 133 | DATA 4 DDR_PHY_DTPR3_0 0x02000000 // tODX, tCCD, tDLLK, tDQSCKmax, tDQSCK (FIXME double check tDLLK) 134 | DATA 4 DDR_PHY_DTPR4_0 0x018A0C1A // tRFC, tWLO, tXP 135 | DATA 4 DDR_PHY_DTPR5_0 0x00320E09 // tRC, tRCD, tWTR 136 | // Set-up PHY Timing Register 137 | DATA 4 DDR_PHY_PTR3_0 0x00082472 // tDINIT0 - 2ms 138 | DATA 4 DDR_PHY_PTR4_0 0x00000181 // tDINIT1 (2000ns) 139 | DATA 4 DDR_PHY_PTR5_0 0x000341C8 // tDINIT2 140 | DATA 4 DDR_PHY_PTR6_0 0x0400042C // tDINIT4 (30ns), tDINIT3 (1us) 141 | 142 | 143 | // Set-up ODT Configuration Register 144 | // DDR ODT_CA signal is tied at boundary of DDR. Thus no need to drive it dynamically. 145 | DATA 4 DDR_PHY_RANKIDR_0 0x00000000 // Select rank 0 to write 146 | DATA 4 DDR_PHY_ODTCR_0 0x00010000 // ODT of rank1 disabled 147 | 148 | 149 | // Set-up AC I/O Configuration Register 150 | // ACIOCR1-4 are untouched 151 | DATA 4 DDR_PHY_ACIOCR0_0 0x30070400 // PNUM2 (i.e.DDR3) selection [10:11] = 0x2 152 | DATA 4 DDR_PHY_ACIOCR5_0 0x00000000 // I/O mode = DDR3 153 | //DATA 4 DDR_PHY_ACIOCR1_0 0x80000000 154 | DATA 4 DDR_PHY_IOVCR0_0 0x03000000 // DDR_PHY_IOVCR0 155 | 156 | // Set-up DATX8 General Configuration Registers 157 | // DXnGCR0-4 are untouched 158 | SET_BIT 4 DDR_PHY_PGCR5_0 0x4 159 | //DATA 4 DDR_PHY_PGCR6_0 0x00033200 // Enable CSN Bit Delay VT Compensation (AC already enabled by default) + drift limit 160 | // Set-up DATX8 General Configuration Registers 161 | DATA 4 DDR_PHY_DX0GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 162 | DATA 4 DDR_PHY_DX1GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 163 | DATA 4 DDR_PHY_DX2GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 164 | DATA 4 DDR_PHY_DX3GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 165 | DATA 4 DDR_PHY_DX4GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 166 | DATA 4 DDR_PHY_DX0GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 167 | DATA 4 DDR_PHY_DX1GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 168 | DATA 4 DDR_PHY_DX2GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 169 | DATA 4 DDR_PHY_DX3GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 170 | DATA 4 DDR_PHY_DX4GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 171 | // Set-up DATX8 DX Control Register 2 172 | // PREOEX=2.5tCK (0.5 more than MR1), POSOEX=1tCK (0.5 more than in MR3), LPWAKEUP_THRSH=0xA 173 | DATA 4 DDR_PHY_DX8SLbDXCTL2_0 0x001C1400 174 | // Set-up DATX8 IO Control Register 175 | DATA 4 DDR_PHY_DX8SLbIOCR_0 0x00000000 // I/O mode = DDR3 176 | 177 | // ECC Support 178 | //DATA 4 DDRC_PCTRL_0_0 0x00000000 // Disable Port 0 179 | //DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_mode = 1 180 | //DATA 4 DDRC_SBRWDATA0_0 0x55AA55AA // SBRWDATA0 = 55AA55AA 181 | //DATA 4 DDRC_SBRCTL_0 0x00000015 // Scrub_en = 1 182 | //CHECK_BITS_CLR 4 DDRC_SBRSTAT_0 0x1 // Wait for Scrub done 183 | //DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_en = 0 184 | //DATA 4 DDRC_SBRCTL_0 0x00000110 // Scrub_interval = 1 185 | //DATA 4 DDRC_SBRCTL_0 0x00000111 // Scrub_en = 1 186 | //DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable Port 0 187 | 188 | #if DDR_TRAIN_IN_DCD 189 | // Wait PHY initialization end then launch DRAM initialization 190 | // Wait for bit 0 of PGSR0 to be '1' 191 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 192 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 // Check that no error occured 193 | 194 | // Launch DRAM 0 initialization (set bit 0) 195 | DATA 4 DDR_PHY_PIR_0 0x180 196 | DATA 4 DDR_PHY_PIR_0 0x181 197 | 198 | // DRAM 0 initialization end 199 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 200 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 201 | 202 | // Launch a second time DRAM initialization due to following Synopsys PHY bug: 203 | // Title: "PUB does not program DDR3 DRAM MR22 prior to running DRAM ZQ calibration" 204 | // Workaround: "Run DRAM Initialization twice" 205 | //DATA 4 DDR_PHY_PIR_0 0x100 206 | //DATA 4 DDR_PHY_PIR_0 0x101 207 | 208 | // Wait (second time) DRAM 0 initialization end 209 | //CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 210 | //CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 211 | 212 | //---------------------------------------------------------------// 213 | // DATA training 214 | //---------------------------------------------------------------// 215 | // configure PHY for data training 216 | // The following register writes are recommended by SNPS prior to running training 217 | //CLR_BIT 4 DDR_PHY_DQSDR0_0 0x00000001 // Disable drift 218 | //SET_BIT 4 DDR_PHY_PGCR6_0 0x00000001 // Disable VT compensation 219 | //CHECK_BITS_SET 4 DDR_PHY_PGSR1_0 0x40000000 // Disable VT compensation 220 | //SET_BIT 4 DDR_PHY_PGCR1_0 0x00020040 // DISDIC=1; PUBMODE=1 221 | // Per SNPS initialize BIST registers for VREF training 222 | //DATA 4 DDR_PHY_BISTAR1_0 0x00010100 //BMRANK=1 (maximum rank minus 1); BIST Address Increment: 0x10 (16) 223 | //DATA 4 DDR_PHY_BISTAR2_0 0x700003FF // BMBANK=8; BMCOL=0x400 (limit to min cols in JEDEC) 224 | //DATA 4 DDR_PHY_BISTAR4_0 0x00003FFF // BMROW=0x4000 (limit to min rows in JEDEC) 225 | 226 | // Set-up Data Training Configuration Register 227 | // Note that DTCR0.RFSHDT are set to 0x0 as a workaround for PHY bug (Synopsys 228 | // case 9001045655: Design limitation in DDR3 mode: REFRESH must be disabled during DQS2DQ training). 229 | // (FYI avoiding refresh during training leads to Denali error (CUMULATIVE_REFRESH_POSTPONE_EXCEEDS_MAX_ALLOWED). 230 | DATA 4 DDR_PHY_DTCR0_0 0x800031CF // Set DTRPTN to 0x7. RFSHDT=0 231 | DATA 4 DDR_PHY_DTCR1_0 0x00010236 // Set RANKEN=3 232 | 233 | CLR_BIT 4 DDR_PHY_DX4GCR1_0 0xFF // disable byte 4 234 | 235 | // Launch Write leveling 236 | DATA 4 DDR_PHY_PIR_0 0x200 237 | DATA 4 DDR_PHY_PIR_0 0x201 238 | // Wait Write leveling to complete 239 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 240 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00200000 241 | 242 | // Set DQS/DQSn glitch suppression resistor for training PHY0 243 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x012640F7 244 | // Launch Read DQS training 245 | DATA 4 DDR_PHY_PIR_0 0x400 246 | DATA 4 DDR_PHY_PIR_0 0x401 247 | // Wait Read DQS training to complete PHY0 248 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 249 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00400000 250 | // Remove DQS/DQSn glitch suppression resistor PHY0 251 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x01264000 252 | 253 | // DQS2DQ training, Write leveling, Deskew and eye trainings 254 | //DATA 4 DDR_PHY_PIR_0 0x0010F800 255 | //DATA 4 DDR_PHY_PIR_0 0x0010F801 256 | DATA 4 DDR_PHY_PIR_0 0x0000F800 257 | DATA 4 DDR_PHY_PIR_0 0x0000F801 258 | // Wait for training to complete 259 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 260 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 261 | 262 | // Launch VREF training 263 | //DATA 4 DDR_PHY_PIR_0 0x00020000 264 | //DATA 4 DDR_PHY_PIR_0 0x00020001 265 | // Wait for training to complete 266 | //CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 267 | //CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00080000 268 | 269 | //Re-allow uMCTL2 to send commands to DDR 270 | CLR_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=0, PUBMODE=0 271 | 272 | //Check that controller is ready to operate 273 | CHECK_BITS_SET 4 DDRC_STAT_0 0x1 274 | 275 | #endif 276 | -------------------------------------------------------------------------------- /iMX8QX/imx8qx_ddr3_dcd_800MHz_ecc.cfg: -------------------------------------------------------------------------------- 1 | #define __ASSEMBLY__ 2 | 3 | #include 4 | #include 5 | 6 | /* 7 | * Device Configuration Data (DCD) 8 | * 9 | * Each entry must have the format: 10 | * Addr-type Address Value 11 | * 12 | * where: 13 | * Addr-type register length (1,2 or 4 bytes) 14 | * Address absolute address of the register 15 | * value value to be stored in the register 16 | */ 17 | 18 | #ifndef SCFW_DCD 19 | // Set DRAM clock frequency for the following operation: 800MHz 20 | DATA 4 0xff190000 0x00000C85 /* DRC0 bringup */ 21 | #else 22 | /* Set the DRC rate to achieve a DRAM rate as close as possible to 800MHz. */ 23 | uint32_t rate2 = SC_400MHz; 24 | pm_set_clock_rate(SC_PT, SC_R_DRC_0, SC_PM_CLK_MISC0, &rate2); 25 | #endif 26 | 27 | DATA 4 0x41C80208 0x1 28 | DATA 4 0x41C80040 0xb // Assert uMCTL2 core reset 29 | DATA 4 0x41C80204 0x1 // Start functional clocks. 30 | 31 | /* DRAM 0 controller configuration begin */ 32 | DATA 4 DDRC_MSTR_0 0x81040001 // Set DDR3l, BL = 16 and active ranks 33 | DATA 4 DDRC_RFSHTMG_0 0x00620068 // tREFI, tRFC 34 | DATA 4 DDRC_INIT0_0 0x400300C5 // pre_cke 35 | DATA 4 DDRC_INIT1_0 0x00500000 // dram_rstn 36 | DATA 4 DDRC_INIT3_0 0x00700006 // MR0, MR1 37 | DATA 4 DDRC_INIT4_0 0x00180000 // MR2, MR3 38 | DATA 4 DDRC_INIT5_0 0x00090000 // ZQINIT 39 | DATA 4 DDRC_RANKCTL_0 0x0000072F // diff_rank_wr_gap, diff_rank_rd_gap, max_rank_rd 40 | DATA 4 DDRC_DRAMTMG0_0 0x0C0E1B0E // wr2pr, tFAW, tRASmax, tRASmin 41 | DATA 4 DDRC_DRAMTMG1_0 0x000A0313 // tXP, rd2pre, tRC 42 | DATA 4 DDRC_DRAMTMG2_0 0x04060609 // WL, RL, rd2wr, wr2rd 43 | DATA 4 DDRC_DRAMTMG3_0 0x00002006 // T_MOD, T_MRD 44 | DATA 4 DDRC_DRAMTMG4_0 0x06020306 // trcd, tccd, trrd, trp 45 | DATA 4 DDRC_DRAMTMG5_0 0x04040403 // tCKCKEH, tCKCKEL, tckesr, tcke 46 | DATA 4 DDRC_DRAMTMG8_0 0x03030905 // tckdpde, tckdpdx, tckcsx 47 | DATA 4 DDRC_ZQCTL0_0 0x40800020 // tZQCAL, tZQLAT 48 | DATA 4 DDRC_ZQCTL1_0 0x02000062 // tZQReset, tzq_short_interval 49 | DATA 4 DDRC_DFITMG0_0 0x04878205 50 | DATA 4 DDRC_DFITMG1_0 0x00060303 // dfi_t_wrdata_delay, dfi_t_dram_clk_disable, dfi_t_dram_clk_enable 51 | DATA 4 DDRC_DFITMG2_0 0x00000503 52 | DATA 4 DDRC_DFIMISC_0 0x00000001 // dfi_data_cs_polarity 53 | DATA 4 DDRC_DFIUPD0_0 0xE0400018 // Disable the automatic dfi_ctrlupd_req generation 54 | DATA 4 DDRC_DFIUPD1_0 0x001A0057 // dfi_ctrlupd_req generation interval generation (min and max) 55 | DATA 4 DDRC_DFIUPD2_0 0x80000000 // dfi_phyupd_en 56 | DATA 4 DDRC_ADDRMAP0_0 0x0000001F // addrmap_cs_bit0 57 | DATA 4 DDRC_ADDRMAP3_0 0x00000000 // addrmap_col_b9, addrmap_col_b8, addrmap_col_b7, addrmap_col_b6 58 | DATA 4 DDRC_ADDRMAP4_0 0x00001F1F // addrmap_col_b10 and addrmap_col_b11 set to de-activated 59 | DATA 4 DDRC_ADDRMAP1_0 0x00080808 // addrmap_bank_b2, addrmap_bank_b1, addrmap_bank_b0 60 | DATA 4 DDRC_ADDRMAP5_0 0x07070707 // addrmap_row_b11, addrmap_row_b10_b2, addrmap_row_b1, addrmap_row_b0 61 | DATA 4 DDRC_ADDRMAP6_0 0x0F070707 // addrmap_row_b15, addrmap_row_b14, addrmap_row_b13, addrmap_row_b12 62 | DATA 4 DDRC_ECCCFG0_0 0x044FFFC4 // ecc support (uncommented when ECC is enabled) 63 | 64 | DATA 4 DDRC_ODTCFG_0 0x06000610 65 | DATA 4 DDRC_ODTMAP_0 0x00000001 // rank[3:0]_wr_odt, rank[3:0]_wr_odt 66 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable port 0 67 | 68 | DATA 4 DDRC_DFITMG0_SHADOW_0 0x00808000 69 | 70 | DATA 4 DDRC_PWRCTL_0 0x00000000 71 | 72 | DATA 4 0x41c80208 0x1 73 | DATA 4 0x41c80040 0xf 74 | DATA 4 0x41c80204 0x1 75 | 76 | //------------------------------------------- 77 | // Configure registers for PHY initialization 78 | // Timings are computed for 800MHz DRAM operation 79 | //-------------------------------------------- 80 | // Set-up DRAM Configuration Register 81 | DATA 4 DDR_PHY_DCR_0 0x0000040B // DDR3 selection with 8 bank 82 | // Set-up byte and bit swapping registers 83 | DATA 4 DDR_PHY_DX0DQMAP0_0 0x00071628 // DQ bit 0/1/2/3/4 remapping 84 | DATA 4 DDR_PHY_DX0DQMAP1_0 0x00004053 // DQ bit 5/6/7 and DM remapping 85 | DATA 4 DDR_PHY_DX1DQMAP0_0 0x00073826 // DQ bit 0/1/2/3/4 remapping 86 | DATA 4 DDR_PHY_DX1DQMAP1_0 0x00004150 // DQ bit 5/6/7 and DM remapping 87 | DATA 4 DDR_PHY_DX2DQMAP0_0 0x00053608 // DQ bit 0/1/2/3/4 remapping 88 | DATA 4 DDR_PHY_DX2DQMAP1_0 0x00004271 // DQ bit 5/6/7 and DM remapping 89 | DATA 4 DDR_PHY_DX3DQMAP0_0 0x00053826 // DQ bit 0/1/2/3/4 remapping 90 | DATA 4 DDR_PHY_DX3DQMAP1_0 0x00004170 // DQ bit 5/6/7 and DM remapping 91 | DATA 4 DDR_PHY_DX4DQMAP0_0 0x00005281 // DQ bit 0/1/2/3/4 remapping 92 | DATA 4 DDR_PHY_DX4DQMAP1_0 0x00004736 // DQ bit 5/6/7 and DM remapping 93 | // Set-up PHY General Configuration Register 94 | // PGCR1,4,5,6,7 are untouched 95 | SET_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=1 (no uMCTL2 commands can go to memory) 96 | DATA 4 DDR_PHY_PGCR0_0 0x07001E00 // Set ADCP=1 (Address Copy) 97 | DATA 4 DDR_PHY_PGCR2_0 0x00F0C170 // Set tREFPRD 98 | DATA 4 DDR_PHY_PGCR3_0 0x050A1080 // CKEN/CKNEN toggling and polarity 99 | // Set-up PHY Timing Register 100 | // PTR2 is untouched 101 | DATA 4 DDR_PHY_PTR0_0 0x32019010 // tPLLPD, tPLLGS, tPHYRST 102 | DATA 4 DDR_PHY_PTR1_0 0x27100E10 // tPLLLOCK, tPLLRST 103 | // Set-up PLL Control Register 104 | DATA 4 DDR_PHY_PLLCR0_0 0x011C0000 105 | DATA 4 DDR_PHY_DX8SLbPLLCR0_0 0x011C0000 106 | // Set-up Impedance Control Register 107 | DATA 4 DDR_PHY_ZQCR_0 0x008A2858 // Set ODT_MODE=0b10(DDR3 stype pullup) 108 | // ZPROG_DRAM_ODT and ZPROG_HOST_ODT 109 | DATA 4 DDR_PHY_ZQ0PR0_0 0x77BB // Optimal setting based on factory testing 110 | DATA 4 DDR_PHY_ZQ1PR0_0 0x77BB // Optimal setting based on factory testing 111 | // Set-up PHY Initialization Register 112 | DATA 4 DDR_PHY_PIR_0 0x72 113 | // Launch initialization (set bit 0) 114 | DATA 4 DDR_PHY_PIR_0 0x73 115 | 116 | 117 | //------------------------------------------- 118 | // Configure registers for DRAM initialization 119 | //------------------------------------------- 120 | // Set-up Mode Register 121 | // MR0, MR3, MR4, MR5 MR6 are untouched 122 | DATA 4 DDR_PHY_MR0_0 0x00000070 123 | DATA 4 DDR_PHY_MR1_0 0x00000006 124 | DATA 4 DDR_PHY_MR2_0 0x00000018 125 | DATA 4 DDR_PHY_MR3_0 0x00000000 126 | 127 | // Set-up DRAM Timing Parameters Register 128 | // DTPR6 is untouched 129 | DATA 4 DDR_PHY_DTPR0_0 0x051B0B06 // tRRD, tRAS, tRP, tRTP 130 | DATA 4 DDR_PHY_DTPR1_0 0x281C0000 // tWLMRD, tFAW, tODTUP, tMRD 131 | DATA 4 DDR_PHY_DTPR2_0 0x01060200 // tRTW, tRTODT, tCMDCKE, tCKE, tVRCG, tXS 132 | DATA 4 DDR_PHY_DTPR3_0 0x02000000 // tODX, tCCD, tDLLK, tDQSCKmax, tDQSCK (FIXME double check tDLLK) 133 | DATA 4 DDR_PHY_DTPR4_0 0x00D00C14 // tRFC, tWLO, tXP 134 | DATA 4 DDR_PHY_DTPR5_0 0x00250B07 // tRC, tRCD, tWTR 135 | // Set-up PHY Timing Register 136 | DATA 4 DDR_PHY_PTR3_0 0x00061A80 // tDINIT0 137 | DATA 4 DDR_PHY_PTR4_0 0x000000D0 // tDINIT1 138 | DATA 4 DDR_PHY_PTR5_0 0x00027100 // tDINIT2 139 | DATA 4 DDR_PHY_PTR6_0 0x04000321 // tDINIT4, tDINIT3 140 | 141 | 142 | // Set-up ODT Configuration Register 143 | // DDR ODT_CA signal is tied at boundary of DDR. Thus no need to drive it dynamically. 144 | DATA 4 DDR_PHY_RANKIDR_0 0x00000000 // Select rank 0 to write 145 | DATA 4 DDR_PHY_ODTCR_0 0x00010000 // ODT of rank1 disabled 146 | 147 | 148 | // Set-up AC I/O Configuration Register 149 | // ACIOCR1-4 are untouched 150 | DATA 4 DDR_PHY_ACIOCR0_0 0x30070400 // PNUM2 (i.e.DDR3) selection [10:11] = 0x2 151 | DATA 4 DDR_PHY_ACIOCR5_0 0x00000000 // I/O mode = DDR3 152 | DATA 4 DDR_PHY_IOVCR0_0 0x03000000 153 | // Set-up DATX8 General Configuration Registers 154 | // DXnGCR0-4 are untouched 155 | DATA 4 DDR_PHY_PGCR5_0 0x01010004 156 | // Set-up DATX8 General Configuration Registers 157 | DATA 4 DDR_PHY_DX0GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 158 | DATA 4 DDR_PHY_DX1GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 159 | DATA 4 DDR_PHY_DX2GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 160 | DATA 4 DDR_PHY_DX3GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 161 | DATA 4 DDR_PHY_DX4GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 162 | DATA 4 DDR_PHY_DX0GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 163 | DATA 4 DDR_PHY_DX1GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 164 | DATA 4 DDR_PHY_DX2GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 165 | DATA 4 DDR_PHY_DX3GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 166 | DATA 4 DDR_PHY_DX4GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 167 | // Set-up DATX8 DX Control Register 2 168 | // PREOEX=2.5tCK (0.5 more than MR1), POSOEX=1tCK (0.5 more than in MR3), LPWAKEUP_THRSH=0xA 169 | DATA 4 DDR_PHY_DX8SLbDXCTL2_0 0x001C1400 170 | // Set-up DATX8 IO Control Register 171 | DATA 4 DDR_PHY_DX8SLbIOCR_0 0x00000000 // I/O mode = DDR3 172 | 173 | #if DDR_TRAIN_IN_DCD 174 | // Wait PHY initialization end then launch DRAM initialization 175 | // Wait for bit 0 of PGSR0 to be '1' 176 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 177 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 // Check that no error occured 178 | 179 | // Launch DRAM 0 initialization (set bit 0) 180 | DATA 4 DDR_PHY_PIR_0 0x180 181 | DATA 4 DDR_PHY_PIR_0 0x181 182 | 183 | // DRAM 0 initialization end 184 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 185 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 186 | 187 | //---------------------------------------------------------------// 188 | // DATA training 189 | //---------------------------------------------------------------// 190 | // Set-up Data Training Configuration Register 191 | // Note that DTCR0.RFSHDT are set to 0x0 as a workaround for PHY bug (Synopsys 192 | // case 9001045655: Design limitation in DDR3 mode: REFRESH must be disabled during DQS2DQ training). 193 | // (FYI avoiding refresh during training leads to Denali error (CUMULATIVE_REFRESH_POSTPONE_EXCEEDS_MAX_ALLOWED). 194 | DATA 4 DDR_PHY_DTCR0_0 0x800031CF // Set DTRPTN to 0x7. RFSHDT=0 195 | DATA 4 DDR_PHY_DTCR1_0 0x00010237 // Set RANKEN=3 196 | 197 | // CLR_BIT 4 DDR_PHY_DX4GCR1_0 0xFF // disable byte 4 (this line is commented out when ECC is enabled) 198 | 199 | // Launch Write leveling 200 | DATA 4 DDR_PHY_PIR_0 0x200 201 | DATA 4 DDR_PHY_PIR_0 0x201 202 | // Wait Write leveling to complete 203 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 204 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00200000 205 | 206 | // Set DQS/DQSn glitch suppression resistor for training PHY0 207 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x012640F7 208 | // Launch Read DQS training 209 | DATA 4 DDR_PHY_PIR_0 0x400 210 | DATA 4 DDR_PHY_PIR_0 0x401 211 | // Wait Read DQS training to complete PHY0 212 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 213 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00400000 214 | // Remove DQS/DQSn glitch suppression resistor PHY0 215 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x01264000 216 | 217 | // DQS2DQ training, Write leveling, Deskew and eye trainings 218 | DATA 4 DDR_PHY_PIR_0 0x0000F800 219 | DATA 4 DDR_PHY_PIR_0 0x0000F801 220 | // Wait for training to complete 221 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 222 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 223 | 224 | //Re-allow uMCTL2 to send commands to DDR 225 | CLR_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=0, PUBMODE=0 226 | 227 | //Check that controller is ready to operate 228 | CHECK_BITS_SET 4 DDRC_STAT_0 0x1 229 | 230 | #endif 231 | 232 | // ECC Support (the following lines are uncommented when ECC is enabled) 233 | DATA 4 DDRC_PCTRL_0_0 0x00000000 // Disable Port 0 234 | DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_mode = 1 235 | DATA 4 DDRC_SBRWDATA0_0 0x55AA55AA // SBRWDATA0 = 55AA55AA 236 | DATA 4 DDRC_SBRCTL_0 0x00000015 // Scrub_en = 1 237 | CHECK_BITS_SET 4 DDRC_SBRSTAT_0 0x2 // Wait for Scrub done 238 | CHECK_BITS_CLR 4 DDRC_SBRSTAT_0 0x1 // Wait for Scrub done 239 | DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_en = 0 240 | DATA 4 DDRC_SBRCTL_0 0x00000110 // Scrub_interval = 1 241 | DATA 4 DDRC_SBRCTL_0 0x00000111 // Scrub_en = 1 242 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable Port 0 243 | 244 | -------------------------------------------------------------------------------- /iMX8QX/imx8qx_ddr3_dcd_933MHz.cfg: -------------------------------------------------------------------------------- 1 | #define __ASSEMBLY__ 2 | 3 | #include 4 | #include 5 | 6 | /* 7 | * Device Configuration Data (DCD) 8 | * 9 | * Each entry must have the format: 10 | * Addr-type Address Value 11 | * 12 | * where: 13 | * Addr-type register length (1,2 or 4 bytes) 14 | * Address absolute address of the register 15 | * value value to be stored in the register 16 | */ 17 | 18 | #ifndef SCFW_DCD 19 | //DATA 4 0xff190000 0x00000C84 /* DRC0 bringup */ 20 | /* For 800MHz DDR, DRC 400MHz operation */ 21 | //DATA 4 0xff190000 0x00000C85 /* DRC0 bringup */ 22 | /* For 933MHz DDR, DRC 465MHz operation */ 23 | DATA 4 0xff190000 0x00000C9B /* DRC0 bringup */ 24 | #else 25 | /* Set the DRC rate to 465MHz, the PHY PLL will double this for the DRAM rate. */ 26 | uint32_t rate2 = SC_465MHZ; 27 | pm_set_clock_rate(SC_PT, SC_R_DRC_0, SC_PM_CLK_MISC0, &rate2); 28 | #endif 29 | 30 | DATA 4 0x41C80208 0x1 31 | DATA 4 0x41C80040 0xb // Assert uMCTL2 core reset 32 | DATA 4 0x41C80204 0x1 // Start functional clocks. 33 | 34 | /* DRAM 0 controller configuration begin */ 35 | DATA 4 DDRC_MSTR_0 0x81040001 // Set DDR3l, BL = 16 and active ranks 36 | DATA 4 DDRC_RFSHTMG_0 0x0072007A // tREFI, tRFC 37 | DATA 4 DDRC_INIT0_0 0x400300E5 // pre_cke = 2ms is too long - DDR3 model hacked for 20us 38 | DATA 4 DDRC_INIT1_0 0x005D0000 // dram_rstn - DDR3 model hacked for 20us; 39 | DATA 4 DDRC_INIT3_0 0x00140006 // MR0, MR1 40 | DATA 4 DDRC_INIT4_0 0x00200000 // MR2, MR3 41 | DATA 4 DDRC_INIT5_0 0x000B0000 // ZQINIT 42 | DATA 4 DDRC_RANKCTL_0 0x0000072F // diff_rank_wr_gap, diff_rank_rd_gap, max_rank_rd 43 | DATA 4 DDRC_DRAMTMG0_0 0x0E112010 // wr2pr, tFAW, tRASmax, tRASmin 44 | DATA 4 DDRC_DRAMTMG1_0 0x000C0416 // tXP, rd2pre, tRC 45 | DATA 4 DDRC_DRAMTMG2_0 0x0507090B // WL, RL, rd2wr, wr2rd 46 | DATA 4 DDRC_DRAMTMG3_0 0x00002008 // T_MOD, T_MRD 47 | DATA 4 DDRC_DRAMTMG4_0 0x07020307 // trcd, tccd, trrd, trp 48 | DATA 4 DDRC_DRAMTMG5_0 0x05050403 // tCKCKEH, tCKCKEL, tckesr, tcke 49 | DATA 4 DDRC_DRAMTMG8_0 0x03030905 // tckdpde, tckdpdx, tckcsx 50 | DATA 4 DDRC_ZQCTL0_0 0x40960026 // tZQCAL, tZQLAT 51 | DATA 4 DDRC_ZQCTL1_0 0x02000072 // tZQReset, tzq_short_interval 52 | DATA 4 DDRC_DFITMG0_0 0x04898206 53 | DATA 4 DDRC_DFITMG1_0 0x00060303 // dfi_t_wrdata_delay, dfi_t_dram_clk_disable, dfi_t_dram_clk_enable 54 | DATA 4 DDRC_DFITMG2_0 0x00000704 55 | DATA 4 DDRC_DFIMISC_0 0x00000001 // dfi_data_cs_polarity 56 | DATA 4 DDRC_DFIUPD0_0 0xE0400018 // Disable the automatic dfi_ctrlupd_req generation 57 | DATA 4 DDRC_DFIUPD1_0 0x001A0057 // dfi_ctrlupd_req generation interval generation (min and max) 58 | DATA 4 DDRC_DFIUPD2_0 0x80000000 // dfi_phyupd_en 59 | DATA 4 DDRC_ADDRMAP0_0 0x0000001F // addrmap_cs_bit0 60 | DATA 4 DDRC_ADDRMAP3_0 0x00000000 // addrmap_col_b9, addrmap_col_b8, addrmap_col_b7, addrmap_col_b6 61 | DATA 4 DDRC_ADDRMAP4_0 0x00001F1F // addrmap_col_b10 and addrmap_col_b11 set to de-activated 62 | DATA 4 DDRC_ADDRMAP1_0 0x00080808 // addrmap_bank_b2, addrmap_bank_b1, addrmap_bank_b0 63 | DATA 4 DDRC_ADDRMAP5_0 0x07070707 // addrmap_row_b11, addrmap_row_b10_b2, addrmap_row_b1, addrmap_row_b0 64 | DATA 4 DDRC_ADDRMAP6_0 0x0F070707 // addrmap_row_b15, addrmap_row_b14, addrmap_row_b13, addrmap_row_b12 65 | // DATA 4 DDRC_ECCCFG0 0x044FFFC0 // ecc support 66 | 67 | DATA 4 DDRC_ODTCFG_0 0x06000610 68 | DATA 4 DDRC_ODTMAP_0 0x00000001 // rank[3:0]_wr_odt, rank[3:0]_wr_odt 69 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable port 0 70 | 71 | DATA 4 DDRC_DFITMG0_SHADOW_0 0x00808000 72 | 73 | DATA 4 DDRC_PWRCTL_0 0x00000000 74 | 75 | DATA 4 0x41c80208 0x1 76 | DATA 4 0x41c80040 0xf 77 | DATA 4 0x41c80204 0x1 78 | 79 | //------------------------------------------- 80 | // Configure registers for PHY initialization 81 | // Timings are computed for 933MHz DRAM operation 82 | //-------------------------------------------- 83 | // Set-up DRAM Configuration Register 84 | DATA 4 DDR_PHY_DCR_0 0x0000040B // DDR3 selection with 8 bank 85 | // Set-up byte and bit swapping registers 86 | DATA 4 DDR_PHY_DX0DQMAP0_0 0x00071628 // DQ bit 0/1/2/3/4 remapping 87 | DATA 4 DDR_PHY_DX0DQMAP1_0 0x00004053 // DQ bit 5/6/7 and DM remapping 88 | DATA 4 DDR_PHY_DX1DQMAP0_0 0x00073826 // DQ bit 0/1/2/3/4 remapping 89 | DATA 4 DDR_PHY_DX1DQMAP1_0 0x00004150 // DQ bit 5/6/7 and DM remapping 90 | DATA 4 DDR_PHY_DX2DQMAP0_0 0x00053608 // DQ bit 0/1/2/3/4 remapping 91 | DATA 4 DDR_PHY_DX2DQMAP1_0 0x00004271 // DQ bit 5/6/7 and DM remapping 92 | DATA 4 DDR_PHY_DX3DQMAP0_0 0x00053826 // DQ bit 0/1/2/3/4 remapping 93 | DATA 4 DDR_PHY_DX3DQMAP1_0 0x00004170 // DQ bit 5/6/7 and DM remapping 94 | DATA 4 DDR_PHY_DX4DQMAP0_0 0x00005281 // DQ bit 0/1/2/3/4 remapping 95 | DATA 4 DDR_PHY_DX4DQMAP1_0 0x00004736 // DQ bit 5/6/7 and DM remapping 96 | // Set-up PHY General Configuration Register 97 | // PGCR1,4,5,6,7 are untouched 98 | SET_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=1 (no uMCTL2 commands can go to memory) 99 | DATA 4 DDR_PHY_PGCR0_0 0x07001E00 // Set ADCP=1 (Address Copy) 100 | DATA 4 DDR_PHY_PGCR2_0 0x00F0E207 // Set tREFPRD (9*3.904us - 600) 101 | DATA 4 DDR_PHY_PGCR3_0 0x050A1080 // CKEN/CKNEN toggling and polarity 102 | // Set-up PHY Timing Register 103 | // PTR2 is untouched 104 | DATA 4 DDR_PHY_PTR0_0 0x3A61D310 // tPLLPD, tPLLGS, tPHYRST 105 | DATA 4 DDR_PHY_PTR1_0 0x2D98106A // tPLLLOCK reduced to 4.3us, tPLLRST=9us 106 | // Set-up PLL Control Register 107 | DATA 4 DDR_PHY_PLLCR0_0 0x011C0000 108 | DATA 4 DDR_PHY_DX8SLbPLLCR0_0 0x011C0000 109 | // Set-up Impedance Control Register 110 | DATA 4 DDR_PHY_ZQCR_0 0x008A2858 // Set ODT_MODE=0b10(DDR3 stype pullup) 111 | // ZPROG_DRAM_ODT and ZPROG_HOST_ODT 112 | DATA 4 DDR_PHY_ZQ0PR0_0 0x77BB // Optimal setting based on factory testing 113 | DATA 4 DDR_PHY_ZQ1PR0_0 0x77BB // Optimal setting based on factory testing 114 | // Set-up PHY Initialization Register 115 | DATA 4 DDR_PHY_PIR_0 0x72 116 | // Launch initialization (set bit 0) 117 | DATA 4 DDR_PHY_PIR_0 0x73 118 | 119 | 120 | //------------------------------------------- 121 | // Configure registers for DRAM initialization 122 | //------------------------------------------- 123 | // Set-up Mode Register 124 | // MR0, MR3, MR4, MR5 MR6 are untouched 125 | DATA 4 DDR_PHY_MR0_0 0x00000014 126 | DATA 4 DDR_PHY_MR1_0 0x00000006 127 | DATA 4 DDR_PHY_MR2_0 0x00000020 128 | DATA 4 DDR_PHY_MR3_0 0x00000000 129 | 130 | // Set-up DRAM Timing Parameters Register 131 | // DTPR6 is untouched 132 | DATA 4 DDR_PHY_DTPR0_0 0x061F0D08 // tRRD, tRAS, tRP, tRTP 133 | DATA 4 DDR_PHY_DTPR1_0 0x28210300 // tWLMRD, tFAW, tODTUP, tMRD 134 | DATA 4 DDR_PHY_DTPR2_0 0x01060200 // tRTW, tRTODT, tCMDCKE, tCKE, tVRCG, tXS 135 | DATA 4 DDR_PHY_DTPR3_0 0x02000000 // tODX, tCCD, tDLLK, tDQSCKmax, tDQSCK (FIXME double check tDLLK) 136 | DATA 4 DDR_PHY_DTPR4_0 0x00F30C17 // tRFC, tWLO, tXP 137 | DATA 4 DDR_PHY_DTPR5_0 0x002C0D09 // tRC, tRCD, tWTR 138 | // Set-up PHY Timing Register 139 | DATA 4 DDR_PHY_PTR3_0 0x00071FA6 // tDINIT0 - 2ms 140 | DATA 4 DDR_PHY_PTR4_0 0x000000F3 // tDINIT1 (2000ns) 141 | DATA 4 DDR_PHY_PTR5_0 0x0002D976 // tDINIT2 142 | DATA 4 DDR_PHY_PTR6_0 0x040003A7 // tDINIT4 (30ns), tDINIT3 (1us) 143 | 144 | 145 | // Set-up ODT Configuration Register 146 | // DDR ODT_CA signal is tied at boundary of DDR. Thus no need to drive it dynamically. 147 | DATA 4 DDR_PHY_RANKIDR_0 0x00000000 // Select rank 0 to write 148 | DATA 4 DDR_PHY_ODTCR_0 0x00010000 // ODT of rank1 disabled 149 | 150 | 151 | // Set-up AC I/O Configuration Register 152 | // ACIOCR1-4 are untouched 153 | DATA 4 DDR_PHY_ACIOCR0_0 0x30070400 // PNUM2 (i.e.DDR3) selection [10:11] = 0x2 154 | DATA 4 DDR_PHY_ACIOCR5_0 0x00000000 // I/O mode = DDR3 155 | DATA 4 DDR_PHY_IOVCR0_0 0x03000000 156 | // Set-up DATX8 General Configuration Registers 157 | // DXnGCR0-4 are untouched 158 | DATA 4 DDR_PHY_PGCR5_0 0x01010004 159 | // Set-up DATX8 General Configuration Registers 160 | DATA 4 DDR_PHY_DX0GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 161 | DATA 4 DDR_PHY_DX1GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 162 | DATA 4 DDR_PHY_DX2GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 163 | DATA 4 DDR_PHY_DX3GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 164 | DATA 4 DDR_PHY_DX4GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 165 | DATA 4 DDR_PHY_DX0GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 166 | DATA 4 DDR_PHY_DX1GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 167 | DATA 4 DDR_PHY_DX2GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 168 | DATA 4 DDR_PHY_DX3GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 169 | DATA 4 DDR_PHY_DX4GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 170 | // Set-up DATX8 DX Control Register 2 171 | // PREOEX=2.5tCK (0.5 more than MR1), POSOEX=1tCK (0.5 more than in MR3), LPWAKEUP_THRSH=0xA 172 | DATA 4 DDR_PHY_DX8SLbDXCTL2_0 0x001C1400 173 | // Set-up DATX8 IO Control Register 174 | DATA 4 DDR_PHY_DX8SLbIOCR_0 0x00000000 // I/O mode = DDR3 175 | 176 | // ECC Support 177 | //DATA 4 DDRC_PCTRL_0_0 0x00000000 // Disable Port 0 178 | //DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_mode = 1 179 | //DATA 4 DDRC_SBRWDATA0_0 0x55AA55AA // SBRWDATA0 = 55AA55AA 180 | //DATA 4 DDRC_SBRCTL_0 0x00000015 // Scrub_en = 1 181 | //CHECK_BITS_CLR 4 DDRC_SBRSTAT_0 0x1 // Wait for Scrub done 182 | //DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_en = 0 183 | //DATA 4 DDRC_SBRCTL_0 0x00000110 // Scrub_interval = 1 184 | //DATA 4 DDRC_SBRCTL_0 0x00000111 // Scrub_en = 1 185 | //DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable Port 0 186 | 187 | #if DDR_TRAIN_IN_DCD 188 | // Wait PHY initialization end then launch DRAM initialization 189 | // Wait for bit 0 of PGSR0 to be '1' 190 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 191 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 // Check that no error occured 192 | 193 | // Launch DRAM 0 initialization (set bit 0) 194 | DATA 4 DDR_PHY_PIR_0 0x180 195 | DATA 4 DDR_PHY_PIR_0 0x181 196 | 197 | // DRAM 0 initialization end 198 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 199 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 200 | 201 | //---------------------------------------------------------------// 202 | // DATA training 203 | //---------------------------------------------------------------// 204 | // Set-up Data Training Configuration Register 205 | // Note that DTCR0.RFSHDT are set to 0x0 as a workaround for PHY bug (Synopsys 206 | // case 9001045655: Design limitation in DDR3 mode: REFRESH must be disabled during DQS2DQ training). 207 | // (FYI avoiding refresh during training leads to Denali error (CUMULATIVE_REFRESH_POSTPONE_EXCEEDS_MAX_ALLOWED). 208 | DATA 4 DDR_PHY_DTCR0_0 0x800031CF // Set DTRPTN to 0x7. RFSHDT=0 209 | DATA 4 DDR_PHY_DTCR1_0 0x00010237 // Set RANKEN=3 210 | 211 | CLR_BIT 4 DDR_PHY_DX4GCR1_0 0xFF // disable byte 4 212 | 213 | // Launch Write leveling 214 | DATA 4 DDR_PHY_PIR_0 0x200 215 | DATA 4 DDR_PHY_PIR_0 0x201 216 | // Wait Write leveling to complete 217 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 218 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00200000 219 | 220 | // Set DQS/DQSn glitch suppression resistor for training PHY0 221 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x012640F7 222 | // Launch Read DQS training 223 | DATA 4 DDR_PHY_PIR_0 0x400 224 | DATA 4 DDR_PHY_PIR_0 0x401 225 | // Wait Read DQS training to complete PHY0 226 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 227 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00400000 228 | // Remove DQS/DQSn glitch suppression resistor PHY0 229 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x01264000 230 | 231 | // DQS2DQ training, Write leveling, Deskew and eye trainings 232 | DATA 4 DDR_PHY_PIR_0 0x0000F800 233 | DATA 4 DDR_PHY_PIR_0 0x0000F801 234 | // Wait for training to complete 235 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 236 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 237 | 238 | //Re-allow uMCTL2 to send commands to DDR 239 | CLR_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=0, PUBMODE=0 240 | 241 | //Check that controller is ready to operate 242 | CHECK_BITS_SET 4 DDRC_STAT_0 0x1 243 | 244 | #endif 245 | -------------------------------------------------------------------------------- /iMX8QX/imx8qx_ddr3_dcd_933MHz_ecc.cfg: -------------------------------------------------------------------------------- 1 | #define __ASSEMBLY__ 2 | 3 | #include 4 | #include 5 | 6 | /* 7 | * Device Configuration Data (DCD) 8 | * 9 | * Each entry must have the format: 10 | * Addr-type Address Value 11 | * 12 | * where: 13 | * Addr-type register length (1,2 or 4 bytes) 14 | * Address absolute address of the register 15 | * value value to be stored in the register 16 | */ 17 | 18 | #ifndef SCFW_DCD 19 | // Set DRAM clock frequency for the following operation: 933MHz 20 | DATA 4 0xff190000 0x00000C9B /* DRC0 bringup */ 21 | #else 22 | /* Set the DRC rate to achieve a DRAM rate as close as possible to 933MHz. */ 23 | uint32_t rate2 = 465000000; 24 | pm_set_clock_rate(SC_PT, SC_R_DRC_0, SC_PM_CLK_MISC0, &rate2); 25 | #endif 26 | 27 | DATA 4 0x41C80208 0x1 28 | DATA 4 0x41C80040 0xb // Assert uMCTL2 core reset 29 | DATA 4 0x41C80204 0x1 // Start functional clocks. 30 | 31 | /* DRAM 0 controller configuration begin */ 32 | DATA 4 DDRC_MSTR_0 0x81040001 // Set DDR3l, BL = 16 and active ranks 33 | DATA 4 DDRC_RFSHTMG_0 0x0072007A // tREFI, tRFC 34 | DATA 4 DDRC_INIT0_0 0x400300E5 // pre_cke 35 | DATA 4 DDRC_INIT1_0 0x005D0000 // dram_rstn 36 | DATA 4 DDRC_INIT3_0 0x00140006 // MR0, MR1 37 | DATA 4 DDRC_INIT4_0 0x00200000 // MR2, MR3 38 | DATA 4 DDRC_INIT5_0 0x000B0000 // ZQINIT 39 | DATA 4 DDRC_RANKCTL_0 0x0000072F // diff_rank_wr_gap, diff_rank_rd_gap, max_rank_rd 40 | DATA 4 DDRC_DRAMTMG0_0 0x0E112010 // wr2pr, tFAW, tRASmax, tRASmin 41 | DATA 4 DDRC_DRAMTMG1_0 0x000C0416 // tXP, rd2pre, tRC 42 | DATA 4 DDRC_DRAMTMG2_0 0x0507060B // WL, RL, rd2wr, wr2rd 43 | DATA 4 DDRC_DRAMTMG3_0 0x00002008 // T_MOD, T_MRD 44 | DATA 4 DDRC_DRAMTMG4_0 0x07020307 // trcd, tccd, trrd, trp 45 | DATA 4 DDRC_DRAMTMG5_0 0x05050403 // tCKCKEH, tCKCKEL, tckesr, tcke 46 | DATA 4 DDRC_DRAMTMG8_0 0x03030905 // tckdpde, tckdpdx, tckcsx 47 | DATA 4 DDRC_ZQCTL0_0 0x40960026 // tZQCAL, tZQLAT 48 | DATA 4 DDRC_ZQCTL1_0 0x02000072 // tZQReset, tzq_short_interval 49 | DATA 4 DDRC_DFITMG0_0 0x04898206 50 | DATA 4 DDRC_DFITMG1_0 0x00060303 // dfi_t_wrdata_delay, dfi_t_dram_clk_disable, dfi_t_dram_clk_enable 51 | DATA 4 DDRC_DFITMG2_0 0x00000704 52 | DATA 4 DDRC_DFIMISC_0 0x00000001 // dfi_data_cs_polarity 53 | DATA 4 DDRC_DFIUPD0_0 0xE0400018 // Disable the automatic dfi_ctrlupd_req generation 54 | DATA 4 DDRC_DFIUPD1_0 0x001A0057 // dfi_ctrlupd_req generation interval generation (min and max) 55 | DATA 4 DDRC_DFIUPD2_0 0x80000000 // dfi_phyupd_en 56 | DATA 4 DDRC_ADDRMAP0_0 0x0000001F // addrmap_cs_bit0 57 | DATA 4 DDRC_ADDRMAP3_0 0x00000000 // addrmap_col_b9, addrmap_col_b8, addrmap_col_b7, addrmap_col_b6 58 | DATA 4 DDRC_ADDRMAP4_0 0x00001F1F // addrmap_col_b10 and addrmap_col_b11 set to de-activated 59 | DATA 4 DDRC_ADDRMAP1_0 0x00080808 // addrmap_bank_b2, addrmap_bank_b1, addrmap_bank_b0 60 | DATA 4 DDRC_ADDRMAP5_0 0x07070707 // addrmap_row_b11, addrmap_row_b10_b2, addrmap_row_b1, addrmap_row_b0 61 | DATA 4 DDRC_ADDRMAP6_0 0x0F070707 // addrmap_row_b15, addrmap_row_b14, addrmap_row_b13, addrmap_row_b12 62 | DATA 4 DDRC_ECCCFG0_0 0x044FFFC4 // ecc support (uncommented when ECC is enabled) 63 | 64 | DATA 4 DDRC_ODTCFG_0 0x06000610 65 | DATA 4 DDRC_ODTMAP_0 0x00000001 // rank[3:0]_wr_odt, rank[3:0]_wr_odt 66 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable port 0 67 | 68 | DATA 4 DDRC_DFITMG0_SHADOW_0 0x00808000 69 | 70 | DATA 4 DDRC_PWRCTL_0 0x00000000 71 | 72 | DATA 4 0x41c80208 0x1 73 | DATA 4 0x41c80040 0xf 74 | DATA 4 0x41c80204 0x1 75 | 76 | //------------------------------------------- 77 | // Configure registers for PHY initialization 78 | // Timings are computed for 933MHz DRAM operation 79 | //-------------------------------------------- 80 | // Set-up DRAM Configuration Register 81 | DATA 4 DDR_PHY_DCR_0 0x0000040B // DDR3 selection with 8 bank 82 | // Set-up byte and bit swapping registers 83 | DATA 4 DDR_PHY_DX0DQMAP0_0 0x00071628 // DQ bit 0/1/2/3/4 remapping 84 | DATA 4 DDR_PHY_DX0DQMAP1_0 0x00004053 // DQ bit 5/6/7 and DM remapping 85 | DATA 4 DDR_PHY_DX1DQMAP0_0 0x00073826 // DQ bit 0/1/2/3/4 remapping 86 | DATA 4 DDR_PHY_DX1DQMAP1_0 0x00004150 // DQ bit 5/6/7 and DM remapping 87 | DATA 4 DDR_PHY_DX2DQMAP0_0 0x00053608 // DQ bit 0/1/2/3/4 remapping 88 | DATA 4 DDR_PHY_DX2DQMAP1_0 0x00004271 // DQ bit 5/6/7 and DM remapping 89 | DATA 4 DDR_PHY_DX3DQMAP0_0 0x00053826 // DQ bit 0/1/2/3/4 remapping 90 | DATA 4 DDR_PHY_DX3DQMAP1_0 0x00004170 // DQ bit 5/6/7 and DM remapping 91 | DATA 4 DDR_PHY_DX4DQMAP0_0 0x00005281 // DQ bit 0/1/2/3/4 remapping 92 | DATA 4 DDR_PHY_DX4DQMAP1_0 0x00004736 // DQ bit 5/6/7 and DM remapping 93 | // Set-up PHY General Configuration Register 94 | // PGCR1,4,5,6,7 are untouched 95 | SET_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=1 (no uMCTL2 commands can go to memory) 96 | DATA 4 DDR_PHY_PGCR0_0 0x07001E00 // Set ADCP=1 (Address Copy) 97 | DATA 4 DDR_PHY_PGCR2_0 0x00F0E207 // Set tREFPRD 98 | DATA 4 DDR_PHY_PGCR3_0 0x050A1080 // CKEN/CKNEN toggling and polarity 99 | // Set-up PHY Timing Register 100 | // PTR2 is untouched 101 | DATA 4 DDR_PHY_PTR0_0 0x3A61D310 // tPLLPD, tPLLGS, tPHYRST 102 | DATA 4 DDR_PHY_PTR1_0 0x2D98106A // tPLLLOCK, tPLLRST 103 | // Set-up PLL Control Register 104 | DATA 4 DDR_PHY_PLLCR0_0 0x011C0000 105 | DATA 4 DDR_PHY_DX8SLbPLLCR0_0 0x011C0000 106 | // Set-up Impedance Control Register 107 | DATA 4 DDR_PHY_ZQCR_0 0x008A2858 // Set ODT_MODE=0b10(DDR3 stype pullup) 108 | // ZPROG_DRAM_ODT and ZPROG_HOST_ODT 109 | DATA 4 DDR_PHY_ZQ0PR0_0 0x77BB // Optimal setting based on factory testing 110 | DATA 4 DDR_PHY_ZQ1PR0_0 0x77BB // Optimal setting based on factory testing 111 | // Set-up PHY Initialization Register 112 | DATA 4 DDR_PHY_PIR_0 0x72 113 | // Launch initialization (set bit 0) 114 | DATA 4 DDR_PHY_PIR_0 0x73 115 | 116 | 117 | //------------------------------------------- 118 | // Configure registers for DRAM initialization 119 | //------------------------------------------- 120 | // Set-up Mode Register 121 | // MR0, MR3, MR4, MR5 MR6 are untouched 122 | DATA 4 DDR_PHY_MR0_0 0x00000014 123 | DATA 4 DDR_PHY_MR1_0 0x00000006 124 | DATA 4 DDR_PHY_MR2_0 0x00000020 125 | DATA 4 DDR_PHY_MR3_0 0x00000000 126 | 127 | // Set-up DRAM Timing Parameters Register 128 | // DTPR6 is untouched 129 | DATA 4 DDR_PHY_DTPR0_0 0x061F0D08 // tRRD, tRAS, tRP, tRTP 130 | DATA 4 DDR_PHY_DTPR1_0 0x28210300 // tWLMRD, tFAW, tODTUP, tMRD 131 | DATA 4 DDR_PHY_DTPR2_0 0x01060200 // tRTW, tRTODT, tCMDCKE, tCKE, tVRCG, tXS 132 | DATA 4 DDR_PHY_DTPR3_0 0x02000000 // tODX, tCCD, tDLLK, tDQSCKmax, tDQSCK (FIXME double check tDLLK) 133 | DATA 4 DDR_PHY_DTPR4_0 0x00F30C17 // tRFC, tWLO, tXP 134 | DATA 4 DDR_PHY_DTPR5_0 0x002C0D09 // tRC, tRCD, tWTR 135 | // Set-up PHY Timing Register 136 | DATA 4 DDR_PHY_PTR3_0 0x00071FA6 // tDINIT0 137 | DATA 4 DDR_PHY_PTR4_0 0x000000F3 // tDINIT1 138 | DATA 4 DDR_PHY_PTR5_0 0x0002D976 // tDINIT2 139 | DATA 4 DDR_PHY_PTR6_0 0x040003A7 // tDINIT4, tDINIT3 140 | 141 | 142 | // Set-up ODT Configuration Register 143 | // DDR ODT_CA signal is tied at boundary of DDR. Thus no need to drive it dynamically. 144 | DATA 4 DDR_PHY_RANKIDR_0 0x00000000 // Select rank 0 to write 145 | DATA 4 DDR_PHY_ODTCR_0 0x00010000 // ODT of rank1 disabled 146 | 147 | 148 | // Set-up AC I/O Configuration Register 149 | // ACIOCR1-4 are untouched 150 | DATA 4 DDR_PHY_ACIOCR0_0 0x30070400 // PNUM2 (i.e.DDR3) selection [10:11] = 0x2 151 | DATA 4 DDR_PHY_ACIOCR5_0 0x00000000 // I/O mode = DDR3 152 | DATA 4 DDR_PHY_IOVCR0_0 0x03000000 153 | // Set-up DATX8 General Configuration Registers 154 | // DXnGCR0-4 are untouched 155 | DATA 4 DDR_PHY_PGCR5_0 0x01010004 156 | // Set-up DATX8 General Configuration Registers 157 | DATA 4 DDR_PHY_DX0GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 158 | DATA 4 DDR_PHY_DX1GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 159 | DATA 4 DDR_PHY_DX2GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 160 | DATA 4 DDR_PHY_DX3GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 161 | DATA 4 DDR_PHY_DX4GCR5_0 0x09090930 // Set DXREFISELR0 and DXREFISELR1 to 0x30, maintain other defaults 162 | DATA 4 DDR_PHY_DX0GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 163 | DATA 4 DDR_PHY_DX1GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 164 | DATA 4 DDR_PHY_DX2GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 165 | DATA 4 DDR_PHY_DX3GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 166 | DATA 4 DDR_PHY_DX4GCR4_0 0x020BBF04 // Set DXREFSSEL,DXREFSSELRANGE,DXREFSEN,DXREFIEN, maintain other defaults 167 | // Set-up DATX8 DX Control Register 2 168 | // PREOEX=2.5tCK (0.5 more than MR1), POSOEX=1tCK (0.5 more than in MR3), LPWAKEUP_THRSH=0xA 169 | DATA 4 DDR_PHY_DX8SLbDXCTL2_0 0x001C1400 170 | // Set-up DATX8 IO Control Register 171 | DATA 4 DDR_PHY_DX8SLbIOCR_0 0x00000000 // I/O mode = DDR3 172 | 173 | #if DDR_TRAIN_IN_DCD 174 | // Wait PHY initialization end then launch DRAM initialization 175 | // Wait for bit 0 of PGSR0 to be '1' 176 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 177 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 // Check that no error occured 178 | 179 | // Launch DRAM 0 initialization (set bit 0) 180 | DATA 4 DDR_PHY_PIR_0 0x180 181 | DATA 4 DDR_PHY_PIR_0 0x181 182 | 183 | // DRAM 0 initialization end 184 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 185 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 186 | 187 | //---------------------------------------------------------------// 188 | // DATA training 189 | //---------------------------------------------------------------// 190 | // Set-up Data Training Configuration Register 191 | // Note that DTCR0.RFSHDT are set to 0x0 as a workaround for PHY bug (Synopsys 192 | // case 9001045655: Design limitation in DDR3 mode: REFRESH must be disabled during DQS2DQ training). 193 | // (FYI avoiding refresh during training leads to Denali error (CUMULATIVE_REFRESH_POSTPONE_EXCEEDS_MAX_ALLOWED). 194 | DATA 4 DDR_PHY_DTCR0_0 0x800031CF // Set DTRPTN to 0x7. RFSHDT=0 195 | DATA 4 DDR_PHY_DTCR1_0 0x00010237 // Set RANKEN=3 196 | 197 | // CLR_BIT 4 DDR_PHY_DX4GCR1_0 0xFF // disable byte 4 (this line is commented out when ECC is enabled) 198 | 199 | // Launch Write leveling 200 | DATA 4 DDR_PHY_PIR_0 0x200 201 | DATA 4 DDR_PHY_PIR_0 0x201 202 | // Wait Write leveling to complete 203 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 204 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00200000 205 | 206 | // Set DQS/DQSn glitch suppression resistor for training PHY0 207 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x012640F7 208 | // Launch Read DQS training 209 | DATA 4 DDR_PHY_PIR_0 0x400 210 | DATA 4 DDR_PHY_PIR_0 0x401 211 | // Wait Read DQS training to complete PHY0 212 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 213 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x00400000 214 | // Remove DQS/DQSn glitch suppression resistor PHY0 215 | DATA 4 DDR_PHY_DX8SLbDQSCTL_0 0x01264000 216 | 217 | // DQS2DQ training, Write leveling, Deskew and eye trainings 218 | DATA 4 DDR_PHY_PIR_0 0x0000F800 219 | DATA 4 DDR_PHY_PIR_0 0x0000F801 220 | // Wait for training to complete 221 | CHECK_BITS_SET 4 DDR_PHY_PGSR0_0 0x1 222 | CHECK_BITS_CLR 4 DDR_PHY_PGSR0_0 0x7FF40000 223 | 224 | //Re-allow uMCTL2 to send commands to DDR 225 | CLR_BIT 4 DDR_PHY_PGCR1_0 0x00020000 // DISDIC=0, PUBMODE=0 226 | 227 | //Check that controller is ready to operate 228 | CHECK_BITS_SET 4 DDRC_STAT_0 0x1 229 | 230 | #endif 231 | 232 | // ECC Support (the following lines are uncommented when ECC is enabled) 233 | DATA 4 DDRC_PCTRL_0_0 0x00000000 // Disable Port 0 234 | DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_mode = 1 235 | DATA 4 DDRC_SBRWDATA0_0 0x55AA55AA // SBRWDATA0 = 55AA55AA 236 | DATA 4 DDRC_SBRCTL_0 0x00000015 // Scrub_en = 1 237 | CHECK_BITS_SET 4 DDRC_SBRSTAT_0 0x2 // Wait for Scrub done 238 | CHECK_BITS_CLR 4 DDRC_SBRSTAT_0 0x1 // Wait for Scrub done 239 | DATA 4 DDRC_SBRCTL_0 0x00000014 // Scrub_en = 0 240 | DATA 4 DDRC_SBRCTL_0 0x00000110 // Scrub_interval = 1 241 | DATA 4 DDRC_SBRCTL_0 0x00000111 // Scrub_en = 1 242 | DATA 4 DDRC_PCTRL_0_0 0x00000001 // Enable Port 0 243 | 244 | -------------------------------------------------------------------------------- /iMX8QX/soc.mak: -------------------------------------------------------------------------------- 1 | MKIMG = ../mkimage_imx8 2 | DCD_CFG_SRC = imx8qx_dcd_1.2GHz.cfg 3 | DCD_CFG = imx8qx_dcd.cfg.tmp 4 | 5 | DCD_CFG_16BIT_SRC = imx8qx_dcd_16bit_1.2GHz.cfg 6 | DCD_16BIT_CFG = imx8qx_16bit_dcd.cfg.tmp 7 | 8 | DCD_CFG_DDR3_SRC = imx8qx_ddr3_dcd_1066MHz_ecc.cfg 9 | DCD_DDR3_CFG = imx8qx_ddr3_dcd_1066MHz_ecc.cfg.tmp 10 | 11 | CC ?= gcc 12 | CFLAGS ?= -O2 -Wall -std=c99 -static 13 | INCLUDE = ./lib 14 | 15 | #set default DDR_training to be in DCDs 16 | 17 | DDR3_DCD ?= 0 18 | DDR_TRAIN ?= 1 19 | WGET = /usr/bin/wget 20 | N ?= latest 21 | SERVER=http://yb2.am.freescale.net 22 | DIR = build-output/Linux_IMX_MX8/$(N)/common_bsp 23 | 24 | ifeq ($(DDR3_DCD), 1) 25 | DCD_CFG_SRC = imx8qx_ddr3_dcd_1066MHz_ecc.cfg 26 | endif 27 | 28 | ifneq ($(wildcard /usr/bin/rename.ul),) 29 | RENAME = rename.ul 30 | else 31 | RENAME = rename 32 | endif 33 | 34 | $(DCD_CFG): FORCE 35 | @echo "Converting iMX8 DCD file" 36 | $(CC) -E -Wp,-MD,.imx8qx_dcd.cfg.cfgtmp.d -nostdinc -Iinclude -I$(INCLUDE) -DDDR_TRAIN_IN_DCD=$(DDR_TRAIN) -x c -o $(DCD_CFG) $(DCD_CFG_SRC) 37 | $(CC) -E -Wp,-MD,.imx8qx_dcd.cfg.cfgtmp.d -nostdinc -Iinclude -I$(INCLUDE) -DDDR_TRAIN_IN_DCD=$(DDR_TRAIN) -x c -o $(DCD_16BIT_CFG) $(DCD_CFG_16BIT_SRC) 38 | $(CC) -E -Wp,-MD,.imx8qx_dcd.cfg.cfgtmp.d -nostdinc -Iinclude -I$(INCLUDE) -DDDR_TRAIN_IN_DCD=$(DDR_TRAIN) -x c -o $(DCD_DDR3_CFG) $(DCD_CFG_DDR3_SRC) 39 | FORCE: 40 | 41 | u-boot-atf.bin: u-boot.bin bl31.bin 42 | @cp bl31.bin u-boot-atf.bin 43 | ./$(MKIMG) -commit > head.hash 44 | @cat u-boot.bin head.hash > u-boot-hash.bin 45 | @dd if=u-boot-hash.bin of=u-boot-atf.bin bs=1K seek=128 46 | 47 | .PHONY: clean nightly 48 | clean: 49 | @rm -f $(MKIMG) $(DCD_CFG) .imx8qx_dcd.cfg.cfgtmp.d 50 | 51 | flash_scfw: $(MKIMG) scfw_tcm.bin 52 | ./$(MKIMG) -soc QX -c -scfw scfw_tcm.bin -out flash.bin 53 | 54 | flash_dcd: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 55 | ./$(MKIMG) -soc QX -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a35 0x80000000 -out flash.bin 56 | 57 | flash_16bit_dcd: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 58 | ./$(MKIMG) -soc QX -c -dcd $(DCD_16BIT_CFG) -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a35 0x80000000 -out flash.bin 59 | 60 | flash_ddr3_dcd: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 61 | ./$(MKIMG) -soc QX -c -dcd $(DCD_DDR3_CFG) -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a35 0x80000000 -out flash.bin 62 | 63 | flash: $(MKIMG) scfw_tcm.bin u-boot-atf.bin 64 | ./$(MKIMG) -soc QX -c -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a35 0x80000000 -out flash.bin 65 | 66 | flash_early: $(MKIMG) scfw_tcm.bin u-boot-atf.bin 67 | ./$(MKIMG) -soc QX -c -flags 0x00400000 -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a35 0x80000000 -out flash.bin 68 | 69 | flash_flexspi: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 70 | ./$(MKIMG) -soc QX -dev flexspi -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a35 0x80000000 -out flash.bin 71 | 72 | flash_multi_cores: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m40_tcm.bin u-boot-atf.bin 73 | ./$(MKIMG) -soc QX -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m40_tcm.bin 0 0x34FE0000 -c -ap u-boot-atf.bin a35 0x80000000 -out flash.bin 74 | 75 | flash_nand: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin 76 | ./$(MKIMG) -soc QX -dev nand -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -c -ap u-boot-atf.bin a35 0x80000000 -out flash.bin 77 | 78 | flash_cm4_0: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m4_image.bin 79 | ./$(MKIMG) -soc QX -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m4_image.bin 0 0x34FE0000 -out flash.bin 80 | 81 | flash_all: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m4_image.bin u-boot-atf.bin scd.bin csf.bin csf_ap.bin 82 | ./$(MKIMG) -soc QX -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m4_image.bin 0 0x34FE0000 -scd scd.bin -csf csf.bin -c -ap u-boot-atf.bin a35 0x80000000 -csf csf_ap.bin -out flash.bin 83 | 84 | flash_ca35_ddrstress: $(MKIMG) scfw_tcm.bin mx8qx_ddr_stress_test.bin 85 | ./$(MKIMG) -soc QX -c -flags 0x00800000 -scfw scfw_tcm.bin -c -ap mx8qx_ddr_stress_test.bin a35 0x00112000 -out flash.bin 86 | 87 | flash_ca35_ddrstress_dcd: $(MKIMG) $(DCD_CFG) scfw_tcm.bin mx8qx_ddr_stress_test.bin 88 | ./$(MKIMG) -soc QX -c -flags 0x00800000 -dcd $(DCD_CFG) -scfw scfw_tcm.bin -c -ap mx8qx_ddr_stress_test.bin a35 0x00112000 -out flash.bin 89 | 90 | flash_cm4ddr: $(MKIMG) $(DCD_CFG) scfw_tcm.bin m4_image.bin 91 | ./$(MKIMG) -soc QX -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -m4 m4_image.bin 0 0x88000000 -out flash.bin 92 | 93 | flash_fastboot: $(MKIMG) $(DCD_CFG) scfw_tcm.bin u-boot-atf.bin m4_image.bin 94 | ./$(MKIMG) -soc QX -dev emmc_fast -c -dcd $(DCD_CFG) -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -out flash.bin 95 | 96 | nightly : 97 | @rm -rf boot 98 | @$(WGET) -q $(SERVER)/$(DIR)/imx-boot/imx-boot-tools/imx8qx/mx8qx-scfw-tcm.bin -O scfw_tcm.bin 99 | @$(WGET) -q $(SERVER)/$(DIR)/imx-boot/imx-boot-tools/imx8qx/bl31-imx8qxp.bin -O bl31.bin 100 | @$(WGET) -q $(SERVER)/$(DIR)/imx-boot/imx-boot-tools/imx8qx/u-boot-imx8qxplpddr4arm2.bin-sd -O u-boot.bin 101 | @$(WGET) -qr -nd -l1 -np $(SERVER)/$(DIR) -P boot -A "Image-fsl-imx8qxp-*.dtb" 102 | @$(WGET) -q $(SERVER)/$(DIR)/Image-imx8_all.bin -O Image 103 | @mv -f Image boot 104 | @$(RENAME) "Image-" "" boot/*.dtb 105 | -------------------------------------------------------------------------------- /iMX8dv/COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /iMX8dv/imx8dv_dcd.cfg: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Freescale Semiconductor, Inc. 3 | * 4 | * SPDX-License-Identifier: GPL-2.0+ 5 | * 6 | * Refer doc/README.imximage for more details about how-to configure 7 | * and create imximage boot image 8 | * 9 | * The syntax is taken as close as possible with the kwbimage 10 | */ 11 | /* image version */ 12 | 13 | #define __ASSEMBLY__ 14 | 15 | IMAGE_VERSION 2 16 | 17 | /* 18 | * Boot Device : 19 | * sd/mmc: flash_offset: 0x4000 20 | */ 21 | BOOT_OFFSET 0x4000 22 | 23 | /* 24 | * Device Configuration Data (DCD) 25 | * 26 | * Each entry must have the format: 27 | * Addr-type Address Value 28 | * 29 | * where: 30 | * Addr-type register length (1,2 or 4 bytes) 31 | * Address absolute address of the register 32 | * value value to be stored in the register 33 | */ 34 | 35 | DATA 4 0x41B60500 0x07C03E00 36 | DATA 4 0x41B80500 0x07C03E00 37 | DATA 4 0x41E20500 0x07C03E00 38 | DATA 4 0x41E40500 0x07C03E00 39 | 40 | DATA 4 0x5C000000 0x03040008 41 | DATA 4 0x5C0001A0 0x80400003 42 | DATA 4 0x5C0001A4 0x00010002 43 | DATA 4 0x5C0001A8 0x80100020 44 | 45 | DATA 4 0x5C000050 0x00210000 46 | DATA 4 0x5C000064 0x00300054 47 | 48 | DATA 4 0x5C0000D0 0x00010001 49 | DATA 4 0x5C0000DC 0x0043001A 50 | DATA 4 0x5C0000E0 0x00020000 51 | DATA 4 0x5C0000E4 0x00190008 52 | DATA 4 0x5C0000F4 0x0000033F 53 | DATA 4 0x5C000100 0x0C141A11 54 | /* Update tRC */ 55 | DATA 4 0x5C000104 0x0003031A 56 | /* Update WR2RD */ 57 | DATA 4 0x5C000108 0x03060809 58 | DATA 4 0x5C00010C 0x0100600C 59 | /* Update Update tCCD and tRP */ 60 | DATA 4 0x5C000110 0x0802040A 61 | DATA 4 0x5C000114 0x02020606 62 | DATA 4 0x5C000118 0x02020004 63 | DATA 4 0x5C00011C 0x00000202 64 | DATA 4 0x5C000120 0x00000008 65 | DATA 4 0x5C000138 0x00000058 66 | DATA 4 0x5C000180 0x20900024 67 | DATA 4 0x5C000184 0x01400100 68 | DATA 4 0x5C000190 0x020A8205 69 | DATA 4 0x5C000194 0x00030303 70 | DATA 4 0x5C000200 0x00000016 71 | DATA 4 0x5C000204 0x00080808 72 | DATA 4 0x5C000214 0x07070707 73 | DATA 4 0x5C000218 0x0F070707 74 | DATA 4 0x5C000240 0x06000601 75 | DATA 4 0x5C000244 0x00001323 76 | DATA 4 0x5C000250 0x00001F05 77 | DATA 4 0x5C000254 0x00000080 78 | DATA 4 0x5C000274 0x00000010 79 | DATA 4 0x5C000490 0x00000001 80 | DATA 4 0x5C000494 0x01120E07 81 | DATA 4 0x5C000498 0x00000070 82 | DATA 4 0x5C000540 0x00000001 83 | DATA 4 0x5C000544 0x01120E07 84 | DATA 4 0x5C000548 0x00000070 85 | DATA 4 0x5C0005F0 0x00000001 86 | DATA 4 0x5C0005F4 0x01120E07 87 | DATA 4 0x5C0005F8 0x00000070 88 | DATA 4 0x5C0006A0 0x00000001 89 | DATA 4 0x5C0006A4 0x01120E07 90 | DATA 4 0x5C0006A8 0x00000020 91 | DATA 4 0x5C020000 0x03040008 92 | DATA 4 0x5C0201A0 0x80400003 93 | DATA 4 0x5C0201A4 0x00010002 94 | DATA 4 0x5C0201A8 0x80100020 95 | 96 | DATA 4 0x5C020050 0x00210000 97 | DATA 4 0x5C020064 0x00300054 98 | 99 | DATA 4 0x5C0200D0 0x00010001 100 | DATA 4 0x5C0200DC 0x0043001A 101 | DATA 4 0x5C0200E0 0x00020000 102 | DATA 4 0x5C0200E4 0x00190008 103 | DATA 4 0x5C0200F4 0x0000033F 104 | DATA 4 0x5C020100 0x0C141A11 105 | /* Update tRC */ 106 | DATA 4 0x5C020104 0x0003031A 107 | /* Update WR2RD */ 108 | DATA 4 0x5C020108 0x03060809 109 | DATA 4 0x5C02010C 0x0100600C 110 | /* Update Update tCCD and tRP */ 111 | DATA 4 0x5C020110 0x0802040A 112 | DATA 4 0x5C020114 0x02020606 113 | DATA 4 0x5C020118 0x02020004 114 | DATA 4 0x5C02011C 0x00000202 115 | DATA 4 0x5C020120 0x00000008 116 | DATA 4 0x5C020138 0x00000058 117 | DATA 4 0x5C020180 0x20900024 118 | DATA 4 0x5C020184 0x01400100 119 | DATA 4 0x5C020190 0x020A8205 120 | DATA 4 0x5C020194 0x00030303 121 | DATA 4 0x5C020200 0x00000016 122 | DATA 4 0x5C020204 0x00080808 123 | DATA 4 0x5C020214 0x07070707 124 | DATA 4 0x5C020218 0x0F070707 125 | DATA 4 0x5C020240 0x06000601 126 | DATA 4 0x5C020244 0x00001323 127 | DATA 4 0x5C020250 0x00001F05 128 | DATA 4 0x5C020254 0x00000080 129 | DATA 4 0x5C020274 0x00000010 130 | DATA 4 0x5C020490 0x00000001 131 | DATA 4 0x5C020494 0x01120E07 132 | DATA 4 0x5C020498 0x00000070 133 | DATA 4 0x5C020540 0x00000001 134 | DATA 4 0x5C020544 0x01120E07 135 | DATA 4 0x5C020548 0x00000070 136 | DATA 4 0x5C0205F0 0x00000001 137 | DATA 4 0x5C0205F4 0x01120E07 138 | DATA 4 0x5C0205F8 0x00000070 139 | DATA 4 0x5C0206A0 0x00000001 140 | DATA 4 0x5C0206A4 0x01120E07 141 | DATA 4 0x5C0206A8 0x00000020 142 | DATA 4 0x41B60040 0xFFFFFFFF 143 | DATA 4 0x41B80040 0xFFFFFFFF 144 | DATA 4 0x5C010000 0x17421E40 145 | DATA 4 0x5C010004 0x20210100 146 | DATA 4 0x5C010008 0x00010004 147 | DATA 4 0x5C010010 0x0007080C 148 | DATA 4 0x5C01009C 0x0DB60DB6 149 | DATA 4 0x5C0100C0 0x0C487304 150 | DATA 4 0x5C0100C0 0x0C4C7304 151 | DATA 4 0x5C0100C0 0x0C4C7306 152 | 153 | CHECK_BITS_SET 4 0x5c0100c4 1 154 | 155 | DATA 4 0x5C0100C0 0x0C487304 156 | 157 | DATA 4 0x5C0100B0 0x1010007E 158 | DATA 4 0x5C01001C 0x00010000 159 | 160 | DATA 4 0x5C010020 0x00000000 161 | DATA 4 0x5C010030 0x08080808 162 | 163 | DATA 4 0x5C010050 0x01000008 164 | DATA 4 0x5C010050 0x00000008 165 | DATA 4 0x5C010018 0x0000000F 166 | DATA 4 0x5C030000 0x17421E40 167 | DATA 4 0x5C030004 0x20210100 168 | DATA 4 0x5C030008 0x00010004 169 | DATA 4 0x5C030010 0x0007080C 170 | DATA 4 0x5C03009C 0x0DB60DB6 171 | DATA 4 0x5C0300C0 0x0C487304 172 | DATA 4 0x5C0300C0 0x0C4C7304 173 | DATA 4 0x5C0300C0 0x0C4C7306 174 | 175 | CHECK_BITS_SET 4 0x5c0300c4 1 176 | 177 | DATA 4 0x5C0300C0 0x0C487304 178 | 179 | DATA 4 0x5C0300B0 0x1010007E 180 | DATA 4 0x5C03001C 0x00010000 181 | 182 | DATA 4 0x5C030020 0x00000000 183 | DATA 4 0x5C030030 0x08080808 184 | 185 | DATA 4 0x5C030050 0x01000008 186 | DATA 4 0x5C030050 0x00000008 187 | DATA 4 0x5C030018 0x0000000F 188 | DATA 4 0x5C060000 0x03040008 189 | DATA 4 0x5C0601A0 0x80400003 190 | DATA 4 0x5C0601A4 0x00010002 191 | DATA 4 0x5C0601A8 0x80100020 192 | 193 | DATA 4 0x5C060050 0x00210000 194 | DATA 4 0x5C060064 0x00300054 195 | 196 | DATA 4 0x5C0600D0 0x00010001 197 | DATA 4 0x5C0600DC 0x0043001A 198 | DATA 4 0x5C0600E0 0x00020000 199 | DATA 4 0x5C0600E4 0x00190008 200 | DATA 4 0x5C0600F4 0x0000033F 201 | DATA 4 0x5C060100 0x0C141A11 202 | /* Update tRC */ 203 | DATA 4 0x5C060104 0x0003031A 204 | /* Update WR2RD */ 205 | DATA 4 0x5C060108 0x03060809 206 | DATA 4 0x5C06010C 0x0100600C 207 | /* Update Update tCCD and tRP */ 208 | DATA 4 0x5C060110 0x0802040A 209 | DATA 4 0x5C060114 0x02020606 210 | DATA 4 0x5C060118 0x02020004 211 | DATA 4 0x5C06011C 0x00000202 212 | DATA 4 0x5C060120 0x00000008 213 | DATA 4 0x5C060138 0x00000058 214 | DATA 4 0x5C060180 0x20900024 215 | DATA 4 0x5C060184 0x01400100 216 | DATA 4 0x5C060190 0x020A8205 217 | DATA 4 0x5C060194 0x00030303 218 | DATA 4 0x5C060200 0x00000016 219 | DATA 4 0x5C060204 0x00080808 220 | DATA 4 0x5C060214 0x07070707 221 | DATA 4 0x5C060218 0x0F070707 222 | DATA 4 0x5C060240 0x06000601 223 | DATA 4 0x5C060244 0x00001323 224 | DATA 4 0x5C060250 0x00001F05 225 | DATA 4 0x5C060254 0x00000080 226 | DATA 4 0x5C060274 0x00000010 227 | DATA 4 0x5C060490 0x00000001 228 | DATA 4 0x5C060494 0x01120E07 229 | DATA 4 0x5C060498 0x00000070 230 | DATA 4 0x5C060540 0x00000001 231 | DATA 4 0x5C060544 0x01120E07 232 | DATA 4 0x5C060548 0x00000070 233 | DATA 4 0x5C0605F0 0x00000001 234 | DATA 4 0x5C0605F4 0x01120E07 235 | DATA 4 0x5C0605F8 0x00000070 236 | DATA 4 0x5C0606A0 0x00000001 237 | DATA 4 0x5C0606A4 0x01120E07 238 | DATA 4 0x5C0606A8 0x00000020 239 | DATA 4 0x5C080000 0x03040008 240 | DATA 4 0x5C0801A0 0x80400003 241 | DATA 4 0x5C0801A4 0x00010002 242 | DATA 4 0x5C0801A8 0x80100020 243 | 244 | DATA 4 0x5C080050 0x00210000 245 | DATA 4 0x5C080064 0x00300054 246 | 247 | DATA 4 0x5C0800D0 0x00010001 248 | DATA 4 0x5C0800DC 0x0043001A 249 | DATA 4 0x5C0800E0 0x00020000 250 | DATA 4 0x5C0800E4 0x00190008 251 | DATA 4 0x5C0800F4 0x0000033F 252 | DATA 4 0x5C080100 0x0C141A11 253 | /* Update tRC */ 254 | DATA 4 0x5C080104 0x0003031A 255 | /* Update WR2RD */ 256 | DATA 4 0x5C080108 0x03060809 257 | DATA 4 0x5C08010C 0x0100600C 258 | /* Update Update tCCD and tRP */ 259 | DATA 4 0x5C080110 0x0802040A 260 | DATA 4 0x5C080114 0x02020606 261 | DATA 4 0x5C080118 0x02020004 262 | DATA 4 0x5C08011C 0x00000202 263 | DATA 4 0x5C080120 0x00000008 264 | DATA 4 0x5C080138 0x00000058 265 | DATA 4 0x5C080180 0x20900024 266 | DATA 4 0x5C080184 0x01400100 267 | DATA 4 0x5C080190 0x020A8205 268 | DATA 4 0x5C080194 0x00030303 269 | DATA 4 0x5C080200 0x00000016 270 | DATA 4 0x5C080204 0x00080808 271 | DATA 4 0x5C080214 0x07070707 272 | DATA 4 0x5C080218 0x0F070707 273 | DATA 4 0x5C080240 0x06000601 274 | DATA 4 0x5C080244 0x00001323 275 | DATA 4 0x5C080250 0x00001F05 276 | DATA 4 0x5C080254 0x00000080 277 | DATA 4 0x5C080274 0x00000010 278 | DATA 4 0x5C080490 0x00000001 279 | DATA 4 0x5C080494 0x01120E07 280 | DATA 4 0x5C080498 0x00000070 281 | DATA 4 0x5C080540 0x00000001 282 | DATA 4 0x5C080544 0x01120E07 283 | DATA 4 0x5C080548 0x00000070 284 | DATA 4 0x5C0805F0 0x00000001 285 | DATA 4 0x5C0805F4 0x01120E07 286 | DATA 4 0x5C0805F8 0x00000070 287 | DATA 4 0x5C0806A0 0x00000001 288 | DATA 4 0x5C0806A4 0x01120E07 289 | DATA 4 0x5C0806A8 0x00000020 290 | DATA 4 0x41E40040 0xFFFFFFFF 291 | DATA 4 0x41E20040 0xFFFFFFFF 292 | DATA 4 0x5C070000 0x17421E40 293 | DATA 4 0x5C070004 0x20210100 294 | DATA 4 0x5C070008 0x00010004 295 | DATA 4 0x5C070010 0x0007080C 296 | DATA 4 0x5C07009C 0x0DB60DB6 297 | DATA 4 0x5C0700C0 0x0C487304 298 | DATA 4 0x5C0700C0 0x0C4C7304 299 | DATA 4 0x5C0700C0 0x0C4C7306 300 | 301 | CHECK_BITS_SET 4 0x5c0700c4 1 302 | 303 | DATA 4 0x5C0700C0 0x0C487304 304 | 305 | DATA 4 0x5C0700B0 0x1010007E 306 | DATA 4 0x5C07001C 0x00010000 307 | 308 | DATA 4 0x5C070020 0x00000000 309 | DATA 4 0x5C070030 0x08080808 310 | 311 | DATA 4 0x5C070050 0x01000008 312 | DATA 4 0x5C070050 0x00000008 313 | DATA 4 0x5C070018 0x0000000F 314 | DATA 4 0x5C090000 0x17421E40 315 | DATA 4 0x5C090004 0x20210100 316 | DATA 4 0x5C090008 0x00010004 317 | DATA 4 0x5C090010 0x0007080C 318 | DATA 4 0x5C09009C 0x0DB60DB6 319 | DATA 4 0x5C0900C0 0x0C487304 320 | DATA 4 0x5C0900C0 0x0C4C7304 321 | DATA 4 0x5C0900C0 0x0C4C7306 322 | 323 | CHECK_BITS_SET 4 0x5c0900c4 1 324 | 325 | DATA 4 0x5C0900C0 0x0C487304 326 | 327 | DATA 4 0x5C0900B0 0x1010007E 328 | DATA 4 0x5C09001C 0x00010000 329 | 330 | DATA 4 0x5C090020 0x00000000 331 | DATA 4 0x5C090030 0x08080808 332 | 333 | DATA 4 0x5C090050 0x01000008 334 | DATA 4 0x5C090050 0x00000008 335 | DATA 4 0x5C090018 0x0000000F 336 | 337 | DATA 4 0x41B60504 0x01000100 338 | CHECK_BITS_SET 4 0x5c000004 1 339 | DATA 4 0x41E40504 0x01000100 340 | CHECK_BITS_SET 4 0x5c060004 1 341 | DATA 4 0x41B80504 0x01000100 342 | CHECK_BITS_SET 4 0x5c020004 1 343 | DATA 4 0x41E20504 0x01000100 344 | CHECK_BITS_SET 4 0x5c080004 1 345 | 346 | DATA 4 0x33BA0510 0x00000000 347 | -------------------------------------------------------------------------------- /iMX8dv/soc.mak: -------------------------------------------------------------------------------- 1 | MKIMG = mkimage_imx8 2 | 3 | CC ?= gcc 4 | CFLAGS ?= -O2 -Wall -std=c99 -static 5 | 6 | $(MKIMG): mkimage_imx8.c imx8dv_dcd.cfg 7 | $(CC) -E -Wp,-MD,.imx8dv_dcd.cfg.cfgtmp.d -nostdinc -Iinclude -x c -o imx8dv_dcd.cfg.tmp imx8dv_dcd.cfg 8 | $(CC) $(CFLAGS) -o $@ mkimage_imx8.c 9 | 10 | .PHONY: clean 11 | 12 | clean: 13 | @rm -f mkimage_imx8 imx8dv_dcd.cfg.tmp .imx8dv_dcd.cfg.cfgtmp.d 14 | 15 | flash: $(MKIMG) 16 | ./mkimage_imx8 -dcd imx8dv_dcd.cfg.tmp -scfw scfw_tcm.bin -ap u-boot.bin a53 0x80000000 -out flash.bin 17 | 18 | flash_ca72: $(MKIMG) 19 | ./mkimage_imx8 -dcd imx8dv_dcd.cfg.tmp -scfw scfw_tcm.bin -ap u-boot.bin a72 0x80000000 -out flash.bin 20 | 21 | flash_cm4_0: $(MKIMG) 22 | ./mkimage_imx8 -dcd imx8dv_dcd.cfg.tmp -scfw scfw_tcm.bin -m4 m4_image.bin 0 0x34FE0000 -out flash.bin 23 | 24 | flash_cm4_1: $(MKIMG) 25 | ./mkimage_imx8 -dcd imx8dv_dcd.cfg.tmp -scfw scfw_tcm.bin -m4 m4_image.bin 1 0x38FE0000 -out flash.bin 26 | -------------------------------------------------------------------------------- /src/imx8qm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 NXP 3 | * 4 | * SPDX-License-Identifier: GPL-2.0+ 5 | * derived from u-boot's mkimage utility 6 | * 7 | */ 8 | 9 | #include 10 | #include "mkimage_common.h" 11 | 12 | #define MAX_NUM_IMGS 4 13 | #define IVT_HEADER_TAG 0xD1 14 | 15 | typedef struct { 16 | uint64_t src; /*8*/ 17 | uint64_t dst; /*8*/ 18 | uint64_t entry; /*8*/ 19 | uint32_t size; /*4*/ 20 | uint32_t flags; /*4*/ 21 | } __attribute__((packed)) boot_img_t; /*32*/ 22 | 23 | typedef struct { 24 | uint32_t num_images; /*4*/ 25 | uint32_t bd_size; /*4*/ 26 | uint32_t bd_flags; /*4*/ 27 | uint32_t reserved; /*4*/ 28 | boot_img_t img[MAX_NUM_IMGS]; /*128*/ 29 | boot_img_t scd; /*32*/ 30 | boot_img_t csf; /*32*/ 31 | boot_img_t img_reserved; /* Reserved for future, 32 */ 32 | } __attribute__((packed)) boot_data_v3_t; /*240*/ 33 | 34 | typedef struct { 35 | ivt_header_t header; /*4*/ 36 | uint32_t reserved1; /*4*/ 37 | uint64_t dcd_ptr; /*8*/ 38 | uint64_t boot_data_ptr; /*8*/ 39 | uint64_t self; /*8*/ 40 | uint64_t csf; /*8*/ 41 | uint64_t scd; /*8*/ 42 | uint64_t reserved2; /*8*/ 43 | uint64_t reserved3; /*8*/ 44 | } __attribute__((packed)) flash_header_v3_t; /*64*/ 45 | 46 | #define MAX_NUM_OF_CONTAINER 2 47 | 48 | typedef struct { 49 | flash_header_v3_t fhdr[MAX_NUM_OF_CONTAINER]; /*64*/ 50 | boot_data_v3_t boot_data[MAX_NUM_OF_CONTAINER]; /*128*/ 51 | dcd_v2_t dcd_table; /*2880*/ 52 | } __attribute__((packed)) imx_header_v3_t; /*3072*/ 53 | 54 | 55 | static void set_imx_hdr_v3(imx_header_v3_t *imxhdr, uint32_t dcd_len, 56 | uint32_t flash_offset, uint32_t hdr_base, uint32_t cont_id) 57 | { 58 | flash_header_v3_t *fhdr_v3 = &imxhdr->fhdr[cont_id]; 59 | 60 | /* Set magic number */ 61 | fhdr_v3->header.tag = IVT_HEADER_TAG; /* 0xD1 */ 62 | fhdr_v3->header.length = cpu_to_be16(sizeof(flash_header_v3_t)); 63 | fhdr_v3->header.version = IVT_VERSION; /* 0x40 */ 64 | 65 | fhdr_v3->reserved1 = fhdr_v3->reserved2 = fhdr_v3->reserved3 = 0; 66 | 67 | fhdr_v3->self = hdr_base + flash_offset + cont_id * sizeof(flash_header_v3_t); 68 | if (dcd_len > 0) 69 | fhdr_v3->dcd_ptr = hdr_base + flash_offset + 70 | offsetof(imx_header_v3_t, dcd_table); 71 | else 72 | fhdr_v3->dcd_ptr = 0; 73 | fhdr_v3->boot_data_ptr = hdr_base + flash_offset 74 | + offsetof(imx_header_v3_t, boot_data) + cont_id * sizeof(boot_data_v3_t); 75 | 76 | fhdr_v3->csf = 0; 77 | fhdr_v3->scd = 0; 78 | } 79 | 80 | int build_container_qm(uint32_t sector_size, uint32_t ivt_offset, char* out_file, bool emmc_fastboot, image_t* image_stack) 81 | { 82 | int file_off, ofd; 83 | 84 | unsigned int dcd_len = 0; 85 | static imx_header_v3_t imx_header; 86 | struct stat sbuf; 87 | uint64_t tmp_to = 0; /*used for offset of memory to find images */ 88 | uint32_t custom_partition = 0;/* 0 denotes defaults */ 89 | 90 | 91 | image_t* img_sp = image_stack; 92 | int container = -1; 93 | int cont_img_count = 0; /* indexes to arrange the container */ 94 | 95 | 96 | memset((char*)&imx_header, 0, sizeof(imx_header_v3_t)); 97 | 98 | 99 | if(image_stack == NULL) { 100 | fprintf(stderr, "Empty image stack "); 101 | exit(EXIT_FAILURE); 102 | } 103 | 104 | fprintf(stdout, "Platform:\ti.MX8QM\n"); 105 | 106 | 107 | if(emmc_fastboot){/* start images after initial 8K */ 108 | file_off = 0x2000 - ivt_offset; 109 | } 110 | else 111 | { 112 | file_off = ALIGN(sizeof(imx_header_v3_t) + ivt_offset, sector_size); 113 | } 114 | 115 | 116 | 117 | do{ /* process DCD if it is found */ 118 | if (img_sp->option == DCD) { 119 | dcd_len = parse_cfg_file(&imx_header.dcd_table, img_sp->filename); 120 | fprintf(stdout, "dcd len = %d\n", dcd_len); 121 | } 122 | img_sp++; 123 | } 124 | while(img_sp->option!= NO_IMG); 125 | 126 | /* change load addr and setup DCD to be attached to first container */ 127 | if (ivt_offset == IVT_OFFSET_FLEXSPI) { 128 | set_imx_hdr_v3(&imx_header, dcd_len, ivt_offset, INITIAL_LOAD_ADDR_FLEXSPI, 0); 129 | set_imx_hdr_v3(&imx_header, 0, ivt_offset, INITIAL_LOAD_ADDR_FLEXSPI, 1); 130 | } else { 131 | set_imx_hdr_v3(&imx_header, dcd_len, ivt_offset, INITIAL_LOAD_ADDR_SCU_ROM, 0); 132 | set_imx_hdr_v3(&imx_header, 0, ivt_offset, INITIAL_LOAD_ADDR_AP_ROM, 1); 133 | } 134 | 135 | 136 | 137 | /* step through image stack and generate the header and img srcs */ 138 | img_sp = image_stack; 139 | while(img_sp->option != NO_IMG){ /* stop once we reach null terminator */ 140 | switch(img_sp->option){ 141 | case SCFW: 142 | check_file(&sbuf, img_sp->filename); 143 | fprintf(stdout, "scfw size = %" PRIi64 "\n", sbuf.st_size); 144 | imx_header.boot_data[container].img[cont_img_count].src = file_off; 145 | img_sp->src = file_off; 146 | imx_header.boot_data[container].img[cont_img_count].dst = 0x30fe0000; /* hard code scfw entry address */ 147 | imx_header.boot_data[container].img[cont_img_count].entry = 0x1ffe0000; 148 | imx_header.boot_data[container].img[cont_img_count].size = sbuf.st_size; 149 | imx_header.boot_data[container].img[cont_img_count].flags = 0; 150 | imx_header.boot_data[container].img[cont_img_count].flags = (CORE_SC & BOOT_IMG_FLAGS_CORE_MASK); 151 | imx_header.boot_data[container].num_images++; 152 | imx_header.boot_data[container].bd_size = sizeof(boot_data_v3_t); 153 | 154 | file_off += ALIGN(sbuf.st_size, sector_size); 155 | tmp_to = ALIGN((imx_header.boot_data[container].img[cont_img_count].dst + sbuf.st_size), IMG_AUTO_ALIGN); 156 | cont_img_count++; 157 | break; 158 | case M4: 159 | check_file(&sbuf, img_sp->filename); 160 | imx_header.boot_data[container].img[cont_img_count].src = file_off; 161 | img_sp->src = file_off; 162 | imx_header.boot_data[container].img[cont_img_count].dst = img_sp->entry; 163 | imx_header.boot_data[container].img[cont_img_count].entry = img_sp->entry; 164 | imx_header.boot_data[container].img[cont_img_count].size = sbuf.st_size; 165 | imx_header.boot_data[container].num_images++; 166 | 167 | if (img_sp->ext == 0) { 168 | imx_header.boot_data[container].img[cont_img_count].flags = (CORE_CM4_0 & BOOT_IMG_FLAGS_CORE_MASK); 169 | imx_header.boot_data[container].img[cont_img_count].flags |= (SC_R_M4_0_PID0 << BOOT_IMG_FLAGS_CPU_RID_SHIFT); 170 | imx_header.boot_data[container].img[cont_img_count].flags |= (SC_R_M4_0_MU_1A << BOOT_IMG_FLAGS_MU_RID_SHIFT); 171 | } 172 | else if (img_sp->ext == 1) { 173 | imx_header.boot_data[container].img[cont_img_count].flags = (CORE_CM4_1 & BOOT_IMG_FLAGS_CORE_MASK); 174 | imx_header.boot_data[container].img[cont_img_count].flags |= (SC_R_M4_1_PID0 << BOOT_IMG_FLAGS_CPU_RID_SHIFT); 175 | imx_header.boot_data[container].img[cont_img_count].flags |= (SC_R_M4_1_MU_1A << BOOT_IMG_FLAGS_MU_RID_SHIFT); 176 | } 177 | else{ 178 | fprintf(stderr, "Error: invalid m4 core id: %" PRIi64 "\n", img_sp->ext); 179 | exit(EXIT_FAILURE); 180 | } 181 | 182 | if(custom_partition != 0) 183 | { 184 | imx_header.boot_data[container].img[cont_img_count].flags |= (custom_partition << BOOT_IMG_FLAGS_PARTITION_ID_SHIFT); 185 | custom_partition = 0; 186 | } 187 | else 188 | { 189 | imx_header.boot_data[container].img[cont_img_count].flags |= (PARTITION_ID_M4 << BOOT_IMG_FLAGS_PARTITION_ID_SHIFT); 190 | } 191 | file_off += ALIGN(sbuf.st_size, sector_size); 192 | cont_img_count++; 193 | break; 194 | case AP: 195 | check_file(&sbuf, img_sp->filename); 196 | imx_header.boot_data[container].img[cont_img_count].src = file_off; 197 | img_sp->src = file_off; 198 | fprintf(stdout, "AP image size = 0x%" PRIx64 "\n", sbuf.st_size); 199 | fprintf(stdout, "AP image offset = 0x%x\n", file_off); 200 | imx_header.boot_data[container].img[cont_img_count].dst = img_sp->entry; 201 | imx_header.boot_data[container].img[cont_img_count].size = sbuf.st_size; 202 | imx_header.boot_data[container].img[cont_img_count].entry = img_sp->entry; 203 | imx_header.boot_data[container].num_images++; 204 | imx_header.boot_data[container].bd_size = sizeof(boot_data_v3_t); 205 | imx_header.boot_data[container].bd_flags = 0; 206 | imx_header.boot_data[container].img[cont_img_count].flags = (img_sp->ext & BOOT_IMG_FLAGS_CORE_MASK); 207 | 208 | if (img_sp->ext == CORE_CA53){ 209 | imx_header.boot_data[container].img[cont_img_count].flags |= (SC_R_A53_0 << BOOT_IMG_FLAGS_CPU_RID_SHIFT); 210 | } 211 | else if (img_sp->ext == CORE_CA72){ 212 | imx_header.boot_data[container].img[cont_img_count].flags |= (SC_R_A72_0 << BOOT_IMG_FLAGS_CPU_RID_SHIFT); 213 | } 214 | else { 215 | fprintf(stderr, "Error: invalid AP core id: %" PRIi64 "\n", img_sp->ext); 216 | exit(EXIT_FAILURE); 217 | } 218 | imx_header.boot_data[container].img[cont_img_count].flags |= (SC_R_MU_0A << BOOT_IMG_FLAGS_MU_RID_SHIFT); 219 | 220 | if(custom_partition != 0) 221 | { 222 | imx_header.boot_data[container].img[cont_img_count].flags |= (custom_partition << BOOT_IMG_FLAGS_PARTITION_ID_SHIFT); 223 | custom_partition = 0; 224 | } 225 | else 226 | { 227 | imx_header.boot_data[container].img[cont_img_count].flags |= (PARTITION_ID_AP << BOOT_IMG_FLAGS_PARTITION_ID_SHIFT); 228 | } 229 | file_off += ALIGN(sbuf.st_size, sector_size); 230 | /* only change the offset if not the first container */ 231 | tmp_to = (container > 0) ? ALIGN((img_sp->entry + sbuf.st_size), IMG_AUTO_ALIGN) : tmp_to; 232 | cont_img_count++; 233 | break; 234 | case SCD: 235 | check_file(&sbuf, img_sp->filename); 236 | imx_header.boot_data[container].scd.src = file_off; 237 | img_sp->src = file_off; 238 | imx_header.boot_data[container].scd.dst = tmp_to; 239 | imx_header.boot_data[container].scd.size = sbuf.st_size; 240 | imx_header.fhdr[container].scd = imx_header.boot_data[container].scd.dst; 241 | 242 | tmp_to = ALIGN((tmp_to + sbuf.st_size), IMG_AUTO_ALIGN); 243 | file_off += ALIGN(sbuf.st_size, sector_size); 244 | break; 245 | case CSF: 246 | check_file(&sbuf, img_sp->filename); 247 | if (sbuf.st_size > CSF_DATA_SIZE) { 248 | fprintf(stderr, "%s: file size %" PRIi64 " is larger than CSF_DATA_SIZE %d\n", 249 | img_sp->filename, sbuf.st_size, CSF_DATA_SIZE); 250 | exit(EXIT_FAILURE); 251 | } 252 | 253 | imx_header.boot_data[container].csf.src = file_off; 254 | img_sp->src = file_off; 255 | imx_header.boot_data[container].csf.dst = tmp_to; 256 | imx_header.boot_data[container].csf.size = CSF_DATA_SIZE; 257 | imx_header.fhdr[container].csf = imx_header.boot_data[container].csf.dst; 258 | 259 | tmp_to = ALIGN((tmp_to + CSF_DATA_SIZE), IMG_AUTO_ALIGN); 260 | file_off += ALIGN(CSF_DATA_SIZE, sector_size); 261 | break; 262 | case FLAG: 263 | imx_header.boot_data[container].bd_flags = img_sp->entry; 264 | break; 265 | case NEW_CONTAINER: /* move the counters forward to start on a new container */ 266 | container++; 267 | cont_img_count=0; /* reset img count when moving to new container */ 268 | tmp_to = 0; /* reset destination offset counter per container */ 269 | break; 270 | case DCD: 271 | break; 272 | case PARTITION: /* keep custom partition until next executable image */ 273 | custom_partition = img_sp->entry; 274 | break; 275 | default: 276 | fprintf(stderr, "unrecognized option in input stack"); 277 | exit(EXIT_FAILURE); 278 | } 279 | img_sp++; 280 | } 281 | 282 | /* reset counters to write output file */ 283 | container = -1; 284 | cont_img_count = 0; 285 | 286 | /* Open output file */ 287 | ofd = open (out_file, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); 288 | if (ofd < 0) { 289 | fprintf(stderr, "%s: Can't open: %s\n", 290 | out_file, strerror(errno)); 291 | exit(EXIT_FAILURE); 292 | } 293 | 294 | /* Note: Image offset are not contained in the image */ 295 | 296 | /* Write image header */ 297 | if (write(ofd, &imx_header, sizeof(imx_header_v3_t)) != sizeof(imx_header_v3_t)) { 298 | fprintf(stderr, "error writing image hdr\n"); 299 | exit(1); 300 | } 301 | 302 | if(emmc_fastboot) 303 | ivt_offset = 0;/*set ivt offset to 0 if emmc */ 304 | 305 | /* step through the image stack again this time copying images to final bin */ 306 | img_sp = image_stack; 307 | while(img_sp->option != NO_IMG){ /* stop once we reach null terminator */ 308 | if (img_sp->option == DCD || 309 | img_sp->option == OUTPUT || 310 | img_sp->option == FLAG || 311 | img_sp->option == DEVICE || 312 | img_sp->option == NEW_CONTAINER || 313 | img_sp->option == PARTITION) { 314 | img_sp++; 315 | continue;/* skip writing to the output file if not an image option */ 316 | } 317 | if (img_sp->option == CSF){ /* only pad if its a CSF image */ 318 | copy_file(ofd, img_sp->filename, CSF_DATA_SIZE, img_sp->src - ivt_offset); 319 | cont_img_count++; 320 | 321 | } 322 | else { 323 | copy_file(ofd, img_sp->filename, 0, img_sp->src - ivt_offset); 324 | } 325 | img_sp++; 326 | } 327 | 328 | /* Close output file */ 329 | close(ofd); 330 | 331 | return 0; 332 | } 333 | 334 | 335 | -------------------------------------------------------------------------------- /src/imx8qx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 NXP 3 | * 4 | * SPDX-License-Identifier: GPL-2.0+ 5 | * derived from u-boot's mkimage utility 6 | * 7 | */ 8 | 9 | #include 10 | #include "mkimage_common.h" 11 | 12 | #define MAX_NUM_IMGS 6 13 | #define IVT_HEADER_TAG 0xDE 14 | 15 | typedef struct { 16 | uint64_t src; /*8*/ 17 | uint64_t dst; /*8*/ 18 | uint64_t entry; /*8*/ 19 | uint32_t size; /*4*/ 20 | uint32_t hab_flags; /*4*/ 21 | uint32_t flags1; /*4*/ 22 | uint32_t flags2; /*4*/ 23 | } __attribute__((packed)) boot_img_t;; /*40*/ 24 | 25 | typedef struct { 26 | uint32_t num_images; /*4*/ 27 | uint32_t bd_size; /*4*/ 28 | uint32_t bd_flags; /*4*/ 29 | uint32_t reserved; /*4*/ 30 | boot_img_t img[MAX_NUM_IMGS]; /*240*/ 31 | } __attribute__((packed)) boot_data_v3_t; /*256*/ 32 | 33 | typedef struct { 34 | ivt_header_t header; /*4*/ 35 | uint32_t ver; /*4*/ 36 | uint64_t dcd_ptr; /*8*/ 37 | uint64_t boot_data_ptr; /*8*/ 38 | uint64_t self; /*8*/ 39 | uint64_t csf; /*8*/ 40 | uint64_t next; /*8*/ 41 | } __attribute__((packed)) flash_header_v3_t; /*48*/ 42 | 43 | #define MAX_NUM_OF_CONTAINER 2 44 | 45 | typedef struct { 46 | flash_header_v3_t fhdr[MAX_NUM_OF_CONTAINER]; /*96*/ 47 | boot_data_v3_t boot_data[MAX_NUM_OF_CONTAINER]; /*512*/ 48 | dcd_v2_t dcd_table; /*2880*/ 49 | } __attribute__((packed)) imx_header_v3_t; /*3488*/ 50 | 51 | 52 | static void set_imx_hdr_v3(imx_header_v3_t *imxhdr, uint32_t dcd_len, 53 | uint32_t flash_offset, uint32_t hdr_base, uint32_t cont_id) 54 | { 55 | flash_header_v3_t *fhdr_v3 = &imxhdr->fhdr[cont_id]; 56 | 57 | /* Set magic number */ 58 | fhdr_v3->header.tag = IVT_HEADER_TAG; /* 0xDE */ 59 | fhdr_v3->header.length = cpu_to_be16(sizeof(flash_header_v3_t)); 60 | fhdr_v3->header.version = IVT_VERSION; /* 0x43 */ 61 | 62 | fhdr_v3->ver = IVT_VER; /* 0x01 */ 63 | 64 | fhdr_v3->self = hdr_base + flash_offset + cont_id * sizeof(flash_header_v3_t); 65 | if (dcd_len > 0) 66 | fhdr_v3->dcd_ptr = hdr_base + flash_offset + 67 | offsetof(imx_header_v3_t, dcd_table); 68 | else 69 | fhdr_v3->dcd_ptr = 0; 70 | fhdr_v3->boot_data_ptr = hdr_base + flash_offset 71 | + offsetof(imx_header_v3_t, boot_data) + cont_id * sizeof(boot_data_v3_t); 72 | 73 | fhdr_v3->csf = 0; 74 | 75 | if ((cont_id + 1) < MAX_NUM_OF_CONTAINER) 76 | fhdr_v3->next = (uintptr_t)&imxhdr->fhdr[cont_id + 1] - (uintptr_t)imxhdr; 77 | else 78 | fhdr_v3->next = 0; 79 | } 80 | 81 | int build_container_qx(uint32_t sector_size, uint32_t ivt_offset, char* out_file, bool emmc_fastboot, image_t* image_stack) 82 | { 83 | int file_off, ofd = -1; 84 | unsigned int dcd_len = 0; 85 | 86 | static imx_header_v3_t imx_header; 87 | image_t* img_sp = image_stack; 88 | struct stat sbuf; 89 | uint64_t tmp_to = 0; /* used for offset of memory to find images */ 90 | uint32_t custom_partition = 0; /* 0 denotes default partition */ 91 | 92 | int container = -1; 93 | int cont_img_count = 0; /* indexes to arrange the container */ 94 | 95 | memset((char*)&imx_header, 0, sizeof(imx_header_v3_t)); 96 | 97 | if(image_stack == NULL) { 98 | fprintf(stderr, "Empty image stack "); 99 | exit(EXIT_FAILURE); 100 | } 101 | 102 | fprintf(stdout, "Platform:\ti.MX8QXP\n"); 103 | 104 | if(emmc_fastboot){/* start images after initial 8K */ 105 | file_off = 0x2000 - ivt_offset; 106 | } 107 | else 108 | { 109 | file_off = ALIGN(sizeof(imx_header_v3_t) + ivt_offset, sector_size); 110 | } 111 | 112 | do{ /* process DCD if it is found */ 113 | if (img_sp->option == DCD) { 114 | dcd_len = parse_cfg_file(&imx_header.dcd_table, img_sp->filename); 115 | fprintf(stdout, "dcd len = %d\n", dcd_len); 116 | } 117 | img_sp++; 118 | } 119 | while(img_sp->option!= NO_IMG); 120 | 121 | 122 | /* change load addr and setup DCD to be attached to first container */ 123 | if (ivt_offset == IVT_OFFSET_FLEXSPI) { 124 | set_imx_hdr_v3(&imx_header, dcd_len, ivt_offset, INITIAL_LOAD_ADDR_FLEXSPI, 0); 125 | set_imx_hdr_v3(&imx_header, 0, ivt_offset, INITIAL_LOAD_ADDR_FLEXSPI, 1); 126 | } else { 127 | set_imx_hdr_v3(&imx_header, dcd_len, ivt_offset, INITIAL_LOAD_ADDR_SCU_ROM, 0); 128 | set_imx_hdr_v3(&imx_header, 0, ivt_offset, INITIAL_LOAD_ADDR_AP_ROM, 1); 129 | } 130 | 131 | 132 | /* step through image stack and generate the header */ 133 | img_sp = image_stack; 134 | while(img_sp->option != NO_IMG){ /* stop once we reach null terminator */ 135 | switch(img_sp->option){ 136 | case SCFW: 137 | check_file(&sbuf, img_sp->filename); 138 | fprintf(stdout, "scfw size = %" PRIi64 "\n", sbuf.st_size); 139 | imx_header.boot_data[container].img[cont_img_count].src = file_off; 140 | img_sp->src = file_off; 141 | imx_header.boot_data[container].img[cont_img_count].dst = 0x1ffe0000; /* hard code scfw entry address */ 142 | imx_header.boot_data[container].img[cont_img_count].entry = 0x1ffe0000; 143 | imx_header.boot_data[container].img[cont_img_count].size = sbuf.st_size; 144 | imx_header.boot_data[container].img[cont_img_count].flags2 = 0; 145 | imx_header.boot_data[container].img[cont_img_count].hab_flags = IMG_TYPE_EXEC; 146 | imx_header.boot_data[container].img[cont_img_count].flags1 = (CORE_SC & BOOT_IMG_FLAGS_CORE_MASK); 147 | imx_header.boot_data[container].num_images++; 148 | imx_header.boot_data[container].bd_size = sizeof(boot_data_v3_t); 149 | 150 | file_off += ALIGN(sbuf.st_size, sector_size); 151 | tmp_to = ALIGN((imx_header.boot_data[container].img[cont_img_count].dst + sbuf.st_size), IMG_AUTO_ALIGN); 152 | cont_img_count++; 153 | break; 154 | case M4: 155 | check_file(&sbuf, img_sp->filename); 156 | imx_header.boot_data[container].img[cont_img_count].src = file_off; 157 | img_sp->src = file_off; 158 | imx_header.boot_data[container].img[cont_img_count].dst = img_sp->entry; 159 | imx_header.boot_data[container].img[cont_img_count].entry = img_sp->entry; 160 | imx_header.boot_data[container].img[cont_img_count].size = sbuf.st_size; 161 | imx_header.boot_data[container].num_images++; 162 | 163 | 164 | imx_header.boot_data[container].img[cont_img_count].flags2 = 0; 165 | imx_header.boot_data[container].img[cont_img_count].hab_flags = IMG_TYPE_EXEC; 166 | if (img_sp->ext == 0) { 167 | imx_header.boot_data[container].img[cont_img_count].flags1 = (CORE_CM4_0 & BOOT_IMG_FLAGS_CORE_MASK); 168 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (SC_R_M4_0_PID0 << BOOT_IMG_FLAGS_CPU_RID_SHIFT); 169 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (SC_R_M4_0_MU_1A << BOOT_IMG_FLAGS_MU_RID_SHIFT); 170 | } 171 | else if (img_sp->ext == 1) { 172 | imx_header.boot_data[container].img[cont_img_count].flags1 = (CORE_CM4_1 & BOOT_IMG_FLAGS_CORE_MASK); 173 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (SC_R_M4_1_PID0 << BOOT_IMG_FLAGS_CPU_RID_SHIFT); 174 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (SC_R_M4_1_MU_1A << BOOT_IMG_FLAGS_MU_RID_SHIFT); 175 | } 176 | else{ 177 | fprintf(stderr, "Error: invalid m4 core id: %" PRIi64 "\n", img_sp->ext); 178 | exit(EXIT_FAILURE); 179 | } 180 | if(custom_partition != 0) 181 | { 182 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (custom_partition << BOOT_IMG_FLAGS_PARTITION_ID_SHIFT); 183 | custom_partition = 0; 184 | } 185 | else 186 | { 187 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (PARTITION_ID_M4 << BOOT_IMG_FLAGS_PARTITION_ID_SHIFT); 188 | } 189 | file_off += ALIGN(sbuf.st_size, sector_size); 190 | cont_img_count++; 191 | break; 192 | case AP: 193 | check_file(&sbuf, img_sp->filename); 194 | imx_header.boot_data[container].img[cont_img_count].src = file_off; 195 | img_sp->src = file_off; 196 | imx_header.boot_data[container].img[cont_img_count].dst = img_sp->entry; 197 | imx_header.boot_data[container].img[cont_img_count].size = sbuf.st_size; 198 | imx_header.boot_data[container].img[cont_img_count].entry = img_sp->entry; 199 | imx_header.boot_data[container].num_images++; 200 | imx_header.boot_data[container].bd_size = sizeof(boot_data_v3_t); 201 | imx_header.boot_data[container].bd_flags = 0; 202 | 203 | 204 | imx_header.boot_data[container].img[cont_img_count].flags2 = 0; 205 | imx_header.boot_data[container].img[cont_img_count].hab_flags = IMG_TYPE_EXEC; 206 | imx_header.boot_data[container].img[cont_img_count].flags1 = (img_sp->ext & BOOT_IMG_FLAGS_CORE_MASK); 207 | if (img_sp->ext != CORE_CA35) { 208 | fprintf(stderr, "Error: invalid AP core id: %" PRIi64 "\n", img_sp->ext); 209 | exit(EXIT_FAILURE); 210 | } 211 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (SC_R_A35_0 << BOOT_IMG_FLAGS_CPU_RID_SHIFT); 212 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (SC_R_MU_0A << BOOT_IMG_FLAGS_MU_RID_SHIFT); 213 | 214 | if(custom_partition != 0) 215 | { 216 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (custom_partition << BOOT_IMG_FLAGS_PARTITION_ID_SHIFT); 217 | custom_partition = 0; 218 | } 219 | else 220 | { 221 | imx_header.boot_data[container].img[cont_img_count].flags1 |= (PARTITION_ID_AP << BOOT_IMG_FLAGS_PARTITION_ID_SHIFT); 222 | } 223 | 224 | file_off += ALIGN(sbuf.st_size, sector_size); 225 | cont_img_count++; 226 | break; 227 | case SCD: 228 | check_file(&sbuf, img_sp->filename); 229 | imx_header.boot_data[container].img[cont_img_count].src = file_off; 230 | img_sp->src = file_off; 231 | imx_header.boot_data[container].img[cont_img_count].dst = tmp_to; 232 | imx_header.boot_data[container].img[cont_img_count].size = sbuf.st_size; 233 | imx_header.boot_data[container].img[cont_img_count].flags2 = 0; 234 | imx_header.boot_data[container].img[cont_img_count].hab_flags = IMG_TYPE_SCD; 235 | imx_header.boot_data[container].img[cont_img_count].flags1 = (CORE_SC & BOOT_IMG_FLAGS_CORE_MASK); 236 | imx_header.boot_data[container].num_images++; /* scd img is count in num_images */ 237 | 238 | tmp_to = ALIGN((tmp_to + sbuf.st_size), IMG_AUTO_ALIGN); 239 | file_off += ALIGN(sbuf.st_size, sector_size); 240 | cont_img_count++; 241 | break; 242 | case CSF: 243 | check_file(&sbuf, img_sp->filename); 244 | if (sbuf.st_size > CSF_DATA_SIZE) { 245 | fprintf(stderr, "%s: file size %" PRIi64 " is larger than CSF_DATA_SIZE %d\n", 246 | img_sp->filename, sbuf.st_size, CSF_DATA_SIZE); 247 | exit(EXIT_FAILURE); 248 | } 249 | imx_header.boot_data[container].img[cont_img_count].src = file_off; 250 | img_sp->src = file_off; 251 | imx_header.boot_data[container].img[cont_img_count].dst = tmp_to; 252 | imx_header.boot_data[container].img[cont_img_count].size = CSF_DATA_SIZE; 253 | imx_header.boot_data[container].img[cont_img_count].flags2 = 0; 254 | imx_header.boot_data[container].img[cont_img_count].hab_flags = IMG_TYPE_CSF; 255 | imx_header.boot_data[container].img[cont_img_count].flags1 = (CORE_SC & BOOT_IMG_FLAGS_CORE_MASK); 256 | imx_header.fhdr[container].csf = imx_header.boot_data[container].img[cont_img_count].dst; 257 | imx_header.boot_data[container].num_images++; /* csf img is count in num_images */ 258 | 259 | tmp_to = ALIGN((tmp_to + CSF_DATA_SIZE), IMG_AUTO_ALIGN); 260 | file_off += ALIGN(CSF_DATA_SIZE, sector_size); 261 | cont_img_count++; 262 | break; 263 | case FLAG: 264 | imx_header.boot_data[container].bd_flags = img_sp->entry; 265 | break; 266 | case NEW_CONTAINER: /* move the counters forward to start on a new container */ 267 | container++; 268 | cont_img_count=0; /* reset img count when moving to new container */ 269 | break; 270 | case DCD: 271 | break; /* skip DCD here because we already processed it */ 272 | default: 273 | fprintf(stderr, "unrecognized option in input stack"); 274 | exit(EXIT_FAILURE); 275 | } 276 | img_sp++;/* advance index */ 277 | } 278 | 279 | /* reset counters to write output file */ 280 | container = 0; 281 | cont_img_count = 0; 282 | /* Open output file */ 283 | ofd = open (out_file, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); 284 | if (ofd < 0) { 285 | fprintf(stderr, "%s: Can't open: %s\n", 286 | out_file, strerror(errno)); 287 | exit(EXIT_FAILURE); 288 | } 289 | 290 | /* Note: Image offset are not contained in the image */ 291 | 292 | /* Write image header */ 293 | if (write(ofd, &imx_header, sizeof(imx_header_v3_t)) != sizeof(imx_header_v3_t)) { 294 | fprintf(stderr, "error writing image hdr\n"); 295 | exit(1); 296 | } 297 | 298 | if(emmc_fastboot) 299 | ivt_offset = 0;/*set ivt offset to 0 if emmc */ 300 | 301 | /* step through the image stack again this time copying images to final bin */ 302 | img_sp = image_stack; 303 | while(img_sp->option != NO_IMG){ /* stop once we reach null terminator */ 304 | if (img_sp->option == DCD || 305 | img_sp->option == OUTPUT || 306 | img_sp->option == FLAG || 307 | img_sp->option == DEVICE || 308 | img_sp->option == NEW_CONTAINER || 309 | img_sp->option == PARTITION) { 310 | img_sp++; 311 | continue;/* skip writing to the output file if not an image option */ 312 | } 313 | if (img_sp->option == CSF){ /* only pad if its a CSF image */ 314 | copy_file(ofd, img_sp->filename, CSF_DATA_SIZE, img_sp->src - ivt_offset); 315 | 316 | } 317 | else { 318 | copy_file(ofd, img_sp->filename, 0, img_sp->src - ivt_offset); 319 | } 320 | img_sp++; 321 | } 322 | 323 | /* Close output file */ 324 | close(ofd); 325 | return 0; 326 | } 327 | 328 | -------------------------------------------------------------------------------- /src/mkimage_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 NXP 3 | * 4 | * SPDX-License-Identifier: GPL-2.0+ 5 | * derived from u-boot's mkimage utility 6 | * 7 | */ 8 | 9 | #ifdef _MSC_VER 10 | #define _CRT_SECURE_NO_WARNINGS 11 | #endif 12 | 13 | #define _GNU_SOURCE 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifndef O_BINARY 29 | #define O_BINARY 0 30 | #endif 31 | 32 | 33 | typedef enum option_type { 34 | NO_IMG = 0, 35 | DCD, 36 | SCFW, 37 | M4, 38 | AP, 39 | OUTPUT, 40 | SCD, 41 | CSF, 42 | FLAG, 43 | DEVICE, 44 | NEW_CONTAINER, 45 | PARTITION 46 | } option_type_t; 47 | 48 | 49 | typedef struct { 50 | option_type_t option; 51 | char* filename; 52 | uint64_t src; 53 | uint64_t dst; 54 | uint64_t entry;/* image entry address or general purpose num */ 55 | uint64_t ext; 56 | } image_t; 57 | 58 | typedef enum SOC_TYPE { 59 | NONE = 0, 60 | QX, 61 | QM 62 | } soc_type_t; 63 | 64 | typedef struct { 65 | uint32_t addr; 66 | uint32_t value; 67 | } dcd_addr_data_t; 68 | 69 | typedef struct { 70 | uint8_t tag; 71 | uint16_t length; 72 | uint8_t version; 73 | } __attribute__((packed)) ivt_header_t; 74 | 75 | typedef struct { 76 | uint8_t tag; 77 | uint16_t length; 78 | uint8_t param; 79 | } __attribute__((packed)) write_dcd_command_t; 80 | 81 | #define MAX_HW_CFG_SIZE_V2 359 82 | 83 | struct dcd_v2_cmd { 84 | write_dcd_command_t write_dcd_command; /*4*/ 85 | dcd_addr_data_t addr_data[MAX_HW_CFG_SIZE_V2]; /*2872*/ 86 | } __attribute__((packed)); 87 | 88 | typedef struct { 89 | ivt_header_t header; /*4*/ 90 | struct dcd_v2_cmd dcd_cmd; /*2876*/ 91 | } __attribute__((packed)) dcd_v2_t; /*2880*/ 92 | 93 | #define CORE_SC 1 94 | #define CORE_CM4_0 2 95 | #define CORE_CM4_1 3 96 | #define CORE_CA53 4 97 | #define CORE_CA35 4 98 | #define CORE_CA72 5 99 | #define CORE_SECO 6 100 | 101 | #define IMG_TYPE_CSF 0x01 /* CSF image type */ 102 | #define IMG_TYPE_SCD 0x02 /* SCD image type */ 103 | #define IMG_TYPE_EXEC 0x03 /* Executable image type */ 104 | #define IMG_TYPE_DATA 0x04 /* Data image type */ 105 | 106 | #define IMG_TYPE_SHIFT 0 107 | #define IMG_TYPE_MASK 0x1f 108 | #define IMG_TYPE(x) (((x) & IMG_TYPE_MASK) >> IMG_TYPE_SHIFT) 109 | 110 | #define BOOT_IMG_FLAGS_CORE_MASK 0xF 111 | #define BOOT_IMG_FLAGS_CPU_RID_MASK 0x3FF0 112 | #define BOOT_IMG_FLAGS_CPU_RID_SHIFT 4 113 | #define BOOT_IMG_FLAGS_MU_RID_MASK 0xFFC000 114 | #define BOOT_IMG_FLAGS_MU_RID_SHIFT 14 115 | #define BOOT_IMG_FLAGS_PARTITION_ID_MASK 0x1F000000 116 | #define BOOT_IMG_FLAGS_PARTITION_ID_SHIFT 24 117 | 118 | #define SC_R_A35_0 508 119 | #define SC_R_A53_0 1 120 | #define SC_R_A72_0 6 121 | #define SC_R_MU_0A 213 122 | #define SC_R_M4_0_PID0 278 123 | #define SC_R_M4_0_MU_1A 297 124 | #define SC_R_M4_1_PID0 298 125 | #define SC_R_M4_1_MU_1A 317 126 | #define PARTITION_ID_M4 0 127 | #define PARTITION_ID_AP 1 128 | 129 | /* Command tags and parameters */ 130 | #define HAB_DATA_WIDTH_BYTE 1 /* 8-bit value */ 131 | #define HAB_DATA_WIDTH_HALF 2 /* 16-bit value */ 132 | #define HAB_DATA_WIDTH_WORD 4 /* 32-bit value */ 133 | #define HAB_CMD_WRT_DAT_MSK 1 /* mask/value flag */ 134 | #define HAB_CMD_WRT_DAT_SET 2 /* set/clear flag */ 135 | #define HAB_CMD_CHK_DAT_SET 2 /* set/clear flag */ 136 | #define HAB_CMD_CHK_DAT_ANY 4 /* any/all flag */ 137 | #define HAB_CMD_WRT_DAT_FLAGS_WIDTH 5 /* flags field width */ 138 | #define HAB_CMD_WRT_DAT_FLAGS_SHIFT 3 /* flags field offset */ 139 | #define HAB_CMD_WRT_DAT_BYTES_WIDTH 3 /* bytes field width */ 140 | #define HAB_CMD_WRT_DAT_BYTES_SHIFT 0 /* bytes field offset */ 141 | 142 | #define IVT_VER 0x01 143 | #define IVT_VERSION 0x43 144 | #define DCD_HEADER_TAG 0xD2 145 | #define DCD_VERSION 0x43 146 | #define DCD_WRITE_DATA_COMMAND_TAG 0xCC 147 | #define DCD_WRITE_DATA_PARAM (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT) /* 0x4 */ 148 | #define DCD_WRITE_CLR_BIT_PARAM ((HAB_CMD_WRT_DAT_MSK << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0xC */ 149 | #define DCD_WRITE_SET_BIT_PARAM ((HAB_CMD_WRT_DAT_MSK << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_CMD_WRT_DAT_SET << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0x1C */ 150 | #define DCD_CHECK_DATA_COMMAND_TAG 0xCF 151 | #define DCD_CHECK_BITS_CLR_PARAM (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT) /* 0x04 */ 152 | #define DCD_CHECK_BITS_SET_PARAM ((HAB_CMD_CHK_DAT_SET << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0x14 */ 153 | #define DCD_CHECK_ANY_BIT_CLR_PARAM ((HAB_CMD_CHK_DAT_ANY << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0x24 */ 154 | #define DCD_CHECK_ANY_BIT_SET_PARAM ((HAB_CMD_CHK_DAT_ANY << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_CMD_CHK_DAT_SET << HAB_CMD_WRT_DAT_FLAGS_SHIFT) | (HAB_DATA_WIDTH_WORD << HAB_CMD_WRT_DAT_BYTES_SHIFT)) /* 0x34 */ 155 | 156 | #define IVT_OFFSET_NAND (0x400) 157 | #define IVT_OFFSET_I2C (0x400) 158 | #define IVT_OFFSET_FLEXSPI (0x1000) 159 | #define IVT_OFFSET_SD (0x400) 160 | #define IVT_OFFSET_SATA (0x400) 161 | #define IVT_OFFSET_EMMC (0x400) 162 | 163 | #define CSF_DATA_SIZE (0x4000) 164 | #define INITIAL_LOAD_ADDR_SCU_ROM 0x2000e000 165 | #define INITIAL_LOAD_ADDR_AP_ROM 0x00110000 166 | #define INITIAL_LOAD_ADDR_FLEXSPI 0x08000000 167 | #define IMG_AUTO_ALIGN 0x10 168 | 169 | #define ALIGN(x,a) __ALIGN_MASK((x),(__typeof__(x))(a)-1) 170 | #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) 171 | 172 | #define uswap_16(x) \ 173 | ((((x) & 0xff00) >> 8) | \ 174 | (((x) & 0x00ff) << 8)) 175 | #define uswap_32(x) \ 176 | ((((x) & 0xff000000) >> 24) | \ 177 | (((x) & 0x00ff0000) >> 8) | \ 178 | (((x) & 0x0000ff00) << 8) | \ 179 | (((x) & 0x000000ff) << 24)) 180 | #define _uswap_64(x, sfx) \ 181 | ((((x) & 0xff00000000000000##sfx) >> 56) | \ 182 | (((x) & 0x00ff000000000000##sfx) >> 40) | \ 183 | (((x) & 0x0000ff0000000000##sfx) >> 24) | \ 184 | (((x) & 0x000000ff00000000##sfx) >> 8) | \ 185 | (((x) & 0x00000000ff000000##sfx) << 8) | \ 186 | (((x) & 0x0000000000ff0000##sfx) << 24) | \ 187 | (((x) & 0x000000000000ff00##sfx) << 40) | \ 188 | (((x) & 0x00000000000000ff##sfx) << 56)) 189 | 190 | #if defined(__GNUC__) 191 | # define uswap_64(x) _uswap_64(x, ull) 192 | #else 193 | #error 194 | # define uswap_64(x) _uswap_64(x, ) 195 | #endif 196 | 197 | #if __BYTE_ORDER == __LITTLE_ENDIAN 198 | # define cpu_to_le16(x) (x) 199 | # define cpu_to_le32(x) (x) 200 | # define cpu_to_le64(x) (x) 201 | # define le16_to_cpu(x) (x) 202 | # define le32_to_cpu(x) (x) 203 | # define le64_to_cpu(x) (x) 204 | # define cpu_to_be16(x) uswap_16(x) 205 | # define cpu_to_be32(x) uswap_32(x) 206 | # define cpu_to_be64(x) uswap_64(x) 207 | # define be16_to_cpu(x) uswap_16(x) 208 | # define be32_to_cpu(x) uswap_32(x) 209 | # define be64_to_cpu(x) uswap_64(x) 210 | #else 211 | #error 212 | # define cpu_to_le16(x) uswap_16(x) 213 | # define cpu_to_le32(x) uswap_32(x) 214 | # define cpu_to_le64(x) uswap_64(x) 215 | # define le16_to_cpu(x) uswap_16(x) 216 | # define le32_to_cpu(x) uswap_32(x) 217 | # define le64_to_cpu(x) uswap_64(x) 218 | # define cpu_to_be16(x) (x) 219 | # define cpu_to_be32(x) (x) 220 | # define cpu_to_be64(x) (x) 221 | # define be16_to_cpu(x) (x) 222 | # define be32_to_cpu(x) (x) 223 | # define be64_to_cpu(x) (x) 224 | #endif 225 | 226 | #define UNDEFINED 0xFFFFFFFF 227 | 228 | #if 0 229 | enum imximage_fld_types { 230 | CFG_INVALID = -1, 231 | CFG_COMMAND, 232 | CFG_REG_SIZE, 233 | CFG_REG_ADDRESS, 234 | CFG_REG_VALUE 235 | }; 236 | 237 | enum imximage_cmd { 238 | CMD_INVALID, 239 | CMD_IMAGE_VERSION, 240 | CMD_BOOT_FROM, 241 | CMD_BOOT_OFFSET, 242 | CMD_WRITE_DATA, 243 | CMD_WRITE_CLR_BIT, 244 | CMD_WRITE_SET_BIT, 245 | CMD_CHECK_BITS_SET, 246 | CMD_CHECK_BITS_CLR, 247 | CMD_CHECK_ANY_BIT_SET, 248 | CMD_CHECK_ANY_BIT_CLR, 249 | CMD_CSF, 250 | CMD_PLUGIN, 251 | }; 252 | 253 | typedef struct table_entry { 254 | int id; 255 | char *sname; /* short (input) name to find table entry */ 256 | char *lname; /* long (output) name to print for messages */ 257 | } table_entry_t; 258 | 259 | /* 260 | * Supported commands for configuration file 261 | */ 262 | static table_entry_t imximage_cmds[] = { 263 | {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, 264 | {CMD_BOOT_OFFSET, "BOOT_OFFSET", "Boot offset", }, 265 | {CMD_WRITE_DATA, "DATA", "Reg Write Data", }, 266 | {CMD_WRITE_CLR_BIT, "CLR_BIT", "Reg clear bit", }, 267 | {CMD_WRITE_SET_BIT, "SET_BIT", "Reg set bit", }, 268 | {CMD_CHECK_BITS_SET, "CHECK_BITS_SET", "Reg Check all bits set", }, 269 | {CMD_CHECK_BITS_CLR, "CHECK_BITS_CLR", "Reg Check all bits clr", }, 270 | {CMD_CHECK_ANY_BIT_SET, "CHECK_ANY_BIT_SET", "Reg Check any bit set", }, 271 | {CMD_CHECK_ANY_BIT_CLR, "CHECK_ANY_BIT_CLR", "Reg Check any bit clr", }, 272 | {CMD_CSF, "CSF", "Command Sequence File", }, 273 | {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, 274 | {-1, "", "", }, 275 | }; 276 | #endif 277 | 278 | void check_file(struct stat* sbuf,char * filename); 279 | void copy_file (int ifd, const char *datafile, int pad, int offset); 280 | uint32_t get_cfg_value(char *token, char *name, int linenr); 281 | void set_dcd_param_v2(dcd_v2_t *dcd_v2, uint32_t dcd_len, 282 | int32_t cmd); 283 | void set_dcd_val_v2(dcd_v2_t *dcd_v2, char *name, int lineno, 284 | int fld, uint32_t value, uint32_t off); 285 | void set_dcd_rst_v2(dcd_v2_t *dcd_v2, uint32_t dcd_len, 286 | char *name, int lineno); 287 | void parse_cfg_cmd(dcd_v2_t *dcd_v2, int32_t cmd, char *token, 288 | char *name, int lineno, int fld, int dcd_len); 289 | void parse_cfg_fld(dcd_v2_t *dcd_v2, int32_t *cmd, 290 | char *token, char *name, int lineno, int fld, int *dcd_len); 291 | uint32_t parse_cfg_file(dcd_v2_t *dcd_v2, char *name); 292 | 293 | int build_container_qm(uint32_t sector_size, uint32_t ivt_offset, char * out_file, 294 | bool emmc_fastboot, image_t* image_stack); 295 | 296 | int build_container_qx(uint32_t sector_size, uint32_t ivt_offset, char * out_file, 297 | bool emmc_fastboot, image_t* image_stack); 298 | 299 | 300 | 301 | -------------------------------------------------------------------------------- /src/mkimage_imx8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Freescale Semiconductor, Inc. 3 | * 4 | * Copyright (C) 2017 NXP 5 | * 6 | * SPDX-License-Identifier: GPL-2.0+ 7 | * derived from u-boot's mkimage utility 8 | * 9 | */ 10 | 11 | #define _GNU_SOURCE 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "mkimage_common.h" 28 | #include "build_info.h" 29 | 30 | #ifndef O_BINARY 31 | #define O_BINARY 0 32 | #endif 33 | 34 | 35 | #define IMG_STACK_SIZE 32 /* max of 32 images for commandline images */ 36 | 37 | enum imximage_fld_types { 38 | CFG_INVALID = -1, 39 | CFG_COMMAND, 40 | CFG_REG_SIZE, 41 | CFG_REG_ADDRESS, 42 | CFG_REG_VALUE 43 | }; 44 | 45 | enum imximage_cmd { 46 | CMD_INVALID, 47 | CMD_IMAGE_VERSION, 48 | CMD_BOOT_FROM, 49 | CMD_BOOT_OFFSET, 50 | CMD_WRITE_DATA, 51 | CMD_WRITE_CLR_BIT, 52 | CMD_WRITE_SET_BIT, 53 | CMD_CHECK_BITS_SET, 54 | CMD_CHECK_BITS_CLR, 55 | CMD_CHECK_ANY_BIT_SET, 56 | CMD_CHECK_ANY_BIT_CLR, 57 | CMD_CSF, 58 | CMD_PLUGIN, 59 | }; 60 | 61 | typedef struct table_entry { 62 | int id; 63 | char *sname; /* short (input) name to find table entry */ 64 | char *lname; /* long (output) name to print for messages */ 65 | } table_entry_t; 66 | 67 | /* 68 | * Supported commands for configuration file 69 | */ 70 | static table_entry_t imximage_cmds[] = { 71 | {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, 72 | {CMD_BOOT_OFFSET, "BOOT_OFFSET", "Boot offset", }, 73 | {CMD_WRITE_DATA, "DATA", "Reg Write Data", }, 74 | {CMD_WRITE_CLR_BIT, "CLR_BIT", "Reg clear bit", }, 75 | {CMD_WRITE_SET_BIT, "SET_BIT", "Reg set bit", }, 76 | {CMD_CHECK_BITS_SET, "CHECK_BITS_SET", "Reg Check all bits set", }, 77 | {CMD_CHECK_BITS_CLR, "CHECK_BITS_CLR", "Reg Check all bits clr", }, 78 | {CMD_CHECK_ANY_BIT_SET, "CHECK_ANY_BIT_SET", "Reg Check any bit set", }, 79 | {CMD_CHECK_ANY_BIT_CLR, "CHECK_ANY_BIT_CLR", "Reg Check any bit clr", }, 80 | {CMD_CSF, "CSF", "Command Sequence File", }, 81 | {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, 82 | {-1, "", "", }, 83 | }; 84 | 85 | void check_file(struct stat* sbuf,char * filename) 86 | { 87 | int tmp_fd = open(filename, O_RDONLY | O_BINARY); 88 | if (tmp_fd < 0) { 89 | fprintf(stderr, "%s: Can't open: %s\n", 90 | filename, strerror(errno)); 91 | exit(EXIT_FAILURE); 92 | } 93 | 94 | if (fstat(tmp_fd, sbuf) < 0) { 95 | fprintf(stderr, "%s: Can't stat: %s\n", 96 | filename, strerror(errno)); 97 | exit(EXIT_FAILURE); 98 | } 99 | close(tmp_fd); 100 | 101 | } 102 | 103 | void 104 | copy_file (int ifd, const char *datafile, int pad, int offset) 105 | { 106 | int dfd; 107 | struct stat sbuf; 108 | unsigned char *ptr; 109 | int tail; 110 | int zero = 0; 111 | uint8_t zeros[4096]; 112 | int size; 113 | 114 | memset(zeros, 0, sizeof(zeros)); 115 | 116 | if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) { 117 | fprintf (stderr, "Can't open %s: %s\n", 118 | datafile, strerror(errno)); 119 | exit (EXIT_FAILURE); 120 | } 121 | 122 | if (fstat(dfd, &sbuf) < 0) { 123 | fprintf (stderr, "Can't stat %s: %s\n", 124 | datafile, strerror(errno)); 125 | exit (EXIT_FAILURE); 126 | } 127 | 128 | ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0); 129 | if (ptr == MAP_FAILED) { 130 | fprintf (stderr, "Can't read %s: %s\n", 131 | datafile, strerror(errno)); 132 | exit (EXIT_FAILURE); 133 | } 134 | 135 | size = sbuf.st_size; 136 | lseek(ifd, offset, SEEK_SET); 137 | if (write(ifd, ptr, size) != size) { 138 | fprintf (stderr, "Write error %s\n", 139 | strerror(errno)); 140 | exit (EXIT_FAILURE); 141 | } 142 | 143 | tail = size % 4; 144 | pad = pad - size; 145 | if ((pad == 1) && (tail != 0)) { 146 | 147 | if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { 148 | fprintf (stderr, "Write error on %s\n", 149 | strerror(errno)); 150 | exit (EXIT_FAILURE); 151 | } 152 | } else if (pad > 1) { 153 | while (pad > 0) { 154 | int todo = sizeof(zeros); 155 | 156 | if (todo > pad) 157 | todo = pad; 158 | if (write(ifd, (char *)&zeros, todo) != todo) { 159 | fprintf(stderr, "Write error: %s\n", 160 | strerror(errno)); 161 | exit(EXIT_FAILURE); 162 | } 163 | pad -= todo; 164 | } 165 | } 166 | 167 | (void) munmap((void *)ptr, sbuf.st_size); 168 | (void) close (dfd); 169 | } 170 | 171 | 172 | static uint32_t imximage_version; 173 | static struct dcd_v2_cmd *gd_last_cmd; 174 | static uint32_t imximage_ivt_offset = UNDEFINED; 175 | static uint32_t imximage_csf_size = UNDEFINED; 176 | 177 | int get_table_entry_id(const table_entry_t *table, 178 | const char *table_name, const char *name) 179 | { 180 | const table_entry_t *t; 181 | 182 | for (t = table; t->id >= 0; ++t) { 183 | if (t->sname && strcasecmp(t->sname, name) == 0) 184 | return (t->id); 185 | } 186 | 187 | return -1; 188 | } 189 | 190 | uint32_t get_cfg_value(char *token, char *name, int linenr) 191 | { 192 | char *endptr; 193 | uint32_t value; 194 | 195 | errno = 0; 196 | value = strtoul(token, &endptr, 16); 197 | if (errno || (token == endptr)) { 198 | fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", 199 | name, linenr, token); 200 | exit(EXIT_FAILURE); 201 | } 202 | return value; 203 | } 204 | 205 | 206 | void set_dcd_param_v2(dcd_v2_t *dcd_v2, uint32_t dcd_len, 207 | int32_t cmd) 208 | { 209 | struct dcd_v2_cmd *d = gd_last_cmd; 210 | struct dcd_v2_cmd *d2; 211 | int len; 212 | 213 | if (!d) 214 | d = &dcd_v2->dcd_cmd; 215 | d2 = d; 216 | len = be16_to_cpu(d->write_dcd_command.length); 217 | if (len > 4) 218 | d2 = (struct dcd_v2_cmd *)(((char *)d) + len); 219 | 220 | switch (cmd) { 221 | /* Write value: *address = val_msk */ 222 | case CMD_WRITE_DATA: 223 | if ((d->write_dcd_command.tag == DCD_WRITE_DATA_COMMAND_TAG) && 224 | (d->write_dcd_command.param == DCD_WRITE_DATA_PARAM)) 225 | break; 226 | d = d2; 227 | d->write_dcd_command.tag = DCD_WRITE_DATA_COMMAND_TAG; 228 | d->write_dcd_command.length = cpu_to_be16(4); 229 | d->write_dcd_command.param = DCD_WRITE_DATA_PARAM; 230 | break; 231 | /* Clear bitmask: *address &= ~val_msk */ 232 | case CMD_WRITE_CLR_BIT: 233 | if ((d->write_dcd_command.tag == DCD_WRITE_DATA_COMMAND_TAG) && 234 | (d->write_dcd_command.param == DCD_WRITE_CLR_BIT_PARAM)) 235 | break; 236 | d = d2; 237 | d->write_dcd_command.tag = DCD_WRITE_DATA_COMMAND_TAG; 238 | d->write_dcd_command.length = cpu_to_be16(4); 239 | d->write_dcd_command.param = DCD_WRITE_CLR_BIT_PARAM; 240 | break; 241 | /* Set bitmask: *address |= val_msk */ 242 | case CMD_WRITE_SET_BIT: 243 | if ((d->write_dcd_command.tag == DCD_WRITE_DATA_COMMAND_TAG) && 244 | (d->write_dcd_command.param == DCD_WRITE_SET_BIT_PARAM)) 245 | break; 246 | d = d2; 247 | d->write_dcd_command.tag = DCD_WRITE_DATA_COMMAND_TAG; 248 | d->write_dcd_command.length = cpu_to_be16(4); 249 | d->write_dcd_command.param = DCD_WRITE_SET_BIT_PARAM; 250 | break; 251 | /* 252 | * Check data command only supports one entry, 253 | */ 254 | /* All bits set: (*address & mask) == mask */ 255 | case CMD_CHECK_BITS_SET: 256 | d = d2; 257 | d->write_dcd_command.tag = DCD_CHECK_DATA_COMMAND_TAG; 258 | d->write_dcd_command.length = cpu_to_be16(4); 259 | d->write_dcd_command.param = DCD_CHECK_BITS_SET_PARAM; 260 | break; 261 | /* All bits clear: (*address & mask) == 0 */ 262 | case CMD_CHECK_BITS_CLR: 263 | d = d2; 264 | d->write_dcd_command.tag = DCD_CHECK_DATA_COMMAND_TAG; 265 | d->write_dcd_command.length = cpu_to_be16(4); 266 | d->write_dcd_command.param = DCD_CHECK_BITS_CLR_PARAM; 267 | break; 268 | /* Any bit clear: (*address & mask) != mask */ 269 | case CMD_CHECK_ANY_BIT_CLR: 270 | d = d2; 271 | d->write_dcd_command.tag = DCD_CHECK_DATA_COMMAND_TAG; 272 | d->write_dcd_command.length = cpu_to_be16(4); 273 | d->write_dcd_command.param = DCD_CHECK_ANY_BIT_CLR_PARAM; 274 | break; 275 | /* Any bit set: (*address & mask) != 0 */ 276 | case CMD_CHECK_ANY_BIT_SET: 277 | d = d2; 278 | d->write_dcd_command.tag = DCD_CHECK_DATA_COMMAND_TAG; 279 | d->write_dcd_command.length = cpu_to_be16(4); 280 | d->write_dcd_command.param = DCD_CHECK_ANY_BIT_SET_PARAM; 281 | break; 282 | default: 283 | break; 284 | } 285 | gd_last_cmd = d; 286 | } 287 | 288 | void set_dcd_val_v2(dcd_v2_t *dcd_v2, char *name, int lineno, 289 | int fld, uint32_t value, uint32_t off) 290 | { 291 | struct dcd_v2_cmd *d = gd_last_cmd; 292 | int len; 293 | 294 | len = be16_to_cpu(d->write_dcd_command.length); 295 | off = (len - 4) >> 3; 296 | 297 | switch (fld) { 298 | case CFG_REG_ADDRESS: 299 | d->addr_data[off].addr = cpu_to_be32(value); 300 | break; 301 | case CFG_REG_VALUE: 302 | d->addr_data[off].value = cpu_to_be32(value); 303 | off++; 304 | d->write_dcd_command.length = cpu_to_be16((off << 3) + 4); 305 | break; 306 | default: 307 | break; 308 | 309 | } 310 | } 311 | 312 | void set_dcd_rst_v2(dcd_v2_t *dcd_v2, uint32_t dcd_len, 313 | char *name, int lineno) 314 | { 315 | struct dcd_v2_cmd *d = gd_last_cmd; 316 | int len; 317 | 318 | if (!d) 319 | d = &dcd_v2->dcd_cmd; 320 | len = be16_to_cpu(d->write_dcd_command.length); 321 | if (len > 4) 322 | d = (struct dcd_v2_cmd *)(((char *)d) + len); 323 | 324 | len = (char *)d - (char *)&dcd_v2->header; 325 | 326 | dcd_v2->header.tag = DCD_HEADER_TAG; 327 | dcd_v2->header.length = cpu_to_be16(len); 328 | dcd_v2->header.version = DCD_VERSION; 329 | } 330 | 331 | void parse_cfg_cmd(dcd_v2_t *dcd_v2, int32_t cmd, char *token, 332 | char *name, int lineno, int fld, int dcd_len) 333 | { 334 | int value; 335 | static int cmd_ver_first = ~0; 336 | 337 | switch (cmd) { 338 | case CMD_IMAGE_VERSION: 339 | imximage_version = get_cfg_value(token, name, lineno); 340 | if (cmd_ver_first == 0) { 341 | fprintf(stderr, "Error: %s[%d] - IMAGE_VERSION " 342 | "command need be the first before other " 343 | "valid command in the file\n", name, lineno); 344 | exit(EXIT_FAILURE); 345 | } 346 | cmd_ver_first = 1; 347 | break; 348 | case CMD_BOOT_OFFSET: 349 | imximage_ivt_offset = get_cfg_value(token, name, lineno); 350 | if (cmd_ver_first != 1) 351 | cmd_ver_first = 0; 352 | break; 353 | case CMD_WRITE_DATA: 354 | case CMD_WRITE_CLR_BIT: 355 | case CMD_WRITE_SET_BIT: 356 | case CMD_CHECK_BITS_SET: 357 | case CMD_CHECK_BITS_CLR: 358 | case CMD_CHECK_ANY_BIT_SET: 359 | case CMD_CHECK_ANY_BIT_CLR: 360 | value = get_cfg_value(token, name, lineno); 361 | set_dcd_param_v2(dcd_v2, dcd_len, cmd); 362 | set_dcd_val_v2(dcd_v2, name, lineno, fld, value, dcd_len); 363 | if (cmd_ver_first != 1) 364 | cmd_ver_first = 0; 365 | break; 366 | case CMD_CSF: 367 | if (imximage_version != 2) { 368 | fprintf(stderr, 369 | "Error: %s[%d] - CSF only supported for VERSION 2(%s)\n", 370 | name, lineno, token); 371 | exit(EXIT_FAILURE); 372 | } 373 | imximage_csf_size = get_cfg_value(token, name, lineno); 374 | if (cmd_ver_first != 1) 375 | cmd_ver_first = 0; 376 | break; 377 | } 378 | } 379 | 380 | void parse_cfg_fld(dcd_v2_t *dcd_v2, int32_t *cmd, 381 | char *token, char *name, int lineno, int fld, int *dcd_len) 382 | { 383 | int value; 384 | 385 | switch (fld) { 386 | case CFG_COMMAND: 387 | *cmd = get_table_entry_id(imximage_cmds, 388 | "imximage commands", token); 389 | if (*cmd < 0) { 390 | fprintf(stderr, "Error: %s[%d] - Invalid command" 391 | "(%s)\n", name, lineno, token); 392 | exit(EXIT_FAILURE); 393 | } 394 | break; 395 | case CFG_REG_SIZE: 396 | parse_cfg_cmd(dcd_v2, *cmd, token, name, lineno, fld, *dcd_len); 397 | break; 398 | case CFG_REG_ADDRESS: 399 | case CFG_REG_VALUE: 400 | switch(*cmd) { 401 | case CMD_WRITE_DATA: 402 | case CMD_WRITE_CLR_BIT: 403 | case CMD_WRITE_SET_BIT: 404 | case CMD_CHECK_BITS_SET: 405 | case CMD_CHECK_BITS_CLR: 406 | case CMD_CHECK_ANY_BIT_SET: 407 | case CMD_CHECK_ANY_BIT_CLR: 408 | value = get_cfg_value(token, name, lineno); 409 | set_dcd_param_v2(dcd_v2, *dcd_len, *cmd); 410 | set_dcd_val_v2(dcd_v2, name, lineno, fld, value, 411 | *dcd_len); 412 | 413 | if (fld == CFG_REG_VALUE) { 414 | (*dcd_len)++; 415 | if (*dcd_len > MAX_HW_CFG_SIZE_V2) { 416 | fprintf(stderr, "Error: %s[%d] -" 417 | "DCD table exceeds maximum size(%d)\n", 418 | name, lineno, MAX_HW_CFG_SIZE_V2); 419 | exit(EXIT_FAILURE); 420 | } 421 | } 422 | break; 423 | default: 424 | break; 425 | } 426 | break; 427 | default: 428 | break; 429 | } 430 | } 431 | 432 | uint32_t parse_cfg_file(dcd_v2_t *dcd_v2, char *name) 433 | { 434 | FILE *fd = NULL; 435 | char *line = NULL; 436 | char *token, *saveptr1, *saveptr2; 437 | int lineno = 0; 438 | int fld; 439 | size_t len; 440 | int dcd_len = 0; 441 | int32_t cmd; 442 | 443 | fd = fopen(name, "r"); 444 | if (fd == 0) { 445 | fprintf(stderr, "Error: %s - Can't open DCD file\n", name); 446 | exit(EXIT_FAILURE); 447 | } 448 | 449 | /* 450 | * Very simple parsing, line starting with # are comments 451 | * and are dropped 452 | */ 453 | while ((getline(&line, &len, fd)) > 0) { 454 | lineno++; 455 | 456 | token = strtok_r(line, "\r\n", &saveptr1); 457 | if (token == NULL) 458 | continue; 459 | 460 | /* Check inside the single line */ 461 | for (fld = CFG_COMMAND, cmd = CMD_INVALID, 462 | line = token; ; line = NULL, fld++) { 463 | token = strtok_r(line, " \t", &saveptr2); 464 | if (token == NULL) 465 | break; 466 | 467 | /* Drop all text starting with '#' as comments */ 468 | if (token[0] == '#') 469 | break; 470 | 471 | parse_cfg_fld(dcd_v2, &cmd, token, name, 472 | lineno, fld, &dcd_len); 473 | } 474 | 475 | } 476 | 477 | set_dcd_rst_v2(dcd_v2, dcd_len, name, lineno); 478 | fclose(fd); 479 | 480 | return dcd_len; 481 | } 482 | 483 | /* 484 | * Read commandline parameters and construct the header in order 485 | * 486 | * This will then construct the image according to the header and 487 | * 488 | * parameters passed in 489 | * 490 | */ 491 | int main(int argc, char **argv) 492 | { 493 | int c; 494 | char *ofname = NULL; 495 | bool scfw = false; 496 | bool output = false; 497 | bool emmc_fastboot = false; 498 | 499 | int container = -1; 500 | image_t param_stack[IMG_STACK_SIZE];/* stack of input images */ 501 | int p_idx = 0;/* param index counter */ 502 | 503 | uint32_t ivt_offset = IVT_OFFSET_SD; 504 | uint32_t sector_size = 0x200; /* default sector size */ 505 | soc_type_t soc = NONE; /* Initially No SOC defined */ 506 | 507 | static struct option long_options[] = 508 | { 509 | {"scfw", required_argument, NULL, 'f'}, 510 | {"m4", required_argument, NULL, 'm'}, 511 | {"ap", required_argument, NULL, 'a'}, 512 | {"dcd", required_argument, NULL, 'd'}, 513 | {"out", required_argument, NULL, 'o'}, 514 | {"flags", required_argument, NULL, 'l'}, 515 | {"scd", required_argument, NULL, 'x'}, 516 | {"csf", required_argument, NULL, 'z'}, 517 | {"dev", required_argument, NULL, 'e'}, 518 | {"soc", required_argument, NULL, 's'}, 519 | {"container", no_argument, NULL, 'c'}, 520 | {"partition", required_argument, NULL, 'p'}, 521 | {"commit", no_argument, NULL, 't'}, 522 | {NULL, 0, NULL, 0} 523 | }; 524 | 525 | 526 | /* scan in parameters in order */ 527 | while(1) 528 | { 529 | /* getopt_long stores the option index here. */ 530 | int option_index = 0; 531 | 532 | c = getopt_long_only (argc, argv, ":f:m:a:d:o:l:x:z:e:p:c", 533 | long_options, &option_index); 534 | 535 | /* Detect the end of the options. */ 536 | if (c == -1) 537 | break; 538 | 539 | switch (c) 540 | { 541 | case 0: 542 | fprintf(stderr, "option %s", long_options[option_index].name); 543 | if (optarg) 544 | fprintf(stderr, " with arg %s", optarg); 545 | fprintf(stderr, "\n"); 546 | break; 547 | case 'p': 548 | fprintf(stdout, "PARTITION:\t%s\n", optarg); 549 | param_stack[p_idx].option = PARTITION; 550 | param_stack[p_idx++].entry = (uint32_t) strtoll(optarg, NULL, 0); 551 | break; 552 | case 's': 553 | if(!strncmp(optarg, "QX", 2)) 554 | soc = QX; 555 | else if (!strncmp(optarg, "QM", 2)) 556 | soc = QM; 557 | else{ 558 | fprintf(stdout, "unrecognized SOC: %s \n",optarg); 559 | exit(EXIT_FAILURE); 560 | } 561 | fprintf(stdout, "SOC: %s \n",optarg); 562 | break; 563 | case 'f': 564 | fprintf(stdout, "SCFW:\t%s\n", optarg); 565 | param_stack[p_idx].option = SCFW; 566 | param_stack[p_idx++].filename = optarg; 567 | scfw = true; 568 | break; 569 | case 'd': 570 | fprintf(stdout, "DCD:\t%s\n", optarg); 571 | param_stack[p_idx].option = DCD; 572 | param_stack[p_idx++].filename = optarg; 573 | break; 574 | case 'm': 575 | fprintf(stdout, "CM4:\t%s", optarg); 576 | param_stack[p_idx].option = M4; 577 | param_stack[p_idx].filename = optarg; 578 | if ((optind < argc && *argv[optind] != '-') && (optind+1 < argc &&*argv[optind+1] != '-' )) { 579 | param_stack[p_idx].ext = strtol(argv[optind++], NULL, 0); 580 | param_stack[p_idx].entry = (uint32_t) strtoll(argv[optind++], NULL, 0); 581 | fprintf(stdout, "\tcore: %" PRIi64, param_stack[p_idx].ext); 582 | fprintf(stdout, " addr: 0x%08" PRIx64 "\n", param_stack[p_idx++].entry); 583 | } else { 584 | fprintf(stderr, "\n-m4 option require THREE arguments: filename, core: 0/1, start address in hex\n\n"); 585 | exit(EXIT_FAILURE); 586 | } 587 | break; 588 | case 'a': 589 | fprintf(stdout, "AP:\t%s", optarg); 590 | param_stack[p_idx].option = AP; 591 | param_stack[p_idx].filename = optarg; 592 | if ((optind < argc && *argv[optind] != '-') && (optind+1 < argc &&*argv[optind+1] != '-' )) { 593 | if (!strncmp(argv[optind], "a53", 3)) 594 | param_stack[p_idx].ext = CORE_CA53; 595 | else if (!strncmp(argv[optind], "a35", 3)) 596 | param_stack[p_idx].ext = CORE_CA35; 597 | else if (!strncmp(argv[optind], "a72", 3)) 598 | param_stack[p_idx].ext = CORE_CA72; 599 | else { 600 | fprintf(stderr, "ERROR: AP Core not found %s\n", argv[optind+2]); 601 | exit(EXIT_FAILURE); 602 | } 603 | 604 | fprintf(stdout, "\tcore: %s", argv[optind++]); 605 | 606 | param_stack[p_idx].entry = (uint32_t) strtoll(argv[optind++], NULL, 0); 607 | 608 | fprintf(stdout, " addr: 0x%08" PRIx64 "\n", param_stack[p_idx++].entry); 609 | } else { 610 | fprintf(stderr, "\n-ap option require THREE arguments: filename, a35/a53/a72, start address in hex\n\n"); 611 | exit(EXIT_FAILURE); 612 | } 613 | break; 614 | case 'l': 615 | fprintf(stdout, "FLAG:\t%s\n", optarg); 616 | param_stack[p_idx].option = FLAG; 617 | param_stack[p_idx++].entry = (uint32_t) strtoll(optarg, NULL, 0); 618 | break; 619 | case 'o': 620 | fprintf(stdout, "Output:\t%s\n", optarg); 621 | ofname = optarg; 622 | output = true; 623 | break; 624 | case 'x': 625 | fprintf(stdout, "SCD:\t%s\n", optarg); 626 | param_stack[p_idx].option = SCD; 627 | param_stack[p_idx++].filename = optarg; 628 | break; 629 | case 'z': 630 | fprintf(stdout, "CSF:\t%s\n", optarg); 631 | param_stack[p_idx].option = CSF; 632 | param_stack[p_idx++].filename = optarg; 633 | break; 634 | case 'e': 635 | fprintf(stdout, "BOOT DEVICE:\t%s\n", optarg); 636 | if (!strcmp(optarg, "flexspi")) { 637 | ivt_offset = IVT_OFFSET_FLEXSPI; 638 | } else if (!strcmp(optarg, "sd")) { 639 | ivt_offset = IVT_OFFSET_SD; 640 | } else if (!strcmp(optarg, "nand")) { 641 | sector_size = 0x8000;/* sector size for NAND */ 642 | } else if (!strcmp(optarg, "emmc_fast")) { 643 | ivt_offset = IVT_OFFSET_EMMC; 644 | emmc_fastboot = true;/* emmc boot */ 645 | } else { 646 | fprintf(stdout, "\n-dev option, Valid boot devices are:\r\n sd\r\nflexspi\r\nnand\n\n"); 647 | exit(EXIT_FAILURE); 648 | } 649 | break; 650 | case 'c': 651 | fprintf(stdout, "New Container: \t%d\n",++container); 652 | param_stack[p_idx++].option = NEW_CONTAINER; 653 | break; 654 | case ':': 655 | fprintf(stderr, "option %c missing arguments\n", optopt); 656 | exit(EXIT_FAILURE); 657 | break; 658 | case 't': 659 | fprintf(stdout, "%08x\n", MKIMAGE_COMMIT); 660 | exit(0); 661 | case '?': 662 | default: 663 | /* invalid option */ 664 | fprintf(stderr, "option '%c' is invalid: ignored\n", 665 | optopt); 666 | exit(EXIT_FAILURE); 667 | } 668 | } 669 | param_stack[p_idx].option = NO_IMG; /* null terminate the img stack */ 670 | 671 | if(soc == NONE){ 672 | fprintf(stderr, " No SOC defined"); 673 | exit(EXIT_FAILURE); 674 | } 675 | 676 | if(container < 0) 677 | { /* check to make sure there is at least 1 container defined */ 678 | fprintf(stderr, " No Container defined"); 679 | exit(EXIT_FAILURE); 680 | } 681 | 682 | if(!(scfw && output)){/* jump out if either scfw or output params are missing */ 683 | fprintf(stderr, "mandatory args scfw and output file name missing! abort\n"); 684 | exit(EXIT_FAILURE); 685 | } 686 | 687 | /* Now begin assembling the image acording to each SOC container */ 688 | 689 | 690 | 691 | switch(soc) 692 | { 693 | case QX: 694 | build_container_qx(sector_size, ivt_offset, ofname, emmc_fastboot, (image_t *) param_stack); 695 | break; 696 | case QM: 697 | build_container_qm(sector_size, ivt_offset, ofname, emmc_fastboot, (image_t *) param_stack); 698 | break; 699 | default: 700 | fprintf(stderr, " unrecognized SOC defined"); 701 | exit(EXIT_FAILURE); 702 | } 703 | 704 | 705 | fprintf(stdout, "DONE.\n"); 706 | fprintf(stdout, "Note: Please copy image to offset: IVT_OFFSET + IMAGE_OFFSET\n"); 707 | 708 | return 0; 709 | } 710 | 711 | --------------------------------------------------------------------------------