]> git.sur5r.net Git - u-boot/commitdiff
Merge branch 'master' of git://git.denx.de/u-boot-video
authorTom Rini <trini@ti.com>
Tue, 10 Feb 2015 15:41:54 +0000 (10:41 -0500)
committerTom Rini <trini@ti.com>
Tue, 10 Feb 2015 15:41:54 +0000 (10:41 -0500)
Conflicts:
include/splash.h

Signed-off-by: Tom Rini <trini@ti.com>
183 files changed:
Kconfig
MAINTAINERS
Makefile
arch/Kconfig
arch/arc/Kconfig
arch/arc/config.mk
arch/arc/cpu/arcv1/config.mk [deleted file]
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/cache.h
arch/arc/include/asm/config.h
arch/arc/lib/Makefile
arch/arc/lib/_millicodethunk.S [new file with mode: 0644]
arch/arc/lib/cache.c
arch/arc/lib/libgcc2.c [new file with mode: 0644]
arch/arc/lib/libgcc2.h [new file with mode: 0644]
arch/arc/lib/memcmp.S
arch/arm/Kconfig
arch/arm/cpu/arm926ejs/mxs/spl_boot.c
arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
arch/arm/cpu/armv7/armada-xp/Makefile
arch/arm/cpu/armv7/armada-xp/lowlevel_spl.S [new file with mode: 0644]
arch/arm/cpu/armv7/armada-xp/spl.c [new file with mode: 0644]
arch/arm/cpu/armv7/mx6/ddr.c
arch/arm/cpu/armv7/mx6/soc.c
arch/arm/cpu/armv7/uniphier/Kconfig
arch/arm/cpu/armv7/uniphier/Makefile
arch/arm/cpu/armv7/uniphier/board_early_init_f.c [new file with mode: 0644]
arch/arm/cpu/armv7/uniphier/board_postclk_init.c [deleted file]
arch/arm/cpu/armv7/uniphier/cmd_pinmon.c
arch/arm/cpu/armv7/uniphier/dram_init.c
arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
arch/arm/cpu/armv7/uniphier/ph1-ld4/board_info.c [deleted file]
arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
arch/arm/cpu/armv7/uniphier/ph1-pro4/board_info.c [deleted file]
arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c
arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
arch/arm/cpu/armv7/uniphier/ph1-sld8/board_info.c [deleted file]
arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c
arch/arm/cpu/armv7/uniphier/print_misc_info.c [new file with mode: 0644]
arch/arm/cpu/armv7/uniphier/spl.c
arch/arm/dts/uniphier-ph1-ld4-ref.dts
arch/arm/dts/uniphier-ph1-pro4-ref.dts
arch/arm/dts/uniphier-ph1-sld3-ref.dts
arch/arm/dts/uniphier-ph1-sld8-ref.dts
arch/arm/dts/uniphier-ref-daughter.dtsi [new file with mode: 0644]
arch/arm/include/asm/arch-armada-xp/config.h
arch/arm/include/asm/arch-armada-xp/cpu.h
arch/arm/include/asm/arch-mx6/imx-regs.h
arch/arm/include/asm/arch-mx6/mx6-ddr.h
arch/arm/include/asm/arch-mxs/sys_proto.h
arch/arm/include/asm/arch-uniphier/boot-device.h
arch/arm/include/asm/arch-uniphier/gpio.h [deleted file]
arch/arm/include/asm/u-boot-arm.h
arch/arm/mvebu-common/Makefile
arch/arm/mvebu-common/serdes/Makefile [new file with mode: 0644]
arch/arm/mvebu-common/serdes/board_env_spec.h [new file with mode: 0644]
arch/arm/mvebu-common/serdes/high_speed_env_lib.c [new file with mode: 0644]
arch/arm/mvebu-common/serdes/high_speed_env_spec.c [new file with mode: 0644]
arch/arm/mvebu-common/serdes/high_speed_env_spec.h [new file with mode: 0644]
arch/arm/mvebu-common/u-boot-spl.lds [new file with mode: 0644]
arch/microblaze/config.mk
arch/microblaze/cpu/exception.c
arch/microblaze/cpu/interrupts.c
arch/microblaze/cpu/irq.S
arch/microblaze/cpu/spl.c
arch/microblaze/cpu/start.S
arch/microblaze/cpu/u-boot-spl.lds
arch/microblaze/cpu/u-boot.lds
arch/microblaze/include/asm/asm.h
arch/microblaze/include/asm/config.h
arch/microblaze/include/asm/microblaze_intc.h
arch/microblaze/include/asm/u-boot.h
arch/microblaze/lib/Makefile
arch/microblaze/lib/board.c [deleted file]
arch/nds32/include/asm/u-boot-nds32.h
arch/sandbox/include/asm/u-boot-sandbox.h
arch/x86/include/asm/u-boot-x86.h
board/Marvell/db-mv784mp-gp/binary.0 [deleted file]
board/Marvell/db-mv784mp-gp/kwbimage.cfg
board/aristainetos/aristainetos.c
board/bachmann/ot1200/Makefile
board/bachmann/ot1200/mx6q_4x_mt41j128.cfg
board/bachmann/ot1200/ot1200.c
board/bachmann/ot1200/ot1200_spl.c [new file with mode: 0644]
board/barco/platinum/Kconfig [new file with mode: 0644]
board/barco/platinum/MAINTAINERS [new file with mode: 0644]
board/barco/platinum/Makefile [new file with mode: 0644]
board/barco/platinum/platinum.c [new file with mode: 0644]
board/barco/platinum/platinum.h [new file with mode: 0644]
board/barco/platinum/platinum_picon.c [new file with mode: 0644]
board/barco/platinum/platinum_titanium.c [new file with mode: 0644]
board/barco/platinum/spl_picon.c [new file with mode: 0644]
board/barco/platinum/spl_titanium.c [new file with mode: 0644]
board/compulab/cm_fx6/cm_fx6.c
board/compulab/cm_t335/cm_t335.c
board/compulab/cm_t35/cm_t35.c
board/compulab/cm_t3517/cm_t3517.c
board/compulab/cm_t54/cm_t54.c
board/compulab/common/Makefile
board/compulab/common/common.h
board/compulab/common/eeprom.c
board/compulab/common/eeprom.h
board/compulab/common/splash.c [deleted file]
board/freescale/mx53loco/imximage.cfg
board/freescale/mx6qsabreauto/mx6qsabreauto.c
board/freescale/mx6sxsabresd/MAINTAINERS
board/freescale/mx6sxsabresd/mx6sxsabresd.c
board/maxbcm/binary.0 [deleted file]
board/maxbcm/kwbimage.cfg
board/maxbcm/maxbcm.c
board/synopsys/Kconfig
board/synopsys/MAINTAINERS
board/xilinx/microblaze-generic/microblaze-generic.c
common/Makefile
common/board_f.c
common/board_r.c
common/cmd_bdinfo.c
common/splash_source.c [new file with mode: 0644]
configs/arcangel4-be_defconfig
configs/arcangel4_defconfig
configs/axs101_defconfig
configs/db-mv784mp-gp_defconfig
configs/maxbcm_defconfig
configs/mx6sxsabresd_spl_defconfig [new file with mode: 0644]
configs/ot1200_spl_defconfig [new file with mode: 0644]
configs/platinum_picon_defconfig [new file with mode: 0644]
configs/platinum_titanium_defconfig [new file with mode: 0644]
configs/tb100_defconfig
doc/README.splashprepare
doc/README.uniphier [new file with mode: 0644]
drivers/ddr/mvebu/Makefile [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_axp.h [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_axp_config.h [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_axp_mc_static.h [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_axp_training_static.h [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_axp_vars.h [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_dfs.c [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_dqs.c [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_hw_training.c [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_hw_training.h [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_init.c [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_init.h [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_patterns_64bit.h [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_pbs.c [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_read_leveling.c [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_sdram.c [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_spd.c [new file with mode: 0644]
drivers/ddr/mvebu/ddr3_write_leveling.c [new file with mode: 0644]
drivers/ddr/mvebu/xor.c [new file with mode: 0644]
drivers/ddr/mvebu/xor.h [new file with mode: 0644]
drivers/ddr/mvebu/xor_regs.h [new file with mode: 0644]
include/common.h
include/configs/arcangel4-be.h [deleted file]
include/configs/arcangel4.h
include/configs/aristainetos.h
include/configs/axs101.h
include/configs/cm_fx6.h
include/configs/cm_t35.h
include/configs/db-mv784mp-gp.h
include/configs/imx6_spl.h
include/configs/maxbcm.h
include/configs/microblaze-generic.h
include/configs/mx6slevk.h
include/configs/mx6sxsabresd.h
include/configs/ot1200.h
include/configs/platinum.h [new file with mode: 0644]
include/configs/platinum_picon.h [new file with mode: 0644]
include/configs/platinum_titanium.h [new file with mode: 0644]
include/configs/sheevaplug.h
include/configs/tb100.h
include/configs/uniphier.h
include/configs/wandboard.h
include/power/pfuze100_pmic.h
include/splash.h
scripts/Makefile.spl
tools/Makefile
tools/imximage.c
tools/imximage.h
tools/kwbimage.c
tools/logos/compulab.bmp [new file with mode: 0644]
tools/mxsboot.c

diff --git a/Kconfig b/Kconfig
index fed488fdaf94212dfce21902d2cf812a827f819e..9af31e3e77a2e36e7b0cd72384b6d4081c132a54 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -139,7 +139,7 @@ config SYS_EXTRA_OPTIONS
          new boards should not use this option.
 
 config SYS_TEXT_BASE
-       depends on SPARC
+       depends on SPARC || ARC
        hex "Text Base"
        help
          TODO: Move CONFIG_SYS_TEXT_BASE for all the architecture
index 1f7735922d6d464476d19dd16419bf8595853829..74a56ecf4ffb88983ad1b0ded502a90169c310d4 100644 (file)
@@ -170,7 +170,7 @@ T:  git git://git.denx.de/u-boot-uniphier.git
 F:     arch/arm/cpu/armv7/uniphier/
 F:     arch/arm/include/asm/arch-uniphier/
 F:     configs/ph1_*_defconfig
-F:     drivers/serial/serial_uniphier.c
+N:     uniphier
 
 ARM ZYNQ
 M:     Michal Simek <monstr@monstr.eu>
index 92faed63fd1208897078d9dc1c88d8fa65e7fc55..76bae8b6d500bb2f5dfb83b0355af3fefbe321cd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -856,12 +856,18 @@ MKIMAGEFLAGS_u-boot.img = -A $(ARCH) -T firmware -C none -O u-boot \
 MKIMAGEFLAGS_u-boot.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \
        -T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
 
+MKIMAGEFLAGS_u-boot-spl.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \
+       -T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
+
 MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
                -R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage
 
 u-boot.img u-boot.kwb u-boot.pbl: u-boot.bin FORCE
        $(call if_changed,mkimage)
 
+u-boot-spl.kwb: u-boot.img spl/u-boot-spl.bin FORCE
+       $(call if_changed,mkimage)
+
 MKIMAGEFLAGS_u-boot-dtb.img = $(MKIMAGEFLAGS_u-boot.img)
 
 u-boot-dtb.img: u-boot-dtb.bin FORCE
index f63cc5a7e9440416c351e612eb5c8615693aa037..132123bcaf1c8da5c2e029508dc3a60dca2e2531 100644 (file)
@@ -4,6 +4,7 @@ choice
 
 config ARC
        bool "ARC architecture"
+       select HAVE_PRIVATE_LIBGCC
 
 config ARM
        bool "ARM architecture"
index c6b1efeb8bf9acb06a8cb66a79a8733c1468ccf3..a8dc4e2336da12aeef0c696be61267688492d925 100644 (file)
@@ -4,9 +4,77 @@ menu "ARC architecture"
 config SYS_ARCH
        default "arc"
 
+config USE_PRIVATE_LIBGCC
+       default y
+
 config SYS_CPU
        default "arcv1"
 
+choice
+       prompt "CPU selection"
+       default CPU_ARC770D
+
+config CPU_ARC750D
+       bool "ARC 750D"
+       select ARC_MMU_V2
+       help
+         Choose this option to build an U-Boot for ARC750D CPU.
+
+config CPU_ARC770D
+       bool "ARC 770D"
+       select ARC_MMU_V3
+       help
+         Choose this option to build an U-Boot for ARC770D CPU.
+
+endchoice
+
+choice
+       prompt "MMU Version"
+       default ARC_MMU_V3 if CPU_ARC770D
+       default ARC_MMU_V2 if CPU_ARC750D
+
+config ARC_MMU_V2
+       bool "MMU v2"
+       depends on CPU_ARC750D
+       help
+         Fixed the deficiency of v1 - possible thrashing in memcpy sceanrio
+         when 2 D-TLB and 1 I-TLB entries index into same 2way set.
+
+config ARC_MMU_V3
+       bool "MMU v3"
+       depends on CPU_ARC770D
+       help
+         Introduced with ARC700 4.10: New Features
+         Variable Page size (1k-16k), var JTLB size 128 x (2 or 4)
+         Shared Address Spaces (SASID)
+
+endchoice
+
+config CPU_BIG_ENDIAN
+       bool "Enable Big Endian Mode"
+       default n
+       help
+         Build kernel for Big Endian Mode of ARC CPU
+
+config SYS_ICACHE_OFF
+       bool "Do not use Instruction Cache"
+       default n
+
+config SYS_DCACHE_OFF
+       bool "Do not use Data Cache"
+       default n
+
+config ARC_CACHE_LINE_SHIFT
+       int "Cache Line Length (as power of 2)"
+       range 5 7
+       default "6"
+       depends on !SYS_DCACHE_OFF || !SYS_DCACHE_OFF
+       help
+         Starting with ARC700 4.9, Cache line length is configurable,
+         This option specifies "N", with Line-len = 2 power N
+         So line lengths of 32, 64, 128 are specified by 5,6,7, respectively
+         Linux only supports same line lengths for I and D caches.
+
 choice
        prompt "Target select"
 
@@ -16,9 +84,6 @@ config TARGET_TB100
 config TARGET_ARCANGEL4
        bool "Support arcangel4"
 
-config TARGET_ARCANGEL4_BE
-       bool "Support arcangel4-be"
-
 config TARGET_AXS101
        bool "Support axs101"
 
index 5321987a566387ffcaeae4c0d51dfa8801f75351..f1e81b689502e94126c74d78c6c6bfa670e5478b 100644 (file)
@@ -4,17 +4,22 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-ifndef CONFIG_SYS_BIG_ENDIAN
+ifndef CONFIG_CPU_BIG_ENDIAN
 CONFIG_SYS_LITTLE_ENDIAN = 1
+else
+CONFIG_SYS_BIG_ENDIAN = 1
 endif
 
 ifdef CONFIG_SYS_LITTLE_ENDIAN
 ARC_CROSS_COMPILE := arc-buildroot-linux-uclibc-
+PLATFORM_LDFLAGS += -EL
+PLATFORM_CPPFLAGS += -mlittle-endian
 endif
 
 ifdef CONFIG_SYS_BIG_ENDIAN
 ARC_CROSS_COMPILE := arceb-buildroot-linux-uclibc-
 PLATFORM_LDFLAGS += -EB
+PLATFORM_CPPFLAGS += -mbig-endian
 endif
 
 ifeq ($(CROSS_COMPILE),)
@@ -25,6 +30,14 @@ ifdef CONFIG_ARC_MMU_VER
 CONFIG_MMU = 1
 endif
 
+ifdef CONFIG_CPU_ARC750D
+PLATFORM_CPPFLAGS += -marc700
+endif
+
+ifdef CONFIG_CPU_ARC770D
+PLATFORM_CPPFLAGS += -marc700 -mlock -mswape
+endif
+
 PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2
 
 # Needed for relocation
diff --git a/arch/arc/cpu/arcv1/config.mk b/arch/arc/cpu/arcv1/config.mk
deleted file mode 100644 (file)
index 3206ff4..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
-#
-# SPDX-License-Identifier:     GPL-2.0+
-#
-
-PLATFORM_CPPFLAGS += -mA7
index 8ace87fa0f25953a910161c8c9eaf4e845822b9f..6a36a81c0f1545680089b9ad3c8d03ace0bff613 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _ASM_ARC_ARCREGS_H
 #define _ASM_ARC_ARCREGS_H
 
+#include <asm/cache.h>
+
 /*
  * ARC architecture has additional address space - auxiliary registers.
  * These registers are mostly used for configuration purposes.
@@ -21,7 +23,7 @@
 #define ARC_AUX_IC_IVIC                0x10
 #define ARC_AUX_IC_CTRL                0x11
 #define ARC_AUX_IC_IVIL                0x19
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
 #define ARC_AUX_IC_PTAG                0x1E
 #endif
 #define ARC_BCR_IC_BUILD       0x77
@@ -40,7 +42,7 @@
 #define ARC_AUX_DC_IVDL                0x4A
 #define ARC_AUX_DC_FLSH                0x4B
 #define ARC_AUX_DC_FLDL                0x4C
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
 #define ARC_AUX_DC_PTAG                0x5C
 #endif
 #define ARC_BCR_DC_BUILD       0x72
index 16e7568ef04bed4f7d51a19dbc269e4d3b950252..27259612217265ae950ec165dc34fab310657ab8 100644 (file)
@@ -9,15 +9,18 @@
 
 #include <config.h>
 
-/*
- * The current upper bound for ARC L1 data cache line sizes is 128 bytes.
- * We use that value for aligning DMA buffers unless the board config has
- * specified an alternate cache line size.
- */
-#ifdef CONFIG_SYS_CACHELINE_SIZE
-#define ARCH_DMA_MINALIGN      CONFIG_SYS_CACHELINE_SIZE
+#ifdef CONFIG_ARC_CACHE_LINE_SHIFT
+#define CONFIG_SYS_CACHELINE_SIZE      (1 << CONFIG_ARC_CACHE_LINE_SHIFT)
+#define ARCH_DMA_MINALIGN              CONFIG_SYS_CACHELINE_SIZE
 #else
-#define ARCH_DMA_MINALIGN      128
+/* Satisfy users of ARCH_DMA_MINALIGN */
+#define ARCH_DMA_MINALIGN              128
+#endif
+
+#if defined(CONFIG_ARC_MMU_V2)
+#define CONFIG_ARC_MMU_VER 2
+#elif defined(CONFIG_ARC_MMU_V3)
+#define CONFIG_ARC_MMU_VER 3
 #endif
 
 #endif /* __ASM_ARC_CACHE_H */
index e5be078c19704776e9cb986d4bf2951e6d5a6335..b4e9099fb165ec14b3815bb062604428c44702f0 100644 (file)
@@ -7,8 +7,10 @@
 #ifndef __ASM_ARC_CONFIG_H_
 #define __ASM_ARC_CONFIG_H_
 
+#define CONFIG_SYS_GENERIC_BOARD
 #define CONFIG_SYS_GENERIC_GLOBAL_DATA
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
+#define CONFIG_ARCH_EARLY_INIT_R
 
 #define CONFIG_LMB
 
index bae44199a41b16c7662607d77bff0715def97b83..b8028c91e11df045b29048521631191fe7cfd180 100644 (file)
@@ -20,3 +20,5 @@ obj-y += reset.o
 obj-y += timer.o
 
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
+
+lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _millicodethunk.o libgcc2.o
diff --git a/arch/arc/lib/_millicodethunk.S b/arch/arc/lib/_millicodethunk.S
new file mode 100644 (file)
index 0000000..b332416
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 1995, 1997, 2007-2013 Free Software Foundation, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+ /* ANSI concatenation macros.  */
+
+ #define CONCAT1(a, b) CONCAT2(a, b)
+ #define CONCAT2(a, b) a ## b
+
+ /* Use the right prefix for global labels.  */
+
+ #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+#ifndef WORKING_ASSEMBLER
+#define abs_l abs
+#define asl_l asl
+#define mov_l mov
+#endif
+
+#define FUNC(X)         .type SYM(X),@function
+#define HIDDEN_FUNC(X) FUNC(X)` .hidden X
+#define ENDFUNC0(X)     .Lfe_##X: .size X,.Lfe_##X-X
+#define ENDFUNC(X)      ENDFUNC0(X)
+
+       .section .text
+       .align 4
+       .global SYM(__st_r13_to_r15)
+       .global SYM(__st_r13_to_r16)
+       .global SYM(__st_r13_to_r17)
+       .global SYM(__st_r13_to_r18)
+       .global SYM(__st_r13_to_r19)
+       .global SYM(__st_r13_to_r20)
+       .global SYM(__st_r13_to_r21)
+       .global SYM(__st_r13_to_r22)
+       .global SYM(__st_r13_to_r23)
+       .global SYM(__st_r13_to_r24)
+       .global SYM(__st_r13_to_r25)
+       HIDDEN_FUNC(__st_r13_to_r15)
+       HIDDEN_FUNC(__st_r13_to_r16)
+       HIDDEN_FUNC(__st_r13_to_r17)
+       HIDDEN_FUNC(__st_r13_to_r18)
+       HIDDEN_FUNC(__st_r13_to_r19)
+       HIDDEN_FUNC(__st_r13_to_r20)
+       HIDDEN_FUNC(__st_r13_to_r21)
+       HIDDEN_FUNC(__st_r13_to_r22)
+       HIDDEN_FUNC(__st_r13_to_r23)
+       HIDDEN_FUNC(__st_r13_to_r24)
+       HIDDEN_FUNC(__st_r13_to_r25)
+       .align 4
+SYM(__st_r13_to_r25):
+       st r25, [sp,48]
+SYM(__st_r13_to_r24):
+       st r24, [sp,44]
+SYM(__st_r13_to_r23):
+       st r23, [sp,40]
+SYM(__st_r13_to_r22):
+       st r22, [sp,36]
+SYM(__st_r13_to_r21):
+       st r21, [sp,32]
+SYM(__st_r13_to_r20):
+       st r20, [sp,28]
+SYM(__st_r13_to_r19):
+       st r19, [sp,24]
+SYM(__st_r13_to_r18):
+       st r18, [sp,20]
+SYM(__st_r13_to_r17):
+       st r17, [sp,16]
+SYM(__st_r13_to_r16):
+       st r16, [sp,12]
+SYM(__st_r13_to_r15):
+#ifdef __ARC700__
+       st r15, [sp,8] ; minimum function size to avoid stall: 6 bytes.
+#else
+       st_s r15, [sp,8]
+#endif
+       st_s r14, [sp,4]
+       j_s.d [%blink]
+       st_s r13, [sp,0]
+       ENDFUNC(__st_r13_to_r15)
+       ENDFUNC(__st_r13_to_r16)
+       ENDFUNC(__st_r13_to_r17)
+       ENDFUNC(__st_r13_to_r18)
+       ENDFUNC(__st_r13_to_r19)
+       ENDFUNC(__st_r13_to_r20)
+       ENDFUNC(__st_r13_to_r21)
+       ENDFUNC(__st_r13_to_r22)
+       ENDFUNC(__st_r13_to_r23)
+       ENDFUNC(__st_r13_to_r24)
+       ENDFUNC(__st_r13_to_r25)
+
+       .section .text
+       .align 4
+;      ==================================
+;      the loads
+
+       .global SYM(__ld_r13_to_r15)
+       .global SYM(__ld_r13_to_r16)
+       .global SYM(__ld_r13_to_r17)
+       .global SYM(__ld_r13_to_r18)
+       .global SYM(__ld_r13_to_r19)
+       .global SYM(__ld_r13_to_r20)
+       .global SYM(__ld_r13_to_r21)
+       .global SYM(__ld_r13_to_r22)
+       .global SYM(__ld_r13_to_r23)
+       .global SYM(__ld_r13_to_r24)
+       .global SYM(__ld_r13_to_r25)
+       HIDDEN_FUNC(__ld_r13_to_r15)
+       HIDDEN_FUNC(__ld_r13_to_r16)
+       HIDDEN_FUNC(__ld_r13_to_r17)
+       HIDDEN_FUNC(__ld_r13_to_r18)
+       HIDDEN_FUNC(__ld_r13_to_r19)
+       HIDDEN_FUNC(__ld_r13_to_r20)
+       HIDDEN_FUNC(__ld_r13_to_r21)
+       HIDDEN_FUNC(__ld_r13_to_r22)
+       HIDDEN_FUNC(__ld_r13_to_r23)
+       HIDDEN_FUNC(__ld_r13_to_r24)
+       HIDDEN_FUNC(__ld_r13_to_r25)
+SYM(__ld_r13_to_r25):
+       ld r25, [sp,48]
+SYM(__ld_r13_to_r24):
+       ld r24, [sp,44]
+SYM(__ld_r13_to_r23):
+       ld r23, [sp,40]
+SYM(__ld_r13_to_r22):
+       ld r22, [sp,36]
+SYM(__ld_r13_to_r21):
+       ld r21, [sp,32]
+SYM(__ld_r13_to_r20):
+       ld r20, [sp,28]
+SYM(__ld_r13_to_r19):
+       ld r19, [sp,24]
+SYM(__ld_r13_to_r18):
+       ld r18, [sp,20]
+SYM(__ld_r13_to_r17):
+       ld r17, [sp,16]
+SYM(__ld_r13_to_r16):
+       ld r16, [sp,12]
+SYM(__ld_r13_to_r15):
+#ifdef __ARC700__
+       ld r15, [sp,8] ; minimum function size to avoid stall: 6 bytes.
+#else
+       ld_s r15, [sp,8]
+#endif
+       ld_s r14, [sp,4]
+       j_s.d [%blink]
+       ld_s r13, [sp,0]
+       ENDFUNC(__ld_r13_to_r15)
+       ENDFUNC(__ld_r13_to_r16)
+       ENDFUNC(__ld_r13_to_r17)
+       ENDFUNC(__ld_r13_to_r18)
+       ENDFUNC(__ld_r13_to_r19)
+       ENDFUNC(__ld_r13_to_r20)
+       ENDFUNC(__ld_r13_to_r21)
+       ENDFUNC(__ld_r13_to_r22)
+       ENDFUNC(__ld_r13_to_r23)
+       ENDFUNC(__ld_r13_to_r24)
+       ENDFUNC(__ld_r13_to_r25)
+
+       .global SYM(__ld_r13_to_r14_ret)
+       .global SYM(__ld_r13_to_r15_ret)
+       .global SYM(__ld_r13_to_r16_ret)
+       .global SYM(__ld_r13_to_r17_ret)
+       .global SYM(__ld_r13_to_r18_ret)
+       .global SYM(__ld_r13_to_r19_ret)
+       .global SYM(__ld_r13_to_r20_ret)
+       .global SYM(__ld_r13_to_r21_ret)
+       .global SYM(__ld_r13_to_r22_ret)
+       .global SYM(__ld_r13_to_r23_ret)
+       .global SYM(__ld_r13_to_r24_ret)
+       .global SYM(__ld_r13_to_r25_ret)
+       HIDDEN_FUNC(__ld_r13_to_r14_ret)
+       HIDDEN_FUNC(__ld_r13_to_r15_ret)
+       HIDDEN_FUNC(__ld_r13_to_r16_ret)
+       HIDDEN_FUNC(__ld_r13_to_r17_ret)
+       HIDDEN_FUNC(__ld_r13_to_r18_ret)
+       HIDDEN_FUNC(__ld_r13_to_r19_ret)
+       HIDDEN_FUNC(__ld_r13_to_r20_ret)
+       HIDDEN_FUNC(__ld_r13_to_r21_ret)
+       HIDDEN_FUNC(__ld_r13_to_r22_ret)
+       HIDDEN_FUNC(__ld_r13_to_r23_ret)
+       HIDDEN_FUNC(__ld_r13_to_r24_ret)
+       HIDDEN_FUNC(__ld_r13_to_r25_ret)
+       .section .text
+       .align 4
+SYM(__ld_r13_to_r25_ret):
+       ld r25, [sp,48]
+SYM(__ld_r13_to_r24_ret):
+       ld r24, [sp,44]
+SYM(__ld_r13_to_r23_ret):
+       ld r23, [sp,40]
+SYM(__ld_r13_to_r22_ret):
+       ld r22, [sp,36]
+SYM(__ld_r13_to_r21_ret):
+       ld r21, [sp,32]
+SYM(__ld_r13_to_r20_ret):
+       ld r20, [sp,28]
+SYM(__ld_r13_to_r19_ret):
+       ld r19, [sp,24]
+SYM(__ld_r13_to_r18_ret):
+       ld r18, [sp,20]
+SYM(__ld_r13_to_r17_ret):
+       ld r17, [sp,16]
+SYM(__ld_r13_to_r16_ret):
+       ld r16, [sp,12]
+SYM(__ld_r13_to_r15_ret):
+       ld r15, [sp,8]
+SYM(__ld_r13_to_r14_ret):
+       ld blink,[sp,r12]
+       ld_s r14, [sp,4]
+       ld.ab r13, [sp,r12]
+       j_s.d [%blink]
+       add_s sp,sp,4
+       ENDFUNC(__ld_r13_to_r14_ret)
+       ENDFUNC(__ld_r13_to_r15_ret)
+       ENDFUNC(__ld_r13_to_r16_ret)
+       ENDFUNC(__ld_r13_to_r17_ret)
+       ENDFUNC(__ld_r13_to_r18_ret)
+       ENDFUNC(__ld_r13_to_r19_ret)
+       ENDFUNC(__ld_r13_to_r20_ret)
+       ENDFUNC(__ld_r13_to_r21_ret)
+       ENDFUNC(__ld_r13_to_r22_ret)
+       ENDFUNC(__ld_r13_to_r23_ret)
+       ENDFUNC(__ld_r13_to_r24_ret)
+       ENDFUNC(__ld_r13_to_r25_ret)
index fa19a13b7e698f49384683423b157a55557ffb17..a2277231ba127ad2d03eb8a5ffcc5439d6223aa7 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <config.h>
 #include <asm/arcregs.h>
+#include <asm/cache.h>
 
 /* Bit values in IC_CTRL */
 #define IC_CTRL_CACHE_DISABLE  (1 << 0)
@@ -101,7 +102,7 @@ void flush_dcache_all(void)
 #ifndef CONFIG_SYS_DCACHE_OFF
 static void dcache_flush_line(unsigned addr)
 {
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
        write_aux_reg(ARC_AUX_DC_PTAG, addr);
 #endif
        write_aux_reg(ARC_AUX_DC_FLDL, addr);
@@ -115,7 +116,7 @@ static void dcache_flush_line(unsigned addr)
         * Invalidate I$ for addresses range just flushed from D$.
         * If we try to execute data flushed above it will be valid/correct
         */
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
        write_aux_reg(ARC_AUX_IC_PTAG, addr);
 #endif
        write_aux_reg(ARC_AUX_IC_IVIL, addr);
@@ -145,7 +146,7 @@ void invalidate_dcache_range(unsigned long start, unsigned long end)
        end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1));
 
        for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) {
-#if (CONFIG_ARC_MMU_VER > 2)
+#if (CONFIG_ARC_MMU_VER == 3)
                write_aux_reg(ARC_AUX_DC_PTAG, addr);
 #endif
                write_aux_reg(ARC_AUX_DC_IVDL, addr);
diff --git a/arch/arc/lib/libgcc2.c b/arch/arc/lib/libgcc2.c
new file mode 100644 (file)
index 0000000..d5ad327
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 1989-2013 Free Software Foundation, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include "libgcc2.h"
+
+DWtype
+__ashldi3(DWtype u, shift_count_type b)
+{
+       if (b == 0)
+               return u;
+
+       const DWunion uu = {.ll = u};
+       const shift_count_type bm = W_TYPE_SIZE - b;
+       DWunion w;
+
+       if (bm <= 0) {
+               w.s.low = 0;
+               w.s.high = (UWtype)uu.s.low << -bm;
+       } else {
+               const UWtype carries = (UWtype) uu.s.low >> bm;
+
+               w.s.low = (UWtype)uu.s.low << b;
+               w.s.high = ((UWtype)uu.s.high << b) | carries;
+       }
+
+       return w.ll;
+}
+
+DWtype
+__ashrdi3(DWtype u, shift_count_type b)
+{
+       if (b == 0)
+               return u;
+
+       const DWunion uu = {.ll = u};
+       const shift_count_type bm = W_TYPE_SIZE - b;
+       DWunion w;
+
+       if (bm <= 0) {
+               /* w.s.high = 1..1 or 0..0 */
+               w.s.high = uu.s.high >> (W_TYPE_SIZE - 1);
+               w.s.low = uu.s.high >> -bm;
+       } else {
+               const UWtype carries = (UWtype) uu.s.high << bm;
+
+               w.s.high = uu.s.high >> b;
+               w.s.low = ((UWtype)uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+DWtype
+__lshrdi3(DWtype u, shift_count_type b)
+{
+       if (b == 0)
+               return u;
+
+       const DWunion uu = {.ll = u};
+       const shift_count_type bm = W_TYPE_SIZE - b;
+       DWunion w;
+
+       if (bm <= 0) {
+               w.s.high = 0;
+               w.s.low = (UWtype)uu.s.high >> -bm;
+       } else {
+               const UWtype carries = (UWtype)uu.s.high << bm;
+
+               w.s.high = (UWtype)uu.s.high >> b;
+               w.s.low = ((UWtype)uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+unsigned long
+udivmodsi4(unsigned long num, unsigned long den, int modwanted)
+{
+       unsigned long bit = 1;
+       unsigned long res = 0;
+
+       while (den < num && bit && !(den & (1L<<31))) {
+               den <<= 1;
+               bit <<= 1;
+       }
+
+       while (bit) {
+               if (num >= den) {
+                       num -= den;
+                       res |= bit;
+               }
+               bit >>= 1;
+               den >>= 1;
+       }
+
+       if (modwanted)
+               return num;
+
+       return res;
+}
+
+long
+__divsi3(long a, long b)
+{
+       int neg = 0;
+       long res;
+
+       if (a < 0) {
+               a = -a;
+               neg = !neg;
+       }
+
+       if (b < 0) {
+               b = -b;
+               neg = !neg;
+       }
+
+       res = udivmodsi4(a, b, 0);
+
+       if (neg)
+               res = -res;
+
+       return res;
+}
+
+long
+__modsi3(long a, long b)
+{
+       int neg = 0;
+       long res;
+
+       if (a < 0) {
+               a = -a;
+               neg = 1;
+       }
+
+       if (b < 0)
+               b = -b;
+
+       res = udivmodsi4(a, b, 1);
+
+       if (neg)
+               res = -res;
+
+       return res;
+}
+
+long
+__udivsi3(long a, long b)
+{
+       return udivmodsi4(a, b, 0);
+}
+
+long
+__umodsi3(long a, long b)
+{
+       return udivmodsi4(a, b, 1);
+}
diff --git a/arch/arc/lib/libgcc2.h b/arch/arc/lib/libgcc2.h
new file mode 100644 (file)
index 0000000..8813c3b
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 1989-2013 Free Software Foundation, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#define UNITS_PER_WORD 4       /* for ARC */
+#define BITS_PER_UNIT 8                /* for ARC */
+
+#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
+
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+
+/* Work out the largest "word" size that we can deal with on this target.  */
+#if MIN_UNITS_PER_WORD > 4
+# define LIBGCC2_MAX_UNITS_PER_WORD 8
+#elif (MIN_UNITS_PER_WORD > 2 \
+       || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4))
+# define LIBGCC2_MAX_UNITS_PER_WORD 4
+#else
+# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
+#endif
+
+/* Work out what word size we are using for this compilation.
+   The value can be set on the command line.  */
+#ifndef LIBGCC2_UNITS_PER_WORD
+#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
+#endif
+
+typedef                 int QItype     __attribute__ ((mode (QI)));
+typedef unsigned int UQItype   __attribute__ ((mode (QI)));
+typedef                 int HItype     __attribute__ ((mode (HI)));
+typedef unsigned int UHItype   __attribute__ ((mode (HI)));
+#if MIN_UNITS_PER_WORD > 1
+/* These typedefs are usually forbidden on dsp's with UNITS_PER_WORD 1.  */
+typedef         int SItype     __attribute__ ((mode (SI)));
+typedef unsigned int USItype   __attribute__ ((mode (SI)));
+#if __SIZEOF_LONG_LONG__ > 4
+/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 2.  */
+typedef                 int DItype     __attribute__ ((mode (DI)));
+typedef unsigned int UDItype   __attribute__ ((mode (DI)));
+#if MIN_UNITS_PER_WORD > 4
+/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 4.  */
+typedef                 int TItype     __attribute__ ((mode (TI)));
+typedef unsigned int UTItype   __attribute__ ((mode (TI)));
+#endif
+#endif
+#endif
+
+#if LIBGCC2_UNITS_PER_WORD == 8
+#define W_TYPE_SIZE (8 * BITS_PER_UNIT)
+#define Wtype  DItype
+#define UWtype UDItype
+#define HWtype DItype
+#define UHWtype        UDItype
+#define DWtype TItype
+#define UDWtype        UTItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)      __gnu_ ## a ## di ## b
+#define __NDW(a,b)     __gnu_ ## a ## ti ## b
+#else
+#define __NW(a,b)      __ ## a ## di ## b
+#define __NDW(a,b)     __ ## a ## ti ## b
+#endif
+#elif LIBGCC2_UNITS_PER_WORD == 4
+#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
+#define Wtype  SItype
+#define UWtype USItype
+#define HWtype SItype
+#define UHWtype        USItype
+#define DWtype DItype
+#define UDWtype        UDItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)      __gnu_ ## a ## si ## b
+#define __NDW(a,b)     __gnu_ ## a ## di ## b
+#else
+#define __NW(a,b)      __ ## a ## si ## b
+#define __NDW(a,b)     __ ## a ## di ## b
+#endif
+#elif LIBGCC2_UNITS_PER_WORD == 2
+#define W_TYPE_SIZE (2 * BITS_PER_UNIT)
+#define Wtype  HItype
+#define UWtype UHItype
+#define HWtype HItype
+#define UHWtype        UHItype
+#define DWtype SItype
+#define UDWtype        USItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)      __gnu_ ## a ## hi ## b
+#define __NDW(a,b)     __gnu_ ## a ## si ## b
+#else
+#define __NW(a,b)      __ ## a ## hi ## b
+#define __NDW(a,b)     __ ## a ## si ## b
+#endif
+#else
+#define W_TYPE_SIZE BITS_PER_UNIT
+#define Wtype  QItype
+#define UWtype  UQItype
+#define HWtype QItype
+#define UHWtype        UQItype
+#define DWtype HItype
+#define UDWtype        UHItype
+#ifdef LIBGCC2_GNU_PREFIX
+#define __NW(a,b)      __gnu_ ## a ## qi ## b
+#define __NDW(a,b)     __gnu_ ## a ## hi ## b
+#else
+#define __NW(a,b)      __ ## a ## qi ## b
+#define __NDW(a,b)     __ ## a ## hi ## b
+#endif
+#endif
+
+typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
+
+#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
+       struct DWstruct {Wtype high, low;};
+#else
+       struct DWstruct {Wtype low, high;};
+#endif
+
+/* We need this union to unpack/pack DImode values, since we don't have
+   any arithmetic yet.  Incoming DImode parameters are stored into the
+   `ll' field, and the unpacked result is read from the struct `s'.  */
+
+typedef union {
+       struct DWstruct s;
+       DWtype ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
index fa5aac5f6743ee83a2f7a79e8a84811710ea2127..87bccab51d74c92f0239237cfe12eefa2c6864c6 100644 (file)
@@ -29,6 +29,7 @@ memcmp:
        ld.a    %r4, [%r0, 8]
        ld.a    %r5, [%r1, 8]
        brne    WORD2, %r12, .Lodd
+       nop
 .Loop_end:
        asl_s   SHIFT, SHIFT, 3
        bhs_s   .Last_cmp
@@ -105,6 +106,7 @@ memcmp:
        ldb.a   %r4, [%r0, 2]
        ldb.a   %r5, [%r1, 2]
        brne    %r3, %r12, .Lbyte_odd
+       nop
 .Lbyte_end:
        bcc     .Lbyte_even
        brne    %r4, %r5, .Lbyte_even
index 986b4c5d81db1009110eafb2c4606c79675c03a7..2a83f265a710b74824df68c76d797329446e5083 100644 (file)
@@ -236,10 +236,12 @@ config KIRKWOOD
 config TARGET_DB_MV784MP_GP
        bool "Support db-mv784mp-gp"
        select CPU_V7
+       select SUPPORT_SPL
 
 config TARGET_MAXBCM
        bool "Support maxbcm"
        select CPU_V7
+       select SUPPORT_SPL
 
 config TARGET_DEVKIT3250
        bool "Support devkit3250"
@@ -644,6 +646,7 @@ config TARGET_MX6SLEVK
 config TARGET_MX6SXSABRESD
        bool "Support mx6sxsabresd"
        select CPU_V7
+       select SUPPORT_SPL
 
 config TARGET_GW_VENTANA
        bool "Support gw_ventana"
@@ -670,6 +673,17 @@ config TARGET_TQMA6
 config TARGET_OT1200
        bool "Bachmann OT1200"
        select CPU_V7
+       select SUPPORT_SPL
+
+config TARGET_PLATINUM_PICON
+       bool "Support platinum-picon"
+       select CPU_V7
+       select SUPPORT_SPL
+
+config TARGET_PLATINUM_TITANIUM
+       bool "Support platinum-titanium"
+       select CPU_V7
+       select SUPPORT_SPL
 
 config OMAP34XX
        bool "OMAP34XX SoC"
@@ -885,6 +899,7 @@ source "board/atmel/sama5d4_xplained/Kconfig"
 source "board/atmel/sama5d4ek/Kconfig"
 source "board/bachmann/ot1200/Kconfig"
 source "board/balloon3/Kconfig"
+source "board/barco/platinum/Kconfig"
 source "board/barco/titanium/Kconfig"
 source "board/bluegiga/apx4devkit/Kconfig"
 source "board/bluewater/snapper9260/Kconfig"
index d29b9aaf3da576889bfb02620e8e7aeb106b8db7..d7956e57de213819ff313b10045c66e5370bbee9 100644 (file)
@@ -147,6 +147,7 @@ void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr,
        mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
 
        mxs_spl_console_init();
+       debug("SPL: Serial Console Initialised\n");
 
        mxs_power_init();
 
@@ -156,6 +157,11 @@ void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr,
        data->boot_mode_idx = bootmode;
 
        mxs_power_wait_pswitch();
+
+       if (mxs_boot_modes[data->boot_mode_idx].boot_pads == MXS_BM_JTAG) {
+               debug("SPL: Waiting for JTAG user\n");
+               asm volatile ("x: b x");
+       }
 }
 
 /* Support aparatus */
index cdfcddd824ff4d42c02d89193a449f22c9ee6196..96bd32f8adac9106584dcdb04d7ac251ed8368a0 100644 (file)
@@ -18,6 +18,8 @@ void mxs_lradc_init(void)
 {
        struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE;
 
+       debug("SPL: Initialisating LRADC\n");
+
        writel(LRADC_CTRL0_SFTRST, &regs->hw_lradc_ctrl0_clr);
        writel(LRADC_CTRL0_CLKGATE, &regs->hw_lradc_ctrl0_clr);
        writel(LRADC_CTRL0_ONCHIP_GROUNDREF, &regs->hw_lradc_ctrl0_clr);
@@ -37,9 +39,15 @@ void mxs_lradc_enable_batt_measurement(void)
 {
        struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE;
 
+       debug("SPL: Enabling LRADC battery measurement\n");
+
        /* Check if the channel is present at all. */
-       if (!(readl(&regs->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT))
+       if (!(readl(&regs->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT)) {
+               debug("SPL: LRADC channel 7 is not present - aborting\n");
                return;
+       }
+
+       debug("SPL: LRADC channel 7 is present - configuring\n");
 
        writel(LRADC_CTRL1_LRADC7_IRQ_EN, &regs->hw_lradc_ctrl1_clr);
        writel(LRADC_CTRL1_LRADC7_IRQ, &regs->hw_lradc_ctrl1_clr);
@@ -65,6 +73,7 @@ void mxs_lradc_enable_batt_measurement(void)
                100, &regs->hw_lradc_delay3);
 
        writel(0xffffffff, &regs->hw_lradc_ch7_clr);
-
        writel(LRADC_DELAY_KICK, &regs->hw_lradc_delay3_set);
+
+       debug("SPL: LRADC channel 7 configuration complete\n");
 }
index 97ef67d8c5843b06fcd6c7d903cd3d4cb21d976b..a744e5d4990a9c4776080293781393257df4bac5 100644 (file)
@@ -92,6 +92,7 @@ static uint32_t dram_vals[] = {
 
 __weak void mxs_adjust_memory_params(uint32_t *dram_vals)
 {
+       debug("SPL: Using default SDRAM parameters\n");
 }
 
 #ifdef CONFIG_MX28
@@ -99,8 +100,10 @@ static void initialize_dram_values(void)
 {
        int i;
 
+       debug("SPL: Setting mx28 board specific SDRAM parameters\n");
        mxs_adjust_memory_params(dram_vals);
 
+       debug("SPL: Applying SDRAM parameters\n");
        for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
                writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
 }
@@ -109,6 +112,7 @@ static void initialize_dram_values(void)
 {
        int i;
 
+       debug("SPL: Setting mx23 board specific SDRAM parameters\n");
        mxs_adjust_memory_params(dram_vals);
 
        /*
@@ -120,6 +124,7 @@ static void initialize_dram_values(void)
         * HW_DRAM_CTL8 is setup as the last element.
         * So skip the initialization of these HW_DRAM_CTL registers.
         */
+       debug("SPL: Applying SDRAM parameters\n");
        for (i = 0; i < ARRAY_SIZE(dram_vals); i++) {
                if (i == 8 || i == 27 || i == 28 || i == 35)
                        continue;
@@ -146,6 +151,8 @@ static void mxs_mem_init_clock(void)
        const unsigned char divider = 21;
 #endif
 
+       debug("SPL: Initialising FRAC0\n");
+
        /* Gate EMI clock */
        writeb(CLKCTRL_FRAC_CLKGATE,
                &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]);
@@ -170,6 +177,7 @@ static void mxs_mem_init_clock(void)
                &clkctrl_regs->hw_clkctrl_clkseq_clr);
 
        early_delay(10000);
+       debug("SPL: FRAC0 Initialised\n");
 }
 
 static void mxs_mem_setup_cpu_and_hbus(void)
@@ -177,6 +185,8 @@ static void mxs_mem_setup_cpu_and_hbus(void)
        struct mxs_clkctrl_regs *clkctrl_regs =
                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
+       debug("SPL: Setting CPU and HBUS clock frequencies\n");
+
        /* Set fractional divider for ref_cpu to 480 * 18 / 19 = 454MHz
         * and ungate CPU clock */
        writeb(19 & CLKCTRL_FRAC_FRAC_MASK,
@@ -209,6 +219,8 @@ static void mxs_mem_setup_vdda(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Configuring VDDA\n");
+
        writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
                (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
                POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
@@ -240,6 +252,8 @@ static void mx23_mem_setup_vddmem(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Setting mx23 VDDMEM\n");
+
        /* We must wait before and after disabling the current limiter! */
        early_delay(10000);
 
@@ -252,6 +266,8 @@ static void mx23_mem_setup_vddmem(void)
 
 static void mx23_mem_init(void)
 {
+       debug("SPL: Initialising mx23 SDRAM Controller\n");
+
        /*
         * Reset/ungate the EMI block. This is essential, otherwise the system
         * suffers from memory instability. This thing is mx23 specific and is
@@ -297,6 +313,8 @@ static void mx28_mem_init(void)
        struct mxs_pinctrl_regs *pinctrl_regs =
                (struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE;
 
+       debug("SPL: Initialising mx28 SDRAM Controller\n");
+
        /* Set DDR2 mode */
        writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
                &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
index 1c54ab7de3bfc3726b1c823e47500a462607b1a4..c342217fa9185087d3e6a0866ad3c68e1ddc0abd 100644 (file)
 
 #include "mxs_init.h"
 
+#ifdef CONFIG_SYS_MXS_VDD5V_ONLY
+#define DCDC4P2_DROPOUT_CONFIG POWER_DCDC4P2_DROPOUT_CTRL_100MV | \
+                               POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2
+#else
+#define DCDC4P2_DROPOUT_CONFIG POWER_DCDC4P2_DROPOUT_CTRL_100MV | \
+                               POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL
+#endif
 /**
  * mxs_power_clock2xtal() - Switch CPU core clock source to 24MHz XTAL
  *
@@ -26,6 +33,8 @@ static void mxs_power_clock2xtal(void)
        struct mxs_clkctrl_regs *clkctrl_regs =
                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
+       debug("SPL: Switching CPU clock to 24MHz XTAL\n");
+
        /* Set XTAL as CPU reference clock */
        writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
                &clkctrl_regs->hw_clkctrl_clkseq_set);
@@ -43,9 +52,23 @@ static void mxs_power_clock2pll(void)
        struct mxs_clkctrl_regs *clkctrl_regs =
                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
 
+       debug("SPL: Switching CPU core clock source to PLL\n");
+
+       /*
+        * TODO: Are we really? It looks like we turn on PLL0, but we then
+        * set the CLKCTRL_CLKSEQ_BYPASS_CPU bit of the (which was already
+        * set by mxs_power_clock2xtal()). Clearing this bit here seems to
+        * introduce some instability (causing the CPU core to hang). Maybe
+        * we aren't giving PLL0 enough time to stabilise?
+        */
        setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
                        CLKCTRL_PLL0CTRL0_POWER);
        early_delay(100);
+
+       /*
+        * TODO: Should the PLL0 FORCE_LOCK bit be set here followed be a
+        * wait on the PLL0 LOCK bit?
+        */
        setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
                        CLKCTRL_CLKSEQ_BYPASS_CPU);
 }
@@ -62,6 +85,8 @@ static void mxs_power_set_auto_restart(void)
        struct mxs_rtc_regs *rtc_regs =
                (struct mxs_rtc_regs *)MXS_RTC_BASE;
 
+       debug("SPL: Setting auto-restart bit\n");
+
        writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr);
        while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST)
                ;
@@ -101,14 +126,17 @@ static void mxs_power_set_linreg(void)
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
        /* Set linear regulator 25mV below switching converter */
+       debug("SPL: Setting VDDD 25mV below DC-DC converters\n");
        clrsetbits_le32(&power_regs->hw_power_vdddctrl,
                        POWER_VDDDCTRL_LINREG_OFFSET_MASK,
                        POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
 
+       debug("SPL: Setting VDDA 25mV below DC-DC converters\n");
        clrsetbits_le32(&power_regs->hw_power_vddactrl,
                        POWER_VDDACTRL_LINREG_OFFSET_MASK,
                        POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW);
 
+       debug("SPL: Setting VDDIO 25mV below DC-DC converters\n");
        clrsetbits_le32(&power_regs->hw_power_vddioctrl,
                        POWER_VDDIOCTRL_LINREG_OFFSET_MASK,
                        POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
@@ -127,6 +155,8 @@ static int mxs_get_batt_volt(void)
        volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
        volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
        volt *= 8;
+
+       debug("SPL: Battery Voltage = %dmV\n", volt);
        return volt;
 }
 
@@ -154,8 +184,10 @@ static int mxs_is_batt_good(void)
                (struct mxs_power_regs *)MXS_POWER_BASE;
        uint32_t volt = mxs_get_batt_volt();
 
-       if ((volt >= 2400) && (volt <= 4300))
+       if ((volt >= 2400) && (volt <= 4300)) {
+               debug("SPL: Battery is good\n");
                return 1;
+       }
 
        clrsetbits_le32(&power_regs->hw_power_5vctrl,
                POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
@@ -175,16 +207,21 @@ static int mxs_is_batt_good(void)
 
        volt = mxs_get_batt_volt();
 
-       if (volt >= 3500)
+       if (volt >= 3500) {
+               debug("SPL: Battery Voltage too high\n");
                return 0;
+       }
 
-       if (volt >= 2400)
+       if (volt >= 2400) {
+               debug("SPL: Battery is good\n");
                return 1;
+       }
 
        writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
                &power_regs->hw_power_charge_clr);
        writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
 
+       debug("SPL: Battery Voltage too low\n");
        return 0;
 }
 
@@ -203,6 +240,7 @@ static void mxs_power_setup_5v_detect(void)
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
        /* Start 5V detection */
+       debug("SPL: Starting 5V input detection comparator\n");
        clrsetbits_le32(&power_regs->hw_power_5vctrl,
                        POWER_5VCTRL_VBUSVALID_TRSH_MASK,
                        POWER_5VCTRL_VBUSVALID_TRSH_4V4 |
@@ -220,6 +258,8 @@ static void mxs_src_power_init(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Pre-Configuring power block\n");
+
        /* Improve efficieny and reduce transient ripple */
        writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST |
                POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set);
@@ -257,6 +297,8 @@ static void mxs_power_init_4p2_params(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Configuring common 4P2 regulator params\n");
+
        /* Setup 4P2 parameters */
        clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
                POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK,
@@ -268,8 +310,7 @@ static void mxs_power_init_4p2_params(void)
 
        clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
                POWER_DCDC4P2_DROPOUT_CTRL_MASK,
-               POWER_DCDC4P2_DROPOUT_CTRL_100MV |
-               POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL);
+               DCDC4P2_DROPOUT_CONFIG);
 
        clrsetbits_le32(&power_regs->hw_power_5vctrl,
                POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
@@ -289,6 +330,8 @@ static void mxs_enable_4p2_dcdc_input(int xfer)
        uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo;
        uint32_t prev_5v_brnout, prev_5v_droop;
 
+       debug("SPL: %s 4P2 DC-DC Input\n", xfer ? "Enabling" : "Disabling");
+
        prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) &
                                POWER_5VCTRL_PWDN_5VBRNOUT;
        prev_5v_droop = readl(&power_regs->hw_power_ctrl) &
@@ -390,6 +433,8 @@ static void mxs_power_init_4p2_regulator(void)
                (struct mxs_power_regs *)MXS_POWER_BASE;
        uint32_t tmp, tmp2;
 
+       debug("SPL: Enabling 4P2 regulator\n");
+
        setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2);
 
        writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set);
@@ -407,6 +452,7 @@ static void mxs_power_init_4p2_regulator(void)
         * gradually to avoid large inrush current from the 5V cable which can
         * cause transients/problems
         */
+       debug("SPL: Charging 4P2 capacitor\n");
        mxs_enable_4p2_dcdc_input(0);
 
        if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) {
@@ -420,6 +466,8 @@ static void mxs_power_init_4p2_regulator(void)
                        POWER_DCDC4P2_ENABLE_DCDC);
                writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
                        &power_regs->hw_power_5vctrl_set);
+
+               debug("SPL: Unable to recover from mx23 errata 5837\n");
                hang();
        }
 
@@ -433,6 +481,7 @@ static void mxs_power_init_4p2_regulator(void)
         * current limit until the brownout status is false or until we've
         * reached our maximum defined 4p2 current limit.
         */
+       debug("SPL: Setting 4P2 brownout level\n");
        clrsetbits_le32(&power_regs->hw_power_dcdc4p2,
                        POWER_DCDC4P2_BO_MASK,
                        22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */
@@ -479,8 +528,11 @@ static void mxs_power_init_dcdc_4p2_source(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Switching DC-DC converters to 4P2\n");
+
        if (!(readl(&power_regs->hw_power_dcdc4p2) &
                POWER_DCDC4P2_ENABLE_DCDC)) {
+               debug("SPL: Already switched - aborting\n");
                hang();
        }
 
@@ -509,6 +561,8 @@ static void mxs_power_enable_4p2(void)
        uint32_t vdddctrl, vddactrl, vddioctrl;
        uint32_t tmp;
 
+       debug("SPL: Powering up 4P2 regulator\n");
+
        vdddctrl = readl(&power_regs->hw_power_vdddctrl);
        vddactrl = readl(&power_regs->hw_power_vddactrl);
        vddioctrl = readl(&power_regs->hw_power_vddioctrl);
@@ -559,6 +613,8 @@ static void mxs_power_enable_4p2(void)
        if (tmp)
                writel(POWER_CHARGE_ENABLE_LOAD,
                        &power_regs->hw_power_charge_clr);
+
+       debug("SPL: 4P2 regulator powered-up\n");
 }
 
 /**
@@ -574,6 +630,8 @@ static void mxs_boot_valid_5v(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Booting from 5V supply\n");
+
        /*
         * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V
         * disconnect event. FIXME
@@ -601,6 +659,9 @@ static void mxs_powerdown(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
+
+       debug("Powering Down\n");
+
        writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset);
        writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF,
                &power_regs->hw_power_reset);
@@ -617,6 +678,8 @@ static void mxs_batt_boot(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Configuring power block to boot from battery\n");
+
        clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
        clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
 
@@ -672,6 +735,8 @@ static void mxs_handle_5v_conflict(void)
                (struct mxs_power_regs *)MXS_POWER_BASE;
        uint32_t tmp;
 
+       debug("SPL: Resolving 5V conflict\n");
+
        setbits_le32(&power_regs->hw_power_vddioctrl,
                        POWER_VDDIOCTRL_BO_OFFSET_MASK);
 
@@ -683,19 +748,27 @@ static void mxs_handle_5v_conflict(void)
                         * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes
                         * unreliable
                         */
+                       debug("SPL: VDDIO has a brownout\n");
                        mxs_powerdown();
                        break;
                }
 
                if (tmp & POWER_STS_VDD5V_GT_VDDIO) {
+                       debug("SPL: POWER_STS_VDD5V_GT_VDDIO is set\n");
                        mxs_boot_valid_5v();
                        break;
                } else {
+                       debug("SPL: POWER_STS_VDD5V_GT_VDDIO is not set\n");
                        mxs_powerdown();
                        break;
                }
 
+               /*
+                * TODO: I can't see this being reached. We'll either
+                * powerdown or boot from a stable 5V supply.
+                */
                if (tmp & POWER_STS_PSWITCH_MASK) {
+                       debug("SPL: POWER_STS_PSWITCH_MASK is set\n");
                        mxs_batt_boot();
                        break;
                }
@@ -713,21 +786,26 @@ static void mxs_5v_boot(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Configuring power block to boot from 5V input\n");
+
        /*
         * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID,
         * but their implementation always returns 1 so we omit it here.
         */
        if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+               debug("SPL: 5V VDD good\n");
                mxs_boot_valid_5v();
                return;
        }
 
        early_delay(1000);
        if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
+               debug("SPL: 5V VDD good (after delay)\n");
                mxs_boot_valid_5v();
                return;
        }
 
+       debug("SPL: 5V VDD not good\n");
        mxs_handle_5v_conflict();
 }
 
@@ -742,6 +820,8 @@ static void mxs_init_batt_bo(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Initialising battery brown-out level to 3.0V\n");
+
        /* Brownout at 3V */
        clrsetbits_le32(&power_regs->hw_power_battmonitor,
                POWER_BATTMONITOR_BRWNOUT_LVL_MASK,
@@ -762,6 +842,8 @@ static void mxs_switch_vddd_to_dcdc_source(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Switching VDDD to DC-DC converters\n");
+
        clrsetbits_le32(&power_regs->hw_power_vdddctrl,
                POWER_VDDDCTRL_LINREG_OFFSET_MASK,
                POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW);
@@ -788,6 +870,8 @@ static void mxs_power_configure_power_source(void)
        struct mxs_lradc_regs *lradc_regs =
                (struct mxs_lradc_regs *)MXS_LRADC_BASE;
 
+       debug("SPL: Configuring power source\n");
+
        mxs_src_power_init();
 
        if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
@@ -811,6 +895,10 @@ static void mxs_power_configure_power_source(void)
                mxs_batt_boot();
        }
 
+       /*
+        * TODO: Do not switch CPU clock to PLL if we are VDD5V is sourced
+        * from USB VBUS
+        */
        mxs_power_clock2pll();
 
        mxs_init_batt_bo();
@@ -819,6 +907,7 @@ static void mxs_power_configure_power_source(void)
 
 #ifdef CONFIG_MX23
        /* Fire up the VDDMEM LinReg now that we're all set. */
+       debug("SPL: Enabling mx23 VDDMEM linear regulator\n");
        writel(POWER_VDDMEMCTRL_ENABLE_LINREG | POWER_VDDMEMCTRL_ENABLE_ILIMIT,
                &power_regs->hw_power_vddmemctrl);
 #endif
@@ -838,6 +927,8 @@ static void mxs_enable_output_rail_protection(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Enabling output rail protection\n");
+
        writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
                POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr);
 
@@ -1077,6 +1168,8 @@ static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg,
  */
 static void mxs_setup_batt_detect(void)
 {
+       debug("SPL: Starting battery voltage measurement logic\n");
+
        mxs_lradc_init();
        mxs_lradc_enable_batt_measurement();
        early_delay(10);
@@ -1111,6 +1204,8 @@ void mxs_power_init(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Initialising Power Block\n");
+
        mxs_ungate_power();
 
        mxs_power_clock2xtal();
@@ -1123,9 +1218,13 @@ void mxs_power_init(void)
        mxs_power_configure_power_source();
        mxs_enable_output_rail_protection();
 
+       debug("SPL: Setting VDDIO to 3V3 (brownout @ 3v15)\n");
        mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150);
+
+       debug("SPL: Setting VDDD to 1V5 (brownout @ 1v0)\n");
        mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1000);
 #ifdef CONFIG_MX23
+       debug("SPL: Setting mx23 VDDMEM to 2V5 (brownout @ 1v7)\n");
        mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700);
 #endif
        writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ |
@@ -1150,6 +1249,7 @@ void mxs_power_wait_pswitch(void)
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       debug("SPL: Waiting for power switch input\n");
        while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK))
                ;
 }
index 885dcee2e192f84e47d3602b5e8cc4df888a4aa7..737159ba12ae1a3c69872c0062b8dd1e17e15dc3 100644 (file)
@@ -5,3 +5,5 @@
 #
 
 obj-y  = cpu.o
+obj-$(CONFIG_SPL_BUILD) += spl.o
+obj-$(CONFIG_SPL_BUILD) += lowlevel_spl.o
diff --git a/arch/arm/cpu/armv7/armada-xp/lowlevel_spl.S b/arch/arm/cpu/armv7/armada-xp/lowlevel_spl.S
new file mode 100644 (file)
index 0000000..1febd7b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <config.h>
+#include <version.h>
+#include <linux/linkage.h>
+
+ENTRY(save_boot_params)
+       bx      lr
+ENDPROC(save_boot_params)
+
+/*
+ * cache_inv - invalidate Cache line
+ * r0 - dest
+ */
+       .global cache_inv
+       .type  cache_inv, %function
+       cache_inv:
+
+       stmfd   sp!, {r1-r12}
+
+       mcr     p15, 0, r0, c7, c6, 1
+
+       ldmfd   sp!, {r1-r12}
+       bx      lr
+
+
+/*
+ * flush_l1_v6 - l1 cache clean invalidate
+ * r0 - dest
+ */
+       .global flush_l1_v6
+       .type   flush_l1_v6, %function
+       flush_l1_v6:
+
+       stmfd   sp!, {r1-r12}
+
+       mcr     p15, 0, r0, c7, c10, 5  /* @ data memory barrier */
+       mcr     p15, 0, r0, c7, c14, 1  /* @ clean & invalidate D line */
+       mcr     p15, 0, r0, c7, c10, 4  /* @ data sync barrier */
+
+       ldmfd   sp!, {r1-r12}
+       bx      lr
+
+
+/*
+ * flush_l1_v7 - l1 cache clean invalidate
+ * r0 - dest
+ */
+       .global flush_l1_v7
+       .type   flush_l1_v7, %function
+       flush_l1_v7:
+
+       stmfd   sp!, {r1-r12}
+
+       dmb                             /* @data memory barrier */
+       mcr     p15, 0, r0, c7, c14, 1  /* @ clean & invalidate D line */
+       dsb                             /* @data sync barrier */
+
+       ldmfd   sp!, {r1-r12}
+       bx      lr
diff --git a/arch/arm/cpu/armv7/armada-xp/spl.c b/arch/arm/cpu/armv7/armada-xp/spl.c
new file mode 100644 (file)
index 0000000..402e520
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 spl_boot_device(void)
+{
+       /* Right now only booting via SPI NOR flash is supported */
+       return BOOT_DEVICE_SPI;
+}
+
+void board_init_f(ulong dummy)
+{
+       /* Set global data pointer */
+       gd = &gdata;
+
+       /* Linux expects the internal registers to be at 0xf1000000 */
+       arch_cpu_init();
+
+       preloader_console_init();
+
+       /* First init the serdes PHY's */
+       serdes_phy_config();
+
+       /* Setup DDR */
+       ddr3_init();
+
+       board_init_r(NULL, 0);
+}
index 7a9b03a68f227a2a86a60c57d6f8ee42eabf0278..fef2231a390ff651682f50d49625d319213042e8 100644 (file)
 #include <asm/io.h>
 #include <asm/types.h>
 
+#if defined(CONFIG_MX6SX)
+/* Configure MX6SX mmdc iomux */
+void mx6sx_dram_iocfg(unsigned width,
+                     const struct mx6sx_iomux_ddr_regs *ddr,
+                     const struct mx6sx_iomux_grp_regs *grp)
+{
+       struct mx6sx_iomux_ddr_regs *mx6_ddr_iomux;
+       struct mx6sx_iomux_grp_regs *mx6_grp_iomux;
+
+       mx6_ddr_iomux = (struct mx6sx_iomux_ddr_regs *)MX6SX_IOM_DDR_BASE;
+       mx6_grp_iomux = (struct mx6sx_iomux_grp_regs *)MX6SX_IOM_GRP_BASE;
+
+       /* DDR IO TYPE */
+       writel(grp->grp_ddr_type, &mx6_grp_iomux->grp_ddr_type);
+       writel(grp->grp_ddrpke, &mx6_grp_iomux->grp_ddrpke);
+
+       /* CLOCK */
+       writel(ddr->dram_sdclk_0, &mx6_ddr_iomux->dram_sdclk_0);
+
+       /* ADDRESS */
+       writel(ddr->dram_cas, &mx6_ddr_iomux->dram_cas);
+       writel(ddr->dram_ras, &mx6_ddr_iomux->dram_ras);
+       writel(grp->grp_addds, &mx6_grp_iomux->grp_addds);
+
+       /* Control */
+       writel(ddr->dram_reset, &mx6_ddr_iomux->dram_reset);
+       writel(ddr->dram_sdba2, &mx6_ddr_iomux->dram_sdba2);
+       writel(ddr->dram_sdcke0, &mx6_ddr_iomux->dram_sdcke0);
+       writel(ddr->dram_sdcke1, &mx6_ddr_iomux->dram_sdcke1);
+       writel(ddr->dram_odt0, &mx6_ddr_iomux->dram_odt0);
+       writel(ddr->dram_odt1, &mx6_ddr_iomux->dram_odt1);
+       writel(grp->grp_ctlds, &mx6_grp_iomux->grp_ctlds);
+
+       /* Data Strobes */
+       writel(grp->grp_ddrmode_ctl, &mx6_grp_iomux->grp_ddrmode_ctl);
+       writel(ddr->dram_sdqs0, &mx6_ddr_iomux->dram_sdqs0);
+       writel(ddr->dram_sdqs1, &mx6_ddr_iomux->dram_sdqs1);
+       if (width >= 32) {
+               writel(ddr->dram_sdqs2, &mx6_ddr_iomux->dram_sdqs2);
+               writel(ddr->dram_sdqs3, &mx6_ddr_iomux->dram_sdqs3);
+       }
+
+       /* Data */
+       writel(grp->grp_ddrmode, &mx6_grp_iomux->grp_ddrmode);
+       writel(grp->grp_b0ds, &mx6_grp_iomux->grp_b0ds);
+       writel(grp->grp_b1ds, &mx6_grp_iomux->grp_b1ds);
+       if (width >= 32) {
+               writel(grp->grp_b2ds, &mx6_grp_iomux->grp_b2ds);
+               writel(grp->grp_b3ds, &mx6_grp_iomux->grp_b3ds);
+       }
+       writel(ddr->dram_dqm0, &mx6_ddr_iomux->dram_dqm0);
+       writel(ddr->dram_dqm1, &mx6_ddr_iomux->dram_dqm1);
+       if (width >= 32) {
+               writel(ddr->dram_dqm2, &mx6_ddr_iomux->dram_dqm2);
+               writel(ddr->dram_dqm3, &mx6_ddr_iomux->dram_dqm3);
+       }
+}
+#endif
+
 #if defined(CONFIG_MX6QDL) || defined(CONFIG_MX6Q) || defined(CONFIG_MX6D)
 /* Configure MX6DQ mmdc iomux */
 void mx6dq_dram_iocfg(unsigned width,
@@ -184,12 +243,19 @@ void mx6sdl_dram_iocfg(unsigned width,
  */
 #define MR(val, ba, cmd, cs1) \
        ((val << 16) | (1 << 15) | (cmd << 4) | (cs1 << 3) | ba)
+#ifdef CONFIG_MX6SX
+#define MMDC1(entry, value)    do {} while (0)
+#else
+#define MMDC1(entry, value) do { mmdc1->entry = value; } while (0)
+#endif
 void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
                  const struct mx6_mmdc_calibration *calib,
                  const struct mx6_ddr3_cfg *ddr3_cfg)
 {
        volatile struct mmdc_p_regs *mmdc0;
+#ifndef CONFIG_MX6SX
        volatile struct mmdc_p_regs *mmdc1;
+#endif
        u32 val;
        u8 tcke, tcksrx, tcksre, txpdll, taofpd, taonpd, trrd;
        u8 todtlon, taxpd, tanpd, tcwl, txp, tfaw, tcl;
@@ -203,7 +269,9 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
        int cs;
 
        mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
+#ifndef CONFIG_MX6SX
        mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;
+#endif
 
        /* MX6D/MX6Q: 1066 MHz memory clock, clkper = 1.894ns = 1894ps */
        if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) {
@@ -362,12 +430,12 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
        mmdc0->mprddlctl = calib->p0_mprddlctl;
        mmdc0->mpwrdlctl = calib->p0_mpwrdlctl;
        if (sysinfo->dsize > 1) {
-               mmdc1->mpwldectrl0 = calib->p1_mpwldectrl0;
-               mmdc1->mpwldectrl1 = calib->p1_mpwldectrl1;
-               mmdc1->mpdgctrl0 = calib->p1_mpdgctrl0;
-               mmdc1->mpdgctrl1 = calib->p1_mpdgctrl1;
-               mmdc1->mprddlctl = calib->p1_mprddlctl;
-               mmdc1->mpwrdlctl = calib->p1_mpwrdlctl;
+               MMDC1(mpwldectrl0, calib->p1_mpwldectrl0);
+               MMDC1(mpwldectrl1, calib->p1_mpwldectrl1);
+               MMDC1(mpdgctrl0, calib->p1_mpdgctrl0);
+               MMDC1(mpdgctrl1, calib->p1_mpdgctrl1);
+               MMDC1(mprddlctl, calib->p1_mprddlctl);
+               MMDC1(mpwrdlctl, calib->p1_mpwrdlctl);
        }
 
        /* Read data DQ Byte0-3 delay */
@@ -379,23 +447,23 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
        }
 
        if (sysinfo->dsize > 1) {
-               mmdc1->mprddqby0dl = 0x33333333;
-               mmdc1->mprddqby1dl = 0x33333333;
-               mmdc1->mprddqby2dl = 0x33333333;
-               mmdc1->mprddqby3dl = 0x33333333;
+               MMDC1(mprddqby0dl, 0x33333333);
+               MMDC1(mprddqby1dl, 0x33333333);
+               MMDC1(mprddqby2dl, 0x33333333);
+               MMDC1(mprddqby3dl, 0x33333333);
        }
 
        /* MMDC Termination: rtt_nom:2 RZQ/2(120ohm), rtt_nom:1 RZQ/4(60ohm) */
        val = (sysinfo->rtt_nom == 2) ? 0x00011117 : 0x00022227;
        mmdc0->mpodtctrl = val;
        if (sysinfo->dsize > 1)
-               mmdc1->mpodtctrl = val;
+               MMDC1(mpodtctrl, val);
 
        /* complete calibration */
        val = (1 << 11); /* Force measurement on delay-lines */
        mmdc0->mpmur0 = val;
        if (sysinfo->dsize > 1)
-               mmdc1->mpmur0 = val;
+               MMDC1(mpmur0, val);
 
        /* Step 1: configuration request */
        mmdc0->mdscr = (u32)(1 << 15); /* config request */
@@ -435,7 +503,7 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
        val = 0xa1390001; /* one-time HW ZQ calib */
        mmdc0->mpzqhwctrl = val;
        if (sysinfo->dsize > 1)
-               mmdc1->mpzqhwctrl = val;
+               MMDC1(mpzqhwctrl, val);
 
        /* Step 7: Enable MMDC with desired chip select */
        mmdc0->mdctl |= (1 << 31) |                          /* SDE_0 for CS0 */
@@ -477,7 +545,7 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
        val = 0xa1390003;
        mmdc0->mpzqhwctrl = val;
        if (sysinfo->dsize > 1)
-               mmdc1->mpzqhwctrl = val;
+               MMDC1(mpzqhwctrl, val);
 
        /* Step 12: Configure and activate periodic refresh */
        mmdc0->mdref = (1 << 14) | /* REF_SEL: Periodic refresh cycle: 32kHz */
index 5f5f49720107f56717e676eafbfd94983ffee9b4..e599a12b3a57789f4c2830ab0f7aa218d9cdf234 100644 (file)
@@ -109,7 +109,7 @@ void init_aips(void)
        aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR;
        aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR;
 #ifdef CONFIG_MX6SX
-       aips3 = (struct aipstz_regs *)AIPS3_BASE_ADDR;
+       aips3 = (struct aipstz_regs *)AIPS3_CONFIG_BASE_ADDR;
 #endif
 
        /*
index 0556e4b3509e6b1e8b50d69bb98add96c1fef4f0..5c5a84fe56c4fc0da0f68f8cc028fa672ed90a01 100644 (file)
@@ -50,21 +50,12 @@ endchoice
 
 config CMD_PINMON
        bool "Enable boot mode pins monitor command"
-       depends on !SPL_BUILD
        default y
        help
          The command "pinmon" shows the state of the boot mode pins.
          The boot mode pins are latched when the system reset is deasserted
          and determine which device the system should load a boot image from.
 
-config SOC_INIT
-       bool
-       default SPL_BUILD
-
-config DRAM_INIT
-       bool
-       default SPL_BUILD
-
 config CMD_DDRPHY_DUMP
        bool "Enable dump command of DDR PHY parameters"
        depends on !SPL_BUILD
@@ -74,7 +65,7 @@ config CMD_DDRPHY_DUMP
 
 choice
        prompt "DDR3 Frequency select"
-       depends on DRAM_INIT
+       depends on SPL_BUILD
 
 config DDR_FREQ_1600
        bool "DDR3 1600"
index 05462320b58c749125f27945639df9e10ad52808..df418dd3c4b8104c11ae1acfdfb36d7e19d2c6ab 100644 (file)
@@ -2,23 +2,32 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-obj-$(CONFIG_SPL_BUILD) += lowlevel_init.o init_page_table.o
-obj-$(CONFIG_SPL_BUILD) += spl.o
+ifdef CONFIG_SPL_BUILD
 
-obj-y += timer.o
-obj-y += reset.o
-obj-y += cache_uniphier.o
-obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o
-obj-y += dram_init.o
-obj-$(CONFIG_DRAM_INIT) += ddrphy_training.o
+obj-y += lowlevel_init.o
+obj-y += init_page_table.o
+obj-y += spl.o
+obj-y += ddrphy_training.o
+
+else
+
+obj-$(CONFIG_BOARD_EARLY_INIT_F) += board_early_init_f.o
 obj-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o
+obj-$(CONFIG_MISC_INIT_F) += print_misc_info.o
+obj-y += dram_init.o
+obj-y += board_common.o
 obj-$(CONFIG_BOARD_EARLY_INIT_R) += board_early_init_r.o
 obj-$(CONFIG_BOARD_LATE_INIT) += board_late_init.o
+obj-y += reset.o
+obj-y += cache_uniphier.o
 obj-$(CONFIG_UNIPHIER_SMP) += smp.o
 obj-$(CONFIG_CMD_PINMON) += cmd_pinmon.o
 obj-$(CONFIG_CMD_DDRPHY_DUMP) += cmd_ddrphy.o
 
-obj-y += board_common.o
+endif
+
+obj-y += timer.o
+
 obj-$(CONFIG_PFC_MICRO_SUPPORT_CARD) += support_card.o
 obj-$(CONFIG_DCC_MICRO_SUPPORT_CARD) += support_card.o
 
diff --git a/arch/arm/cpu/armv7/uniphier/board_early_init_f.c b/arch/arm/cpu/armv7/uniphier/board_early_init_f.c
new file mode 100644 (file)
index 0000000..d25bbae
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012-2015 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm/arch/led.h>
+#include <asm/arch/board.h>
+
+void pin_init(void);
+
+int board_early_init_f(void)
+{
+       led_write(U, 0, , );
+
+       pin_init();
+
+       led_write(U, 1, , );
+
+       return 0;
+}
diff --git a/arch/arm/cpu/armv7/uniphier/board_postclk_init.c b/arch/arm/cpu/armv7/uniphier/board_postclk_init.c
deleted file mode 100644 (file)
index 89e44bb..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Panasonic Corporation
- *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <linux/compiler.h>
-#include <asm/arch/led.h>
-#include <asm/arch/board.h>
-
-void __weak bcu_init(void)
-{
-};
-void sbc_init(void);
-void sg_init(void);
-void pll_init(void);
-void pin_init(void);
-void clkrst_init(void);
-
-int board_postclk_init(void)
-{
-#ifdef CONFIG_SOC_INIT
-       bcu_init();
-
-       sbc_init();
-
-       sg_init();
-
-       uniphier_board_reset();
-
-       pll_init();
-
-       uniphier_board_init();
-
-       led_write(B, 1, , );
-
-       clkrst_init();
-
-       led_write(B, 2, , );
-#endif
-       pin_init();
-
-       led_write(B, 3, , );
-
-       return 0;
-}
index 3561b40a33196deed9568fcf5fd57ddc1675c07b..3c1b32597646b94a8c7f20be000a4feaff3eb750 100644 (file)
 
 static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-       struct boot_device_info *table;
-       u32 mode_sel, n = 0;
-
-       mode_sel = get_boot_mode_sel();
+       int mode_sel, i;
 
        printf("Boot Swap: %s\n\n", boot_is_swapped() ? "ON" : "OFF");
 
+       mode_sel = get_boot_mode_sel();
+
        puts("Boot Mode Pin:\n");
 
-       for (table = boot_device_table; strlen(table->info); table++) {
-               printf(" %c %02x %s\n", n == mode_sel ? '*' : ' ', n,
-                      table->info);
-               n++;
-       }
+       for (i = 0; boot_device_table[i].info; i++)
+               printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i,
+                      boot_device_table[i].info);
 
        return 0;
 }
index 7de657b7af91d53bddd4639cc77b8603f0548d60..4b8c938b5ead10b2362b2a7b956315e6cff6f42a 100644 (file)
@@ -1,37 +1,16 @@
 /*
- * Copyright (C) 2012-2014 Panasonic Corporation
+ * Copyright (C) 2012-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
-#include <asm/arch/led.h>
-
-int umc_init(void);
-void enable_dpll_ssc(void);
 
 int dram_init(void)
 {
        DECLARE_GLOBAL_DATA_PTR;
        gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
 
-#ifdef CONFIG_DRAM_INIT
-       led_write(B, 4, , );
-
-       {
-               int res;
-
-               res = umc_init();
-               if (res < 0)
-                       return res;
-       }
-       led_write(B, 5, , );
-
-       enable_dpll_ssc();
-#endif
-
-       led_write(B, 6, , );
-
        return 0;
 }
index 07529061213e6be38ca5e7de7fa0ddda86c93c70..72f46636fd5d60aa39f689c9f3f2c3a5807b1147 100644 (file)
@@ -2,11 +2,13 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_DEBUG_LL) += lowlevel_debug.o
+obj-y += bcu_init.o sbc_init.o sg_init.o pll_init.o clkrst_init.o \
+       pll_spectrum.o umc_init.o ddrphy_init.o
+else
+obj-$(CONFIG_BOARD_EARLY_INIT_F) += pinctrl.o
 obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
+endif
+
 obj-y += boot-mode.o
-obj-$(CONFIG_DEBUG_LL) += lowlevel_debug.o
-obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \
-                                                               clkrst_init.o
-obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
-obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/board_info.c b/arch/arm/cpu/armv7/uniphier/ph1-ld4/board_info.c
deleted file mode 100644 (file)
index 27d772e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Panasonic Corporation
- *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arch/board.h>
-
-int checkboard(void)
-{
-       puts("Board: PH1-LD4 Board\n");
-
-       return check_support_card();
-}
index 8206e2a3542774e0133525825c95e7238f3a1657..e330fda1ed44a7f420744011525c98b59cf33b9e 100644 (file)
@@ -2,10 +2,13 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_DEBUG_LL) += lowlevel_debug.o
+obj-y += sbc_init.o sg_init.o pll_init.o clkrst_init.o \
+       pll_spectrum.o umc_init.o ddrphy_init.o
+else
+obj-$(CONFIG_BOARD_EARLY_INIT_F) += pinctrl.o
 obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
+endif
+
 obj-y += boot-mode.o
-obj-$(CONFIG_DEBUG_LL) += lowlevel_debug.o
-obj-$(CONFIG_SOC_INIT) += sbc_init.o sg_init.o pll_init.o clkrst_init.o
-obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
-obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/board_info.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/board_info.c
deleted file mode 100644 (file)
index 325a4f6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Panasonic Corporation
- *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arch/board.h>
-
-int checkboard(void)
-{
-       puts("Board: PH1-Pro4 Board\n");
-
-       return check_support_card();
-}
index 33bccff2a5e05ffe616f1c7a8a3a65ef1770b737..c31b74badd26968550dd6a2f09074c4b4bb7d343 100644 (file)
@@ -45,17 +45,17 @@ struct boot_device_info boot_device_table[] = {
        {BOOT_DEVICE_NONE, "Reserved"},
        {BOOT_DEVICE_NONE, "Reserved"},
        {BOOT_DEVICE_NONE, "Reserved"},
-       {BOOT_DEVICE_NONE, ""}
+       { /* sentinel */ }
 };
 
-u32 get_boot_mode_sel(void)
+int get_boot_mode_sel(void)
 {
        return (readl(SG_PINMON0) >> 1) & 0x1f;
 }
 
 u32 spl_boot_device(void)
 {
-       u32 boot_mode;
+       int boot_mode;
 
        if (boot_is_swapped())
                return BOOT_DEVICE_NOR;
index 07529061213e6be38ca5e7de7fa0ddda86c93c70..72f46636fd5d60aa39f689c9f3f2c3a5807b1147 100644 (file)
@@ -2,11 +2,13 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_DEBUG_LL) += lowlevel_debug.o
+obj-y += bcu_init.o sbc_init.o sg_init.o pll_init.o clkrst_init.o \
+       pll_spectrum.o umc_init.o ddrphy_init.o
+else
+obj-$(CONFIG_BOARD_EARLY_INIT_F) += pinctrl.o
 obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
+endif
+
 obj-y += boot-mode.o
-obj-$(CONFIG_DEBUG_LL) += lowlevel_debug.o
-obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \
-                                                               clkrst_init.o
-obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
-obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/board_info.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/board_info.c
deleted file mode 100644 (file)
index 15dc289..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 2012-2014 Panasonic Corporation
- *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arch/board.h>
-
-int checkboard(void)
-{
-       puts("Board: PH1-sLD8 Board\n");
-
-       return check_support_card();
-}
index 2b6403f88fc7dc3113c2acf6226c4a08cdfdbf6a..5e80335b581ff25c0e28ad6a4e19f5ddd4fa0109 100644 (file)
@@ -26,6 +26,15 @@ void pin_init(void)
        sg_set_pinsel(111, 1);  /* SBI0 -> RXD3 */
 #endif
 
+#ifdef CONFIG_SYS_I2C_UNIPHIER
+       {
+               u32 tmp;
+               tmp = readl(SG_IECTRL);
+               tmp |= 0xc00; /* enable SCL0, SDA0, SCL1, SDA1 */
+               writel(tmp, SG_IECTRL);
+       }
+#endif
+
 #ifdef CONFIG_NAND_DENALI
        sg_set_pinsel(15, 0);   /* XNFRE_GB -> XNFRE_GB */
        sg_set_pinsel(16, 0);   /* XNFWE_GB -> XNFWE_GB */
diff --git a/arch/arm/cpu/armv7/uniphier/print_misc_info.c b/arch/arm/cpu/armv7/uniphier/print_misc_info.c
new file mode 100644 (file)
index 0000000..69cfab5
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2015 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm/arch/board.h>
+
+int misc_init_f(void)
+{
+       return check_support_card();
+}
index 40d28adaf336bfe5f4405fc5eb68d3982d9ea97c..8a4eafc266a03dd0ea20092aab7885a5ac91395c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2014 Panasonic Corporation
+ * Copyright (C) 2013-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
@@ -7,11 +7,53 @@
 
 #include <common.h>
 #include <spl.h>
+#include <linux/compiler.h>
+#include <asm/arch/led.h>
+#include <asm/arch/board.h>
+
+void __weak bcu_init(void)
+{
+};
+void sbc_init(void);
+void sg_init(void);
+void pll_init(void);
+void pin_init(void);
+void clkrst_init(void);
+int umc_init(void);
+void enable_dpll_ssc(void);
 
 void spl_board_init(void)
 {
-#if defined(CONFIG_BOARD_POSTCLK_INIT)
-       board_postclk_init();
-#endif
-       dram_init();
+       bcu_init();
+
+       sbc_init();
+
+       sg_init();
+
+       uniphier_board_reset();
+
+       pll_init();
+
+       uniphier_board_init();
+
+       led_write(L, 0, , );
+
+       clkrst_init();
+
+       led_write(L, 1, , );
+
+       {
+               int res;
+
+               res = umc_init();
+               if (res < 0) {
+                       while (1)
+                               ;
+               }
+       }
+       led_write(L, 2, , );
+
+       enable_dpll_ssc();
+
+       led_write(L, 3, , );
 }
index 6855878c29110d3e5092c79bba9eada22b3296a8..d479be1d4d6ebdf155915be5ad8d125bf0e419bb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for UniPhier PH1-LD4 Reference Board
  *
- * Copyright (C) 2014 Panasonic Corporation
+ * Copyright (C) 2014-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 /include/ "uniphier-ph1-ld4.dtsi"
+/include/ "uniphier-ref-daughter.dtsi"
 
 / {
        model = "Panasonic UniPhier PH1-LD4 Reference Board";
 
 &i2c0 {
        status = "okay";
-       eeprom {
-               compatible = "i2c-eeprom";
-               reg = <0x50>;
-       };
 };
 
 &usb0 {
index 1227b628d19fcbeb24047a869c25b0e5930ca47f..d9e7a8c52b8c7445e52e3f6c112b099bb2b0ed79 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for UniPhier PH1-Pro4 Reference Board
  *
- * Copyright (C) 2014 Panasonic Corporation
+ * Copyright (C) 2014-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 /include/ "uniphier-ph1-pro4.dtsi"
+/include/ "uniphier-ref-daughter.dtsi"
 
 / {
        model = "Panasonic UniPhier PH1-Pro4 Reference Board";
 
 &i2c0 {
        status = "okay";
-       eeprom {
-               compatible = "i2c-eeprom";
-               reg = <0x50>;
-       };
 };
 
 &usb0 {
index fefc592589e80735dde855a4aab238ff388bdd41..8a7f90ac78dc76b6946a9136e46b1e0222ce69a0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for UniPhier PH1-sLD3 Reference Board
  *
- * Copyright (C) 2014 Panasonic Corporation
+ * Copyright (C) 2014-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 /include/ "uniphier-ph1-sld3.dtsi"
+/include/ "uniphier-ref-daughter.dtsi"
 
 / {
        model = "Panasonic UniPhier PH1-sLD3 Reference Board";
 
 &i2c0 {
        status = "okay";
-       eeprom {
-               compatible = "i2c-eeprom";
-               reg = <0x50>;
-       };
 };
 
 &usb0 {
index 9b6d95c4808437e6fc1d1ca5d208a0ea067ac330..0cb9c47b6570b71e8ee96c69aa7f9b1cd9c973a3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for UniPhier PH1-sLD8 Reference Board
  *
- * Copyright (C) 2014 Panasonic Corporation
+ * Copyright (C) 2014-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 /include/ "uniphier-ph1-sld8.dtsi"
+/include/ "uniphier-ref-daughter.dtsi"
 
 / {
        model = "Panasonic UniPhier PH1-sLD8 Reference Board";
 
 &i2c0 {
        status = "okay";
-       eeprom {
-               compatible = "i2c-eeprom";
-               reg = <0x50>;
-       };
 };
 
 &usb0 {
diff --git a/arch/arm/dts/uniphier-ref-daughter.dtsi b/arch/arm/dts/uniphier-ref-daughter.dtsi
new file mode 100644 (file)
index 0000000..0145b51
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Device Tree Source for UniPhier Reference Daughter Board
+ *
+ * Copyright (C) 2014-2015 Panasonic Corporation
+ *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+&i2c0 {
+       eeprom {
+               compatible = "i2c-eeprom";
+               reg = <0x50>;
+               u-boot,i2c-offset-len = <2>;
+       };
+};
index 00ee775a45150655840a137e7ec8ce5a4a7b6ed7..f9fd4246099a6d28d8dff9759e0424eb3e7a1db3 100644 (file)
 #endif /* CONFIG_SYS_KWD_CONFIG */
 
 /* Add target to build it automatically upon "make" */
+#ifdef CONFIG_SPL
+#define CONFIG_BUILD_TARGET    "u-boot-spl.kwb"
+#else
 #define CONFIG_BUILD_TARGET    "u-boot.kwb"
+#endif
 
 /* end of 16M scrubbed by training in bootrom */
 #define CONFIG_SYS_INIT_SP_ADDR                0x00FF0000
index 6b60c21ceb8e7391d98fca49f2a883535258c0ac..4f5ff96d844990b2ee04cd8e938d9ee2bb5e010b 100644 (file)
@@ -96,6 +96,9 @@ struct kwgpio_registers {
        u32 irq_level;
 };
 
+/* Needed for dynamic (board-specific) mbus configuration */
+extern struct mvebu_mbus_state mbus_state;
+
 /*
  * functions
  */
@@ -103,5 +106,18 @@ unsigned int mvebu_sdram_bar(enum memory_bank bank);
 unsigned int mvebu_sdram_bs(enum memory_bank bank);
 void mvebu_sdram_size_adjust(enum memory_bank bank);
 int mvebu_mbus_probe(struct mbus_win windows[], int count);
+
+/*
+ * Highspeed SERDES PHY config init, ported from bin_hdr
+ * to mainline U-Boot
+ */
+int serdes_phy_config(void);
+
+/*
+ * DDR3 init / training code ported from Marvell bin_hdr. Now
+ * available in mainline U-Boot in:
+ * drivers/ddr/mvebu/
+ */
+int ddr3_init(void);
 #endif /* __ASSEMBLY__ */
 #endif /* _ARMADA_XP_CPU_H */
index c968600b770f397972722e655221a0f834d49d6c..ae88b6ecab45eb9752f758ccd186242b1467c723 100644 (file)
@@ -88,8 +88,8 @@
 #define AIPS2_ARB_BASE_ADDR             0x02100000
 #define AIPS2_ARB_END_ADDR              0x021FFFFF
 #ifdef CONFIG_MX6SX
-#define AIPS3_BASE_ADDR                        0x02200000
-#define AIPS3_END_ADDR                 0x022FFFFF
+#define AIPS3_ARB_BASE_ADDR             0x02200000
+#define AIPS3_ARB_END_ADDR              0x022FFFFF
 #define WEIM_ARB_BASE_ADDR              0x50000000
 #define WEIM_ARB_END_ADDR               0x57FFFFFF
 #define QSPI0_AMBA_BASE                0x60000000
@@ -624,12 +624,16 @@ struct fuse_bank0_regs {
        u32     rsvd1[3];
        u32     uid_high;
        u32     rsvd2[3];
-       u32     rsvd3[4];
-       u32     rsvd4[4];
-       u32     rsvd5[4];
+       u32     cfg2;
+       u32     rsvd3[3];
+       u32     cfg3;
+       u32     rsvd4[3];
+       u32     cfg4;
+       u32     rsvd5[3];
        u32     cfg5;
        u32     rsvd6[3];
-       u32     rsvd7[4];
+       u32     cfg6;
+       u32     rsvd7[3];
 };
 
 #ifdef CONFIG_MX6SX
index 5ebabfa271f572672d59c33e97ae1d5b87609eec..8e0d7d15c17a87becd9fafb296e6b2522222276a 100644 (file)
@@ -62,6 +62,49 @@ struct mmdc_p_regs {
        u32 mpmur0;
 };
 
+#define MX6SX_IOM_DDR_BASE     0x020e0200
+struct mx6sx_iomux_ddr_regs {
+       u32 res1[59];
+       u32 dram_dqm0;
+       u32 dram_dqm1;
+       u32 dram_dqm2;
+       u32 dram_dqm3;
+       u32 dram_ras;
+       u32 dram_cas;
+       u32 res2[2];
+       u32 dram_sdwe_b;
+       u32 dram_odt0;
+       u32 dram_odt1;
+       u32 dram_sdba0;
+       u32 dram_sdba1;
+       u32 dram_sdba2;
+       u32 dram_sdcke0;
+       u32 dram_sdcke1;
+       u32 dram_sdclk_0;
+       u32 dram_sdqs0;
+       u32 dram_sdqs1;
+       u32 dram_sdqs2;
+       u32 dram_sdqs3;
+       u32 dram_reset;
+};
+
+#define MX6SX_IOM_GRP_BASE     0x020e0500
+struct mx6sx_iomux_grp_regs {
+       u32 res1[61];
+       u32 grp_addds;
+       u32 grp_ddrmode_ctl;
+       u32 grp_ddrpke;
+       u32 grp_ddrpk;
+       u32 grp_ddrhys;
+       u32 grp_ddrmode;
+       u32 grp_b0ds;
+       u32 grp_b1ds;
+       u32 grp_ctlds;
+       u32 grp_ddr_type;
+       u32 grp_b2ds;
+       u32 grp_b3ds;
+};
+
 /*
  * MMDC iomux registers (pinctl/padctl) - (different for IMX6DQ vs IMX6SDL)
  */
@@ -243,6 +286,9 @@ void mx6dq_dram_iocfg(unsigned width,
 void mx6sdl_dram_iocfg(unsigned width,
                       const struct mx6sdl_iomux_ddr_regs *,
                       const struct mx6sdl_iomux_grp_regs *);
+void mx6sx_dram_iocfg(unsigned width,
+                     const struct mx6sx_iomux_ddr_regs *,
+                     const struct mx6sx_iomux_grp_regs *);
 
 /* configure mx6 mmdc registers */
 void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
index 062f3de1d05bfd4de1011762b55fbb6311c84fc9..46787237540c2c697fd253bc76bb0c97a3089144 100644 (file)
@@ -74,6 +74,23 @@ static const struct mxs_pair mxs_boot_modes[] = {
 #endif
 };
 
+#define MXS_BM_USB                     0x00
+#define MXS_BM_I2C_MASTER_3V3          0x01
+#define MXS_BM_I2C_MASTER_1V8          0x11
+#define MXS_BM_SPI2_MASTER_3V3_NOR     0x02
+#define MXS_BM_SPI2_MASTER_1V8_NOR     0x12
+#define MXS_BM_SPI3_MASTER_3V3_NOR     0x03
+#define MXS_BM_SPI3_MASTER_1V8_NOR     0x13
+#define MXS_BM_NAND_3V3                        0x04
+#define MXS_BM_NAND_1V8                        0x14
+#define MXS_BM_JTAG                    0x06
+#define MXS_BM_SPI3_MASTER_3V3_EEPROM  0x08
+#define MXS_BM_SPI3_MASTER_1V8_EEPROM  0x18
+#define MXS_BM_SDMMC0_3V3              0x09
+#define MXS_BM_SDMMC0_1V8              0x19
+#define MXS_BM_SDMMC1_3V3              0x0a
+#define MXS_BM_SDMMC1_1V8              0x1a
+
 struct mxs_spl_data {
        uint8_t         boot_mode_idx;
        uint32_t        mem_dram_size;
index 6987f5766960a7c4ab65f50973bf001f1f62d366..7a10f1c5b2c89db6a9f30f0552632cbf9c060f24 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef _ASM_BOOT_DEVICE_H_
 #define _ASM_BOOT_DEVICE_H_
 
-u32 get_boot_mode_sel(void);
+int get_boot_mode_sel(void);
 
 struct boot_device_info {
        u32 type;
diff --git a/arch/arm/include/asm/arch-uniphier/gpio.h b/arch/arm/include/asm/arch-uniphier/gpio.h
deleted file mode 100644 (file)
index 1fc4e19..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
- * Dummy header file to enable CONFIG_OF_CONTROL.
- * If CONFIG_OF_CONTROL is enabled, lib/fdtdec.c is compiled.
- * It includes <asm/arch/gpio.h> via <asm/gpio.h>, so those SoCs that enable
- * OF_CONTROL must have arch/gpio.h even if GPIO is not supported.
- */
index f97f3dd1496aa54f7ca0667d0ebea299c95d50e7..414042d4039b52b626eeae689b0b5a0e31d59fc5 100644 (file)
@@ -36,7 +36,6 @@ int   arch_early_init_r(void);
 
 /* board/.../... */
 int    board_init(void);
-int    dram_init (void);
 void   dram_init_banksize (void);
 
 /* cpu/.../interrupt.c */
index 9dcab6958c5de92c03fc8d6d189ac7a110d1fa6e..de243feaab51e1a2c86b4ebb15b5f8c5ef55d8fc 100644 (file)
@@ -10,3 +10,5 @@ obj-y = dram.o
 obj-y  += gpio.o
 obj-$(CONFIG_ARMADA_XP) += mbus.o
 obj-y  += timer.o
+
+obj-y  += serdes/
diff --git a/arch/arm/mvebu-common/serdes/Makefile b/arch/arm/mvebu-common/serdes/Makefile
new file mode 100644 (file)
index 0000000..a380fee
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-$(CONFIG_SPL_BUILD)        = high_speed_env_lib.o
+obj-$(CONFIG_SPL_BUILD)        += high_speed_env_spec.o
diff --git a/arch/arm/mvebu-common/serdes/board_env_spec.h b/arch/arm/mvebu-common/serdes/board_env_spec.h
new file mode 100644 (file)
index 0000000..36e0ed8
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __BOARD_ENV_SPEC
+#define __BOARD_ENV_SPEC
+
+/* Board specific configuration */
+
+/* KW40 */
+#define MV_6710_DEV_ID                 0x6710
+
+#define MV_6710_Z1_REV                 0x0
+#define MV_6710_Z1_ID                  ((MV_6710_DEV_ID << 16) | MV_6710_Z1_REV)
+#define MV_6710_Z1_NAME                        "MV6710 Z1"
+
+/* Armada XP Family */
+#define MV_78130_DEV_ID                        0x7813
+#define MV_78160_DEV_ID                        0x7816
+#define MV_78230_DEV_ID                        0x7823
+#define MV_78260_DEV_ID                        0x7826
+#define MV_78460_DEV_ID                        0x7846
+#define MV_78000_DEV_ID                        0x7888
+
+#define MV_FPGA_DEV_ID                 0x2107
+
+#define MV_78XX0_Z1_REV                        0x0
+
+/* boards ID numbers */
+#define BOARD_ID_BASE                  0x0
+
+/* New board ID numbers */
+#define DB_88F78XX0_BP_ID              (BOARD_ID_BASE)
+#define RD_78460_SERVER_ID             (DB_88F78XX0_BP_ID + 1)
+#define DB_78X60_PCAC_ID               (RD_78460_SERVER_ID + 1)
+#define FPGA_88F78XX0_ID               (DB_78X60_PCAC_ID + 1)
+#define DB_88F78XX0_BP_REV2_ID         (FPGA_88F78XX0_ID + 1)
+#define RD_78460_NAS_ID                        (DB_88F78XX0_BP_REV2_ID + 1)
+#define DB_78X60_AMC_ID                        (RD_78460_NAS_ID + 1)
+#define DB_78X60_PCAC_REV2_ID          (DB_78X60_AMC_ID + 1)
+#define RD_78460_SERVER_REV2_ID                (DB_78X60_PCAC_REV2_ID + 1)
+#define DB_784MP_GP_ID                 (RD_78460_SERVER_REV2_ID + 1)
+#define RD_78460_CUSTOMER_ID           (DB_784MP_GP_ID + 1)
+#define MV_MAX_BOARD_ID                        (RD_78460_CUSTOMER_ID + 1)
+#define INVALID_BAORD_ID               0xFFFFFFFF
+
+/* Sample at Reset */
+#define MPP_SAMPLE_AT_RESET(id)                (0x18230 + (id * 4))
+
+/* BIOS Modes related defines */
+
+#define SAR0_BOOTWIDTH_OFFSET          3
+#define SAR0_BOOTWIDTH_MASK            (0x3 << SAR0_BOOTWIDTH_OFFSET)
+#define SAR0_BOOTSRC_OFFSET            5
+#define SAR0_BOOTSRC_MASK              (0xF << SAR0_BOOTSRC_OFFSET)
+
+#define SAR0_L2_SIZE_OFFSET            19
+#define SAR0_L2_SIZE_MASK              (0x3 << SAR0_L2_SIZE_OFFSET)
+#define SAR0_CPU_FREQ_OFFSET           21
+#define SAR0_CPU_FREQ_MASK             (0x7 << SAR0_CPU_FREQ_OFFSET)
+#define SAR0_FABRIC_FREQ_OFFSET                24
+#define SAR0_FABRIC_FREQ_MASK          (0xF << SAR0_FABRIC_FREQ_OFFSET)
+#define SAR0_CPU0CORE_OFFSET           31
+#define SAR0_CPU0CORE_MASK             (0x1 << SAR0_CPU0CORE_OFFSET)
+#define SAR1_CPU0CORE_OFFSET           0
+#define SAR1_CPU0CORE_MASK             (0x1 << SAR1_CPU0CORE_OFFSET)
+
+#define PEX_CLK_100MHZ_OFFSET          2
+#define PEX_CLK_100MHZ_MASK            (0x1 << PEX_CLK_100MHZ_OFFSET)
+
+#define SAR1_FABRIC_MODE_OFFSET                19
+#define SAR1_FABRIC_MODE_MASK          (0x1 << SAR1_FABRIC_MODE_OFFSET)
+#define SAR1_CPU_MODE_OFFSET           20
+#define SAR1_CPU_MODE_MASK             (0x1 << SAR1_CPU_MODE_OFFSET)
+
+#define SAR_CPU_FAB_GET(cpu, fab)      (((cpu & 0x7) << 21) | ((fab & 0xF) << 24))
+
+
+#define CORE_AVS_CONTROL_0REG          0x18300
+#define CORE_AVS_CONTROL_2REG          0x18308
+#define CPU_AVS_CONTROL2_REG           0x20868
+#define CPU_AVS_CONTROL0_REG           0x20860
+#define GENERAL_PURPOSE_RESERVED0_REG  0x182E0
+
+#define MSAR_TCLK_OFFS                 28
+#define MSAR_TCLK_MASK                 (0x1 << MSAR_TCLK_OFFS)
+
+
+/* Controler environment registers offsets */
+#define GEN_PURP_RES_1_REG             0x182F4
+#define GEN_PURP_RES_2_REG             0x182F8
+
+/* registers offsets */
+#define MV_GPP_REGS_OFFSET(unit)       (0x18100 + ((unit) * 0x40))
+#define MPP_CONTROL_REG(id)            (0x18000 + (id * 4))
+#define MV_GPP_REGS_BASE(unit)         (MV_GPP_REGS_OFFSET(unit))
+#define MV_GPP_REGS_BASE_0             (MV_GPP_REGS_OFFSET_0)
+
+#define GPP_DATA_OUT_REG(grp)          (MV_GPP_REGS_BASE(grp) + 0x00)
+#define GPP_DATA_OUT_REG_0             (MV_GPP_REGS_BASE_0 + 0x00)     /* Used in .S files */
+#define GPP_DATA_OUT_EN_REG(grp)       (MV_GPP_REGS_BASE(grp) + 0x04)
+#define GPP_BLINK_EN_REG(grp)          (MV_GPP_REGS_BASE(grp) + 0x08)
+#define GPP_DATA_IN_POL_REG(grp)       (MV_GPP_REGS_BASE(grp) + 0x0C)
+#define GPP_DATA_IN_REG(grp)           (MV_GPP_REGS_BASE(grp) + 0x10)
+#define GPP_INT_CAUSE_REG(grp)         (MV_GPP_REGS_BASE(grp) + 0x14)
+#define GPP_INT_MASK_REG(grp)          (MV_GPP_REGS_BASE(grp) + 0x18)
+#define GPP_INT_LVL_REG(grp)           (MV_GPP_REGS_BASE(grp) + 0x1C)
+#define GPP_OUT_SET_REG(grp)           (0x18130 + ((grp) * 0x40))
+#define GPP_64_66_DATA_OUT_SET_REG     0x181A4
+#define GPP_OUT_CLEAR_REG(grp)         (0x18134 + ((grp) * 0x40))
+#define GPP_64_66_DATA_OUT_CLEAR_REG   0x181B0
+#define GPP_FUNC_SELECT_REG            (MV_GPP_REGS_BASE(0) + 0x40)
+
+#define MV_GPP66                       (1 << 2)
+
+/* Relevant for MV78XX0 */
+#define GPP_DATA_OUT_SET_REG           (MV_GPP_REGS_BASE(0) + 0x20)
+#define GPP_DATA_OUT_CLEAR_REG         (MV_GPP_REGS_BASE(0) + 0x24)
+
+/* This define describes the maximum number of supported PEX Interfaces */
+#define MV_PEX_MAX_IF                  10
+#define MV_PEX_MAX_UNIT                        4
+
+#define MV_SERDES_NUM_TO_PEX_NUM(num)  ((num < 8) ? (num) : (8 + (num / 12)))
+
+#define PEX_PHY_ACCESS_REG(unit)       (0x40000 + ((unit) % 2 * 0x40000) + \
+                                        ((unit)/2 * 0x2000) + 0x1B00)
+
+#define SATA_BASE_REG(port)            (0xA2000 + (port)*0x2000)
+
+#define SATA_PWR_PLL_CTRL_REG(port)    (SATA_BASE_REG(port) + 0x804)
+#define SATA_DIG_LP_ENA_REG(port)      (SATA_BASE_REG(port) + 0x88C)
+#define SATA_REF_CLK_SEL_REG(port)     (SATA_BASE_REG(port) + 0x918)
+#define SATA_COMPHY_CTRL_REG(port)     (SATA_BASE_REG(port) + 0x920)
+#define SATA_LP_PHY_EXT_CTRL_REG(port) (SATA_BASE_REG(port) + 0x058)
+#define SATA_LP_PHY_EXT_STAT_REG(port) (SATA_BASE_REG(port) + 0x05C)
+#define SATA_IMP_TX_SSC_CTRL_REG(port) (SATA_BASE_REG(port) + 0x810)
+#define SATA_GEN_1_SET_0_REG(port)     (SATA_BASE_REG(port) + 0x834)
+#define SATA_GEN_1_SET_1_REG(port)     (SATA_BASE_REG(port) + 0x838)
+#define SATA_GEN_2_SET_0_REG(port)     (SATA_BASE_REG(port) + 0x83C)
+#define SATA_GEN_2_SET_1_REG(port)     (SATA_BASE_REG(port) + 0x840)
+
+#define MV_ETH_BASE_ADDR               (0x72000)
+#define MV_ETH_REGS_OFFSET(port)       (MV_ETH_BASE_ADDR - ((port) / 2) * \
+                                        0x40000 + ((port) % 2) * 0x4000)
+#define MV_ETH_REGS_BASE(port)         MV_ETH_REGS_OFFSET(port)
+
+
+#define SGMII_PWR_PLL_CTRL_REG(port)   (MV_ETH_REGS_BASE(port) + 0xE04)
+#define SGMII_DIG_LP_ENA_REG(port)     (MV_ETH_REGS_BASE(port) + 0xE8C)
+#define SGMII_REF_CLK_SEL_REG(port)    (MV_ETH_REGS_BASE(port) + 0xF18)
+#define SGMII_SERDES_CFG_REG(port)     (MV_ETH_REGS_BASE(port) + 0x4A0)
+#define SGMII_SERDES_STAT_REG(port)    (MV_ETH_REGS_BASE(port) + 0x4A4)
+#define SGMII_COMPHY_CTRL_REG(port)    (MV_ETH_REGS_BASE(port) + 0xF20)
+#define QSGMII_GEN_1_SETTING_REG(port) (MV_ETH_REGS_BASE(port) + 0xE38)
+#define QSGMII_SERDES_CFG_REG(port)    (MV_ETH_REGS_BASE(port) + 0x4a0)
+
+#define SERDES_LINE_MUX_REG_0_7                0x18270
+#define SERDES_LINE_MUX_REG_8_15       0x18274
+#define QSGMII_CONTROL_1_REG           0x18404
+
+/* SOC_CTRL_REG fields */
+#define SCR_PEX_ENA_OFFS(pex)          ((pex) & 0x3)
+#define SCR_PEX_ENA_MASK(pex)          (1 << pex)
+
+#define PCIE0_QUADX1_EN                        (1<<7)
+#define PCIE1_QUADX1_EN                        (1<<8)
+
+#define SCR_PEX_4BY1_OFFS(pex)         ((pex) + 7)
+#define SCR_PEX_4BY1_MASK(pex)         (1 << SCR_PEX_4BY1_OFFS(pex))
+
+#define PCIE1_CLK_OUT_EN_OFF           5
+#define PCIE1_CLK_OUT_EN_MASK          (1 << PCIE1_CLK_OUT_EN_OFF)
+
+#define PCIE0_CLK_OUT_EN_OFF           4
+#define PCIE0_CLK_OUT_EN_MASK          (1 << PCIE0_CLK_OUT_EN_OFF)
+
+#define SCR_PEX0_4BY1_OFFS             7
+#define SCR_PEX0_4BY1_MASK             (1 << SCR_PEX0_4BY1_OFFS)
+
+#define SCR_PEX1_4BY1_OFFS             8
+#define SCR_PEX1_4BY1_MASK             (1 << SCR_PEX1_4BY1_OFFS)
+
+
+#define MV_MISC_REGS_OFFSET            (0x18200)
+#define MV_MISC_REGS_BASE              (MV_MISC_REGS_OFFSET)
+#define SOC_CTRL_REG                   (MV_MISC_REGS_BASE + 0x4)
+
+/*
+ * PCI Express Control and Status Registers
+ */
+#define MAX_PEX_DEVICES                        32
+#define MAX_PEX_FUNCS                  8
+#define MAX_PEX_BUSSES                 256
+
+#define PXSR_PEX_BUS_NUM_OFFS          8       /* Bus Number Indication */
+#define PXSR_PEX_BUS_NUM_MASK          (0xff << PXSR_PEX_BUS_NUM_OFFS)
+
+#define PXSR_PEX_DEV_NUM_OFFS          16      /* Device Number Indication */
+#define PXSR_PEX_DEV_NUM_MASK          (0x1f << PXSR_PEX_DEV_NUM_OFFS)
+
+#define PXSR_DL_DOWN                   0x1     /* DL_Down indication. */
+#define PXCAR_CONFIG_EN                        (1 << 31)
+#define PEX_STATUS_AND_COMMAND         0x004
+#define PXSAC_MABORT                   (1 << 29) /* Recieved Master Abort */
+
+/* PCI Express Configuration Address Register */
+
+/* PEX_CFG_ADDR_REG (PXCAR) */
+#define PXCAR_REG_NUM_OFFS             2
+#define PXCAR_REG_NUM_MAX              0x3F
+#define PXCAR_REG_NUM_MASK             (PXCAR_REG_NUM_MAX << PXCAR_REG_NUM_OFFS)
+#define PXCAR_FUNC_NUM_OFFS            8
+#define PXCAR_FUNC_NUM_MAX             0x7
+#define PXCAR_FUNC_NUM_MASK            (PXCAR_FUNC_NUM_MAX << PXCAR_FUNC_NUM_OFFS)
+#define PXCAR_DEVICE_NUM_OFFS          11
+#define PXCAR_DEVICE_NUM_MAX           0x1F
+#define PXCAR_DEVICE_NUM_MASK          (PXCAR_DEVICE_NUM_MAX << PXCAR_DEVICE_NUM_OFFS)
+#define PXCAR_BUS_NUM_OFFS             16
+#define PXCAR_BUS_NUM_MAX              0xFF
+#define PXCAR_BUS_NUM_MASK             (PXCAR_BUS_NUM_MAX << PXCAR_BUS_NUM_OFFS)
+#define PXCAR_EXT_REG_NUM_OFFS         24
+#define PXCAR_EXT_REG_NUM_MAX          0xF
+
+#define PXCAR_REAL_EXT_REG_NUM_OFFS     8
+#define PXCAR_REAL_EXT_REG_NUM_MASK     (0xF << PXCAR_REAL_EXT_REG_NUM_OFFS)
+
+
+#define PEX_CAPABILITIES_REG(if)       ((MV_PEX_IF_REGS_BASE(if)) + 0x60)
+#define PEX_LINK_CAPABILITIES_REG(if)  ((MV_PEX_IF_REGS_BASE(if)) + 0x6C)
+#define PEX_LINK_CTRL_STATUS_REG(if)   ((MV_PEX_IF_REGS_BASE(if)) + 0x70)
+#define PEX_LINK_CTRL_STATUS2_REG(if)  ((MV_PEX_IF_REGS_BASE(if)) + 0x90)
+#define PEX_CTRL_REG(if)               ((MV_PEX_IF_REGS_BASE(if)) + 0x1A00)
+#define PEX_STATUS_REG(if)             ((MV_PEX_IF_REGS_BASE(if)) + 0x1A04)
+#define PEX_COMPLT_TMEOUT_REG(if)      ((MV_PEX_IF_REGS_BASE(if)) + 0x1A10)
+#define PEX_PWR_MNG_EXT_REG(if)                ((MV_PEX_IF_REGS_BASE(if)) + 0x1A18)
+#define PEX_FLOW_CTRL_REG(if)          ((MV_PEX_IF_REGS_BASE(if)) + 0x1A20)
+#define PEX_DYNMC_WIDTH_MNG_REG(if)    ((MV_PEX_IF_REGS_BASE(if)) + 0x1A30)
+#define PEX_ROOT_CMPLX_SSPL_REG(if)    ((MV_PEX_IF_REGS_BASE(if)) + 0x1A0C)
+#define PEX_RAM_PARITY_CTRL_REG(if)    ((MV_PEX_IF_REGS_BASE(if)) + 0x1A50)
+#define PEX_DBG_CTRL_REG(if)           ((MV_PEX_IF_REGS_BASE(if)) + 0x1A60)
+#define PEX_DBG_STATUS_REG(if)         ((MV_PEX_IF_REGS_BASE(if)) + 0x1A64)
+
+#define PXLCSR_NEG_LNK_GEN_OFFS                16      /* Negotiated Link GEN */
+#define PXLCSR_NEG_LNK_GEN_MASK                (0xf << PXLCSR_NEG_LNK_GEN_OFFS)
+#define PXLCSR_NEG_LNK_GEN_1_1         (0x1 << PXLCSR_NEG_LNK_GEN_OFFS)
+#define PXLCSR_NEG_LNK_GEN_2_0         (0x2 << PXLCSR_NEG_LNK_GEN_OFFS)
+
+#define PEX_CFG_ADDR_REG(if)           ((MV_PEX_IF_REGS_BASE(if)) + 0x18F8)
+#define PEX_CFG_DATA_REG(if)           ((MV_PEX_IF_REGS_BASE(if)) + 0x18FC)
+#define PEX_CAUSE_REG(if)              ((MV_PEX_IF_REGS_BASE(if)) + 0x1900)
+
+#define PEX_CAPABILITY_REG             0x60
+#define PEX_DEV_CAPABILITY_REG         0x64
+#define PEX_DEV_CTRL_STAT_REG          0x68
+#define PEX_LINK_CAPABILITY_REG                0x6C
+#define PEX_LINK_CTRL_STAT_REG         0x70
+#define PEX_LINK_CTRL_STAT_2_REG       0x90
+
+#endif /* __BOARD_ENV_SPEC */
diff --git a/arch/arm/mvebu-common/serdes/high_speed_env_lib.c b/arch/arm/mvebu-common/serdes/high_speed_env_lib.c
new file mode 100644 (file)
index 0000000..702273a
--- /dev/null
@@ -0,0 +1,1572 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "high_speed_env_spec.h"
+#include "board_env_spec.h"
+
+#define        SERDES_VERION   "2.1.5"
+#define ENDED_OK       "High speed PHY - Ended Successfully\n"
+
+static const u8 serdes_cfg[][SERDES_LAST_UNIT] = BIN_SERDES_CFG;
+
+extern MV_BIN_SERDES_CFG *serdes_info_tbl[];
+
+extern u8 rd78460gp_twsi_dev[];
+extern u8 db88f78xx0rev2_twsi_dev[];
+
+u32 pex_cfg_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 offs);
+int pex_local_bus_num_set(u32 pex_if, u32 bus_num);
+int pex_local_dev_num_set(u32 pex_if, u32 dev_num);
+
+#define MV_BOARD_PEX_MODULE_ADDR               0x23
+#define MV_BOARD_PEX_MODULE_ID                 1
+#define MV_BOARD_ETM_MODULE_ID                 2
+
+#define        PEX_MODULE_DETECT               1
+#define        ETM_MODULE_DETECT               2
+
+#define PEX_MODE_GET(satr)             ((satr & 0x6) >> 1)
+#define PEX_CAPABILITY_GET(satr)       (satr & 1)
+#define MV_PEX_UNIT_TO_IF(pex_unit)    ((pex_unit < 3) ? (pex_unit * 4) : 9)
+
+/* Static parametes */
+static int config_module;
+static int switch_module;
+
+/* Local function */
+static u32 board_id_get(void)
+{
+#if defined(CONFIG_DB_88F78X60)
+       return DB_88F78XX0_BP_ID;
+#elif defined(CONFIG_RD_88F78460_SERVER)
+       return RD_78460_SERVER_ID;
+#elif defined(CONFIG_RD_78460_SERVER_REV2)
+       return RD_78460_SERVER_REV2_ID;
+#elif defined(CONFIG_DB_78X60_PCAC)
+       return DB_78X60_PCAC_ID;
+#elif defined(CONFIG_DB_88F78X60_REV2)
+       return DB_88F78XX0_BP_REV2_ID;
+#elif defined(CONFIG_RD_78460_NAS)
+       return RD_78460_NAS_ID;
+#elif defined(CONFIG_DB_78X60_AMC)
+       return DB_78X60_AMC_ID;
+#elif defined(CONFIG_DB_78X60_PCAC_REV2)
+       return DB_78X60_PCAC_REV2_ID;
+#elif defined(CONFIG_DB_784MP_GP)
+       return DB_784MP_GP_ID;
+#elif defined(CONFIG_RD_78460_CUSTOMER)
+       return RD_78460_CUSTOMER_ID;
+#else
+       /*
+        * Return 0 here for custom board as this should not be used
+        * for custom boards.
+        */
+       return 0;
+#endif
+}
+
+static u8 board_sat_r_get(u8 dev_num, u8 reg)
+{
+       u8 data;
+       u8 *dev;
+       u32 board_id = board_id_get();
+       int ret;
+
+       i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+       switch (board_id) {
+       case DB_784MP_GP_ID:
+               dev = rd78460gp_twsi_dev;
+
+               break;
+       case DB_88F78XX0_BP_ID:
+       case DB_88F78XX0_BP_REV2_ID:
+               dev = db88f78xx0rev2_twsi_dev;
+               break;
+
+       case DB_78X60_PCAC_ID:
+       case FPGA_88F78XX0_ID:
+       case DB_78X60_PCAC_REV2_ID:
+       case RD_78460_SERVER_REV2_ID:
+       default:
+               return 0;
+       }
+
+       /* Read MPP module ID */
+       ret = i2c_read(dev[dev_num], 0, 1, (u8 *)&data, 1);
+       if (ret)
+               return MV_ERROR;
+
+       return data;
+}
+
+static int board_modules_scan(void)
+{
+       u8 val;
+       u32 board_id = board_id_get();
+       int ret;
+
+       /* Perform scan only for DB board */
+       if ((board_id == DB_88F78XX0_BP_ID) ||
+           (board_id == DB_88F78XX0_BP_REV2_ID)) {
+               /* reset modules flags */
+               config_module = 0;
+
+               i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+               /* SERDES module (only PEX model is supported now) */
+               ret = i2c_read(MV_BOARD_PEX_MODULE_ADDR, 0, 1, (u8 *)&val, 1);
+               if (ret)
+                       return MV_ERROR;
+
+               if (val == MV_BOARD_PEX_MODULE_ID)
+                       config_module = PEX_MODULE_DETECT;
+               if (val == MV_BOARD_ETM_MODULE_ID)
+                       config_module = ETM_MODULE_DETECT;
+       } else if (board_id == RD_78460_NAS_ID) {
+               switch_module = 0;
+               if ((reg_read(GPP_DATA_IN_REG(2)) & MV_GPP66) == 0x0)
+                       switch_module = 1;
+       }
+
+       return MV_OK;
+}
+
+u32 pex_max_unit_get(void)
+{
+       /*
+        * TODO:
+        * Right now only MV78460 is supported. Other SoC's might need
+        * a different value here.
+        */
+       return MV_PEX_MAX_UNIT;
+}
+
+u32 pex_max_if_get(void)
+{
+       /*
+        * TODO:
+        * Right now only MV78460 is supported. Other SoC's might need
+        * a different value here.
+        */
+       return MV_PEX_MAX_IF;
+}
+
+u8 board_cpu_freq_get(void)
+{
+       u32 sar;
+       u32 sar_msb;
+
+       sar = reg_read(MPP_SAMPLE_AT_RESET(0));
+       sar_msb = reg_read(MPP_SAMPLE_AT_RESET(1));
+       return ((sar_msb & 0x100000) >> 17) | ((sar & 0xe00000) >> 21);
+}
+
+__weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
+{
+       u32 board_id;
+       u32 serdes_cfg_val = 0; /* default */
+
+       board_id = board_id_get();
+
+       switch (board_id) {
+       case DB_784MP_GP_ID:
+               serdes_cfg_val = 0;
+               break;
+       }
+
+       return &serdes_info_tbl[board_id - BOARD_ID_BASE][serdes_cfg_val];
+}
+
+u16 ctrl_model_get(void)
+{
+       /* Right now only MV78460 supported */
+       return MV_78460_DEV_ID;
+}
+
+u32 get_line_cfg(u32 line_num, MV_BIN_SERDES_CFG *info)
+{
+       if (line_num < 8)
+               return (info->line0_7 >> (line_num << 2)) & 0xF;
+       else
+               return (info->line8_15 >> ((line_num - 8) << 2)) & 0xF;
+}
+
+int serdes_phy_config(void)
+{
+       int status = MV_OK;
+       u32 line_cfg;
+       u8 line_num;
+       /* addr/value for each line @ every setup step */
+       u32 addr[16][11], val[16][11];
+       u8 pex_unit, pex_line_num;
+       u8 sgmii_port = 0;
+       u32 tmp;
+       u32 in_direct;
+       u8 max_serdes_lines;
+       MV_BIN_SERDES_CFG *info;
+       u8 satr11;
+       u8 sata_port;
+       u8 freq;
+       u8 device_rev;
+       u32 rx_high_imp_mode;
+       u16 ctrl_mode;
+       u32 board_id = board_id_get();
+       u32 pex_if;
+       u32 pex_if_num;
+
+       /*
+        * TODO:
+        * Right now we only support the MV78460 with 16 serdes lines
+        */
+       max_serdes_lines = 16;
+       if (max_serdes_lines == 0)
+               return MV_OK;
+
+       switch (board_id) {
+       case DB_78X60_AMC_ID:
+       case DB_78X60_PCAC_REV2_ID:
+       case RD_78460_CUSTOMER_ID:
+       case RD_78460_SERVER_ID:
+       case RD_78460_SERVER_REV2_ID:
+       case DB_78X60_PCAC_ID:
+               satr11 = (0x1 << 1) | 1;
+               break;
+       case FPGA_88F78XX0_ID:
+       case RD_78460_NAS_ID:
+               satr11 = (0x0 << 1) | 1;
+               break;
+       case DB_88F78XX0_BP_REV2_ID:
+       case DB_784MP_GP_ID:
+       case DB_88F78XX0_BP_ID:
+               satr11 = board_sat_r_get(1, 1);
+               if ((u8) MV_ERROR == (u8) satr11)
+                       return MV_ERROR;
+               break;
+       }
+
+       board_modules_scan();
+       memset(addr, 0, sizeof(addr));
+       memset(val, 0, sizeof(val));
+
+       /* Check if DRAM is already initialized  */
+       if (reg_read(REG_BOOTROM_ROUTINE_ADDR) &
+           (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) {
+               DEBUG_INIT_S("High speed PHY - Version: ");
+               DEBUG_INIT_S(SERDES_VERION);
+               DEBUG_INIT_S(" - 2nd boot - Skip\n");
+               return MV_OK;
+       }
+       DEBUG_INIT_S("High speed PHY - Version: ");
+       DEBUG_INIT_S(SERDES_VERION);
+       DEBUG_INIT_S(" (COM-PHY-V20)\n");
+
+       /*
+        * AVS :  disable AVS for frequency less than 1333
+        */
+       freq = board_cpu_freq_get();
+       device_rev = mv_ctrl_rev_get();
+
+       if (device_rev == 2) {  /*   for B0 only */
+               u32 cpu_avs;
+               u8 fabric_freq;
+               cpu_avs = reg_read(CPU_AVS_CONTROL2_REG);
+               DEBUG_RD_REG(CPU_AVS_CONTROL2_REG, cpu_avs);
+               cpu_avs &= ~(1 << 9);
+
+               if ((0x4 == freq) || (0xB == freq)) {
+                       u32 tmp2;
+
+                       tmp2 = reg_read(CPU_AVS_CONTROL0_REG);
+                       DEBUG_RD_REG(CPU_AVS_CONTROL0_REG, tmp2);
+                       /* cpu upper limit = 1.1V  cpu lower limit = 0.9125V  */
+                       tmp2 |= 0x0FF;
+                       reg_write(CPU_AVS_CONTROL0_REG, tmp2);
+                       DEBUG_WR_REG(CPU_AVS_CONTROL0_REG, tmp2);
+                       cpu_avs |= (1 << 9);    /* cpu avs enable */
+                       cpu_avs |= (1 << 18);   /* AvsAvddDetEn enable  */
+                       fabric_freq = (reg_read(MPP_SAMPLE_AT_RESET(0)) &
+                                      SAR0_FABRIC_FREQ_MASK) >> SAR0_FABRIC_FREQ_OFFSET;
+                       if ((0xB == freq) && (5 == fabric_freq)) {
+                               u32 core_avs;
+
+                               core_avs = reg_read(CORE_AVS_CONTROL_0REG);
+                               DEBUG_RD_REG(CORE_AVS_CONTROL_0REG, core_avs);
+
+                               /*
+                                * Set core lower limit = 0.9V &
+                                * core upper limit = 0.9125V
+                                */
+                               core_avs &= ~(0xff);
+                               core_avs |= 0x0E;
+                               reg_write(CORE_AVS_CONTROL_0REG, core_avs);
+                               DEBUG_WR_REG(CORE_AVS_CONTROL_0REG, core_avs);
+
+                               core_avs = reg_read(CORE_AVS_CONTROL_2REG);
+                               DEBUG_RD_REG(CORE_AVS_CONTROL_2REG, core_avs);
+                               core_avs |= (1 << 9);   /*  core AVS enable  */
+                               reg_write(CORE_AVS_CONTROL_2REG, core_avs);
+                               DEBUG_WR_REG(CORE_AVS_CONTROL_2REG, core_avs);
+
+                               tmp2 = reg_read(GENERAL_PURPOSE_RESERVED0_REG);
+                               DEBUG_RD_REG(GENERAL_PURPOSE_RESERVED0_REG,
+                                            tmp2);
+                               tmp2 |= 0x1;    /*  AvsCoreAvddDetEn enable   */
+                               reg_write(GENERAL_PURPOSE_RESERVED0_REG, tmp2);
+                               DEBUG_WR_REG(GENERAL_PURPOSE_RESERVED0_REG,
+                                            tmp2);
+                       }
+               }
+               reg_write(CPU_AVS_CONTROL2_REG, cpu_avs);
+               DEBUG_WR_REG(CPU_AVS_CONTROL2_REG, cpu_avs);
+       }
+
+       info = board_serdes_cfg_get(PEX_MODE_GET(satr11));
+       DEBUG_INIT_FULL_S("info->line0_7= 0x");
+       DEBUG_INIT_FULL_D(info->line0_7, 8);
+       DEBUG_INIT_FULL_S("   info->line8_15= 0x");
+       DEBUG_INIT_FULL_D(info->line8_15, 8);
+       DEBUG_INIT_FULL_S("\n");
+
+       if (info == NULL) {
+               DEBUG_INIT_S("Hight speed PHY Error #1\n");
+               return MV_ERROR;
+       }
+
+       if (config_module & ETM_MODULE_DETECT) {        /* step 0.9 ETM */
+               DEBUG_INIT_FULL_S("ETM module detect Step 0.9:\n");
+               reg_write(SERDES_LINE_MUX_REG_0_7, 0x11111111);
+               DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, 0x11111111);
+               info->pex_mode[1] = PEX_BUS_DISABLED;   /* pex unit 1 is configure for ETM */
+               mdelay(100);
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x002 << 16) | 0xf44d);       /* SETM0 - start calibration         */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x002 << 16) | 0xf44d);    /* SETM0 - start calibration         */
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x302 << 16) | 0xf44d);       /* SETM1 - start calibration         */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x302 << 16) | 0xf44d);    /* SETM1 - start calibration         */
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x001 << 16) | 0xf801);       /* SETM0 - SATA mode & 25MHz ref clk */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x001 << 16) | 0xf801);    /* SETM0 - SATA mode & 25MHz ref clk */
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x301 << 16) | 0xf801);       /* SETM1 - SATA mode & 25MHz ref clk */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x301 << 16) | 0xf801);    /* SETM1 - SATA mode & 25MHz ref clk */
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x011 << 16) | 0x0BFF);       /* SETM0 - G3 full swing AMP         */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x011 << 16) | 0x0BFF);    /* SETM0 - G3 full swing AMP         */
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x311 << 16) | 0x0BFF);       /* SETM1 - G3 full swing AMP         */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x311 << 16) | 0x0BFF);    /* SETM1 - G3 full swing AMP         */
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x023 << 16) | 0x0800);       /* SETM0 - 40 data bit width         */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x023 << 16) | 0x0800);    /* SETM0 - 40 data bit width         */
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x323 << 16) | 0x0800);       /* SETM1 - 40 data bit width         */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x323 << 16) | 0x0800);    /* SETM1 - 40 data bit width         */
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x046 << 16) | 0x0400);       /* lane0(serdes4)                    */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x046 << 16) | 0x0400);    /* lane0(serdes4)                    */
+               reg_write(PEX_PHY_ACCESS_REG(1), (0x346 << 16) | 0x0400);       /* lane3(serdes7)                    */
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(1), (0x346 << 16) | 0x0400);    /* lane3(serdes7)                    */
+       }
+
+       /* STEP -1 [PEX-Only] First phase of PEX-PIPE Configuration: */
+       DEBUG_INIT_FULL_S("Step 1: First phase of PEX-PIPE Configuration\n");
+       for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) {
+               if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+                       continue;
+
+               /* 1.   GLOB_CLK_CTRL Reset and Clock Control */
+               reg_write(PEX_PHY_ACCESS_REG(pex_unit), (0xC1 << 16) | 0x25);
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), (0xC1 << 16) | 0x25);
+
+               /* 2.   GLOB_TEST_CTRL Test Mode Control */
+               if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) {
+                       reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+                                 (0xC2 << 16) | 0x200);
+                       DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+                                    (0xC2 << 16) | 0x200);
+               }
+
+               /* 3.   GLOB_CLK_SRC_LO Clock Source Low */
+               if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) {
+                       reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+                                 (0xC3 << 16) | 0x0F);
+                       DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+                                    (0xC3 << 16) | 0x0F);
+               }
+
+               reg_write(PEX_PHY_ACCESS_REG(pex_unit), (0xC5 << 16) | 0x11F);
+               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+                            (0xC5 << 16) | 0x11F);
+       }
+
+       /*
+        * 2 Configure the desire PIN_PHY_GEN and do power down to the PU_PLL,
+        * PU_RX,PU_TX. (bits[12:5])
+        */
+       DEBUG_INIT_FULL_S("Step 2: Configure the desire PIN_PHY_GEN\n");
+       for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+               line_cfg = get_line_cfg(line_num, info);
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+                       continue;
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX])
+                       continue;
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) {
+                       switch (line_num) {
+                       case 4:
+                       case 6:
+                               sata_port = 0;
+                               break;
+                       case 5:
+                               sata_port = 1;
+                               break;
+                       default:
+                               DEBUG_INIT_C
+                                   ("SATA port error for serdes line: ",
+                                    line_num, 2);
+                               return MV_ERROR;
+                       }
+                       tmp = reg_read(SATA_LP_PHY_EXT_CTRL_REG(sata_port));
+                       DEBUG_RD_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+                       tmp &= ~((0x1ff << 5) | 0x7);
+                       tmp |= ((info->bus_speed & (1 << line_num)) != 0) ?
+                               (0x11 << 5) : 0x0;
+
+                       reg_write(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+                       DEBUG_WR_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+               }
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+                       /*
+                        * 4) Configure the desire PIN_PHY_GEN and do power
+                        * down to the PU_PLL,PU_RX,PU_TX. (bits[12:5])
+                        */
+                       tmp = reg_read(SGMII_SERDES_CFG_REG(0));
+                       DEBUG_RD_REG(SGMII_SERDES_CFG_REG(0), tmp);
+                       tmp &= ~((0x1ff << 5) | 0x7);
+                       tmp |= 0x660;
+                       reg_write(SGMII_SERDES_CFG_REG(0), tmp);
+                       DEBUG_WR_REG(SGMII_SERDES_CFG_REG(0), tmp);
+                       continue;
+               }
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0])
+                       sgmii_port = 0;
+               else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1])
+                       sgmii_port = 1;
+               else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2])
+                       sgmii_port = 2;
+               else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3])
+                       sgmii_port = 3;
+               else
+                       continue;
+
+               tmp = reg_read(SGMII_SERDES_CFG_REG(sgmii_port));
+               DEBUG_RD_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+               tmp &= ~((0x1ff << 5) | 0x7);
+               tmp |= (((info->bus_speed & (1 << line_num)) != 0) ?
+                       (0x88 << 5) : (0x66 << 5));
+               reg_write(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+               DEBUG_WR_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+       }
+
+       /* Step 3 - QSGMII enable */
+       DEBUG_INIT_FULL_S("Step 3 QSGMII enable\n");
+       for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+               line_cfg = get_line_cfg(line_num, info);
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+                       /* QSGMII Active bit set to true */
+                       tmp = reg_read(QSGMII_CONTROL_1_REG);
+                       DEBUG_RD_REG(QSGMII_CONTROL_1_REG, tmp);
+                       tmp |= (1 << 30);
+#ifdef ERRATA_GL_6572255
+                       tmp |= (1 << 27);
+#endif
+                       reg_write(QSGMII_CONTROL_1_REG, tmp);
+                       DEBUG_WR_REG(QSGMII_CONTROL_1_REG, tmp);
+               }
+       }
+
+       /* Step 4 - configure SERDES MUXes */
+       DEBUG_INIT_FULL_S("Step 4: Configure SERDES MUXes\n");
+       if (config_module & ETM_MODULE_DETECT) {
+               reg_write(SERDES_LINE_MUX_REG_0_7, 0x40041111);
+               DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, 0x40041111);
+       } else {
+               reg_write(SERDES_LINE_MUX_REG_0_7, info->line0_7);
+               DEBUG_WR_REG(SERDES_LINE_MUX_REG_0_7, info->line0_7);
+       }
+       reg_write(SERDES_LINE_MUX_REG_8_15, info->line8_15);
+       DEBUG_WR_REG(SERDES_LINE_MUX_REG_8_15, info->line8_15);
+
+       /* Step 5: Activate the RX High Impedance Mode  */
+       DEBUG_INIT_FULL_S("Step 5: Activate the RX High Impedance Mode\n");
+       rx_high_imp_mode = 0x8080;
+       if (device_rev == 2)    /*   for B0 only */
+               rx_high_imp_mode |= 4;
+
+       for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+               /* for each serdes lane */
+               DEBUG_INIT_FULL_S("SERDES  ");
+               DEBUG_INIT_FULL_D_10(line_num, 2);
+               line_cfg = get_line_cfg(line_num, info);
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED]) {
+                       DEBUG_INIT_FULL_S(" unconnected ***\n");
+                       continue;
+               }
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) {
+                       pex_unit = line_num >> 2;
+                       pex_line_num = line_num % 4;
+                       DEBUG_INIT_FULL_S(" - PEX unit ");
+                       DEBUG_INIT_FULL_D_10(pex_unit, 1);
+                       DEBUG_INIT_FULL_S(" line=  ");
+                       DEBUG_INIT_FULL_D_10(pex_line_num, 1);
+                       DEBUG_INIT_FULL_S("\n");
+
+                       /* Needed for PEX_PHY_ACCESS_REG macro */
+                       if ((line_num > 7) &&
+                           (info->pex_mode[3] == PEX_BUS_MODE_X8))
+                               /* lines 8 - 15 are belong to PEX3 in x8 mode */
+                               pex_unit = 3;
+
+                       if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+                               continue;
+
+                       /*
+                        * 8)  Activate the RX High Impedance Mode field
+                        * (bit [2]) in register /PCIe_USB Control (Each MAC
+                        * contain different Access to reach its
+                        * Serdes-Regfile).
+                        * [PEX-Only] Set bit[12]: The analog part latches idle
+                        * if PU_TX = 1 and PU_PLL =1.
+                        */
+
+                       /* Termination enable */
+                       if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1) {
+                               in_direct = (0x48 << 16) | (pex_line_num << 24) |
+                                       0x1000 | rx_high_imp_mode;      /* x1 */
+                       } else if ((info->pex_mode[pex_unit] ==
+                                   PEX_BUS_MODE_X4) && (pex_line_num == 0))
+                               in_direct = (0x48 << 16) | (pex_line_num << 24) |
+                                       0x1000 | (rx_high_imp_mode & 0xff);     /* x4 */
+                       else
+                               in_direct = 0;
+
+                       if (in_direct) {
+                               reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+                                         in_direct);
+                               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+                                            in_direct);
+                       }
+
+                       continue;
+               }
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) {
+                       /*
+                        * port 0 for serdes lines 4,6,  and port 1 for
+                        * serdes lines 5
+                        */
+                       sata_port = line_num & 1;
+                       DEBUG_INIT_FULL_S(" - SATA port  ");
+                       DEBUG_INIT_FULL_D_10(sata_port, 2);
+                       DEBUG_INIT_FULL_S("\n");
+                       reg_write(SATA_COMPHY_CTRL_REG(sata_port),
+                                 rx_high_imp_mode);
+                       DEBUG_WR_REG(SATA_COMPHY_CTRL_REG(sata_port),
+                                    rx_high_imp_mode);
+                       continue;
+               }
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+                       DEBUG_INIT_FULL_S(" - QSGMII\n");
+                       reg_write(SGMII_COMPHY_CTRL_REG(0), rx_high_imp_mode);
+                       DEBUG_WR_REG(SGMII_COMPHY_CTRL_REG(0),
+                                    rx_high_imp_mode);
+                       continue;
+               }
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0])
+                       sgmii_port = 0;
+               else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1])
+                       sgmii_port = 1;
+               else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2])
+                       sgmii_port = 2;
+               else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3])
+                       sgmii_port = 3;
+               else
+                       continue;
+               DEBUG_INIT_FULL_S(" - SGMII port  ");
+               DEBUG_INIT_FULL_D_10(sgmii_port, 2);
+               DEBUG_INIT_FULL_S("\n");
+               reg_write(SGMII_COMPHY_CTRL_REG(sgmii_port), rx_high_imp_mode);
+               DEBUG_WR_REG(SGMII_COMPHY_CTRL_REG(sgmii_port),
+                            rx_high_imp_mode);
+       }                       /* for each serdes lane */
+
+       /* Step 6 [PEX-Only] PEX-Main configuration (X4 or X1): */
+       DEBUG_INIT_FULL_S("Step 6: [PEX-Only] PEX-Main configuration (X4 or X1)\n");
+       tmp = reg_read(SOC_CTRL_REG);
+       DEBUG_RD_REG(SOC_CTRL_REG, tmp);
+       tmp &= 0x200;
+       if (info->pex_mode[0] == PEX_BUS_MODE_X1)
+               tmp |= PCIE0_QUADX1_EN;
+       if (info->pex_mode[1] == PEX_BUS_MODE_X1)
+               tmp |= PCIE1_QUADX1_EN;
+       if (((reg_read(MPP_SAMPLE_AT_RESET(0)) & PEX_CLK_100MHZ_MASK) >>
+            PEX_CLK_100MHZ_OFFSET) == 0x1)
+               tmp |= (PCIE0_CLK_OUT_EN_MASK | PCIE1_CLK_OUT_EN_MASK);
+
+       reg_write(SOC_CTRL_REG, tmp);
+       DEBUG_WR_REG(SOC_CTRL_REG, tmp);
+
+       /* 6.2 PCI Express Link Capabilities */
+       DEBUG_INIT_FULL_S("Step 6.2: [PEX-Only] PCI Express Link Capabilities\n");
+
+       for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+               line_cfg = get_line_cfg(line_num, info);
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) {
+                       /*
+                        * PCI Express Control
+                        * 0xX1A00 [0]:
+                        * 0x0 X4-Link.
+                        * 0x1 X1-Link
+                        */
+                       pex_unit = line_num >> 2;
+                       pex_if = MV_SERDES_NUM_TO_PEX_NUM(line_num);
+                       if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+                               continue;
+
+                       /*  set Common Clock Configuration */
+                       tmp = reg_read(PEX_LINK_CTRL_STATUS_REG(pex_if));
+                       DEBUG_RD_REG(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp);
+                       tmp |= (1 << 6);
+                       reg_write(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp);
+                       DEBUG_WR_REG(PEX_LINK_CTRL_STATUS_REG(pex_if), tmp);
+
+                       tmp = reg_read(PEX_LINK_CAPABILITIES_REG(pex_if));
+                       DEBUG_RD_REG(PEX_LINK_CAPABILITIES_REG(pex_if), tmp);
+                       tmp &= ~(0x3FF);
+                       if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X1)
+                               tmp |= (0x1 << 4);
+                       if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)
+                               tmp |= (0x4 << 4);
+                       if (0 == PEX_CAPABILITY_GET(satr11))
+                               tmp |= 0x1;
+                       else
+                               tmp |= 0x2;
+                       DEBUG_INIT_FULL_S("Step 6.2: PEX ");
+                       DEBUG_INIT_FULL_D(pex_if, 1);
+                       DEBUG_INIT_FULL_C(" set GEN", (tmp & 3), 1);
+                       reg_write(PEX_LINK_CAPABILITIES_REG(pex_if), tmp);
+                       DEBUG_WR_REG(PEX_LINK_CAPABILITIES_REG(pex_if), tmp);
+
+                       /*
+                        * If pex is X4, no need to pass thru the other
+                        * 3X1 serdes lines
+                        */
+                       if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)
+                               line_num += 3;
+               }
+       }
+
+       /*
+        * Step 7 [PEX-X4 Only] To create PEX-Link that contain 4-lanes you
+        * need to config the register SOC_Misc/General Purpose2
+        * (Address= 182F8)
+        */
+       DEBUG_INIT_FULL_S("Step 7: [PEX-X4 Only] To create PEX-Link\n");
+       tmp = reg_read(GEN_PURP_RES_2_REG);
+       DEBUG_RD_REG(GEN_PURP_RES_2_REG, tmp);
+
+       tmp &= 0xFFFF0000;
+       if (info->pex_mode[0] == PEX_BUS_MODE_X4)
+               tmp |= 0x0000000F;
+
+       if (info->pex_mode[1] == PEX_BUS_MODE_X4)
+               tmp |= 0x000000F0;
+
+       if (info->pex_mode[2] == PEX_BUS_MODE_X4)
+               tmp |= 0x00000F00;
+
+       if (info->pex_mode[3] == PEX_BUS_MODE_X4)
+               tmp |= 0x0000F000;
+
+       reg_write(GEN_PURP_RES_2_REG, tmp);
+       DEBUG_WR_REG(GEN_PURP_RES_2_REG, tmp);
+
+       /* Steps  8 , 9 ,10 - use prepared REG addresses and values */
+       DEBUG_INIT_FULL_S("Steps 7,8,9,10 and 11\n");
+
+       /* Prepare PHY parameters for each step according to  MUX selection */
+       for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+               /* for each serdes lane */
+
+               line_cfg = get_line_cfg(line_num, info);
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+                       continue;
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) {
+                       pex_unit = line_num >> 2;
+                       pex_line_num = line_num % 4;
+
+                       if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+                               continue;
+                       /*
+                        * 8)   Configure the desire PHY_MODE (bits [7:5])
+                        * and REF_FREF_SEL (bits[4:0]) in the register Power
+                        * and PLL Control (Each MAC contain different Access
+                        * to reach its Serdes-Regfile).
+                        */
+                       if (((info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) &&
+                            (0 == pex_line_num))
+                           || ((info->pex_mode[pex_unit] == PEX_BUS_MODE_X1))) {
+                               reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+                                         (0x01 << 16) | (pex_line_num << 24) |
+                                         0xFC60);
+                               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+                                            (0x01 << 16) | (pex_line_num << 24)
+                                            | 0xFC60);
+                               /*
+                                * Step 8.1: [PEX-Only] Configure Max PLL Rate
+                                * (bit 8 in  KVCO Calibration Control and
+                                * bits[10:9] in
+                                */
+                               /* Use Maximum PLL Rate(Bit 8) */
+                               reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+                                         (0x02 << 16) | (1 << 31) |
+                                         (pex_line_num << 24)); /* read command */
+                               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+                                            (0x02 << 16) | (1 << 31) |
+                                            (pex_line_num << 24));
+                               tmp = reg_read(PEX_PHY_ACCESS_REG(pex_unit));
+                               DEBUG_RD_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+                               tmp &= ~(1 << 31);
+                               tmp |= (1 << 8);
+                               reg_write(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+                               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+
+                               /* Use Maximum PLL Rate(Bits [10:9]) */
+                               reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+                                         (0x81 << 16) | (1 << 31) |
+                                         (pex_line_num << 24)); /* read command */
+                               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+                                            (0x81 << 16) | (1 << 31) |
+                                            (pex_line_num << 24));
+                               tmp = reg_read(PEX_PHY_ACCESS_REG(pex_unit));
+                               DEBUG_RD_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+                               tmp &= ~(1 << 31);
+                               tmp |= (3 << 9);
+                               reg_write(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+                               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit), tmp);
+                       }
+
+                       continue;
+               }
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) {
+                       /*
+                        * Port 0 for serdes lines 4,6,  and port 1 for serdes
+                        * lines 5
+                        */
+                       sata_port = line_num & 1;
+
+                       /*
+                        * 8) Configure the desire PHY_MODE (bits [7:5]) and
+                        * REF_FREF_SEL (bits[4:0]) in the register Power
+                        * and PLL Control (Each MAC contain different Access
+                        * to reach its Serdes-Regfile).
+                        */
+                       reg_write(SATA_PWR_PLL_CTRL_REG(sata_port), 0xF801);
+                       DEBUG_WR_REG(SATA_PWR_PLL_CTRL_REG(sata_port), 0xF801);
+
+                       /*  9)  Configure the desire SEL_BITS  */
+                       reg_write(SATA_DIG_LP_ENA_REG(sata_port), 0x400);
+                       DEBUG_WR_REG(SATA_DIG_LP_ENA_REG(sata_port), 0x400);
+
+                       /* 10)  Configure the desire REFCLK_SEL */
+
+                       reg_write(SATA_REF_CLK_SEL_REG(sata_port), 0x400);
+                       DEBUG_WR_REG(SATA_REF_CLK_SEL_REG(sata_port), 0x400);
+
+                       /* 11)  Power up to the PU_PLL,PU_RX,PU_TX.   */
+                       tmp = reg_read(SATA_LP_PHY_EXT_CTRL_REG(sata_port));
+                       DEBUG_RD_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+                       tmp |= 7;
+                       reg_write(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+                       DEBUG_WR_REG(SATA_LP_PHY_EXT_CTRL_REG(sata_port), tmp);
+
+                       continue;
+               }
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+                       /*
+                        * 8)   Configure the desire PHY_MODE (bits [7:5])
+                        * and REF_FREF_SEL (bits[4:0]) in the register
+                        */
+                       reg_write(SGMII_PWR_PLL_CTRL_REG(0), 0xF881);
+                       DEBUG_WR_REG(SGMII_PWR_PLL_CTRL_REG(0), 0xF881);
+
+                       /*
+                        * 9)   Configure the desire SEL_BITS (bits [11:0]
+                        * in register
+                        */
+                       reg_write(SGMII_DIG_LP_ENA_REG(0), 0x400);
+                       DEBUG_WR_REG(SGMII_DIG_LP_ENA_REG(0), 0x400);
+
+                       /*
+                        * 10)  Configure the desire REFCLK_SEL (bit [10])
+                        * in register
+                        */
+                       reg_write(SGMII_REF_CLK_SEL_REG(0), 0x400);
+                       DEBUG_WR_REG(SGMII_REF_CLK_SEL_REG(0), 0x400);
+
+                       /* 11)  Power up to the PU_PLL,PU_RX,PU_TX.  */
+                       tmp = reg_read(SGMII_SERDES_CFG_REG(0));
+                       DEBUG_RD_REG(SGMII_SERDES_CFG_REG(0), tmp);
+                       tmp |= 7;
+                       reg_write(SGMII_SERDES_CFG_REG(0), tmp);
+                       DEBUG_WR_REG(SGMII_SERDES_CFG_REG(0), tmp);
+                       continue;
+               }
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII0])
+                       sgmii_port = 0;
+               else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII1])
+                       sgmii_port = 1;
+               else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII2])
+                       sgmii_port = 2;
+               else if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SGMII3])
+                       sgmii_port = 3;
+               else
+                       continue;
+
+               /*
+                * 8)   Configure the desire PHY_MODE (bits [7:5]) and
+                * REF_FREF_SEL (bits[4:0]) in the register
+                */
+               reg_write(SGMII_PWR_PLL_CTRL_REG(sgmii_port), 0xF881);
+               DEBUG_WR_REG(SGMII_PWR_PLL_CTRL_REG(sgmii_port), 0xF881);
+
+               /* 9)   Configure the desire SEL_BITS (bits [11:0] in register */
+               reg_write(SGMII_DIG_LP_ENA_REG(sgmii_port), 0);
+               DEBUG_WR_REG(SGMII_DIG_LP_ENA_REG(sgmii_port), 0);
+
+               /* 10)  Configure the desire REFCLK_SEL (bit [10]) in register  */
+               reg_write(SGMII_REF_CLK_SEL_REG(sgmii_port), 0x400);
+               DEBUG_WR_REG(SGMII_REF_CLK_SEL_REG(sgmii_port), 0x400);
+
+               /* 11)  Power up to the PU_PLL,PU_RX,PU_TX.  */
+               tmp = reg_read(SGMII_SERDES_CFG_REG(sgmii_port));
+               DEBUG_RD_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+               tmp |= 7;
+               reg_write(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+               DEBUG_WR_REG(SGMII_SERDES_CFG_REG(sgmii_port), tmp);
+
+       }                       /* for each serdes lane */
+
+       /* Step 12 [PEX-Only] Last phase of PEX-PIPE Configuration */
+       DEBUG_INIT_FULL_S("Steps 12: [PEX-Only] Last phase of PEX-PIPE Configuration\n");
+       for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+               /* for each serdes lane */
+
+               line_cfg = get_line_cfg(line_num, info);
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+                       continue;
+
+               if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX]) {
+                       pex_unit = line_num >> 2;
+                       pex_line_num = line_num % 4;
+                       if (0 == pex_line_num) {
+                               reg_write(PEX_PHY_ACCESS_REG(pex_unit),
+                                         (0xC1 << 16) | 0x24);
+                               DEBUG_WR_REG(PEX_PHY_ACCESS_REG(pex_unit),
+                                            (0xC1 << 16) | 0x24);
+                       }
+               }
+       }
+
+       /*--------------------------------------------------------------*/
+       /* Step 13: Wait 15ms before checking results */
+       DEBUG_INIT_FULL_S("Steps 13: Wait 15ms before checking results");
+       mdelay(15);
+       tmp = 20;
+       while (tmp) {
+               status = MV_OK;
+               for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+                       u32 tmp;
+                       line_cfg = get_line_cfg(line_num, info);
+                       if (line_cfg ==
+                           serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+                               continue;
+
+                       if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_PEX])
+                               continue;
+
+                       if (line_cfg == serdes_cfg[line_num][SERDES_UNIT_SATA]) {
+                               /*
+                                * Port 0 for serdes lines 4,6,  and port 1
+                                * for serdes lines 5
+                                */
+                               sata_port = line_num & 1;
+
+                               tmp =
+                                   reg_read(SATA_LP_PHY_EXT_STAT_REG
+                                            (sata_port));
+                               DEBUG_RD_REG(SATA_LP_PHY_EXT_STAT_REG
+                                            (sata_port), tmp);
+                               if ((tmp & 0x7) != 0x7)
+                                       status = MV_ERROR;
+                               continue;
+                       }
+
+                       if (line_cfg ==
+                           serdes_cfg[line_num][SERDES_UNIT_QSGMII]) {
+                               tmp = reg_read(SGMII_SERDES_STAT_REG(0));
+                               DEBUG_RD_REG(SGMII_SERDES_STAT_REG(0), tmp);
+                               if ((tmp & 0x7) != 0x7)
+                                       status = MV_ERROR;
+                               continue;
+                       }
+
+                       if (line_cfg ==
+                           serdes_cfg[line_num][SERDES_UNIT_SGMII0])
+                               sgmii_port = 0;
+                       else if (line_cfg ==
+                                serdes_cfg[line_num][SERDES_UNIT_SGMII1])
+                               sgmii_port = 1;
+                       else if (line_cfg ==
+                                serdes_cfg[line_num][SERDES_UNIT_SGMII2])
+                               sgmii_port = 2;
+                       else if (line_cfg ==
+                                serdes_cfg[line_num][SERDES_UNIT_SGMII3])
+                               sgmii_port = 3;
+                       else
+                               continue;
+
+                       tmp = reg_read(SGMII_SERDES_STAT_REG(sgmii_port));
+                       DEBUG_RD_REG(SGMII_SERDES_STAT_REG(sgmii_port), tmp);
+                       if ((tmp & 0x7) != 0x7)
+                               status = MV_ERROR;
+               }
+
+               if (status == MV_OK)
+                       break;
+               mdelay(5);
+               tmp--;
+       }
+
+       /*
+        * Step14 [PEX-Only]  In order to configure RC/EP mode please write
+        * to register 0x0060 bits
+        */
+       DEBUG_INIT_FULL_S("Steps 14: [PEX-Only]  In order to configure\n");
+       for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) {
+               if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+                       continue;
+               tmp =
+                   reg_read(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)));
+               DEBUG_RD_REG(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)),
+                            tmp);
+               tmp &= ~(0xf << 20);
+               if (info->pex_type == MV_PEX_ROOT_COMPLEX)
+                       tmp |= (0x4 << 20);
+               else
+                       tmp |= (0x1 << 20);
+               reg_write(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)),
+                         tmp);
+               DEBUG_WR_REG(PEX_CAPABILITIES_REG(MV_PEX_UNIT_TO_IF(pex_unit)),
+                            tmp);
+       }
+
+       /*
+        * Step 15 [PEX-Only] Only for EP mode set to Zero bits 19 and 16 of
+        * register 0x1a60
+        */
+       DEBUG_INIT_FULL_S("Steps 15: [PEX-Only]  In order to configure\n");
+       for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) {
+               if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED)
+                       continue;
+               if (info->pex_type == MV_PEX_END_POINT) {
+                       tmp =
+                           reg_read(PEX_DBG_CTRL_REG
+                                    (MV_PEX_UNIT_TO_IF(pex_unit)));
+                       DEBUG_RD_REG(PEX_DBG_CTRL_REG
+                                    (MV_PEX_UNIT_TO_IF(pex_unit)), tmp);
+                       tmp &= 0xfff6ffff;
+                       reg_write(PEX_DBG_CTRL_REG(MV_PEX_UNIT_TO_IF(pex_unit)),
+                                 tmp);
+                       DEBUG_WR_REG(PEX_DBG_CTRL_REG
+                                    (MV_PEX_UNIT_TO_IF(pex_unit)), tmp);
+               }
+       }
+
+       if (info->serdes_m_phy_change) {
+               MV_SERDES_CHANGE_M_PHY *serdes_m_phy_change;
+               u32 bus_speed;
+               for (line_num = 0; line_num < max_serdes_lines; line_num++) {
+                       line_cfg = get_line_cfg(line_num, info);
+                       if (line_cfg ==
+                           serdes_cfg[line_num][SERDES_UNIT_UNCONNECTED])
+                               continue;
+                       serdes_m_phy_change = info->serdes_m_phy_change;
+                       bus_speed = info->bus_speed & (1 << line_num);
+                       while (serdes_m_phy_change->type !=
+                              SERDES_UNIT_UNCONNECTED) {
+                               switch (serdes_m_phy_change->type) {
+                               case SERDES_UNIT_PEX:
+                                       if (line_cfg != SERDES_UNIT_PEX)
+                                               break;
+                                       pex_unit = line_num >> 2;
+                                       pex_line_num = line_num % 4;
+                                       if (info->pex_mode[pex_unit] ==
+                                           PEX_BUS_DISABLED)
+                                               break;
+                                       if ((info->pex_mode[pex_unit] ==
+                                            PEX_BUS_MODE_X4) && pex_line_num)
+                                               break;
+
+                                       if (bus_speed) {
+                                               reg_write(PEX_PHY_ACCESS_REG
+                                                         (pex_unit),
+                                                         (pex_line_num << 24) |
+                                                         serdes_m_phy_change->val_hi_speed);
+                                               DEBUG_WR_REG(PEX_PHY_ACCESS_REG
+                                                            (pex_unit),
+                                                            (pex_line_num <<
+                                                             24) |
+                                                            serdes_m_phy_change->val_hi_speed);
+                                       } else {
+                                               reg_write(PEX_PHY_ACCESS_REG
+                                                         (pex_unit),
+                                                         (pex_line_num << 24) |
+                                                         serdes_m_phy_change->val_low_speed);
+                                               DEBUG_WR_REG(PEX_PHY_ACCESS_REG
+                                                            (pex_unit),
+                                                            (pex_line_num <<
+                                                             24) |
+                                                            serdes_m_phy_change->val_low_speed);
+                                       }
+                                       break;
+                               case SERDES_UNIT_SATA:
+                                       if (line_cfg != SERDES_UNIT_SATA)
+                                               break;
+                                       /*
+                                        * Port 0 for serdes lines 4,6,  and
+                                        * port 1 for serdes lines 5
+                                        */
+                                       sata_port = line_num & 1;
+                                       if (bus_speed) {
+                                               reg_write(SATA_BASE_REG
+                                                         (sata_port) |
+                                                         serdes_m_phy_change->reg_hi_speed,
+                                                         serdes_m_phy_change->val_hi_speed);
+                                               DEBUG_WR_REG(SATA_BASE_REG
+                                                            (sata_port) |
+                                                            serdes_m_phy_change->reg_hi_speed,
+                                                            serdes_m_phy_change->val_hi_speed);
+                                       } else {
+                                               reg_write(SATA_BASE_REG
+                                                         (sata_port) |
+                                                         serdes_m_phy_change->reg_low_speed,
+                                                         serdes_m_phy_change->val_low_speed);
+                                               DEBUG_WR_REG(SATA_BASE_REG
+                                                            (sata_port) |
+                                                            serdes_m_phy_change->reg_low_speed,
+                                                            serdes_m_phy_change->val_low_speed);
+                                       }
+                                       break;
+                               case SERDES_UNIT_SGMII0:
+                               case SERDES_UNIT_SGMII1:
+                               case SERDES_UNIT_SGMII2:
+                               case SERDES_UNIT_SGMII3:
+                                       if (line_cfg == serdes_cfg[line_num]
+                                           [SERDES_UNIT_SGMII0])
+                                               sgmii_port = 0;
+                                       else if (line_cfg ==
+                                                serdes_cfg[line_num]
+                                                [SERDES_UNIT_SGMII1])
+                                               sgmii_port = 1;
+                                       else if (line_cfg ==
+                                                serdes_cfg[line_num]
+                                                [SERDES_UNIT_SGMII2])
+                                               sgmii_port = 2;
+                                       else if (line_cfg ==
+                                                serdes_cfg[line_num]
+                                                [SERDES_UNIT_SGMII3])
+                                               sgmii_port = 3;
+                                       else
+                                               break;
+                                       if (bus_speed) {
+                                               reg_write(MV_ETH_REGS_BASE
+                                                         (sgmii_port) |
+                                                         serdes_m_phy_change->reg_hi_speed,
+                                                         serdes_m_phy_change->val_hi_speed);
+                                               DEBUG_WR_REG(MV_ETH_REGS_BASE
+                                                            (sgmii_port) |
+                                                            serdes_m_phy_change->reg_hi_speed,
+                                                            serdes_m_phy_change->val_hi_speed);
+                                       } else {
+                                               reg_write(MV_ETH_REGS_BASE
+                                                         (sgmii_port) |
+                                                         serdes_m_phy_change->reg_low_speed,
+                                                         serdes_m_phy_change->val_low_speed);
+                                               DEBUG_WR_REG(MV_ETH_REGS_BASE
+                                                            (sgmii_port) |
+                                                            serdes_m_phy_change->reg_low_speed,
+                                                            serdes_m_phy_change->val_low_speed);
+                                       }
+                                       break;
+                               case SERDES_UNIT_QSGMII:
+                                       if (line_cfg != SERDES_UNIT_QSGMII)
+                                               break;
+                                       if (bus_speed) {
+                                               reg_write
+                                                   (serdes_m_phy_change->reg_hi_speed,
+                                                    serdes_m_phy_change->val_hi_speed);
+                                               DEBUG_WR_REG
+                                                   (serdes_m_phy_change->reg_hi_speed,
+                                                    serdes_m_phy_change->val_hi_speed);
+                                       } else {
+                                               reg_write
+                                                   (serdes_m_phy_change->reg_low_speed,
+                                                    serdes_m_phy_change->val_low_speed);
+                                               DEBUG_WR_REG
+                                                   (serdes_m_phy_change->reg_low_speed,
+                                                    serdes_m_phy_change->val_low_speed);
+                                       }
+                                       break;
+                               default:
+                                       break;
+                               }
+                               serdes_m_phy_change++;
+                       }
+               }
+       }
+
+       /* Step 16 [PEX-Only] Training Enable */
+       DEBUG_INIT_FULL_S("Steps 16: [PEX-Only] Training Enable");
+       tmp = reg_read(SOC_CTRL_REG);
+       DEBUG_RD_REG(SOC_CTRL_REG, tmp);
+       tmp &= ~(0x0F);
+       for (pex_unit = 0; pex_unit < pex_max_unit_get(); pex_unit++) {
+               reg_write(PEX_CAUSE_REG(pex_unit), 0);
+               DEBUG_WR_REG(PEX_CAUSE_REG(pex_unit), 0);
+               if (info->pex_mode[pex_unit] != PEX_BUS_DISABLED)
+                       tmp |= (0x1 << pex_unit);
+       }
+       reg_write(SOC_CTRL_REG, tmp);
+       DEBUG_WR_REG(SOC_CTRL_REG, tmp);
+
+       /* Step 17: Speed change to target speed and width */
+       {
+               u32 tmp_reg, tmp_pex_reg;
+               u32 addr;
+               u32 first_busno, next_busno;
+               u32 max_link_width = 0;
+               u32 neg_link_width = 0;
+               pex_if_num = pex_max_if_get();
+               mdelay(150);
+               DEBUG_INIT_FULL_C("step 17: max_if= 0x", pex_if_num, 1);
+               next_busno = 0;
+               for (pex_if = 0; pex_if < pex_if_num; pex_if++) {
+                       line_num = (pex_if <= 8) ? pex_if : 12;
+                       line_cfg = get_line_cfg(line_num, info);
+                       if (line_cfg != serdes_cfg[line_num][SERDES_UNIT_PEX])
+                               continue;
+                       pex_unit = (pex_if < 9) ? (pex_if >> 2) : 3;
+                       DEBUG_INIT_FULL_S("step 17:  PEX");
+                       DEBUG_INIT_FULL_D(pex_if, 1);
+                       DEBUG_INIT_FULL_C("  pex_unit= ", pex_unit, 1);
+
+                       if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) {
+                               DEBUG_INIT_FULL_C("PEX disabled interface ",
+                                                 pex_if, 1);
+                               if (pex_if < 8)
+                                       pex_if += 3;
+                               continue;
+                       }
+                       first_busno = next_busno;
+                       if ((info->pex_type == MV_PEX_END_POINT) &&
+                           (0 == pex_if)) {
+                               if ((pex_if < 8) && (info->pex_mode[pex_unit] ==
+                                                    PEX_BUS_MODE_X4))
+                                       pex_if += 3;
+                               continue;
+                       }
+
+                       tmp = reg_read(PEX_DBG_STATUS_REG(pex_if));
+                       DEBUG_RD_REG(PEX_DBG_STATUS_REG(pex_if), tmp);
+                       if ((tmp & 0x7f) == 0x7e) {
+                               next_busno++;
+                               tmp = reg_read(PEX_LINK_CAPABILITIES_REG(pex_if));
+                               max_link_width = tmp;
+                               DEBUG_RD_REG((PEX_LINK_CAPABILITIES_REG
+                                             (pex_if)), tmp);
+                               max_link_width = ((max_link_width >> 4) & 0x3F);
+                               neg_link_width =
+                                   reg_read(PEX_LINK_CTRL_STATUS_REG(pex_if));
+                               DEBUG_RD_REG((PEX_LINK_CTRL_STATUS_REG(pex_if)),
+                                            neg_link_width);
+                               neg_link_width = ((neg_link_width >> 20) & 0x3F);
+                               if (max_link_width > neg_link_width) {
+                                       tmp &= ~(0x3F << 4);
+                                       tmp |= (neg_link_width << 4);
+                                       reg_write(PEX_LINK_CAPABILITIES_REG
+                                                 (pex_if), tmp);
+                                       DEBUG_WR_REG((PEX_LINK_CAPABILITIES_REG
+                                                     (pex_if)), tmp);
+                                       mdelay(1);      /* wait 1ms before reading  capability for speed */
+                                       DEBUG_INIT_S("PEX");
+                                       DEBUG_INIT_D(pex_if, 1);
+                                       DEBUG_INIT_C(": change width to X",
+                                                    neg_link_width, 1);
+                               }
+                               tmp_pex_reg =
+                                   reg_read((PEX_CFG_DIRECT_ACCESS
+                                             (pex_if,
+                                              PEX_LINK_CAPABILITY_REG)));
+                               DEBUG_RD_REG((PEX_CFG_DIRECT_ACCESS
+                                             (pex_if,
+                                              PEX_LINK_CAPABILITY_REG)),
+                                            tmp_pex_reg);
+                               tmp_pex_reg &= (0xF);
+                               if (tmp_pex_reg == 0x2) {
+                                       tmp_reg =
+                                           (reg_read
+                                            (PEX_CFG_DIRECT_ACCESS
+                                             (pex_if,
+                                              PEX_LINK_CTRL_STAT_REG)) &
+                                            0xF0000) >> 16;
+                                       DEBUG_RD_REG(PEX_CFG_DIRECT_ACCESS
+                                                    (pex_if,
+                                                     PEX_LINK_CTRL_STAT_REG),
+                                                    tmp_pex_reg);
+                                       /* check if the link established is GEN1 */
+                                       if (tmp_reg == 0x1) {
+                                               pex_local_bus_num_set(pex_if,
+                                                                     first_busno);
+                                               pex_local_dev_num_set(pex_if,
+                                                                     1);
+
+                                               DEBUG_INIT_FULL_S("** Link is Gen1, check the EP capability\n");
+                                               /* link is Gen1, check the EP capability */
+                                               addr =
+                                                   pex_cfg_read(pex_if,
+                                                                first_busno, 0,
+                                                                0,
+                                                                0x34) & 0xFF;
+                                               DEBUG_INIT_FULL_C("pex_cfg_read: return addr=0x%x",
+                                                    addr, 4);
+                                               if (addr == 0xff) {
+                                                       DEBUG_INIT_FULL_C("pex_cfg_read: return 0xff -->PEX (%d): Detected No Link.",
+                                                                         pex_if, 1);
+                                                       continue;
+                                               }
+                                               while ((pex_cfg_read
+                                                       (pex_if, first_busno, 0,
+                                                        0,
+                                                        addr) & 0xFF) !=
+                                                      0x10) {
+                                                       addr =
+                                                           (pex_cfg_read
+                                                            (pex_if,
+                                                             first_busno, 0, 0,
+                                                             addr) & 0xFF00) >>
+                                                           8;
+                                               }
+                                               if ((pex_cfg_read
+                                                    (pex_if, first_busno, 0, 0,
+                                                     addr + 0xC) & 0xF) >=
+                                                   0x2) {
+                                                       tmp =
+                                                           reg_read
+                                                           (PEX_LINK_CTRL_STATUS2_REG
+                                                            (pex_if));
+                                                       DEBUG_RD_REG
+                                                           (PEX_LINK_CTRL_STATUS2_REG
+                                                            (pex_if), tmp);
+                                                       tmp &= ~(0x1 | 1 << 1);
+                                                       tmp |= (1 << 1);
+                                                       reg_write
+                                                           (PEX_LINK_CTRL_STATUS2_REG
+                                                            (pex_if), tmp);
+                                                       DEBUG_WR_REG
+                                                           (PEX_LINK_CTRL_STATUS2_REG
+                                                            (pex_if), tmp);
+
+                                                       tmp =
+                                                           reg_read
+                                                           (PEX_CTRL_REG
+                                                            (pex_if));
+                                                       DEBUG_RD_REG
+                                                           (PEX_CTRL_REG
+                                                            (pex_if), tmp);
+                                                       tmp |= (1 << 10);
+                                                       reg_write(PEX_CTRL_REG
+                                                                 (pex_if),
+                                                                 tmp);
+                                                       DEBUG_WR_REG
+                                                           (PEX_CTRL_REG
+                                                            (pex_if), tmp);
+                                                       mdelay(10);     /* We need to wait 10ms before reading the PEX_DBG_STATUS_REG in order not to read the status of the former state */
+                                                       DEBUG_INIT_FULL_S
+                                                           ("Gen2 client!\n");
+                                               } else {
+                                                       DEBUG_INIT_FULL_S
+                                                           ("GEN1 client!\n");
+                                               }
+                                       }
+                               }
+                       } else {
+                               DEBUG_INIT_FULL_S("PEX");
+                               DEBUG_INIT_FULL_D(pex_if, 1);
+                               DEBUG_INIT_FULL_S(" : Detected No Link. Status Reg(0x");
+                               DEBUG_INIT_FULL_D(PEX_DBG_STATUS_REG(pex_if),
+                                                 8);
+                               DEBUG_INIT_FULL_C(") = 0x", tmp, 8);
+                       }
+
+                       if ((pex_if < 8) &&
+                           (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4))
+                               pex_if += 3;
+               }
+       }
+
+       /* Step 18: update pex DEVICE ID */
+       {
+               u32 devId;
+               pex_if_num = pex_max_if_get();
+               ctrl_mode = ctrl_model_get();
+               for (pex_if = 0; pex_if < pex_if_num; pex_if++) {
+                       pex_unit = (pex_if < 9) ? (pex_if >> 2) : 3;
+                       if (info->pex_mode[pex_unit] == PEX_BUS_DISABLED) {
+                               if ((pex_if < 8) &&
+                                   (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4))
+                                       pex_if += 3;
+                               continue;
+                       }
+
+                       devId = reg_read(PEX_CFG_DIRECT_ACCESS(
+                                                pex_if, PEX_DEVICE_AND_VENDOR_ID));
+                       devId &= 0xFFFF;
+                       devId |= ((ctrl_mode << 16) & 0xffff0000);
+                       DEBUG_INIT_S("Update Device ID PEX");
+                       DEBUG_INIT_D(pex_if, 1);
+                       DEBUG_INIT_D(devId, 8);
+                       DEBUG_INIT_S("\n");
+                       reg_write(PEX_CFG_DIRECT_ACCESS
+                                 (pex_if, PEX_DEVICE_AND_VENDOR_ID), devId);
+                       if ((pex_if < 8) &&
+                           (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4))
+                               pex_if += 3;
+               }
+               DEBUG_INIT_S("Update PEX Device ID 0x");
+               DEBUG_INIT_D(ctrl_mode, 4);
+               DEBUG_INIT_S("0\n");
+       }
+       tmp = reg_read(PEX_DBG_STATUS_REG(0));
+       DEBUG_RD_REG(PEX_DBG_STATUS_REG(0), tmp);
+
+       DEBUG_INIT_S(ENDED_OK);
+       return MV_OK;
+}
+
+/* PEX configuration space read write */
+
+/*
+ * pex_cfg_read - Read from configuration space
+ *
+ * DESCRIPTION:
+ *       This function performs a 32 bit read from PEX configuration space.
+ *       It supports both type 0 and type 1 of Configuration Transactions
+ *       (local and over bridge). In order to read from local bus segment, use
+ *       bus number retrieved from mvPexLocalBusNumGet(). Other bus numbers
+ *       will result configuration transaction of type 1 (over bridge).
+ *
+ * INPUT:
+ *       pex_if   - PEX interface number.
+ *       bus     - PEX segment bus number.
+ *       dev     - PEX device number.
+ *       func    - Function number.
+ *       offss - Register offset.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       32bit register data, 0xffffffff on error
+ *
+ */
+u32 pex_cfg_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 offs)
+{
+       u32 pex_data = 0;
+       u32 local_dev, local_bus;
+       u32 val;
+
+       if (pex_if >= MV_PEX_MAX_IF)
+               return 0xFFFFFFFF;
+
+       if (dev >= MAX_PEX_DEVICES) {
+               DEBUG_INIT_C("pex_cfg_read: ERR. device number illigal ", dev,
+                            1);
+               return 0xFFFFFFFF;
+       }
+
+       if (func >= MAX_PEX_FUNCS) {
+               DEBUG_INIT_C("pex_cfg_read: ERR. function num illigal ", func,
+                            1);
+               return 0xFFFFFFFF;
+       }
+
+       if (bus >= MAX_PEX_BUSSES) {
+               DEBUG_INIT_C("pex_cfg_read: ERR. bus number illigal ", bus, 1);
+               return MV_ERROR;
+       }
+       val = reg_read(PEX_STATUS_REG(pex_if));
+
+       local_dev =
+           ((val & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS);
+       local_bus =
+           ((val & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS);
+
+       /* Speed up the process. In case on no link, return MV_ERROR */
+       if ((dev != local_dev) || (bus != local_bus)) {
+               pex_data = reg_read(PEX_STATUS_REG(pex_if));
+
+               if ((pex_data & PXSR_DL_DOWN))
+                       return MV_ERROR;
+       }
+
+       /*
+        * In PCI Express we have only one device number
+        * and this number is the first number we encounter else that the
+        * local_dev spec pex define return on config read/write on any device
+        */
+       if (bus == local_bus) {
+               if (local_dev == 0) {
+                       /*
+                        * If local dev is 0 then the first number we encounter
+                        * after 0 is 1
+                        */
+                       if ((dev != 1) && (dev != local_dev))
+                               return MV_ERROR;
+               } else {
+                       /*
+                        * If local dev is not 0 then the first number we
+                        * encounter is 0
+                        */
+                       if ((dev != 0) && (dev != local_dev))
+                               return MV_ERROR;
+               }
+       }
+
+       /* Creating PEX address to be passed */
+       pex_data = (bus << PXCAR_BUS_NUM_OFFS);
+       pex_data |= (dev << PXCAR_DEVICE_NUM_OFFS);
+       pex_data |= (func << PXCAR_FUNC_NUM_OFFS);
+       pex_data |= (offs & PXCAR_REG_NUM_MASK);        /* lgacy register space */
+       /* extended register space */
+       pex_data |= (((offs & PXCAR_REAL_EXT_REG_NUM_MASK) >>
+                    PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS);
+
+       pex_data |= PXCAR_CONFIG_EN;
+
+       /* Write the address to the PEX configuration address register */
+       reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data);
+
+       /*
+        * In order to let the PEX controller absorbed the address of the read
+        * transaction we perform a validity check that the address was written
+        */
+       if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if)))
+               return MV_ERROR;
+
+       /* cleaning Master Abort */
+       reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND),
+                   PXSAC_MABORT);
+       /* Read the Data returned in the PEX Data register */
+       pex_data = reg_read(PEX_CFG_DATA_REG(pex_if));
+
+       DEBUG_INIT_FULL_C(" --> ", pex_data, 4);
+
+       return pex_data;
+}
+
+/*
+ * pex_local_bus_num_set - Set PEX interface local bus number.
+ *
+ * DESCRIPTION:
+ *       This function sets given PEX interface its local bus number.
+ *       Note: In case the PEX interface is PEX-X, the information is read-only.
+ *
+ * INPUT:
+ *       pex_if  - PEX interface number.
+ *       bus_num - Bus number.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_NOT_ALLOWED in case PEX interface is PEX-X.
+ *             MV_BAD_PARAM on bad parameters ,
+ *       otherwise MV_OK
+ *
+ */
+int pex_local_bus_num_set(u32 pex_if, u32 bus_num)
+{
+       u32 val;
+
+       if (bus_num >= MAX_PEX_BUSSES) {
+               DEBUG_INIT_C("pex_local_bus_num_set: ERR. bus number illigal %d\n",
+                    bus_num, 4);
+               return MV_ERROR;
+       }
+
+       val = reg_read(PEX_STATUS_REG(pex_if));
+       val &= ~PXSR_PEX_BUS_NUM_MASK;
+       val |= (bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
+       reg_write(PEX_STATUS_REG(pex_if), val);
+
+       return MV_OK;
+}
+
+/*
+ * pex_local_dev_num_set - Set PEX interface local device number.
+ *
+ * DESCRIPTION:
+ *       This function sets given PEX interface its local device number.
+ *       Note: In case the PEX interface is PEX-X, the information is read-only.
+ *
+ * INPUT:
+ *       pex_if  - PEX interface number.
+ *       dev_num - Device number.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_NOT_ALLOWED in case PEX interface is PEX-X.
+ *             MV_BAD_PARAM on bad parameters ,
+ *       otherwise MV_OK
+ *
+ */
+int pex_local_dev_num_set(u32 pex_if, u32 dev_num)
+{
+       u32 val;
+
+       if (pex_if >= MV_PEX_MAX_IF)
+               return MV_BAD_PARAM;
+
+       val = reg_read(PEX_STATUS_REG(pex_if));
+       val &= ~PXSR_PEX_DEV_NUM_MASK;
+       val |= (dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
+       reg_write(PEX_STATUS_REG(pex_if), val);
+
+       return MV_OK;
+}
diff --git a/arch/arm/mvebu-common/serdes/high_speed_env_spec.c b/arch/arm/mvebu-common/serdes/high_speed_env_spec.c
new file mode 100644 (file)
index 0000000..115ec2c
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "high_speed_env_spec.h"
+
+MV_SERDES_CHANGE_M_PHY serdes_change_m_phy[] = {
+       /* SERDES TYPE, Low REG OFFS, Low REG VALUE, Hi REG OFS, Hi REG VALUE */
+       {
+               /* PEX: Change of Slew Rate port0   */
+               SERDES_UNIT_PEX, 0x0,
+               (0x0F << 16) | 0x2a21, 0x0, (0x0F << 16) | 0x2a21
+       }, {
+               /* PEX: Change PLL BW port0                   */
+               SERDES_UNIT_PEX, 0x0,
+               (0x4F << 16) | 0x6219, 0x0, (0x4F << 16) | 0x6219
+       }, {
+               /* SATA: Slew rate change port 0  */
+               SERDES_UNIT_SATA, 0x0083C, 0x8a31, 0x0083C, 0x8a31
+       }, {
+               /* SATA: Slew rate change port 0  */
+               SERDES_UNIT_SATA, 0x00834, 0xc928, 0x00834, 0xc928
+       }, {
+               /* SATA: Slew rate change port 0  */
+               SERDES_UNIT_SATA, 0x00838, 0x30f0, 0x00838, 0x30f0
+       }, {
+               /* SATA: Slew rate change port 0  */
+               SERDES_UNIT_SATA, 0x00840, 0x30f5, 0x00840, 0x30f5
+       }, {
+               /* SGMII: FFE setting Port0         */
+               SERDES_UNIT_SGMII0, 0x00E18, 0x989F, 0x00E18, 0x989F
+       }, {
+               /* SGMII: SELMUP and SELMUF Port0   */
+               SERDES_UNIT_SGMII0, 0x00E38, 0x10FA, 0x00E38, 0x10FA
+       }, {
+               /* SGMII: Amplitude new setting gen2 Port3 */
+               SERDES_UNIT_SGMII0, 0x00E34, 0xC968, 0x00E34, 0xC66C
+       }, {
+               /* QSGMII: Amplitude and slew rate change  */
+               SERDES_UNIT_QSGMII, 0x72E34, 0xaa58, 0x72E34, 0xaa58
+       }, {
+               /* QSGMII: SELMUP and SELMUF               */
+               SERDES_UNIT_QSGMII, 0x72e38, 0x10aF, 0x72e38, 0x10aF
+       }, {
+               /* QSGMII: 0x72e18                         */
+               SERDES_UNIT_QSGMII, 0x72e18, 0x98AC, 0x72e18, 0x98AC
+       }, {
+               /* Null terminated */
+               SERDES_UNIT_UNCONNECTED, 0, 0
+       }
+};
+
+MV_BIN_SERDES_CFG db88f78xx0_serdes_cfg[] = {
+       /* Z1B */
+       {MV_PEX_ROOT_COMPLEX, 0x32221111, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy},                  /* Default */
+       {MV_PEX_ROOT_COMPLEX, 0x31211111, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_MODE_X1, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy},                  /* PEX module */
+       /* Z1A */
+       {MV_PEX_ROOT_COMPLEX, 0x32220000, 0x00000000,
+        {PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED,
+         PEX_BUS_DISABLED}, 0x0030, serdes_change_m_phy}, /* Default - Z1A */
+       {MV_PEX_ROOT_COMPLEX, 0x31210000, 0x00000000,
+        {PEX_BUS_DISABLED, PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+        0x0030, serdes_change_m_phy}   /* PEX module - Z1A */
+};
+
+MV_BIN_SERDES_CFG db88f78xx0rev2_serdes_cfg[] = {
+       /* A0 */
+       {MV_PEX_ROOT_COMPLEX, 0x33221111, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy}, /* Default: No Pex module, PEX0 x1, disabled */
+       {MV_PEX_ROOT_COMPLEX, 0x33211111, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_MODE_X1, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy}, /* Pex module, PEX0 x1, PEX1 x1 */
+       {MV_PEX_ROOT_COMPLEX, 0x33221111, 0x11111111,
+        {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy}, /* no Pex module, PEX0 x4, PEX1 disabled */
+       {MV_PEX_ROOT_COMPLEX, 0x33211111, 0x11111111,
+        {PEX_BUS_MODE_X4, PEX_BUS_MODE_X1, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy}, /* Pex module, PEX0 x4, PEX1 x1 */
+       {MV_PEX_ROOT_COMPLEX, 0x11111111, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy}, /* Pex module, PEX0 x1, PEX1 x4 */
+       {MV_PEX_ROOT_COMPLEX, 0x11111111, 0x11111111,
+        {PEX_BUS_MODE_X4, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy}, /* Pex module, PEX0 x4, PEX1 x4 */
+};
+
+MV_BIN_SERDES_CFG rd78460nas_serdes_cfg[] = {
+       {MV_PEX_ROOT_COMPLEX, 0x00223001, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy}, /* Default */
+       {MV_PEX_ROOT_COMPLEX, 0x33320201, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x00f4, serdes_change_m_phy}, /* Switch module */
+};
+
+MV_BIN_SERDES_CFG rd78460_serdes_cfg[] = {
+       {MV_PEX_ROOT_COMPLEX, 0x22321111, 0x00000000,
+        {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+        0x0010, serdes_change_m_phy}, /* CPU0 */
+       {MV_PEX_ROOT_COMPLEX, 0x00321111, 0x00000000,
+        {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+        0x0010, serdes_change_m_phy} /* CPU1-3 */
+};
+
+MV_BIN_SERDES_CFG rd78460server_rev2_serdes_cfg[] = {
+       {MV_PEX_ROOT_COMPLEX, 0x00321111, 0x00000000,
+        {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+        0x0010, serdes_change_m_phy}, /* CPU0 */
+       {MV_PEX_ROOT_COMPLEX, 0x00321111, 0x00000000,
+        {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+        0x0010, serdes_change_m_phy} /* CPU1-3 */
+};
+
+MV_BIN_SERDES_CFG db78X60pcac_serdes_cfg[] = {
+       {MV_PEX_END_POINT, 0x22321111, 0x00000000,
+        {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+        0x0010, serdes_change_m_phy}   /* Default */
+};
+
+MV_BIN_SERDES_CFG db78X60pcacrev2_serdes_cfg[] = {
+       {MV_PEX_END_POINT, 0x23321111, 0x00000000,
+        {PEX_BUS_MODE_X4, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+        0x0010, serdes_change_m_phy}   /* Default */
+};
+
+MV_BIN_SERDES_CFG fpga88f78xx0_serdes_cfg[] = {
+       {MV_PEX_ROOT_COMPLEX, 0x00000000, 0x00000000,
+        {PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED, PEX_BUS_DISABLED},
+        0x0000, serdes_change_m_phy}   /* No PEX in FPGA */
+};
+
+MV_BIN_SERDES_CFG db78X60amc_serdes_cfg[] = {
+       {MV_PEX_ROOT_COMPLEX, 0x33111111, 0x00010001,
+        {PEX_BUS_MODE_X4, PEX_BUS_MODE_X1, PEX_BUS_MODE_X1, PEX_BUS_MODE_X1},
+        0x0030, serdes_change_m_phy}   /* Default */
+};
+
+/*
+ * ARMADA-XP CUSTOMER BOARD
+ */
+MV_BIN_SERDES_CFG rd78460customer_serdes_cfg[] = {
+       {MV_PEX_ROOT_COMPLEX, 0x00223001, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x00000030, serdes_change_m_phy}, /* Default */
+       {MV_PEX_ROOT_COMPLEX, 0x33320201, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x00000030, serdes_change_m_phy}, /* Switch module */
+};
+
+MV_BIN_SERDES_CFG rd78460AXP_GP_serdes_cfg[] = {
+       {MV_PEX_ROOT_COMPLEX, 0x00223001, 0x11111111,
+        {PEX_BUS_MODE_X1, PEX_BUS_DISABLED, PEX_BUS_MODE_X4, PEX_BUS_MODE_X4},
+        0x0030, serdes_change_m_phy}   /* Default */
+};
+
+MV_BIN_SERDES_CFG *serdes_info_tbl[] = {
+       db88f78xx0_serdes_cfg,
+       rd78460_serdes_cfg,
+       db78X60pcac_serdes_cfg,
+       fpga88f78xx0_serdes_cfg,
+       db88f78xx0rev2_serdes_cfg,
+       rd78460nas_serdes_cfg,
+       db78X60amc_serdes_cfg,
+       db78X60pcacrev2_serdes_cfg,
+       rd78460server_rev2_serdes_cfg,
+       rd78460AXP_GP_serdes_cfg,
+       rd78460customer_serdes_cfg
+};
+
+u8 rd78460gp_twsi_dev[] = { 0x4C, 0x4D, 0x4E };
+u8 db88f78xx0rev2_twsi_dev[] = { 0x4C, 0x4D, 0x4E, 0x4F };
diff --git a/arch/arm/mvebu-common/serdes/high_speed_env_spec.h b/arch/arm/mvebu-common/serdes/high_speed_env_spec.h
new file mode 100644 (file)
index 0000000..e5aa1b0
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __HIGHSPEED_ENV_SPEC_H
+#define __HIGHSPEED_ENV_SPEC_H
+
+#include "../../../drivers/ddr/mvebu/ddr3_hw_training.h"
+
+typedef enum {
+       SERDES_UNIT_UNCONNECTED = 0x0,
+       SERDES_UNIT_PEX         = 0x1,
+       SERDES_UNIT_SATA        = 0x2,
+       SERDES_UNIT_SGMII0      = 0x3,
+       SERDES_UNIT_SGMII1      = 0x4,
+       SERDES_UNIT_SGMII2      = 0x5,
+       SERDES_UNIT_SGMII3      = 0x6,
+       SERDES_UNIT_QSGMII      = 0x7,
+       SERDES_UNIT_SETM        = 0x8,
+       SERDES_LAST_UNIT
+} MV_BIN_SERDES_UNIT_INDX;
+
+
+typedef enum {
+       PEX_BUS_DISABLED        = 0,
+       PEX_BUS_MODE_X1         = 1,
+       PEX_BUS_MODE_X4         = 2,
+       PEX_BUS_MODE_X8         = 3
+} MV_PEX_UNIT_CFG;
+
+typedef enum pex_type {
+       MV_PEX_ROOT_COMPLEX,    /* root complex device */
+       MV_PEX_END_POINT        /* end point device */
+} MV_PEX_TYPE;
+
+typedef struct serdes_change_m_phy {
+       MV_BIN_SERDES_UNIT_INDX type;
+       u32 reg_low_speed;
+       u32 val_low_speed;
+       u32 reg_hi_speed;
+       u32 val_hi_speed;
+} MV_SERDES_CHANGE_M_PHY;
+
+/*
+ * Configuration per SERDES line. Each nibble is MV_SERDES_LINE_TYPE
+ */
+typedef struct board_serdes_conf {
+       MV_PEX_TYPE pex_type; /* MV_PEX_ROOT_COMPLEX MV_PEX_END_POINT */
+       u32 line0_7; /* Lines 0 to 7 SERDES MUX one nibble per line */
+       u32 line8_15; /* Lines 8 to 15 SERDES MUX one nibble per line */
+       MV_PEX_UNIT_CFG pex_mode[4];
+
+       /*
+        * Bus speed - one bit per SERDES line:
+        *              Low speed (0)           High speed (1)
+        * PEX          2.5 G (10 bit)          5 G (20 bit)
+        * SATA         1.5 G                   3 G
+        * SGMII        1.25 Gbps               3.125 Gbps
+        */
+       u32     bus_speed;
+
+       MV_SERDES_CHANGE_M_PHY *serdes_m_phy_change;
+} MV_BIN_SERDES_CFG;
+
+
+#define BIN_SERDES_CFG {       \
+       {0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 0 */       \
+       {0, 1, -1 , -1, -1, -1, -1, -1,  2}, /* Lane 1 */       \
+       {0, 1, -1 ,  2, -1, -1, -1, -1,  3}, /* Lane 2 */       \
+       {0, 1, -1 , -1,  2, -1, -1,  3, -1}, /* Lane 3 */       \
+       {0, 1,  2 , -1, -1,  3, -1, -1,  4}, /* Lane 4 */       \
+       {0, 1,  2 , -1,  3, -1, -1,  4, -1}, /* Lane 5 */       \
+       {0, 1,  2 ,  4, -1,  3, -1, -1, -1}, /* Lane 6 */       \
+       {0, 1, -1 ,  2, -1, -1,  3, -1,  4}, /* Lane 7*/        \
+       {0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 8 */       \
+       {0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 9 */       \
+       {0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 10 */      \
+       {0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 11 */      \
+       {0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 12 */      \
+       {0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 13 */      \
+       {0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 14 */      \
+       {0, 1, -1 , -1, -1, -1, -1, -1, -1}, /* Lane 15 */      \
+}
+
+#endif /* __HIGHSPEED_ENV_SPEC_H */
diff --git a/arch/arm/mvebu-common/u-boot-spl.lds b/arch/arm/mvebu-common/u-boot-spl.lds
new file mode 100644 (file)
index 0000000..eee1db4
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+ *
+ * (C) Copyright 2010
+ * Texas Instruments, <www.ti.com>
+ *     Aneesh V <aneesh@ti.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
+               LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+               LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+       .text      :
+       {
+               __start = .;
+               arch/arm/cpu/armv7/start.o      (.text*)
+               *(.text*)
+               *(.vectors)
+       } >.sram
+
+       . = ALIGN(4);
+       .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
+
+       . = ALIGN(4);
+       .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
+
+       . = ALIGN(4);
+       .u_boot_list : {
+               KEEP(*(SORT(.u_boot_list*_i2c_*)));
+       } >.sram
+
+       . = ALIGN(4);
+       __image_copy_end = .;
+
+       .end :
+       {
+               *(.__end)
+       }
+
+       .bss :
+       {
+               . = ALIGN(4);
+               __bss_start = .;
+               *(.bss*)
+               . = ALIGN(4);
+               __bss_end = .;
+       } >.sdram
+}
index 98bbf794fa7d736cbefa735d90ea1f0b790bcad0..2b817be61a5dc254915886d603169ce89c046932 100644 (file)
@@ -15,3 +15,8 @@ endif
 CONFIG_STANDALONE_LOAD_ADDR ?= 0x80F00000
 
 PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__
+
+ifeq ($(CONFIG_SPL_BUILD),)
+PLATFORM_CPPFLAGS += -fPIC
+endif
+__HAVE_ARCH_GENERIC_BOARD := y
index 227842f6a483a585a36574fa5857557c00affc61..aa34f45befe1ec5817f5c0485ccf8a996f12f38a 100644 (file)
@@ -13,49 +13,52 @@ void _hw_exception_handler (void)
 {
        int address = 0;
        int state = 0;
+
        /* loading address of exception EAR */
-       MFS (address, rear);
+       MFS(address, rear);
        /* loading excetpion state register ESR */
-       MFS (state, resr);
-       printf ("Hardware exception at 0x%x address\n", address);
+       MFS(state, resr);
+       printf("Hardware exception at 0x%x address\n", address);
+       R17(address);
+       printf("Return address from exception 0x%x\n", address);
        switch (state & 0x1f) { /* mask on exception cause */
        case 0x1:
-               puts ("Unaligned data access exception\n");
+               puts("Unaligned data access exception\n");
                break;
        case 0x2:
-               puts ("Illegal op-code exception\n");
+               puts("Illegal op-code exception\n");
                break;
        case 0x3:
-               puts ("Instruction bus error exception\n");
+               puts("Instruction bus error exception\n");
                break;
        case 0x4:
-               puts ("Data bus error exception\n");
+               puts("Data bus error exception\n");
                break;
        case 0x5:
-               puts ("Divide by zero exception\n");
+               puts("Divide by zero exception\n");
                break;
 #ifdef MICROBLAZE_V5
        case 0x7:
                puts("Priviledged or stack protection violation exception\n");
                break;
        case 0x1000:
-               puts ("Exception in delay slot\n");
+               puts("Exception in delay slot\n");
                break;
 #endif
        default:
-               puts ("Undefined cause\n");
+               puts("Undefined cause\n");
                break;
        }
-       printf ("Unaligned %sword access\n", ((state & 0x800) ? "" : "half"));
-       printf ("Unaligned %s access\n", ((state & 0x400) ? "store" : "load"));
-       printf ("Register R%x\n", (state & 0x3E) >> 5);
-       hang ();
+       printf("Unaligned %sword access\n", ((state & 0x800) ? "" : "half"));
+       printf("Unaligned %s access\n", ((state & 0x400) ? "store" : "load"));
+       printf("Register R%x\n", (state & 0x3E) >> 5);
+       hang();
 }
 
 #ifdef CONFIG_SYS_USR_EXCEP
 void _exception_handler (void)
 {
-       puts ("User vector_exception\n");
-       hang ();
+       puts("User vector_exception\n");
+       hang();
 }
 #endif
index 9364e2fa9c9b0fb1e810ad2d2f88a6cd7deafdd0..b6d6610f2fd70ec6f3410b42c27a9d2013572183 100644 (file)
 #include <asm/microblaze_intc.h>
 #include <asm/asm.h>
 
-#undef DEBUG_INT
-
 void enable_interrupts(void)
 {
+       debug("Enable interrupts for the whole CPU\n");
        MSRSET(0x2);
 }
 
@@ -50,12 +49,11 @@ static void enable_one_interrupt(int irq)
        offset <<= irq;
        mask = intc->ier;
        intc->ier = (mask | offset);
-#ifdef DEBUG_INT
-       printf("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
-               intc->ier);
-       printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-               intc->iar, intc->mer);
-#endif
+
+       debug("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
+             intc->ier);
+       debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+             intc->iar, intc->mer);
 }
 
 static void disable_one_interrupt(int irq)
@@ -66,12 +64,11 @@ static void disable_one_interrupt(int irq)
        offset <<= irq;
        mask = intc->ier;
        intc->ier = (mask & ~offset);
-#ifdef DEBUG_INT
-       printf("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
-               intc->ier);
-       printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-               intc->iar, intc->mer);
-#endif
+
+       debug("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
+             intc->ier);
+       debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+             intc->iar, intc->mer);
 }
 
 int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
@@ -88,12 +85,12 @@ int install_interrupt_handler(int irq, interrupt_handler_t *hdlr, void *arg)
                act->handler = hdlr;
                act->arg = arg;
                act->count = 0;
-               enable_one_interrupt (irq);
+               enable_one_interrupt(irq);
                return 0;
        }
 
        /* Disable */
-       act->handler = (interrupt_handler_t *) def_hdlr;
+       act->handler = (interrupt_handler_t *)def_hdlr;
        act->arg = (void *)irq;
        disable_one_interrupt(irq);
        return 1;
@@ -107,18 +104,17 @@ static void intc_init(void)
        intc->iar = 0xFFFFFFFF;
        /* XIntc_Start - hw_interrupt enable and all interrupt enable */
        intc->mer = 0x3;
-#ifdef DEBUG_INT
-       printf("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-               intc->iar, intc->mer);
-#endif
+
+       debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+             intc->iar, intc->mer);
 }
 
-int interrupts_init(void)
+int interrupt_init(void)
 {
        int i;
 
 #if defined(CONFIG_SYS_INTC_0_ADDR) && defined(CONFIG_SYS_INTC_0_NUM)
-       intc = (microblaze_intc_t *) (CONFIG_SYS_INTC_0_ADDR);
+       intc = (microblaze_intc_t *)CONFIG_SYS_INTC_0_ADDR;
        irq_no = CONFIG_SYS_INTC_0_NUM;
 #endif
        if (irq_no) {
@@ -130,7 +126,7 @@ int interrupts_init(void)
 
                /* initialize irq list */
                for (i = 0; i < irq_no; i++) {
-                       vecs[i].handler = (interrupt_handler_t *) def_hdlr;
+                       vecs[i].handler = (interrupt_handler_t *)def_hdlr;
                        vecs[i].arg = (void *)i;
                        vecs[i].count = 0;
                }
@@ -147,31 +143,29 @@ void interrupt_handler(void)
 {
        int irqs = intc->ivr;   /* find active interrupt */
        int mask = 1;
-#ifdef DEBUG_INT
        int value;
-       printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
-               intc->iar, intc->mer);
-       R14(value);
-       printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
-#endif
        struct irq_action *act = vecs + irqs;
 
-#ifdef DEBUG_INT
-       printf
-           ("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
-            act->handler, act->count, act->arg);
+       debug("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+             intc->iar, intc->mer);
+#ifdef DEBUG
+       R14(value);
 #endif
-       act->handler (act->arg);
+       debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
+
+       debug("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
+             (u32)act->handler, act->count, (u32)act->arg);
+       act->handler(act->arg);
        act->count++;
 
        intc->iar = mask << irqs;
 
-#ifdef DEBUG_INT
-       printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
-               intc->ier, intc->iar, intc->mer);
+       debug("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
+             intc->ier, intc->iar, intc->mer);
+#ifdef DEBUG
        R14(value);
-       printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
 #endif
+       debug("Interrupt handler on %x line, r14 %x\n", irqs, value);
 }
 
 #if defined(CONFIG_CMD_IRQ)
@@ -186,10 +180,10 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, const char *argv[])
                      "-----------------------------\n");
 
                for (i = 0; i < irq_no; i++) {
-                       if (act->handler != (interrupt_handler_t *) def_hdlr) {
+                       if (act->handler != (interrupt_handler_t *)def_hdlr) {
                                printf("%02d  %08x  %08x  %d\n", i,
-                                       (int)act->handler, (int)act->arg,
-                                                               act->count);
+                                      (int)act->handler, (int)act->arg,
+                                      act->count);
                        }
                        act++;
                }
index 24015898b0aa172f798f3468781abf55b7311499..5cfe1516bfcd65fd82f8843b2271ada36990add8 100644 (file)
        .text
        .global _interrupt_handler
 _interrupt_handler:
-       swi     r2, r1, -4
-       swi     r3, r1, -8
-       swi     r4, r1, -12
-       swi     r5, r1, -16
-       swi     r6, r1, -20
-       swi     r7, r1, -24
-       swi     r8, r1, -28
-       swi     r9, r1, -32
-       swi     r10, r1, -36
-       swi     r11, r1, -40
-       swi     r12, r1, -44
-       swi     r13, r1, -48
-       swi     r14, r1, -52
-       swi     r15, r1, -56
-       swi     r16, r1, -60
-       swi     r17, r1, -64
-       swi     r18, r1, -68
-       swi     r19, r1, -72
-       swi     r20, r1, -76
-       swi     r21, r1, -80
-       swi     r22, r1, -84
-       swi     r23, r1, -88
-       swi     r24, r1, -92
-       swi     r25, r1, -96
-       swi     r26, r1, -100
-       swi     r27, r1, -104
-       swi     r28, r1, -108
-       swi     r29, r1, -112
-       swi     r30, r1, -116
-       swi     r31, r1, -120
        addik   r1, r1, -124
+       swi     r2, r1, 4
+       swi     r3, r1, 8
+       swi     r4, r1, 12
+       swi     r5, r1, 16
+       swi     r6, r1, 20
+       swi     r7, r1, 24
+       swi     r8, r1, 28
+       swi     r9, r1, 32
+       swi     r10, r1, 36
+       swi     r11, r1, 40
+       swi     r12, r1, 44
+       swi     r13, r1, 48
+       swi     r14, r1, 52
+       swi     r15, r1, 56
+       swi     r16, r1, 60
+       swi     r17, r1, 64
+       swi     r18, r1, 68
+       swi     r19, r1, 72
+       swi     r20, r1, 76
+       swi     r21, r1, 80
+       swi     r22, r1, 84
+       swi     r23, r1, 88
+       swi     r24, r1, 92
+       swi     r25, r1, 96
+       swi     r26, r1, 100
+       swi     r27, r1, 104
+       swi     r28, r1, 108
+       swi     r29, r1, 112
+       swi     r30, r1, 116
+       swi     r31, r1, 120
        brlid   r15, interrupt_handler
        nop
+       lwi     r31, r1, 120
+       lwi     r30, r1, 116
+       lwi     r29, r1, 112
+       lwi     r28, r1, 108
+       lwi     r27, r1, 104
+       lwi     r26, r1, 100
+       lwi     r25, r1, 96
+       lwi     r24, r1, 92
+       lwi     r23, r1, 88
+       lwi     r22, r1, 84
+       lwi     r21, r1, 80
+       lwi     r20, r1, 76
+       lwi     r19, r1, 72
+       lwi     r18, r1, 68
+       lwi     r17, r1, 64
+       lwi     r16, r1, 60
+       lwi     r15, r1, 56
+       lwi     r14, r1, 52
+       lwi     r13, r1, 48
+       lwi     r12, r1, 44
+       lwi     r11, r1, 40
+       lwi     r10, r1, 36
+       lwi     r9, r1, 32
+       lwi     r8, r1, 28
+       lwi     r7, r1, 24
+       lwi     r6, r1, 20
+       lwi     r5, r1, 16
+       lwi     r4, r1, 12
+       lwi     r3, r1, 8
+       lwi     r2, r1, 4
        addik   r1, r1, 124
-       lwi     r31, r1, -120
-       lwi     r30, r1, -116
-       lwi     r29, r1, -112
-       lwi     r28, r1, -108
-       lwi     r27, r1, -104
-       lwi     r26, r1, -100
-       lwi     r25, r1, -96
-       lwi     r24, r1, -92
-       lwi     r23, r1, -88
-       lwi     r22, r1, -84
-       lwi     r21, r1, -80
-       lwi     r20, r1, -76
-       lwi     r19, r1, -72
-       lwi     r18, r1, -68
-       lwi     r17, r1, -64
-       lwi     r16, r1, -60
-       lwi     r15, r1, -56
-       lwi     r14, r1, -52
-       lwi     r13, r1, -48
-       lwi     r12, r1, -44
-       lwi     r11, r1, -40
-       lwi     r10, r1, -36
-       lwi     r9, r1, -32
-       lwi     r8, r1, -28
-       lwi     r7, r1, -24
-       lwi     r6, r1, -20
-       lwi     r5, r1, -16
-       lwi     r4, r1, -12
-       lwi     r3, r1, -8
-       lwi     r2, r1, -4
-
        rtid    r14, 0
        nop
        .size _interrupt_handler,.-_interrupt_handler
index 091226133e4fa2c1ae7a2182622951ae8eb74d05..2cc0a2da89e16e48c8c8786e892aeece71af02fa 100644 (file)
@@ -25,8 +25,6 @@ u32 spl_boot_device(void)
 /* Board initialization after bss clearance */
 void spl_board_init(void)
 {
-       gd = (gd_t *)CONFIG_SPL_STACK_ADDR;
-
        /* enable console uart printing */
        preloader_console_init();
 }
index 84c29e54091e68819891f165a30d6c0eeac1c285..953d3a15eef21c391f611bf01b346d187d79246f 100644 (file)
@@ -29,8 +29,12 @@ _start:
        addi    r1, r0, CONFIG_SPL_STACK_ADDR
        mts     rshr, r1
        addi    r1, r1, -4      /* Decrement SP to top of memory */
+#else
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
+       addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
 #else
        addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET
+#endif
        mts     rshr, r1
        addi    r1, r1, -4      /* Decrement SP to top of memory */
 
@@ -129,7 +133,7 @@ _start:
        /* Flush cache before enable cache */
        addik   r5, r0, 0
        addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
-flush: bralid r15, flush_cache
+       bralid r15, flush_cache
        nop
 
        /* enable instruction and data cache */
@@ -150,12 +154,28 @@ clear_bss:
        bnei    r6, 2b
 3:     /* jumping to board_init */
 #ifndef CONFIG_SPL_BUILD
+       or      r5, r0, r0      /* flags - empty */
+       addi    r31, r0, _gd
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
+       addi    r6, r0, CONFIG_SYS_INIT_SP_OFFSET
+       swi     r6, r31, GD_MALLOC_BASE
+#endif
        brai    board_init_f
 #else
+       addi    r31, r0, _gd
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
+       addi    r6, r0, CONFIG_SPL_STACK_ADDR
+       swi     r6, r31, GD_MALLOC_BASE
+#endif
        brai    board_init_r
 #endif
 1:     bri     1b
 
+ .section .bss
+.align 4
+_gd:
+         .space  GENERATED_GBL_DATA_SIZE
+
 #ifndef CONFIG_SPL_BUILD
 /*
  * Read 16bit little endian
@@ -189,4 +209,108 @@ out16:    bslli   r3, r6, 8
        rtsd    r15, 8
        or      r0, r0, r0
        .end    out16
+
+/*
+ * Relocate u-boot
+ */
+       .text
+       .global relocate_code
+       .ent    relocate_code
+       .align  2
+relocate_code:
+       /*
+        * r5 - start_addr_sp
+        * r6 - new_gd
+        * r7 - reloc_addr
+        */
+       addi    r1, r5, 0 /* Start to use new SP */
+       addi    r31, r6, 0 /* Start to use new GD */
+
+       add     r23, r0, r7 /* Move reloc addr to r23 */
+       /* Relocate text and data - r12 temp value */
+       addi    r21, r0, _start
+       addi    r22, r0, __end - 4 /* Include BSS too */
+
+       rsub    r6, r21, r22
+       or      r5, r0, r0
+1:     lw      r12, r21, r5 /* Load u-boot data */
+       sw      r12, r23, r5 /* Write zero to loc */
+       cmp     r12, r5, r6 /* Check if we have reach the end */
+       bneid   r12, 1b
+       addi    r5, r5, 4 /* Increment to next loc - relocate code */
+
+       /* R23 points to the base address. */
+       add     r23, r0, r7 /* Move reloc addr to r23 */
+       addi    r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
+       rsub    r23, r24, r23 /* keep - this is already here gd->reloc_off */
+
+       addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
+       lwi     r7, r0, 0x28
+       swi     r6, r0, 0x28 /* used first unused MB vector */
+       lbui    r10, r0, 0x28 /* used first unused MB vector */
+       swi     r7, r0, 0x28
+
+#ifdef CONFIG_SYS_USR_EXCEP
+       addik   r6, r0, _exception_handler
+       addk    r6, r6, r23 /* add offset */
+       sw      r6, r1, r0
+       lhu     r7, r1, r10
+       rsubi   r8, r10, 0xa
+       sh      r7, r0, r8
+       rsubi   r8, r10, 0xe
+       sh      r6, r0, r8
+#endif
+       addik   r6, r0, _hw_exception_handler
+       addk    r6, r6, r23 /* add offset */
+       sw      r6, r1, r0
+       lhu     r7, r1, r10
+       rsubi   r8, r10, 0x22
+       sh      r7, r0, r8
+       rsubi   r8, r10, 0x26
+       sh      r6, r0, r8
+
+       addik   r6, r0, _interrupt_handler
+       addk    r6, r6, r23 /* add offset */
+       sw      r6, r1, r0
+       lhu     r7, r1, r10
+       rsubi   r8, r10, 0x12
+       sh      r7, r0, r8
+       rsubi   r8, r10, 0x16
+       sh      r6, r0, r8
+
+       /* Check if GOT exist */
+       addik   r21, r23, _got_start
+       addik   r22, r23, _got_end
+       cmpu    r12, r21, r22
+       beqi    r12, 2f /* No GOT table - jump over */
+
+       /* Skip last 3 entries plus 1 because of loop boundary below */
+       addik   r22, r22, -0x10
+
+        /* Relocate the GOT. */
+3:     lw      r12, r21, r0 /* Load entry */
+       addk    r12, r12, r23 /* Add reloc offset */
+       sw      r12, r21, r0 /* Save entry back */
+
+       cmpu    r12, r21, r22 /* Check if this cross boundary */
+       bneid   r12, 3b
+       addik   r21. r21, 4
+
+       /* Update pointer to GOT */
+       mfs     r20, rpc
+       addik   r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
+       addk    r20, r20, r23
+
+       /* Flush caches to ensure consistency */
+       addik   r5, r0, 0
+       addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
+       bralid  r15, flush_cache
+       nop
+
+2:     addi    r5, r31, 0 /* gd is initialized in board_r.c */
+       addi    r6, r0, CONFIG_SYS_TEXT_BASE
+       addi    r12, r23, board_init_r
+       bra     r12 /* Jump to relocated code */
+
+       .end    relocate_code
 #endif
index 96353cd96ca7903c08ea0f9fb1db8fadf83cfd59..c60336ca5ca839ab0bef3ed39a188e4eb6792808 100644 (file)
@@ -37,6 +37,12 @@ SECTIONS
                __data_end = .;
        }
 
+       . = ALIGN(4);
+       .u_boot_list : {
+               KEEP(*(SORT(.u_boot_list*)));
+       }
+       __init_end = . ;
+
        .bss ALIGN(0x4):
        {
                __bss_start = .;
index fdad20753d3244ad10ac7a7ae8513cc2bc0b7bdf..2502a0db2b147716bc0f99e92df2f00c46c4274c 100644 (file)
@@ -29,17 +29,23 @@ SECTIONS
        .data ALIGN(0x4):
        {
                __data_start = .;
-#ifdef CONFIG_OF_EMBED
-               dts/built-in.o (.data)
-#endif
                *(.data)
                __data_end = .;
        }
 
+       .got ALIGN(4):
+       {
+               _got_start = .;
+               *(.got*)
+               . = ALIGN(4);
+               _got_end = .;
+       }
+
        . = ALIGN(4);
        .u_boot_list : {
                KEEP(*(SORT(.u_boot_list*)));
        }
+       __init_end = . ;
 
        .bss ALIGN(0x4):
        {
index c1c3b03985795a966dff2d821b79bb19ead98d39..11f3dd0f0ec026acba812efffc8351114bf2a334 100644 (file)
 #define R14(val) \
        __asm__ __volatile__ ("addi %0, r14, 0":"=r" (val));
 
+/* get return address from interrupt */
+#define R17(val) \
+       __asm__ __volatile__ ("addi %0, r17, 0" : "=r" (val));
+
 #define NOP    __asm__ __volatile__ ("nop");
 
 /* use machine status registe USE_MSR_REG */
index cd29734789449b2cd0a0a006a821af9cf897e0d1..32fd636b61dfc3ff4f89e764e32ffa958182fc99 100644 (file)
@@ -7,4 +7,11 @@
 #ifndef _ASM_CONFIG_H_
 #define _ASM_CONFIG_H_
 
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_NEEDS_MANUAL_RELOC
+#endif
+
+#define CONFIG_NR_DRAM_BANKS   1
+#define CONFIG_SYS_GENERIC_BOARD
+
 #endif
index 0fb9207882fe23064cdbab55fceb2669bc6f38ac..65868386b0d87a98b8b9987eef11bbfaca218354 100644 (file)
@@ -34,5 +34,3 @@ struct irq_action {
  */
 int install_interrupt_handler(int irq, interrupt_handler_t *hdlr,
                                       void *arg);
-
-int interrupts_init(void);
index 54d415ebb5bd22320f63f5cac66da3a06b708d9b..66f8f952c9d0ad78070effbdf91f1e52bf178d2f 100644 (file)
 #ifndef _U_BOOT_H_
 #define _U_BOOT_H_
 
-typedef struct bd_info {
-       unsigned long   bi_memstart;    /* start of DRAM memory */
-       phys_size_t     bi_memsize;     /* size  of DRAM memory in bytes */
-       unsigned long   bi_flashstart;  /* start of FLASH memory */
-       unsigned long   bi_flashsize;   /* size  of FLASH memory */
-       unsigned long   bi_flashoffset; /* reserved area for startup monitor */
-       unsigned long   bi_sramstart;   /* start of SRAM memory */
-       unsigned long   bi_sramsize;    /* size  of SRAM memory */
-       ulong           bi_boot_params; /* where this board expects params */
-} bd_t;
+#include <asm-generic/u-boot.h>
 
 /* For image.h:image_check_target_arch() */
 #define IH_ARCH_DEFAULT IH_ARCH_MICROBLAZE
index 339dd153a0fdec9c29d17400c8254e1b3ef6d212..0289d0cd609a9bec2ccab14b6a2f2e1bae6dc933 100644 (file)
@@ -5,6 +5,5 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-obj-y  += board.o
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 obj-y  += muldi3.o
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
deleted file mode 100644 (file)
index 600c80a..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * (C) Copyright 2007 Michal Simek
- * (C) Copyright 2004 Atmark Techno, Inc.
- *
- * Michal  SIMEK <monstr@monstr.eu>
- * Yasushi SHOJI <yashi@atmark-techno.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <command.h>
-#include <malloc.h>
-#include <version.h>
-#include <watchdog.h>
-#include <stdio_dev.h>
-#include <serial.h>
-#include <net.h>
-#include <spi.h>
-#include <linux/compiler.h>
-#include <asm/processor.h>
-#include <asm/microblaze_intc.h>
-#include <fdtdec.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static int display_banner(void)
-{
-       printf("\n\n%s\n\n", version_string);
-       return 0;
-}
-
-/*
- * All attempts to come up with a "common" initialization sequence
- * that works for all boards and architectures failed: some of the
- * requirements are just _too_ different. To get rid of the resulting
- * mess of board dependend #ifdef'ed code we now make the whole
- * initialization sequence configurable to the user.
- *
- * The requirements for any new initalization function is simple: it
- * receives a pointer to the "global data" structure as it's only
- * argument, and returns an integer return code, where 0 means
- * "continue" and != 0 means "fatal error, hang the system".
- */
-typedef int (init_fnc_t) (void);
-
-init_fnc_t *init_sequence[] = {
-       env_init,
-#ifdef CONFIG_OF_CONTROL
-       fdtdec_check_fdt,
-#endif
-       serial_init,
-#ifndef CONFIG_SPL_BUILD
-       console_init_f,
-#endif
-       display_banner,
-#ifndef CONFIG_SPL_BUILD
-       interrupts_init,
-       timer_init,
-#endif
-       NULL,
-};
-
-unsigned long monitor_flash_len;
-
-void board_init_f(ulong not_used)
-{
-       bd_t *bd;
-       init_fnc_t **init_fnc_ptr;
-       gd = (gd_t *)(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET);
-       bd = (bd_t *)(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET
-                                               - GENERATED_BD_INFO_SIZE);
-#if defined(CONFIG_CMD_FLASH) && !defined(CONFIG_SPL_BUILD)
-       ulong flash_size = 0;
-#endif
-       asm ("nop");    /* FIXME gd is not initialize - wait */
-       memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
-       memset((void *)bd, 0, GENERATED_BD_INFO_SIZE);
-       gd->bd = bd;
-       gd->baudrate = CONFIG_BAUDRATE;
-       bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
-       bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
-       gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
-
-       monitor_flash_len = __end - __text_start;
-
-#ifdef CONFIG_OF_EMBED
-       /* Get a pointer to the FDT */
-       gd->fdt_blob = __dtb_dt_begin;
-#elif defined CONFIG_OF_SEPARATE
-       /* FDT is at end of image */
-       gd->fdt_blob = (void *)__end;
-#endif
-
-#ifndef CONFIG_SPL_BUILD
-       /* Allow the early environment to override the fdt address */
-       gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
-                                               (uintptr_t)gd->fdt_blob);
-#endif
-
-       /*
-        * The Malloc area is immediately below the monitor copy in DRAM
-        * aka CONFIG_SYS_MONITOR_BASE - Note there is no need for reloc_off
-        * as our monitory code is run from SDRAM
-        */
-       mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
-
-       serial_initialize();
-
-#ifdef CONFIG_XILINX_TB_WATCHDOG
-       hw_watchdog_init();
-#endif
-       for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
-               WATCHDOG_RESET();
-               if ((*init_fnc_ptr) () != 0)
-                       hang();
-       }
-
-#ifndef CONFIG_SPL_BUILD
-#ifdef CONFIG_OF_CONTROL
-       /* For now, put this check after the console is ready */
-       if (fdtdec_prepare_fdt())
-               panic("** No FDT - please see doc/README.fdt-control");
-       else
-               printf("DTB: 0x%x\n", (u32)gd->fdt_blob);
-#endif
-
-       puts("SDRAM :\n");
-       printf("\t\tIcache:%s\n", icache_status() ? "ON" : "OFF");
-       printf("\t\tDcache:%s\n", dcache_status() ? "ON" : "OFF");
-       printf("\tU-Boot Start:0x%08x\n", CONFIG_SYS_TEXT_BASE);
-
-#if defined(CONFIG_CMD_FLASH)
-       puts("Flash: ");
-       bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
-       flash_size = flash_init();
-       if (bd->bi_flashstart && flash_size > 0) {
-# ifdef CONFIG_SYS_FLASH_CHECKSUM
-               print_size(flash_size, "");
-               /*
-                * Compute and print flash CRC if flashchecksum is set to 'y'
-                *
-                * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
-                */
-               if (getenv_yesno("flashchecksum") == 1) {
-                       printf("  CRC: %08X",
-                              crc32(0, (const u8 *)bd->bi_flashstart,
-                                    flash_size)
-                       );
-               }
-               putc('\n');
-# else /* !CONFIG_SYS_FLASH_CHECKSUM */
-               print_size(flash_size, "\n");
-# endif /* CONFIG_SYS_FLASH_CHECKSUM */
-               bd->bi_flashsize = flash_size;
-               bd->bi_flashoffset = bd->bi_flashstart + flash_size;
-       } else {
-               puts("Flash init FAILED");
-               bd->bi_flashstart = 0;
-               bd->bi_flashsize = 0;
-               bd->bi_flashoffset = 0;
-       }
-#endif
-
-#ifdef CONFIG_SPI
-       spi_init();
-#endif
-
-       /* relocate environment function pointers etc. */
-       env_relocate();
-
-       /* Initialize stdio devices */
-       stdio_init();
-
-       /* Initialize the jump table for applications */
-       jumptable_init();
-
-       /* Initialize the console (after the relocation and devices init) */
-       console_init_r();
-
-       board_init();
-
-       /* Initialize from environment */
-       load_addr = getenv_ulong("loadaddr", 16, load_addr);
-
-#if defined(CONFIG_CMD_NET)
-       printf("Net:   ");
-       eth_initialize(gd->bd);
-
-       uchar enetaddr[6];
-       eth_getenv_enetaddr("ethaddr", enetaddr);
-       printf("MAC:   %pM\n", enetaddr);
-#endif
-
-       /* main_loop */
-       for (;;) {
-               WATCHDOG_RESET();
-               main_loop();
-       }
-#endif /* CONFIG_SPL_BUILD */
-}
index b07908692a920740f5e76db508749a42fb84630d..dee5f43ae1552d67de77b7d7d4aee0768eb124d0 100644 (file)
@@ -22,7 +22,6 @@ int   cleanup_before_linux(void);
 
 /* board/.../... */
 int    board_init(void);
-int    dram_init(void);
 
 /* cpu/.../interrupt.c */
 void   reset_timer_masked(void);
index d2f1b6566d7051afe75c1199a57c929fabcd0ae3..770ab5c9cc07ec6fa497bd3d7b631072b8e10f5d 100644 (file)
@@ -17,7 +17,6 @@
 
 /* board/.../... */
 int board_init(void);
-int dram_init(void);
 
 /* start.c */
 int sandbox_early_getopt_check(void);
index b98afa801d3a60849c58d01d3955965bbc5bc99d..c24846b3ed50b49a3010d62dd87d9b93b0646d08 100644 (file)
@@ -26,15 +26,9 @@ unsigned long get_tbclk_mhz(void);
 void timer_set_base(uint64_t base);
 int pcat_timer_init(void);
 
-/* Architecture specific DRAM init */
-int dram_init(void);
-
 /* cpu/.../interrupts.c */
 int cpu_init_interrupts(void);
 
-/* board/.../... */
-int dram_init(void);
-
 int cleanup_before_linux(void);
 int x86_cleanup_before_linux(void);
 void x86_enable_caches(void);
diff --git a/board/Marvell/db-mv784mp-gp/binary.0 b/board/Marvell/db-mv784mp-gp/binary.0
deleted file mode 100644 (file)
index 17bfad9..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
---------
-WARNING:
---------
-This file should contain the bin_hdr generated by the original Marvell
-U-Boot implementation. As this is currently not included in this
-U-Boot version, we have added this placeholder, so that the U-Boot
-image can be generated without errors.
-
-If you have a known to be working bin_hdr for your board, then you
-just need to replace this text file here with the binary header
-and recompile U-Boot.
-
-In a few weeks, mainline U-Boot will get support to generate the
-bin_hdr with the DDR training code itself. By implementing this code
-as SPL U-Boot. Then this file will not be needed any more and will
-get removed.
-
index d7ef4071dd06809018a92bb23b97ba66bc1059a4..cc057925566c584d66b0dc73207f5a62523ad2f6 100644 (file)
@@ -9,4 +9,4 @@ VERSION         1
 BOOT_FROM      spi
 
 # Binary Header (bin_hdr) with DDR3 training code
-BINARY board/Marvell/db-mv784mp-gp/binary.0 0000005b 00000068
+BINARY spl/u-boot-spl.bin 0000005b 00000068
index 67ac260055233eb8bfa4a5060e3a7035026602a2..8330bb64bdae56163054bb266dc88b5af0443397 100644 (file)
@@ -321,8 +321,8 @@ static void enable_lvds(struct display_info_t const *dev)
        /* enable backlight PWM 3 */
        if (pwm_init(2, 0, 0))
                goto error;
-       /* duty cycle 200ns, period: 3000ns */
-       if (pwm_config(2, 200, 3000))
+       /* duty cycle 500ns, period: 3000ns */
+       if (pwm_config(2, 500, 3000))
                goto error;
        if (pwm_enable(2))
                goto error;
@@ -350,8 +350,8 @@ struct display_info_t const displays[] = {
                        .right_margin   = 88,
                        .upper_margin   = 10,
                        .lower_margin   = 10,
-                       .hsync_len      = 25,
-                       .vsync_len      = 1,
+                       .hsync_len      = 80,
+                       .vsync_len      = 25,
                        .sync           = 0,
                        .vmode          = FB_VMODE_NONINTERLACED
                }
index 1bd42e8321186349d6fefe643a2832224537a974..9e50bfeb8683d958e7e20b2ce5ab43ed2c931031 100644 (file)
@@ -6,4 +6,8 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+ifdef CONFIG_SPL_BUILD
+obj-y  := ot1200.o ot1200_spl.o
+else
 obj-y  := ot1200.o
+endif
index bb6c60b4c3cc902b8d3e2d2fa5909c768b6d3b68..c25f99dcfd844bfa4674bf0752e758ba7a563f32 100644 (file)
@@ -142,20 +142,6 @@ DATA 4 0x021b48b8 0x00000800
 DATA 4 0x021b001c 0x00000000
 DATA 4 0x021b0404 0x00011006
 
-/* set the default clock gate to save power */
-DATA 4 0x020c4068 0x00C03F3F
-DATA 4 0x020c406c 0x0030FC03
-DATA 4 0x020c4070 0x0FFFC000
-DATA 4 0x020c4074 0x3FF00000
-DATA 4 0x020c4078 0x00FFF300
-DATA 4 0x020c407c 0x0F0000C3
-DATA 4 0x020c4080 0x000003FF
-
-/* enable AXI cache for VDOA/VPU/IPU */
-DATA 4 0x020e0010 0xF00000CF
-/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
-DATA 4 0x020e0018 0x007F007F
-DATA 4 0x020e001c 0x007F007F
 
 /*
  * Setup CCM_CCOSR register as follows:
index 93f3d651764b9a4c0aaa00fd7e815062155eb976..e434ed9b877286a662bb58b942f6a43d145a4420 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/iomux.h>
@@ -16,6 +17,7 @@
 #include <asm/imx-common/mxc_i2c.h>
 #include <asm/imx-common/boot_mode.h>
 #include <asm/arch/crm_regs.h>
+#include <asm/arch/sys_proto.h>
 #include <mmc.h>
 #include <fsl_esdhc.h>
 #include <netdev.h>
@@ -46,7 +48,7 @@ DECLARE_GLOBAL_DATA_PTR;
 
 int dram_init(void)
 {
-       gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+       gd->ram_size = imx_ddr_size();
 
        return 0;
 }
@@ -118,8 +120,35 @@ static void setup_iomux_features(void)
                ARRAY_SIZE(feature_pads));
 }
 
+static void ccgr_init(void)
+{
+       struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+       writel(0x00C03F3F, &ccm->CCGR0);
+       writel(0x0030FC33, &ccm->CCGR1);
+       writel(0x0FFFC000, &ccm->CCGR2);
+       writel(0x3FF00000, &ccm->CCGR3);
+       writel(0x00FFF300, &ccm->CCGR4);
+       writel(0x0F0000C3, &ccm->CCGR5);
+       writel(0x000003FF, &ccm->CCGR6);
+}
+
+static void gpr_init(void)
+{
+       struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+       /* enable AXI cache for VDOA/VPU/IPU */
+       writel(0xF00000CF, &iomux->gpr[4]);
+       /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+       writel(0x007F007F, &iomux->gpr[6]);
+       writel(0x007F007F, &iomux->gpr[7]);
+}
+
 int board_early_init_f(void)
 {
+       ccgr_init();
+       gpr_init();
+
        setup_iomux_uart();
        setup_iomux_spi();
        setup_iomux_features();
@@ -290,9 +319,6 @@ int board_init(void)
 
        leds_on();
 
-       /* enable ecspi3 clocks */
-       enable_cspi_clock(1, 2);
-
 #ifdef CONFIG_CMD_SATA
        setup_sata();
 #endif
diff --git a/board/bachmann/ot1200/ot1200_spl.c b/board/bachmann/ot1200/ot1200_spl.c
new file mode 100644 (file)
index 0000000..9c77fd3
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015, Bachmann electronic GmbH
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <asm/arch/mx6-ddr.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Configure MX6Q/DUAL mmdc DDR io registers */
+static struct mx6dq_iomux_ddr_regs ot1200_ddr_ioregs = {
+       /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 48ohm */
+       .dram_sdclk_0   = 0x00000028,
+       .dram_sdclk_1   = 0x00000028,
+       .dram_cas       = 0x00000028,
+       .dram_ras       = 0x00000028,
+       .dram_reset     = 0x00000028,
+       /* SDCKE[0:1]: 100k pull-up */
+       .dram_sdcke0    = 0x00003000,
+       .dram_sdcke1    = 0x00003000,
+       /* SDBA2: pull-up disabled */
+       .dram_sdba2         = 0x00000000,
+       /* SDODT[0:1]: 100k pull-up, 48 ohm */
+       .dram_sdodt0    = 0x00000028,
+       .dram_sdodt1    = 0x00000028,
+       /* SDQS[0:7]: Differential input, 48 ohm */
+       .dram_sdqs0     = 0x00000028,
+       .dram_sdqs1     = 0x00000028,
+       .dram_sdqs2     = 0x00000028,
+       .dram_sdqs3     = 0x00000028,
+       .dram_sdqs4     = 0x00000028,
+       .dram_sdqs5     = 0x00000028,
+       .dram_sdqs6     = 0x00000028,
+       .dram_sdqs7     = 0x00000028,
+       /* DQM[0:7]: Differential input, 48 ohm */
+       .dram_dqm0      = 0x00000028,
+       .dram_dqm1      = 0x00000028,
+       .dram_dqm2      = 0x00000028,
+       .dram_dqm3      = 0x00000028,
+       .dram_dqm4      = 0x00000028,
+       .dram_dqm5      = 0x00000028,
+       .dram_dqm6      = 0x00000028,
+       .dram_dqm7      = 0x00000028,
+};
+
+/* Configure MX6Q/DUAL mmdc GRP io registers */
+static struct mx6dq_iomux_grp_regs ot1200_grp_ioregs = {
+       /* DDR3 */
+       .grp_ddr_type    = 0x000c0000,
+       .grp_ddrmode_ctl = 0x00020000,
+       /* Disable DDR pullups */
+       .grp_ddrpke      = 0x00000000,
+       /* ADDR[00:16], SDBA[0:1]: 48 ohm */
+       .grp_addds       = 0x00000028,
+       /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 48 ohm */
+       .grp_ctlds       = 0x00000028,
+       /* DATA[00:63]: Differential input, 48 ohm */
+       .grp_ddrmode     = 0x00020000,
+       .grp_b0ds        = 0x00000028,
+       .grp_b1ds        = 0x00000028,
+       .grp_b2ds        = 0x00000028,
+       .grp_b3ds        = 0x00000028,
+       .grp_b4ds        = 0x00000028,
+       .grp_b5ds        = 0x00000028,
+       .grp_b6ds        = 0x00000028,
+       .grp_b7ds        = 0x00000028,
+};
+
+static struct mx6_ddr_sysinfo ot1200_ddr_sysinfo = {
+       /* Width of data bus: 0=16, 1=32, 2=64 */
+       .dsize      = 2,
+       /* config for full 4GB range so that get_mem_size() works */
+       .cs_density = 32, /* 32Gb per CS */
+       /* Single chip select */
+       .ncs        = 1,
+       .cs1_mirror = 0,        /* war 0 */
+       .rtt_wr     = 1,        /* DDR3_RTT_60_OHM - RTT_Wr = RZQ/4 */
+       .rtt_nom    = 1,        /* DDR3_RTT_60_OHM - RTT_Nom = RZQ/4 */
+       .walat      = 1,        /* Write additional latency */
+       .ralat      = 5,        /* Read additional latency */
+       .mif3_mode  = 3,        /* Command prediction working mode */
+       .bi_on      = 1,        /* Bank interleaving enabled */ /* war 1 */
+       .sde_to_rst = 0x10,     /* 14 cycles, 200us (JEDEC default) */
+       .rst_to_cke = 0x23,     /* 33 cycles, 500us (JEDEC default) */
+};
+
+/* MT41K128M16JT-125 */
+static struct mx6_ddr3_cfg micron_2gib_1600 = {
+       .mem_speed = 1600,
+       .density   = 2,
+       .width     = 16,
+       .banks     = 8,
+       .rowaddr   = 14,
+       .coladdr   = 10,
+       .pagesz    = 2,
+       .trcd      = 1375,
+       .trcmin    = 4875,
+       .trasmin   = 3500,
+       .SRT       = 1,
+};
+
+static struct mx6_mmdc_calibration micron_2gib_1600_mmdc_calib = {
+       /* write leveling calibration determine */
+       .p0_mpwldectrl0 = 0x00260025,
+       .p0_mpwldectrl1 = 0x00270021,
+       .p1_mpwldectrl0 = 0x00180034,
+       .p1_mpwldectrl1 = 0x00180024,
+       /* Read DQS Gating calibration */
+       .p0_mpdgctrl0   = 0x04380344,
+       .p0_mpdgctrl1   = 0x0330032C,
+       .p1_mpdgctrl0   = 0x0338033C,
+       .p1_mpdgctrl1   = 0x032C0300,
+       /* Read Calibration: DQS delay relative to DQ read access */
+       .p0_mprddlctl   = 0x3C2E3238,
+       .p1_mprddlctl   = 0x3A2E303C,
+       /* Write Calibration: DQ/DM delay relative to DQS write access */
+       .p0_mpwrdlctl   = 0x36384036,
+       .p1_mpwrdlctl   = 0x442E4438,
+};
+
+static void ot1200_spl_dram_init(void)
+{
+       mx6dq_dram_iocfg(64, &ot1200_ddr_ioregs, &ot1200_grp_ioregs);
+       mx6_dram_cfg(&ot1200_ddr_sysinfo, &micron_2gib_1600_mmdc_calib,
+                    &micron_2gib_1600);
+}
+
+/*
+ * called from C runtime startup code (arch/arm/lib/crt0.S:_main)
+ * - we have a stack and a place to store GD, both in SRAM
+ * - no variable global data is available
+ */
+void board_init_f(ulong dummy)
+{
+       /* setup AIPS and disable watchdog */
+       arch_cpu_init();
+
+       /* iomux and setup of i2c */
+       board_early_init_f();
+
+       /* setup GP timer */
+       timer_init();
+
+       /* UART clocks enabled and gd valid - init serial console */
+       preloader_console_init();
+
+       /* configure MMDC for SDRAM width/size and per-model calibration */
+       ot1200_spl_dram_init();
+
+       /* Clear the BSS. */
+       memset(__bss_start, 0, __bss_end - __bss_start);
+
+       /* load/boot image from boot device */
+       board_init_r(NULL, 0);
+}
+
+void reset_cpu(ulong addr)
+{
+}
diff --git a/board/barco/platinum/Kconfig b/board/barco/platinum/Kconfig
new file mode 100644 (file)
index 0000000..8bbad24
--- /dev/null
@@ -0,0 +1,37 @@
+if TARGET_PLATINUM_PICON
+
+config SYS_CPU
+       default "armv7"
+
+config SYS_VENDOR
+       default "barco"
+
+config SYS_SOC
+       default "mx6"
+
+config SYS_BOARD
+       default "platinum"
+
+config SYS_CONFIG_NAME
+       default "platinum_picon"
+
+endif
+
+if TARGET_PLATINUM_TITANIUM
+
+config SYS_CPU
+       default "armv7"
+
+config SYS_VENDOR
+       default "barco"
+
+config SYS_SOC
+       default "mx6"
+
+config SYS_BOARD
+       default "platinum"
+
+config SYS_CONFIG_NAME
+       default "platinum_titanium"
+
+endif
diff --git a/board/barco/platinum/MAINTAINERS b/board/barco/platinum/MAINTAINERS
new file mode 100644 (file)
index 0000000..a22584b
--- /dev/null
@@ -0,0 +1,7 @@
+PLATINUM BOARD
+M:     Stefan Roese <sr@denx.de>
+S:     Maintained
+F:     board/barco/platinum/
+F:     include/configs/platinum.h
+F:     configs/platinum_picon_defconfig
+F:     configs/platinum_titanium_defconfig
diff --git a/board/barco/platinum/Makefile b/board/barco/platinum/Makefile
new file mode 100644 (file)
index 0000000..abc9419
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Copyright (C) 2014, Barco (www.barco.com)
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y := platinum.o
+obj-$(CONFIG_TARGET_PLATINUM_PICON)     += platinum_picon.o
+obj-$(CONFIG_TARGET_PLATINUM_TITANIUM)  += platinum_titanium.o
+
+ifneq ($(CONFIG_SPL_BUILD),)
+obj-$(CONFIG_TARGET_PLATINUM_PICON) += spl_picon.o
+obj-$(CONFIG_TARGET_PLATINUM_TITANIUM) += spl_titanium.o
+endif
diff --git a/board/barco/platinum/platinum.c b/board/barco/platinum/platinum.c
new file mode 100644 (file)
index 0000000..1485a48
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <fsl_esdhc.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/boot_mode.h>
+
+#include "platinum.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+iomux_v3_cfg_t const usdhc3_pads[] = {
+       MX6_PAD_SD3_CLK__SD3_CLK        | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD3_CMD__SD3_CMD        | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD3_DAT0__SD3_DATA0     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD3_DAT1__SD3_DATA1     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD3_DAT2__SD3_DATA2     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD3_DAT3__SD3_DATA3     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+       MX6_PAD_SD3_DAT5__GPIO7_IO00    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
+};
+
+iomux_v3_cfg_t nfc_pads[] = {
+       MX6_PAD_NANDF_CLE__NAND_CLE             | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_ALE__NAND_ALE             | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_WP_B__NAND_WP_B           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_RB0__NAND_READY_B         | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_CS0__NAND_CE0_B           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_CS1__NAND_CE1_B           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_CS2__NAND_CE2_B           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_CS3__NAND_CE3_B           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_SD4_CMD__NAND_RE_B              | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_SD4_CLK__NAND_WE_B              | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_D0__NAND_DATA00           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_D1__NAND_DATA01           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_D2__NAND_DATA02           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_D3__NAND_DATA03           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_D4__NAND_DATA04           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_D5__NAND_DATA05           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_D6__NAND_DATA06           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_NANDF_D7__NAND_DATA07           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_SD4_DAT0__NAND_DQS              | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+struct fsl_esdhc_cfg usdhc_cfg[] = {
+       { USDHC3_BASE_ADDR },
+};
+
+void setup_gpmi_nand(void)
+{
+       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+       /* config gpmi nand iomux */
+       imx_iomux_v3_setup_multiple_pads(nfc_pads, ARRAY_SIZE(nfc_pads));
+
+       /* config gpmi and bch clock to 100 MHz */
+       clrsetbits_le32(&mxc_ccm->cs2cdr,
+                       MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
+                       MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
+                       MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
+                       MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
+                       MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
+                       MXC_CCM_CS2CDR_ENFC_CLK_SEL(3));
+
+       /* enable gpmi and bch clock gating */
+       setbits_le32(&mxc_ccm->CCGR4,
+                    MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
+                    MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
+                    MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
+                    MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
+                    MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET);
+
+       /* enable apbh clock gating */
+       setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
+}
+
+int dram_init(void)
+{
+       gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+
+       return 0;
+}
+
+int board_ehci_hcd_init(int port)
+{
+       return 0;
+}
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+       struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+
+       if (cfg->esdhc_base == usdhc_cfg[0].esdhc_base) {
+               unsigned sd3_cd = IMX_GPIO_NR(7, 0);
+               gpio_direction_input(sd3_cd);
+               return !gpio_get_value(sd3_cd);
+       }
+
+       return 0;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+       imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
+       usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+
+       return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+}
+
+void board_init_gpio(void)
+{
+       platinum_init_gpio();
+}
+
+void board_init_gpmi_nand(void)
+{
+       setup_gpmi_nand();
+}
+
+void board_init_i2c(void)
+{
+       platinum_setup_i2c();
+}
+
+void board_init_spi(void)
+{
+       platinum_setup_spi();
+}
+
+void board_init_uart(void)
+{
+       platinum_setup_uart();
+}
+
+void board_init_usb(void)
+{
+       platinum_init_usb();
+}
+
+void board_init_finished(void)
+{
+       platinum_init_finished();
+}
+
+int board_phy_config(struct phy_device *phydev)
+{
+       return platinum_phy_config(phydev);
+}
+
+int board_eth_init(bd_t *bis)
+{
+       return cpu_eth_init(bis);
+}
+
+int board_early_init_f(void)
+{
+       board_init_uart();
+
+       return 0;
+}
+
+int board_init(void)
+{
+       /* address of boot parameters */
+       gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+       board_init_spi();
+
+       board_init_i2c();
+
+       board_init_gpmi_nand();
+
+       board_init_gpio();
+
+       board_init_usb();
+
+       board_init_finished();
+
+       return 0;
+}
+
+int checkboard(void)
+{
+       puts("Board: " CONFIG_PLATINUM_BOARD "\n");
+       return 0;
+}
+
+static const struct boot_mode board_boot_modes[] = {
+       /* NAND */
+       { "nand", MAKE_CFGVAL(0x80, 0x02, 0x00, 0x00) },
+       /* 4 bit bus width */
+       { "mmc0", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00) },
+       { "mmc1", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00) },
+       { NULL, 0 },
+};
+
+int misc_init_r(void)
+{
+       add_board_boot_modes(board_boot_modes);
+
+       return 0;
+}
diff --git a/board/barco/platinum/platinum.h b/board/barco/platinum/platinum.h
new file mode 100644 (file)
index 0000000..d3ea8bd
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _PLATINUM_H_
+#define _PLATINUM_H_
+
+#include <miiphy.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/io.h>
+
+/* Defines */
+
+#define ECSPI1_PAD_CLK         (PAD_CTL_SRE_SLOW | PAD_CTL_PUS_100K_DOWN | \
+                                PAD_CTL_SPEED_LOW | PAD_CTL_DSE_40ohm | \
+                                PAD_CTL_HYS)
+#define ECSPI2_PAD_CLK         (PAD_CTL_SRE_FAST | PAD_CTL_PUS_100K_DOWN | \
+                                PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
+                                PAD_CTL_HYS)
+#define ECSPI_PAD_MOSI         (PAD_CTL_SRE_SLOW | PAD_CTL_PUS_100K_DOWN | \
+                                PAD_CTL_SPEED_LOW | PAD_CTL_DSE_120ohm | \
+                                PAD_CTL_HYS)
+#define ECSPI_PAD_MISO         (PAD_CTL_SRE_FAST | PAD_CTL_PUS_100K_DOWN | \
+                                PAD_CTL_SPEED_LOW | PAD_CTL_DSE_40ohm | \
+                                PAD_CTL_HYS)
+#define ECSPI_PAD_SS           (PAD_CTL_SRE_SLOW | PAD_CTL_PUS_100K_UP | \
+                                PAD_CTL_SPEED_LOW | PAD_CTL_DSE_120ohm | \
+                                PAD_CTL_HYS)
+
+#define ENET_PAD_CTRL          (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+                                PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
+
+#define I2C_PAD_CTRL           (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+                                PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
+                                PAD_CTL_ODE | PAD_CTL_SRE_FAST)
+#define I2C_PAD_CTRL_SCL       (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \
+                                PAD_CTL_DSE_80ohm | PAD_CTL_HYS | \
+                                PAD_CTL_ODE | PAD_CTL_SRE_SLOW)
+
+#define UART_PAD_CTRL          (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
+                                PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | \
+                                PAD_CTL_HYS)
+
+#define USDHC_PAD_CTRL         (PAD_CTL_PUS_47K_UP  | PAD_CTL_SPEED_LOW | \
+                               PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | \
+                               PAD_CTL_HYS)
+
+
+#define PC                     MUX_PAD_CTRL(I2C_PAD_CTRL)
+#define PC_SCL                 MUX_PAD_CTRL(I2C_PAD_CTRL_SCL)
+
+/* Prototypes */
+
+int platinum_setup_enet(void);
+int platinum_setup_i2c(void);
+int platinum_setup_spi(void);
+int platinum_setup_uart(void);
+int platinum_phy_config(struct phy_device *phydev);
+int platinum_init_gpio(void);
+int platinum_init_usb(void);
+int platinum_init_finished(void);
+
+static inline void ccgr_init(void)
+{
+       struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+       writel(0x00C03F3F, &ccm->CCGR0);
+       writel(0x0030FC03, &ccm->CCGR1);
+       writel(0x0FFFC000, &ccm->CCGR2);
+       writel(0x3FF00000, &ccm->CCGR3);
+       writel(0xFFFFF300, &ccm->CCGR4);        /* enable NAND/GPMI/BCH clks */
+       writel(0x0F0000C3, &ccm->CCGR5);
+       writel(0x000003FF, &ccm->CCGR6);
+}
+
+static inline void gpr_init(void)
+{
+       struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+
+       /* enable AXI cache for VDOA/VPU/IPU */
+       writel(0xF00000CF, &iomux->gpr[4]);
+       /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
+       writel(0x007F007F, &iomux->gpr[6]);
+       writel(0x007F007F, &iomux->gpr[7]);
+}
+
+#endif /* _PLATINUM_H_ */
diff --git a/board/barco/platinum/platinum_picon.c b/board/barco/platinum/platinum_picon.c
new file mode 100644 (file)
index 0000000..b2eab76
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <i2c.h>
+#include <miiphy.h>
+
+#include "platinum.h"
+
+#define GPIO_IP_NCONFIG                IMX_GPIO_NR(5, 18)
+#define GPIO_HK_NCONFIG                IMX_GPIO_NR(7, 13)
+#define GPIO_LS_NCONFIG                IMX_GPIO_NR(5, 19)
+
+#define GPIO_I2C0_SEL0         IMX_GPIO_NR(5,  2)
+#define GPIO_I2C0_SEL1         IMX_GPIO_NR(1, 11)
+#define GPIO_I2C0_ENBN         IMX_GPIO_NR(1, 13)
+
+#define GPIO_I2C2_SEL0         IMX_GPIO_NR(1, 17)
+#define GPIO_I2C2_SEL1         IMX_GPIO_NR(1, 20)
+#define GPIO_I2C2_ENBN         IMX_GPIO_NR(1, 14)
+
+#define GPIO_USB_RESET         IMX_GPIO_NR(1,  5)
+
+iomux_v3_cfg_t const ecspi1_pads[] = {
+       MX6_PAD_EIM_D16__ECSPI1_SCLK            | MUX_PAD_CTRL(ECSPI1_PAD_CLK),
+       MX6_PAD_EIM_D17__ECSPI1_MISO            | MUX_PAD_CTRL(ECSPI_PAD_MISO),
+       MX6_PAD_EIM_D18__ECSPI1_MOSI            | MUX_PAD_CTRL(ECSPI_PAD_MOSI),
+       MX6_PAD_CSI0_DAT7__ECSPI1_SS0           | MUX_PAD_CTRL(ECSPI_PAD_SS),
+       MX6_PAD_EIM_D24__ECSPI1_SS2             | MUX_PAD_CTRL(ECSPI_PAD_SS),
+       MX6_PAD_EIM_D25__ECSPI1_SS3             | MUX_PAD_CTRL(ECSPI_PAD_SS),
+};
+
+iomux_v3_cfg_t const ecspi2_pads[] = {
+       MX6_PAD_EIM_CS0__ECSPI2_SCLK            | MUX_PAD_CTRL(ECSPI2_PAD_CLK),
+       MX6_PAD_EIM_OE__ECSPI2_MISO             | MUX_PAD_CTRL(ECSPI_PAD_MISO),
+       MX6_PAD_EIM_CS1__ECSPI2_MOSI            | MUX_PAD_CTRL(ECSPI_PAD_MOSI),
+       MX6_PAD_EIM_RW__ECSPI2_SS0              | MUX_PAD_CTRL(ECSPI_PAD_SS),
+       MX6_PAD_EIM_LBA__ECSPI2_SS1             | MUX_PAD_CTRL(ECSPI_PAD_SS),
+};
+
+iomux_v3_cfg_t const enet_pads[] = {
+       MX6_PAD_ENET_MDIO__ENET_MDIO            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_MDC__ENET_MDC              | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_CRS_DV__ENET_RX_EN         | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_GPIO_16__ENET_REF_CLK           | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_RX_ER__ENET_RX_ER          | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_RXD0__ENET_RX_DATA0        | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_RXD1__ENET_RX_DATA1        | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_TX_EN__ENET_TX_EN          | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_TXD0__ENET_TX_DATA0        | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_TXD1__ENET_TX_DATA1        | MUX_PAD_CTRL(ENET_PAD_CTRL),
+};
+
+/* PHY nRESET */
+iomux_v3_cfg_t const phy_reset_pad = {
+       MX6_PAD_SD1_DAT2__GPIO1_IO19            | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart1_pads[] = {
+       MX6_PAD_SD3_DAT6__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_SD3_DAT7__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart4_pads[] = {
+       MX6_PAD_CSI0_DAT12__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI0_DAT13__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI0_DAT16__UART4_RTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI0_DAT17__UART4_CTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart5_pads[] = {
+       MX6_PAD_CSI0_DAT14__UART5_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI0_DAT15__UART5_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI0_DAT18__UART5_RTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI0_DAT19__UART5_CTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const i2c0_mux_pads[] = {
+       MX6_PAD_EIM_A25__GPIO5_IO02             | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_SD2_CMD__GPIO1_IO11             | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_SD2_DAT2__GPIO1_IO13            | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const i2c2_mux_pads[] = {
+       MX6_PAD_SD1_DAT1__GPIO1_IO17            | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_SD1_CLK__GPIO1_IO20             | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_SD2_DAT1__GPIO1_IO14            | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+struct i2c_pads_info i2c_pad_info0 = {
+       .scl = {
+               .i2c_mode  = MX6_PAD_CSI0_DAT9__I2C1_SCL        | PC_SCL,
+               .gpio_mode = MX6_PAD_CSI0_DAT9__GPIO5_IO27      | PC_SCL,
+               .gp = IMX_GPIO_NR(5, 27)
+       },
+       .sda = {
+               .i2c_mode = MX6_PAD_CSI0_DAT8__I2C1_SDA         | PC,
+               .gpio_mode = MX6_PAD_CSI0_DAT8__GPIO5_IO26      | PC,
+               .gp = IMX_GPIO_NR(5, 26)
+        }
+};
+
+struct i2c_pads_info i2c_pad_info2 = {
+       .scl = {
+               .i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL            | PC_SCL,
+               .gpio_mode = MX6_PAD_GPIO_3__GPIO1_IO03         | PC_SCL,
+               .gp = IMX_GPIO_NR(1, 3)
+       },
+       .sda = {
+               .i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA            | PC,
+               .gpio_mode = MX6_PAD_GPIO_6__GPIO1_IO06         | PC,
+               .gp = IMX_GPIO_NR(1, 6)
+        }
+};
+
+/*
+ * This enet related pin-muxing and GPIO handling is done
+ * in SPL U-Boot. For early initialization. And to give the
+ * PHY some time to come out of reset before the U-Boot
+ * ethernet driver tries to access its registers via MDIO.
+ */
+int platinum_setup_enet(void)
+{
+       struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
+       unsigned phy_reset = IMX_GPIO_NR(1, 19);
+
+       /* First configure PHY reset GPIO pin */
+       imx_iomux_v3_setup_pad(phy_reset_pad);
+
+       /* Reconfigure enet muxing while PHY is in reset */
+       gpio_direction_output(phy_reset, 0);
+       imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
+       mdelay(10);
+       gpio_set_value(phy_reset, 1);
+       udelay(100);
+
+       /* set GPIO_16 as ENET_REF_CLK_OUT */
+       setbits_le32(&iomux->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK);
+
+       return enable_fec_anatop_clock(ENET_50MHZ);
+}
+
+int platinum_setup_i2c(void)
+{
+       imx_iomux_v3_setup_multiple_pads(i2c0_mux_pads,
+                                        ARRAY_SIZE(i2c0_mux_pads));
+       imx_iomux_v3_setup_multiple_pads(i2c2_mux_pads,
+                                        ARRAY_SIZE(i2c2_mux_pads));
+
+       mdelay(10);
+
+       /* Disable i2c mux 0 */
+       gpio_direction_output(GPIO_I2C0_SEL0, 0);
+       gpio_direction_output(GPIO_I2C0_SEL1, 0);
+       gpio_direction_output(GPIO_I2C0_ENBN, 1);
+
+       /* Disable i2c mux 1 */
+       gpio_direction_output(GPIO_I2C2_SEL0, 0);
+       gpio_direction_output(GPIO_I2C2_SEL1, 0);
+       gpio_direction_output(GPIO_I2C2_ENBN, 1);
+
+       udelay(10);
+
+       setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
+       setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+
+       /* Disable all leds */
+       i2c_set_bus_num(0);
+       i2c_reg_write(0x60, 0x05, 0x55);
+
+       return 0;
+}
+
+int platinum_setup_spi(void)
+{
+       imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+       imx_iomux_v3_setup_multiple_pads(ecspi2_pads, ARRAY_SIZE(ecspi2_pads));
+
+       return 0;
+}
+
+int platinum_setup_uart(void)
+{
+       imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+       imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
+       imx_iomux_v3_setup_multiple_pads(uart5_pads, ARRAY_SIZE(uart5_pads));
+
+       return 0;
+}
+
+int platinum_phy_config(struct phy_device *phydev)
+{
+       /* Use generic infrastructure, no specific setup */
+       if (phydev->drv->config)
+               phydev->drv->config(phydev);
+
+       return 0;
+}
+
+int platinum_init_gpio(void)
+{
+       /* Reset FPGA's */
+       gpio_direction_output(GPIO_IP_NCONFIG, 0);
+       gpio_direction_output(GPIO_HK_NCONFIG, 0);
+       gpio_direction_output(GPIO_LS_NCONFIG, 0);
+       udelay(3);
+       gpio_set_value(GPIO_IP_NCONFIG, 1);
+       gpio_set_value(GPIO_HK_NCONFIG, 1);
+       gpio_set_value(GPIO_LS_NCONFIG, 1);
+
+       /* no dmd configuration yet */
+
+       return 0;
+}
+
+int platinum_init_usb(void)
+{
+       /* Reset usb hub */
+       gpio_direction_output(GPIO_USB_RESET, 0);
+       udelay(100);
+       gpio_set_value(GPIO_USB_RESET, 1);
+
+       return 0;
+}
+
+int platinum_init_finished(void)
+{
+       /* Enable led 0 */
+       i2c_set_bus_num(0);
+       i2c_reg_write(0x60, 0x05, 0x54);
+
+       return 0;
+}
diff --git a/board/barco/platinum/platinum_titanium.c b/board/barco/platinum/platinum_titanium.c
new file mode 100644 (file)
index 0000000..73a955f
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/gpio.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <miiphy.h>
+#include <micrel.h>
+
+#include "platinum.h"
+
+iomux_v3_cfg_t const ecspi1_pads[] = {
+       MX6_PAD_EIM_D16__ECSPI1_SCLK            | MUX_PAD_CTRL(ECSPI1_PAD_CLK),
+       MX6_PAD_EIM_D17__ECSPI1_MISO            | MUX_PAD_CTRL(ECSPI_PAD_MISO),
+       MX6_PAD_EIM_D18__ECSPI1_MOSI            | MUX_PAD_CTRL(ECSPI_PAD_MOSI),
+       MX6_PAD_CSI0_DAT7__ECSPI1_SS0           | MUX_PAD_CTRL(ECSPI_PAD_SS),
+       /* non mounted spi nor flash for booting */
+       MX6_PAD_EIM_D19__ECSPI1_SS1             | MUX_PAD_CTRL(NO_PAD_CTRL),
+       MX6_PAD_EIM_D24__ECSPI1_SS2             | MUX_PAD_CTRL(ECSPI_PAD_SS),
+       MX6_PAD_EIM_D25__ECSPI1_SS3             | MUX_PAD_CTRL(ECSPI_PAD_SS),
+};
+
+iomux_v3_cfg_t const ecspi2_pads[] = {
+       MX6_PAD_EIM_CS0__ECSPI2_SCLK            | MUX_PAD_CTRL(ECSPI2_PAD_CLK),
+       MX6_PAD_EIM_OE__ECSPI2_MISO             | MUX_PAD_CTRL(ECSPI_PAD_MISO),
+       MX6_PAD_EIM_CS1__ECSPI2_MOSI            | MUX_PAD_CTRL(ECSPI_PAD_MOSI),
+       MX6_PAD_EIM_RW__ECSPI2_SS0              | MUX_PAD_CTRL(ECSPI_PAD_SS),
+};
+
+iomux_v3_cfg_t const enet_pads1[] = {
+       MX6_PAD_ENET_MDIO__ENET_MDIO            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_MDC__ENET_MDC              | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_TXC__RGMII_TXC            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_TD0__RGMII_TD0            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_TD1__RGMII_TD1            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_TD2__RGMII_TD2            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_TD3__RGMII_TD3            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL      | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_ENET_REF_CLK__ENET_TX_CLK       | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       /* pin 35 - 1 (PHY_AD2) on reset */
+       MX6_PAD_RGMII_RXC__GPIO6_IO30           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       /* pin 32 - 1 - (MODE0) all */
+       MX6_PAD_RGMII_RD0__GPIO6_IO25           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       /* pin 31 - 1 - (MODE1) all */
+       MX6_PAD_RGMII_RD1__GPIO6_IO27           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       /* pin 28 - 1 - (MODE2) all */
+       MX6_PAD_RGMII_RD2__GPIO6_IO28           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       /* pin 27 - 1 - (MODE3) all */
+       MX6_PAD_RGMII_RD3__GPIO6_IO29           | MUX_PAD_CTRL(NO_PAD_CTRL),
+       /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
+       MX6_PAD_RGMII_RX_CTL__GPIO6_IO24        | MUX_PAD_CTRL(NO_PAD_CTRL),
+       /* pin 42 PHY nRST */
+       MX6_PAD_EIM_D23__GPIO3_IO23             | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const enet_pads2[] = {
+       MX6_PAD_RGMII_RXC__RGMII_RXC            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_RD0__RGMII_RD0            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_RD1__RGMII_RD1            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_RD2__RGMII_RD2            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_RD3__RGMII_RD3            | MUX_PAD_CTRL(ENET_PAD_CTRL),
+       MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL      | MUX_PAD_CTRL(ENET_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart1_pads[] = {
+       MX6_PAD_SD3_DAT6__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_SD3_DAT7__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart2_pads[] = {
+       MX6_PAD_EIM_D26__UART2_TX_DATA   | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_EIM_D27__UART2_RX_DATA   | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_EIM_D28__UART2_DTE_CTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_EIM_D29__UART2_RTS_B     | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+iomux_v3_cfg_t const uart4_pads[] = {
+       MX6_PAD_CSI0_DAT12__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI0_DAT13__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI0_DAT16__UART4_RTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+       MX6_PAD_CSI0_DAT17__UART4_CTS_B   | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+struct i2c_pads_info i2c_pad_info0 = {
+       .scl = {
+               .i2c_mode  = MX6_PAD_CSI0_DAT9__I2C1_SCL        | PC_SCL,
+               .gpio_mode = MX6_PAD_CSI0_DAT9__GPIO5_IO27      | PC_SCL,
+               .gp = IMX_GPIO_NR(5, 27)
+       },
+       .sda = {
+               .i2c_mode = MX6_PAD_CSI0_DAT8__I2C1_SDA         | PC,
+               .gpio_mode = MX6_PAD_CSI0_DAT8__GPIO5_IO26      | PC,
+               .gp = IMX_GPIO_NR(5, 26)
+        }
+};
+
+struct i2c_pads_info i2c_pad_info2 = {
+       .scl = {
+               .i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL            | PC_SCL,
+               .gpio_mode = MX6_PAD_GPIO_3__GPIO1_IO03         | PC_SCL,
+               .gp = IMX_GPIO_NR(1, 3)
+       },
+       .sda = {
+               .i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA            | PC,
+               .gpio_mode = MX6_PAD_GPIO_16__GPIO7_IO11        | PC,
+               .gp = IMX_GPIO_NR(7, 11)
+        }
+};
+
+/*
+ * This enet related pin-muxing and GPIO handling is done
+ * in SPL U-Boot. For early initialization. And to give the
+ * PHY some time to come out of reset before the U-Boot
+ * ethernet driver tries to access its registers via MDIO.
+ */
+int platinum_setup_enet(void)
+{
+       gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
+       gpio_direction_output(IMX_GPIO_NR(6, 30), 1);
+       gpio_direction_output(IMX_GPIO_NR(6, 25), 1);
+       gpio_direction_output(IMX_GPIO_NR(6, 27), 1);
+       gpio_direction_output(IMX_GPIO_NR(6, 28), 1);
+       gpio_direction_output(IMX_GPIO_NR(6, 29), 1);
+       imx_iomux_v3_setup_multiple_pads(enet_pads1, ARRAY_SIZE(enet_pads1));
+       gpio_direction_output(IMX_GPIO_NR(6, 24), 1);
+
+       /* Need delay 10ms according to KSZ9021 spec */
+       mdelay(10);
+       gpio_set_value(IMX_GPIO_NR(3, 23), 1);
+       udelay(100);
+
+       imx_iomux_v3_setup_multiple_pads(enet_pads2, ARRAY_SIZE(enet_pads2));
+
+       return 0;
+}
+
+int platinum_setup_i2c(void)
+{
+       setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info0);
+       setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+
+       return 0;
+}
+
+int platinum_setup_spi(void)
+{
+       imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
+       imx_iomux_v3_setup_multiple_pads(ecspi2_pads, ARRAY_SIZE(ecspi2_pads));
+
+       return 0;
+}
+
+int platinum_setup_uart(void)
+{
+       imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+       imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
+       imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
+
+       return 0;
+}
+
+int platinum_phy_config(struct phy_device *phydev)
+{
+       /* min rx data delay */
+       ksz9021_phy_extended_write(phydev, MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW,
+                                  0x0);
+       /* min tx data delay */
+       ksz9021_phy_extended_write(phydev, MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW,
+                                  0x0);
+       /* max rx/tx clock delay, min rx/tx control */
+       ksz9021_phy_extended_write(phydev, MII_KSZ9021_EXT_RGMII_CLOCK_SKEW,
+                                  0xf0f0);
+       if (phydev->drv->config)
+               phydev->drv->config(phydev);
+
+       return 0;
+}
+
+int platinum_init_gpio(void)
+{
+       /* Default GPIO's */
+       /* Toggle CONFIG_n to reset fpga on every boot */
+       gpio_direction_output(IMX_GPIO_NR(5, 18), 0);
+       /* Need delay >=2uS */
+       udelay(3);
+       gpio_set_value(IMX_GPIO_NR(5, 18), 1);
+
+       /* Default pin 1,15 high - DLP_FLASH_WPZ */
+       gpio_direction_output(IMX_GPIO_NR(1, 15), 1);
+
+       return 0;
+}
+
+int platinum_init_usb(void)
+{
+       return 0;
+}
+
+int platinum_init_finished(void)
+{
+       return 0;
+}
diff --git a/board/barco/platinum/spl_picon.c b/board/barco/platinum/spl_picon.c
new file mode 100644 (file)
index 0000000..f421c21
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * Based on: gw_ventana_spl.c which is:
+ * Copyright (C) 2014 Gateworks Corporation
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-ddr.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <spl.h>
+
+#include "platinum.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#undef RTT_NOM_120OHM  /* use 120ohm Rtt_nom vs 60ohm (lower power) */
+
+/* Configure MX6Q/DUAL mmdc DDR io registers */
+struct mx6sdl_iomux_ddr_regs mx6sdl_ddr_ioregs = {
+       /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */
+       .dram_sdclk_0 = 0x00020030,
+       .dram_sdclk_1 = 0x00020030,
+       .dram_cas = 0x00020030,
+       .dram_ras = 0x00020030,
+       .dram_reset = 0x00020030,
+       /* SDCKE[0:1]: 100k pull-up */
+       .dram_sdcke0 = 0x00003000,
+       .dram_sdcke1 = 0x00003000,
+       /* SDBA2: pull-up disabled */
+       .dram_sdba2 = 0x00000000,
+       /* SDODT[0:1]: 100k pull-up, 40 ohm */
+       .dram_sdodt0 = 0x00003030,
+       .dram_sdodt1 = 0x00003030,
+       /* SDQS[0:7]: Differential input, 40 ohm */
+       .dram_sdqs0 = 0x00000030,
+       .dram_sdqs1 = 0x00000030,
+       .dram_sdqs2 = 0x00000030,
+       .dram_sdqs3 = 0x00000030,
+       .dram_sdqs4 = 0x00000030,
+       .dram_sdqs5 = 0x00000030,
+       .dram_sdqs6 = 0x00000030,
+       .dram_sdqs7 = 0x00000030,
+       /* DQM[0:7]: Differential input, 40 ohm */
+       .dram_dqm0 = 0x00020030,
+       .dram_dqm1 = 0x00020030,
+       .dram_dqm2 = 0x00020030,
+       .dram_dqm3 = 0x00020030,
+       .dram_dqm4 = 0x00020030,
+       .dram_dqm5 = 0x00020030,
+       .dram_dqm6 = 0x00020030,
+       .dram_dqm7 = 0x00020030,
+};
+
+/* Configure MX6Q/DUAL mmdc GRP io registers */
+struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
+       /* DDR3 */
+       .grp_ddr_type = 0x000c0000,
+       .grp_ddrmode_ctl = 0x00020000,
+       /* disable DDR pullups */
+       .grp_ddrpke = 0x00000000,
+       /* ADDR[00:16], SDBA[0:1]: 40 ohm */
+       .grp_addds = 0x00000030,
+       /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */
+       .grp_ctlds = 0x00000030,
+       /* DATA[00:63]: Differential input, 40 ohm */
+       .grp_ddrmode = 0x00020000,
+       .grp_b0ds = 0x00000030,
+       .grp_b1ds = 0x00000030,
+       .grp_b2ds = 0x00000030,
+       .grp_b3ds = 0x00000030,
+       .grp_b4ds = 0x00000030,
+       .grp_b5ds = 0x00000030,
+       .grp_b6ds = 0x00000030,
+       .grp_b7ds = 0x00000030,
+};
+
+/* MT41K256M16HA-125 */
+static struct mx6_ddr3_cfg mt41k256m16ha_125 = {
+       .mem_speed = 1600,
+       .density = 4,           /* 4Gbit */
+       .width = 16,
+       .banks = 8,
+       .rowaddr = 15,
+       .coladdr = 10,
+       .pagesz = 2,
+       .trcd = 1375,
+       .trcmin = 4875,
+       .trasmin = 3500,
+};
+
+/*
+ * Values from running the Freescale DDR stress tool via USB
+ */
+static struct mx6_mmdc_calibration mx6dq_mmdc_calib = {
+       /* write leveling calibration determine */
+       .p0_mpwldectrl0 = 0x0044004E,
+       .p0_mpwldectrl1 = 0x001F0023,
+       /* Read DQS Gating calibration */
+       .p0_mpdgctrl0 = 0x02480248,
+       .p0_mpdgctrl1 = 0x0210021C,
+       /* Read Calibration: DQS delay relative to DQ read access */
+       .p0_mprddlctl = 0x42444444,
+       /* Write Calibration: DQ/DM delay relative to DQS write access */
+       .p0_mpwrdlctl = 0x36322C32,
+};
+
+static void spl_dram_init(int width)
+{
+       struct mx6_ddr3_cfg *mem = &mt41k256m16ha_125;
+       struct mx6_ddr_sysinfo sysinfo = {
+               /* width of data bus:0=16,1=32,2=64 */
+               .dsize = width / 32,
+               /* config for full 4GB range so that get_mem_size() works */
+               .cs_density = 32, /* 32Gb per CS */
+               /* single chip select */
+               .ncs = 1,
+               .cs1_mirror = 1,
+               .rtt_wr = 1 /*DDR3_RTT_60_OHM*/,        /* RTT_Wr = RZQ/4 */
+#ifdef RTT_NOM_120OHM
+               .rtt_nom = 2 /*DDR3_RTT_120_OHM*/,      /* RTT_Nom = RZQ/2 */
+#else
+               .rtt_nom = 1 /*DDR3_RTT_60_OHM*/,       /* RTT_Nom = RZQ/4 */
+#endif
+               .walat = 0,     /* Write additional latency */
+               .ralat = 5,     /* Read additional latency */
+               .mif3_mode = 3, /* Command prediction working mode */
+               .bi_on = 1,     /* Bank interleaving enabled */
+               .sde_to_rst = 0x10,     /* 14 cycles, 200us (JEDEC default) */
+               .rst_to_cke = 0x23,     /* 33 cycles, 500us (JEDEC default) */
+       };
+
+       mx6sdl_dram_iocfg(width, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs);
+       mx6_dram_cfg(&sysinfo, &mx6dq_mmdc_calib, mem);
+}
+
+/*
+ * Called from C runtime startup code (arch/arm/lib/crt0.S:_main)
+ * - we have a stack and a place to store GD, both in SRAM
+ * - no variable global data is available
+ */
+void board_init_f(ulong dummy)
+{
+       /* Setup AIPS and disable watchdog */
+       arch_cpu_init();
+
+       ccgr_init();
+       gpr_init();
+
+       /* UART iomux */
+       board_early_init_f();
+
+       /* Setup GP timer */
+       timer_init();
+
+       /* UART clocks enabled and gd valid - init serial console */
+       preloader_console_init();
+
+       /* Init DDR with 32bit width */
+       spl_dram_init(32);
+
+       /* Clear the BSS */
+       memset(__bss_start, 0, __bss_end - __bss_start);
+
+       /*
+        * Setup enet related MUXing early to give the PHY
+        * some time to wake-up from reset
+        */
+       platinum_setup_enet();
+
+       /* load/boot image from boot device */
+       board_init_r(NULL, 0);
+}
diff --git a/board/barco/platinum/spl_titanium.c b/board/barco/platinum/spl_titanium.c
new file mode 100644 (file)
index 0000000..26fe26b
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * Based on: gw_ventana_spl.c which is:
+ * Copyright (C) 2014 Gateworks Corporation
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/iomux.h>
+#include <asm/arch/mx6-ddr.h>
+#include <asm/arch/mx6-pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <asm/imx-common/mxc_i2c.h>
+#include <spl.h>
+
+#include "platinum.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#undef RTT_NOM_120OHM  /* use 120ohm Rtt_nom vs 60ohm (lower power) */
+
+/* Configure MX6Q/DUAL mmdc DDR io registers */
+struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = {
+       /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */
+       .dram_sdclk_0 = 0x00020030,
+       .dram_sdclk_1 = 0x00020030,
+       .dram_cas = 0x00020030,
+       .dram_ras = 0x00020030,
+       .dram_reset = 0x00020030,
+       /* SDCKE[0:1]: 100k pull-up */
+       .dram_sdcke0 = 0x00003000,
+       .dram_sdcke1 = 0x00003000,
+       /* SDBA2: pull-up disabled */
+       .dram_sdba2 = 0x00000000,
+       /* SDODT[0:1]: 100k pull-up, 40 ohm */
+       .dram_sdodt0 = 0x00003030,
+       .dram_sdodt1 = 0x00003030,
+       /* SDQS[0:7]: Differential input, 40 ohm */
+       .dram_sdqs0 = 0x00000030,
+       .dram_sdqs1 = 0x00000030,
+       .dram_sdqs2 = 0x00000030,
+       .dram_sdqs3 = 0x00000030,
+       .dram_sdqs4 = 0x00000030,
+       .dram_sdqs5 = 0x00000030,
+       .dram_sdqs6 = 0x00000030,
+       .dram_sdqs7 = 0x00000030,
+       /* DQM[0:7]: Differential input, 40 ohm */
+       .dram_dqm0 = 0x00020030,
+       .dram_dqm1 = 0x00020030,
+       .dram_dqm2 = 0x00020030,
+       .dram_dqm3 = 0x00020030,
+       .dram_dqm4 = 0x00020030,
+       .dram_dqm5 = 0x00020030,
+       .dram_dqm6 = 0x00020030,
+       .dram_dqm7 = 0x00020030,
+};
+
+/* Configure MX6Q/DUAL mmdc GRP io registers */
+struct mx6dq_iomux_grp_regs mx6dq_grp_ioregs = {
+       /* DDR3 */
+       .grp_ddr_type = 0x000c0000,
+       .grp_ddrmode_ctl = 0x00020000,
+       /* disable DDR pullups */
+       .grp_ddrpke = 0x00000000,
+       /* ADDR[00:16], SDBA[0:1]: 40 ohm */
+       .grp_addds = 0x00000030,
+       /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */
+       .grp_ctlds = 0x00000030,
+       /* DATA[00:63]: Differential input, 40 ohm */
+       .grp_ddrmode = 0x00020000,
+       .grp_b0ds = 0x00000030,
+       .grp_b1ds = 0x00000030,
+       .grp_b2ds = 0x00000030,
+       .grp_b3ds = 0x00000030,
+       .grp_b4ds = 0x00000030,
+       .grp_b5ds = 0x00000030,
+       .grp_b6ds = 0x00000030,
+       .grp_b7ds = 0x00000030,
+};
+
+/* MT41J128M16JT-125 */
+static struct mx6_ddr3_cfg mt41j128m16jt_125 = {
+       .mem_speed = 1600,
+       .density = 2,
+       .width = 16,
+       .banks = 8,
+       .rowaddr = 14,
+       .coladdr = 10,
+       .pagesz = 2,
+       .trcd = 1375,
+       .trcmin = 4875,
+       .trasmin = 3500,
+};
+
+static struct mx6_mmdc_calibration mx6dq_mmdc_calib = {
+       /* Write leveling calibration determine */
+       .p0_mpwldectrl0 = 0x001f001f,
+       .p0_mpwldectrl1 = 0x001f001f,
+       .p1_mpwldectrl0 = 0x00440044,
+       .p1_mpwldectrl1 = 0x00440044,
+       /* Read DQS Gating calibration */
+       .p0_mpdgctrl0 = 0x434b0350,
+       .p0_mpdgctrl1 = 0x034c0359,
+       .p1_mpdgctrl0 = 0x434b0350,
+       .p1_mpdgctrl1 = 0x03650348,
+       /* Read Calibration: DQS delay relative to DQ read access */
+       .p0_mprddlctl = 0x4436383b,
+       .p1_mprddlctl = 0x39393341,
+       /* Write Calibration: DQ/DM delay relative to DQS write access */
+       .p0_mpwrdlctl = 0x35373933,
+       .p1_mpwrdlctl = 0x48254a36,
+};
+
+static void spl_dram_init(int width)
+{
+       struct mx6_ddr3_cfg *mem = &mt41j128m16jt_125;
+       struct mx6_ddr_sysinfo sysinfo = {
+               /* width of data bus:0=16,1=32,2=64 */
+               .dsize = width / 32,
+               /* config for full 4GB range so that get_mem_size() works */
+               .cs_density = 32, /* 32Gb per CS */
+               /* single chip select */
+               .ncs = 1,
+               .cs1_mirror = 1,
+               .rtt_wr = 1 /*DDR3_RTT_60_OHM*/,        /* RTT_Wr = RZQ/4 */
+#ifdef RTT_NOM_120OHM
+               .rtt_nom = 2 /*DDR3_RTT_120_OHM*/,      /* RTT_Nom = RZQ/2 */
+#else
+               .rtt_nom = 1 /*DDR3_RTT_60_OHM*/,       /* RTT_Nom = RZQ/4 */
+#endif
+               .walat = 0,     /* Write additional latency */
+               .ralat = 5,     /* Read additional latency */
+               .mif3_mode = 3, /* Command prediction working mode */
+               .bi_on = 1,     /* Bank interleaving enabled */
+               .sde_to_rst = 0x10,     /* 14 cycles, 200us (JEDEC default) */
+               .rst_to_cke = 0x23,     /* 33 cycles, 500us (JEDEC default) */
+       };
+
+       mx6dq_dram_iocfg(width, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
+       mx6_dram_cfg(&sysinfo, &mx6dq_mmdc_calib, mem);
+}
+
+/*
+ * Called from C runtime startup code (arch/arm/lib/crt0.S:_main)
+ * - we have a stack and a place to store GD, both in SRAM
+ * - no variable global data is available
+ */
+void board_init_f(ulong dummy)
+{
+       /* Setup AIPS and disable watchdog */
+       arch_cpu_init();
+
+       ccgr_init();
+       gpr_init();
+
+       /* UART iomux */
+       board_early_init_f();
+
+       /* Setup GP timer */
+       timer_init();
+
+       /* UART clocks enabled and gd valid - init serial console */
+       preloader_console_init();
+
+       /* Init DDR with 32bit width */
+       spl_dram_init(32);
+
+       /* Clear the BSS */
+       memset(__bss_start, 0, __bss_end - __bss_start);
+
+       /*
+        * Setup enet related MUXing early to give the PHY
+        * some time to wake-up from reset
+        */
+       platinum_setup_enet();
+
+       /* load/boot image from boot device */
+       board_init_r(NULL, 0);
+}
index 84e36439fa18ddf10040043f63abd2fba478562f..ae6945ba9c9ca2b7f5f86f7f61bee3f310634eb0 100644 (file)
 #include <netdev.h>
 #include <fdt_support.h>
 #include <sata.h>
+#include <splash.h>
 #include <asm/arch/crm_regs.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/iomux.h>
+#include <asm/arch/mxc_hdmi.h>
 #include <asm/imx-common/mxc_i2c.h>
 #include <asm/imx-common/sata.h>
+#include <asm/imx-common/video.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <dm/platform_data/serial_mxc.h>
 #include "common.h"
 #include "../common/eeprom.h"
+#include "../common/common.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#ifdef CONFIG_SPLASH_SCREEN
+static struct splash_location cm_fx6_splash_locations[] = {
+       {
+               .name = "sf",
+               .storage = SPLASH_STORAGE_SF,
+               .offset = 0x100000,
+       },
+};
+
+int splash_screen_prepare(void)
+{
+       return splash_source_load(cm_fx6_splash_locations,
+                                 ARRAY_SIZE(cm_fx6_splash_locations));
+}
+#endif
+
+#ifdef CONFIG_IMX_HDMI
+static void cm_fx6_enable_hdmi(struct display_info_t const *dev)
+{
+       imx_enable_hdmi_phy();
+}
+
+struct display_info_t const displays[] = {
+       {
+               .bus    = -1,
+               .addr   = 0,
+               .pixfmt = IPU_PIX_FMT_RGB24,
+               .detect = detect_hdmi,
+               .enable = cm_fx6_enable_hdmi,
+               .mode   = {
+                       .name           = "HDMI",
+                       .refresh        = 60,
+                       .xres           = 1024,
+                       .yres           = 768,
+                       .pixclock       = 40385,
+                       .left_margin    = 220,
+                       .right_margin   = 40,
+                       .upper_margin   = 21,
+                       .lower_margin   = 7,
+                       .hsync_len      = 60,
+                       .vsync_len      = 10,
+                       .sync           = FB_SYNC_EXT,
+                       .vmode          = FB_VMODE_NONINTERLACED,
+               }
+       },
+};
+size_t display_count = ARRAY_SIZE(displays);
+
+static void cm_fx6_setup_display(void)
+{
+       struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+       int reg;
+
+       enable_ipu_clock();
+       imx_setup_hdmi();
+       reg = __raw_readl(&mxc_ccm->CCGR3);
+       reg |= MXC_CCM_CCGR3_IPU1_IPU_DI0_MASK;
+       writel(reg, &mxc_ccm->CCGR3);
+}
+#else
+static inline void cm_fx6_setup_display(void) {}
+#endif /* CONFIG_VIDEO_IPUV3 */
+
 #ifdef CONFIG_DWC_AHSATA
 static int cm_fx6_issd_gpios[] = {
        /* The order of the GPIOs in the array is important! */
@@ -345,32 +412,36 @@ static iomux_v3_cfg_t const enet_pads[] = {
                                                MUX_PAD_CTRL(ENET_PAD_CTRL)),
 };
 
-static int handle_mac_address(void)
+static int handle_mac_address(char *env_var, uint eeprom_bus)
 {
        unsigned char enetaddr[6];
        int rc;
 
-       rc = eth_getenv_enetaddr("ethaddr", enetaddr);
+       rc = eth_getenv_enetaddr(env_var, enetaddr);
        if (rc)
                return 0;
 
-       rc = cl_eeprom_read_mac_addr(enetaddr);
+       rc = cl_eeprom_read_mac_addr(enetaddr, eeprom_bus);
        if (rc)
                return rc;
 
        if (!is_valid_ether_addr(enetaddr))
                return -1;
 
-       return eth_setenv_enetaddr("ethaddr", enetaddr);
+       return eth_setenv_enetaddr(env_var, enetaddr);
 }
 
+#define SB_FX6_I2C_EEPROM_BUS  0
+#define NO_MAC_ADDR            "No MAC address found for %s\n"
 int board_eth_init(bd_t *bis)
 {
        int err;
 
-       err = handle_mac_address();
-       if (err)
-               puts("No MAC address found\n");
+       if (handle_mac_address("ethaddr", CONFIG_SYS_I2C_EEPROM_BUS))
+               printf(NO_MAC_ADDR, "primary NIC");
+
+       if (handle_mac_address("eth1addr", SB_FX6_I2C_EEPROM_BUS))
+               printf(NO_MAC_ADDR, "secondary NIC");
 
        SETUP_IOMUX_PADS(enet_pads);
        /* phy reset */
@@ -464,7 +535,13 @@ int ft_board_setup(void *blob, bd_t *bd)
 
        /* MAC addr */
        if (eth_getenv_enetaddr("ethaddr", enetaddr)) {
-               fdt_find_and_setprop(blob, "/fec", "local-mac-address",
+               fdt_find_and_setprop(blob,
+                                    "/soc/aips-bus@02100000/ethernet@02188000",
+                                    "local-mac-address", enetaddr, 6, 1);
+       }
+
+       if (eth_getenv_enetaddr("eth1addr", enetaddr)) {
+               fdt_find_and_setprop(blob, "/eth@pcie", "local-mac-address",
                                     enetaddr, 6, 1);
        }
 
@@ -506,6 +583,8 @@ int board_init(void)
        if (ret)
                printf("Warning: I2C setup failed: %d\n", ret);
 
+       cm_fx6_setup_display();
+
        return 0;
 }
 
index 9583149bed61bd315dcea3c6abdfa1b1c9226a49..592ef3d30fcd01f4bc0c3241b418095e2d1fc2ea 100644 (file)
@@ -110,7 +110,7 @@ static int handle_mac_address(void)
        if (rv)
                return 0;
 
-       rv = cl_eeprom_read_mac_addr(enetaddr);
+       rv = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
        if (rv)
                get_efuse_mac_addr(enetaddr);
 
index 43463d5b4701cf0220049e3f82e34f47d40e608e..c4ea8ea875f533f21a4d0bec13bf8795026658b9 100644 (file)
@@ -19,6 +19,7 @@
 #include <i2c.h>
 #include <usb.h>
 #include <mmc.h>
+#include <splash.h>
 #include <twl4030.h>
 #include <linux/compiler.h>
 
@@ -59,11 +60,18 @@ void get_board_mem_timings(struct board_sdrc_timings *timings)
 }
 #endif
 
-#define CM_T35_SPLASH_NAND_OFFSET 0x100000
+struct splash_location splash_locations[] = {
+       {
+               .name = "nand",
+               .storage = SPLASH_STORAGE_NAND,
+               .offset = 0x100000,
+       },
+};
 
 int splash_screen_prepare(void)
 {
-       return cl_splash_screen_prepare(CM_T35_SPLASH_NAND_OFFSET);
+       return splash_source_load(splash_locations,
+                                 ARRAY_SIZE(splash_locations));
 }
 
 /*
@@ -429,7 +437,7 @@ static int handle_mac_address(void)
        if (rc)
                return 0;
 
-       rc = cl_eeprom_read_mac_addr(enetaddr);
+       rc = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
        if (rc)
                return rc;
 
index cac1ad9ef11d1ca5be5c100c6677a4795bac0b5e..624cf4c03463f472b2a3b164cec1c92c0f20c63c 100644 (file)
@@ -163,7 +163,7 @@ static int cm_t3517_handle_mac_address(void)
        if (ret)
                return 0;
 
-       ret = cl_eeprom_read_mac_addr(enetaddr);
+       ret = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
        if (ret) {
                ret = am3517_get_efuse_enetaddr(enetaddr);
                if (ret)
index 2c2530ab3fd1e6ce5c3e200276bebaac51daea43..fdea909ff74a0109ac42282c11a1130e468033d8 100644 (file)
@@ -165,7 +165,7 @@ static int handle_mac_address(void)
        if (ret)
                return 0;
 
-       ret = cl_eeprom_read_mac_addr(enetaddr);
+       ret = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
        if (ret || !is_valid_ether_addr(enetaddr))
                generate_mac_addr(enetaddr);
 
index dbf0009652a69263b48a15e19c8dc338f3068102..286f32731da28e0f81ff811600f8ee6da215b67e 100644 (file)
@@ -9,5 +9,4 @@
 obj-y                          += common.o
 obj-$(CONFIG_SYS_I2C)          += eeprom.o
 obj-$(CONFIG_LCD)              += omap3_display.o
-obj-$(CONFIG_SPLASH_SCREEN)    += splash.o
 obj-$(CONFIG_SMC911X)          += omap3_smc911x.o
index 68ffb111dc369a0b65dd7d514b791a422f0717b5..8f38b79fb0543042f2f8599df22fd3d26cc2d65b 100644 (file)
@@ -24,15 +24,6 @@ static inline int cl_usb_hub_init(int gpio, const char *label)
 static inline void cl_usb_hub_deinit(int gpio) {}
 #endif /* CONFIG_CMD_USB */
 
-#ifdef CONFIG_SPLASH_SCREEN
-int cl_splash_screen_prepare(int nand_offset);
-#else /* !CONFIG_SPLASH_SCREEN */
-static inline int cl_splash_screen_prepare(int nand_offset)
-{
-       return -ENOSYS;
-}
-#endif /* CONFIG_SPLASH_SCREEN */
-
 #ifdef CONFIG_SMC911X
 int cl_omap3_smc911x_init(int id, int cs, u32 base_addr,
                          int (*reset)(int), int rst_gpio);
index a45e7be11f76a0ba2f3548bef62f41198c641974..77bcea44b41cf5a5c653f1ffa2621c37ed5ea1ec 100644 (file)
@@ -31,6 +31,7 @@
 #define LAYOUT_INVALID 0
 #define LAYOUT_LEGACY  0xff
 
+static int cl_eeprom_bus;
 static int cl_eeprom_layout; /* Implicitly LAYOUT_INVALID */
 
 static int cl_eeprom_read(uint offset, uchar *buf, int len)
@@ -38,7 +39,7 @@ static int cl_eeprom_read(uint offset, uchar *buf, int len)
        int res;
        unsigned int current_i2c_bus = i2c_get_bus_num();
 
-       res = i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS);
+       res = i2c_set_bus_num(cl_eeprom_bus);
        if (res < 0)
                return res;
 
@@ -50,13 +51,18 @@ static int cl_eeprom_read(uint offset, uchar *buf, int len)
        return res;
 }
 
-static int cl_eeprom_setup_layout(void)
+static int cl_eeprom_setup(uint eeprom_bus)
 {
        int res;
 
-       if (cl_eeprom_layout != LAYOUT_INVALID)
+       /*
+        * We know the setup was already done when the layout is set to a valid
+        * value and we're using the same bus as before.
+        */
+       if (cl_eeprom_layout != LAYOUT_INVALID && eeprom_bus == cl_eeprom_bus)
                return 0;
 
+       cl_eeprom_bus = eeprom_bus;
        res = cl_eeprom_read(EEPROM_LAYOUT_VER_OFFSET,
                             (uchar *)&cl_eeprom_layout, 1);
        if (res) {
@@ -77,7 +83,7 @@ void get_board_serial(struct tag_serialnr *serialnr)
 
        memset(serialnr, 0, sizeof(*serialnr));
 
-       if (cl_eeprom_setup_layout())
+       if (cl_eeprom_setup(CONFIG_SYS_I2C_EEPROM_BUS))
                return;
 
        offset = (cl_eeprom_layout != LAYOUT_LEGACY) ?
@@ -96,11 +102,11 @@ void get_board_serial(struct tag_serialnr *serialnr)
  * Routine: cl_eeprom_read_mac_addr
  * Description: read mac address and store it in buf.
  */
-int cl_eeprom_read_mac_addr(uchar *buf)
+int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus)
 {
        uint offset;
 
-       if (cl_eeprom_setup_layout())
+       if (cl_eeprom_setup(eeprom_bus))
                return 0;
 
        offset = (cl_eeprom_layout != LAYOUT_LEGACY) ?
@@ -123,7 +129,7 @@ u32 cl_eeprom_get_board_rev(void)
        if (board_rev)
                return board_rev;
 
-       if (cl_eeprom_setup_layout())
+       if (cl_eeprom_setup(CONFIG_SYS_I2C_EEPROM_BUS))
                return 0;
 
        if (cl_eeprom_layout != LAYOUT_LEGACY)
index 85d5bf03d69171c81f57dcaee0e05f7af509399d..50c6b0226fc0ee2a39102f40e92e7288c823ca87 100644 (file)
 #define _EEPROM_
 
 #ifdef CONFIG_SYS_I2C
-int cl_eeprom_read_mac_addr(uchar *buf);
+int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus);
 u32 cl_eeprom_get_board_rev(void);
 #else
-static inline int cl_eeprom_read_mac_addr(uchar *buf)
+static inline int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus)
 {
        return 1;
 }
diff --git a/board/compulab/common/splash.c b/board/compulab/common/splash.c
deleted file mode 100644 (file)
index 49ed49b..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
- *
- * Authors: Igor Grinberg <grinberg@compulab.co.il>
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#include <common.h>
-#include <nand.h>
-#include <bmp_layout.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#ifdef CONFIG_CMD_NAND
-static int splash_load_from_nand(u32 bmp_load_addr, int nand_offset)
-{
-       struct bmp_header *bmp_hdr;
-       int res;
-       size_t bmp_size, bmp_header_size = sizeof(struct bmp_header);
-
-       if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp)
-               goto splash_address_too_high;
-
-       res = nand_read_skip_bad(&nand_info[nand_curr_device],
-                       nand_offset, &bmp_header_size,
-                       NULL, nand_info[nand_curr_device].size,
-                       (u_char *)bmp_load_addr);
-       if (res < 0)
-               return res;
-
-       bmp_hdr = (struct bmp_header *)bmp_load_addr;
-       bmp_size = le32_to_cpu(bmp_hdr->file_size);
-
-       if (bmp_load_addr + bmp_size >= gd->start_addr_sp)
-               goto splash_address_too_high;
-
-       return nand_read_skip_bad(&nand_info[nand_curr_device],
-                       nand_offset, &bmp_size,
-                       NULL, nand_info[nand_curr_device].size,
-                       (u_char *)bmp_load_addr);
-
-splash_address_too_high:
-       printf("Error: splashimage address too high. Data overwrites U-Boot "
-               "and/or placed beyond DRAM boundaries.\n");
-
-       return -1;
-}
-#else
-static inline int splash_load_from_nand(u32 bmp_load_addr, int nand_offset)
-{
-       return -1;
-}
-#endif /* CONFIG_CMD_NAND */
-
-int cl_splash_screen_prepare(int nand_offset)
-{
-       char *env_splashimage_value;
-       u32 bmp_load_addr;
-
-       env_splashimage_value = getenv("splashimage");
-       if (env_splashimage_value == NULL)
-               return -1;
-
-       bmp_load_addr = simple_strtoul(env_splashimage_value, 0, 16);
-       if (bmp_load_addr == 0) {
-               printf("Error: bad splashimage address specified\n");
-               return -1;
-       }
-
-       return splash_load_from_nand(bmp_load_addr, nand_offset);
-}
index d1c1931e468fb32034bd00cfbafc4f2017940ad0..a5f1d98bd1c548259480790a48e78839c830f032 100644 (file)
@@ -59,7 +59,7 @@ DATA 4 0x63fd9090 0x4d444c44
 DATA 4 0x63fd907c 0x01370138
 DATA 4 0x63fd9080 0x013b013c
 DATA 4 0x63fd9018 0x00011740
-DATA 4 0x63fd9000 0xc3190000
+DATA 4 0x63fd9000 0x83190000
 DATA 4 0x63fd900c 0x9f5152e3
 DATA 4 0x63fd9010 0xb68e8a63
 DATA 4 0x63fd9014 0x01ff00db
@@ -72,6 +72,7 @@ DATA 4 0x63fd901c 0x00008033
 DATA 4 0x63fd901c 0x00028031
 DATA 4 0x63fd901c 0x052080b0
 DATA 4 0x63fd901c 0x04008040
+DATA 4 0x63fd9000 0xc3190000
 DATA 4 0x63fd901c 0x0000803a
 DATA 4 0x63fd901c 0x0000803b
 DATA 4 0x63fd901c 0x00028039
index 59387ffaaa7e7960e625f3b8e0833f7f297dee23..a90360f2df9ef887d6b4938153ea814b8225b1e8 100644 (file)
@@ -311,30 +311,9 @@ static void setup_gpmi_nand(void)
        /* config gpmi nand iomux */
        imx_iomux_v3_setup_multiple_pads(gpmi_pads, ARRAY_SIZE(gpmi_pads));
 
-       /* gate ENFC_CLK_ROOT clock first,before clk source switch */
-       clrbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
-       clrbits_le32(&mxc_ccm->CCGR4,
-               MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK);
-
-       /* config gpmi and bch clock to 100 MHz */
-       clrsetbits_le32(&mxc_ccm->cs2cdr,
-                       MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK |
-                       MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK |
-                       MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK,
-                       MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
+       setup_gpmi_io_clk((MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
                        MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
-                       MXC_CCM_CS2CDR_ENFC_CLK_SEL(3));
-
-       /* enable ENFC_CLK_ROOT clock */
-       setbits_le32(&mxc_ccm->CCGR2, MXC_CCM_CCGR2_IOMUX_IPT_CLK_IO_MASK);
-
-       /* enable gpmi and bch clock gating */
-       setbits_le32(&mxc_ccm->CCGR4,
-                    MXC_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB_MASK |
-                    MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH_MASK |
-                    MXC_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_MASK |
-                    MXC_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB_MASK |
-                    MXC_CCM_CCGR4_PL301_MX6QPER1_BCH_OFFSET);
+                       MXC_CCM_CS2CDR_ENFC_CLK_SEL(3)));
 
        /* enable apbh clock gating */
        setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
index f52f300bedf83fa806b1f1b2d4414a294ce5987b..c0f5d9c8e4b17162d0a4ce4d652dcdb74e009ba5 100644 (file)
@@ -4,3 +4,4 @@ S:      Maintained
 F:     board/freescale/mx6sxsabresd/
 F:     include/configs/mx6sxsabresd.h
 F:     configs/mx6sxsabresd_defconfig
+F:     configs/mx6sxsabresd_spl_defconfig
index 5cc58ac8683325ebbd6df685065b41916da8e7b9..a2c9aae32cd3a03bf3d68dbe3c80a0e9615f5258 100644 (file)
@@ -326,6 +326,7 @@ int board_mmc_getcd(struct mmc *mmc)
 
 int board_mmc_init(bd_t *bis)
 {
+#ifndef CONFIG_SPL_BUILD
        int i, ret;
 
        /*
@@ -369,6 +370,47 @@ int board_mmc_init(bd_t *bis)
        }
 
        return 0;
+#else
+       struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+       u32 val;
+       u32 port;
+
+       val = readl(&src_regs->sbmr1);
+
+       if ((val & 0xc0) != 0x40) {
+               printf("Not boot from USDHC!\n");
+               return -EINVAL;
+       }
+
+       port = (val >> 11) & 0x3;
+       printf("port %d\n", port);
+       switch (port) {
+       case 1:
+               imx_iomux_v3_setup_multiple_pads(
+                       usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
+               usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+               usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR;
+               break;
+       case 2:
+               imx_iomux_v3_setup_multiple_pads(
+                       usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
+               gpio_direction_input(USDHC3_CD_GPIO);
+               gpio_direction_output(USDHC3_PWR_GPIO, 1);
+               usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
+               usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR;
+               break;
+       case 3:
+               imx_iomux_v3_setup_multiple_pads(
+                       usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
+               gpio_direction_input(USDHC4_CD_GPIO);
+               usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
+               usdhc_cfg[0].esdhc_base = USDHC4_BASE_ADDR;
+               break;
+       }
+
+       gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
+       return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
+#endif
 }
 
 #ifdef CONFIG_FSL_QSPI
@@ -423,14 +465,135 @@ int board_init(void)
        return 0;
 }
 
-int board_late_init(void)
+int checkboard(void)
 {
+       puts("Board: MX6SX SABRE SDB\n");
+
        return 0;
 }
 
-int checkboard(void)
+#ifdef CONFIG_SPL_BUILD
+#include <libfdt.h>
+#include <spl.h>
+#include <asm/arch/mx6-ddr.h>
+
+const struct mx6sx_iomux_ddr_regs mx6_ddr_ioregs = {
+       .dram_dqm0 = 0x00000028,
+       .dram_dqm1 = 0x00000028,
+       .dram_dqm2 = 0x00000028,
+       .dram_dqm3 = 0x00000028,
+       .dram_ras = 0x00000020,
+       .dram_cas = 0x00000020,
+       .dram_odt0 = 0x00000020,
+       .dram_odt1 = 0x00000020,
+       .dram_sdba2 = 0x00000000,
+       .dram_sdcke0 = 0x00003000,
+       .dram_sdcke1 = 0x00003000,
+       .dram_sdclk_0 = 0x00000030,
+       .dram_sdqs0 = 0x00000028,
+       .dram_sdqs1 = 0x00000028,
+       .dram_sdqs2 = 0x00000028,
+       .dram_sdqs3 = 0x00000028,
+       .dram_reset = 0x00000020,
+};
+
+const struct mx6sx_iomux_grp_regs mx6_grp_ioregs = {
+       .grp_addds = 0x00000020,
+       .grp_ddrmode_ctl = 0x00020000,
+       .grp_ddrpke = 0x00000000,
+       .grp_ddrmode = 0x00020000,
+       .grp_b0ds = 0x00000028,
+       .grp_b1ds = 0x00000028,
+       .grp_ctlds = 0x00000020,
+       .grp_ddr_type = 0x000c0000,
+       .grp_b2ds = 0x00000028,
+       .grp_b3ds = 0x00000028,
+};
+
+const struct mx6_mmdc_calibration mx6_mmcd_calib = {
+       .p0_mpwldectrl0 = 0x00290025,
+       .p0_mpwldectrl1 = 0x00220022,
+       .p0_mpdgctrl0 = 0x41480144,
+       .p0_mpdgctrl1 = 0x01340130,
+       .p0_mprddlctl = 0x3C3E4244,
+       .p0_mpwrdlctl = 0x34363638,
+};
+
+static struct mx6_ddr3_cfg mem_ddr = {
+       .mem_speed = 1600,
+       .density = 4,
+       .width = 32,
+       .banks = 8,
+       .rowaddr = 15,
+       .coladdr = 10,
+       .pagesz = 2,
+       .trcd = 1375,
+       .trcmin = 4875,
+       .trasmin = 3500,
+};
+
+static void ccgr_init(void)
 {
-       puts("Board: MX6SX SABRE SDB\n");
+       struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
+
+       writel(0xFFFFFFFF, &ccm->CCGR0);
+       writel(0xFFFFFFFF, &ccm->CCGR1);
+       writel(0xFFFFFFFF, &ccm->CCGR2);
+       writel(0xFFFFFFFF, &ccm->CCGR3);
+       writel(0xFFFFFFFF, &ccm->CCGR4);
+       writel(0xFFFFFFFF, &ccm->CCGR5);
+       writel(0xFFFFFFFF, &ccm->CCGR6);
+       writel(0xFFFFFFFF, &ccm->CCGR7);
+}
 
-       return 0;
+static void spl_dram_init(void)
+{
+       struct mx6_ddr_sysinfo sysinfo = {
+               .dsize = mem_ddr.width/32,
+               .cs_density = 24,
+               .ncs = 1,
+               .cs1_mirror = 0,
+               .rtt_wr = 2,
+               .rtt_nom = 2,           /* RTT_Nom = RZQ/2 */
+               .walat = 1,             /* Write additional latency */
+               .ralat = 5,             /* Read additional latency */
+               .mif3_mode = 3,         /* Command prediction working mode */
+               .bi_on = 1,             /* Bank interleaving enabled */
+               .sde_to_rst = 0x10,     /* 14 cycles, 200us (JEDEC default) */
+               .rst_to_cke = 0x23,     /* 33 cycles, 500us (JEDEC default) */
+       };
+
+       mx6sx_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
+       mx6_dram_cfg(&sysinfo, &mx6_mmcd_calib, &mem_ddr);
+}
+
+void board_init_f(ulong dummy)
+{
+       /* setup AIPS and disable watchdog */
+       arch_cpu_init();
+
+       ccgr_init();
+
+       /* iomux and setup of i2c */
+       board_early_init_f();
+
+       /* setup GP timer */
+       timer_init();
+
+       /* UART clocks enabled and gd valid - init serial console */
+       preloader_console_init();
+
+       /* DDR initialization */
+       spl_dram_init();
+
+       /* Clear the BSS. */
+       memset(__bss_start, 0, __bss_end - __bss_start);
+
+       /* load/boot image from boot device */
+       board_init_r(NULL, 0);
 }
+
+void reset_cpu(ulong addr)
+{
+}
+#endif
diff --git a/board/maxbcm/binary.0 b/board/maxbcm/binary.0
deleted file mode 100644 (file)
index 17bfad9..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
---------
-WARNING:
---------
-This file should contain the bin_hdr generated by the original Marvell
-U-Boot implementation. As this is currently not included in this
-U-Boot version, we have added this placeholder, so that the U-Boot
-image can be generated without errors.
-
-If you have a known to be working bin_hdr for your board, then you
-just need to replace this text file here with the binary header
-and recompile U-Boot.
-
-In a few weeks, mainline U-Boot will get support to generate the
-bin_hdr with the DDR training code itself. By implementing this code
-as SPL U-Boot. Then this file will not be needed any more and will
-get removed.
-
index 5a3bc67c1c8fae78a063cda5dba3786434063fb2..cc057925566c584d66b0dc73207f5a62523ad2f6 100644 (file)
@@ -9,4 +9,4 @@ VERSION         1
 BOOT_FROM      spi
 
 # Binary Header (bin_hdr) with DDR3 training code
-BINARY board/maxbcm/binary.0 0000005b 00000068
+BINARY spl/u-boot-spl.bin 0000005b 00000068
index 7fc83ee8205d2a5a00ed86aaf8d02b9032365fd2..46b16ac29ccc843aaeeb85c42818d1638aaff9df 100644 (file)
@@ -11,6 +11,9 @@
 #include <asm/arch/soc.h>
 #include <linux/mbus.h>
 
+#include "../drivers/ddr/mvebu/ddr3_hw_training.h"
+#include "../arch/arm/mvebu-common/serdes/high_speed_env_spec.h"
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /* Base addresses for the external device chip selects */
@@ -19,8 +22,84 @@ DECLARE_GLOBAL_DATA_PTR;
 #define DEV_CS2_BASE           0xe2000000
 #define DEV_CS3_BASE           0xe3000000
 
-/* Needed for dynamic (board-specific) mbus configuration */
-extern struct mvebu_mbus_state mbus_state;
+/* DDR3 static configuration */
+MV_DRAM_MC_INIT ddr3_b0_maxbcm[MV_MAX_DDR3_STATIC_SIZE] = {
+       {0x00001400, 0x7301CC30},       /* DDR SDRAM Configuration Register */
+       {0x00001404, 0x30000820},       /* Dunit Control Low Register */
+       {0x00001408, 0x5515BAAB},       /* DDR SDRAM Timing (Low) Register */
+       {0x0000140C, 0x38DA3F97},       /* DDR SDRAM Timing (High) Register */
+       {0x00001410, 0x20100005},       /* DDR SDRAM Address Control Register */
+       {0x00001414, 0x0000F3FF},       /* DDR SDRAM Open Pages Control Reg */
+       {0x00001418, 0x00000e00},       /* DDR SDRAM Operation Register */
+       {0x0000141C, 0x00000672},       /* DDR SDRAM Mode Register */
+       {0x00001420, 0x00000004},       /* DDR SDRAM Extended Mode Register */
+       {0x00001424, 0x0000F3FF},       /* Dunit Control High Register */
+       {0x00001428, 0x0011A940},       /* Dunit Control High Register */
+       {0x0000142C, 0x014C5134},       /* Dunit Control High Register */
+       {0x0000147C, 0x0000D771},
+
+       {0x00001494, 0x00010000},       /* DDR SDRAM ODT Control (Low) Reg */
+       {0x0000149C, 0x00000001},       /* DDR Dunit ODT Control Register */
+       {0x000014A0, 0x00000001},
+       {0x000014A8, 0x00000101},
+
+       /* Recommended Settings from Marvell for 4 x 16 bit devices: */
+       {0x000014C0, 0x192424C9},       /* DRAM addr and Ctrl Driving Strenght*/
+       {0x000014C4, 0xAAA24C9},        /* DRAM Data and DQS Driving Strenght */
+
+       /*
+        * DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the
+        * training sequence
+        */
+       {0x000200e8, 0x3FFF0E01},
+       {0x00020184, 0x3FFFFFE0},       /* Close fast path Window to - 2G */
+
+       {0x0001504, 0x3FFFFFE1},        /* CS0 Size */
+       {0x000150C, 0x00000000},        /* CS1 Size */
+       {0x0001514, 0x00000000},        /* CS2 Size */
+       {0x000151C, 0x00000000},        /* CS3 Size */
+
+       {0x0020220, 0x00000007},        /* Reserved */
+
+       {0x00001538, 0x0000000B},       /* Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000B},       /* Read Data Ready Delay Register */
+
+       {0x000015D0, 0x00000670},       /* MR0 */
+       {0x000015D4, 0x00000044},       /* MR1 */
+       {0x000015D8, 0x00000018},       /* MR2 */
+       {0x000015DC, 0x00000000},       /* MR3 */
+       {0x000015E0, 0x00000001},
+       {0x000015E4, 0x00203c18},       /* ZQDS Configuration Register */
+       {0x000015EC, 0xF800A225},       /* DDR PHY */
+
+       {0x0, 0x0}
+};
+
+MV_DRAM_MODES maxbcm_ddr_modes[MV_DDR3_MODES_NUMBER] = {
+       {"maxbcm_1600-800", 0xB, 0x5, 0x0, A0, ddr3_b0_maxbcm,  NULL},
+};
+
+extern MV_SERDES_CHANGE_M_PHY serdes_change_m_phy[];
+
+/* MAXBCM: SERDES 0-4 PCIE, Serdes 7 = SGMII 0, all others =  unconnected */
+MV_BIN_SERDES_CFG maxbcm_serdes_cfg[] = {
+       { MV_PEX_ROOT_COMPLEX, 0x20011111, 0x00000000,
+         { PEX_BUS_MODE_X1, PEX_BUS_MODE_X1, PEX_BUS_DISABLED,
+           PEX_BUS_DISABLED },
+         0x1f, serdes_change_m_phy
+       }
+};
+
+MV_DRAM_MODES *ddr3_get_static_ddr_mode(void)
+{
+       /* Only one mode supported for this board */
+       return &maxbcm_ddr_modes[0];
+}
+
+MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
+{
+       return &maxbcm_serdes_cfg[0];
+}
 
 int board_early_init_f(void)
 {
@@ -63,9 +142,7 @@ int checkboard(void)
 /* Configure and enable MV88E6185 switch */
 void reset_phy(void)
 {
-       u16 devadr = CONFIG_PHY_BASE_ADDR;
        char *name = "neta0";
-       u16 reg;
 
        if (miiphy_set_current_dev(name))
                return;
index f614f88cc611444be2b05e24c9d454525605a68b..8ab48cd91c44aae6cc5fad3ab0a0308a0344814e 100644 (file)
@@ -7,13 +7,3 @@ config SYS_CONFIG_NAME
        default "arcangel4"
 
 endif
-
-if TARGET_ARCANGEL4_BE
-
-config SYS_VENDOR
-       default "synopsys"
-
-config SYS_CONFIG_NAME
-       default "arcangel4-be"
-
-endif
index 720edd8893f14417b35696e0126ac44ee0bcc29e..43114cea5ecf5dc180dc218dd0d54a785d7ca80b 100644 (file)
@@ -3,5 +3,4 @@ M:      Alexey Brodkin <abrodkin@synopsys.com>
 S:     Maintained
 F:     include/configs/arcangel4.h
 F:     configs/arcangel4_defconfig
-F:     include/configs/arcangel4-be.h
 F:     configs/arcangel4-be_defconfig
index 42a8d0c400e5917262f709fffe128095568e50a7..3110405a1b615ad938b85df61ff88000feca21d1 100644 (file)
 
 #include <common.h>
 #include <config.h>
+#include <fdtdec.h>
 #include <netdev.h>
 #include <asm/processor.h>
 #include <asm/microblaze_intc.h>
 #include <asm/asm.h>
 #include <asm/gpio.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #ifdef CONFIG_XILINX_GPIO
 static int reset_pin = -1;
 #endif
 
+#ifdef CONFIG_OF_CONTROL
+ulong ram_base;
+
+void dram_init_banksize(void)
+{
+       gd->bd->bi_dram[0].start = ram_base;
+       gd->bd->bi_dram[0].size = get_effective_memsize();
+}
+
+int dram_init(void)
+{
+       int node;
+       fdt_addr_t addr;
+       fdt_size_t size;
+       const void *blob = gd->fdt_blob;
+
+       node = fdt_node_offset_by_prop_value(blob, -1, "device_type",
+                                            "memory", 7);
+       if (node == -FDT_ERR_NOTFOUND) {
+               debug("DRAM: Can't get memory node\n");
+               return 1;
+       }
+       addr = fdtdec_get_addr_size(blob, node, "reg", &size);
+       if (addr == FDT_ADDR_T_NONE || size == 0) {
+               debug("DRAM: Can't get base address or size\n");
+               return 1;
+       }
+       ram_base = addr;
+
+       gd->ram_top = addr; /* In setup_dest_addr() is done +ram_size */
+       gd->ram_size = size;
+
+       return 0;
+};
+#else
+int dram_init(void)
+{
+       gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+       return 0;
+}
+#endif
+
 int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 #ifdef CONFIG_XILINX_GPIO
index 71f16dc5a050cd029ccbd10d7e3a5c2fe01b20d4..7216a1392230e32e8e980d36e26391d3b512eac3 100644 (file)
@@ -198,6 +198,7 @@ obj-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o
 obj-$(CONFIG_I2C_EDID) += edid.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-y += splash.o
+obj-$(CONFIG_SPLASH_SOURCE) += splash_source.o
 obj-$(CONFIG_LCD) += lcd.o lcd_console.o
 obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
 obj-$(CONFIG_LYNXKDI) += lynxkdi.o
index 79531377a78b6d4b304c3f9bff7590b2ae0fa20f..d25329a0aa87238eb3a40b185679eedefe121d49 100644 (file)
@@ -262,7 +262,7 @@ static int zero_global_data(void)
 
 static int setup_mon_len(void)
 {
-#ifdef __ARM__
+#if defined(__ARM__) || defined(__MICROBLAZE__)
        gd->mon_len = (ulong)&__bss_end - (ulong)_start;
 #elif defined(CONFIG_SANDBOX)
        gd->mon_len = (ulong)&_end - (ulong)_init;
@@ -909,7 +909,7 @@ static init_fnc_t init_sequence_f[] = {
 #endif
        announce_dram_init,
        /* TODO: unify all these dram functions? */
-#if defined(CONFIG_ARM) || defined(CONFIG_X86)
+#if defined(CONFIG_ARM) || defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE)
        dram_init,              /* configure available RAM banks */
 #endif
 #if defined(CONFIG_MIPS) || defined(CONFIG_PPC)
index 68a9448b5549da7f0e9b1d0db843dbd7f3de0486..907b33cca7624124cd251b656db219a1e5052449 100644 (file)
@@ -294,6 +294,15 @@ static int initr_announce(void)
        return 0;
 }
 
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+static int initr_manual_reloc_cmdtable(void)
+{
+       fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd),
+                      ll_entry_count(cmd_tbl_t, cmd));
+       return 0;
+}
+#endif
+
 #if !defined(CONFIG_SYS_NO_FLASH)
 static int initr_flash(void)
 {
@@ -702,6 +711,9 @@ init_fnc_t init_sequence_r[] = {
        initr_serial,
        initr_announce,
        INIT_FUNC_WATCHDOG_RESET
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+       initr_manual_reloc_cmdtable,
+#endif
 #ifdef CONFIG_PPC
        initr_trap,
 #endif
@@ -801,7 +813,7 @@ init_fnc_t init_sequence_r[] = {
 #if defined(CONFIG_ARM)
        initr_enable_interrupts,
 #endif
-#ifdef CONFIG_X86
+#if defined(CONFIG_X86) || defined(CONFIG_MICROBLAZE)
        timer_init,             /* initialize timer */
 #endif
 #if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT)
index e6d8a7ae2c50715daa03af64934f21d23d4635a7..e9eab232f961bb873a019fde8580a06fe4236b80 100644 (file)
@@ -183,8 +183,14 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        bd_t *bd = gd->bd;
-       print_num("mem start      ",    (ulong)bd->bi_memstart);
-       print_lnum("mem size       ",   (u64)bd->bi_memsize);
+       int i;
+
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
+               print_num("DRAM bank",  i);
+               print_num("-> start",   bd->bi_dram[i].start);
+               print_num("-> size",    bd->bi_dram[i].size);
+       }
+
        print_num("flash start    ",    (ulong)bd->bi_flashstart);
        print_num("flash size     ",    (ulong)bd->bi_flashsize);
        print_num("flash offset   ",    (ulong)bd->bi_flashoffset);
@@ -196,6 +202,12 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        print_eths();
 #endif
        printf("baudrate    = %u bps\n", gd->baudrate);
+       print_num("relocaddr", gd->relocaddr);
+       print_num("reloc off", gd->reloc_off);
+       print_num("fdt_blob", (ulong)gd->fdt_blob);
+       print_num("new_fdt", (ulong)gd->new_fdt);
+       print_num("fdt_size", (ulong)gd->fdt_size);
+
        return 0;
 }
 
diff --git a/common/splash_source.c b/common/splash_source.c
new file mode 100644 (file)
index 0000000..d1bb5a4
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
+ *
+ * Authors: Igor Grinberg <grinberg@compulab.co.il>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <nand.h>
+#include <errno.h>
+#include <splash.h>
+#include <spi_flash.h>
+#include <spi.h>
+#include <bmp_layout.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SPI_FLASH
+static struct spi_flash *sf;
+static int splash_sf_read(u32 bmp_load_addr, int offset, size_t read_size)
+{
+       if (!sf) {
+               sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+                                    CONFIG_SF_DEFAULT_CS,
+                                    CONFIG_SF_DEFAULT_SPEED,
+                                    CONFIG_SF_DEFAULT_MODE);
+               if (!sf)
+                       return -ENODEV;
+       }
+
+       return spi_flash_read(sf, offset, read_size, (void *)bmp_load_addr);
+}
+#else
+static int splash_sf_read(u32 bmp_load_addr, int offset, size_t read_size)
+{
+       debug("%s: sf support not available\n", __func__);
+       return -ENOSYS;
+}
+#endif
+
+#ifdef CONFIG_CMD_NAND
+static int splash_nand_read(u32 bmp_load_addr, int offset, size_t read_size)
+{
+       return nand_read_skip_bad(&nand_info[nand_curr_device], offset,
+                                 &read_size, NULL,
+                                 nand_info[nand_curr_device].size,
+                                 (u_char *)bmp_load_addr);
+}
+#else
+static int splash_nand_read(u32 bmp_load_addr, int offset, size_t read_size)
+{
+       debug("%s: nand support not available\n", __func__);
+       return -ENOSYS;
+}
+#endif
+
+static int splash_storage_read(struct splash_location *location,
+                              u32 bmp_load_addr, size_t read_size)
+{
+       u32 offset;
+
+       if (!location)
+               return -EINVAL;
+
+       offset = location->offset;
+       switch (location->storage) {
+       case SPLASH_STORAGE_NAND:
+               return splash_nand_read(bmp_load_addr, offset, read_size);
+       case SPLASH_STORAGE_SF:
+               return splash_sf_read(bmp_load_addr, offset, read_size);
+       default:
+               printf("Unknown splash location\n");
+       }
+
+       return -EINVAL;
+}
+
+static int splash_load_raw(struct splash_location *location, u32 bmp_load_addr)
+{
+       struct bmp_header *bmp_hdr;
+       int res;
+       size_t bmp_size, bmp_header_size = sizeof(struct bmp_header);
+
+       if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp)
+               goto splash_address_too_high;
+
+       res = splash_storage_read(location, bmp_load_addr, bmp_header_size);
+       if (res < 0)
+               return res;
+
+       bmp_hdr = (struct bmp_header *)bmp_load_addr;
+       bmp_size = le32_to_cpu(bmp_hdr->file_size);
+
+       if (bmp_load_addr + bmp_size >= gd->start_addr_sp)
+               goto splash_address_too_high;
+
+       return splash_storage_read(location, bmp_load_addr, bmp_size);
+
+splash_address_too_high:
+       printf("Error: splashimage address too high. Data overwrites U-Boot and/or placed beyond DRAM boundaries.\n");
+
+       return -EFAULT;
+}
+
+/**
+ * select_splash_location - return the splash location based on board support
+ *                         and env variable "splashsource".
+ *
+ * @locations:         An array of supported splash locations.
+ * @size:              Size of splash_locations array.
+ *
+ * @return: If a null set of splash locations is given, or
+ *         splashsource env variable is set to unsupported value
+ *                     return NULL.
+ *         If splashsource env variable is not defined
+ *                     return the first entry in splash_locations as default.
+ *         If splashsource env variable contains a supported value
+ *                     return the location selected by splashsource.
+ */
+static struct splash_location *select_splash_location(
+                           struct splash_location *locations, uint size)
+{
+       int i;
+       char *env_splashsource;
+
+       if (!locations || size == 0)
+               return NULL;
+
+       env_splashsource = getenv("splashsource");
+       if (env_splashsource == NULL)
+               return &locations[0];
+
+       for (i = 0; i < size; i++) {
+               if (!strcmp(locations[i].name, env_splashsource))
+                       return &locations[i];
+       }
+
+       printf("splashsource env variable set to unsupported value\n");
+       return NULL;
+}
+
+/**
+ * splash_source_load - load splash image from a supported location.
+ *
+ * Select a splash image location based on the value of splashsource environment
+ * variable and the board supported splash source locations, and load a
+ * splashimage to the address pointed to by splashimage environment variable.
+ *
+ * @locations:         An array of supported splash locations.
+ * @size:              Size of splash_locations array.
+ *
+ * @return: 0 on success, negative value on failure.
+ */
+int splash_source_load(struct splash_location *locations, uint size)
+{
+       struct splash_location *splash_location;
+       char *env_splashimage_value;
+       u32 bmp_load_addr;
+
+       env_splashimage_value = getenv("splashimage");
+       if (env_splashimage_value == NULL)
+               return -ENOENT;
+
+       bmp_load_addr = simple_strtoul(env_splashimage_value, 0, 16);
+       if (bmp_load_addr == 0) {
+               printf("Error: bad splashimage address specified\n");
+               return -EFAULT;
+       }
+
+       splash_location = select_splash_location(locations, size);
+       if (!splash_location)
+               return -EINVAL;
+
+       return splash_load_raw(splash_location, bmp_load_addr);
+}
index 0c3ab4e4fc74cff8025be89bd8c23179d7e1487d..979f26e6dccece5024974614451e477603dbcea7 100644 (file)
@@ -1,3 +1,5 @@
 CONFIG_ARC=y
-CONFIG_TARGET_ARCANGEL4_BE=y
+CONFIG_TARGET_ARCANGEL4=y
 CONFIG_SYS_CLK_FREQ=70000000
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_SYS_TEXT_BASE=0x81000000
index a63ef21de80ce9cbb26940ee8931db5f69e12ee3..797595f2c30ebc6c270b41a8d360684044dbe696 100644 (file)
@@ -1,3 +1,4 @@
 CONFIG_ARC=y
 CONFIG_TARGET_ARCANGEL4=y
 CONFIG_SYS_CLK_FREQ=70000000
+CONFIG_SYS_TEXT_BASE=0x81000000
index 5c0ca11fa55419314c40a5e749021c829938746c..34ed9633a1362f02e1adcfe7cba6e25b03c92a84 100644 (file)
@@ -1,3 +1,6 @@
 CONFIG_ARC=y
 CONFIG_TARGET_AXS101=y
-CONFIG_SYS_CLK_FREQ=750000000
\ No newline at end of file
+CONFIG_SYS_CLK_FREQ=750000000
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+CONFIG_SYS_DCACHE_OFF=y
+CONFIG_SYS_TEXT_BASE=0x81000000
\ No newline at end of file
index 7aa216c47d49186fa67d360e4a33db1c5b01b4fc..a7f13e2132be1751eeaad5366d891ea023f72b8b 100644 (file)
@@ -1,2 +1,3 @@
-CONFIG_ARM=y
-CONFIG_TARGET_DB_MV784MP_GP=y
+CONFIG_SPL=y
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_DB_MV784MP_GP=y
index 4bcffd8c2da773d50249b4974565379e421be2e9..219586a27da76614676163e96613a093e98f745c 100644 (file)
@@ -1,2 +1,3 @@
-CONFIG_ARM=y
-CONFIG_TARGET_MAXBCM=y
+CONFIG_SPL=y
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_MAXBCM=y
diff --git a/configs/mx6sxsabresd_spl_defconfig b/configs/mx6sxsabresd_spl_defconfig
new file mode 100644 (file)
index 0000000..6b36e06
--- /dev/null
@@ -0,0 +1,4 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6SX"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_MX6SXSABRESD=y
diff --git a/configs/ot1200_spl_defconfig b/configs/ot1200_spl_defconfig
new file mode 100644 (file)
index 0000000..ad57f88
--- /dev/null
@@ -0,0 +1,4 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6Q"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_OT1200=y
diff --git a/configs/platinum_picon_defconfig b/configs/platinum_picon_defconfig
new file mode 100644 (file)
index 0000000..c3ca040
--- /dev/null
@@ -0,0 +1,4 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6DL"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_PLATINUM_PICON=y
diff --git a/configs/platinum_titanium_defconfig b/configs/platinum_titanium_defconfig
new file mode 100644 (file)
index 0000000..db8cef9
--- /dev/null
@@ -0,0 +1,4 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,MX6Q"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_PLATINUM_TITANIUM=y
index d2de03b649b9925e31700aba878d2a4e3ab31bbd..b0e8c9f602d9f1e4435b2b29a8738b3b3230fa0f 100644 (file)
@@ -1,3 +1,5 @@
 CONFIG_ARC=y
 CONFIG_TARGET_TB100=y
-CONFIG_SYS_CLK_FREQ=500000000
\ No newline at end of file
+CONFIG_SYS_CLK_FREQ=500000000
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+CONFIG_SYS_TEXT_BASE=0x84000000
index 61b4ec53ecaddee676e0c6c2ec1dac65efe544d4..a0f0f3ca51f794630f3f398f40dae0c567c1ad1a 100644 (file)
@@ -6,3 +6,16 @@ common/splash.c. It is called as part of the splash screen display
 sequence. It gives the board an opportunity to prepare the splash
 image data before it is processed and sent to the frame buffer by
 U-Boot.  Define your own version to use this feature.
+
+CONFIG_SPLASH_SOURCE
+
+Use the splash_source.c library. This library provides facilities to declare
+board specific splash image locations, routines for loading splash image from
+supported locations, and a way of controlling the selected splash location
+using the "splashsource" environment variable.
+
+splashsource works as follows:
+- If splashsource is set to a supported location name as defined by board code,
+  use that splash location.
+- If splashsource is undefined, use the first splash location as default.
+- If splashsource is set to an unsupported value, do not load a splash screen.
diff --git a/doc/README.uniphier b/doc/README.uniphier
new file mode 100644 (file)
index 0000000..aaeb50c
--- /dev/null
@@ -0,0 +1,85 @@
+U-Boot for UniPhier SoC family
+==============================
+
+
+Tested toolchains
+-----------------
+
+ (a) Ubuntu packages  (CROSS_COMPILE=arm-linux-gnueabi-)
+
+  If you are building U-Boot on Ubuntu, its standard package is recommended.
+  You can install it as follows:
+
+    $ sudo apt-get install gcc-arm-linux-gnueabi-
+
+ (b) Linaro compilers  (CROSS_COMPILE=arm-linux-gnueabihf-)
+
+  You can download pre-built toolchains from:
+
+    http://www.linaro.org/downloads/
+
+ (c) kernel.org compilers  (CROSS_COMPILE=arm-unknown-linux-gnueabi-)
+
+  You can download pre-built toolchains from:
+
+    ftp://www.kernel.org/pub/tools/crosstool/files/bin/
+
+
+Compile the source
+------------------
+
+PH1-Pro4:
+    $ make ph1_pro4_defconfig
+    $ make CROSS_COMPILE=arm-linux-gnueabi-
+
+PH1-LD4:
+    $ make ph1_ld4_defconfig
+    $ make CROSS_COMPILE=arm-linux-gnueabi-
+
+PH1-sLD8:
+    $ make ph1_sld8_defconfig
+    $ make CROSS_COMPILE=arm-linux-gnueabi-
+
+You may wish to change the "CROSS_COMPILE=arm-linux-gnueabi-"
+to use your favorite compiler.
+
+
+Burn U-Boot images to NAND
+--------------------------
+
+Write two files to the NAND device as follows:
+ - spl/u-boot-spl.bin at the offset address 0x00000000
+ - u-boot-dtb.img     at the offset address 0x00010000
+
+If a TFTP server is available, the images can be easily updated.
+Just copy the u-boot-spl.bin and u-boot-dtb.img to the TFTP public directory,
+and then run the following command at the U-Boot command line:
+
+  => run nandupdate
+
+
+UniPhier specific commands
+--------------------------
+
+ - pinmon (enabled by CONFIG_CMD_PINMON)
+     shows the boot mode pins that has been latched at the power-on reset
+
+ - ddrphy (enabled by CONFIG_CMD_DDRPHY_DUMP)
+     shows the DDR PHY parameters set by the PHY training
+
+
+Supported devices
+-----------------
+
+ - UART (on-chip)
+ - NAND
+ - USB (2.0)
+ - LAN (on-board SMSC9118)
+ - I2C
+ - EEPROM (connected to the on-board I2C bus)
+ - Support card (SRAM, NOR flash, some peripherals)
+
+
+--
+Masahiro Yamada <yamada.m@jp.panasonic.com>
+Feb. 2015
diff --git a/drivers/ddr/mvebu/Makefile b/drivers/ddr/mvebu/Makefile
new file mode 100644 (file)
index 0000000..50a69ea
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-$(CONFIG_SPL_BUILD) += ddr3_dfs.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_dqs.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_hw_training.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_init.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_pbs.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_read_leveling.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_sdram.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_spd.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_write_leveling.o
+obj-$(CONFIG_SPL_BUILD) += xor.o
diff --git a/drivers/ddr/mvebu/ddr3_axp.h b/drivers/ddr/mvebu/ddr3_axp.h
new file mode 100644 (file)
index 0000000..bf65f6b
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __DDR3_AXP_H
+#define __DDR3_AXP_H
+
+#define MV_78XX0_Z1_REV                        0x0
+#define MV_78XX0_A0_REV                        0x1
+#define MV_78XX0_B0_REV                        0x2
+
+#define SAR_DDR3_FREQ_MASK             0xFE00000
+#define SAR_CPU_FAB_GET(cpu, fab)      (((cpu & 0x7) << 21) | ((fab & 0xF) << 24))
+
+#define MAX_CS                         4
+
+#define MIN_DIMM_ADDR                  0x50
+#define FAR_END_DIMM_ADDR              0x50
+#define MAX_DIMM_ADDR                  0x60
+
+#ifndef CONFIG_DDR_FIXED_SIZE
+#define SDRAM_CS_SIZE                  0xFFFFFFF
+#else
+#define SDRAM_CS_SIZE                  (CONFIG_DDR_FIXED_SIZE - 1)
+#endif
+#define SDRAM_CS_BASE                  0x0
+#define SDRAM_DIMM_SIZE                        0x80000000
+
+#define CPU_CONFIGURATION_REG(id)      (0x21800 + (id * 0x100))
+#define CPU_MRVL_ID_OFFSET             0x10
+#define SAR1_CPU_CORE_MASK             0x00000018
+#define SAR1_CPU_CORE_OFFSET           3
+
+#define ECC_SUPPORT
+#define NEW_FABRIC_TWSI_ADDR           0x4E
+#ifdef DB_784MP_GP
+#define BUS_WIDTH_ECC_TWSI_ADDR                0x4E
+#else
+#define BUS_WIDTH_ECC_TWSI_ADDR                0x4F
+#endif
+#define MV_MAX_DDR3_STATIC_SIZE                50
+#define MV_DDR3_MODES_NUMBER           30
+
+#define RESUME_RL_PATTERNS_ADDR                (0xFE0000)
+#define RESUME_RL_PATTERNS_SIZE                (0x100)
+#define RESUME_TRAINING_VALUES_ADDR    (RESUME_RL_PATTERNS_ADDR + RESUME_RL_PATTERNS_SIZE)
+#define RESUME_TRAINING_VALUES_MAX     (0xCD0)
+#define BOOT_INFO_ADDR                 (RESUME_RL_PATTERNS_ADDR + 0x1000)
+#define CHECKSUM_RESULT_ADDR           (BOOT_INFO_ADDR + 0x1000)
+#define NUM_OF_REGISTER_ADDR           (CHECKSUM_RESULT_ADDR + 4)
+#define SUSPEND_MAGIC_WORD             (0xDEADB002)
+#define REGISTER_LIST_END              (0xFFFFFFFF)
+
+/*
+ * Registers offset
+ */
+
+#define REG_SAMPLE_RESET_LOW_ADDR              0x18230
+#define REG_SAMPLE_RESET_HIGH_ADDR             0x18234
+#define        REG_SAMPLE_RESET_CPU_FREQ_OFFS          21
+#define        REG_SAMPLE_RESET_CPU_FREQ_MASK          0x00E00000
+#define        REG_SAMPLE_RESET_FAB_OFFS               24
+#define        REG_SAMPLE_RESET_FAB_MASK               0xF000000
+#define        REG_SAMPLE_RESET_TCLK_OFFS              28
+#define        REG_SAMPLE_RESET_CPU_ARCH_OFFS          31
+#define        REG_SAMPLE_RESET_HIGH_CPU_FREQ_OFFS     20
+
+/* MISC */
+/*
+ * In mainline U-Boot we're re-configuring the mvebu base address
+ * register to 0xf1000000. So need to use this value for the DDR
+ * training code as well.
+ */
+#define INTER_REGS_BASE                                SOC_REGS_PHY_BASE
+
+/* DDR */
+#define REG_SDRAM_CONFIG_ADDR                  0x1400
+#define REG_SDRAM_CONFIG_MASK                  0x9FFFFFFF
+#define REG_SDRAM_CONFIG_RFRS_MASK             0x3FFF
+#define REG_SDRAM_CONFIG_WIDTH_OFFS            15
+#define REG_SDRAM_CONFIG_REGDIMM_OFFS          17
+#define REG_SDRAM_CONFIG_ECC_OFFS              18
+#define REG_SDRAM_CONFIG_IERR_OFFS             19
+#define REG_SDRAM_CONFIG_PUPRSTDIV_OFFS                28
+#define REG_SDRAM_CONFIG_RSTRD_OFFS            30
+
+#define REG_DUNIT_CTRL_LOW_ADDR                        0x1404
+#define REG_DUNIT_CTRL_LOW_2T_OFFS             3
+#define REG_DUNIT_CTRL_LOW_2T_MASK             0x3
+#define REG_DUNIT_CTRL_LOW_DPDE_OFFS           14
+
+#define REG_SDRAM_TIMING_LOW_ADDR              0x1408
+
+#define REG_SDRAM_TIMING_HIGH_ADDR             0x140C
+#define REG_SDRAM_TIMING_H_R2R_OFFS            7
+#define REG_SDRAM_TIMING_H_R2R_MASK            0x3
+#define REG_SDRAM_TIMING_H_R2W_W2R_OFFS                9
+#define REG_SDRAM_TIMING_H_R2W_W2R_MASK                0x3
+#define REG_SDRAM_TIMING_H_W2W_OFFS            11
+#define REG_SDRAM_TIMING_H_W2W_MASK            0x1F
+#define REG_SDRAM_TIMING_H_R2R_H_OFFS          19
+#define REG_SDRAM_TIMING_H_R2R_H_MASK          0x7
+#define REG_SDRAM_TIMING_H_R2W_W2R_H_OFFS      22
+#define REG_SDRAM_TIMING_H_R2W_W2R_H_MASK      0x7
+
+#define REG_SDRAM_ADDRESS_CTRL_ADDR            0x1410
+#define REG_SDRAM_ADDRESS_SIZE_OFFS            2
+#define REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS       18
+#define REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS     4
+
+#define REG_SDRAM_OPEN_PAGES_ADDR              0x1414
+#define REG_SDRAM_OPERATION_CS_OFFS            8
+
+#define REG_SDRAM_OPERATION_ADDR               0x1418
+#define REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS 24
+#define REG_SDRAM_OPERATION_CWA_DATA_OFFS      20
+#define REG_SDRAM_OPERATION_CWA_DATA_MASK      0xF
+#define REG_SDRAM_OPERATION_CWA_RC_OFFS                16
+#define REG_SDRAM_OPERATION_CWA_RC_MASK                0xF
+#define REG_SDRAM_OPERATION_CMD_MR0            0xF03
+#define REG_SDRAM_OPERATION_CMD_MR1            0xF04
+#define REG_SDRAM_OPERATION_CMD_MR2            0xF08
+#define REG_SDRAM_OPERATION_CMD_MR3            0xF09
+#define REG_SDRAM_OPERATION_CMD_RFRS           0xF02
+#define REG_SDRAM_OPERATION_CMD_CWA            0xF0E
+#define REG_SDRAM_OPERATION_CMD_RFRS_DONE      0xF
+#define REG_SDRAM_OPERATION_CMD_MASK           0xF
+#define REG_SDRAM_OPERATION_CS_OFFS            8
+
+#define REG_OUDDR3_TIMING_ADDR                 0x142C
+
+#define REG_SDRAM_MODE_ADDR                    0x141C
+
+#define REG_SDRAM_EXT_MODE_ADDR                        0x1420
+
+#define REG_DDR_CONT_HIGH_ADDR                 0x1424
+
+#define REG_ODT_TIME_LOW_ADDR                  0x1428
+#define REG_ODT_ON_CTL_RD_OFFS                  12
+#define REG_ODT_OFF_CTL_RD_OFFS                 16
+#define REG_SDRAM_ERROR_ADDR                   0x1454
+#define REG_SDRAM_AUTO_PWR_SAVE_ADDR           0x1474
+#define REG_ODT_TIME_HIGH_ADDR                 0x147C
+
+#define REG_SDRAM_INIT_CTRL_ADDR               0x1480
+#define REG_SDRAM_INIT_CTRL_OFFS               0
+#define REG_SDRAM_INIT_CKE_ASSERT_OFFS         2
+#define REG_SDRAM_INIT_RESET_DEASSERT_OFFS     3
+
+#define REG_SDRAM_ODT_CTRL_LOW_ADDR            0x1494
+
+#define REG_SDRAM_ODT_CTRL_HIGH_ADDR           0x1498
+/*#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK    0xFFFFFF55 */
+#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK      0x0
+#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_ENA       0x3
+
+#define REG_DUNIT_ODT_CTRL_ADDR                        0x149C
+#define REG_DUNIT_ODT_CTRL_OVRD_OFFS            8
+#define REG_DUNIT_ODT_CTRL_OVRD_VAL_OFFS        9
+
+#define REG_DRAM_FIFO_CTRL_ADDR                        0x14A0
+
+#define REG_DRAM_AXI_CTRL_ADDR                 0x14A8
+#define REG_DRAM_AXI_CTRL_AXIDATABUSWIDTH_OFFS 0
+
+#define REG_METAL_MASK_ADDR                    0x14B0
+#define REG_METAL_MASK_MASK                    0xDFFFFFFF
+#define REG_METAL_MASK_RETRY_OFFS              0
+
+#define REG_DRAM_ADDR_CTRL_DRIVE_STRENGTH_ADDR 0x14C0
+
+#define REG_DRAM_DATA_DQS_DRIVE_STRENGTH_ADDR  0x14C4
+#define REG_DRAM_VER_CAL_MACHINE_CTRL_ADDR     0x14c8
+#define REG_DRAM_MAIN_PADS_CAL_ADDR            0x14CC
+
+#define REG_DRAM_HOR_CAL_MACHINE_CTRL_ADDR     0x17c8
+
+#define REG_CS_SIZE_SCRATCH_ADDR               0x1504
+#define REG_DYNAMIC_POWER_SAVE_ADDR            0x1520
+#define REG_DDR_IO_ADDR                                0x1524
+#define REG_DDR_IO_CLK_RATIO_OFFS              15
+
+#define REG_DFS_ADDR                           0x1528
+#define REG_DFS_DLLNEXTSTATE_OFFS              0
+#define REG_DFS_BLOCK_OFFS                     1
+#define REG_DFS_SR_OFFS                                2
+#define REG_DFS_ATSR_OFFS                      3
+#define REG_DFS_RECONF_OFFS                    4
+#define REG_DFS_CL_NEXT_STATE_OFFS             8
+#define REG_DFS_CL_NEXT_STATE_MASK             0xF
+#define REG_DFS_CWL_NEXT_STATE_OFFS            12
+#define REG_DFS_CWL_NEXT_STATE_MASK            0x7
+
+#define REG_READ_DATA_SAMPLE_DELAYS_ADDR       0x1538
+#define REG_READ_DATA_SAMPLE_DELAYS_MASK       0x1F
+#define REG_READ_DATA_SAMPLE_DELAYS_OFFS       8
+
+#define REG_READ_DATA_READY_DELAYS_ADDR                0x153C
+#define REG_READ_DATA_READY_DELAYS_MASK                0x1F
+#define REG_READ_DATA_READY_DELAYS_OFFS                8
+
+#define START_BURST_IN_ADDR                    1
+
+#define REG_DRAM_TRAINING_SHADOW_ADDR          0x18488
+#define REG_DRAM_TRAINING_ADDR                 0x15B0
+#define REG_DRAM_TRAINING_LOW_FREQ_OFFS                0
+#define REG_DRAM_TRAINING_PATTERNS_OFFS                4
+#define REG_DRAM_TRAINING_MED_FREQ_OFFS                2
+#define REG_DRAM_TRAINING_WL_OFFS              3
+#define REG_DRAM_TRAINING_RL_OFFS              6
+#define REG_DRAM_TRAINING_DQS_RX_OFFS          15
+#define REG_DRAM_TRAINING_DQS_TX_OFFS          16
+#define REG_DRAM_TRAINING_CS_OFFS              20
+#define REG_DRAM_TRAINING_RETEST_OFFS          24
+#define REG_DRAM_TRAINING_DFS_FREQ_OFFS                27
+#define REG_DRAM_TRAINING_DFS_REQ_OFFS         29
+#define REG_DRAM_TRAINING_ERROR_OFFS           30
+#define REG_DRAM_TRAINING_AUTO_OFFS            31
+#define REG_DRAM_TRAINING_RETEST_PAR           0x3
+#define REG_DRAM_TRAINING_RETEST_MASK          0xF8FFFFFF
+#define REG_DRAM_TRAINING_CS_MASK              0xFF0FFFFF
+#define REG_DRAM_TRAINING_PATTERNS_MASK                0xFF0F0000
+
+#define REG_DRAM_TRAINING_1_ADDR               0x15B4
+#define REG_DRAM_TRAINING_1_TRNBPOINT_OFFS     16
+
+#define REG_DRAM_TRAINING_2_ADDR               0x15B8
+#define REG_DRAM_TRAINING_2_OVERRUN_OFFS       17
+#define REG_DRAM_TRAINING_2_FIFO_RST_OFFS      4
+#define REG_DRAM_TRAINING_2_RL_MODE_OFFS       3
+#define REG_DRAM_TRAINING_2_WL_MODE_OFFS       2
+#define REG_DRAM_TRAINING_2_ECC_MUX_OFFS       1
+#define REG_DRAM_TRAINING_2_SW_OVRD_OFFS       0
+
+#define REG_DRAM_TRAINING_PATTERN_BASE_ADDR    0x15BC
+#define REG_DRAM_TRAINING_PATTERN_BASE_OFFS    3
+
+#define REG_TRAINING_DEBUG_2_ADDR              0x15C4
+#define REG_TRAINING_DEBUG_2_OFFS              16
+#define REG_TRAINING_DEBUG_2_MASK              0x3
+
+#define REG_TRAINING_DEBUG_3_ADDR              0x15C8
+#define REG_TRAINING_DEBUG_3_OFFS              3
+#define REG_TRAINING_DEBUG_3_MASK              0x7
+
+#define        MR_CS_ADDR_OFFS                         4
+
+#define        REG_DDR3_MR0_ADDR                       0x15D0
+#define        REG_DDR3_MR0_CS_ADDR                    0x1870
+#define REG_DDR3_MR0_CL_MASK                   0x74
+#define        REG_DDR3_MR0_CL_OFFS                    2
+#define        REG_DDR3_MR0_CL_HIGH_OFFS               3
+#define        CL_MASK                                 0xF
+
+#define        REG_DDR3_MR1_ADDR                       0x15D4
+#define        REG_DDR3_MR1_CS_ADDR                    0x1874
+#define REG_DDR3_MR1_RTT_MASK                  0xFFFFFDBB
+#define REG_DDR3_MR1_DLL_ENA_OFFS              0
+#define REG_DDR3_MR1_RTT_DISABLED              0x0
+#define REG_DDR3_MR1_RTT_RZQ2                  0x40
+#define REG_DDR3_MR1_RTT_RZQ4                  0x2
+#define REG_DDR3_MR1_RTT_RZQ6                  0x42
+#define REG_DDR3_MR1_RTT_RZQ8                  0x202
+#define REG_DDR3_MR1_RTT_RZQ12                 0x4
+#define REG_DDR3_MR1_OUTBUF_WL_MASK            0xFFFFEF7F      /* WL-disabled,OB-enabled */
+#define REG_DDR3_MR1_OUTBUF_DIS_OFFS           12      /* Output Buffer Disabled */
+#define REG_DDR3_MR1_WL_ENA_OFFS               7
+#define REG_DDR3_MR1_WL_ENA                    0x80    /* WL Enabled */
+#define REG_DDR3_MR1_ODT_MASK                  0xFFFFFDBB
+
+#define        REG_DDR3_MR2_ADDR                       0x15D8
+#define        REG_DDR3_MR2_CS_ADDR                    0x1878
+#define        REG_DDR3_MR2_CWL_OFFS                   3
+#define        REG_DDR3_MR2_CWL_MASK                   0x7
+#define REG_DDR3_MR2_ODT_MASK                  0xFFFFF9FF
+#define        REG_DDR3_MR3_ADDR                       0x15DC
+#define        REG_DDR3_MR3_CS_ADDR                    0x187C
+
+#define REG_DDR3_RANK_CTRL_ADDR                        0x15E0
+#define REG_DDR3_RANK_CTRL_CS_ENA_MASK         0xF
+#define REG_DDR3_RANK_CTRL_MIRROR_OFFS         4
+
+#define REG_ZQC_CONF_ADDR                      0x15E4
+
+#define REG_DRAM_PHY_CONFIG_ADDR               0x15EC
+#define REG_DRAM_PHY_CONFIG_MASK               0x3FFFFFFF
+
+#define REG_ODPG_CNTRL_ADDR                    0x1600
+#define REG_ODPG_CNTRL_OFFS                    21
+
+#define REG_PHY_LOCK_MASK_ADDR                 0x1670
+#define REG_PHY_LOCK_MASK_MASK                 0xFFFFF000
+
+#define REG_PHY_LOCK_STATUS_ADDR               0x1674
+#define REG_PHY_LOCK_STATUS_LOCK_OFFS          9
+#define REG_PHY_LOCK_STATUS_LOCK_MASK          0xFFF
+#define REG_PHY_LOCK_APLL_ADLL_STATUS_MASK     0x7FF
+
+#define REG_PHY_REGISTRY_FILE_ACCESS_ADDR      0x16A0
+#define REG_PHY_REGISTRY_FILE_ACCESS_OP_WR     0xC0000000
+#define REG_PHY_REGISTRY_FILE_ACCESS_OP_RD     0x80000000
+#define REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE   0x80000000
+#define REG_PHY_BC_OFFS                                27
+#define REG_PHY_CNTRL_OFFS                     26
+#define REG_PHY_CS_OFFS                                16
+#define REG_PHY_DQS_REF_DLY_OFFS               10
+#define REG_PHY_PHASE_OFFS                     8
+#define REG_PHY_PUP_OFFS                       22
+
+#define REG_TRAINING_WL_ADDR                   0x16AC
+#define REG_TRAINING_WL_CS_MASK                        0xFFFFFFFC
+#define REG_TRAINING_WL_UPD_OFFS               2
+#define REG_TRAINING_WL_CS_DONE_OFFS           3
+#define REG_TRAINING_WL_RATIO_MASK             0xFFFFFF0F
+#define REG_TRAINING_WL_1TO1                   0x50
+#define REG_TRAINING_WL_2TO1                   0x10
+#define REG_TRAINING_WL_DELAYEXP_MASK          0x20000000
+#define REG_TRAINING_WL_RESULTS_MASK           0x000001FF
+#define REG_TRAINING_WL_RESULTS_OFFS           20
+
+#define REG_REGISTERED_DRAM_CTRL_ADDR          0x16D0
+#define REG_REGISTERED_DRAM_CTRL_SR_FLOAT_OFFS 15
+#define REG_REGISTERED_DRAM_CTRL_PARITY_MASK   0x3F
+/* DLB*/
+#define REG_STATIC_DRAM_DLB_CONTROL            0x1700
+#define DLB_BUS_OPTIMIZATION_WEIGHTS_REG       0x1704
+#define DLB_AGING_REGISTER                     0x1708
+#define DLB_EVICTION_CONTROL_REG               0x170c
+#define DLB_EVICTION_TIMERS_REGISTER_REG       0x1710
+
+#define DLB_ENABLE                             0x1
+#define DLB_WRITE_COALESING                    (0x1 << 2)
+#define DLB_AXI_PREFETCH_EN                    (0x1 << 3)
+#define DLB_MBUS_PREFETCH_EN                   (0x1 << 4)
+#define PREFETCH_NLNSZTR                       (0x1 << 6)
+
+/* CPU    */
+#define REG_BOOTROM_ROUTINE_ADDR               0x182D0
+#define REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS     12
+
+#define REG_DRAM_INIT_CTRL_STATUS_ADDR         0x18488
+#define REG_DRAM_INIT_CTRL_TRN_CLK_OFFS                16
+#define REG_CPU_DIV_CLK_CTRL_0_NEW_RATIO       0x000200FF
+#define REG_DRAM_INIT_CTRL_STATUS_2_ADDR       0x1488
+
+#define REG_CPU_DIV_CLK_CTRL_0_ADDR            0x18700
+
+#define REG_CPU_DIV_CLK_CTRL_1_ADDR            0x18704
+#define REG_CPU_DIV_CLK_CTRL_2_ADDR            0x18708
+
+#define REG_CPU_DIV_CLK_CTRL_3_ADDR            0x1870C
+#define REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK       0xFFFFC0FF
+#define REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS       8
+
+#define REG_CPU_DIV_CLK_CTRL_4_ADDR            0x18710
+
+#define REG_CPU_DIV_CLK_STATUS_0_ADDR          0x18718
+#define REG_CPU_DIV_CLK_ALL_STABLE_OFFS                8
+
+#define REG_CPU_PLL_CTRL_0_ADDR                        0x1871C
+#define REG_CPU_PLL_STATUS_0_ADDR              0x18724
+#define REG_CORE_DIV_CLK_CTRL_ADDR             0x18740
+#define REG_CORE_DIV_CLK_STATUS_ADDR           0x18744
+#define REG_DDRPHY_APLL_CTRL_ADDR              0x18780
+
+#define REG_DDRPHY_APLL_CTRL_2_ADDR            0x18784
+
+#define REG_SFABRIC_CLK_CTRL_ADDR              0x20858
+#define REG_SFABRIC_CLK_CTRL_SMPL_OFFS         8
+
+/* DRAM Windows */
+#define REG_XBAR_WIN_19_CTRL_ADDR              0x200e8
+#define REG_XBAR_WIN_4_CTRL_ADDR               0x20040
+#define REG_XBAR_WIN_4_BASE_ADDR               0x20044
+#define REG_XBAR_WIN_4_REMAP_ADDR              0x20048
+#define REG_FASTPATH_WIN_0_CTRL_ADDR           0x20184
+#define REG_XBAR_WIN_7_REMAP_ADDR              0x20078
+
+/* SRAM */
+#define REG_CDI_CONFIG_ADDR                    0x20220
+#define REG_SRAM_WINDOW_0_ADDR                 0x20240
+#define REG_SRAM_WINDOW_0_ENA_OFFS             0
+#define REG_SRAM_WINDOW_1_ADDR                 0x20244
+#define REG_SRAM_L2_ENA_ADDR                   0x8500
+#define REG_SRAM_CLEAN_BY_WAY_ADDR             0x87BC
+
+/* PMU */
+#define REG_PMU_I_F_CTRL_ADDR                  0x1C090
+#define REG_PMU_DUNIT_BLK_OFFS                 16
+#define REG_PMU_DUNIT_RFRS_OFFS                        20
+#define REG_PMU_DUNIT_ACK_OFFS                 24
+
+/* MBUS*/
+#define MBUS_UNITS_PRIORITY_CONTROL_REG                (MV_MBUS_REGS_OFFSET + 0x420)
+#define FABRIC_UNITS_PRIORITY_CONTROL_REG      (MV_MBUS_REGS_OFFSET + 0x424)
+#define MBUS_UNITS_PREFETCH_CONTROL_REG                (MV_MBUS_REGS_OFFSET + 0x428)
+#define FABRIC_UNITS_PREFETCH_CONTROL_REG      (MV_MBUS_REGS_OFFSET + 0x42c)
+
+#define REG_PM_STAT_MASK_ADDR                  0x2210C
+#define REG_PM_STAT_MASK_CPU0_IDLE_MASK_OFFS   16
+
+#define REG_PM_EVENT_STAT_MASK_ADDR            0x22120
+#define REG_PM_EVENT_STAT_MASK_DFS_DONE_OFFS   17
+
+#define REG_PM_CTRL_CONFIG_ADDR                        0x22104
+#define REG_PM_CTRL_CONFIG_DFS_REQ_OFFS                18
+
+#define REG_FABRIC_LOCAL_IRQ_MASK_ADDR         0x218C4
+#define REG_FABRIC_LOCAL_IRQ_PMU_MASK_OFFS     18
+
+/* Controller revision info */
+#define PCI_CLASS_CODE_AND_REVISION_ID         0x008
+#define PCCRIR_REVID_OFFS                      0       /* Revision ID */
+#define PCCRIR_REVID_MASK                      (0xff << PCCRIR_REVID_OFFS)
+
+/*  Power Management Clock Gating Control Register     */
+#define MV_PEX_IF_REGS_OFFSET(if) \
+       (if < 8 ? (0x40000 + ((if) / 4) * 0x40000 + ((if) % 4) * 0x4000) \
+        : (0x42000 + ((if) % 8) * 0x40000))
+#define MV_PEX_IF_REGS_BASE(unit)              (MV_PEX_IF_REGS_OFFSET(unit))
+#define POWER_MNG_CTRL_REG                     0x18220
+#define PEX_DEVICE_AND_VENDOR_ID               0x000
+#define PEX_CFG_DIRECT_ACCESS(if, reg)         (MV_PEX_IF_REGS_BASE(if) + (reg))
+#define PMC_PEXSTOPCLOCK_OFFS(port)            ((port) < 8 ? (5 + (port)) : (18 + (port)))
+#define PMC_PEXSTOPCLOCK_MASK(port)            (1 << PMC_PEXSTOPCLOCK_OFFS(port))
+#define PMC_PEXSTOPCLOCK_EN(port)              (1 << PMC_PEXSTOPCLOCK_OFFS(port))
+#define PMC_PEXSTOPCLOCK_STOP(port)            (0 << PMC_PEXSTOPCLOCK_OFFS(port))
+
+/* TWSI */
+#define TWSI_DATA_ADDR_MASK                    0x7
+#define TWSI_DATA_ADDR_OFFS                    1
+
+/* General */
+#define MAX_CS                                 4
+
+/* Frequencies */
+#define FAB_OPT                                        21
+#define CLK_CPU                                        12
+#define CLK_VCO                                        (2 * CLK_CPU)
+#define CLK_DDR                                        12
+
+/* Cpu Frequencies: */
+#define CLK_CPU_1000                           0
+#define CLK_CPU_1066                           1
+#define CLK_CPU_1200                           2
+#define CLK_CPU_1333                           3
+#define CLK_CPU_1500                           4
+#define CLK_CPU_1666                           5
+#define CLK_CPU_1800                           6
+#define CLK_CPU_2000                           7
+#define CLK_CPU_600                            8
+#define CLK_CPU_667                            9
+#define CLK_CPU_800                            0xa
+
+/* Extra Cpu Frequencies: */
+#define CLK_CPU_1600                           11
+#define CLK_CPU_2133                           12
+#define CLK_CPU_2200                           13
+#define CLK_CPU_2400                           14
+
+/* DDR3 Frequencies: */
+#define DDR_100                                        0
+#define DDR_300                                        1
+#define DDR_333                                        1
+#define DDR_360                                        2
+#define DDR_400                                        3
+#define DDR_444                                        4
+#define DDR_500                                        5
+#define DDR_533                                        6
+#define DDR_600                                        7
+#define DDR_640                                        8
+#define DDR_666                                        8
+#define DDR_720                                        9
+#define DDR_750                                        9
+#define DDR_800                                        10
+#define DDR_833                                        11
+#define DDR_HCLK                               20
+#define DDR_S                                  12
+#define DDR_S_1TO1                             13
+#define MARGIN_FREQ                            DDR_400
+#define DFS_MARGIN                             DDR_100
+
+#define ODT_OPT                                        16
+#define ODT20                                  0x200
+#define ODT30                                  0x204
+#define ODT40                                  0x44
+#define ODT120                                 0x40
+#define ODT120D                                        0x400
+
+#define MRS_DELAY                              100
+
+#define SDRAM_WL_SW_OFFS                       0x100
+#define SDRAM_RL_OFFS                          0x0
+#define SDRAM_PBS_I_OFFS                       0x140
+#define SDRAM_PBS_II_OFFS                      0x180
+#define SDRAM_PBS_NEXT_OFFS                    (SDRAM_PBS_II_OFFS - SDRAM_PBS_I_OFFS)
+#define SDRAM_PBS_TX_OFFS                      0x180
+#define SDRAM_PBS_TX_DM_OFFS                   576
+#define SDRAM_DQS_RX_OFFS                      1024
+#define SDRAM_DQS_TX_OFFS                      2048
+#define SDRAM_DQS_RX_SPECIAL_OFFS              5120
+
+#define LEN_STD_PATTERN                                16
+#define LEN_KILLER_PATTERN                     128
+#define LEN_SPECIAL_PATTERN                    128
+#define LEN_PBS_PATTERN                                16
+
+#endif /* __DDR3_AXP_H */
diff --git a/drivers/ddr/mvebu/ddr3_axp_config.h b/drivers/ddr/mvebu/ddr3_axp_config.h
new file mode 100644 (file)
index 0000000..800d2d1
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __DDR3_AXP_CONFIG_H
+#define __DDR3_AXP_CONFIG_H
+
+/*
+ * DDR3_LOG_LEVEL Information
+ *
+ * Level 0: Provides an error code in a case of failure, RL, WL errors
+ *          and other algorithm failure
+ * Level 1: Provides the D-Unit setup (SPD/Static configuration)
+ * Level 2: Provides the windows margin as a results of DQS centeralization
+ * Level 3: Provides the windows margin of each DQ as a results of DQS
+ *          centeralization
+ */
+#ifdef CONFIG_DDR_LOG_LEVEL
+#define        DDR3_LOG_LEVEL  CONFIG_DDR_LOG_LEVEL
+#else
+#define        DDR3_LOG_LEVEL  0
+#endif
+
+#define DDR3_PBS        1
+
+/* This flag allows the execution of SW WL/RL upon HW failure */
+#define DDR3_RUN_SW_WHEN_HW_FAIL    1
+
+/*
+ * General Configurations
+ *
+ * The following parameters are required for proper setup:
+ *
+ * DDR_TARGET_FABRIC   - Set desired fabric configuration
+ *                       (for sample@Reset fabfreq parameter)
+ * DRAM_ECC            - Set ECC support 1/0
+ * BUS_WIDTH           - 64/32 bit
+ * CONFIG_SPD_EEPROM   - Enables auto detection of DIMMs and their timing values
+ * DQS_CLK_ALIGNED     - Set this if CLK and DQS signals are aligned on board
+ * MIXED_DIMM_STATIC   - Mixed DIMM + On board devices support (ODT registers
+ *                       values are taken statically)
+ * DDR3_TRAINING_DEBUG - Debug prints of internal code
+ */
+#define DDR_TARGET_FABRIC                      5
+#define DRAM_ECC                               0
+
+#ifdef MV_DDR_32BIT
+#define BUS_WIDTH                               32
+#else
+#define BUS_WIDTH                              64
+#endif
+
+#undef DQS_CLK_ALIGNED
+#undef MIXED_DIMM_STATIC
+#define DDR3_TRAINING_DEBUG                    0
+#define REG_DIMM_SKIP_WL                       0
+
+/* Marvell boards specific configurations */
+#if defined(DB_78X60_PCAC)
+#undef CONFIG_SPD_EEPROM
+#define STATIC_TRAINING
+#endif
+
+#if defined(DB_78X60_AMC)
+#undef CONFIG_SPD_EEPROM
+#undef  DRAM_ECC
+#define DRAM_ECC                               1
+#endif
+
+#ifdef CONFIG_SPD_EEPROM
+/*
+ * DIMM support parameters:
+ * DRAM_2T - Set Desired 2T Mode - 0 - 1T, 0x1 - 2T, 0x2 - 3T
+ * DIMM_CS_BITMAP - bitmap representing the optional CS in DIMMs
+ * (0xF=CS0+CS1+CS2+CS3, 0xC=CS2+CS3...)
+ */
+#define DRAM_2T                                        0x0
+#define DIMM_CS_BITMAP                         0xF
+#define DUNIT_SPD
+#endif
+
+#ifdef DRAM_ECC
+/*
+ * ECC support parameters:
+ *
+ * U_BOOT_START_ADDR, U_BOOT_SCRUB_SIZE - relevant when using ECC and need
+ * to configure the scrubbing area
+ */
+#define TRAINING_SIZE                          0x20000
+#define U_BOOT_START_ADDR                      0
+#define U_BOOT_SCRUB_SIZE                      0x1000000 /* TRAINING_SIZE */
+#endif
+
+/*
+ * Registered DIMM Support - In case registered DIMM is attached,
+ * please supply the following values:
+ * (see JEDEC - JESD82-29A "Definition of the SSTE32882 Registering Clock
+ * Driver with Parity and Quad Chip
+ * Selects for DDR3/DDR3L/DDR3U RDIMM 1.5 V/1.35 V/1.25 V Applications")
+ * RC0: Global Features Control Word
+ * RC1: Clock Driver Enable Control Word
+ * RC2: Timing Control Word
+ * RC3-RC5 - taken from SPD
+ * RC8: Additional IBT Setting Control Word
+ * RC9: Power Saving Settings Control Word
+ * RC10: Encoding for RDIMM Operating Speed
+ * RC11: Operating Voltage VDD and VREFCA Control Word
+ */
+#define RDIMM_RC0                              0
+#define RDIMM_RC1                              0
+#define RDIMM_RC2                              0
+#define RDIMM_RC8                              0
+#define RDIMM_RC9                              0
+#define RDIMM_RC10                             0x2
+#define RDIMM_RC11                             0x0
+
+#if defined(MIXED_DIMM_STATIC) || !defined(CONFIG_SPD_EEPROM)
+#define DUNIT_STATIC
+#endif
+
+#if defined(MIXED_DIMM_STATIC) || defined(CONFIG_SPD_EEPROM)
+/*
+ * This flag allows the user to change the dram refresh cycle in ps,
+ * only in case of SPD or MIX DIMM topology
+ */
+#define TREFI_USER_EN
+
+#ifdef TREFI_USER_EN
+#define TREFI_USER                             3900000
+#endif
+#endif
+
+#ifdef CONFIG_SPD_EEPROM
+/*
+ * AUTO_DETECTION_SUPPORT - relevant ONLY for Marvell DB boards.
+ * Enables I2C auto detection different options
+ */
+#if defined(CONFIG_DB_88F78X60) || defined(CONFIG_DB_88F78X60_REV2) || \
+    defined(CONFIG_DB_784MP_GP)
+#define AUTO_DETECTION_SUPPORT
+#endif
+#endif
+
+#endif /* __DDR3_AXP_CONFIG_H */
diff --git a/drivers/ddr/mvebu/ddr3_axp_mc_static.h b/drivers/ddr/mvebu/ddr3_axp_mc_static.h
new file mode 100644 (file)
index 0000000..2c0e907
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __AXP_MC_STATIC_H
+#define __AXP_MC_STATIC_H
+
+MV_DRAM_MC_INIT ddr3_A0_db_667[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+       {0x00001400, 0x7301c924},       /*DDR SDRAM Configuration Register */
+#else /*MV_DDR_64BIT */
+       {0x00001400, 0x7301CA28},       /*DDR SDRAM Configuration Register */
+#endif
+       {0x00001404, 0x3630b800},       /*Dunit Control Low Register */
+       {0x00001408, 0x43149775},       /*DDR SDRAM Timing (Low) Register */
+       /* {0x0000140C, 0x38000C6A}, *//*DDR SDRAM Timing (High) Register */
+       {0x0000140C, 0x38d83fe0},       /*DDR SDRAM Timing (High) Register */
+
+#ifdef DB_78X60_PCAC
+       {0x00001410, 0x040F0001},       /*DDR SDRAM Address Control Register */
+#else
+       {0x00001410, 0x040F0000},       /*DDR SDRAM Open Pages Control Register */
+#endif
+
+       {0x00001414, 0x00000000},       /*DDR SDRAM Open Pages Control Register */
+       {0x00001418, 0x00000e00},       /*DDR SDRAM Operation Register */
+       {0x00001420, 0x00000004},       /*DDR SDRAM Extended Mode Register */
+       {0x00001424, 0x0000D3FF},       /*Dunit Control High Register */
+       {0x00001428, 0x000F8830},       /*Dunit Control High Register */
+       {0x0000142C, 0x214C2F38},       /*Dunit Control High Register */
+       {0x0000147C, 0x0000c671},
+
+       {0x000014a0, 0x000002A9},
+       {0x000014a8, 0x00000101},       /*2:1 */
+       {0x00020220, 0x00000007},
+
+       {0x00001494, 0x00010000},       /*DDR SDRAM ODT Control (Low) Register */
+       {0x00001498, 0x00000000},       /*DDR SDRAM ODT Control (High) Register */
+       {0x0000149C, 0x00000301},       /*DDR Dunit ODT Control Register */
+
+       {0x000014C0, 0x192434e9},       /* DRAM address and Control Driving Strenght  */
+       {0x000014C4, 0x092434e9},       /* DRAM Data and DQS Driving Strenght  */
+
+       {0x000200e8, 0x3FFF0E01},       /* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+       {0x00020184, 0x3FFFFFE0},       /* DO NOT Modify - Close fast path Window to - 2G */
+
+       {0x0001504, 0x7FFFFFF1},        /* CS0 Size */
+       {0x000150C, 0x00000000},        /* CS1 Size */
+       {0x0001514, 0x00000000},        /* CS2 Size */
+       {0x000151C, 0x00000000},        /* CS3 Size */
+
+       /*     {0x00001524, 0x0000C800},  */
+       {0x00001538, 0x0000000b},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000d},       /*Read Data Ready Delay Register */
+
+       {0x000015D0, 0x00000640},       /*MR0 */
+       {0x000015D4, 0x00000046},       /*MR1 */
+       {0x000015D8, 0x00000010},       /*MR2 */
+       {0x000015DC, 0x00000000},       /*MR3 */
+
+       {0x000015E4, 0x00203c18},       /*ZQC Configuration Register */
+       {0x000015EC, 0xd800aa25},       /*DDR PHY */
+       {0x0, 0x0}
+};
+
+MV_DRAM_MC_INIT ddr3_A0_AMC_667[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+       {0x00001400, 0x7301c924},       /*DDR SDRAM Configuration Register */
+#else /*MV_DDR_64BIT */
+       {0x00001400, 0x7301CA28},       /*DDR SDRAM Configuration Register */
+#endif
+       {0x00001404, 0x3630b800},       /*Dunit Control Low Register */
+       {0x00001408, 0x43149775},       /*DDR SDRAM Timing (Low) Register */
+       /* {0x0000140C, 0x38000C6A}, *//*DDR SDRAM Timing (High) Register */
+       {0x0000140C, 0x38d83fe0},       /*DDR SDRAM Timing (High) Register */
+
+#ifdef DB_78X60_PCAC
+       {0x00001410, 0x040F0001},       /*DDR SDRAM Address Control Register */
+#else
+       {0x00001410, 0x040F000C},       /*DDR SDRAM Open Pages Control Register */
+#endif
+
+       {0x00001414, 0x00000000},       /*DDR SDRAM Open Pages Control Register */
+       {0x00001418, 0x00000e00},       /*DDR SDRAM Operation Register */
+       {0x00001420, 0x00000004},       /*DDR SDRAM Extended Mode Register */
+       {0x00001424, 0x0000D3FF},       /*Dunit Control High Register */
+       {0x00001428, 0x000F8830},       /*Dunit Control High Register */
+       {0x0000142C, 0x214C2F38},       /*Dunit Control High Register */
+       {0x0000147C, 0x0000c671},
+
+       {0x000014a0, 0x000002A9},
+       {0x000014a8, 0x00000101},       /*2:1 */
+       {0x00020220, 0x00000007},
+
+       {0x00001494, 0x00010000},       /*DDR SDRAM ODT Control (Low) Register */
+       {0x00001498, 0x00000000},       /*DDR SDRAM ODT Control (High) Register */
+       {0x0000149C, 0x00000301},       /*DDR Dunit ODT Control Register */
+
+       {0x000014C0, 0x192434e9},       /* DRAM address and Control Driving Strenght  */
+       {0x000014C4, 0x092434e9},       /* DRAM Data and DQS Driving Strenght  */
+
+       {0x000200e8, 0x3FFF0E01},       /* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+       {0x00020184, 0x3FFFFFE0},       /* DO NOT Modify - Close fast path Window to - 2G */
+
+       {0x0001504, 0x3FFFFFF1},        /* CS0 Size */
+       {0x000150C, 0x00000000},        /* CS1 Size */
+       {0x0001514, 0x00000000},        /* CS2 Size */
+       {0x000151C, 0x00000000},        /* CS3 Size */
+
+       /*     {0x00001524, 0x0000C800},  */
+       {0x00001538, 0x0000000b},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000d},       /*Read Data Ready Delay Register */
+
+       {0x000015D0, 0x00000640},       /*MR0 */
+       {0x000015D4, 0x00000046},       /*MR1 */
+       {0x000015D8, 0x00000010},       /*MR2 */
+       {0x000015DC, 0x00000000},       /*MR3 */
+
+       {0x000015E4, 0x00203c18},       /*ZQC Configuration Register */
+       {0x000015EC, 0xd800aa25},       /*DDR PHY */
+       {0x0, 0x0}
+};
+
+MV_DRAM_MC_INIT ddr3_A0_db_400[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+       {0x00001400, 0x73004C30},       /*DDR SDRAM Configuration Register */
+#else /* MV_DDR_64BIT */
+       {0x00001400, 0x7300CC30},       /*DDR SDRAM Configuration Register */
+#endif
+       {0x00001404, 0x3630B840},       /*Dunit Control Low Register */
+       {0x00001408, 0x33137663},       /*DDR SDRAM Timing (Low) Register */
+       {0x0000140C, 0x38000C55},       /*DDR SDRAM Timing (High) Register */
+       {0x00001410, 0x040F0000},       /*DDR SDRAM Address Control Register */
+       {0x00001414, 0x00000000},       /*DDR SDRAM Open Pages Control Register */
+       {0x00001418, 0x00000e00},       /*DDR SDRAM Operation Register */
+       {0x0000141C, 0x00000672},       /*DDR SDRAM Mode Register */
+       {0x00001420, 0x00000004},       /*DDR SDRAM Extended Mode Register */
+       {0x00001424, 0x0100D3FF},       /*Dunit Control High Register */
+       {0x00001428, 0x000D6720},       /*Dunit Control High Register */
+       {0x0000142C, 0x014C2F38},       /*Dunit Control High Register */
+       {0x0000147C, 0x00006571},
+
+       {0x00001494, 0x00010000},       /*DDR SDRAM ODT Control (Low) Register */
+       {0x00001498, 0x00000000},       /*DDR SDRAM ODT Control (High) Register */
+       {0x0000149C, 0x00000301},       /*DDR Dunit ODT Control Register */
+
+       {0x000014a0, 0x000002A9},
+       {0x000014a8, 0x00000101},       /*2:1 */
+       {0x00020220, 0x00000007},
+
+       {0x000014C0, 0x192424C8},       /* DRAM address and Control Driving Strenght  */
+       {0x000014C4, 0xEFB24C8},        /* DRAM Data and DQS Driving Strenght  */
+
+       {0x000200e8, 0x3FFF0E01},       /* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+       {0x00020184, 0x3FFFFFE0},       /* DO NOT Modify - Close fast path Window to - 2G */
+
+       {0x0001504, 0x7FFFFFF1},        /* CS0 Size */
+       {0x000150C, 0x00000000},        /* CS1 Size */
+       {0x0001514, 0x00000000},        /* CS2 Size */
+       {0x000151C, 0x00000000},        /* CS3 Size */
+
+       {0x00001538, 0x00000008},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000A},       /*Read Data Ready Delay Register */
+
+       {0x000015D0, 0x00000630},       /*MR0 */
+       {0x000015D4, 0x00000046},       /*MR1 */
+       {0x000015D8, 0x00000008},       /*MR2 */
+       {0x000015DC, 0x00000000},       /*MR3 */
+
+       {0x000015E4, 0x00203c18},       /*ZQDS Configuration Register */
+       /* {0x000015EC, 0xDE000025}, *//*DDR PHY */
+       {0x000015EC, 0xF800AA25},       /*DDR PHY */
+       {0x0, 0x0}
+};
+
+MV_DRAM_MC_INIT ddr3_Z1_db_600[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+       {0x00001400, 0x73014A28},       /*DDR SDRAM Configuration Register */
+#else /*MV_DDR_64BIT */
+       {0x00001400, 0x7301CA28},       /*DDR SDRAM Configuration Register */
+#endif
+       {0x00001404, 0x3630B040},       /*Dunit Control Low Register */
+       {0x00001408, 0x44149887},       /*DDR SDRAM Timing (Low) Register */
+       /* {0x0000140C, 0x38000C6A}, *//*DDR SDRAM Timing (High) Register */
+       {0x0000140C, 0x38D83FE0},       /*DDR SDRAM Timing (High) Register */
+
+#ifdef DB_78X60_PCAC
+       {0x00001410, 0x040F0001},       /*DDR SDRAM Address Control Register */
+#else
+       {0x00001410, 0x040F0000},       /*DDR SDRAM Open Pages Control Register */
+#endif
+
+       {0x00001414, 0x00000000},       /*DDR SDRAM Open Pages Control Register */
+       {0x00001418, 0x00000e00},       /*DDR SDRAM Operation Register */
+       {0x00001420, 0x00000004},       /*DDR SDRAM Extended Mode Register */
+       {0x00001424, 0x0100D1FF},       /*Dunit Control High Register */
+       {0x00001428, 0x000F8830},       /*Dunit Control High Register */
+       {0x0000142C, 0x214C2F38},       /*Dunit Control High Register */
+       {0x0000147C, 0x0000c671},
+
+       {0x000014a8, 0x00000101},       /*2:1 */
+       {0x00020220, 0x00000007},
+
+       {0x00001494, 0x00010000},       /*DDR SDRAM ODT Control (Low) Register */
+       {0x00001498, 0x00000000},       /*DDR SDRAM ODT Control (High) Register */
+       {0x0000149C, 0x00000301},       /*DDR Dunit ODT Control Register */
+
+       {0x000014C0, 0x192424C8},       /* DRAM address and Control Driving Strenght  */
+       {0x000014C4, 0xEFB24C8},        /* DRAM Data and DQS Driving Strenght  */
+
+       {0x000200e8, 0x3FFF0E01},       /* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+       {0x00020184, 0x3FFFFFE0},       /* DO NOT Modify - Close fast path Window to - 2G */
+
+       {0x0001504, 0x7FFFFFF1},        /* CS0 Size */
+       {0x000150C, 0x00000000},        /* CS1 Size */
+       {0x0001514, 0x00000000},        /* CS2 Size */
+       {0x000151C, 0x00000000},        /* CS3 Size */
+
+       /*     {0x00001524, 0x0000C800},  */
+       {0x00001538, 0x0000000b},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000d},       /*Read Data Ready Delay Register */
+
+       {0x000015D0, 0x00000650},       /*MR0 */
+       {0x000015D4, 0x00000046},       /*MR1 */
+       {0x000015D8, 0x00000010},       /*MR2 */
+       {0x000015DC, 0x00000000},       /*MR3 */
+
+       {0x000015E4, 0x00203c18},       /*ZQC Configuration Register */
+       {0x000015EC, 0xDE000025},       /*DDR PHY */
+       {0x0, 0x0}
+};
+
+MV_DRAM_MC_INIT ddr3_Z1_db_300[MV_MAX_DDR3_STATIC_SIZE] = {
+#ifdef MV_DDR_32BIT
+       {0x00001400, 0x73004C30},       /*DDR SDRAM Configuration Register */
+#else /*MV_DDR_64BIT */
+       {0x00001400, 0x7300CC30},       /*DDR SDRAM Configuration Register */
+       /*{0x00001400, 0x7304CC30},  *//*DDR SDRAM Configuration Register */
+#endif
+       {0x00001404, 0x3630B840},       /*Dunit Control Low Register */
+       {0x00001408, 0x33137663},       /*DDR SDRAM Timing (Low) Register */
+       {0x0000140C, 0x38000C55},       /*DDR SDRAM Timing (High) Register */
+       {0x00001410, 0x040F0000},       /*DDR SDRAM Address Control Register */
+       {0x00001414, 0x00000000},       /*DDR SDRAM Open Pages Control Register */
+       {0x00001418, 0x00000e00},       /*DDR SDRAM Operation Register */
+       {0x0000141C, 0x00000672},       /*DDR SDRAM Mode Register */
+       {0x00001420, 0x00000004},       /*DDR SDRAM Extended Mode Register */
+       {0x00001424, 0x0100F1FF},       /*Dunit Control High Register */
+       {0x00001428, 0x000D6720},       /*Dunit Control High Register */
+       {0x0000142C, 0x014C2F38},       /*Dunit Control High Register */
+       {0x0000147C, 0x00006571},
+
+       {0x00001494, 0x00010000},       /*DDR SDRAM ODT Control (Low) Register */
+       {0x00001498, 0x00000000},       /*DDR SDRAM ODT Control (High) Register */
+       {0x0000149C, 0x00000301},       /*DDR Dunit ODT Control Register */
+
+       {0x000014C0, 0x192424C8},       /* DRAM address and Control Driving Strenght  */
+       {0x000014C4, 0xEFB24C8},        /* DRAM Data and DQS Driving Strenght  */
+
+       {0x000200e8, 0x3FFF0E01},       /* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence */
+       {0x00020184, 0x3FFFFFE0},       /* DO NOT Modify - Close fast path Window to - 2G */
+
+       {0x0001504, 0x7FFFFFF1},        /* CS0 Size */
+       {0x000150C, 0x00000000},        /* CS1 Size */
+       {0x0001514, 0x00000000},        /* CS2 Size */
+       {0x000151C, 0x00000000},        /* CS3 Size */
+
+       {0x00001538, 0x00000008},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000A},       /*Read Data Ready Delay Register */
+
+       {0x000015D0, 0x00000630},       /*MR0 */
+       {0x000015D4, 0x00000046},       /*MR1 */
+       {0x000015D8, 0x00000008},       /*MR2 */
+       {0x000015DC, 0x00000000},       /*MR3 */
+
+       {0x000015E4, 0x00203c18},       /*ZQDS Configuration Register */
+       {0x000015EC, 0xDE000025},       /*DDR PHY */
+
+       {0x0, 0x0}
+};
+
+#endif /* __AXP_MC_STATIC_H */
diff --git a/drivers/ddr/mvebu/ddr3_axp_training_static.h b/drivers/ddr/mvebu/ddr3_axp_training_static.h
new file mode 100644 (file)
index 0000000..4e61547
--- /dev/null
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __AXP_TRAINING_STATIC_H
+#define __AXP_TRAINING_STATIC_H
+
+/*
+ * STATIC_TRAINING - Set only if static parameters for training are set and
+ * required
+ */
+
+MV_DRAM_TRAINING_INIT ddr3_db_rev2_667[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0     */
+       {0x000016A0, 0xC002011A},
+       /*1 */
+       {0x000016A0, 0xC0420100},
+       /*2 */
+       {0x000016A0, 0xC082020A},
+       /*3 */
+       {0x000016A0, 0xC0C20017},
+       /*4 */
+       {0x000016A0, 0xC1020113},
+       /*5 */
+       {0x000016A0, 0xC1420107},
+       /*6 */
+       {0x000016A0, 0xC182011F},
+       /*7 */
+       {0x000016A0, 0xC1C2001C},
+       /*8 */
+       {0x000016A0, 0xC202010D},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC0004A06},
+       /*1 */
+       {0x000016A0, 0xC040690D},
+       /*2 */
+       {0x000016A0, 0xC0806A0D},
+       /*3 */
+       {0x000016A0, 0xC0C0A01B},
+       /*4 */
+       {0x000016A0, 0xC1003A01},
+       /*5 */
+       {0x000016A0, 0xC1408113},
+       /*6 */
+       {0x000016A0, 0xC1805609},
+       /*7 */
+       {0x000016A0, 0xC1C04504},
+       /*8 */
+       {0x000016A0, 0xC2009518},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x0000000B},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000F},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_rev2_800[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0     */
+       {0x000016A0, 0xC0020301},
+       /*1 */
+       {0x000016A0, 0xC0420202},
+       /*2 */
+       {0x000016A0, 0xC0820314},
+       /*3 */
+       {0x000016A0, 0xC0C20117},
+       /*4 */
+       {0x000016A0, 0xC1020219},
+       /*5 */
+       {0x000016A0, 0xC142020B},
+       /*6 */
+       {0x000016A0, 0xC182030A},
+       /*7 */
+       {0x000016A0, 0xC1C2011D},
+       /*8 */
+       {0x000016A0, 0xC2020212},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC0007A12},
+       /*1 */
+       {0x000016A0, 0xC0408D16},
+       /*2 */
+       {0x000016A0, 0xC0809E1B},
+       /*3 */
+       {0x000016A0, 0xC0C0AC1F},
+       /*4 */
+       {0x000016A0, 0xC1005E0A},
+       /*5 */
+       {0x000016A0, 0xC140A91D},
+       /*6 */
+       {0x000016A0, 0xC1808E17},
+       /*7 */
+       {0x000016A0, 0xC1C05509},
+       /*8 */
+       {0x000016A0, 0xC2003A01},
+
+       /* PBS Leveling */
+       /*0 */
+       {0x000016A0, 0xC0007A12},
+       /*1 */
+       {0x000016A0, 0xC0408D16},
+       /*2 */
+       {0x000016A0, 0xC0809E1B},
+       /*3 */
+       {0x000016A0, 0xC0C0AC1F},
+       /*4 */
+       {0x000016A0, 0xC1005E0A},
+       /*5 */
+       {0x000016A0, 0xC140A91D},
+       /*6 */
+       {0x000016A0, 0xC1808E17},
+       /*7 */
+       {0x000016A0, 0xC1C05509},
+       /*8 */
+       {0x000016A0, 0xC2003A01},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000B},
+
+       {0x00001538, 0x0000000D},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x00000011},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_400[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0             2               4               15 */
+       {0x000016A0, 0xC002010C},
+       /*1             2               4               2 */
+       {0x000016A0, 0xC042001C},
+       /*2             2               4               27 */
+       {0x000016A0, 0xC0820115},
+       /*3             2               4               0 */
+       {0x000016A0, 0xC0C20019},
+       /*4             2               4               13 */
+       {0x000016A0, 0xC1020108},
+       /*5             2               4               5 */
+       {0x000016A0, 0xC1420100},
+       /*6             2               4               19 */
+       {0x000016A0, 0xC1820111},
+       /*7             2               4               0 */
+       {0x000016A0, 0xC1C2001B},
+       /*8             2               4               10 */
+       /*{0x000016A0, 0xC2020117}, */
+       {0x000016A0, 0xC202010C},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC0005508},
+       /*1 */
+       {0x000016A0, 0xC0409819},
+       /*2 */
+       {0x000016A0, 0xC080650C},
+       /*3 */
+       {0x000016A0, 0xC0C0700F},
+       /*4 */
+       {0x000016A0, 0xC1004103},
+       /*5 */
+       {0x000016A0, 0xC140A81D},
+       /*6 */
+       {0x000016A0, 0xC180650C},
+       /*7 */
+       {0x000016A0, 0xC1C08013},
+       /*8 */
+       {0x000016A0, 0xC2005508},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x00000008},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000A},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_533[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0             2               4               15 */
+       {0x000016A0, 0xC002040C},
+       /*1             2               4               2 */
+       {0x000016A0, 0xC0420117},
+       /*2             2               4               27 */
+       {0x000016A0, 0xC082041B},
+       /*3             2               4               0 */
+       {0x000016A0, 0xC0C20117},
+       /*4             2               4               13 */
+       {0x000016A0, 0xC102040A},
+       /*5             2               4               5 */
+       {0x000016A0, 0xC1420117},
+       /*6             2               4               19 */
+       {0x000016A0, 0xC1820419},
+       /*7             2               4               0 */
+       {0x000016A0, 0xC1C20117},
+       /*8             2               4               10 */
+       {0x000016A0, 0xC2020117},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC0008113},
+       /*1 */
+       {0x000016A0, 0xC0404504},
+       /*2 */
+       {0x000016A0, 0xC0808514},
+       /*3 */
+       {0x000016A0, 0xC0C09418},
+       /*4 */
+       {0x000016A0, 0xC1006D0E},
+       /*5 */
+       {0x000016A0, 0xC1405508},
+       /*6 */
+       {0x000016A0, 0xC1807D12},
+       /*7 */
+       {0x000016A0, 0xC1C0b01F},
+       /*8 */
+       {0x000016A0, 0xC2005D0A},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x00000008},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000A},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_600[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0             2               3               1 */
+       {0x000016A0, 0xC0020104},
+       /*1             2               2               6 */
+       {0x000016A0, 0xC0420010},
+       /*2             2               3               16 */
+       {0x000016A0, 0xC0820112},
+       /*3             2               1               26 */
+       {0x000016A0, 0xC0C20009},
+       /*4             2               2               29 */
+       {0x000016A0, 0xC102001F},
+       /*5             2               2               13 */
+       {0x000016A0, 0xC1420014},
+       /*6             2               3               6 */
+       {0x000016A0, 0xC1820109},
+       /*7             2               1               31 */
+       {0x000016A0, 0xC1C2000C},
+       /*8             2               2               22 */
+       {0x000016A0, 0xC2020112},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC0009919},
+       /*1 */
+       {0x000016A0, 0xC0405508},
+       /*2 */
+       {0x000016A0, 0xC0809919},
+       /*3 */
+       {0x000016A0, 0xC0C09C1A},
+       /*4 */
+       {0x000016A0, 0xC1008113},
+       /*5 */
+       {0x000016A0, 0xC140650C},
+       /*6 */
+       {0x000016A0, 0xC1809518},
+       /*7 */
+       {0x000016A0, 0xC1C04103},
+       /*8 */
+       {0x000016A0, 0xC2006D0E},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x0000000B},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000F},       /*Read Data Ready Delay Register */
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_667[MV_MAX_DDR3_STATIC_SIZE] = {
+
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0             2               3               1 */
+       {0x000016A0, 0xC0020103},
+       /*1            2               2               6 */
+       {0x000016A0, 0xC0420012},
+       /*2            2               3               16 */
+       {0x000016A0, 0xC0820113},
+       /*3            2               1               26 */
+       {0x000016A0, 0xC0C20012},
+       /*4            2               2               29 */
+       {0x000016A0, 0xC1020100},
+       /*5            2               2               13 */
+       {0x000016A0, 0xC1420016},
+       /*6            2               3               6 */
+       {0x000016A0, 0xC1820109},
+       /*7            2               1               31 */
+       {0x000016A0, 0xC1C20010},
+       /*8            2               2               22 */
+       {0x000016A0, 0xC2020112},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC000b11F},
+       /*1 */
+       {0x000016A0, 0xC040690D},
+       /*2 */
+       {0x000016A0, 0xC0803600},
+       /*3 */
+       {0x000016A0, 0xC0C0a81D},
+       /*4 */
+       {0x000016A0, 0xC1009919},
+       /*5 */
+       {0x000016A0, 0xC1407911},
+       /*6 */
+       {0x000016A0, 0xC180ad1e},
+       /*7 */
+       {0x000016A0, 0xC1C04d06},
+       /*8 */
+       {0x000016A0, 0xC2008514},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x0000000B},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000F},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_800[MV_MAX_DDR3_STATIC_SIZE] = {
+
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0             2               3               1 */
+       {0x000016A0, 0xC0020213},
+       /*1            2               2               6 */
+       {0x000016A0, 0xC0420108},
+       /*2            2               3               16 */
+       {0x000016A0, 0xC0820210},
+       /*3            2               1               26 */
+       {0x000016A0, 0xC0C20108},
+       /*4            2               2               29 */
+       {0x000016A0, 0xC102011A},
+       /*5            2               2               13 */
+       {0x000016A0, 0xC1420300},
+       /*6            2               3               6 */
+       {0x000016A0, 0xC1820204},
+       /*7            2               1               31 */
+       {0x000016A0, 0xC1C20106},
+       /*8            2               2               22 */
+       {0x000016A0, 0xC2020112},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC000620B},
+       /*1 */
+       {0x000016A0, 0xC0408D16},
+       /*2 */
+       {0x000016A0, 0xC0806A0D},
+       /*3 */
+       {0x000016A0, 0xC0C03D02},
+       /*4 */
+       {0x000016A0, 0xC1004a05},
+       /*5 */
+       {0x000016A0, 0xC140A11B},
+       /*6 */
+       {0x000016A0, 0xC1805E0A},
+       /*7 */
+       {0x000016A0, 0xC1C06D0E},
+       /*8 */
+       {0x000016A0, 0xC200AD1E},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x0000000C},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000E},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_rd_667_0[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0 */
+       {0x000016A0, 0xC002010E},
+       /*1 */
+       {0x000016A0, 0xC042001E},
+       /*2 */
+       {0x000016A0, 0xC0820118},
+       /*3 */
+       {0x000016A0, 0xC0C2001E},
+       /*4 */
+       {0x000016A0, 0xC102010C},
+       /*5 */
+       {0x000016A0, 0xC1420102},
+       /*6 */
+       {0x000016A0, 0xC1820111},
+       /*7 */
+       {0x000016A0, 0xC1C2001C},
+       /*8 */
+       {0x000016A0, 0xC2020109},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC0003600},
+       /*1 */
+       {0x000016A0, 0xC040690D},
+       /*2 */
+       {0x000016A0, 0xC0805207},
+       /*3 */
+       {0x000016A0, 0xC0C0A81D},
+       /*4 */
+       {0x000016A0, 0xC1009919},
+       /*5 */
+       {0x000016A0, 0xC1407911},
+       /*6 */
+       {0x000016A0, 0xC1803E02},
+       /*7 */
+       {0x000016A0, 0xC1C05107},
+       /*8 */
+       {0x000016A0, 0xC2008113},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x0000000B},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000F},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_rd_667_1[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0 */
+       {0x000016A0, 0xC0020106},
+       /*1 */
+       {0x000016A0, 0xC0420016},
+       /*2 */
+       {0x000016A0, 0xC0820117},
+       /*3 */
+       {0x000016A0, 0xC0C2000F},
+       /*4 */
+       {0x000016A0, 0xC1020105},
+       /*5 */
+       {0x000016A0, 0xC142001B},
+       /*6 */
+       {0x000016A0, 0xC182010C},
+       /*7 */
+       {0x000016A0, 0xC1C20011},
+       /*8 */
+       {0x000016A0, 0xC2020101},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC0003600},
+       /*1 */
+       {0x000016A0, 0xC0406D0E},
+       /*2 */
+       {0x000016A0, 0xC0803600},
+       /*3 */
+       {0x000016A0, 0xC0C04504},
+       /*4 */
+       {0x000016A0, 0xC1009919},
+       /*5 */
+       {0x000016A0, 0xC1407911},
+       /*6 */
+       {0x000016A0, 0xC1803600},
+       /*7 */
+       {0x000016A0, 0xC1C0610B},
+       /*8 */
+       {0x000016A0, 0xC2008113},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x0000000B},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000F},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_rd_667_2[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0 */
+       {0x000016A0, 0xC002010C},
+       /*1 */
+       {0x000016A0, 0xC042001B},
+       /*2 */
+       {0x000016A0, 0xC082011D},
+       /*3 */
+       {0x000016A0, 0xC0C20015},
+       /*4 */
+       {0x000016A0, 0xC102010B},
+       /*5 */
+       {0x000016A0, 0xC1420101},
+       /*6 */
+       {0x000016A0, 0xC1820113},
+       /*7 */
+       {0x000016A0, 0xC1C20017},
+       /*8 */
+       {0x000016A0, 0xC2020107},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC0003600},
+       /*1 */
+       {0x000016A0, 0xC0406D0E},
+       /*2 */
+       {0x000016A0, 0xC0803600},
+       /*3 */
+       {0x000016A0, 0xC0C04504},
+       /*4 */
+       {0x000016A0, 0xC1009919},
+       /*5 */
+       {0x000016A0, 0xC1407911},
+       /*6 */
+       {0x000016A0, 0xC180B11F},
+       /*7 */
+       {0x000016A0, 0xC1C0610B},
+       /*8 */
+       {0x000016A0, 0xC2008113},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x0000000B},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000F},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_db_667_M[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /* CS 0 */
+       /*0             2               3               1 */
+       {0x000016A0, 0xC0020103},
+       /*1            2               2               6 */
+       {0x000016A0, 0xC0420012},
+       /*2            2               3               16 */
+       {0x000016A0, 0xC0820113},
+       /*3            2               1               26 */
+       {0x000016A0, 0xC0C20012},
+       /*4            2               2               29 */
+       {0x000016A0, 0xC1020100},
+       /*5            2               2               13 */
+       {0x000016A0, 0xC1420016},
+       /*6            2               3               6 */
+       {0x000016A0, 0xC1820109},
+       /*7            2               1               31 */
+       {0x000016A0, 0xC1C20010},
+       /*8            2               2               22 */
+       {0x000016A0, 0xC2020112},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC000b11F},
+       /*1 */
+       {0x000016A0, 0xC040690D},
+       /*2 */
+       {0x000016A0, 0xC0803600},
+       /*3 */
+       {0x000016A0, 0xC0C0a81D},
+       /*4 */
+       {0x000016A0, 0xC1009919},
+       /*5 */
+       {0x000016A0, 0xC1407911},
+       /*6 */
+       {0x000016A0, 0xC180ad1e},
+       /*7 */
+       {0x000016A0, 0xC1C04d06},
+       /*8 */
+       {0x000016A0, 0xC2008514},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       /* CS 1 */
+
+       {0x000016A0, 0xC0060103},
+       /*1            2               2               6 */
+       {0x000016A0, 0xC0460012},
+       /*2            2               3               16 */
+       {0x000016A0, 0xC0860113},
+       /*3            2               1               26 */
+       {0x000016A0, 0xC0C60012},
+       /*4            2               2               29 */
+       {0x000016A0, 0xC1060100},
+       /*5            2               2               13 */
+       {0x000016A0, 0xC1460016},
+       /*6            2               3               6 */
+       {0x000016A0, 0xC1860109},
+       /*7            2               1               31 */
+       {0x000016A0, 0xC1C60010},
+       /*8            2               2               22 */
+       {0x000016A0, 0xC2060112},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC004b11F},
+       /*1 */
+       {0x000016A0, 0xC044690D},
+       /*2 */
+       {0x000016A0, 0xC0843600},
+       /*3 */
+       {0x000016A0, 0xC0C4a81D},
+       /*4 */
+       {0x000016A0, 0xC1049919},
+       /*5 */
+       {0x000016A0, 0xC1447911},
+       /*6 */
+       {0x000016A0, 0xC184ad1e},
+       /*7 */
+       {0x000016A0, 0xC1C44d06},
+       /*8 */
+       {0x000016A0, 0xC2048514},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC807000F},
+
+       /* Both CS */
+
+       {0x00001538, 0x00000B0B},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x00000F0F},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_rd_667_3[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0 */
+       {0x000016A0, 0xC0020118},
+       /*1 */
+       {0x000016A0, 0xC0420108},
+       /*2 */
+       {0x000016A0, 0xC0820202},
+       /*3 */
+       {0x000016A0, 0xC0C20108},
+       /*4 */
+       {0x000016A0, 0xC1020117},
+       /*5 */
+       {0x000016A0, 0xC142010C},
+       /*6 */
+       {0x000016A0, 0xC182011B},
+       /*7 */
+       {0x000016A0, 0xC1C20107},
+       /*8 */
+       {0x000016A0, 0xC2020113},
+
+       /* Write Leveling */
+       /*0 */
+       {0x000016A0, 0xC0003600},
+       /*1 */
+       {0x000016A0, 0xC0406D0E},
+       /*2 */
+       {0x000016A0, 0xC0805207},
+       /*3 */
+       {0x000016A0, 0xC0C0A81D},
+       /*4 */
+       {0x000016A0, 0xC1009919},
+       /*5 */
+       {0x000016A0, 0xC1407911},
+       /*6 */
+       {0x000016A0, 0xC1803E02},
+       /*7 */
+       {0x000016A0, 0xC1C04D06},
+       /*8 */
+       {0x000016A0, 0xC2008113},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+
+       {0x00001538, 0x0000000B},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000F},       /*Read Data Ready Delay Register */
+
+       /*init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+MV_DRAM_TRAINING_INIT ddr3_pcac_600[MV_MAX_DDR3_STATIC_SIZE] = {
+       /* Read Leveling */
+       /*PUP   RdSampleDly (+CL)       Phase   RL ADLL value */
+       /*0 */
+       {0x000016A0, 0xC0020404},
+       /* 1           2               2               6 */
+       {0x000016A0, 0xC042031E},
+       /* 2           2               3               16 */
+       {0x000016A0, 0xC0820411},
+       /* 3           2               1               26 */
+       {0x000016A0, 0xC0C20400},
+       /* 4           2               2               29 */
+       {0x000016A0, 0xC1020404},
+       /* 5           2               2               13 */
+       {0x000016A0, 0xC142031D},
+       /* 6           2               3               6 */
+       {0x000016A0, 0xC182040C},
+       /* 7           2               1               31 */
+       {0x000016A0, 0xC1C2031B},
+       /* 8           2               2               22 */
+       {0x000016A0, 0xC2020112},
+
+       /*  Write Leveling */
+       /* 0 */
+       {0x000016A0, 0xC0004905},
+       /* 1 */
+       {0x000016A0, 0xC040A81D},
+       /* 2 */
+       {0x000016A0, 0xC0804504},
+       /* 3 */
+       {0x000016A0, 0xC0C08013},
+       /* 4 */
+       {0x000016A0, 0xC1004504},
+       /* 5 */
+       {0x000016A0, 0xC140A81D},
+       /* 6 */
+       {0x000016A0, 0xC1805909},
+       /* 7 */
+       {0x000016A0, 0xC1C09418},
+       /* 8 */
+       {0x000016A0, 0xC2006D0E},
+
+       /*center DQS on read cycle */
+       {0x000016A0, 0xC803000F},
+       {0x00001538, 0x00000009},       /*Read Data Sample Delays Register */
+       {0x0000153C, 0x0000000D},       /*Read Data Ready Delay Register */
+       /* init DRAM */
+       {0x00001480, 0x00000001},
+       {0x0, 0x0}
+};
+
+#endif /* __AXP_TRAINING_STATIC_H */
diff --git a/drivers/ddr/mvebu/ddr3_axp_vars.h b/drivers/ddr/mvebu/ddr3_axp_vars.h
new file mode 100644 (file)
index 0000000..1b0ab56
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __AXP_VARS_H
+#define __AXP_VARS_H
+
+#include "ddr3_axp_config.h"
+#include "ddr3_axp_mc_static.h"
+#include "ddr3_axp_training_static.h"
+
+MV_DRAM_MODES ddr_modes[MV_DDR3_MODES_NUMBER] = {
+       /*      Conf name               CPUFreq         FabFreq         Chip ID Chip/Board      MC regs                 Training Values */
+       /* db board values: */
+       {"db_800-400", 0xA, 0x5, 0x0, A0, ddr3_A0_db_400, NULL},
+       {"db_1200-300", 0x2, 0xC, 0x0, A0, ddr3_A0_db_400, NULL},
+       {"db_1200-600", 0x2, 0x5, 0x0, A0, NULL, NULL},
+       {"db_1333-667", 0x3, 0x5, 0x0, A0, ddr3_A0_db_667, ddr3_db_rev2_667},
+       {"db_1600-800", 0xB, 0x5, 0x0, A0, ddr3_A0_db_667, ddr3_db_rev2_800},
+       {"amc_1333-667", 0x3, 0x5, 0x0, A0_AMC, ddr3_A0_AMC_667, NULL},
+       {"db_667-667", 0x9, 0x13, 0x0, Z1, ddr3_Z1_db_600, ddr3_db_667},
+       {"db_800-400", 0xA, 0x1, 0x0, Z1, ddr3_Z1_db_300, ddr3_db_400},
+       {"db_1066-533", 0x1, 0x1, 0x0, Z1, ddr3_Z1_db_300, ddr3_db_533},
+       {"db_1200-300", 0x2, 0xC, 0x0, Z1, ddr3_Z1_db_300, ddr3_db_667},
+       {"db_1200-600", 0x2, 0x5, 0x0, Z1, ddr3_Z1_db_600, NULL},
+       {"db_1333-333", 0x3, 0xC, 0x0, Z1, ddr3_Z1_db_300, ddr3_db_400},
+       {"db_1333-667", 0x3, 0x5, 0x0, Z1, ddr3_Z1_db_600, ddr3_db_667},
+       /* pcac board values (Z1 device): */
+       {"pcac_1200-600", 0x2, 0x5, 0x0, Z1_PCAC, ddr3_Z1_db_600,
+        ddr3_pcac_600},
+       /* rd board values (Z1 device): */
+       {"rd_667_0", 0x3, 0x5, 0x0, Z1_RD_SLED, ddr3_Z1_db_600, ddr3_rd_667_0},
+       {"rd_667_1", 0x3, 0x5, 0x1, Z1_RD_SLED, ddr3_Z1_db_600, ddr3_rd_667_1},
+       {"rd_667_2", 0x3, 0x5, 0x2, Z1_RD_SLED, ddr3_Z1_db_600, ddr3_rd_667_2},
+       {"rd_667_3", 0x3, 0x5, 0x3, Z1_RD_SLED, ddr3_Z1_db_600, ddr3_rd_667_3}
+};
+
+/* ODT settings - if needed update the following tables: (ODT_OPT - represents the CS configuration bitmap) */
+
+u16 odt_static[ODT_OPT][MAX_CS] = {    /*        NearEnd/FarEnd */
+       {0, 0, 0, 0},           /* 0000         0/0 - Not supported */
+       {ODT40, 0, 0, 0},       /* 0001         0/1 */
+       {0, 0, 0, 0},           /* 0010         0/0 - Not supported */
+       {ODT40, ODT40, 0, 0},   /* 0011         0/2 */
+       {0, 0, ODT40, 0},       /* 0100         1/0 */
+       {ODT30, 0, ODT30, 0},   /* 0101         1/1 */
+       {0, 0, 0, 0},           /* 0110         0/0 - Not supported */
+       {ODT120, ODT20, ODT20, 0},      /* 0111         1/2 */
+       {0, 0, 0, 0},           /* 1000         0/0 - Not supported */
+       {0, 0, 0, 0},           /* 1001         0/0 - Not supported */
+       {0, 0, 0, 0},           /* 1010         0/0 - Not supported */
+       {0, 0, 0, 0},           /* 1011         0/0 - Not supported */
+       {0, 0, ODT40, 0},       /* 1100         2/0 */
+       {ODT20, 0, ODT120, ODT20},      /* 1101         2/1 */
+       {0, 0, 0, 0},           /* 1110         0/0 - Not supported */
+       {ODT120, ODT30, ODT120, ODT30}  /* 1111         2/2 */
+};
+
+u16 odt_dynamic[ODT_OPT][MAX_CS] = {   /*        NearEnd/FarEnd */
+       {0, 0, 0, 0},           /* 0000         0/0 */
+       {0, 0, 0, 0},           /* 0001         0/1 */
+       {0, 0, 0, 0},           /* 0010         0/0 - Not supported */
+       {0, 0, 0, 0},           /* 0011         0/2 */
+       {0, 0, 0, 0},           /* 0100         1/0 */
+       {ODT120D, 0, ODT120D, 0},       /* 0101         1/1 */
+       {0, 0, 0, 0},           /* 0110         0/0 - Not supported */
+       {0, 0, ODT120D, 0},     /* 0111         1/2 */
+       {0, 0, 0, 0},           /* 1000         0/0 - Not supported */
+       {0, 0, 0, 0},           /* 1001         0/0 - Not supported */
+       {0, 0, 0, 0},           /* 1010         0/0 - Not supported */
+       {0, 0, 0, 0},           /* 1011         0/0 - Not supported */
+       {0, 0, 0, 0},           /* 1100         2/0 */
+       {ODT120D, 0, 0, 0},     /* 1101         2/1 */
+       {0, 0, 0, 0},           /* 1110         0/0 - Not supported */
+       {0, 0, 0, 0}            /* 1111         2/2 */
+};
+
+u32 odt_config[ODT_OPT] = {
+       0, 0x00010000, 0, 0x00030000, 0x04000000, 0x05050104, 0, 0x07430340, 0,
+           0, 0, 0,
+       0x30000, 0x1C0D100C, 0, 0x3CC330C0
+};
+
+/*
+ * User can manually set SPD values (in case SPD is not available on
+ * DIMM/System).
+ * SPD Values can simplify calculating the DUNIT registers values
+ */
+u8 spd_data[SPD_SIZE] = {
+       /* AXP DB Board DIMM SPD Values - manually set */
+       0x92, 0x10, 0x0B, 0x2, 0x3, 0x19, 0x0, 0x9, 0x09, 0x52, 0x1, 0x8, 0x0C,
+       0x0, 0x7E, 0x0, 0x69, 0x78,
+       0x69, 0x30, 0x69, 0x11, 0x20, 0x89, 0x0, 0x5, 0x3C, 0x3C, 0x0, 0xF0,
+       0x82, 0x5, 0x80, 0x0, 0x0, 0x0,
+       0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+       0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+       0x0, 0x0, 0x0, 0x0, 0x0F, 0x1, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+       0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+       0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+       0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+       0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+       0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+       0x0, 0x80, 0x2C, 0x1, 0x10, 0x23, 0x35, 0x28, 0xEB, 0xCA, 0x19, 0x8F
+};
+
+/*
+ * Controller Specific configurations Starts Here - DO NOT MODIFY
+ */
+
+/* Frequency - values are 1/HCLK in ps */
+u32 cpu_fab_clk_to_hclk[FAB_OPT][CLK_CPU] =
+/* CPU Frequency:
+       1000    1066    1200    1333    1500    1666    1800    2000    600             667             800             1600    Fabric */
+{
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 3000, 2500, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 4500, 3750, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 2500, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {4000, 3750, 3333, 3000, 2666, 2400, 0, 0, 0, 0, 5000, 2500},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 3000, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {2500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 5000, 0, 4000, 0, 0, 0, 0, 0, 0, 3750},
+       {5000, 0, 0, 3750, 3333, 0, 0, 0, 0, 0, 0, 3125},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 3330, 3000, 0, 0, 0, 0, 0, 0, 0, 2500},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3750},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 3000, 2500, 0},
+       {3000, 0, 2500, 0, 0, 0, 0, 0, 0, 0, 3750, 0}
+};
+
+u32 cpu_ddr_ratios[FAB_OPT][CLK_CPU] =
+/* CPU Frequency:
+       1000    1066    1200    1333    1500    1666    1800    2000    600             667             800             1600    Fabric */
+{
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, DDR_333, DDR_400, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, DDR_444, DDR_533, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, DDR_400, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {DDR_500, DDR_533, DDR_600, DDR_666, DDR_750, DDR_833, 0, 0, 0, 0,
+        DDR_400, DDR_800},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, DDR_333, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {DDR_400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, DDR_400, 0, DDR_500, 0, 0, 0, 0, 0, 0, DDR_533},
+       {DDR_400, 0, 0, DDR_533, DDR_600, 0, 0, 0, 0, 0, 0, DDR_640},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, DDR_300, DDR_333, 0, 0, 0, 0, 0, 0, 0, DDR_400},
+       {0, 0, 0, 0, 0, 0, DDR_600, DDR_666, 0, 0, 0, DDR_533},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, DDR_666, DDR_800, 0},
+       {DDR_666, 0, DDR_800, 0, 0, 0, 0, 0, 0, 0, DDR_533, 0}
+};
+
+u8 div_ratio1to1[CLK_VCO][CLK_DDR] =
+/* DDR Frequency:
+       100             300     360     400     444     500     533     600     666     750     800     833  */
+{ {0xA, 3, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0},      /*  1:1     CLK_CPU_1000  */
+{0xB, 3, 0, 3, 0, 0, 2, 0, 0, 0, 0, 0},        /*  1:1     CLK_CPU_1066  */
+{0xC, 4, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0},        /*  1:1     CLK_CPU_1200  */
+{0xD, 4, 0, 4, 0, 0, 0, 0, 2, 0, 0, 0},        /*      1:1     CLK_CPU_1333  */
+{0xF, 5, 0, 4, 0, 3, 0, 0, 0, 0, 0, 0},        /*      1:1     CLK_CPU_1500  */
+{0x11, 5, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0},       /*      1:1     CLK_CPU_1666  */
+{0x12, 6, 5, 4, 0, 0, 0, 3, 0, 0, 0, 0},       /*      1:1     CLK_CPU_1800  */
+{0x14, 7, 0, 5, 0, 4, 0, 0, 3, 0, 0, 0},       /*      1:1     CLK_CPU_2000  */
+{0x6, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0},        /*      1:1 CLK_CPU_600   */
+{0x6, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0},        /*      1:1     CLK_CPU_667   */
+{0x8, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0},        /*      1:1 CLK_CPU_800   */
+{0x10, 5, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0},       /*      1:1 CLK_CPU_1600   */
+{0x14, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0},       /*  1:1     CLK_CPU_1000 VCO_2000 */
+{0x15, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0},       /*  1:1     CLK_CPU_1066 VCO_2133 */
+{0x18, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0},       /*  1:1     CLK_CPU_1200 VCO_2400 */
+{0x1A, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0},       /*      1:1     CLK_CPU_1333 VCO_2666 */
+{0x1E, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0},       /*      1:1     CLK_CPU_1500 VCO_3000 */
+{0x21, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0},       /*      1:1     CLK_CPU_1666 VCO_3333 */
+{0x24, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0},       /*      1:1     CLK_CPU_1800 VCO_3600 */
+{0x28, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0},      /*      1:1     CLK_CPU_2000 VCO_4000 */
+{0xC, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0},        /*      1:1 CLK_CPU_600 VCO_1200 */
+{0xD, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0},        /*      1:1     CLK_CPU_667 VCO_1333 */
+{0x10, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0},       /*  1:1 CLK_CPU_800 VCO_1600 */
+{0x20, 10, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0}       /*      1:1 CLK_CPU_1600 VCO_3200 */
+};
+
+u8 div_ratio2to1[CLK_VCO][CLK_DDR] =
+/* DDR Frequency:
+               100     300     360     400     444     500     533     600     666     750     800     833  */
+{ {0, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0},        /*      2:1     CLK_CPU_1000  */
+{0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0},  /*      2:1     CLK_CPU_1066  */
+{0, 0, 0, 3, 5, 0, 0, 2, 0, 0, 3, 3},  /*      2:1     CLK_CPU_1200  */
+{0, 0, 0, 0, 0, 0, 5, 0, 2, 0, 3, 0},  /*      2:1     CLK_CPU_1333  */
+{0, 0, 0, 0, 0, 3, 0, 5, 0, 2, 0, 0},  /*      2:1     CLK_CPU_1500  */
+{0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 2},  /*      2:1     CLK_CPU_1666  */
+{0, 0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 0},  /*      2:1     CLK_CPU_1800  */
+{0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 5},  /*      2:1     CLK_CPU_2000  */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},  /*      2:1     CLK_CPU_600   */
+{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},  /*  2:1 CLK_CPU_667   */
+{0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0},  /*      2:1 CLK_CPU_800   */
+{0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0},  /*      2:1 CLK_CPU_1600   */
+{0, 0, 0, 5, 0, 0, 0, 0, 3, 0, 0, 0},  /*      2:1     CLK_CPU_1000 VCO_2000 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},  /*      2:1     CLK_CPU_1066 VCO_2133 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0},  /*      2:1     CLK_CPU_1200 VCO_2400 */
+{0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0},  /*      2:1     CLK_CPU_1333 VCO_2666 */
+{0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0},  /*      2:1     CLK_CPU_1500 VCO_3000 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},  /*      2:1     CLK_CPU_1666 VCO_3333 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},  /*      2:1     CLK_CPU_1800 VCO_3600 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},  /*      2:1     CLK_CPU_2000 VCO_4000 */
+{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},  /*      2:1     CLK_CPU_600 VCO_1200 */
+{0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0},  /*  2:1 CLK_CPU_667 VCO_1333 */
+{0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0},  /*      2:1 CLK_CPU_800 VCO_1600 */
+{0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0}   /*      2:1 CLK_CPU_1600 VCO_3200 */
+};
+
+#endif /* __AXP_VARS_H */
diff --git a/drivers/ddr/mvebu/ddr3_dfs.c b/drivers/ddr/mvebu/ddr3_dfs.c
new file mode 100644 (file)
index 0000000..9347773
--- /dev/null
@@ -0,0 +1,1552 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_DFS_C(s, d, l) \
+       DEBUG_DFS_S(s); DEBUG_DFS_D(d, l); DEBUG_DFS_S("\n")
+#define DEBUG_DFS_FULL_C(s, d, l) \
+       DEBUG_DFS_FULL_S(s); DEBUG_DFS_FULL_D(d, l); DEBUG_DFS_FULL_S("\n")
+
+#ifdef MV_DEBUG_DFS
+#define DEBUG_DFS_S(s)                 puts(s)
+#define DEBUG_DFS_D(d, l)              printf("%x", d)
+#else
+#define DEBUG_DFS_S(s)
+#define DEBUG_DFS_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_DFS_FULL
+#define DEBUG_DFS_FULL_S(s)            puts(s)
+#define DEBUG_DFS_FULL_D(d, l)         printf("%x", d)
+#else
+#define DEBUG_DFS_FULL_S(s)
+#define DEBUG_DFS_FULL_D(d, l)
+#endif
+
+#if defined(MV88F672X)
+extern u8 div_ratio[CLK_VCO][CLK_DDR];
+extern void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps);
+#else
+extern u16 odt_dynamic[ODT_OPT][MAX_CS];
+extern u8 div_ratio1to1[CLK_CPU][CLK_DDR];
+extern u8 div_ratio2to1[CLK_CPU][CLK_DDR];
+#endif
+extern u16 odt_static[ODT_OPT][MAX_CS];
+
+extern u32 cpu_fab_clk_to_hclk[FAB_OPT][CLK_CPU];
+
+extern u32 ddr3_get_vco_freq(void);
+
+u32 ddr3_get_freq_parameter(u32 target_freq, int ratio_2to1);
+
+#ifdef MV_DEBUG_DFS
+static inline void dfs_reg_write(u32 addr, u32 val)
+{
+       printf("\n write reg 0x%08x = 0x%08x", addr, val);
+       writel(val, INTER_REGS_BASE + addr);
+}
+#else
+static inline void dfs_reg_write(u32 addr, u32 val)
+{
+       writel(val, INTER_REGS_BASE + addr);
+}
+#endif
+
+static void wait_refresh_op_complete(void)
+{
+       u32 reg;
+
+       /* Poll - Wait for Refresh operation completion */
+       do {
+               reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+                       REG_SDRAM_OPERATION_CMD_RFRS_DONE;
+       } while (reg);          /* Wait for '0' */
+}
+
+/*
+ * Name:     ddr3_get_freq_parameter
+ * Desc:     Finds CPU/DDR frequency ratio according to Sample@reset and table.
+ * Args:     target_freq - target frequency
+ * Notes:
+ * Returns:  freq_par - the ratio parameter
+ */
+u32 ddr3_get_freq_parameter(u32 target_freq, int ratio_2to1)
+{
+       u32 ui_vco_freq, freq_par;
+
+       ui_vco_freq = ddr3_get_vco_freq();
+
+#if defined(MV88F672X)
+       freq_par = div_ratio[ui_vco_freq][target_freq];
+#else
+       /* Find the ratio between PLL frequency and ddr-clk */
+       if (ratio_2to1)
+               freq_par = div_ratio2to1[ui_vco_freq][target_freq];
+       else
+               freq_par = div_ratio1to1[ui_vco_freq][target_freq];
+#endif
+
+       return freq_par;
+}
+
+/*
+ * Name:     ddr3_dfs_high_2_low
+ * Desc:
+ * Args:     freq - target frequency
+ * Notes:
+ * Returns:  MV_OK - success, MV_FAIL - fail
+ */
+int ddr3_dfs_high_2_low(u32 freq, MV_DRAM_INFO *dram_info)
+{
+#if defined(MV88F78X60) || defined(MV88F672X)
+       /* This Flow is relevant for ArmadaXP A0 */
+       u32 reg, freq_par, tmp;
+       u32 cs = 0;
+
+       DEBUG_DFS_C("DDR3 - DFS - High To Low - Starting DFS procedure to Frequency - ",
+                   freq, 1);
+
+       /* target frequency - 100MHz */
+       freq_par = ddr3_get_freq_parameter(freq, 0);
+
+#if defined(MV88F672X)
+       u32 hclk;
+       u32 cpu_freq = ddr3_get_cpu_freq();
+       get_target_freq(cpu_freq, &tmp, &hclk);
+#endif
+
+       /* Configure - DRAM DLL final state after DFS is complete - Enable */
+       reg = reg_read(REG_DFS_ADDR);
+       /* [0] - DfsDllNextState - Disable */
+       reg |= (1 << REG_DFS_DLLNEXTSTATE_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Configure - XBAR Retry response during Block to enable internal
+        * access - Disable
+        */
+       reg = reg_read(REG_METAL_MASK_ADDR);
+       /* [0] - RetryMask - Disable */
+       reg &= ~(1 << REG_METAL_MASK_RETRY_OFFS);
+       /* 0x14B0 - Dunit MMask Register */
+       dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+       /* Configure - Block new external transactions - Enable */
+       reg = reg_read(REG_DFS_ADDR);
+       reg |= (1 << REG_DFS_BLOCK_OFFS);       /* [1] - DfsBlock - Enable  */
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* Registered DIMM support */
+       if (dram_info->reg_dimm) {
+               /*
+                * Configure - Disable Register DIMM CKE Power
+                * Down mode - CWA_RC
+                */
+               reg = (0x9 & REG_SDRAM_OPERATION_CWA_RC_MASK) <<
+                       REG_SDRAM_OPERATION_CWA_RC_OFFS;
+               /*
+                * Configure - Disable Register DIMM CKE Power
+                * Down mode - CWA_DATA
+                */
+               reg |= ((0 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+                       REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+
+               /*
+                * Configure - Disable Register DIMM CKE Power
+                * Down mode - Set Delay - tMRD
+                */
+               reg |= (0 << REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS);
+
+               /* Configure - Issue CWA command with the above parameters */
+               reg |= (REG_SDRAM_OPERATION_CMD_CWA &
+                       ~(0xF << REG_SDRAM_OPERATION_CS_OFFS));
+
+               /* 0x1418 - SDRAM Operation Register */
+               dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+               /* Poll - Wait for CWA operation completion */
+               do {
+                       reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+                              (REG_SDRAM_OPERATION_CMD_MASK);
+               } while (reg);
+
+               /* Configure - Disable outputs floating during Self Refresh */
+               reg = reg_read(REG_REGISTERED_DRAM_CTRL_ADDR);
+               /* [15] - SRFloatEn - Disable */
+               reg &= ~(1 << REG_REGISTERED_DRAM_CTRL_SR_FLOAT_OFFS);
+               /* 0x16D0 - DDR3 Registered DRAM Control */
+               dfs_reg_write(REG_REGISTERED_DRAM_CTRL_ADDR, reg);
+       }
+
+       /* Optional - Configure - DDR3_Rtt_nom_CS# */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       reg = reg_read(REG_DDR3_MR1_CS_ADDR +
+                                      (cs << MR_CS_ADDR_OFFS));
+                       reg &= REG_DDR3_MR1_RTT_MASK;
+                       dfs_reg_write(REG_DDR3_MR1_CS_ADDR +
+                                     (cs << MR_CS_ADDR_OFFS), reg);
+               }
+       }
+
+       /* Configure - Move DRAM into Self Refresh */
+       reg = reg_read(REG_DFS_ADDR);
+       reg |= (1 << REG_DFS_SR_OFFS);  /* [2] - DfsSR - Enable */
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* Poll - Wait for Self Refresh indication */
+       do {
+               reg = ((reg_read(REG_DFS_ADDR)) & (1 << REG_DFS_ATSR_OFFS));
+       } while (reg == 0x0);   /* 0x1528 [3] - DfsAtSR - Wait for '1' */
+
+       /* Start of clock change procedure (PLL) */
+#if defined(MV88F672X)
+       /* avantaLP */
+       /* Configure    cpupll_clkdiv_reset_mask */
+       reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+       reg &= CPU_PLL_CLOCK_DIVIDER_CNTRL0_MASK;
+       /* 0xE8264[7:0]   0xff CPU Clock Dividers Reset mask */
+       dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0, (reg + 0xFF));
+
+       /* Configure    cpu_clkdiv_reload_smooth    */
+       reg = reg_read(CPU_PLL_CNTRL0);
+       reg &= CPU_PLL_CNTRL0_RELOAD_SMOOTH_MASK;
+       /* 0xE8260   [15:8]  0x2 CPU Clock Dividers Reload Smooth enable */
+       dfs_reg_write(CPU_PLL_CNTRL0,
+                     (reg + (2 << CPU_PLL_CNTRL0_RELOAD_SMOOTH_OFFS)));
+
+       /* Configure    cpupll_clkdiv_relax_en */
+       reg = reg_read(CPU_PLL_CNTRL0);
+       reg &= CPU_PLL_CNTRL0_RELAX_EN_MASK;
+       /* 0xE8260 [31:24] 0x2 Relax Enable */
+       dfs_reg_write(CPU_PLL_CNTRL0,
+                     (reg + (2 << CPU_PLL_CNTRL0_RELAX_EN_OFFS)));
+
+       /* Configure    cpupll_clkdiv_ddr_clk_ratio */
+       reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL1);
+       /*
+        * 0xE8268  [13:8]  N   Set Training clock:
+        * APLL Out Clock (VCO freq) / N = 100 MHz
+        */
+       reg &= CPU_PLL_CLOCK_DIVIDER_CNTRL1_MASK;
+       reg |= (freq_par << 8); /* full Integer ratio from PLL-out to ddr-clk */
+       dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL1, reg);
+
+       /* Configure    cpupll_clkdiv_reload_ratio  */
+       reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+       reg &= CPU_PLL_CLOCK_RELOAD_RATIO_MASK;
+       /* 0xE8264 [8]=0x1 CPU Clock Dividers Reload Ratio trigger set */
+       dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0,
+                     (reg + (1 << CPU_PLL_CLOCK_RELOAD_RATIO_OFFS)));
+
+       udelay(1);
+
+       /* Configure    cpupll_clkdiv_reload_ratio  */
+       reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+       reg &= CPU_PLL_CLOCK_RELOAD_RATIO_MASK;
+       /* 0xE8264 [8]=0x0 CPU Clock Dividers Reload Ratio trigger clear */
+       dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0, reg);
+
+       udelay(5);
+
+#else
+       /*
+        * Initial Setup - assure that the "load new ratio" is clear (bit 24)
+        * and in the same chance, block reassertions of reset [15:8] and
+        * force reserved bits[7:0].
+        */
+       reg = 0x0000FDFF;
+       /* 0x18700 - CPU Div CLK control 0 */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       /*
+        * RelaX whenever reset is asserted to that channel
+        * (good for any case)
+        */
+       reg = 0x0000FF00;
+       /* 0x18704 - CPU Div CLK control 0 */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+       reg = reg_read(REG_CPU_DIV_CLK_CTRL_2_ADDR) &
+               REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK;
+
+       /* full Integer ratio from PLL-out to ddr-clk */
+       reg |= (freq_par << REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS);
+       /* 0x1870C - CPU Div CLK control 3 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_2_ADDR, reg);
+
+       /*
+        * Shut off clock enable to the DDRPHY clock channel (this is the "D").
+        * All the rest are kept as is (forced, but could be read-modify-write).
+        * This is done now by RMW above.
+        */
+
+       /* Clock is not shut off gracefully - keep it running */
+       reg = 0x000FFF02;
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_4_ADDR, reg);
+
+       /* Wait before replacing the clock on the DDR Phy Channel. */
+       udelay(1);
+
+       /*
+        * This for triggering the frequency update. Bit[24] is the
+        * central control
+        * bits [23:16] == which channels to change ==2 ==>
+        *                 only DDR Phy (smooth transition)
+        * bits [15:8] == mask reset reassertion due to clock modification
+        *                to these channels.
+        * bits [7:0] == not in use
+        */
+       reg = 0x0102FDFF;
+       /* 0x18700 - CPU Div CLK control 0 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       udelay(1);              /* Wait 1usec */
+
+       /*
+        * Poll Div CLK status 0 register - indication that the clocks
+        * are active - 0x18718 [8]
+        */
+       do {
+               reg = (reg_read(REG_CPU_DIV_CLK_STATUS_0_ADDR)) &
+                       (1 << REG_CPU_DIV_CLK_ALL_STABLE_OFFS);
+       } while (reg == 0);
+
+       /*
+        * Clean the CTRL0, to be ready for next resets and next requests
+        * of ratio modifications.
+        */
+       reg = 0x000000FF;
+       /* 0x18700 - CPU Div CLK control 0 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       udelay(5);
+#endif
+       /* End of clock change procedure (PLL) */
+
+       /* Configure - Select normal clock for the DDR PHY - Enable */
+       reg = reg_read(REG_DRAM_INIT_CTRL_STATUS_ADDR);
+       /* [16] - ddr_phy_trn_clk_sel - Enable  */
+       reg |= (1 << REG_DRAM_INIT_CTRL_TRN_CLK_OFFS);
+       /* 0x18488 - DRAM Init control status register */
+       dfs_reg_write(REG_DRAM_INIT_CTRL_STATUS_ADDR, reg);
+
+       /* Configure - Set Correct Ratio - 1:1 */
+       /* [15] - Phy2UnitClkRatio = 0 - Set 1:1 Ratio between Dunit and Phy */
+
+       reg = reg_read(REG_DDR_IO_ADDR) & ~(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+       dfs_reg_write(REG_DDR_IO_ADDR, reg);    /* 0x1524 - DDR IO Register */
+
+       /* Configure - 2T Mode - Restore original configuration */
+       reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+       /* [3:4] 2T - 1T Mode - low freq */
+       reg &= ~(REG_DUNIT_CTRL_LOW_2T_MASK << REG_DUNIT_CTRL_LOW_2T_OFFS);
+       /* 0x1404 - DDR Controller Control Low Register */
+       dfs_reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+       /* Configure - Restore CL and CWL - MRS Commands */
+       reg = reg_read(REG_DFS_ADDR);
+       reg &= ~(REG_DFS_CL_NEXT_STATE_MASK << REG_DFS_CL_NEXT_STATE_OFFS);
+       reg &= ~(REG_DFS_CWL_NEXT_STATE_MASK << REG_DFS_CWL_NEXT_STATE_OFFS);
+       /* [8] - DfsCLNextState - MRS CL=6 after DFS (due to DLL-off mode) */
+       reg |= (0x4 << REG_DFS_CL_NEXT_STATE_OFFS);
+       /* [12] - DfsCWLNextState - MRS CWL=6 after DFS (due to DLL-off mode) */
+       reg |= (0x1 << REG_DFS_CWL_NEXT_STATE_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* Poll - Wait for APLL + ADLLs lock on new frequency */
+       do {
+               reg = (reg_read(REG_PHY_LOCK_STATUS_ADDR)) &
+                       REG_PHY_LOCK_APLL_ADLL_STATUS_MASK;
+               /* 0x1674 [10:0] - Phy lock status Register */
+       } while (reg != REG_PHY_LOCK_APLL_ADLL_STATUS_MASK);
+
+       /* Configure - Reset the PHY Read FIFO and Write channels - Set Reset */
+       reg = (reg_read(REG_SDRAM_CONFIG_ADDR) & REG_SDRAM_CONFIG_MASK);
+       /* [30:29] = 0 - Data Pup R/W path reset */
+       /* 0x1400 - SDRAM Configuration register */
+       dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+       /*
+        * Configure - DRAM Data PHY Read [30], Write [29] path
+        * reset - Release Reset
+        */
+       reg = (reg_read(REG_SDRAM_CONFIG_ADDR) | ~REG_SDRAM_CONFIG_MASK);
+       /* [30:29] = '11' - Data Pup R/W path reset */
+       /* 0x1400 - SDRAM Configuration register */
+       dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+       /* Registered DIMM support */
+       if (dram_info->reg_dimm) {
+               /*
+                * Configure - Change register DRAM operating speed
+                * (below 400MHz) - CWA_RC
+                */
+               reg = (0xA & REG_SDRAM_OPERATION_CWA_RC_MASK) <<
+                       REG_SDRAM_OPERATION_CWA_RC_OFFS;
+
+               /*
+                * Configure - Change register DRAM operating speed
+                * (below 400MHz) - CWA_DATA
+                */
+               reg |= ((0x0 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+                       REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+
+               /* Configure - Set Delay - tSTAB */
+               reg |= (0x1 << REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS);
+
+               /* Configure - Issue CWA command with the above parameters */
+               reg |= (REG_SDRAM_OPERATION_CMD_CWA &
+                       ~(0xF << REG_SDRAM_OPERATION_CS_OFFS));
+
+               /* 0x1418 - SDRAM Operation Register */
+               dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+               /* Poll - Wait for CWA operation completion */
+               do {
+                       reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+                               (REG_SDRAM_OPERATION_CMD_MASK);
+               } while (reg);
+       }
+
+       /* Configure - Exit Self Refresh */
+       /* [2] - DfsSR  */
+       reg = (reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_SR_OFFS));
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Poll - DFS Register - 0x1528 [3] - DfsAtSR - All DRAM devices
+        * on all ranks are NOT in self refresh mode
+        */
+       do {
+               reg = ((reg_read(REG_DFS_ADDR)) & (1 << REG_DFS_ATSR_OFFS));
+       } while (reg);          /* Wait for '0' */
+
+       /* Configure - Issue Refresh command */
+       /* [3-0] = 0x2 - Refresh Command, [11-8] - enabled Cs */
+       reg = REG_SDRAM_OPERATION_CMD_RFRS;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs))
+                       reg &= ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+       }
+
+       /* 0x1418 - SDRAM Operation Register */
+       dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+       /* Poll - Wait for Refresh operation completion */
+       wait_refresh_op_complete();
+
+       /* Configure - Block new external transactions - Disable */
+       reg = reg_read(REG_DFS_ADDR);
+       reg &= ~(1 << REG_DFS_BLOCK_OFFS);      /* [1] - DfsBlock - Disable  */
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Configure -  XBAR Retry response during Block to enable
+        * internal access - Disable
+        */
+       reg = reg_read(REG_METAL_MASK_ADDR);
+       /* [0] - RetryMask - Enable */
+       reg |= (1 << REG_METAL_MASK_RETRY_OFFS);
+       /* 0x14B0 - Dunit MMask Register */
+       dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       /* Configure - Set CL */
+                       reg = reg_read(REG_DDR3_MR0_CS_ADDR +
+                                      (cs << MR_CS_ADDR_OFFS)) &
+                               ~REG_DDR3_MR0_CL_MASK;
+                       tmp = 0x4;      /* CL=6 - 0x4 */
+                       reg |= ((tmp & 0x1) << REG_DDR3_MR0_CL_OFFS);
+                       reg |= ((tmp & 0xE) << REG_DDR3_MR0_CL_HIGH_OFFS);
+                       dfs_reg_write(REG_DDR3_MR0_CS_ADDR +
+                                     (cs << MR_CS_ADDR_OFFS), reg);
+
+                       /* Configure - Set CWL */
+                       reg = reg_read(REG_DDR3_MR2_CS_ADDR +
+                                      (cs << MR_CS_ADDR_OFFS))
+                               & ~(REG_DDR3_MR2_CWL_MASK << REG_DDR3_MR2_CWL_OFFS);
+                       /* CWL=6 - 0x1 */
+                       reg |= ((0x1) << REG_DDR3_MR2_CWL_OFFS);
+                       dfs_reg_write(REG_DDR3_MR2_CS_ADDR +
+                                     (cs << MR_CS_ADDR_OFFS), reg);
+               }
+       }
+
+       DEBUG_DFS_C("DDR3 - DFS - High To Low - Ended successfuly - new Frequency - ",
+                   freq, 1);
+
+       return MV_OK;
+#else
+       /* This Flow is relevant for Armada370 A0 and ArmadaXP Z1 */
+
+       u32 reg, freq_par;
+       u32 cs = 0;
+
+       DEBUG_DFS_C("DDR3 - DFS - High To Low - Starting DFS procedure to Frequency - ",
+                   freq, 1);
+
+       /* target frequency - 100MHz */
+       freq_par = ddr3_get_freq_parameter(freq, 0);
+
+       reg = 0x0000FF00;
+       /* 0x18700 - CPU Div CLK control 0 */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+       /* 0x1600 - ODPG_CNTRL_Control */
+       reg = reg_read(REG_ODPG_CNTRL_ADDR);
+       /* [21] = 1 - auto refresh disable */
+       reg |= (1 << REG_ODPG_CNTRL_OFFS);
+       dfs_reg_write(REG_ODPG_CNTRL_ADDR, reg);
+
+       /* 0x1670 - PHY lock mask register */
+       reg = reg_read(REG_PHY_LOCK_MASK_ADDR);
+       reg &= REG_PHY_LOCK_MASK_MASK;  /* [11:0] = 0 */
+       dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+       reg = reg_read(REG_DFS_ADDR);   /* 0x1528 - DFS register */
+
+       /* Disable reconfig */
+       reg &= ~0x10;   /* [4] - Enable reconfig MR registers after DFS_ERG */
+       reg |= 0x1;     /* [0] - DRAM DLL disabled after DFS */
+
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       reg = reg_read(REG_METAL_MASK_ADDR) & ~(1 << 0); /* [0] - disable */
+       /* 0x14B0 - Dunit MMask Register */
+       dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+       /* [1] - DFS Block enable  */
+       reg = reg_read(REG_DFS_ADDR) | (1 << REG_DFS_BLOCK_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* [2] - DFS Self refresh enable  */
+       reg = reg_read(REG_DFS_ADDR) | (1 << REG_DFS_SR_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Poll DFS Register - 0x1528 [3] - DfsAtSR -
+        * All DRAM devices on all ranks are in self refresh mode -
+        * DFS can be executed afterwards
+        */
+       do {
+               reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+       } while (reg == 0x0);   /* Wait for '1' */
+
+       /* Disable ODT on DLL-off mode */
+       dfs_reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR,
+                     REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK);
+
+       /* [11:0] = 0 */
+       reg = (reg_read(REG_PHY_LOCK_MASK_ADDR) & REG_PHY_LOCK_MASK_MASK);
+       /* 0x1670 - PHY lock mask register */
+       dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+       /* Add delay between entering SR and start ratio modification */
+       udelay(1);
+
+       /*
+        * Initial Setup - assure that the "load new ratio" is clear (bit 24)
+        * and in the same chance, block reassertions of reset [15:8] and
+        * force reserved bits[7:0].
+        */
+       reg = 0x0000FDFF;
+       /* 0x18700 - CPU Div CLK control 0 */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       /*
+        * RelaX whenever reset is asserted to that channel (good for any case)
+        */
+       reg = 0x0000FF00;
+       /* 0x18700 - CPU Div CLK control 0 */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+       reg = reg_read(REG_CPU_DIV_CLK_CTRL_3_ADDR) &
+               REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK;
+       /* Full Integer ratio from PLL-out to ddr-clk */
+       reg |= (freq_par << REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS);
+       /* 0x1870C - CPU Div CLK control 3 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_3_ADDR, reg);
+
+       /*
+        * Shut off clock enable to the DDRPHY clock channel (this is the "D").
+        * All the rest are kept as is (forced, but could be read-modify-write).
+        * This is done now by RMW above.
+        */
+
+       /* Clock is not shut off gracefully - keep it running */
+       reg = 0x000FFF02;
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_4_ADDR, reg);
+
+       /* Wait before replacing the clock on the DDR Phy Channel. */
+       udelay(1);
+
+       /*
+        * This for triggering the frequency update. Bit[24] is the
+        * central control
+        * bits [23:16] == which channels to change ==2 ==> only DDR Phy
+        *                 (smooth transition)
+        * bits [15:8] == mask reset reassertion due to clock modification
+        *                to these channels.
+        * bits [7:0] == not in use
+        */
+       reg = 0x0102FDFF;
+       /* 0x18700 - CPU Div CLK control 0 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       udelay(1);              /* Wait 1usec */
+
+       /*
+        * Poll Div CLK status 0 register - indication that the clocks
+        * are active - 0x18718 [8]
+        */
+       do {
+               reg = (reg_read(REG_CPU_DIV_CLK_STATUS_0_ADDR)) &
+                       (1 << REG_CPU_DIV_CLK_ALL_STABLE_OFFS);
+       } while (reg == 0);
+
+       /*
+        * Clean the CTRL0, to be ready for next resets and next requests of
+        * ratio modifications.
+        */
+       reg = 0x000000FF;
+       /* 0x18700 - CPU Div CLK control 0 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       udelay(5);
+
+       /* Switch HCLK Mux to training clk (100Mhz), keep DFS request bit */
+       reg = 0x20050000;
+       /* 0x18488 - DRAM Init control status register */
+       dfs_reg_write(REG_DRAM_INIT_CTRL_STATUS_ADDR, reg);
+
+       reg = reg_read(REG_DDR_IO_ADDR) & ~(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+       /* [15] = 0 - Set 1:1 Ratio between Dunit and Phy */
+       dfs_reg_write(REG_DDR_IO_ADDR, reg);    /* 0x1524 - DDR IO Regist */
+
+       reg = reg_read(REG_DRAM_PHY_CONFIG_ADDR) & REG_DRAM_PHY_CONFIG_MASK;
+       /* [31:30]] - reset pup data ctrl ADLL */
+       /* 0x15EC - DRAM PHY Config register */
+       dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+       reg = (reg_read(REG_DRAM_PHY_CONFIG_ADDR) | ~REG_DRAM_PHY_CONFIG_MASK);
+       /* [31:30] - normal pup data ctrl ADLL */
+       /* 0x15EC - DRAM PHY Config register */
+       dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+       udelay(1);              /* Wait 1usec */
+
+       /* 0x1404 */
+       reg = (reg_read(REG_DUNIT_CTRL_LOW_ADDR) & 0xFFFFFFE7);
+       dfs_reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+       /* Poll Phy lock status register - APLL lock indication - 0x1674 */
+       do {
+               reg = (reg_read(REG_PHY_LOCK_STATUS_ADDR)) &
+                       REG_PHY_LOCK_STATUS_LOCK_MASK;
+       } while (reg != REG_PHY_LOCK_STATUS_LOCK_MASK); /* Wait for '0xFFF' */
+
+       reg = (reg_read(REG_SDRAM_CONFIG_ADDR) & REG_SDRAM_CONFIG_MASK);
+       /* [30:29] = 0 - Data Pup R/W path reset */
+       /* 0x1400 - SDRAM Configuration register */
+       dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+       reg = reg_read(REG_SDRAM_CONFIG_ADDR) | ~REG_SDRAM_CONFIG_MASK;
+       /* [30:29] = '11' - Data Pup R/W path reset */
+       /* 0x1400 - SDRAM Configuration register */
+       dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+       udelay(1000);           /* Wait 1msec */
+
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       /* Poll - Wait for Refresh operation completion */
+                       wait_refresh_op_complete();
+
+                       /* Config CL and CWL with MR0 and MR2 registers */
+                       reg = reg_read(REG_DDR3_MR0_ADDR);
+                       reg &= ~0x74;   /* CL [3:0]; [6:4],[2] */
+                       reg |= (1 << 5);        /* CL = 4, CAS is 6 */
+                       dfs_reg_write(REG_DDR3_MR0_ADDR, reg);
+                       reg = REG_SDRAM_OPERATION_CMD_MR0 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /* 0x1418 - SDRAM Operation Register */
+                       dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       /* Poll - Wait for Refresh operation completion */
+                       wait_refresh_op_complete();
+
+                       reg = reg_read(REG_DDR3_MR2_ADDR);
+                       reg &= ~0x38;   /* CWL [5:3] */
+                       reg |= (1 << 3);        /* CWL = 1, CWL is 6 */
+                       dfs_reg_write(REG_DDR3_MR2_ADDR, reg);
+
+                       reg = REG_SDRAM_OPERATION_CMD_MR2 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /* 0x1418 - SDRAM Operation Register */
+                       dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       /* Poll - Wait for Refresh operation completion */
+                       wait_refresh_op_complete();
+
+                       /* Set current rd_sample_delay  */
+                       reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+                       reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK <<
+                                (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+                       reg |= (5 << (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+                       dfs_reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, reg);
+
+                       /* Set current rd_ready_delay  */
+                       reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+                       reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+                                (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                       reg |= ((6) << (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                       dfs_reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+               }
+       }
+
+       /* [2] - DFS Self refresh disable  */
+       reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_SR_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* [1] - DFS Block enable  */
+       reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_BLOCK_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Poll DFS Register - 0x1528 [3] - DfsAtSR -
+        * All DRAM devices on all ranks are in self refresh mode - DFS can
+        * be executed afterwards
+        */
+       do {
+               reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+       } while (reg);          /* Wait for '1' */
+
+       reg = (reg_read(REG_METAL_MASK_ADDR) | (1 << 0));
+       /* [0] - Enable Dunit to crossbar retry */
+       /* 0x14B0 - Dunit MMask Register */
+       dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+       /* 0x1600 - PHY lock mask register */
+       reg = reg_read(REG_ODPG_CNTRL_ADDR);
+       reg &= ~(1 << REG_ODPG_CNTRL_OFFS);     /* [21] = 0 */
+       dfs_reg_write(REG_ODPG_CNTRL_ADDR, reg);
+
+       /* 0x1670 - PHY lock mask register */
+       reg = reg_read(REG_PHY_LOCK_MASK_ADDR);
+       reg |= ~REG_PHY_LOCK_MASK_MASK; /* [11:0] = FFF */
+       dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+       DEBUG_DFS_C("DDR3 - DFS - High To Low - Ended successfuly - new Frequency - ",
+                   freq, 1);
+
+       return MV_OK;
+#endif
+}
+
+/*
+ * Name:     ddr3_dfs_low_2_high
+ * Desc:
+ * Args:     freq - target frequency
+ * Notes:
+ * Returns:  MV_OK - success, MV_FAIL - fail
+ */
+int ddr3_dfs_low_2_high(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info)
+{
+#if defined(MV88F78X60) || defined(MV88F672X)
+       /* This Flow is relevant for ArmadaXP A0 */
+       u32 reg, freq_par, tmp;
+       u32 cs = 0;
+
+       DEBUG_DFS_C("DDR3 - DFS - Low To High - Starting DFS procedure to Frequency - ",
+                   freq, 1);
+
+       /* target frequency - freq */
+       freq_par = ddr3_get_freq_parameter(freq, ratio_2to1);
+
+#if defined(MV88F672X)
+       u32 hclk;
+       u32 cpu_freq = ddr3_get_cpu_freq();
+       get_target_freq(cpu_freq, &tmp, &hclk);
+#endif
+
+       /* Configure - DRAM DLL final state after DFS is complete - Enable */
+       reg = reg_read(REG_DFS_ADDR);
+       /* [0] - DfsDllNextState - Enable */
+       reg &= ~(1 << REG_DFS_DLLNEXTSTATE_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Configure -  XBAR Retry response during Block to enable
+        * internal access - Disable
+        */
+       reg = reg_read(REG_METAL_MASK_ADDR);
+       /* [0] - RetryMask - Disable */
+       reg &= ~(1 << REG_METAL_MASK_RETRY_OFFS);
+       /* 0x14B0 - Dunit MMask Register */
+       dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+       /* Configure - Block new external transactions - Enable */
+       reg = reg_read(REG_DFS_ADDR);
+       reg |= (1 << REG_DFS_BLOCK_OFFS);       /* [1] - DfsBlock - Enable  */
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* Configure - Move DRAM into Self Refresh */
+       reg = reg_read(REG_DFS_ADDR);
+       reg |= (1 << REG_DFS_SR_OFFS);  /* [2] - DfsSR - Enable */
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* Poll - Wait for Self Refresh indication */
+       do {
+               reg = ((reg_read(REG_DFS_ADDR)) & (1 << REG_DFS_ATSR_OFFS));
+       } while (reg == 0x0);   /* 0x1528 [3] - DfsAtSR - Wait for '1' */
+
+       /* Start of clock change procedure (PLL) */
+#if defined(MV88F672X)
+       /* avantaLP */
+       /* Configure    cpupll_clkdiv_reset_mask */
+       reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+       reg &= CPU_PLL_CLOCK_DIVIDER_CNTRL0_MASK;
+       /* 0xE8264[7:0]   0xff CPU Clock Dividers Reset mask */
+       dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0, (reg + 0xFF));
+
+       /* Configure    cpu_clkdiv_reload_smooth    */
+       reg = reg_read(CPU_PLL_CNTRL0);
+       reg &= CPU_PLL_CNTRL0_RELOAD_SMOOTH_MASK;
+       /* 0xE8260   [15:8]  0x2 CPU Clock Dividers Reload Smooth enable */
+       dfs_reg_write(CPU_PLL_CNTRL0,
+                     reg + (2 << CPU_PLL_CNTRL0_RELOAD_SMOOTH_OFFS));
+
+       /* Configure    cpupll_clkdiv_relax_en */
+       reg = reg_read(CPU_PLL_CNTRL0);
+       reg &= CPU_PLL_CNTRL0_RELAX_EN_MASK;
+       /* 0xE8260 [31:24] 0x2 Relax Enable */
+       dfs_reg_write(CPU_PLL_CNTRL0,
+                     reg + (2 << CPU_PLL_CNTRL0_RELAX_EN_OFFS));
+
+       /* Configure    cpupll_clkdiv_ddr_clk_ratio */
+       reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL1);
+       /*
+        * 0xE8268  [13:8]  N   Set Training clock:
+        * APLL Out Clock (VCO freq) / N = 100 MHz
+        */
+       reg &= CPU_PLL_CLOCK_DIVIDER_CNTRL1_MASK;
+       reg |= (freq_par << 8); /* full Integer ratio from PLL-out to ddr-clk */
+       dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL1, reg);
+       /* Configure    cpupll_clkdiv_reload_ratio  */
+       reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+       reg &= CPU_PLL_CLOCK_RELOAD_RATIO_MASK;
+       /* 0xE8264 [8]=0x1 CPU Clock Dividers Reload Ratio trigger set */
+       dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0,
+                     reg + (1 << CPU_PLL_CLOCK_RELOAD_RATIO_OFFS));
+
+       udelay(1);
+
+       /* Configure    cpupll_clkdiv_reload_ratio  */
+       reg = reg_read(CPU_PLL_CLOCK_DIVIDER_CNTRL0);
+       reg &= CPU_PLL_CLOCK_RELOAD_RATIO_MASK;
+       /* 0xE8264 [8]=0x0 CPU Clock Dividers Reload Ratio trigger clear */
+       dfs_reg_write(CPU_PLL_CLOCK_DIVIDER_CNTRL0, reg);
+
+       udelay(5);
+
+#else
+       /*
+        * Initial Setup - assure that the "load new ratio" is clear (bit 24)
+        * and in the same chance, block reassertions of reset [15:8]
+        * and force reserved bits[7:0].
+        */
+       reg = 0x0000FFFF;
+
+       /* 0x18700 - CPU Div CLK control 0 */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       /*
+        * RelaX whenever reset is asserted to that channel (good for any case)
+        */
+       reg = 0x0000FF00;
+       /* 0x18704 - CPU Div CLK control 0 */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+       reg = reg_read(REG_CPU_DIV_CLK_CTRL_2_ADDR) &
+               REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK;
+       reg |= (freq_par << REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS);
+       /* full Integer ratio from PLL-out to ddr-clk */
+       /* 0x1870C - CPU Div CLK control 3 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_2_ADDR, reg);
+
+       /*
+        * Shut off clock enable to the DDRPHY clock channel (this is the "D").
+        * All the rest are kept as is (forced, but could be read-modify-write).
+        * This is done now by RMW above.
+        */
+       reg = 0x000FFF02;
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_4_ADDR, reg);
+
+       /* Wait before replacing the clock on the DDR Phy Channel. */
+       udelay(1);
+
+       reg = 0x0102FDFF;
+       /*
+        * This for triggering the frequency update. Bit[24] is the
+        * central control
+        * bits [23:16] == which channels to change ==2 ==> only DDR Phy
+        *                 (smooth transition)
+        * bits [15:8] == mask reset reassertion due to clock modification
+        *                to these channels.
+        * bits [7:0] == not in use
+        */
+       /* 0x18700 - CPU Div CLK control 0 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       udelay(1);
+
+       /*
+        * Poll Div CLK status 0 register - indication that the clocks
+        * are active - 0x18718 [8]
+        */
+       do {
+               reg = reg_read(REG_CPU_DIV_CLK_STATUS_0_ADDR) &
+                       (1 << REG_CPU_DIV_CLK_ALL_STABLE_OFFS);
+       } while (reg == 0);
+
+       reg = 0x000000FF;
+       /*
+        * Clean the CTRL0, to be ready for next resets and next requests
+        * of ratio modifications.
+        */
+       /* 0x18700 - CPU Div CLK control 0 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+#endif
+       /* End of clock change procedure (PLL) */
+
+       if (ratio_2to1) {
+               /* Configure - Select normal clock for the DDR PHY - Disable */
+               reg = reg_read(REG_DRAM_INIT_CTRL_STATUS_ADDR);
+               /* [16] - ddr_phy_trn_clk_sel - Disable  */
+               reg &= ~(1 << REG_DRAM_INIT_CTRL_TRN_CLK_OFFS);
+               /* 0x18488 - DRAM Init control status register */
+               dfs_reg_write(REG_DRAM_INIT_CTRL_STATUS_ADDR, reg);
+       }
+
+       /*
+        * Configure - Set Correct Ratio - according to target ratio
+        * parameter - 2:1/1:1
+        */
+       if (ratio_2to1) {
+               /*
+                * [15] - Phy2UnitClkRatio = 1 - Set 2:1 Ratio between
+                * Dunit and Phy
+                */
+               reg = reg_read(REG_DDR_IO_ADDR) |
+                       (1 << REG_DDR_IO_CLK_RATIO_OFFS);
+       } else {
+               /*
+                * [15] - Phy2UnitClkRatio = 0 - Set 1:1 Ratio between
+                * Dunit and Phy
+                */
+               reg = reg_read(REG_DDR_IO_ADDR) &
+                       ~(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+       }
+       dfs_reg_write(REG_DDR_IO_ADDR, reg);    /* 0x1524 - DDR IO Register */
+
+       /* Configure - 2T Mode - Restore original configuration */
+       reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+       /* [3:4] 2T - Restore value */
+       reg &= ~(REG_DUNIT_CTRL_LOW_2T_MASK << REG_DUNIT_CTRL_LOW_2T_OFFS);
+       reg |= ((dram_info->mode_2t & REG_DUNIT_CTRL_LOW_2T_MASK) <<
+               REG_DUNIT_CTRL_LOW_2T_OFFS);
+       /* 0x1404 - DDR Controller Control Low Register */
+       dfs_reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+       /* Configure - Restore CL and CWL - MRS Commands */
+       reg = reg_read(REG_DFS_ADDR);
+       reg &= ~(REG_DFS_CL_NEXT_STATE_MASK << REG_DFS_CL_NEXT_STATE_OFFS);
+       reg &= ~(REG_DFS_CWL_NEXT_STATE_MASK << REG_DFS_CWL_NEXT_STATE_OFFS);
+
+       if (freq == DDR_400) {
+               if (dram_info->target_frequency == 0x8)
+                       tmp = ddr3_cl_to_valid_cl(5);
+               else
+                       tmp = ddr3_cl_to_valid_cl(6);
+       } else {
+               tmp = ddr3_cl_to_valid_cl(dram_info->cl);
+       }
+
+       /* [8] - DfsCLNextState */
+       reg |= ((tmp & REG_DFS_CL_NEXT_STATE_MASK) << REG_DFS_CL_NEXT_STATE_OFFS);
+       if (freq == DDR_400) {
+               /* [12] - DfsCWLNextState */
+               reg |= (((0) & REG_DFS_CWL_NEXT_STATE_MASK) <<
+                       REG_DFS_CWL_NEXT_STATE_OFFS);
+       } else {
+               /* [12] - DfsCWLNextState */
+               reg |= (((dram_info->cwl) & REG_DFS_CWL_NEXT_STATE_MASK) <<
+                       REG_DFS_CWL_NEXT_STATE_OFFS);
+       }
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* Optional - Configure - DDR3_Rtt_nom_CS# */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       reg = reg_read(REG_DDR3_MR1_CS_ADDR +
+                                      (cs << MR_CS_ADDR_OFFS));
+                       reg &= REG_DDR3_MR1_RTT_MASK;
+                       reg |= odt_static[dram_info->cs_ena][cs];
+                       dfs_reg_write(REG_DDR3_MR1_CS_ADDR +
+                                     (cs << MR_CS_ADDR_OFFS), reg);
+               }
+       }
+
+       /* Configure - Reset ADLLs - Set Reset */
+       reg = reg_read(REG_DRAM_PHY_CONFIG_ADDR) & REG_DRAM_PHY_CONFIG_MASK;
+       /* [31:30]] - reset pup data ctrl ADLL */
+       /* 0x15EC - DRAM PHY Config Register */
+       dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+       /* Configure - Reset ADLLs - Release Reset */
+       reg = reg_read(REG_DRAM_PHY_CONFIG_ADDR) | ~REG_DRAM_PHY_CONFIG_MASK;
+       /* [31:30] - normal pup data ctrl ADLL */
+       /* 0x15EC - DRAM PHY Config register */
+       dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+       /* Poll - Wait for APLL + ADLLs lock on new frequency */
+       do {
+               reg = reg_read(REG_PHY_LOCK_STATUS_ADDR) &
+                       REG_PHY_LOCK_APLL_ADLL_STATUS_MASK;
+               /* 0x1674 [10:0] - Phy lock status Register */
+       } while (reg != REG_PHY_LOCK_APLL_ADLL_STATUS_MASK);
+
+       /* Configure - Reset the PHY SDR clock divider */
+       if (ratio_2to1) {
+               /* Pup Reset Divider B - Set Reset */
+               /* [28] - DataPupRdRST = 0 */
+               reg = reg_read(REG_SDRAM_CONFIG_ADDR) &
+                       ~(1 << REG_SDRAM_CONFIG_PUPRSTDIV_OFFS);
+               /* [28] - DataPupRdRST = 1 */
+               tmp = reg_read(REG_SDRAM_CONFIG_ADDR) |
+                       (1 << REG_SDRAM_CONFIG_PUPRSTDIV_OFFS);
+               /* 0x1400 - SDRAM Configuration register */
+               dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+               /* Pup Reset Divider B - Release Reset */
+               /* 0x1400 - SDRAM Configuration register */
+               dfs_reg_write(REG_SDRAM_CONFIG_ADDR, tmp);
+       }
+
+       /* Configure - Reset the PHY Read FIFO and Write channels - Set Reset */
+       reg = reg_read(REG_SDRAM_CONFIG_ADDR) & REG_SDRAM_CONFIG_MASK;
+       /* [30:29] = 0 - Data Pup R/W path reset */
+       /* 0x1400 - SDRAM Configuration register */
+       dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+       /*
+        * Configure - DRAM Data PHY Read [30], Write [29] path reset -
+        * Release Reset
+        */
+       reg = reg_read(REG_SDRAM_CONFIG_ADDR) | ~REG_SDRAM_CONFIG_MASK;
+       /* [30:29] = '11' - Data Pup R/W path reset */
+       /* 0x1400 - SDRAM Configuration register */
+       dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+       /* Registered DIMM support */
+       if (dram_info->reg_dimm) {
+               /*
+                * Configure - Change register DRAM operating speed
+                * (DDR3-1333 / DDR3-1600) - CWA_RC
+                */
+               reg = (0xA & REG_SDRAM_OPERATION_CWA_RC_MASK) <<
+                       REG_SDRAM_OPERATION_CWA_RC_OFFS;
+               if (freq <= DDR_400) {
+                       /*
+                        * Configure - Change register DRAM operating speed
+                        * (DDR3-800) - CWA_DATA
+                        */
+                       reg |= ((0x0 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+                               REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+               } else if ((freq > DDR_400) && (freq <= DDR_533)) {
+                       /*
+                        * Configure - Change register DRAM operating speed
+                        * (DDR3-1066) - CWA_DATA
+                        */
+                       reg |= ((0x1 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+                               REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+               } else if ((freq > DDR_533) && (freq <= DDR_666)) {
+                       /*
+                        * Configure - Change register DRAM operating speed
+                        * (DDR3-1333) - CWA_DATA
+                        */
+                       reg |= ((0x2 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+                               REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+               } else {
+                       /*
+                        * Configure - Change register DRAM operating speed
+                        * (DDR3-1600) - CWA_DATA
+                        */
+                       reg |= ((0x3 & REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+                               REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+               }
+
+               /* Configure - Set Delay - tSTAB */
+               reg |= (0x1 << REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS);
+               /* Configure - Issue CWA command with the above parameters */
+               reg |= (REG_SDRAM_OPERATION_CMD_CWA &
+                       ~(0xF << REG_SDRAM_OPERATION_CS_OFFS));
+
+               /* 0x1418 - SDRAM Operation Register */
+               dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+               /* Poll - Wait for CWA operation completion */
+               do {
+                       reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+                               REG_SDRAM_OPERATION_CMD_MASK;
+               } while (reg);
+       }
+
+       /* Configure - Exit Self Refresh */
+       /* [2] - DfsSR  */
+       reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_SR_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Poll - DFS Register - 0x1528 [3] - DfsAtSR - All DRAM
+        * devices on all ranks are NOT in self refresh mode
+        */
+       do {
+               reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+       } while (reg);          /* Wait for '0' */
+
+       /* Configure - Issue Refresh command */
+       /* [3-0] = 0x2 - Refresh Command, [11-8] - enabled Cs */
+       reg = REG_SDRAM_OPERATION_CMD_RFRS;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs))
+                       reg &= ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+       }
+
+       /* 0x1418 - SDRAM Operation Register */
+       dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+       /* Poll - Wait for Refresh operation completion */
+       wait_refresh_op_complete();
+
+       /* Configure - Block new external transactions - Disable */
+       reg = reg_read(REG_DFS_ADDR);
+       reg &= ~(1 << REG_DFS_BLOCK_OFFS);      /* [1] - DfsBlock - Disable  */
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Configure -  XBAR Retry response during Block to enable
+        * internal access - Disable
+        */
+       reg = reg_read(REG_METAL_MASK_ADDR);
+       /* [0] - RetryMask - Enable */
+       reg |= (1 << REG_METAL_MASK_RETRY_OFFS);
+       /* 0x14B0 - Dunit MMask Register */
+       dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       /* Configure - Set CL */
+                       reg = reg_read(REG_DDR3_MR0_CS_ADDR +
+                                      (cs << MR_CS_ADDR_OFFS)) &
+                               ~REG_DDR3_MR0_CL_MASK;
+                       if (freq == DDR_400)
+                               tmp = ddr3_cl_to_valid_cl(6);
+                       else
+                               tmp = ddr3_cl_to_valid_cl(dram_info->cl);
+                       reg |= ((tmp & 0x1) << REG_DDR3_MR0_CL_OFFS);
+                       reg |= ((tmp & 0xE) << REG_DDR3_MR0_CL_HIGH_OFFS);
+                       dfs_reg_write(REG_DDR3_MR0_CS_ADDR +
+                                     (cs << MR_CS_ADDR_OFFS), reg);
+
+                       /* Configure - Set CWL */
+                       reg = reg_read(REG_DDR3_MR2_CS_ADDR +
+                                      (cs << MR_CS_ADDR_OFFS)) &
+                               ~(REG_DDR3_MR2_CWL_MASK << REG_DDR3_MR2_CWL_OFFS);
+                       if (freq == DDR_400)
+                               reg |= ((0) << REG_DDR3_MR2_CWL_OFFS);
+                       else
+                               reg |= ((dram_info->cwl) << REG_DDR3_MR2_CWL_OFFS);
+                       dfs_reg_write(REG_DDR3_MR2_CS_ADDR +
+                                     (cs << MR_CS_ADDR_OFFS), reg);
+               }
+       }
+
+       DEBUG_DFS_C("DDR3 - DFS - Low To High - Ended successfuly - new Frequency - ",
+                   freq, 1);
+
+       return MV_OK;
+
+#else
+
+       /* This Flow is relevant for Armada370 A0 and ArmadaXP Z1 */
+
+       u32 reg, freq_par, tmp;
+       u32 cs = 0;
+
+       DEBUG_DFS_C("DDR3 - DFS - Low To High - Starting DFS procedure to Frequency - ",
+                   freq, 1);
+
+       /* target frequency - freq */
+       freq_par = ddr3_get_freq_parameter(freq, ratio_2to1);
+
+       reg = 0x0000FF00;
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+       /* 0x1600 - PHY lock mask register */
+       reg = reg_read(REG_ODPG_CNTRL_ADDR);
+       reg |= (1 << REG_ODPG_CNTRL_OFFS);      /* [21] = 1 */
+       dfs_reg_write(REG_ODPG_CNTRL_ADDR, reg);
+
+       /* 0x1670 - PHY lock mask register */
+       reg = reg_read(REG_PHY_LOCK_MASK_ADDR);
+       reg &= REG_PHY_LOCK_MASK_MASK;  /* [11:0] = 0 */
+       dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+       /* Enable reconfig MR Registers after DFS */
+       reg = reg_read(REG_DFS_ADDR);   /* 0x1528 - DFS register */
+       /* [4] - Disable - reconfig MR registers after DFS_ERG */
+       reg &= ~0x11;
+       /* [0] - Enable - DRAM DLL after DFS */
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* Disable DRAM Controller to crossbar retry */
+       /* [0] - disable */
+       reg = reg_read(REG_METAL_MASK_ADDR) & ~(1 << 0);
+       /* 0x14B0 - Dunit MMask Register */
+       dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+       /* Enable DRAM Blocking */
+       /* [1] - DFS Block enable  */
+       reg = reg_read(REG_DFS_ADDR) | (1 << REG_DFS_BLOCK_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* Enable Self refresh */
+       /* [2] - DFS Self refresh enable  */
+       reg = reg_read(REG_DFS_ADDR) | (1 << REG_DFS_SR_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Poll DFS Register - All DRAM devices on all ranks are in
+        * self refresh mode - DFS can be executed afterwards
+        */
+       /* 0x1528 [3] - DfsAtSR  */
+       do {
+               reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+       } while (reg == 0x0);   /* Wait for '1' */
+
+       /*
+        * Set Correct Ratio - if freq>MARGIN_FREQ use 2:1 ratio
+        * else use 1:1 ratio
+        */
+       if (ratio_2to1) {
+               /* [15] = 1 - Set 2:1 Ratio between Dunit and Phy */
+               reg = reg_read(REG_DDR_IO_ADDR) |
+                       (1 << REG_DDR_IO_CLK_RATIO_OFFS);
+       } else {
+               /* [15] = 0 - Set 1:1 Ratio between Dunit and Phy */
+               reg = reg_read(REG_DDR_IO_ADDR) &
+                       ~(1 << REG_DDR_IO_CLK_RATIO_OFFS);
+       }
+       dfs_reg_write(REG_DDR_IO_ADDR, reg);    /* 0x1524 - DDR IO Register */
+
+       /* Switch HCLK Mux from (100Mhz) [16]=0, keep DFS request bit */
+       reg = 0x20040000;
+       /*
+        * [29] - training logic request DFS, [28:27] -
+        * preload patterns frequency [18]
+        */
+
+       /* 0x18488 - DRAM Init control status register */
+       dfs_reg_write(REG_DRAM_INIT_CTRL_STATUS_ADDR, reg);
+
+       /* Add delay between entering SR and start ratio modification */
+       udelay(1);
+
+       /*
+        * Initial Setup - assure that the "load new ratio" is clear (bit 24)
+        * and in the same chance, block reassertions of reset [15:8] and
+        * force reserved bits[7:0].
+        */
+       reg = 0x0000FFFF;
+       /* 0x18700 - CPU Div CLK control 0 */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       /*
+        * RelaX whenever reset is asserted to that channel (good for any case)
+        */
+       reg = 0x0000FF00;
+       /* 0x18704 - CPU Div CLK control 0 */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_1_ADDR, reg);
+
+       reg = reg_read(REG_CPU_DIV_CLK_CTRL_3_ADDR) &
+               REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK;
+       reg |= (freq_par << REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS);
+       /* Full Integer ratio from PLL-out to ddr-clk */
+       /* 0x1870C - CPU Div CLK control 3 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_3_ADDR, reg);
+
+       /*
+        * Shut off clock enable to the DDRPHY clock channel (this is the "D").
+        * All the rest are kept as is (forced, but could be read-modify-write).
+        * This is done now by RMW above.
+        */
+
+       reg = 0x000FFF02;
+
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_4_ADDR, reg);
+
+       /* Wait before replacing the clock on the DDR Phy Channel. */
+       udelay(1);
+
+       reg = 0x0102FDFF;
+       /*
+        * This for triggering the frequency update. Bit[24] is the
+        * central control
+        * bits [23:16] == which channels to change ==2 ==> only DDR Phy
+        *                 (smooth transition)
+        * bits [15:8] == mask reset reassertion due to clock modification
+        *                to these channels.
+        * bits [7:0] == not in use
+        */
+       /* 0x18700 - CPU Div CLK control 0 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       udelay(1);
+
+       /*
+        * Poll Div CLK status 0 register - indication that the clocks are
+        * active - 0x18718 [8]
+        */
+       do {
+               reg = reg_read(REG_CPU_DIV_CLK_STATUS_0_ADDR) &
+                       (1 << REG_CPU_DIV_CLK_ALL_STABLE_OFFS);
+       } while (reg == 0);
+
+       reg = 0x000000FF;
+       /*
+        * Clean the CTRL0, to be ready for next resets and next requests of
+        * ratio modifications.
+        */
+       /* 0x18700 - CPU Div CLK control 0 register */
+       dfs_reg_write(REG_CPU_DIV_CLK_CTRL_0_ADDR, reg);
+
+       udelay(5);
+
+       if (ratio_2to1) {
+               /* Pup Reset Divider B - Set Reset */
+               /* [28] = 0 - Pup Reset Divider B */
+               reg = reg_read(REG_SDRAM_CONFIG_ADDR) & ~(1 << 28);
+               /* [28] = 1 - Pup Reset Divider B */
+               tmp = reg_read(REG_SDRAM_CONFIG_ADDR) | (1 << 28);
+               /* 0x1400 - SDRAM Configuration register */
+               dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+               /* Pup Reset Divider B - Release Reset */
+               /* 0x1400 - SDRAM Configuration register */
+               dfs_reg_write(REG_SDRAM_CONFIG_ADDR, tmp);
+       }
+
+       /* DRAM Data PHYs ADLL Reset - Set Reset */
+       reg = (reg_read(REG_DRAM_PHY_CONFIG_ADDR) & REG_DRAM_PHY_CONFIG_MASK);
+       /* [31:30]] - reset pup data ctrl ADLL */
+       /* 0x15EC - DRAM PHY Config Register */
+       dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+       udelay(25);
+
+       /* APLL lock indication - Poll Phy lock status Register - 0x1674 [9] */
+       do {
+               reg = reg_read(REG_PHY_LOCK_STATUS_ADDR) &
+                       (1 << REG_PHY_LOCK_STATUS_LOCK_OFFS);
+       } while (reg == 0);
+
+       /* DRAM Data PHYs ADLL Reset - Release Reset */
+       reg = reg_read(REG_DRAM_PHY_CONFIG_ADDR) | ~REG_DRAM_PHY_CONFIG_MASK;
+       /* [31:30] - normal pup data ctrl ADLL */
+       /* 0x15EC - DRAM PHY Config register */
+       dfs_reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+       udelay(10000);          /* Wait 10msec */
+
+       /*
+        * APLL lock indication - Poll Phy lock status Register - 0x1674 [11:0]
+        */
+       do {
+               reg = reg_read(REG_PHY_LOCK_STATUS_ADDR) &
+                       REG_PHY_LOCK_STATUS_LOCK_MASK;
+       } while (reg != REG_PHY_LOCK_STATUS_LOCK_MASK);
+
+       /* DRAM Data PHY Read [30], Write [29] path reset - Set Reset */
+       reg = reg_read(REG_SDRAM_CONFIG_ADDR) & REG_SDRAM_CONFIG_MASK;
+       /* [30:29] = 0 - Data Pup R/W path reset */
+       /* 0x1400 - SDRAM Configuration register */
+       dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+       /* DRAM Data PHY Read [30], Write [29] path reset - Release Reset */
+       reg = reg_read(REG_SDRAM_CONFIG_ADDR) | ~REG_SDRAM_CONFIG_MASK;
+       /* [30:29] = '11' - Data Pup R/W path reset */
+       /* 0x1400 - SDRAM Configuration register */
+       dfs_reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+       /* Disable DFS Reconfig */
+       reg = reg_read(REG_DFS_ADDR) & ~(1 << 4);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* [2] - DFS Self refresh disable  */
+       reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_SR_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /*
+        * Poll DFS Register - 0x1528 [3] - DfsAtSR - All DRAM devices on
+        * all ranks are NOT in self refresh mode
+        */
+       do {
+               reg = reg_read(REG_DFS_ADDR) & (1 << REG_DFS_ATSR_OFFS);
+       } while (reg);          /* Wait for '0' */
+
+       /* 0x1404 */
+       reg = (reg_read(REG_DUNIT_CTRL_LOW_ADDR) & 0xFFFFFFE7) | 0x2;
+
+       /* Configure - 2T Mode - Restore original configuration */
+       /* [3:4] 2T - Restore value */
+       reg &= ~(REG_DUNIT_CTRL_LOW_2T_MASK << REG_DUNIT_CTRL_LOW_2T_OFFS);
+       reg |= ((dram_info->mode_2t & REG_DUNIT_CTRL_LOW_2T_MASK) <<
+               REG_DUNIT_CTRL_LOW_2T_OFFS);
+       dfs_reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+       udelay(1);              /* Wait 1us */
+
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       reg = (reg_read(REG_DDR3_MR1_ADDR));
+                       /* DLL Enable */
+                       reg &= ~(1 << REG_DDR3_MR1_DLL_ENA_OFFS);
+                       dfs_reg_write(REG_DDR3_MR1_ADDR, reg);
+
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR1 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       /* Poll - Wait for Refresh operation completion */
+                       wait_refresh_op_complete();
+
+                       /* DLL Reset - MR0 */
+                       reg = reg_read(REG_DDR3_MR0_ADDR);
+                       dfs_reg_write(REG_DDR3_MR0_ADDR, reg);
+
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR0 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       /* Poll - Wait for Refresh operation completion */
+                       wait_refresh_op_complete();
+
+                       reg = reg_read(REG_DDR3_MR0_ADDR);
+                       reg &= ~0x74;   /* CL [3:0]; [6:4],[2] */
+
+                       if (freq == DDR_400)
+                               tmp = ddr3_cl_to_valid_cl(6) & 0xF;
+                       else
+                               tmp = ddr3_cl_to_valid_cl(dram_info->cl) & 0xF;
+
+                       reg |= ((tmp & 0x1) << 2);
+                       reg |= ((tmp >> 1) << 4);       /* to bit 4 */
+                       dfs_reg_write(REG_DDR3_MR0_ADDR, reg);
+
+                       reg = REG_SDRAM_OPERATION_CMD_MR0 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /* 0x1418 - SDRAM Operation Register */
+                       dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       /* Poll - Wait for Refresh operation completion */
+                       wait_refresh_op_complete();
+
+                       reg = reg_read(REG_DDR3_MR2_ADDR);
+                       reg &= ~0x38;   /* CWL [5:3] */
+                       /* CWL = 0 ,for 400 MHg is 5 */
+                       if (freq != DDR_400)
+                               reg |= dram_info->cwl << REG_DDR3_MR2_CWL_OFFS;
+                       dfs_reg_write(REG_DDR3_MR2_ADDR, reg);
+                       reg = REG_SDRAM_OPERATION_CMD_MR2 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /* 0x1418 - SDRAM Operation Register */
+                       dfs_reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       /* Poll - Wait for Refresh operation completion */
+                       wait_refresh_op_complete();
+
+                       /* Set current rd_sample_delay  */
+                       reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+                       reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK <<
+                                (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+                       reg |= (dram_info->cl <<
+                               (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+                       dfs_reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, reg);
+
+                       /* Set current rd_ready_delay  */
+                       reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+                       reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+                                (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                       reg |= ((dram_info->cl + 1) <<
+                               (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+                       dfs_reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+               }
+       }
+
+       /* Enable ODT on DLL-on mode */
+       dfs_reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, 0);
+
+       /* [1] - DFS Block disable  */
+       reg = reg_read(REG_DFS_ADDR) & ~(1 << REG_DFS_BLOCK_OFFS);
+       dfs_reg_write(REG_DFS_ADDR, reg);       /* 0x1528 - DFS register */
+
+       /* Change DDR frequency to 100MHz procedure: */
+       /* 0x1600 - PHY lock mask register */
+       reg = reg_read(REG_ODPG_CNTRL_ADDR);
+       reg &= ~(1 << REG_ODPG_CNTRL_OFFS);     /* [21] = 0 */
+       dfs_reg_write(REG_ODPG_CNTRL_ADDR, reg);
+
+       /* Change DDR frequency to 100MHz procedure: */
+       /* 0x1670 - PHY lock mask register */
+       reg = reg_read(REG_PHY_LOCK_MASK_ADDR);
+       reg |= ~REG_PHY_LOCK_MASK_MASK; /* [11:0] = FFF */
+       dfs_reg_write(REG_PHY_LOCK_MASK_ADDR, reg);
+
+       reg = reg_read(REG_METAL_MASK_ADDR) | (1 << 0); /* [0] - disable */
+       /* 0x14B0 - Dunit MMask Register */
+       dfs_reg_write(REG_METAL_MASK_ADDR, reg);
+
+       DEBUG_DFS_C("DDR3 - DFS - Low To High - Ended successfuly - new Frequency - ",
+                   freq, 1);
+       return MV_OK;
+#endif
+}
diff --git a/drivers/ddr/mvebu/ddr3_dqs.c b/drivers/ddr/mvebu/ddr3_dqs.c
new file mode 100644 (file)
index 0000000..71a986d
--- /dev/null
@@ -0,0 +1,1374 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_DQS_C(s, d, l) \
+       DEBUG_DQS_S(s); DEBUG_DQS_D(d, l); DEBUG_DQS_S("\n")
+#define DEBUG_DQS_FULL_C(s, d, l) \
+       DEBUG_DQS_FULL_S(s); DEBUG_DQS_FULL_D(d, l); DEBUG_DQS_FULL_S("\n")
+#define DEBUG_DQS_RESULTS_C(s, d, l) \
+       DEBUG_DQS_RESULTS_S(s); DEBUG_DQS_RESULTS_D(d, l); DEBUG_DQS_RESULTS_S("\n")
+#define DEBUG_PER_DQ_C(s, d, l) \
+       puts(s); printf("%x", d); puts("\n")
+
+#define DEBUG_DQS_RESULTS_S(s) \
+       debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
+#define DEBUG_DQS_RESULTS_D(d, l) \
+       debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
+
+#define DEBUG_PER_DQ_S(s) \
+       debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%s", s)
+#define DEBUG_PER_DQ_D(d, l) \
+       debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%x", d)
+#define DEBUG_PER_DQ_DD(d, l) \
+       debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%d", d)
+
+#ifdef MV_DEBUG_DQS
+#define DEBUG_DQS_S(s)                 puts(s)
+#define DEBUG_DQS_D(d, l)              printf("%x", d)
+#else
+#define DEBUG_DQS_S(s)
+#define DEBUG_DQS_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_DQS_FULL
+#define DEBUG_DQS_FULL_S(s)            puts(s)
+#define DEBUG_DQS_FULL_D(d, l)         printf("%x", d)
+#else
+#define DEBUG_DQS_FULL_S(s)
+#define DEBUG_DQS_FULL_D(d, l)
+#endif
+
+/* State machine for centralization - find low & high limit */
+enum {
+       PUP_ADLL_LIMITS_STATE_FAIL,
+       PUP_ADLL_LIMITS_STATE_PASS,
+       PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS,
+};
+
+/* Hold centralization low results */
+static int centralization_low_limit[MAX_PUP_NUM] = { 0 };
+/* Hold centralization high results */
+static int centralization_high_limit[MAX_PUP_NUM] = { 0 };
+
+int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx);
+int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
+                         int *size_valid);
+static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+                           int is_tx);
+int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+                             int is_tx, u32 special_pattern_pup);
+int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+                                  int is_tx, u32 special_pattern_pup);
+int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+                                   int is_tx);
+
+#ifdef MV88F78X60
+extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
+extern u32 killer_pattern_64b[DQ_NUM][LEN_SPECIAL_PATTERN];
+extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
+#else
+extern u32 killer_pattern[DQ_NUM][LEN_16BIT_KILLER_PATTERN];
+extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
+#if defined(MV88F672X)
+extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
+#endif
+#endif
+extern u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN];
+
+static u32 *ddr3_dqs_choose_pattern(MV_DRAM_INFO *dram_info, u32 victim_dq)
+{
+       u32 *pattern_ptr;
+
+       /* Choose pattern */
+       switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+       case 16:
+               pattern_ptr = (u32 *)&killer_pattern[victim_dq];
+               break;
+#endif
+       case 32:
+               pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
+               break;
+#if defined(MV88F78X60)
+       case 64:
+               pattern_ptr = (u32 *)&killer_pattern_64b[victim_dq];
+               break;
+#endif
+       default:
+#if defined(MV88F78X60)
+               pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
+#else
+               pattern_ptr = (u32 *)&killer_pattern[victim_dq];
+#endif
+               break;
+       }
+
+       return pattern_ptr;
+}
+
+/*
+ * Name:     ddr3_dqs_centralization_rx
+ * Desc:     Execute the DQS centralization RX phase.
+ * Args:     dram_info
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_dqs_centralization_rx(MV_DRAM_INFO *dram_info)
+{
+       u32 cs, ecc, reg;
+       int status;
+
+       DEBUG_DQS_S("DDR3 - DQS Centralization RX - Starting procedure\n");
+
+       /* Enable SW override */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+
+       /* [0] = 1 - Enable SW override  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+       DEBUG_DQS_S("DDR3 - DQS Centralization RX - SW Override Enabled\n");
+
+       reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       /* Loop for each CS */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       DEBUG_DQS_FULL_C("DDR3 - DQS Centralization RX - CS - ",
+                                        (u32) cs, 1);
+
+                       for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
+
+                               /* ECC Support - Switch ECC Mux on ecc=1 */
+                               reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+                                       ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg |= (dram_info->ecc_ena *
+                                       ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+                               if (ecc)
+                                       DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Enabled\n");
+                               else
+                                       DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Disabled\n");
+
+                               DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Find all limits\n");
+
+                               status = ddr3_find_adll_limits(dram_info, cs,
+                                                              ecc, 0);
+                               if (MV_OK != status)
+                                       return status;
+
+                               DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Start calculating center\n");
+
+                               status = ddr3_center_calc(dram_info, cs, ecc,
+                                                         0);
+                               if (MV_OK != status)
+                                       return status;
+                       }
+               }
+       }
+
+       /* ECC Support - Disable ECC MUX */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+               ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       /* Disable SW override - Must be in a different stage */
+       /* [0]=0 - Enable SW override  */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+               (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+       reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_dqs_centralization_tx
+ * Desc:     Execute the DQS centralization TX phase.
+ * Args:     dram_info
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_dqs_centralization_tx(MV_DRAM_INFO *dram_info)
+{
+       u32 cs, ecc, reg;
+       int status;
+
+       DEBUG_DQS_S("DDR3 - DQS Centralization TX - Starting procedure\n");
+
+       /* Enable SW override */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+
+       /* [0] = 1 - Enable SW override  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+       DEBUG_DQS_S("DDR3 - DQS Centralization TX - SW Override Enabled\n");
+
+       reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       /* Loop for each CS */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       DEBUG_DQS_FULL_C("DDR3 - DQS Centralization TX - CS - ",
+                                        (u32) cs, 1);
+                       for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
+                               /* ECC Support - Switch ECC Mux on ecc=1 */
+                               reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+                                       ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg |= (dram_info->ecc_ena *
+                                       ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+                               if (ecc)
+                                       DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Enabled\n");
+                               else
+                                       DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Disabled\n");
+
+                               DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Find all limits\n");
+
+                               status = ddr3_find_adll_limits(dram_info, cs,
+                                                              ecc, 1);
+                               if (MV_OK != status)
+                                       return status;
+
+                               DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Start calculating center\n");
+
+                               status = ddr3_center_calc(dram_info, cs, ecc,
+                                                         1);
+                               if (MV_OK != status)
+                                       return status;
+                       }
+               }
+       }
+
+       /* ECC Support - Disable ECC MUX */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+               ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       /* Disable SW override - Must be in a different stage */
+       /* [0]=0 - Enable SW override  */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+               (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+       reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_find_adll_limits
+ * Desc:     Execute the Find ADLL limits phase.
+ * Args:     dram_info
+ *           cs
+ *           ecc_ena
+ *           is_tx             Indicate whether Rx or Tx
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx)
+{
+       u32 victim_dq, pup, tmp;
+       u32 adll_addr;
+       u32 max_pup;            /* maximal pup index */
+       u32 pup_mask = 0;
+       u32 unlock_pup;         /* bit array of un locked pups */
+       u32 new_unlock_pup;     /* bit array of compare failed pups */
+       u32 curr_adll;
+       u32 adll_start_val;     /* adll start loop value - for rx or tx limit */
+       u32 high_limit; /* holds found High Limit */
+       u32 low_limit;          /* holds found Low Limit */
+       int win_valid;
+       int update_win;
+       u32 sdram_offset;
+       u32 uj, cs_count, cs_tmp, ii;
+       u32 *pattern_ptr;
+       u32 dq;
+       u32 adll_end_val;       /* adll end of loop val - for rx or tx limit */
+       u8 analog_pbs[DQ_NUM][MAX_PUP_NUM][DQ_NUM][2];
+       u8 analog_pbs_sum[MAX_PUP_NUM][DQ_NUM][2];
+       int pup_adll_limit_state[MAX_PUP_NUM];  /* hold state of each pup */
+
+       adll_addr = ((is_tx == 1) ? PUP_DQS_WR : PUP_DQS_RD);
+       adll_end_val = ((is_tx == 1) ? ADLL_MIN : ADLL_MAX);
+       adll_start_val = ((is_tx == 1) ? ADLL_MAX : ADLL_MIN);
+       max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
+
+       DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - Starting Find ADLL Limits\n");
+
+       /* init the array */
+       for (pup = 0; pup < max_pup; pup++) {
+               centralization_low_limit[pup] = ADLL_MIN;
+               centralization_high_limit[pup] = ADLL_MAX;
+       }
+
+       /* Killer Pattern */
+       cs_count = 0;
+       for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
+               if (dram_info->cs_ena & (1 << cs_tmp))
+                       cs_count++;
+       }
+       sdram_offset = cs_count * (SDRAM_CS_SIZE + 1);
+       sdram_offset += ((is_tx == 1) ?
+                        SDRAM_DQS_TX_OFFS : SDRAM_DQS_RX_OFFS);
+
+       /* Prepare pup masks */
+       for (pup = 0; pup < max_pup; pup++)
+               pup_mask |= (1 << pup);
+
+       for (pup = 0; pup < max_pup; pup++) {
+               for (dq = 0; dq < DQ_NUM; dq++) {
+                       analog_pbs_sum[pup][dq][0] = adll_start_val;
+                       analog_pbs_sum[pup][dq][1] = adll_end_val;
+               }
+       }
+
+       /* Loop - use different pattern for each victim_dq */
+       for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+               DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Victim DQ - ",
+                                (u32)victim_dq, 1);
+               /*
+                * The pups 3 bit arrays represent state machine. with
+                * 3 stages for each pup.
+                * 1. fail and didn't get pass in earlier compares.
+                * 2. pass compare
+                * 3. fail after pass - end state.
+                * The window limits are the adll values where the adll
+                * was in the pass stage.
+                */
+
+               /* Set all states to Fail (1st state) */
+               for (pup = 0; pup < max_pup; pup++)
+                       pup_adll_limit_state[pup] = PUP_ADLL_LIMITS_STATE_FAIL;
+
+               /* Set current valid pups */
+               unlock_pup = pup_mask;
+
+               /* Set ADLL to start value */
+               curr_adll = adll_start_val;
+
+#if defined(MV88F78X60)
+               for (pup = 0; pup < max_pup; pup++) {
+                       for (dq = 0; dq < DQ_NUM; dq++) {
+                               analog_pbs[victim_dq][pup][dq][0] =
+                                       adll_start_val;
+                               analog_pbs[victim_dq][pup][dq][1] =
+                                       adll_end_val;
+                               per_bit_data[pup][dq] = 0;
+                       }
+               }
+#endif
+
+               for (uj = 0; uj < ADLL_MAX; uj++) {
+                       DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Setting ADLL to ",
+                                        curr_adll, 2);
+                       for (pup = 0; pup < max_pup; pup++) {
+                               if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+                                       tmp = ((is_tx == 1) ? curr_adll +
+                                              dram_info->wl_val[cs]
+                                              [pup * (1 - ecc) + ecc * ECC_PUP]
+                                              [D] : curr_adll);
+                                       ddr3_write_pup_reg(adll_addr, cs, pup +
+                                               (ecc * ECC_PUP), 0, tmp);
+                               }
+                       }
+
+                       /* Choose pattern */
+                       pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
+                                                             victim_dq);
+
+                       /* '1' - means pup failed, '0' - means pup pass */
+                       new_unlock_pup = 0;
+
+                       /* Read and compare results for Victim_DQ# */
+                       for (ii = 0; ii < 3; ii++) {
+                               u32 tmp = 0;
+                               if (MV_OK != ddr3_sdram_dqs_compare(dram_info,
+                                                          unlock_pup, &tmp,
+                                                          pattern_ptr,
+                                                          LEN_KILLER_PATTERN,
+                                                          sdram_offset +
+                                                          LEN_KILLER_PATTERN *
+                                                          4 * victim_dq,
+                                                          is_tx, 0, NULL,
+                                                          0))
+                                       return MV_DDR3_TRAINING_ERR_DRAM_COMPARE;
+
+                               new_unlock_pup |= tmp;
+                       }
+
+                       pup = 0;
+                       DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - UnlockPup: ",
+                                        unlock_pup, 2);
+                       DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - NewUnlockPup: ",
+                                        new_unlock_pup, 2);
+
+                       /* Update pup state */
+                       for (pup = 0; pup < max_pup; pup++) {
+                               if (IS_PUP_ACTIVE(unlock_pup, pup) == 0) {
+                                       DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Skipping pup ",
+                                                        pup, 1);
+                                       continue;
+                               }
+
+                               /*
+                                * Still didn't find the window limit of the pup
+                                */
+                               if (IS_PUP_ACTIVE(new_unlock_pup, pup) == 1) {
+                                       /* Current compare result == fail */
+                                       if (pup_adll_limit_state[pup] ==
+                                           PUP_ADLL_LIMITS_STATE_PASS) {
+                                               /*
+                                                * If now it failed but passed
+                                                * earlier
+                                                */
+                                               DEBUG_DQS_S("DDR3 - DQS Find Limits - PASS to FAIL: CS - ");
+                                               DEBUG_DQS_D(cs, 1);
+                                               DEBUG_DQS_S(", DQ - ");
+                                               DEBUG_DQS_D(victim_dq, 1);
+                                               DEBUG_DQS_S(", Pup - ");
+                                               DEBUG_DQS_D(pup, 1);
+                                               DEBUG_DQS_S(", ADLL - ");
+                                               DEBUG_DQS_D(curr_adll, 2);
+                                               DEBUG_DQS_S("\n");
+
+#if defined(MV88F78X60)
+                                               for (dq = 0; dq < DQ_NUM; dq++) {
+                                                       if ((analog_pbs[victim_dq][pup][dq][0] != adll_start_val)
+                                                           && (analog_pbs[victim_dq][pup]
+                                                               [dq][1] == adll_end_val))
+                                                               analog_pbs
+                                                                       [victim_dq]
+                                                                       [pup][dq]
+                                                                       [1] =
+                                                                       curr_adll;
+                                               }
+#endif
+                                               win_valid = 1;
+                                               update_win = 0;
+
+                                               /* Keep min / max limit value */
+                                               if (is_tx == 0) {
+                                                       /* RX - found upper limit */
+                                                       if (centralization_high_limit[pup] >
+                                                           (curr_adll - 1)) {
+                                                               high_limit =
+                                                                       curr_adll - 1;
+                                                               low_limit =
+                                                                       centralization_low_limit[pup];
+                                                               update_win = 1;
+                                                       }
+                                               } else {
+                                                       /* TX - found lower limit */
+                                                       if (centralization_low_limit[pup] < (curr_adll + 1)) {
+                                                               high_limit =
+                                                                       centralization_high_limit
+                                                                       [pup];
+                                                               low_limit =
+                                                                       curr_adll + 1;
+                                                               update_win =
+                                                                       1;
+                                                       }
+                                               }
+
+                                               if (update_win == 1) {
+                                                       /*
+                                                        * Before updating
+                                                        * window limits we need
+                                                        * to check that the
+                                                        * limits are valid
+                                                        */
+                                                       if (MV_OK !=
+                                                           ddr3_check_window_limits
+                                                           (pup, high_limit,
+                                                            low_limit, is_tx,
+                                                            &win_valid))
+                                                               return MV_DDR3_TRAINING_ERR_WIN_LIMITS;
+
+                                                       if (win_valid == 1) {
+                                                               /*
+                                                                * Window limits
+                                                                * should be
+                                                                * updated
+                                                                */
+                                                               centralization_low_limit
+                                                                       [pup] =
+                                                                       low_limit;
+                                                               centralization_high_limit
+                                                                       [pup] =
+                                                                       high_limit;
+                                                       }
+                                               }
+
+                                               if (win_valid == 1) {
+                                                       /* Found end of window - lock the pup */
+                                                       pup_adll_limit_state[pup] =
+                                                               PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS;
+                                                       unlock_pup &= ~(1 << pup);
+                                               } else {
+                                                       /* Probably false pass - reset status */
+                                                       pup_adll_limit_state[pup] =
+                                                               PUP_ADLL_LIMITS_STATE_FAIL;
+
+#if defined(MV88F78X60)
+                                                       /* Clear logging array of win size (per Dq) */
+                                                       for (dq = 0;
+                                                            dq < DQ_NUM;
+                                                            dq++) {
+                                                               analog_pbs
+                                                                       [victim_dq]
+                                                                       [pup][dq]
+                                                                       [0] =
+                                                                       adll_start_val;
+                                                               analog_pbs
+                                                                       [victim_dq]
+                                                                       [pup][dq]
+                                                                       [1] =
+                                                                       adll_end_val;
+                                                               per_bit_data
+                                                                       [pup][dq]
+                                                                       = 0;
+                                                       }
+#endif
+                                               }
+                                       }
+                               } else {
+                                       /* Current compare result == pass */
+                                       if (pup_adll_limit_state[pup] ==
+                                           PUP_ADLL_LIMITS_STATE_FAIL) {
+                                               /* If now it passed but failed earlier */
+                                               DEBUG_DQS_S("DDR3 - DQS Find Limits - FAIL to PASS: CS - ");
+                                               DEBUG_DQS_D(cs, 1);
+                                               DEBUG_DQS_S(", DQ - ");
+                                               DEBUG_DQS_D(victim_dq, 1);
+                                               DEBUG_DQS_S(", Pup - ");
+                                               DEBUG_DQS_D(pup, 1);
+                                               DEBUG_DQS_S(", ADLL - ");
+                                               DEBUG_DQS_D(curr_adll, 2);
+                                               DEBUG_DQS_S("\n");
+
+#if defined(MV88F78X60)
+                                               for (dq = 0; dq < DQ_NUM;
+                                                    dq++) {
+                                                       if (analog_pbs[victim_dq][pup][dq][0] == adll_start_val)
+                                                               analog_pbs
+                                                                   [victim_dq]
+                                                                   [pup][dq]
+                                                                   [0] =
+                                                                   curr_adll;
+                                               }
+#endif
+                                               /* Found start of window */
+                                               pup_adll_limit_state[pup] =
+                                                   PUP_ADLL_LIMITS_STATE_PASS;
+
+                                               /* Keep min / max limit value */
+                                               if (is_tx == 0) {
+                                                       /* RX - found low limit */
+                                                       if (centralization_low_limit[pup] <= curr_adll)
+                                                               centralization_low_limit
+                                                                   [pup] =
+                                                                   curr_adll;
+                                               } else {
+                                                       /* TX - found high limit */
+                                                       if (centralization_high_limit[pup] >= curr_adll)
+                                                               centralization_high_limit
+                                                                   [pup] =
+                                                                   curr_adll;
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (unlock_pup == 0) {
+                               /* Found limit to all pups */
+                               DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - found PUP limit\n");
+                               break;
+                       }
+
+                       /*
+                        * Increment / decrement (Move to right / left
+                        * one phase - ADLL) dqs RX / TX delay (for all un
+                        * lock pups
+                        */
+                       if (is_tx == 0)
+                               curr_adll++;
+                       else
+                               curr_adll--;
+               }
+
+               if (unlock_pup != 0) {
+                       /*
+                        * Found pups that didn't reach to the end of the
+                        * state machine
+                        */
+                       DEBUG_DQS_C("DDR3 - DQS Find Limits - Pups that didn't reached end of the state machine: ",
+                                   unlock_pup, 1);
+
+                       for (pup = 0; pup < max_pup; pup++) {
+                               if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+                                       if (pup_adll_limit_state[pup] ==
+                                           PUP_ADLL_LIMITS_STATE_FAIL) {
+                                               /* ERROR - found fail for all window size */
+                                               DEBUG_DQS_S("DDR3 - DQS Find Limits - Got FAIL for the complete range on pup - ");
+                                               DEBUG_DQS_D(pup, 1);
+                                               DEBUG_DQS_C(" victim DQ ",
+                                                           victim_dq, 1);
+
+                                               /* For debug - set min limit to illegal limit */
+                                               centralization_low_limit[pup]
+                                                       = ADLL_ERROR;
+                                               /*
+                                                * In case the pup is in mode
+                                                * PASS - the limit is the min
+                                                * / max adll, no need to
+                                                * update because of the results
+                                                * array default value
+                                                */
+                                               return MV_DDR3_TRAINING_ERR_PUP_RANGE;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       DEBUG_DQS_S("DDR3 - DQS Find Limits - DQ values per victim results:\n");
+       for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+               for (pup = 0; pup < max_pup; pup++) {
+                       DEBUG_DQS_S("Victim DQ-");
+                       DEBUG_DQS_D(victim_dq, 1);
+                       DEBUG_DQS_S(", PUP-");
+                       DEBUG_DQS_D(pup, 1);
+                       for (dq = 0; dq < DQ_NUM; dq++) {
+                               DEBUG_DQS_S(", DQ-");
+                               DEBUG_DQS_D(dq, 1);
+                               DEBUG_DQS_S(",S-");
+                               DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
+                                           [0], 2);
+                               DEBUG_DQS_S(",E-");
+                               DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
+                                           [1], 2);
+
+                               if (is_tx == 0) {
+                                       if (analog_pbs[victim_dq][pup][dq][0]
+                                           > analog_pbs_sum[pup][dq][0])
+                                               analog_pbs_sum[pup][dq][0] =
+                                                   analog_pbs[victim_dq][pup]
+                                                   [dq][0];
+                                       if (analog_pbs[victim_dq][pup][dq][1]
+                                           < analog_pbs_sum[pup][dq][1])
+                                               analog_pbs_sum[pup][dq][1] =
+                                                   analog_pbs[victim_dq][pup]
+                                                   [dq][1];
+                               } else {
+                                       if (analog_pbs[victim_dq][pup][dq][0]
+                                           < analog_pbs_sum[pup][dq][0])
+                                               analog_pbs_sum[pup][dq][0] =
+                                                   analog_pbs[victim_dq][pup]
+                                                   [dq][0];
+                                       if (analog_pbs[victim_dq][pup][dq][1]
+                                           > analog_pbs_sum[pup][dq][1])
+                                               analog_pbs_sum[pup][dq][1] =
+                                                   analog_pbs[victim_dq][pup]
+                                                   [dq][1];
+                               }
+                       }
+                       DEBUG_DQS_S("\n");
+               }
+       }
+
+       if (ddr3_get_log_level() >= MV_LOG_LEVEL_3) {
+               u32 dq;
+
+               DEBUG_PER_DQ_S("\n########## LOG LEVEL 3(Windows margins per-DQ) ##########\n");
+               if (is_tx) {
+                       DEBUG_PER_DQ_C("DDR3 - TX  CS: ", cs, 1);
+               } else {
+                       DEBUG_PER_DQ_C("DDR3 - RX  CS: ", cs, 1);
+               }
+
+               if (ecc == 0) {
+                       DEBUG_PER_DQ_S("\n DATA RESULTS:\n");
+               } else {
+                       DEBUG_PER_DQ_S("\n ECC RESULTS:\n");
+               }
+
+               /* Since all dq has the same value we take 0 as representive */
+               dq = 0;
+               for (pup = 0; pup < max_pup; pup++) {
+                       if (ecc == 0) {
+                               DEBUG_PER_DQ_S("\nBYTE:");
+                               DEBUG_PER_DQ_D(pup, 1);
+                               DEBUG_PER_DQ_S("\n");
+                       } else {
+                               DEBUG_PER_DQ_S("\nECC BYTE:\n");
+                       }
+                       DEBUG_PER_DQ_S("  DQ's        LOW       HIGH       WIN-SIZE\n");
+                       DEBUG_PER_DQ_S("============================================\n");
+                       for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+                               if (ecc == 0) {
+                                       DEBUG_PER_DQ_S("DQ[");
+                                       DEBUG_PER_DQ_DD((victim_dq +
+                                                        DQ_NUM * pup), 2);
+                                       DEBUG_PER_DQ_S("]");
+                               } else {
+                                       DEBUG_PER_DQ_S("CB[");
+                                       DEBUG_PER_DQ_DD(victim_dq, 2);
+                                       DEBUG_PER_DQ_S("]");
+                               }
+                               if (is_tx) {
+                                       DEBUG_PER_DQ_S("      0x");
+                                       DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1], 2);   /* low value */
+                                       DEBUG_PER_DQ_S("        0x");
+                                       DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2);   /* high value */
+                                       DEBUG_PER_DQ_S("        0x");
+                                       DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0] - analog_pbs[victim_dq][pup][dq][1], 2);       /* win-size */
+                               } else {
+                                       DEBUG_PER_DQ_S("     0x");
+                                       DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2);   /* low value */
+                                       DEBUG_PER_DQ_S("       0x");
+                                       DEBUG_PER_DQ_D((analog_pbs[victim_dq][pup][dq][1] - 1), 2);     /* high value */
+                                       DEBUG_PER_DQ_S("       0x");
+                                       DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1] - analog_pbs[victim_dq][pup][dq][0], 2);       /* win-size */
+                               }
+                               DEBUG_PER_DQ_S("\n");
+                       }
+               }
+               DEBUG_PER_DQ_S("\n");
+       }
+
+       if (is_tx) {
+               DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
+       } else {
+               DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
+       }
+
+       for (pup = 0; pup < max_pup; pup++) {
+               DEBUG_DQS_S("PUP-");
+               DEBUG_DQS_D(pup, 1);
+               for (dq = 0; dq < DQ_NUM; dq++) {
+                       DEBUG_DQS_S(", DQ-");
+                       DEBUG_DQS_D(dq, 1);
+                       DEBUG_DQS_S(",S-");
+                       DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
+                       DEBUG_DQS_S(",E-");
+                       DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
+               }
+               DEBUG_DQS_S("\n");
+       }
+
+       if (is_tx) {
+               DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
+       } else {
+               DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
+       }
+
+       for (pup = 0; pup < max_pup; pup++) {
+               if (max_pup == 1) {
+                       /* For ECC PUP */
+                       DEBUG_DQS_S("DDR3 - DQS8");
+               } else {
+                       DEBUG_DQS_S("DDR3 - DQS");
+                       DEBUG_DQS_D(pup, 1);
+               }
+
+               for (dq = 0; dq < DQ_NUM; dq++) {
+                       DEBUG_DQS_S(", DQ-");
+                       DEBUG_DQS_D(dq, 1);
+                       DEBUG_DQS_S("::S-");
+                       DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
+                       DEBUG_DQS_S(",E-");
+                       DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
+               }
+               DEBUG_DQS_S("\n");
+       }
+
+       DEBUG_DQS_S("DDR3 - DQS Find Limits - Ended\n");
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_check_window_limits
+ * Desc:     Check window High & Low limits.
+ * Args:     pup                pup index
+ *           high_limit           window high limit
+ *           low_limit            window low limit
+ *           is_tx                Indicate whether Rx or Tx
+ *           size_valid          Indicate whether window size is valid
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
+                            int *size_valid)
+{
+       DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Starting\n");
+
+       if (low_limit > high_limit) {
+               DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
+               DEBUG_DQS_D(pup, 1);
+               DEBUG_DQS_S(" Low Limit grater than High Limit\n");
+               *size_valid = 0;
+               return MV_OK;
+       }
+
+       /*
+        * Check that window size is valid, if not it was probably false pass
+        * before
+        */
+       if ((high_limit - low_limit) < MIN_WIN_SIZE) {
+               /*
+                * Since window size is too small probably there was false
+                * pass
+                */
+               *size_valid = 0;
+
+               DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
+               DEBUG_DQS_D(pup, 1);
+               DEBUG_DQS_S(" Window size is smaller than MIN_WIN_SIZE\n");
+
+       } else if ((high_limit - low_limit) > ADLL_MAX) {
+               *size_valid = 0;
+
+               DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
+               DEBUG_DQS_D(pup, 1);
+               DEBUG_DQS_S
+                   (" Window size is bigger than max ADLL taps (31)  Exiting.\n");
+
+               return MV_FAIL;
+
+       } else {
+               *size_valid = 1;
+
+               DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Pup ");
+               DEBUG_DQS_FULL_D(pup, 1);
+               DEBUG_DQS_FULL_C(" window size is ", (high_limit - low_limit),
+                                2);
+       }
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_center_calc
+ * Desc:     Execute the calculate the center of windows phase.
+ * Args:     pDram Info
+ *           is_tx             Indicate whether Rx or Tx
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+                           int is_tx)
+{
+       /* bit array of pups that need specail search */
+       u32 special_pattern_i_pup = 0;
+       u32 special_pattern_ii_pup = 0;
+       u32 pup;
+       u32 max_pup;
+
+       max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
+
+       for (pup = 0; pup < max_pup; pup++) {
+               if (is_tx == 0) {
+                       /* Check special pattern I */
+                       /*
+                        * Special pattern Low limit search - relevant only
+                        * for Rx, win size < threshold and low limit = 0
+                        */
+                       if (((centralization_high_limit[pup] -
+                             centralization_low_limit[pup]) < VALID_WIN_THRS)
+                           && (centralization_low_limit[pup] == MIN_DELAY))
+                               special_pattern_i_pup |= (1 << pup);
+
+                       /* Check special pattern II */
+                       /*
+                        * Special pattern High limit search - relevant only
+                        * for Rx, win size < threshold and high limit = 31
+                        */
+                       if (((centralization_high_limit[pup] -
+                             centralization_low_limit[pup]) < VALID_WIN_THRS)
+                           && (centralization_high_limit[pup] == MAX_DELAY))
+                               special_pattern_ii_pup |= (1 << pup);
+               }
+       }
+
+       /* Run special pattern Low limit search - for relevant pup */
+       if (special_pattern_i_pup != 0) {
+               DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern I for Low limit search\n");
+               if (MV_OK !=
+                   ddr3_special_pattern_i_search(dram_info, cs, ecc, is_tx,
+                                             special_pattern_i_pup))
+                       return MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH;
+       }
+
+       /* Run special pattern High limit search - for relevant pup */
+       if (special_pattern_ii_pup != 0) {
+               DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern II for High limit search\n");
+               if (MV_OK !=
+                   ddr3_special_pattern_ii_search(dram_info, cs, ecc, is_tx,
+                                                  special_pattern_ii_pup))
+                       return MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH;
+       }
+
+       /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
+       return ddr3_set_dqs_centralization_results(dram_info, cs, ecc, is_tx);
+}
+
+/*
+ * Name:     ddr3_special_pattern_i_search
+ * Desc:     Execute special pattern low limit search.
+ * Args:
+ *           special_pattern_pup  The pups that need the special search
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+                                 int is_tx, u32 special_pattern_pup)
+{
+       u32 victim_dq;          /* loop index - victim DQ */
+       u32 adll_idx;
+       u32 pup;
+       u32 unlock_pup;         /* bit array of the unlock pups  */
+       u32 first_fail; /* bit array - of pups that  get first fail */
+       u32 new_lockup_pup;     /* bit array of compare failed pups */
+       u32 pass_pup;           /* bit array of compare pass pup */
+       u32 sdram_offset;
+       u32 max_pup;
+       u32 comp_val;
+       u32 special_res[MAX_PUP_NUM];   /* hold tmp results */
+
+       DEBUG_DQS_S("DDR3 - DQS - Special Pattern I Search - Starting\n");
+
+       max_pup = ecc + (1 - ecc) * dram_info->num_of_std_pups;
+
+       /* Init the temporary results to max ADLL value */
+       for (pup = 0; pup < max_pup; pup++)
+               special_res[pup] = ADLL_MAX;
+
+       /* Run special pattern for all DQ - use the same pattern */
+       for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+               unlock_pup = special_pattern_pup;
+               first_fail = 0;
+
+               sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS +
+                       LEN_KILLER_PATTERN * 4 * victim_dq;
+
+               for (pup = 0; pup < max_pup; pup++) {
+                       /* Set adll value per PUP. adll = high limit per pup */
+                       if (IS_PUP_ACTIVE(unlock_pup, pup)) {
+                               /* only for pups that need special search */
+                               ddr3_write_pup_reg(PUP_DQS_RD, cs,
+                                                  pup + (ecc * ECC_PUP), 0,
+                                                  centralization_high_limit
+                                                  [pup]);
+                       }
+               }
+
+               adll_idx = 0;
+               do {
+                       /*
+                        * Perform read and compare simultaneously for all
+                        * un-locked MC use the special pattern mask
+                        */
+                       new_lockup_pup = 0;
+
+                       if (MV_OK !=
+                           ddr3_sdram_dqs_compare(dram_info, unlock_pup,
+                                                  &new_lockup_pup,
+                                                  special_pattern
+                                                  [victim_dq],
+                                                  LEN_SPECIAL_PATTERN,
+                                                  sdram_offset, 0,
+                                                  0, NULL, 1))
+                               return MV_FAIL;
+
+                       DEBUG_DQS_S("DDR3 - DQS - Special I - ADLL value is: ");
+                       DEBUG_DQS_D(adll_idx, 2);
+                       DEBUG_DQS_S(", UnlockPup: ");
+                       DEBUG_DQS_D(unlock_pup, 2);
+                       DEBUG_DQS_S(", NewLockPup: ");
+                       DEBUG_DQS_D(new_lockup_pup, 2);
+                       DEBUG_DQS_S("\n");
+
+                       if (unlock_pup != new_lockup_pup)
+                               DEBUG_DQS_S("DDR3 - DQS - Special I - Some Pup passed!\n");
+
+                       /* Search for pups with passed compare & already fail */
+                       pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
+                       first_fail |= new_lockup_pup;
+                       unlock_pup &= ~pass_pup;
+
+                       /* Get pass pups */
+                       if (pass_pup != 0) {
+                               for (pup = 0; pup < max_pup; pup++) {
+                                       if (IS_PUP_ACTIVE(pass_pup, pup) ==
+                                           1) {
+                                               /* If pup passed and has first fail = 1 */
+                                               /* keep min value of ADLL max value - current adll */
+                                               /* (centralization_high_limit[pup] + adll_idx) = current adll !!! */
+                                               comp_val =
+                                                   (ADLL_MAX -
+                                                    (centralization_high_limit
+                                                     [pup] + adll_idx));
+
+                                               DEBUG_DQS_C
+                                                   ("DDR3 - DQS - Special I - Pup - ",
+                                                    pup, 1);
+                                               DEBUG_DQS_C
+                                                   (" comp_val = ",
+                                                    comp_val, 2);
+
+                                               if (comp_val <
+                                                   special_res[pup]) {
+                                                       special_res[pup] =
+                                                           comp_val;
+                                                       centralization_low_limit
+                                                           [pup] =
+                                                           (-1) *
+                                                           comp_val;
+
+                                                       DEBUG_DQS_C
+                                                           ("DDR3 - DQS - Special I - Pup - ",
+                                                            pup, 1);
+                                                       DEBUG_DQS_C
+                                                           (" Changed Low limit to ",
+                                                            centralization_low_limit
+                                                            [pup], 2);
+                                               }
+                                       }
+                               }
+                       }
+
+                       /*
+                        * Did all PUP found missing window?
+                        * Check for each pup if adll (different for each pup)
+                        * reach maximum if reach max value - lock the pup
+                        * if not - increment (Move to right one phase - ADLL)
+                        * dqs RX delay
+                        */
+                       adll_idx++;
+                       for (pup = 0; pup < max_pup; pup++) {
+                               if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+                                       /* Check only unlocked pups */
+                                       if ((centralization_high_limit[pup] +
+                                            adll_idx) >= ADLL_MAX) {
+                                               /* reach maximum - lock the pup */
+                                               DEBUG_DQS_C("DDR3 - DQS - Special I - reach maximum - lock pup ",
+                                                           pup, 1);
+                                               unlock_pup &= ~(1 << pup);
+                                       } else {
+                                               /* Didn't reach maximum - increment ADLL */
+                                               ddr3_write_pup_reg(PUP_DQS_RD,
+                                                                  cs,
+                                                                  pup +
+                                                                  (ecc *
+                                                                   ECC_PUP), 0,
+                                                                  (centralization_high_limit
+                                                                   [pup] +
+                                                                   adll_idx));
+                                       }
+                               }
+                       }
+               } while (unlock_pup != 0);
+       }
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_special_pattern_ii_search
+ * Desc:     Execute special pattern high limit search.
+ * Args:
+ *           special_pattern_pup  The pups that need the special search
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
+                                  int is_tx, u32 special_pattern_pup)
+{
+       u32 victim_dq;          /* loop index - victim DQ */
+       u32 adll_idx;
+       u32 pup;
+       u32 unlock_pup;         /* bit array of the unlock pups  */
+       u32 first_fail; /* bit array - of pups that  get first fail */
+       u32 new_lockup_pup;     /* bit array of compare failed pups */
+       u32 pass_pup;           /* bit array of compare pass pup */
+       u32 sdram_offset;
+       u32 max_pup;
+       u32 comp_val;
+       u32 special_res[MAX_PUP_NUM];   /* hold tmp results */
+
+       DEBUG_DQS_S("DDR3 - DQS - Special Pattern II Search - Starting\n");
+
+       max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
+
+       /* init the tmporary results to max ADLL value */
+       for (pup = 0; pup < max_pup; pup++)
+               special_res[pup] = ADLL_MAX;
+
+       sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS;
+
+       /* run special pattern for all DQ - use the same pattern */
+       for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+               unlock_pup = special_pattern_pup;
+               first_fail = 0;
+
+               for (pup = 0; pup < max_pup; pup++) {
+                       /* Set adll value per PUP. adll = 0 */
+                       if (IS_PUP_ACTIVE(unlock_pup, pup)) {
+                               /* Only for pups that need special search */
+                               ddr3_write_pup_reg(PUP_DQS_RD, cs,
+                                                  pup + (ecc * ECC_PUP), 0,
+                                                  ADLL_MIN);
+                       }
+               }
+
+               adll_idx = 0;
+               do {
+                       /*
+                        * Perform read and compare simultaneously for all
+                        * un-locked MC use the special pattern mask
+                        */
+                       new_lockup_pup = 0;
+
+                       if (MV_OK != ddr3_sdram_dqs_compare(
+                                   dram_info, unlock_pup, &new_lockup_pup,
+                                   special_pattern[victim_dq],
+                                   LEN_SPECIAL_PATTERN,
+                                   sdram_offset, 0, 0, NULL, 0))
+                               return MV_FAIL;
+
+                       DEBUG_DQS_S("DDR3 - DQS - Special II - ADLL value is ");
+                       DEBUG_DQS_D(adll_idx, 2);
+                       DEBUG_DQS_S("unlock_pup ");
+                       DEBUG_DQS_D(unlock_pup, 1);
+                       DEBUG_DQS_S("new_lockup_pup ");
+                       DEBUG_DQS_D(new_lockup_pup, 1);
+                       DEBUG_DQS_S("\n");
+
+                       if (unlock_pup != new_lockup_pup) {
+                               DEBUG_DQS_S("DDR3 - DQS - Special II - Some Pup passed!\n");
+                       }
+
+                       /* Search for pups with passed compare & already fail */
+                       pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
+                       first_fail |= new_lockup_pup;
+                       unlock_pup &= ~pass_pup;
+
+                       /* Get pass pups */
+                       if (pass_pup != 0) {
+                               for (pup = 0; pup < max_pup; pup++) {
+                                       if (IS_PUP_ACTIVE(pass_pup, pup) ==
+                                           1) {
+                                               /* If pup passed and has first fail = 1 */
+                                               /* keep min value of ADLL max value - current adll */
+                                               /* (adll_idx) = current adll !!! */
+                                               comp_val = adll_idx;
+
+                                               DEBUG_DQS_C("DDR3 - DQS - Special II - Pup - ",
+                                                           pup, 1);
+                                               DEBUG_DQS_C(" comp_val = ",
+                                                           comp_val, 1);
+
+                                               if (comp_val <
+                                                   special_res[pup]) {
+                                                       special_res[pup] =
+                                                           comp_val;
+                                                       centralization_high_limit
+                                                           [pup] =
+                                                           ADLL_MAX +
+                                                           comp_val;
+
+                                                       DEBUG_DQS_C
+                                                           ("DDR3 - DQS - Special II - Pup - ",
+                                                            pup, 1);
+                                                       DEBUG_DQS_C
+                                                           (" Changed High limit to ",
+                                                            centralization_high_limit
+                                                            [pup], 2);
+                                               }
+                                       }
+                               }
+                       }
+
+                       /*
+                        * Did all PUP found missing window?
+                        * Check for each pup if adll (different for each pup)
+                        * reach maximum if reach max value - lock the pup
+                        * if not - increment (Move to right one phase - ADLL)
+                        * dqs RX delay
+                        */
+                       adll_idx++;
+                       for (pup = 0; pup < max_pup; pup++) {
+                               if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+                                       /* Check only unlocked pups */
+                                       if ((adll_idx) >= ADLL_MAX) {
+                                               /* Reach maximum - lock the pup */
+                                               DEBUG_DQS_C("DDR3 - DQS - Special II - reach maximum - lock pup ",
+                                                           pup, 1);
+                                               unlock_pup &= ~(1 << pup);
+                                       } else {
+                                               /* Didn't reach maximum - increment ADLL */
+                                               ddr3_write_pup_reg(PUP_DQS_RD,
+                                                                  cs,
+                                                                  pup +
+                                                                  (ecc *
+                                                                   ECC_PUP), 0,
+                                                                  (adll_idx));
+                                       }
+                               }
+                       }
+               } while (unlock_pup != 0);
+       }
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_set_dqs_centralization_results
+ * Desc:     Set to HW the DQS centralization phase results.
+ * Args:
+ *           is_tx             Indicates whether to set Tx or RX results
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs,
+                                       u32 ecc, int is_tx)
+{
+       u32 pup, pup_num;
+       int addl_val;
+       u32 max_pup;
+
+       max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
+
+       DEBUG_DQS_RESULTS_S("\n############ LOG LEVEL 2(Windows margins) ############\n");;
+
+       if (is_tx) {
+               DEBUG_DQS_RESULTS_C("DDR3 - DQS TX - Set Dqs Centralization Results - CS: ",
+                                   cs, 1);
+       } else {
+               DEBUG_DQS_RESULTS_C("DDR3 - DQS RX - Set Dqs Centralization Results - CS: ",
+                                   cs, 1);
+       }
+
+       /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
+       DEBUG_DQS_RESULTS_S("\nDQS    LOW     HIGH     WIN-SIZE      Set\n");
+       DEBUG_DQS_RESULTS_S("==============================================\n");
+       for (pup = 0; pup < max_pup; pup++) {
+               addl_val = (centralization_high_limit[pup] +
+                           centralization_low_limit[pup]) / 2;
+
+               pup_num = pup * (1 - ecc) + ecc * ECC_PUP;
+
+               DEBUG_DQS_RESULTS_D(pup_num, 1);
+               DEBUG_DQS_RESULTS_S("     0x");
+               DEBUG_DQS_RESULTS_D(centralization_low_limit[pup], 2);
+               DEBUG_DQS_RESULTS_S("      0x");
+               DEBUG_DQS_RESULTS_D(centralization_high_limit[pup], 2);
+               DEBUG_DQS_RESULTS_S("      0x");
+               DEBUG_DQS_RESULTS_D(centralization_high_limit[pup] -
+                                   centralization_low_limit[pup], 2);
+               DEBUG_DQS_RESULTS_S("       0x");
+               DEBUG_DQS_RESULTS_D(addl_val, 2);
+               DEBUG_DQS_RESULTS_S("\n");
+
+               if (addl_val < ADLL_MIN) {
+                       addl_val = ADLL_MIN;
+                       DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MIN (since it was lower than 0)\n");
+               }
+
+               if (addl_val > ADLL_MAX) {
+                       addl_val = ADLL_MAX;
+                       DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MAX (since it was higher than 31)\n");
+               }
+
+               if (is_tx) {
+                       ddr3_write_pup_reg(PUP_DQS_WR, cs, pup_num, 0,
+                                          addl_val +
+                                          dram_info->wl_val[cs][pup_num][D]);
+               } else {
+                       ddr3_write_pup_reg(PUP_DQS_RD, cs, pup_num, 0,
+                                          addl_val);
+               }
+       }
+
+       return MV_OK;
+}
+
+/*
+ * Set training patterns
+ */
+int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info)
+{
+       u32 cs, cs_count, cs_tmp, victim_dq;
+       u32 sdram_addr;
+       u32 *pattern_ptr;
+
+       /* Loop for each CS */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       cs_count = 0;
+                       for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
+                               if (dram_info->cs_ena & (1 << cs_tmp))
+                                       cs_count++;
+                       }
+
+                       /* Init killer pattern */
+                       sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
+                                     SDRAM_DQS_RX_OFFS);
+                       for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+                               pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
+                                                                     victim_dq);
+                               if (MV_OK != ddr3_sdram_dqs_compare(
+                                           dram_info, (u32)NULL, NULL,
+                                           pattern_ptr, LEN_KILLER_PATTERN,
+                                           sdram_addr + LEN_KILLER_PATTERN *
+                                           4 * victim_dq, 1, 0, NULL,
+                                           0))
+                                       return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
+                       }
+
+                       /* Init special-killer pattern */
+                       sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
+                                     SDRAM_DQS_RX_SPECIAL_OFFS);
+                       for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
+                               if (MV_OK != ddr3_sdram_dqs_compare(
+                                           dram_info, (u32)NULL, NULL,
+                                           special_pattern[victim_dq],
+                                           LEN_KILLER_PATTERN, sdram_addr +
+                                           LEN_KILLER_PATTERN * 4 * victim_dq,
+                                           1, 0, NULL, 0))
+                                       return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
+                       }
+               }
+       }
+
+       return MV_OK;
+}
diff --git a/drivers/ddr/mvebu/ddr3_hw_training.c b/drivers/ddr/mvebu/ddr3_hw_training.c
new file mode 100644 (file)
index 0000000..a8c5e6a
--- /dev/null
@@ -0,0 +1,1115 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_init.h"
+#include "ddr3_hw_training.h"
+#include "xor.h"
+
+#ifdef MV88F78X60
+#include "ddr3_patterns_64bit.h"
+#else
+#include "ddr3_patterns_16bit.h"
+#if defined(MV88F672X)
+#include "ddr3_patterns_16bit.h"
+#endif
+#endif
+
+/*
+ * Debug
+ */
+
+#define DEBUG_MAIN_C(s, d, l) \
+       DEBUG_MAIN_S(s); DEBUG_MAIN_D(d, l); DEBUG_MAIN_S("\n")
+#define DEBUG_MAIN_FULL_C(s, d, l) \
+       DEBUG_MAIN_FULL_S(s); DEBUG_MAIN_FULL_D(d, l); DEBUG_MAIN_FULL_S("\n")
+
+#ifdef MV_DEBUG_MAIN
+#define DEBUG_MAIN_S(s)                        puts(s)
+#define DEBUG_MAIN_D(d, l)             printf("%x", d)
+#else
+#define DEBUG_MAIN_S(s)
+#define DEBUG_MAIN_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_MAIN_FULL
+#define DEBUG_MAIN_FULL_S(s)           puts(s)
+#define DEBUG_MAIN_FULL_D(d, l)                printf("%x", d)
+#else
+#define DEBUG_MAIN_FULL_S(s)
+#define DEBUG_MAIN_FULL_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_SUSPEND_RESUME
+#define DEBUG_SUSPEND_RESUME_S(s)      puts(s)
+#define DEBUG_SUSPEND_RESUME_D(d, l)   printf("%x", d)
+#else
+#define DEBUG_SUSPEND_RESUME_S(s)
+#define DEBUG_SUSPEND_RESUME_D(d, l)
+#endif
+
+static u32 ddr3_sw_wl_rl_debug;
+static u32 ddr3_run_pbs = 1;
+
+void ddr3_print_version(void)
+{
+       puts("DDR3 Training Sequence - Ver 5.7.");
+}
+
+void ddr3_set_sw_wl_rl_debug(u32 val)
+{
+       ddr3_sw_wl_rl_debug = val;
+}
+
+void ddr3_set_pbs(u32 val)
+{
+       ddr3_run_pbs = val;
+}
+
+int ddr3_hw_training(u32 target_freq, u32 ddr_width, int xor_bypass,
+                    u32 scrub_offs, u32 scrub_size, int dqs_clk_aligned,
+                    int debug_mode, int reg_dimm_skip_wl)
+{
+       /* A370 has no PBS mechanism */
+       __maybe_unused u32 first_loop_flag = 0;
+       u32 freq, reg;
+       MV_DRAM_INFO dram_info;
+       int ratio_2to1 = 0;
+       int tmp_ratio = 1;
+       int status;
+
+       if (debug_mode)
+               DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 1\n");
+
+       memset(&dram_info, 0, sizeof(dram_info));
+       dram_info.num_cs = ddr3_get_cs_num_from_reg();
+       dram_info.cs_ena = ddr3_get_cs_ena_from_reg();
+       dram_info.target_frequency = target_freq;
+       dram_info.ddr_width = ddr_width;
+       dram_info.num_of_std_pups = ddr_width / PUP_SIZE;
+       dram_info.rl400_bug = 0;
+       dram_info.multi_cs_mr_support = 0;
+#ifdef MV88F67XX
+       dram_info.rl400_bug = 1;
+#endif
+
+       /* Ignore ECC errors - if ECC is enabled */
+       reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+       if (reg & (1 << REG_SDRAM_CONFIG_ECC_OFFS)) {
+               dram_info.ecc_ena = 1;
+               reg |= (1 << REG_SDRAM_CONFIG_IERR_OFFS);
+               reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+       } else {
+               dram_info.ecc_ena = 0;
+       }
+
+       reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+       if (reg & (1 << REG_SDRAM_CONFIG_REGDIMM_OFFS))
+               dram_info.reg_dimm = 1;
+       else
+               dram_info.reg_dimm = 0;
+
+       dram_info.num_of_total_pups = ddr_width / PUP_SIZE + dram_info.ecc_ena;
+
+       /* Get target 2T value */
+       reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+       dram_info.mode_2t = (reg >> REG_DUNIT_CTRL_LOW_2T_OFFS) &
+               REG_DUNIT_CTRL_LOW_2T_MASK;
+
+       /* Get target CL value */
+#ifdef MV88F67XX
+       reg = reg_read(REG_DDR3_MR0_ADDR) >> 2;
+#else
+       reg = reg_read(REG_DDR3_MR0_CS_ADDR) >> 2;
+#endif
+
+       reg = (((reg >> 1) & 0xE) | (reg & 0x1)) & 0xF;
+       dram_info.cl = ddr3_valid_cl_to_cl(reg);
+
+       /* Get target CWL value */
+#ifdef MV88F67XX
+       reg = reg_read(REG_DDR3_MR2_ADDR) >> REG_DDR3_MR2_CWL_OFFS;
+#else
+       reg = reg_read(REG_DDR3_MR2_CS_ADDR) >> REG_DDR3_MR2_CWL_OFFS;
+#endif
+
+       reg &= REG_DDR3_MR2_CWL_MASK;
+       dram_info.cwl = reg;
+#if !defined(MV88F67XX)
+       /* A370 has no PBS mechanism */
+#if defined(MV88F78X60)
+       if ((dram_info.target_frequency > DDR_400) && (ddr3_run_pbs))
+               first_loop_flag = 1;
+#else
+       /* first_loop_flag = 1; skip mid freq at ALP/A375 */
+       if ((dram_info.target_frequency > DDR_400) && (ddr3_run_pbs) &&
+           (mv_ctrl_revision_get() >= UMC_A0))
+               first_loop_flag = 1;
+       else
+               first_loop_flag = 0;
+#endif
+#endif
+
+       freq = dram_info.target_frequency;
+
+       /* Set ODT to always on */
+       ddr3_odt_activate(1);
+
+       /* Init XOR */
+       mv_sys_xor_init(&dram_info);
+
+       /* Get DRAM/HCLK ratio */
+       if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS))
+               ratio_2to1 = 1;
+
+       /*
+        * Xor Bypass - ECC support in AXP is currently available for 1:1
+        * modes frequency modes.
+        * Not all frequency modes support the ddr3 training sequence
+        * (Only 1200/300).
+        * Xor Bypass allows using the Xor initializations and scrubbing
+        * inside the ddr3 training sequence without running the training
+        * itself.
+        */
+       if (xor_bypass == 0) {
+               if (ddr3_run_pbs) {
+                       DEBUG_MAIN_S("DDR3 Training Sequence - Run with PBS.\n");
+               } else {
+                       DEBUG_MAIN_S("DDR3 Training Sequence - Run without PBS.\n");
+               }
+
+               if (dram_info.target_frequency > DFS_MARGIN) {
+                       tmp_ratio = 0;
+                       freq = DDR_100;
+
+                       if (dram_info.reg_dimm == 1)
+                               freq = DDR_300;
+
+                       if (MV_OK != ddr3_dfs_high_2_low(freq, &dram_info)) {
+                               /* Set low - 100Mhz DDR Frequency by HW */
+                               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Dfs High2Low)\n");
+                               return MV_DDR3_TRAINING_ERR_DFS_H2L;
+                       }
+
+                       if ((dram_info.reg_dimm == 1) &&
+                           (reg_dimm_skip_wl == 0)) {
+                               if (MV_OK !=
+                                   ddr3_write_leveling_hw_reg_dimm(freq,
+                                                                   &dram_info))
+                                       DEBUG_MAIN_S("DDR3 Training Sequence - Registered DIMM Low WL - SKIP\n");
+                       }
+
+                       if (ddr3_get_log_level() >= MV_LOG_LEVEL_1)
+                               ddr3_print_freq(freq);
+
+                       if (debug_mode)
+                               DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 2\n");
+               } else {
+                       if (!dqs_clk_aligned) {
+#ifdef MV88F67XX
+                               /*
+                                * If running training sequence without DFS,
+                                * we must run Write leveling before writing
+                                * the patterns
+                                */
+
+                               /*
+                                * ODT - Multi CS system use SW WL,
+                                * Single CS System use HW WL
+                                */
+                               if (dram_info.cs_ena > 1) {
+                                       if (MV_OK !=
+                                           ddr3_write_leveling_sw(
+                                                   freq, tmp_ratio,
+                                                   &dram_info)) {
+                                               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Sw)\n");
+                                               return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+                                       }
+                               } else {
+                                       if (MV_OK !=
+                                           ddr3_write_leveling_hw(freq,
+                                                                  &dram_info)) {
+                                               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+                                               return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+                                       }
+                               }
+#else
+                               if (MV_OK != ddr3_write_leveling_hw(
+                                           freq, &dram_info)) {
+                                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+                                       if (ddr3_sw_wl_rl_debug) {
+                                               if (MV_OK !=
+                                                   ddr3_write_leveling_sw(
+                                                           freq, tmp_ratio,
+                                                           &dram_info)) {
+                                                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Sw)\n");
+                                                       return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+                                               }
+                                       } else {
+                                               return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+                                       }
+                               }
+#endif
+                       }
+
+                       if (debug_mode)
+                               DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 3\n");
+               }
+
+               if (MV_OK != ddr3_load_patterns(&dram_info, 0)) {
+                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Loading Patterns)\n");
+                       return MV_DDR3_TRAINING_ERR_LOAD_PATTERNS;
+               }
+
+               /*
+                * TODO:
+                * The mainline U-Boot port of the bin_hdr DDR training code
+                * needs a delay of minimum 20ms here (10ms is a bit too short
+                * and the CPU hangs). The bin_hdr code doesn't have this delay.
+                * To be save here, lets add a delay of 50ms here.
+                *
+                * Tested on the Marvell DB-MV784MP-GP board
+                */
+               mdelay(50);
+
+               do {
+                       freq = dram_info.target_frequency;
+                       tmp_ratio = ratio_2to1;
+                       DEBUG_MAIN_FULL_S("DDR3 Training Sequence - DEBUG - 4\n");
+
+#if defined(MV88F78X60)
+                       /*
+                        * There is a difference on the DFS frequency at the
+                        * first iteration of this loop
+                        */
+                       if (first_loop_flag) {
+                               freq = DDR_400;
+                               tmp_ratio = 0;
+                       }
+#endif
+
+                       if (MV_OK != ddr3_dfs_low_2_high(freq, tmp_ratio,
+                                                        &dram_info)) {
+                               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Dfs Low2High)\n");
+                               return MV_DDR3_TRAINING_ERR_DFS_H2L;
+                       }
+
+                       if (ddr3_get_log_level() >= MV_LOG_LEVEL_1) {
+                               ddr3_print_freq(freq);
+                       }
+
+                       if (debug_mode)
+                               DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 5\n");
+
+                       /* Write leveling */
+                       if (!dqs_clk_aligned) {
+#ifdef MV88F67XX
+                               /*
+                                * ODT - Multi CS system that not support Multi
+                                * CS MRS commands must use SW WL
+                                */
+                               if (dram_info.cs_ena > 1) {
+                                       if (MV_OK != ddr3_write_leveling_sw(
+                                                   freq, tmp_ratio, &dram_info)) {
+                                               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Sw)\n");
+                                               return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+                                       }
+                               } else {
+                                       if (MV_OK != ddr3_write_leveling_hw(
+                                                   freq, &dram_info)) {
+                                               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+                                               return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+                                       }
+                               }
+#else
+                               if ((dram_info.reg_dimm == 1) &&
+                                   (freq == DDR_400)) {
+                                       if (reg_dimm_skip_wl == 0) {
+                                               if (MV_OK != ddr3_write_leveling_hw_reg_dimm(
+                                                           freq, &dram_info))
+                                                       DEBUG_MAIN_S("DDR3 Training Sequence - Registered DIMM WL - SKIP\n");
+                                       }
+                               } else {
+                                       if (MV_OK != ddr3_write_leveling_hw(
+                                                   freq, &dram_info)) {
+                                               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+                                               if (ddr3_sw_wl_rl_debug) {
+                                                       if (MV_OK != ddr3_write_leveling_sw(
+                                                                   freq, tmp_ratio, &dram_info)) {
+                                                               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Sw)\n");
+                                                               return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+                                                       }
+                                               } else {
+                                                       return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+                                               }
+                                       }
+                               }
+#endif
+                               if (debug_mode)
+                                       DEBUG_MAIN_S
+                                           ("DDR3 Training Sequence - DEBUG - 6\n");
+                       }
+
+                       /* Read Leveling */
+                       /*
+                        * Armada 370 - Support for HCLK @ 400MHZ - must use
+                        * SW read leveling
+                        */
+                       if (freq == DDR_400 && dram_info.rl400_bug) {
+                               status = ddr3_read_leveling_sw(freq, tmp_ratio,
+                                                      &dram_info);
+                               if (MV_OK != status) {
+                                       DEBUG_MAIN_S
+                                           ("DDR3 Training Sequence - FAILED (Read Leveling Sw)\n");
+                                       return status;
+                               }
+                       } else {
+                               if (MV_OK != ddr3_read_leveling_hw(
+                                           freq, &dram_info)) {
+                                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Read Leveling Hw)\n");
+                                       if (ddr3_sw_wl_rl_debug) {
+                                               if (MV_OK != ddr3_read_leveling_sw(
+                                                           freq, tmp_ratio,
+                                                           &dram_info)) {
+                                                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Read Leveling Sw)\n");
+                                                       return MV_DDR3_TRAINING_ERR_WR_LVL_SW;
+                                               }
+                                       } else {
+                                               return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+                                       }
+                               }
+                       }
+
+                       if (debug_mode)
+                               DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 7\n");
+
+                       if (MV_OK != ddr3_wl_supplement(&dram_info)) {
+                               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hi-Freq Sup)\n");
+                               return MV_DDR3_TRAINING_ERR_WR_LVL_HI_FREQ;
+                       }
+
+                       if (debug_mode)
+                               DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 8\n");
+#if !defined(MV88F67XX)
+                       /* A370 has no PBS mechanism */
+#if defined(MV88F78X60) || defined(MV88F672X)
+                       if (first_loop_flag == 1) {
+                               first_loop_flag = 0;
+
+                               status = MV_OK;
+                               status = ddr3_pbs_rx(&dram_info);
+                               if (MV_OK != status) {
+                                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (PBS RX)\n");
+                                       return status;
+                               }
+
+                               if (debug_mode)
+                                       DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 9\n");
+
+                               status = ddr3_pbs_tx(&dram_info);
+                               if (MV_OK != status) {
+                                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (PBS TX)\n");
+                                       return status;
+                               }
+
+                               if (debug_mode)
+                                       DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 10\n");
+                       }
+#endif
+#endif
+               } while (freq != dram_info.target_frequency);
+
+               status = ddr3_dqs_centralization_rx(&dram_info);
+               if (MV_OK != status) {
+                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (DQS Centralization RX)\n");
+                       return status;
+               }
+
+               if (debug_mode)
+                       DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 11\n");
+
+               status = ddr3_dqs_centralization_tx(&dram_info);
+               if (MV_OK != status) {
+                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (DQS Centralization TX)\n");
+                       return status;
+               }
+
+               if (debug_mode)
+                       DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 12\n");
+       }
+
+       ddr3_set_performance_params(&dram_info);
+
+       if (dram_info.ecc_ena) {
+               /* Need to SCRUB the DRAM memory area to load U-boot */
+               mv_sys_xor_finish();
+               dram_info.num_cs = 1;
+               dram_info.cs_ena = 1;
+               mv_sys_xor_init(&dram_info);
+               mv_xor_mem_init(0, scrub_offs, scrub_size, 0xdeadbeef,
+                               0xdeadbeef);
+
+               /* Wait for previous transfer completion */
+               while (mv_xor_state_get(0) != MV_IDLE)
+                       ;
+
+               if (debug_mode)
+                       DEBUG_MAIN_S("DDR3 Training Sequence - DEBUG - 13\n");
+       }
+
+       /* Return XOR State */
+       mv_sys_xor_finish();
+
+#if defined(MV88F78X60)
+       /* Save training results in memeory for resume state */
+       ddr3_save_training(&dram_info);
+#endif
+       /* Clear ODT always on */
+       ddr3_odt_activate(0);
+
+       /* Configure Dynamic read ODT */
+       ddr3_odt_read_dynamic_config(&dram_info);
+
+       return MV_OK;
+}
+
+void ddr3_set_performance_params(MV_DRAM_INFO *dram_info)
+{
+       u32 twr2wr, trd2rd, trd2wr_wr2rd;
+       u32 tmp1, tmp2, reg;
+
+       DEBUG_MAIN_FULL_C("Max WL Phase: ", dram_info->wl_max_phase, 2);
+       DEBUG_MAIN_FULL_C("Min WL Phase: ", dram_info->wl_min_phase, 2);
+       DEBUG_MAIN_FULL_C("Max RL Phase: ", dram_info->rl_max_phase, 2);
+       DEBUG_MAIN_FULL_C("Min RL Phase: ", dram_info->rl_min_phase, 2);
+
+       if (dram_info->wl_max_phase < 2)
+               twr2wr = 0x2;
+       else
+               twr2wr = 0x3;
+
+       trd2rd = 0x1 + (dram_info->rl_max_phase + 1) / 2 +
+               (dram_info->rl_max_phase + 1) % 2;
+
+       tmp1 = (dram_info->rl_max_phase - dram_info->wl_min_phase) / 2 +
+               (((dram_info->rl_max_phase - dram_info->wl_min_phase) % 2) >
+                0 ? 1 : 0);
+       tmp2 = (dram_info->wl_max_phase - dram_info->rl_min_phase) / 2 +
+               ((dram_info->wl_max_phase - dram_info->rl_min_phase) % 2 >
+                0 ? 1 : 0);
+       trd2wr_wr2rd = (tmp1 >= tmp2) ? tmp1 : tmp2;
+
+       trd2wr_wr2rd += 2;
+       trd2rd += 2;
+       twr2wr += 2;
+
+       DEBUG_MAIN_FULL_C("WR 2 WR: ", twr2wr, 2);
+       DEBUG_MAIN_FULL_C("RD 2 RD: ", trd2rd, 2);
+       DEBUG_MAIN_FULL_C("RD 2 WR / WR 2 RD: ", trd2wr_wr2rd, 2);
+
+       reg = reg_read(REG_SDRAM_TIMING_HIGH_ADDR);
+
+       reg &= ~(REG_SDRAM_TIMING_H_W2W_MASK << REG_SDRAM_TIMING_H_W2W_OFFS);
+       reg |= ((twr2wr & REG_SDRAM_TIMING_H_W2W_MASK) <<
+               REG_SDRAM_TIMING_H_W2W_OFFS);
+
+       reg &= ~(REG_SDRAM_TIMING_H_R2R_MASK << REG_SDRAM_TIMING_H_R2R_OFFS);
+       reg &= ~(REG_SDRAM_TIMING_H_R2R_H_MASK <<
+                REG_SDRAM_TIMING_H_R2R_H_OFFS);
+       reg |= ((trd2rd & REG_SDRAM_TIMING_H_R2R_MASK) <<
+               REG_SDRAM_TIMING_H_R2R_OFFS);
+       reg |= (((trd2rd >> 2) & REG_SDRAM_TIMING_H_R2R_H_MASK) <<
+               REG_SDRAM_TIMING_H_R2R_H_OFFS);
+
+       reg &= ~(REG_SDRAM_TIMING_H_R2W_W2R_MASK <<
+                REG_SDRAM_TIMING_H_R2W_W2R_OFFS);
+       reg &= ~(REG_SDRAM_TIMING_H_R2W_W2R_H_MASK <<
+                REG_SDRAM_TIMING_H_R2W_W2R_H_OFFS);
+       reg |= ((trd2wr_wr2rd & REG_SDRAM_TIMING_H_R2W_W2R_MASK) <<
+               REG_SDRAM_TIMING_H_R2W_W2R_OFFS);
+       reg |= (((trd2wr_wr2rd >> 2) & REG_SDRAM_TIMING_H_R2W_W2R_H_MASK) <<
+               REG_SDRAM_TIMING_H_R2W_W2R_H_OFFS);
+
+       reg_write(REG_SDRAM_TIMING_HIGH_ADDR, reg);
+}
+
+/*
+ * Perform DDR3 PUP Indirect Write
+ */
+void ddr3_write_pup_reg(u32 mode, u32 cs, u32 pup, u32 phase, u32 delay)
+{
+       u32 reg = 0;
+
+       if (pup == PUP_BC)
+               reg |= (1 << REG_PHY_BC_OFFS);
+       else
+               reg |= (pup << REG_PHY_PUP_OFFS);
+
+       reg |= ((0x4 * cs + mode) << REG_PHY_CS_OFFS);
+       reg |= (phase << REG_PHY_PHASE_OFFS) | delay;
+
+       if (mode == PUP_WL_MODE)
+               reg |= ((INIT_WL_DELAY + delay) << REG_PHY_DQS_REF_DLY_OFFS);
+
+       reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);      /* 0x16A0 */
+       reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+       reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);      /* 0x16A0 */
+
+       do {
+               reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+                       REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+       } while (reg);  /* Wait for '0' to mark the end of the transaction */
+
+       /* If read Leveling mode - need to write to register 3 separetly */
+       if (mode == PUP_RL_MODE) {
+               reg = 0;
+
+               if (pup == PUP_BC)
+                       reg |= (1 << REG_PHY_BC_OFFS);
+               else
+                       reg |= (pup << REG_PHY_PUP_OFFS);
+
+               reg |= ((0x4 * cs + mode + 1) << REG_PHY_CS_OFFS);
+               reg |= (INIT_RL_DELAY);
+
+               reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg); /* 0x16A0 */
+               reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+               reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg); /* 0x16A0 */
+
+               do {
+                       reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+                               REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+               } while (reg);
+       }
+}
+
+/*
+ * Perform DDR3 PUP Indirect Read
+ */
+u32 ddr3_read_pup_reg(u32 mode, u32 cs, u32 pup)
+{
+       u32 reg;
+
+       reg = (pup << REG_PHY_PUP_OFFS) |
+               ((0x4 * cs + mode) << REG_PHY_CS_OFFS);
+       reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);      /* 0x16A0 */
+
+       reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_RD;
+       reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);      /* 0x16A0 */
+
+       do {
+               reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+                       REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+       } while (reg);  /* Wait for '0' to mark the end of the transaction */
+
+       return reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR);     /* 0x16A0 */
+}
+
+/*
+ * Set training patterns
+ */
+int ddr3_load_patterns(MV_DRAM_INFO *dram_info, int resume)
+{
+       u32 reg;
+
+       /* Enable SW override - Required for the ECC Pup */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+
+       /* [0] = 1 - Enable SW override  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       if (resume == 0) {
+#if defined(MV88F78X60) || defined(MV88F672X)
+               ddr3_load_pbs_patterns(dram_info);
+#endif
+               ddr3_load_dqs_patterns(dram_info);
+       }
+
+       /* Disable SW override - Must be in a different stage */
+       /* [0]=0 - Enable SW override  */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+               (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+       reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+       /* Set Base Addr */
+#if defined(MV88F67XX)
+       reg_write(REG_DRAM_TRAINING_PATTERN_BASE_ADDR, 0);
+#else
+       if (resume == 0)
+               reg_write(REG_DRAM_TRAINING_PATTERN_BASE_ADDR, 0);
+       else
+               reg_write(REG_DRAM_TRAINING_PATTERN_BASE_ADDR,
+                         RESUME_RL_PATTERNS_ADDR);
+#endif
+
+       /* Set Patterns */
+       if (resume == 0) {
+               reg = (dram_info->cs_ena << REG_DRAM_TRAINING_CS_OFFS) |
+                       (1 << REG_DRAM_TRAINING_PATTERNS_OFFS);
+       } else {
+               reg = (0x1 << REG_DRAM_TRAINING_CS_OFFS) |
+                       (1 << REG_DRAM_TRAINING_PATTERNS_OFFS);
+       }
+
+       reg |= (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+
+       reg_write(REG_DRAM_TRAINING_ADDR, reg);
+
+       udelay(100);
+
+       /* Check if Successful */
+       if (reg_read(REG_DRAM_TRAINING_ADDR) &
+           (1 << REG_DRAM_TRAINING_ERROR_OFFS))
+               return MV_OK;
+       else
+               return MV_FAIL;
+}
+
+#if !defined(MV88F67XX)
+/*
+ * Name:     ddr3_save_training(MV_DRAM_INFO *dram_info)
+ * Desc:     saves the training results to memeory (RL,WL,PBS,Rx/Tx
+ *           Centeralization)
+ * Args:     MV_DRAM_INFO *dram_info
+ * Notes:
+ * Returns:  None.
+ */
+void ddr3_save_training(MV_DRAM_INFO *dram_info)
+{
+       u32 val, pup, tmp_cs, cs, i, dq;
+       u32 crc = 0;
+       u32 regs = 0;
+       u32 *sdram_offset = (u32 *)RESUME_TRAINING_VALUES_ADDR;
+       u32 mode_config[MAX_TRAINING_MODE];
+
+       mode_config[DQS_WR_MODE] = PUP_DQS_WR;
+       mode_config[WL_MODE_] = PUP_WL_MODE;
+       mode_config[RL_MODE_] = PUP_RL_MODE;
+       mode_config[DQS_RD_MODE] = PUP_DQS_RD;
+       mode_config[PBS_TX_DM_MODE] = PUP_PBS_TX_DM;
+       mode_config[PBS_TX_MODE] = PUP_PBS_TX;
+       mode_config[PBS_RX_MODE] = PUP_PBS_RX;
+
+       /* num of training modes */
+       for (i = 0; i < MAX_TRAINING_MODE; i++) {
+               tmp_cs = dram_info->cs_ena;
+               /* num of CS */
+               for (cs = 0; cs < MAX_CS; cs++) {
+                       if (tmp_cs & (1 << cs)) {
+                               /* num of PUPs */
+                               for (pup = 0; pup < dram_info->num_of_total_pups;
+                                    pup++) {
+                                       if (pup == dram_info->num_of_std_pups &&
+                                           dram_info->ecc_ena)
+                                               pup = ECC_PUP;
+                                       if (i == PBS_TX_DM_MODE) {
+                                               /*
+                                                * Change CS bitmask because
+                                                * PBS works only with CS0
+                                                */
+                                               tmp_cs = 0x1;
+                                               val = ddr3_read_pup_reg(
+                                                       mode_config[i], CS0, pup);
+                                       } else if (i == PBS_TX_MODE ||
+                                                  i == PBS_RX_MODE) {
+                                               /*
+                                                * Change CS bitmask because
+                                                * PBS works only with CS0
+                                                */
+                                               tmp_cs = 0x1;
+                                               for (dq = 0; dq <= DQ_NUM;
+                                                    dq++) {
+                                                       val = ddr3_read_pup_reg(
+                                                               mode_config[i] + dq,
+                                                               CS0,
+                                                               pup);
+                                                       (*sdram_offset) = val;
+                                                       crc += *sdram_offset;
+                                                       sdram_offset++;
+                                                       regs++;
+                                               }
+                                               continue;
+                                       } else {
+                                               val = ddr3_read_pup_reg(
+                                                       mode_config[i], cs, pup);
+                                       }
+
+                                       *sdram_offset = val;
+                                       crc += *sdram_offset;
+                                       sdram_offset++;
+                                       regs++;
+                               }
+                       }
+               }
+       }
+
+       *sdram_offset = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+       crc += *sdram_offset;
+       sdram_offset++;
+       regs++;
+       *sdram_offset = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+       crc += *sdram_offset;
+       sdram_offset++;
+       regs++;
+       sdram_offset = (u32 *)NUM_OF_REGISTER_ADDR;
+       *sdram_offset = regs;
+       DEBUG_SUSPEND_RESUME_S("Training Results CheckSum write= ");
+       DEBUG_SUSPEND_RESUME_D(crc, 8);
+       DEBUG_SUSPEND_RESUME_S("\n");
+       sdram_offset = (u32 *)CHECKSUM_RESULT_ADDR;
+       *sdram_offset = crc;
+}
+
+/*
+ * Name:     ddr3_read_training_results()
+ * Desc:     Reads the training results from memeory (RL,WL,PBS,Rx/Tx
+ *           Centeralization)
+ *           and writes them to the relevant registers
+ * Args:     MV_DRAM_INFO *dram_info
+ * Notes:
+ * Returns:  None.
+ */
+int ddr3_read_training_results(void)
+{
+       u32 val, reg, idx, dqs_wr_idx = 0, crc = 0;
+       u32 *sdram_offset = (u32 *)RESUME_TRAINING_VALUES_ADDR;
+       u32 training_val[RESUME_TRAINING_VALUES_MAX] = { 0 };
+       u32 regs = *((u32 *)NUM_OF_REGISTER_ADDR);
+
+       /*
+        * Read Training results & Dunit registers from memory and write
+        * it to an array
+        */
+       for (idx = 0; idx < regs; idx++) {
+               training_val[idx] = *sdram_offset;
+               crc += *sdram_offset;
+               sdram_offset++;
+       }
+
+       sdram_offset = (u32 *)CHECKSUM_RESULT_ADDR;
+
+       if ((*sdram_offset) == crc) {
+               DEBUG_SUSPEND_RESUME_S("Training Results CheckSum read PASS= ");
+               DEBUG_SUSPEND_RESUME_D(crc, 8);
+               DEBUG_SUSPEND_RESUME_S("\n");
+       } else {
+               DEBUG_MAIN_S("Wrong Training Results CheckSum\n");
+               return MV_FAIL;
+       }
+
+       /*
+        * We iterate through all the registers except for the last 2 since
+        * they are Dunit registers (and not PHY registers)
+        */
+       for (idx = 0; idx < (regs - 2); idx++) {
+               val = training_val[idx];
+               reg = (val >> REG_PHY_CS_OFFS) & 0x3F; /*read the phy address */
+
+               /* Check if the values belongs to the DQS WR */
+               if (reg == PUP_WL_MODE) {
+                       /* bit[5:0] in DQS_WR are delay */
+                       val = (training_val[dqs_wr_idx++] & 0x3F);
+                       /*
+                        * bit[15:10] are DQS_WR delay & bit[9:0] are
+                        * WL phase & delay
+                        */
+                       val = (val << REG_PHY_DQS_REF_DLY_OFFS) |
+                               (training_val[idx] & 0x3C003FF);
+                       /* Add Request pending and write operation bits */
+                       val |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+               } else if (reg == PUP_DQS_WR) {
+                       /*
+                        * Do nothing since DQS_WR will be done in PUP_WL_MODE
+                        */
+                       continue;
+               }
+
+               val |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+               reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, val);
+               do {
+                       val = (reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR)) &
+                               REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+               } while (val);  /* Wait for '0' to mark the end of the transaction */
+       }
+
+       /* write last 2 Dunit configurations */
+       val = training_val[idx];
+       reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, val);       /* reg 0x1538 */
+       val = training_val[idx + 1];
+       reg_write(REG_READ_DATA_READY_DELAYS_ADDR, val);        /* reg 0x153c */
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_check_if_resume_mode()
+ * Desc:     Reads the address (0x3000) of the Resume Magic word (0xDEADB002)
+ * Args:     MV_DRAM_INFO *dram_info
+ * Notes:
+ * Returns:  return (magic_word == SUSPEND_MAGIC_WORD)
+ */
+int ddr3_check_if_resume_mode(MV_DRAM_INFO *dram_info, u32 freq)
+{
+       u32 magic_word;
+       u32 *sdram_offset = (u32 *)BOOT_INFO_ADDR;
+
+       if (dram_info->reg_dimm != 1) {
+               /*
+                * Perform write levleling in order initiate the phy with
+                * low frequency
+                */
+               if (MV_OK != ddr3_write_leveling_hw(freq, dram_info)) {
+                       DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Write Leveling Hw)\n");
+                       return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+               }
+       }
+
+       if (MV_OK != ddr3_load_patterns(dram_info, 1)) {
+               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Loading Patterns)\n");
+               return MV_DDR3_TRAINING_ERR_LOAD_PATTERNS;
+       }
+
+       /* Enable CS0 only for RL */
+       dram_info->cs_ena = 0x1;
+
+       /* Perform Read levleling in order to get stable memory */
+       if (MV_OK != ddr3_read_leveling_hw(freq, dram_info)) {
+               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Read Leveling Hw)\n");
+               return MV_DDR3_TRAINING_ERR_WR_LVL_HW;
+       }
+
+       /* Back to relevant CS */
+       dram_info->cs_ena = ddr3_get_cs_ena_from_reg();
+
+       magic_word = *sdram_offset;
+       return magic_word == SUSPEND_MAGIC_WORD;
+}
+
+/*
+ * Name:     ddr3_training_suspend_resume()
+ * Desc:     Execute the Resume state
+ * Args:     MV_DRAM_INFO *dram_info
+ * Notes:
+ * Returns:  return (magic_word == SUSPEND_MAGIC_WORD)
+ */
+int ddr3_training_suspend_resume(MV_DRAM_INFO *dram_info)
+{
+       u32 freq, reg;
+       int tmp_ratio;
+
+       /* Configure DDR */
+       if (MV_OK != ddr3_read_training_results())
+               return MV_FAIL;
+
+       /* Reset read FIFO */
+       reg = reg_read(REG_DRAM_TRAINING_ADDR);
+
+       /* Start Auto Read Leveling procedure */
+       reg |= (1 << REG_DRAM_TRAINING_RL_OFFS);
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg |= ((1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS) +
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS));
+
+       /* [0] = 1 - Enable SW override, [4] = 1 - FIFO reset  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       udelay(2);
+
+       reg = reg_read(REG_DRAM_TRAINING_ADDR);
+       /* Clear Auto Read Leveling procedure */
+       reg &= ~(1 << REG_DRAM_TRAINING_RL_OFFS);
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       /* Return to target frequency */
+       freq = dram_info->target_frequency;
+       tmp_ratio = 1;
+       if (MV_OK != ddr3_dfs_low_2_high(freq, tmp_ratio, dram_info)) {
+               DEBUG_MAIN_S("DDR3 Training Sequence - FAILED (Dfs Low2High)\n");
+               return MV_DDR3_TRAINING_ERR_DFS_H2L;
+       }
+
+       if (dram_info->ecc_ena) {
+               /* Scabbling the RL area pattern and the training area */
+               mv_sys_xor_finish();
+               dram_info->num_cs = 1;
+               dram_info->cs_ena = 1;
+               mv_sys_xor_init(dram_info);
+               mv_xor_mem_init(0, RESUME_RL_PATTERNS_ADDR,
+                               RESUME_RL_PATTERNS_SIZE, 0xFFFFFFFF, 0xFFFFFFFF);
+
+               /* Wait for previous transfer completion */
+
+               while (mv_xor_state_get(0) != MV_IDLE)
+                       ;
+
+               /* Return XOR State */
+               mv_sys_xor_finish();
+       }
+
+       return MV_OK;
+}
+#endif
+
+void ddr3_print_freq(u32 freq)
+{
+       u32 tmp_freq;
+
+       switch (freq) {
+       case 0:
+               tmp_freq = 100;
+               break;
+       case 1:
+               tmp_freq = 300;
+               break;
+       case 2:
+               tmp_freq = 360;
+               break;
+       case 3:
+               tmp_freq = 400;
+               break;
+       case 4:
+               tmp_freq = 444;
+               break;
+       case 5:
+               tmp_freq = 500;
+               break;
+       case 6:
+               tmp_freq = 533;
+               break;
+       case 7:
+               tmp_freq = 600;
+               break;
+       case 8:
+               tmp_freq = 666;
+               break;
+       case 9:
+               tmp_freq = 720;
+               break;
+       case 10:
+               tmp_freq = 800;
+               break;
+       default:
+               tmp_freq = 100;
+       }
+
+       printf("Current frequency is: %dMHz\n", tmp_freq);
+}
+
+int ddr3_get_min_max_read_sample_delay(u32 cs_enable, u32 reg, u32 *min,
+                                      u32 *max, u32 *cs_max)
+{
+       u32 cs, delay;
+
+       *min = 0xFFFFFFFF;
+       *max = 0x0;
+
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if ((cs_enable & (1 << cs)) == 0)
+                       continue;
+
+               delay = ((reg >> (cs * 8)) & 0x1F);
+
+               if (delay < *min)
+                       *min = delay;
+
+               if (delay > *max) {
+                       *max = delay;
+                       *cs_max = cs;
+               }
+       }
+
+       return MV_OK;
+}
+
+int ddr3_get_min_max_rl_phase(MV_DRAM_INFO *dram_info, u32 *min, u32 *max,
+                             u32 cs)
+{
+       u32 pup, reg, phase;
+
+       *min = 0xFFFFFFFF;
+       *max = 0x0;
+
+       for (pup = 0; pup < dram_info->num_of_total_pups; pup++) {
+               reg = ddr3_read_pup_reg(PUP_RL_MODE, cs, pup);
+               phase = ((reg >> 8) & 0x7);
+
+               if (phase < *min)
+                       *min = phase;
+
+               if (phase > *max)
+                       *max = phase;
+       }
+
+       return MV_OK;
+}
+
+int ddr3_odt_activate(int activate)
+{
+       u32 reg, mask;
+
+       mask = (1 << REG_DUNIT_ODT_CTRL_OVRD_OFFS) |
+               (1 << REG_DUNIT_ODT_CTRL_OVRD_VAL_OFFS);
+       /* {0x0000149C}  -   DDR Dunit ODT Control Register */
+       reg = reg_read(REG_DUNIT_ODT_CTRL_ADDR);
+       if (activate)
+               reg |= mask;
+       else
+               reg &= ~mask;
+
+       reg_write(REG_DUNIT_ODT_CTRL_ADDR, reg);
+
+       return MV_OK;
+}
+
+int ddr3_odt_read_dynamic_config(MV_DRAM_INFO *dram_info)
+{
+       u32 min_read_sample_delay, max_read_sample_delay, max_rl_phase;
+       u32 min, max, cs_max;
+       u32 cs_ena, reg;
+
+       reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+       cs_ena = ddr3_get_cs_ena_from_reg();
+
+       /* Get minimum and maximum of read sample delay of all CS */
+       ddr3_get_min_max_read_sample_delay(cs_ena, reg, &min_read_sample_delay,
+                                          &max_read_sample_delay, &cs_max);
+
+       /*
+        * Get minimum and maximum read leveling phase which belongs to the
+        * maximal read sample delay
+        */
+       ddr3_get_min_max_rl_phase(dram_info, &min, &max, cs_max);
+       max_rl_phase = max;
+
+       /* DDR ODT Timing (Low) Register calculation */
+       reg = reg_read(REG_ODT_TIME_LOW_ADDR);
+       reg &= ~(0x1FF << REG_ODT_ON_CTL_RD_OFFS);
+       reg |= (((min_read_sample_delay - 1) & 0xF) << REG_ODT_ON_CTL_RD_OFFS);
+       reg |= (((max_read_sample_delay + 4 + (((max_rl_phase + 1) / 2) + 1)) &
+                0x1F) << REG_ODT_OFF_CTL_RD_OFFS);
+       reg_write(REG_ODT_TIME_LOW_ADDR, reg);
+
+       return MV_OK;
+}
diff --git a/drivers/ddr/mvebu/ddr3_hw_training.h b/drivers/ddr/mvebu/ddr3_hw_training.h
new file mode 100644 (file)
index 0000000..cffa7c4
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __DDR3_TRAINING_H
+#define __DDR3_TRAINING_H
+
+#include "ddr3_init.h"
+
+#ifdef MV88F78X60
+#include "ddr3_axp.h"
+#elif defined(MV88F67XX)
+#include "ddr3_a370.h"
+#elif defined(MV88F672X)
+#include "ddr3_a375.h"
+#endif
+
+/* The following is a list of Marvell status    */
+#define MV_ERROR       (-1)
+#define MV_OK          (0x00)  /* Operation succeeded                   */
+#define MV_FAIL                (0x01)  /* Operation failed                      */
+#define MV_BAD_VALUE   (0x02)  /* Illegal value (general)               */
+#define MV_OUT_OF_RANGE        (0x03)  /* The value is out of range             */
+#define MV_BAD_PARAM   (0x04)  /* Illegal parameter in function called  */
+#define MV_BAD_PTR     (0x05)  /* Illegal pointer value                 */
+#define MV_BAD_SIZE    (0x06)  /* Illegal size                          */
+#define MV_BAD_STATE   (0x07)  /* Illegal state of state machine        */
+#define MV_SET_ERROR   (0x08)  /* Set operation failed                  */
+#define MV_GET_ERROR   (0x09)  /* Get operation failed                  */
+#define MV_CREATE_ERROR        (0x0A)  /* Fail while creating an item           */
+#define MV_NOT_FOUND   (0x0B)  /* Item not found                        */
+#define MV_NO_MORE     (0x0C)  /* No more items found                   */
+#define MV_NO_SUCH     (0x0D)  /* No such item                          */
+#define MV_TIMEOUT     (0x0E)  /* Time Out                              */
+#define MV_NO_CHANGE   (0x0F)  /* Parameter(s) is already in this value */
+#define MV_NOT_SUPPORTED (0x10)        /* This request is not support           */
+#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented*/
+#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized          */
+#define MV_NO_RESOURCE (0x13)  /* Resource not available (memory ...)   */
+#define MV_FULL                (0x14)  /* Item is full (Queue or table etc...)  */
+#define MV_EMPTY       (0x15)  /* Item is empty (Queue or table etc...) */
+#define MV_INIT_ERROR  (0x16)  /* Error occured while INIT process      */
+#define MV_HW_ERROR    (0x17)  /* Hardware error                        */
+#define MV_TX_ERROR    (0x18)  /* Transmit operation not succeeded      */
+#define MV_RX_ERROR    (0x19)  /* Recieve operation not succeeded       */
+#define MV_NOT_READY   (0x1A)  /* The other side is not ready yet       */
+#define MV_ALREADY_EXIST (0x1B)        /* Tried to create existing item         */
+#define MV_OUT_OF_CPU_MEM   (0x1C) /* Cpu memory allocation failed.      */
+#define MV_NOT_STARTED (0x1D)  /* Not started yet                       */
+#define MV_BUSY                (0x1E)  /* Item is busy.                         */
+#define MV_TERMINATE   (0x1F)  /* Item terminates it's work.            */
+#define MV_NOT_ALIGNED (0x20)  /* Wrong alignment                       */
+#define MV_NOT_ALLOWED (0x21)  /* Operation NOT allowed                 */
+#define MV_WRITE_PROTECT (0x22)        /* Write protected                       */
+
+#define MV_INVALID     (int)(-1)
+
+/*
+ * Debug (Enable/Disable modules) and Error report
+ */
+
+#ifdef BASIC_DEBUG
+#define MV_DEBUG_WL
+#define MV_DEBUG_RL
+#define MV_DEBUG_DQS_RESULTS
+#endif
+
+#ifdef FULL_DEBUG
+#define MV_DEBUG_WL
+#define MV_DEBUG_RL
+#define MV_DEBUG_DQS
+
+#define MV_DEBUG_PBS
+#define MV_DEBUG_DFS
+#define MV_DEBUG_MAIN_FULL
+#define MV_DEBUG_DFS_FULL
+#define MV_DEBUG_DQS_FULL
+#define MV_DEBUG_RL_FULL
+#define MV_DEBUG_WL_FULL
+#endif
+
+/*
+ * General Consts
+ */
+
+#define SDRAM_READ_WRITE_LEN_IN_WORDS           16
+#define SDRAM_READ_WRITE_LEN_IN_DOUBLE_WORDS    8
+#define CACHE_LINE_SIZE                         0x20
+
+#define SDRAM_CS_BASE                           0x0
+
+#define SRAM_BASE                               0x40000000
+#define SRAM_SIZE                               0xFFF
+
+#define LEN_64BIT_STD_PATTERN                   16
+#define LEN_64BIT_KILLER_PATTERN                128
+#define LEN_64BIT_SPECIAL_PATTERN               128
+#define LEN_64BIT_PBS_PATTERN                   16
+#define LEN_WL_SUP_PATTERN                             32
+
+#define LEN_16BIT_STD_PATTERN                   4
+#define LEN_16BIT_KILLER_PATTERN                128
+#define LEN_16BIT_SPECIAL_PATTERN               128
+#define LEN_16BIT_PBS_PATTERN                   4
+
+#define CMP_BYTE_SHIFT                          8
+#define CMP_BYTE_MASK                           0xFF
+#define PUP_SIZE                                8
+
+#define S 0
+#define C 1
+#define P 2
+#define D 3
+#define DQS 6
+#define PS 2
+#define DS 3
+#define PE 4
+#define DE 5
+
+#define CS0                                     0
+#define MAX_DIMM_NUM                            2
+#define MAX_DELAY                               0x1F
+
+/*
+ * Invertion limit and phase1 limit are WA for the RL @ 1:1 design bug -
+ * Armada 370 & AXP Z1
+ */
+#define MAX_DELAY_INV_LIMIT                     0x5
+#define MIN_DELAY_PHASE_1_LIMIT                 0x10
+
+#define MAX_DELAY_INV                           (0x3F - MAX_DELAY_INV_LIMIT)
+#define MIN_DELAY                               0
+#define MAX_PUP_NUM                             9
+#define ECC_PUP                                 8
+#define DQ_NUM                                  8
+#define DQS_DQ_NUM                              8
+#define INIT_WL_DELAY                           13
+#define INIT_RL_DELAY                           15
+#define TWLMRD_DELAY                            20
+#define TCLK_3_DELAY                            3
+#define ECC_BIT                                 8
+#define DMA_SIZE                                64
+#define MV_DMA_0                                0
+#define MAX_TRAINING_RETRY                      10
+
+#define PUP_RL_MODE                             0x2
+#define PUP_WL_MODE                             0
+#define PUP_PBS_TX                              0x10
+#define PUP_PBS_TX_DM                           0x1A
+#define PUP_PBS_RX                              0x30
+#define PUP_DQS_WR                              0x1
+#define PUP_DQS_RD                              0x3
+#define PUP_BC                                  10
+#define PUP_DELAY_MASK                          0x1F
+#define PUP_PHASE_MASK                          0x7
+#define PUP_NUM_64BIT                           8
+#define PUP_NUM_32BIT                           4
+#define PUP_NUM_16BIT                           2
+
+/* control PHY registers */
+#define CNTRL_PUP_DESKEW                        0x10
+
+/* WL */
+#define COUNT_WL_HI_FREQ                        2
+#define COUNT_WL                                2
+#define COUNT_WL_RFRS                           9
+#define WL_HI_FREQ_SHIFT                        2
+#define WL_HI_FREQ_STATE                        1
+#define COUNT_HW_WL                             2
+
+/* RL */
+/*
+ * RL_MODE - this define uses the RL mode SW RL instead of the functional
+ * window SW RL
+ */
+#define RL_MODE
+#define RL_WINDOW_WA
+#define MAX_PHASE_1TO1                          2
+#define MAX_PHASE_2TO1                          4
+
+#define MAX_PHASE_RL_UL_1TO1                    0
+#define MAX_PHASE_RL_L_1TO1                     4
+#define MAX_PHASE_RL_UL_2TO1                    3
+#define MAX_PHASE_RL_L_2TO1                     7
+
+#define RL_UNLOCK_STATE                         0
+#define RL_WINDOW_STATE                         1
+#define RL_FINAL_STATE                          2
+#define RL_RETRY_COUNT                          2
+#define COUNT_HW_RL                             2
+
+/* PBS */
+#define MAX_PBS                                 31
+#define MIN_PBS                                 0
+#define COUNT_PBS_PATTERN                       2
+#define COUNT_PBS_STARTOVER                     2
+#define COUNT_PBS_REPEAT                        3
+#define COUNT_PBS_COMP_RETRY_NUM                2
+#define PBS_DIFF_LIMIT                          31
+#define PATTERN_PBS_TX_A                        0x55555555
+#define PATTERN_PBS_TX_B                        0xAAAAAAAA
+
+/* DQS */
+#define ADLL_ERROR                              0x55
+#define ADLL_MAX                                31
+#define ADLL_MIN                                0
+#define MIN_WIN_SIZE                            4
+#define VALID_WIN_THRS                          MIN_WIN_SIZE
+
+#define MODE_2TO1                               1
+#define MODE_1TO1                               0
+
+/*
+ * Macros
+ */
+#define IS_PUP_ACTIVE(_data_, _pup_)        (((_data_) >> (_pup_)) & 0x1)
+
+/*
+ * Internal ERROR codes
+ */
+#define MV_DDR3_TRAINING_ERR_WR_LVL_HW              0xDD302001
+#define MV_DDR3_TRAINING_ERR_LOAD_PATTERNS          0xDD302002
+#define MV_DDR3_TRAINING_ERR_WR_LVL_HI_FREQ         0xDD302003
+#define MV_DDR3_TRAINING_ERR_DFS_H2L                0xDD302004
+#define MV_DDR3_TRAINING_ERR_DRAM_COMPARE           0xDD302005
+#define MV_DDR3_TRAINING_ERR_WIN_LIMITS             0xDD302006
+#define MV_DDR3_TRAINING_ERR_PUP_RANGE              0xDD302025
+#define MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH   0xDD302007
+#define MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH  0xDD302008
+#define MV_DDR3_TRAINING_ERR_DQS_PATTERN            0xDD302009
+#define MV_DDR3_TRAINING_ERR_PBS_ADLL_SHR_1PHASE    0xDD302010
+#define MV_DDR3_TRAINING_ERR_PBS_TX_MAX_VAL         0xDD302011
+#define MV_DDR3_TRAINING_ERR_PBS_RX_PER_BIT         0xDD302012
+#define MV_DDR3_TRAINING_ERR_PBS_TX_PER_BIT         0xDD302013
+#define MV_DDR3_TRAINING_ERR_PBS_RX_MAX_VAL         0xDD302014
+#define MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP 0xDD302015
+#define MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_MAX_VAL  0xDD302016
+#define MV_DDR3_TRAINING_ERR_RD_LVL_RL_PATTERN      0xDD302017
+#define MV_DDR3_TRAINING_ERR_RD_LVL_RL_PUP_UNLOCK   0xDD302018
+#define MV_DDR3_TRAINING_ERR_RD_LVL_PUP_UNLOCK      0xDD302019
+#define MV_DDR3_TRAINING_ERR_WR_LVL_SW              0xDD302020
+#define MV_DDR3_TRAINING_ERR_PRBS_RX                0xDD302021
+#define MV_DDR3_TRAINING_ERR_DQS_RX                 0xDD302022
+#define MV_DDR3_TRAINING_ERR_PRBS_TX                0xDD302023
+#define MV_DDR3_TRAINING_ERR_DQS_TX                 0xDD302024
+
+/*
+ * DRAM information structure
+ */
+typedef struct dram_info {
+       u32 num_cs;
+       u32 cs_ena;
+       u32 num_of_std_pups;    /* Q value = ddrWidth/8 - Without ECC!! */
+       u32 num_of_total_pups;  /* numOfStdPups + eccEna */
+       u32 target_frequency;   /* DDR Frequency */
+       u32 ddr_width;          /* 32/64 Bit or 16/32 Bit */
+       u32 ecc_ena;            /* 0/1 */
+       u32 wl_val[MAX_CS][MAX_PUP_NUM][7];
+       u32 rl_val[MAX_CS][MAX_PUP_NUM][7];
+       u32 rl_max_phase;
+       u32 rl_min_phase;
+       u32 wl_max_phase;
+       u32 wl_min_phase;
+       u32 rd_smpl_dly;
+       u32 rd_rdy_dly;
+       u32 cl;
+       u32 cwl;
+       u32 mode_2t;
+       int rl400_bug;
+       int multi_cs_mr_support;
+       int reg_dimm;
+} MV_DRAM_INFO;
+
+enum training_modes  {
+       DQS_WR_MODE,
+       WL_MODE_,
+       RL_MODE_,
+       DQS_RD_MODE,
+       PBS_TX_DM_MODE,
+       PBS_TX_MODE,
+       PBS_RX_MODE,
+       MAX_TRAINING_MODE,
+};
+
+typedef struct dram_training_init {
+       u32 reg_addr;
+       u32 reg_value;
+} MV_DRAM_TRAINING_INIT;
+
+typedef struct dram_mv_init {
+       u32 reg_addr;
+       u32 reg_value;
+} MV_DRAM_MC_INIT;
+
+/* Board/Soc revisions define */
+enum board_rev {
+       Z1,
+       Z1_PCAC,
+       Z1_RD_SLED,
+       A0,
+       A0_AMC
+};
+
+typedef struct dram_modes {
+       char *mode_name;
+       u8 cpu_freq;
+       u8 fab_freq;
+       u8 chip_id;
+       int chip_board_rev;
+       MV_DRAM_MC_INIT *regs;
+       MV_DRAM_TRAINING_INIT *vals;
+} MV_DRAM_MODES;
+
+/*
+ * Function Declarations
+ */
+
+u32 cache_inv(u32 addr);
+void flush_l1_v7(u32 line);
+void flush_l1_v6(u32 line);
+
+u32 ddr3_cl_to_valid_cl(u32 cl);
+u32 ddr3_valid_cl_to_cl(u32 ui_valid_cl);
+
+void ddr3_write_pup_reg(u32 mode, u32 cs, u32 pup, u32 phase, u32 delay);
+u32 ddr3_read_pup_reg(u32 mode, u32 cs, u32 pup);
+
+int ddr3_sdram_pbs_compare(MV_DRAM_INFO *dram_info, u32 pup_locked, int is_tx,
+                          u32 pbs_pattern_idx, u32 pbs_curr_val,
+                          u32 pbs_lock_val, u32 *skew_array,
+                          u8 *unlock_pup_dq_array, u32 ecc);
+
+int ddr3_sdram_dqs_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+                          u32 *new_locked_pup, u32 *pattern,
+                          u32 pattern_len, u32 sdram_offset, int write,
+                          int mask, u32 *mask_pattern, int b_special_compare);
+
+int ddr3_sdram_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+                      u32 *new_locked_pup, u32 *pattern, u32 pattern_len,
+                      u32 sdram_offset, int write, int mask,
+                      u32 *mask_pattern, int b_special_compare);
+
+int ddr3_sdram_direct_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+                             u32 *new_locked_pup, u32 *pattern,
+                             u32 pattern_len, u32 sdram_offset, int write,
+                             int mask, u32 *mask_pattern);
+
+int ddr3_sdram_dm_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+                         u32 *new_locked_pup, u32 *pattern,
+                         u32 sdram_offset);
+int ddr3_dram_sram_read(u32 src, u32 dst, u32 len);
+int ddr3_load_patterns(MV_DRAM_INFO *dram_info, int resume);
+
+int ddr3_read_leveling_hw(u32 freq, MV_DRAM_INFO *dram_info);
+int ddr3_read_leveling_sw(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info);
+
+int ddr3_write_leveling_hw(u32 freq, MV_DRAM_INFO *dram_info);
+int ddr3_write_leveling_sw(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info);
+int ddr3_write_leveling_hw_reg_dimm(u32 freq, MV_DRAM_INFO *dram_info);
+int ddr3_wl_supplement(MV_DRAM_INFO *dram_info);
+
+int ddr3_dfs_high_2_low(u32 freq, MV_DRAM_INFO *dram_info);
+int ddr3_dfs_low_2_high(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info);
+
+int ddr3_pbs_tx(MV_DRAM_INFO *dram_info);
+int ddr3_pbs_rx(MV_DRAM_INFO *dram_info);
+int ddr3_load_pbs_patterns(MV_DRAM_INFO *dram_info);
+
+int ddr3_dqs_centralization_rx(MV_DRAM_INFO *dram_info);
+int ddr3_dqs_centralization_tx(MV_DRAM_INFO *dram_info);
+int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info);
+
+void ddr3_static_training_init(void);
+
+u8 ddr3_get_eprom_fabric(void);
+void ddr3_set_performance_params(MV_DRAM_INFO *dram_info);
+int ddr3_dram_sram_burst(u32 src, u32 dst, u32 len);
+void ddr3_save_training(MV_DRAM_INFO *dram_info);
+int ddr3_read_training_results(void);
+int ddr3_training_suspend_resume(MV_DRAM_INFO *dram_info);
+int ddr3_get_min_max_read_sample_delay(u32 cs_enable, u32 reg, u32 *min,
+                                      u32 *max, u32 *cs_max);
+int ddr3_get_min_max_rl_phase(MV_DRAM_INFO *dram_info, u32 *min, u32 *max,
+                             u32 cs);
+int ddr3_odt_activate(int activate);
+int ddr3_odt_read_dynamic_config(MV_DRAM_INFO *dram_info);
+void ddr3_print_freq(u32 freq);
+void ddr3_reset_phy_read_fifo(void);
+
+#endif /* __DDR3_TRAINING_H */
diff --git a/drivers/ddr/mvebu/ddr3_init.c b/drivers/ddr/mvebu/ddr3_init.c
new file mode 100644 (file)
index 0000000..11b8591
--- /dev/null
@@ -0,0 +1,1219 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_init.h"
+
+#if defined(MV88F78X60)
+#include "ddr3_axp_vars.h"
+#elif defined(MV88F67XX)
+#include "ddr3_a370_vars.h"
+#elif defined(MV88F672X)
+#include "ddr3_a375_vars.h"
+#endif
+
+#ifdef STATIC_TRAINING
+static void ddr3_static_training_init(void);
+#endif
+#ifdef DUNIT_STATIC
+static void ddr3_static_mc_init(void);
+#endif
+#if defined(DUNIT_STATIC) || defined(STATIC_TRAINING)
+MV_DRAM_MODES *ddr3_get_static_ddr_mode(void);
+#endif
+#if defined(MV88F672X)
+void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps);
+#endif
+u32 mv_board_id_get(void);
+extern void ddr3_set_sw_wl_rl_debug(u32);
+extern void ddr3_set_pbs(u32);
+extern void ddr3_set_log_level(u32 val);
+
+static u32 log_level = DDR3_LOG_LEVEL;
+
+static u32 ddr3_init_main(void);
+
+/*
+ * Name:     ddr3_set_log_level
+ * Desc:     This routine initialize the log_level acording to nLogLevel
+ *           which getting from user
+ * Args:     nLogLevel
+ * Notes:
+ * Returns:  None.
+ */
+void ddr3_set_log_level(u32 val)
+{
+       log_level = val;
+}
+
+/*
+ * Name:     ddr3_get_log_level
+ * Desc:     This routine returns the log level
+ * Args:     none
+ * Notes:
+ * Returns:  log level.
+ */
+u32 ddr3_get_log_level(void)
+{
+       return log_level;
+}
+
+static void debug_print_reg(u32 reg)
+{
+       printf("0x%08x = 0x%08x\n", reg, reg_read(reg));
+}
+
+static void print_dunit_setup(void)
+{
+       puts("\n########### LOG LEVEL 1 (D-UNIT SETUP)###########\n");
+
+#ifdef DUNIT_STATIC
+       puts("\nStatic D-UNIT Setup:\n");
+#endif
+#ifdef DUNIT_SPD
+       puts("\nDynamic(using SPD) D-UNIT Setup:\n");
+#endif
+       debug_print_reg(REG_SDRAM_CONFIG_ADDR);
+       debug_print_reg(REG_DUNIT_CTRL_LOW_ADDR);
+       debug_print_reg(REG_SDRAM_TIMING_LOW_ADDR);
+       debug_print_reg(REG_SDRAM_TIMING_HIGH_ADDR);
+       debug_print_reg(REG_SDRAM_ADDRESS_CTRL_ADDR);
+       debug_print_reg(REG_SDRAM_OPEN_PAGES_ADDR);
+       debug_print_reg(REG_SDRAM_OPERATION_ADDR);
+       debug_print_reg(REG_SDRAM_MODE_ADDR);
+       debug_print_reg(REG_SDRAM_EXT_MODE_ADDR);
+       debug_print_reg(REG_DDR_CONT_HIGH_ADDR);
+       debug_print_reg(REG_ODT_TIME_LOW_ADDR);
+       debug_print_reg(REG_SDRAM_ERROR_ADDR);
+       debug_print_reg(REG_SDRAM_AUTO_PWR_SAVE_ADDR);
+       debug_print_reg(REG_OUDDR3_TIMING_ADDR);
+       debug_print_reg(REG_ODT_TIME_HIGH_ADDR);
+       debug_print_reg(REG_SDRAM_ODT_CTRL_LOW_ADDR);
+       debug_print_reg(REG_SDRAM_ODT_CTRL_HIGH_ADDR);
+       debug_print_reg(REG_DUNIT_ODT_CTRL_ADDR);
+#ifndef MV88F67XX
+       debug_print_reg(REG_DRAM_FIFO_CTRL_ADDR);
+       debug_print_reg(REG_DRAM_AXI_CTRL_ADDR);
+       debug_print_reg(REG_DRAM_ADDR_CTRL_DRIVE_STRENGTH_ADDR);
+       debug_print_reg(REG_DRAM_DATA_DQS_DRIVE_STRENGTH_ADDR);
+       debug_print_reg(REG_DRAM_VER_CAL_MACHINE_CTRL_ADDR);
+       debug_print_reg(REG_DRAM_MAIN_PADS_CAL_ADDR);
+       debug_print_reg(REG_DRAM_HOR_CAL_MACHINE_CTRL_ADDR);
+       debug_print_reg(REG_CS_SIZE_SCRATCH_ADDR);
+       debug_print_reg(REG_DYNAMIC_POWER_SAVE_ADDR);
+       debug_print_reg(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+       debug_print_reg(REG_READ_DATA_READY_DELAYS_ADDR);
+       debug_print_reg(REG_DDR3_MR0_ADDR);
+       debug_print_reg(REG_DDR3_MR1_ADDR);
+       debug_print_reg(REG_DDR3_MR2_ADDR);
+       debug_print_reg(REG_DDR3_MR3_ADDR);
+       debug_print_reg(REG_DDR3_RANK_CTRL_ADDR);
+       debug_print_reg(REG_DRAM_PHY_CONFIG_ADDR);
+       debug_print_reg(REG_STATIC_DRAM_DLB_CONTROL);
+       debug_print_reg(DLB_BUS_OPTIMIZATION_WEIGHTS_REG);
+       debug_print_reg(DLB_AGING_REGISTER);
+       debug_print_reg(DLB_EVICTION_CONTROL_REG);
+       debug_print_reg(DLB_EVICTION_TIMERS_REGISTER_REG);
+#if defined(MV88F672X)
+       debug_print_reg(REG_FASTPATH_WIN_CTRL_ADDR(0));
+       debug_print_reg(REG_FASTPATH_WIN_BASE_ADDR(0));
+       debug_print_reg(REG_FASTPATH_WIN_CTRL_ADDR(1));
+       debug_print_reg(REG_FASTPATH_WIN_BASE_ADDR(1));
+#else
+       debug_print_reg(REG_FASTPATH_WIN_0_CTRL_ADDR);
+#endif
+       debug_print_reg(REG_CDI_CONFIG_ADDR);
+#endif
+}
+
+#if !defined(STATIC_TRAINING)
+static void ddr3_restore_and_set_final_windows(u32 *win_backup)
+{
+       u32 ui, reg, cs;
+       u32 win_ctrl_reg, num_of_win_regs;
+       u32 cs_ena = ddr3_get_cs_ena_from_reg();
+
+#if defined(MV88F672X)
+       if (DDR3_FAST_PATH_EN == 0)
+               return;
+#endif
+
+#if defined(MV88F672X)
+       win_ctrl_reg = REG_XBAR_WIN_16_CTRL_ADDR;
+       num_of_win_regs = 8;
+#else
+       win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR;
+       num_of_win_regs = 16;
+#endif
+
+       /* Return XBAR windows 4-7 or 16-19 init configuration */
+       for (ui = 0; ui < num_of_win_regs; ui++)
+               reg_write((win_ctrl_reg + 0x4 * ui), win_backup[ui]);
+
+       DEBUG_INIT_FULL_S("DDR3 Training Sequence - Switching XBAR Window to FastPath Window\n");
+
+#if defined(MV88F672X)
+       /* Set L2 filtering to 1G */
+       reg_write(0x8c04, 0x40000000);
+
+       /* Open fast path windows */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs)) {
+                       /* set fast path window control for the cs */
+                       reg = 0x1FFFFFE1;
+                       reg |= (cs << 2);
+                       reg |= (SDRAM_CS_SIZE & 0xFFFF0000);
+                       /* Open fast path Window */
+                       reg_write(REG_FASTPATH_WIN_CTRL_ADDR(cs), reg);
+                       /* set fast path window base address for the cs */
+                       reg = (((SDRAM_CS_SIZE + 1) * cs) & 0xFFFF0000);
+                       /* Set base address */
+                       reg_write(REG_FASTPATH_WIN_BASE_ADDR(cs), reg);
+               }
+       }
+#else
+       reg = 0x1FFFFFE1;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs)) {
+                       reg |= (cs << 2);
+                       break;
+               }
+       }
+
+       /* Open fast path Window to - 0.5G */
+       reg_write(REG_FASTPATH_WIN_0_CTRL_ADDR, reg);
+#endif
+}
+
+static void ddr3_save_and_set_training_windows(u32 *win_backup)
+{
+       u32 cs_ena = ddr3_get_cs_ena_from_reg();
+       u32 reg, tmp_count, cs, ui;
+       u32 win_ctrl_reg, win_base_reg, win_remap_reg;
+       u32 num_of_win_regs, win_jump_index;
+
+#if defined(MV88F672X)
+       /* Disable L2 filtering */
+       reg_write(0x8c04, 0);
+
+       win_ctrl_reg = REG_XBAR_WIN_16_CTRL_ADDR;
+       win_base_reg = REG_XBAR_WIN_16_BASE_ADDR;
+       win_remap_reg = REG_XBAR_WIN_16_REMAP_ADDR;
+       win_jump_index = 0x8;
+       num_of_win_regs = 8;
+#else
+       win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR;
+       win_base_reg = REG_XBAR_WIN_4_BASE_ADDR;
+       win_remap_reg = REG_XBAR_WIN_4_REMAP_ADDR;
+       win_jump_index = 0x10;
+       num_of_win_regs = 16;
+#endif
+
+       /* Close XBAR Window 19 - Not needed */
+       /* {0x000200e8}  -   Open Mbus Window - 2G */
+       reg_write(REG_XBAR_WIN_19_CTRL_ADDR, 0);
+
+       /* Save XBAR Windows 4-19 init configurations */
+       for (ui = 0; ui < num_of_win_regs; ui++)
+               win_backup[ui] = reg_read(win_ctrl_reg + 0x4 * ui);
+
+       /* Open XBAR Windows 4-7 or 16-19 for other CS */
+       reg = 0;
+       tmp_count = 0;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs)) {
+                       switch (cs) {
+                       case 0:
+                               reg = 0x0E00;
+                               break;
+                       case 1:
+                               reg = 0x0D00;
+                               break;
+                       case 2:
+                               reg = 0x0B00;
+                               break;
+                       case 3:
+                               reg = 0x0700;
+                               break;
+                       }
+                       reg |= (1 << 0);
+                       reg |= (SDRAM_CS_SIZE & 0xFFFF0000);
+
+                       reg_write(win_ctrl_reg + win_jump_index * tmp_count,
+                                 reg);
+                       reg = ((SDRAM_CS_SIZE + 1) * (tmp_count)) & 0xFFFF0000;
+                       reg_write(win_base_reg + win_jump_index * tmp_count,
+                                 reg);
+
+                       if (win_remap_reg <= REG_XBAR_WIN_7_REMAP_ADDR) {
+                               reg_write(win_remap_reg +
+                                         win_jump_index * tmp_count, 0);
+                       }
+
+                       tmp_count++;
+               }
+       }
+}
+#endif /*  !defined(STATIC_TRAINING) */
+
+/*
+ * Name:     ddr3_init - Main DDR3 Init function
+ * Desc:     This routine initialize the DDR3 MC and runs HW training.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+int ddr3_init(void)
+{
+       unsigned int status;
+
+       ddr3_set_pbs(DDR3_PBS);
+       ddr3_set_sw_wl_rl_debug(DDR3_RUN_SW_WHEN_HW_FAIL);
+
+       status = ddr3_init_main();
+       if (status == MV_DDR3_TRAINING_ERR_BAD_SAR)
+               DEBUG_INIT_S("DDR3 Training Error: Bad sample at reset");
+       if (status == MV_DDR3_TRAINING_ERR_BAD_DIMM_SETUP)
+               DEBUG_INIT_S("DDR3 Training Error: Bad DIMM setup");
+       if (status == MV_DDR3_TRAINING_ERR_MAX_CS_LIMIT)
+               DEBUG_INIT_S("DDR3 Training Error: Max CS limit");
+       if (status == MV_DDR3_TRAINING_ERR_MAX_ENA_CS_LIMIT)
+               DEBUG_INIT_S("DDR3 Training Error: Max enable CS limit");
+       if (status == MV_DDR3_TRAINING_ERR_BAD_R_DIMM_SETUP)
+               DEBUG_INIT_S("DDR3 Training Error: Bad R-DIMM setup");
+       if (status == MV_DDR3_TRAINING_ERR_TWSI_FAIL)
+               DEBUG_INIT_S("DDR3 Training Error: TWSI failure");
+       if (status == MV_DDR3_TRAINING_ERR_DIMM_TYPE_NO_MATCH)
+               DEBUG_INIT_S("DDR3 Training Error: DIMM type no match");
+       if (status == MV_DDR3_TRAINING_ERR_TWSI_BAD_TYPE)
+               DEBUG_INIT_S("DDR3 Training Error: TWSI bad type");
+       if (status == MV_DDR3_TRAINING_ERR_BUS_WIDTH_NOT_MATCH)
+               DEBUG_INIT_S("DDR3 Training Error: bus width no match");
+       if (status > MV_DDR3_TRAINING_ERR_HW_FAIL_BASE)
+               DEBUG_INIT_C("DDR3 Training Error: HW Failure 0x", status, 8);
+
+       return status;
+}
+
+static void print_ddr_target_freq(u32 cpu_freq, u32 fab_opt)
+{
+       puts("\nDDR3 Training Sequence - Run DDR3 at ");
+
+       switch (cpu_freq) {
+#if defined(MV88F672X)
+       case 21:
+               puts("533 Mhz\n");
+               break;
+#else
+       case 1:
+               puts("533 Mhz\n");
+               break;
+       case 2:
+               if (fab_opt == 5)
+                       puts("600 Mhz\n");
+               if (fab_opt == 9)
+                       puts("400 Mhz\n");
+               break;
+       case 3:
+               puts("667 Mhz\n");
+               break;
+       case 4:
+               if (fab_opt == 5)
+                       puts("750 Mhz\n");
+               if (fab_opt == 9)
+                       puts("500 Mhz\n");
+               break;
+       case 0xa:
+               puts("400 Mhz\n");
+               break;
+       case 0xb:
+               if (fab_opt == 5)
+                       puts("800 Mhz\n");
+               if (fab_opt == 9)
+                       puts("553 Mhz\n");
+               if (fab_opt == 0xA)
+                       puts("640 Mhz\n");
+               break;
+#endif
+       default:
+               puts("NOT DEFINED FREQ\n");
+       }
+}
+
+static u32 ddr3_init_main(void)
+{
+       u32 target_freq;
+       u32 reg = 0;
+       u32 cpu_freq, fab_opt, hclk_time_ps, soc_num;
+       __maybe_unused u32 ecc = DRAM_ECC;
+       __maybe_unused int dqs_clk_aligned = 0;
+       __maybe_unused u32 scrub_offs, scrub_size;
+       __maybe_unused u32 ddr_width = BUS_WIDTH;
+       __maybe_unused int status;
+       __maybe_unused u32 win_backup[16];
+
+       /* SoC/Board special Initializtions */
+       fab_opt = ddr3_get_fab_opt();
+
+#ifdef CONFIG_SPD_EEPROM
+       i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+#endif
+
+       ddr3_print_version();
+       DEBUG_INIT_S("4\n");
+       /* Lib version 5.5.4 */
+
+       fab_opt = ddr3_get_fab_opt();
+
+       /* Switching CPU to MRVL ID */
+       soc_num = (reg_read(REG_SAMPLE_RESET_HIGH_ADDR) & SAR1_CPU_CORE_MASK) >>
+               SAR1_CPU_CORE_OFFSET;
+       switch (soc_num) {
+       case 0x3:
+               reg_bit_set(CPU_CONFIGURATION_REG(3), CPU_MRVL_ID_OFFSET);
+               reg_bit_set(CPU_CONFIGURATION_REG(2), CPU_MRVL_ID_OFFSET);
+       case 0x1:
+               reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET);
+       case 0x0:
+               reg_bit_set(CPU_CONFIGURATION_REG(0), CPU_MRVL_ID_OFFSET);
+       default:
+               break;
+       }
+
+       /* Power down deskew PLL */
+#if !defined(MV88F672X)
+       /* 0x18780 [25] */
+       reg = (reg_read(REG_DDRPHY_APLL_CTRL_ADDR) & ~(1 << 25));
+       reg_write(REG_DDRPHY_APLL_CTRL_ADDR, reg);
+#endif
+
+       /*
+        * Stage 0 - Set board configuration
+        */
+       cpu_freq = ddr3_get_cpu_freq();
+       if (fab_opt > FAB_OPT)
+               fab_opt = FAB_OPT - 1;
+
+       if (ddr3_get_log_level() > 0)
+               print_ddr_target_freq(cpu_freq, fab_opt);
+
+#if defined(MV88F672X)
+       get_target_freq(cpu_freq, &target_freq, &hclk_time_ps);
+#else
+       target_freq = cpu_ddr_ratios[fab_opt][cpu_freq];
+       hclk_time_ps = cpu_fab_clk_to_hclk[fab_opt][cpu_freq];
+#endif
+       if ((target_freq == 0) || (hclk_time_ps == 0)) {
+               DEBUG_INIT_S("DDR3 Training Sequence - FAILED - Wrong Sample at Reset Configurations\n");
+               if (target_freq == 0) {
+                       DEBUG_INIT_C("target_freq", target_freq, 2);
+                       DEBUG_INIT_C("fab_opt", fab_opt, 2);
+                       DEBUG_INIT_C("cpu_freq", cpu_freq, 2);
+               } else if (hclk_time_ps == 0) {
+                       DEBUG_INIT_C("hclk_time_ps", hclk_time_ps, 2);
+                       DEBUG_INIT_C("fab_opt", fab_opt, 2);
+                       DEBUG_INIT_C("cpu_freq", cpu_freq, 2);
+               }
+
+               return MV_DDR3_TRAINING_ERR_BAD_SAR;
+       }
+
+#if defined(ECC_SUPPORT)
+       scrub_offs = U_BOOT_START_ADDR;
+       scrub_size = U_BOOT_SCRUB_SIZE;
+#else
+       scrub_offs = 0;
+       scrub_size = 0;
+#endif
+
+#if defined(ECC_SUPPORT) && defined(AUTO_DETECTION_SUPPORT)
+       ecc = DRAM_ECC;
+#endif
+
+#if defined(ECC_SUPPORT) && defined(AUTO_DETECTION_SUPPORT)
+       ecc = 0;
+       if (ddr3_check_config(BUS_WIDTH_ECC_TWSI_ADDR, CONFIG_ECC))
+               ecc = 1;
+#endif
+
+#ifdef DQS_CLK_ALIGNED
+       dqs_clk_aligned = 1;
+#endif
+
+       /* Check if DRAM is already initialized  */
+       if (reg_read(REG_BOOTROM_ROUTINE_ADDR) &
+           (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) {
+               DEBUG_INIT_S("DDR3 Training Sequence - 2nd boot - Skip\n");
+               return MV_OK;
+       }
+
+       /*
+        * Stage 1 - Dunit Setup
+        */
+
+#ifdef DUNIT_STATIC
+       /*
+        * For Static D-Unit Setup use must set the correct static values
+        * at the ddr3_*soc*_vars.h file
+        */
+       DEBUG_INIT_FULL_S("DDR3 Training Sequence - Static MC Init\n");
+       ddr3_static_mc_init();
+
+#ifdef ECC_SUPPORT
+       ecc = DRAM_ECC;
+       if (ecc) {
+               reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+               reg |= (1 << REG_SDRAM_CONFIG_ECC_OFFS);
+               reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+       }
+#endif
+#endif
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+#if defined(AUTO_DETECTION_SUPPORT)
+       /*
+        * Configurations for both static and dynamic MC setups
+        *
+        * Dynamically Set 32Bit and ECC for AXP (Relevant only for
+        * Marvell DB boards)
+        */
+       if (ddr3_check_config(BUS_WIDTH_ECC_TWSI_ADDR, CONFIG_BUS_WIDTH)) {
+               ddr_width = 32;
+               DEBUG_INIT_S("DDR3 Training Sequence - DRAM bus width 32Bit\n");
+       }
+#endif
+
+#if defined(MV88F672X)
+       reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+       if ((reg >> 15) & 1)
+               ddr_width = 32;
+       else
+               ddr_width = 16;
+#endif
+#endif
+
+#ifdef DUNIT_SPD
+       status = ddr3_dunit_setup(ecc, hclk_time_ps, &ddr_width);
+       if (MV_OK != status) {
+               DEBUG_INIT_S("DDR3 Training Sequence - FAILED (ddr3 Dunit Setup)\n");
+               return status;
+       }
+#endif
+
+       /* Fix read ready phases for all SOC in reg 0x15C8 */
+       reg = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+       reg &= ~(REG_TRAINING_DEBUG_3_MASK);
+       reg |= 0x4;             /* Phase 0 */
+       reg &= ~(REG_TRAINING_DEBUG_3_MASK << REG_TRAINING_DEBUG_3_OFFS);
+       reg |= (0x4 << (1 * REG_TRAINING_DEBUG_3_OFFS));        /* Phase 1 */
+       reg &= ~(REG_TRAINING_DEBUG_3_MASK << (3 * REG_TRAINING_DEBUG_3_OFFS));
+       reg |= (0x6 << (3 * REG_TRAINING_DEBUG_3_OFFS));        /* Phase 3 */
+       reg &= ~(REG_TRAINING_DEBUG_3_MASK << (4 * REG_TRAINING_DEBUG_3_OFFS));
+       reg |= (0x6 << (4 * REG_TRAINING_DEBUG_3_OFFS));
+       reg &= ~(REG_TRAINING_DEBUG_3_MASK << (5 * REG_TRAINING_DEBUG_3_OFFS));
+       reg |= (0x6 << (5 * REG_TRAINING_DEBUG_3_OFFS));
+       reg_write(REG_TRAINING_DEBUG_3_ADDR, reg);
+
+#if defined(MV88F672X)
+       /*
+        * AxiBrespMode[8] = Compliant,
+        * AxiAddrDecodeCntrl[11] = Internal,
+        * AxiDataBusWidth[0] = 128bit
+        */
+       /* 0x14A8 - AXI Control Register */
+       reg_write(REG_DRAM_AXI_CTRL_ADDR, 0);
+#else
+       /* 0x14A8 - AXI Control Register */
+       reg_write(REG_DRAM_AXI_CTRL_ADDR, 0x00000100);
+       reg_write(REG_CDI_CONFIG_ADDR, 0x00000006);
+
+       if ((ddr_width == 64) && (reg_read(REG_DDR_IO_ADDR) &
+                                 (1 << REG_DDR_IO_CLK_RATIO_OFFS))) {
+               /* 0x14A8 - AXI Control Register */
+               reg_write(REG_DRAM_AXI_CTRL_ADDR, 0x00000101);
+               reg_write(REG_CDI_CONFIG_ADDR, 0x00000007);
+       }
+#endif
+
+#if !defined(MV88F67XX)
+       /*
+        * ARMADA-370 activate DLB later at the u-boot,
+        * Armada38x - No DLB activation at this time
+        */
+       reg_write(DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0x18C01E);
+
+#if defined(MV88F78X60)
+       /* WA according to eratta GL-8672902*/
+       if (mv_ctrl_rev_get() == MV_78XX0_B0_REV)
+               reg_write(DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0xc19e);
+#endif
+
+       reg_write(DLB_AGING_REGISTER, 0x0f7f007f);
+       reg_write(DLB_EVICTION_CONTROL_REG, 0x0);
+       reg_write(DLB_EVICTION_TIMERS_REGISTER_REG, 0x00FF3C1F);
+
+       reg_write(MBUS_UNITS_PRIORITY_CONTROL_REG, 0x55555555);
+       reg_write(FABRIC_UNITS_PRIORITY_CONTROL_REG, 0xAA);
+       reg_write(MBUS_UNITS_PREFETCH_CONTROL_REG, 0xffff);
+       reg_write(FABRIC_UNITS_PREFETCH_CONTROL_REG, 0xf0f);
+
+#if defined(MV88F78X60)
+       /* WA according to eratta GL-8672902 */
+       if (mv_ctrl_rev_get() == MV_78XX0_B0_REV) {
+               reg = reg_read(REG_STATIC_DRAM_DLB_CONTROL);
+               reg |= DLB_ENABLE;
+               reg_write(REG_STATIC_DRAM_DLB_CONTROL, reg);
+       }
+#endif /* end defined(MV88F78X60) */
+#endif /* end !defined(MV88F67XX) */
+
+       if (ddr3_get_log_level() >= MV_LOG_LEVEL_1)
+               print_dunit_setup();
+
+       /*
+        * Stage 2 - Training Values Setup
+        */
+#ifdef STATIC_TRAINING
+       /*
+        * DRAM Init - After all the D-unit values are set, its time to init
+        * the D-unit
+        */
+       /* Wait for '0' */
+       reg_write(REG_SDRAM_INIT_CTRL_ADDR, 0x1);
+       do {
+               reg = (reg_read(REG_SDRAM_INIT_CTRL_ADDR)) &
+                       (1 << REG_SDRAM_INIT_CTRL_OFFS);
+       } while (reg);
+
+       /* ddr3 init using static parameters - HW training is disabled */
+       DEBUG_INIT_FULL_S("DDR3 Training Sequence - Static Training Parameters\n");
+       ddr3_static_training_init();
+
+#if defined(MV88F78X60)
+       /*
+        * If ECC is enabled, need to scrub the U-Boot area memory region -
+        * Run training function with Xor bypass just to scrub the memory
+        */
+       status = ddr3_hw_training(target_freq, ddr_width,
+                                 1, scrub_offs, scrub_size,
+                                 dqs_clk_aligned, DDR3_TRAINING_DEBUG,
+                                 REG_DIMM_SKIP_WL);
+       if (MV_OK != status) {
+               DEBUG_INIT_FULL_S("DDR3 Training Sequence - FAILED\n");
+               return status;
+       }
+#endif
+#else
+       /* Set X-BAR windows for the training sequence */
+       ddr3_save_and_set_training_windows(win_backup);
+
+       /* Run DDR3 Training Sequence */
+       /* DRAM Init */
+       reg_write(REG_SDRAM_INIT_CTRL_ADDR, 0x1);
+       do {
+               reg = (reg_read(REG_SDRAM_INIT_CTRL_ADDR)) &
+                       (1 << REG_SDRAM_INIT_CTRL_OFFS);
+       } while (reg);          /* Wait for '0' */
+
+       /* ddr3 init using DDR3 HW training procedure */
+       DEBUG_INIT_FULL_S("DDR3 Training Sequence - HW Training Procedure\n");
+       status = ddr3_hw_training(target_freq, ddr_width,
+                                 0, scrub_offs, scrub_size,
+                                 dqs_clk_aligned, DDR3_TRAINING_DEBUG,
+                                 REG_DIMM_SKIP_WL);
+       if (MV_OK != status) {
+               DEBUG_INIT_FULL_S("DDR3 Training Sequence - FAILED\n");
+               return status;
+       }
+#endif
+
+       /*
+        * Stage 3 - Finish
+        */
+#if defined(MV88F78X60) || defined(MV88F672X)
+       /* Disable ECC Ignore bit */
+       reg = reg_read(REG_SDRAM_CONFIG_ADDR) &
+               ~(1 << REG_SDRAM_CONFIG_IERR_OFFS);
+       reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+#endif
+
+#if !defined(STATIC_TRAINING)
+       /* Restore and set windows */
+       ddr3_restore_and_set_final_windows(win_backup);
+#endif
+
+       /* Update DRAM init indication in bootROM register */
+       reg = reg_read(REG_BOOTROM_ROUTINE_ADDR);
+       reg_write(REG_BOOTROM_ROUTINE_ADDR,
+                 reg | (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS));
+
+#if !defined(MV88F67XX)
+#if defined(MV88F78X60)
+       if (mv_ctrl_rev_get() == MV_78XX0_B0_REV) {
+               reg = reg_read(REG_SDRAM_CONFIG_ADDR);
+               if (ecc == 0)
+                       reg_write(REG_SDRAM_CONFIG_ADDR, reg | (1 << 19));
+       }
+#endif /* end defined(MV88F78X60) */
+
+       reg_write(DLB_EVICTION_CONTROL_REG, 0x9);
+
+       reg = reg_read(REG_STATIC_DRAM_DLB_CONTROL);
+       reg |= (DLB_ENABLE | DLB_WRITE_COALESING | DLB_AXI_PREFETCH_EN |
+               DLB_MBUS_PREFETCH_EN | PREFETCH_NLNSZTR);
+       reg_write(REG_STATIC_DRAM_DLB_CONTROL, reg);
+#endif /* end !defined(MV88F67XX) */
+
+#ifdef STATIC_TRAINING
+       DEBUG_INIT_S("DDR3 Training Sequence - Ended Successfully (S)\n");
+#else
+       DEBUG_INIT_S("DDR3 Training Sequence - Ended Successfully\n");
+#endif
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_get_cpu_freq
+ * Desc:     read S@R and return CPU frequency
+ * Args:
+ * Notes:
+ * Returns:  required value
+ */
+
+u32 ddr3_get_cpu_freq(void)
+{
+       u32 reg, cpu_freq;
+
+#if defined(MV88F672X)
+       /* Read sample at reset setting */
+       reg = reg_read(REG_SAMPLE_RESET_HIGH_ADDR);     /* 0xE8200 */
+       cpu_freq = (reg & REG_SAMPLE_RESET_CPU_FREQ_MASK) >>
+               REG_SAMPLE_RESET_CPU_FREQ_OFFS;
+#else
+       /* Read sample at reset setting */
+       reg = reg_read(REG_SAMPLE_RESET_LOW_ADDR);      /* 0x18230 [23:21] */
+#if defined(MV88F78X60)
+       cpu_freq = (reg & REG_SAMPLE_RESET_CPU_FREQ_MASK) >>
+               REG_SAMPLE_RESET_CPU_FREQ_OFFS;
+       reg = reg_read(REG_SAMPLE_RESET_HIGH_ADDR);     /* 0x18234 [20] */
+       cpu_freq |= (((reg >> REG_SAMPLE_RESET_HIGH_CPU_FREQ_OFFS) & 0x1) << 3);
+#elif defined(MV88F67XX)
+       cpu_freq = (reg & REG_SAMPLE_RESET_CPU_FREQ_MASK) >>
+               REG_SAMPLE_RESET_CPU_FREQ_OFFS;
+#endif
+#endif
+
+       return cpu_freq;
+}
+
+/*
+ * Name:     ddr3_get_fab_opt
+ * Desc:     read S@R and return CPU frequency
+ * Args:
+ * Notes:
+ * Returns:  required value
+ */
+u32 ddr3_get_fab_opt(void)
+{
+       __maybe_unused u32 reg, fab_opt;
+
+#if defined(MV88F672X)
+       return 0;               /* No fabric */
+#else
+       /* Read sample at reset setting */
+       reg = reg_read(REG_SAMPLE_RESET_LOW_ADDR);
+       fab_opt = (reg & REG_SAMPLE_RESET_FAB_MASK) >>
+               REG_SAMPLE_RESET_FAB_OFFS;
+
+#if defined(MV88F78X60)
+       reg = reg_read(REG_SAMPLE_RESET_HIGH_ADDR);
+       fab_opt |= (((reg >> 19) & 0x1) << 4);
+#endif
+
+       return fab_opt;
+#endif
+}
+
+/*
+ * Name:     ddr3_get_vco_freq
+ * Desc:     read S@R and return VCO frequency
+ * Args:
+ * Notes:
+ * Returns:  required value
+ */
+u32 ddr3_get_vco_freq(void)
+{
+       u32 fab, cpu_freq, ui_vco_freq;
+
+       fab = ddr3_get_fab_opt();
+       cpu_freq = ddr3_get_cpu_freq();
+
+       if (fab == 2 || fab == 3 || fab == 7 || fab == 8 || fab == 10 ||
+           fab == 15 || fab == 17 || fab == 20)
+               ui_vco_freq = cpu_freq + CLK_CPU;
+       else
+               ui_vco_freq = cpu_freq;
+
+       return ui_vco_freq;
+}
+
+#ifdef STATIC_TRAINING
+/*
+ * Name:     ddr3_static_training_init - Init DDR3 Training with
+ *           static parameters
+ * Desc:     Use this routine to init the controller without the HW training
+ *           procedure
+ *           User must provide compatible header file with registers data.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+void ddr3_static_training_init(void)
+{
+       MV_DRAM_MODES *ddr_mode;
+       u32 reg;
+       int j;
+
+       ddr_mode = ddr3_get_static_ddr_mode();
+
+       j = 0;
+       while (ddr_mode->vals[j].reg_addr != 0) {
+               udelay(10);     /* haim want to delay each write */
+               reg_write(ddr_mode->vals[j].reg_addr,
+                         ddr_mode->vals[j].reg_value);
+
+               if (ddr_mode->vals[j].reg_addr ==
+                   REG_PHY_REGISTRY_FILE_ACCESS_ADDR)
+                       do {
+                               reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+                                       REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+                       } while (reg);
+               j++;
+       }
+}
+#endif
+
+/*
+ * Name:     ddr3_get_static_mc_value - Init Memory controller with static
+ *           parameters
+ * Desc:     Use this routine to init the controller without the HW training
+ *           procedure
+ *           User must provide compatible header file with registers data.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+u32 ddr3_get_static_mc_value(u32 reg_addr, u32 offset1, u32 mask1, u32 offset2,
+                            u32 mask2)
+{
+       u32 reg, tmp;
+
+       reg = reg_read(reg_addr);
+
+       tmp = (reg >> offset1) & mask1;
+       if (mask2)
+               tmp |= (reg >> offset2) & mask2;
+
+       return tmp;
+}
+
+/*
+ * Name:     ddr3_get_static_ddr_mode - Init Memory controller with static
+ *           parameters
+ * Desc:     Use this routine to init the controller without the HW training
+ *           procedure
+ *           User must provide compatible header file with registers data.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+__weak MV_DRAM_MODES *ddr3_get_static_ddr_mode(void)
+{
+       u32 chip_board_rev, i;
+       u32 size;
+
+       /* Do not modify this code. relevant only for marvell Boards */
+#if defined(DB_78X60_PCAC)
+       chip_board_rev = Z1_PCAC;
+#elif defined(DB_78X60_AMC)
+       chip_board_rev = A0_AMC;
+#elif defined(DB_88F6710_PCAC)
+       chip_board_rev = A0_PCAC;
+#elif defined(RD_88F6710)
+       chip_board_rev = A0_RD;
+#elif defined(MV88F672X)
+       chip_board_rev = mv_board_id_get();
+#else
+       chip_board_rev = A0;
+#endif
+
+       size = sizeof(ddr_modes) / sizeof(MV_DRAM_MODES);
+       for (i = 0; i < size; i++) {
+               if ((ddr3_get_cpu_freq() == ddr_modes[i].cpu_freq) &&
+                   (ddr3_get_fab_opt() == ddr_modes[i].fab_freq) &&
+                   (chip_board_rev == ddr_modes[i].chip_board_rev))
+                       return &ddr_modes[i];
+       }
+
+       return &ddr_modes[0];
+}
+
+#ifdef DUNIT_STATIC
+/*
+ * Name:     ddr3_static_mc_init - Init Memory controller with static parameters
+ * Desc:     Use this routine to init the controller without the HW training
+ *           procedure
+ *           User must provide compatible header file with registers data.
+ * Args:     None.
+ * Notes:
+ * Returns:  None.
+ */
+void ddr3_static_mc_init(void)
+{
+       MV_DRAM_MODES *ddr_mode;
+       u32 reg;
+       int j;
+
+       ddr_mode = ddr3_get_static_ddr_mode();
+       j = 0;
+       while (ddr_mode->regs[j].reg_addr != 0) {
+               reg_write(ddr_mode->regs[j].reg_addr,
+                         ddr_mode->regs[j].reg_value);
+               if (ddr_mode->regs[j].reg_addr ==
+                   REG_PHY_REGISTRY_FILE_ACCESS_ADDR)
+                       do {
+                               reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+                                       REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+                       } while (reg);
+               j++;
+       }
+}
+#endif
+
+/*
+ * Name:     ddr3_check_config - Check user configurations: ECC/MultiCS
+ * Desc:
+ * Args:     twsi Address
+ * Notes:    Only Available for ArmadaXP/Armada 370 DB boards
+ * Returns:  None.
+ */
+int ddr3_check_config(u32 twsi_addr, MV_CONFIG_TYPE config_type)
+{
+#ifdef AUTO_DETECTION_SUPPORT
+       u8 data = 0;
+       int ret;
+       int offset;
+
+       if ((config_type == CONFIG_ECC) || (config_type == CONFIG_BUS_WIDTH))
+               offset = 1;
+       else
+               offset = 0;
+
+       ret = i2c_read(twsi_addr, offset, 1, (u8 *)&data, 1);
+       if (!ret) {
+               switch (config_type) {
+               case CONFIG_ECC:
+                       if (data & 0x2)
+                               return 1;
+                       break;
+               case CONFIG_BUS_WIDTH:
+                       if (data & 0x1)
+                               return 1;
+                       break;
+#ifdef DB_88F6710
+               case CONFIG_MULTI_CS:
+                       if (CFG_MULTI_CS_MODE(data))
+                               return 1;
+                       break;
+#else
+               case CONFIG_MULTI_CS:
+                       break;
+#endif
+               }
+       }
+#endif
+
+       return 0;
+}
+
+#if defined(DB_88F78X60_REV2)
+/*
+ * Name:     ddr3_get_eprom_fabric - Get Fabric configuration from EPROM
+ * Desc:
+ * Args:     twsi Address
+ * Notes:    Only Available for ArmadaXP DB Rev2 boards
+ * Returns:  None.
+ */
+u8 ddr3_get_eprom_fabric(void)
+{
+#ifdef AUTO_DETECTION_SUPPORT
+       u8 data = 0;
+       int ret;
+
+       ret = i2c_read(NEW_FABRIC_TWSI_ADDR, 1, 1, (u8 *)&data, 1);
+       if (!ret)
+               return data & 0x1F;
+#endif
+
+       return 0;
+}
+
+#endif
+
+/*
+ * Name:     ddr3_cl_to_valid_cl - this return register matching CL value
+ * Desc:
+ * Args:     clValue - the value
+
+ * Notes:
+ * Returns:  required CL value
+ */
+u32 ddr3_cl_to_valid_cl(u32 cl)
+{
+       switch (cl) {
+       case 5:
+               return 2;
+               break;
+       case 6:
+               return 4;
+               break;
+       case 7:
+               return 6;
+               break;
+       case 8:
+               return 8;
+               break;
+       case 9:
+               return 10;
+               break;
+       case 10:
+               return 12;
+               break;
+       case 11:
+               return 14;
+               break;
+       case 12:
+               return 1;
+               break;
+       case 13:
+               return 3;
+               break;
+       case 14:
+               return 5;
+               break;
+       default:
+               return 2;
+       }
+}
+
+/*
+ * Name:     ddr3_cl_to_valid_cl - this return register matching CL value
+ * Desc:
+ * Args:     clValue - the value
+ * Notes:
+ * Returns:  required CL value
+ */
+u32 ddr3_valid_cl_to_cl(u32 ui_valid_cl)
+{
+       switch (ui_valid_cl) {
+       case 1:
+               return 12;
+               break;
+       case 2:
+               return 5;
+               break;
+       case 3:
+               return 13;
+               break;
+       case 4:
+               return 6;
+               break;
+       case 5:
+               return 14;
+               break;
+       case 6:
+               return 7;
+               break;
+       case 8:
+               return 8;
+               break;
+       case 10:
+               return 9;
+               break;
+       case 12:
+               return 10;
+               break;
+       case 14:
+               return 11;
+               break;
+       default:
+               return 0;
+       }
+}
+
+/*
+ * Name:     ddr3_get_cs_num_from_reg
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:
+ */
+u32 ddr3_get_cs_num_from_reg(void)
+{
+       u32 cs_ena = ddr3_get_cs_ena_from_reg();
+       u32 cs_count = 0;
+       u32 cs;
+
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs))
+                       cs_count++;
+       }
+
+       return cs_count;
+}
+
+/*
+ * Name:     ddr3_get_cs_ena_from_reg
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:
+ */
+u32 ddr3_get_cs_ena_from_reg(void)
+{
+       return reg_read(REG_DDR3_RANK_CTRL_ADDR) &
+               REG_DDR3_RANK_CTRL_CS_ENA_MASK;
+}
+
+/*
+ * mv_ctrl_rev_get - Get Marvell controller device revision number
+ *
+ * DESCRIPTION:
+ *       This function returns 8bit describing the device revision as defined
+ *       in PCI Express Class Code and Revision ID Register.
+ *
+ * INPUT:
+ *       None.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       8bit desscribing Marvell controller revision number
+ *
+ */
+#if !defined(MV88F672X)
+u8 mv_ctrl_rev_get(void)
+{
+       u8 rev_num;
+
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+       /* Check pex power state */
+       u32 pex_power;
+       pex_power = mv_ctrl_pwr_clck_get(PEX_UNIT_ID, 0);
+       if (pex_power == 0)
+               mv_ctrl_pwr_clck_set(PEX_UNIT_ID, 0, 1);
+#endif
+       rev_num = (u8)reg_read(PEX_CFG_DIRECT_ACCESS(0,
+                       PCI_CLASS_CODE_AND_REVISION_ID));
+
+#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
+       /* Return to power off state */
+       if (pex_power == 0)
+               mv_ctrl_pwr_clck_set(PEX_UNIT_ID, 0, 0);
+#endif
+
+       return (rev_num & PCCRIR_REVID_MASK) >> PCCRIR_REVID_OFFS;
+}
+
+#endif
+
+#if defined(MV88F672X)
+void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps)
+{
+       u32 tmp, hclk;
+
+       switch (freq_mode) {
+       case CPU_333MHz_DDR_167MHz_L2_167MHz:
+               hclk = 84;
+               tmp = DDR_100;
+               break;
+       case CPU_266MHz_DDR_266MHz_L2_133MHz:
+       case CPU_333MHz_DDR_222MHz_L2_167MHz:
+       case CPU_400MHz_DDR_200MHz_L2_200MHz:
+       case CPU_400MHz_DDR_267MHz_L2_200MHz:
+       case CPU_533MHz_DDR_267MHz_L2_267MHz:
+       case CPU_500MHz_DDR_250MHz_L2_250MHz:
+       case CPU_600MHz_DDR_300MHz_L2_300MHz:
+       case CPU_800MHz_DDR_267MHz_L2_400MHz:
+       case CPU_900MHz_DDR_300MHz_L2_450MHz:
+               tmp = DDR_300;
+               hclk = 150;
+               break;
+       case CPU_333MHz_DDR_333MHz_L2_167MHz:
+       case CPU_500MHz_DDR_334MHz_L2_250MHz:
+       case CPU_666MHz_DDR_333MHz_L2_333MHz:
+               tmp = DDR_333;
+               hclk = 165;
+               break;
+       case CPU_533MHz_DDR_356MHz_L2_267MHz:
+               tmp = DDR_360;
+               hclk = 180;
+               break;
+       case CPU_400MHz_DDR_400MHz_L2_200MHz:
+       case CPU_600MHz_DDR_400MHz_L2_300MHz:
+       case CPU_800MHz_DDR_400MHz_L2_400MHz:
+       case CPU_400MHz_DDR_400MHz_L2_400MHz:
+               tmp = DDR_400;
+               hclk = 200;
+               break;
+       case CPU_666MHz_DDR_444MHz_L2_333MHz:
+       case CPU_900MHz_DDR_450MHz_L2_450MHz:
+               tmp = DDR_444;
+               hclk = 222;
+               break;
+       case CPU_500MHz_DDR_500MHz_L2_250MHz:
+       case CPU_1000MHz_DDR_500MHz_L2_500MHz:
+       case CPU_1000MHz_DDR_500MHz_L2_333MHz:
+               tmp = DDR_500;
+               hclk = 250;
+               break;
+       case CPU_533MHz_DDR_533MHz_L2_267MHz:
+       case CPU_800MHz_DDR_534MHz_L2_400MHz:
+       case CPU_1100MHz_DDR_550MHz_L2_550MHz:
+               tmp = DDR_533;
+               hclk = 267;
+               break;
+       case CPU_600MHz_DDR_600MHz_L2_300MHz:
+       case CPU_900MHz_DDR_600MHz_L2_450MHz:
+       case CPU_1200MHz_DDR_600MHz_L2_600MHz:
+               tmp = DDR_600;
+               hclk = 300;
+               break;
+       case CPU_666MHz_DDR_666MHz_L2_333MHz:
+       case CPU_1000MHz_DDR_667MHz_L2_500MHz:
+               tmp = DDR_666;
+               hclk = 333;
+               break;
+       default:
+               *ddr_freq = 0;
+               *hclk_ps = 0;
+               break;
+       }
+
+       *ddr_freq = tmp;                /* DDR freq define */
+       *hclk_ps = 1000000 / hclk;      /* values are 1/HCLK in ps */
+
+       return;
+}
+#endif
diff --git a/drivers/ddr/mvebu/ddr3_init.h b/drivers/ddr/mvebu/ddr3_init.h
new file mode 100644 (file)
index 0000000..b259e09
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __DDR3_INIT_H
+#define __DDR3_INIT_H
+
+/*
+ * Debug
+ */
+
+/*
+ * MV_DEBUG_INIT need to be defines, otherwise the output of the
+ * DDR2 training code is not complete and misleading
+ */
+#define MV_DEBUG_INIT
+
+#ifdef MV_DEBUG_INIT
+#define DEBUG_INIT_S(s)                        puts(s)
+#define DEBUG_INIT_D(d, l)             printf("%x", d)
+#define DEBUG_INIT_D_10(d, l)          printf("%d", d)
+#else
+#define DEBUG_INIT_S(s)
+#define DEBUG_INIT_D(d, l)
+#define DEBUG_INIT_D_10(d, l)
+#endif
+
+#ifdef MV_DEBUG_INIT_FULL
+#define DEBUG_INIT_FULL_S(s)           puts(s)
+#define DEBUG_INIT_FULL_D(d, l)                printf("%x", d)
+#define DEBUG_INIT_FULL_D_10(d, l)     printf("%d", d)
+#define DEBUG_WR_REG(reg, val) \
+       { DEBUG_INIT_S("Write Reg: 0x"); DEBUG_INIT_D((reg), 8); \
+         DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); }
+#define DEBUG_RD_REG(reg, val) \
+       { DEBUG_INIT_S("Read  Reg: 0x"); DEBUG_INIT_D((reg), 8); \
+         DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); }
+#else
+#define DEBUG_INIT_FULL_S(s)
+#define DEBUG_INIT_FULL_D(d, l)
+#define DEBUG_INIT_FULL_D_10(d, l)
+#define DEBUG_WR_REG(reg, val)
+#define DEBUG_RD_REG(reg, val)
+#endif
+
+#define DEBUG_INIT_FULL_C(s, d, l) \
+       { DEBUG_INIT_FULL_S(s); DEBUG_INIT_FULL_D(d, l); DEBUG_INIT_FULL_S("\n"); }
+#define DEBUG_INIT_C(s, d, l) \
+       { DEBUG_INIT_S(s); DEBUG_INIT_D(d, l); DEBUG_INIT_S("\n"); }
+
+#define MV_MBUS_REGS_OFFSET                 (0x20000)
+
+#include "ddr3_hw_training.h"
+
+#define MAX_DIMM_NUM                   2
+#define SPD_SIZE                       128
+
+#ifdef MV88F78X60
+#include "ddr3_axp.h"
+#elif defined(MV88F67XX)
+#include "ddr3_a370.h"
+#elif defined(MV88F672X)
+#include "ddr3_a375.h"
+#endif
+
+/* DRR training Error codes */
+/* Stage 0 errors */
+#define MV_DDR3_TRAINING_ERR_BAD_SAR                   0xDD300001
+/* Stage 1 errors */
+#define MV_DDR3_TRAINING_ERR_TWSI_FAIL                 0xDD301001
+#define MV_DDR3_TRAINING_ERR_DIMM_TYPE_NO_MATCH                0xDD301001
+#define MV_DDR3_TRAINING_ERR_TWSI_BAD_TYPE             0xDD301003
+#define MV_DDR3_TRAINING_ERR_BUS_WIDTH_NOT_MATCH       0xDD301004
+#define MV_DDR3_TRAINING_ERR_BAD_DIMM_SETUP            0xDD301005
+#define MV_DDR3_TRAINING_ERR_MAX_CS_LIMIT              0xDD301006
+#define MV_DDR3_TRAINING_ERR_MAX_ENA_CS_LIMIT          0xDD301007
+#define MV_DDR3_TRAINING_ERR_BAD_R_DIMM_SETUP          0xDD301008
+/* Stage 2 errors */
+#define MV_DDR3_TRAINING_ERR_HW_FAIL_BASE              0xDD302000
+
+typedef enum config_type {
+       CONFIG_ECC,
+       CONFIG_MULTI_CS,
+       CONFIG_BUS_WIDTH
+} MV_CONFIG_TYPE;
+
+enum log_level  {
+       MV_LOG_LEVEL_0,
+       MV_LOG_LEVEL_1,
+       MV_LOG_LEVEL_2,
+       MV_LOG_LEVEL_3
+};
+
+int ddr3_hw_training(u32 target_freq, u32 ddr_width,
+                    int xor_bypass, u32 scrub_offs, u32 scrub_size,
+                    int dqs_clk_aligned, int debug_mode, int reg_dimm_skip_wl);
+
+void ddr3_print_version(void);
+void fix_pll_val(u8 target_fab);
+u8 ddr3_get_eprom_fabric(void);
+u32 ddr3_get_fab_opt(void);
+u32 ddr3_get_cpu_freq(void);
+u32 ddr3_get_vco_freq(void);
+int ddr3_check_config(u32 addr, MV_CONFIG_TYPE config_type);
+u32 ddr3_get_static_mc_value(u32 reg_addr, u32 offset1, u32 mask1, u32 offset2,
+                            u32 mask2);
+u32 ddr3_cl_to_valid_cl(u32 cl);
+u32 ddr3_valid_cl_to_cl(u32 ui_valid_cl);
+u32 ddr3_get_cs_num_from_reg(void);
+u32 ddr3_get_cs_ena_from_reg(void);
+u8 mv_ctrl_rev_get(void);
+
+u32 ddr3_get_log_level(void);
+
+/* SPD */
+int ddr3_dunit_setup(u32 ecc_ena, u32 hclk_time, u32 *ddr_width);
+
+/*
+ * Accessor functions for the registers
+ */
+static inline void reg_write(u32 addr, u32 val)
+{
+       writel(val, INTER_REGS_BASE + addr);
+}
+
+static inline u32 reg_read(u32 addr)
+{
+       return readl(INTER_REGS_BASE + addr);
+}
+
+static inline void reg_bit_set(u32 addr, u32 mask)
+{
+       setbits_le32(INTER_REGS_BASE + addr, mask);
+}
+
+static inline void reg_bit_clr(u32 addr, u32 mask)
+{
+       clrbits_le32(INTER_REGS_BASE + addr, mask);
+}
+
+#endif /* __DDR3_INIT_H */
diff --git a/drivers/ddr/mvebu/ddr3_patterns_64bit.h b/drivers/ddr/mvebu/ddr3_patterns_64bit.h
new file mode 100644 (file)
index 0000000..1b57328
--- /dev/null
@@ -0,0 +1,924 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __DDR3_PATTERNS_64_H
+#define __DDR3_PATTERNS_64_H
+
+/*
+ * Patterns Declerations
+ */
+
+u32 wl_sup_pattern[LEN_WL_SUP_PATTERN] __aligned(32) = {
+       0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d,
+       0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d,
+       0x24232221, 0x28272625, 0x2c2b2a29, 0x302f2e2d,
+       0x34333231, 0x38373635, 0x3c3b3a39, 0x403f3e3d,
+       0x44434241, 0x48474645, 0x4c4b4a49, 0x504f4e4d,
+       0x54535251, 0x58575655, 0x5c5b5a59, 0x605f5e5d,
+       0x64636261, 0x68676665, 0x6c6b6a69, 0x706f6e6d,
+       0x74737271, 0x78777675, 0x7c7b7a79, 0x807f7e7d
+};
+
+u32 pbs_pattern_32b[2][LEN_PBS_PATTERN] __aligned(32) = {
+       {
+               0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555,
+               0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555,
+               0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555,
+               0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x55555555
+       },
+       {
+               0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA,
+               0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA,
+               0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA,
+               0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA
+       }
+};
+
+u32 pbs_pattern_64b[2][LEN_PBS_PATTERN] __aligned(32) = {
+       {
+               0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+               0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+               0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+               0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555
+       },
+       {
+               0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+               0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+               0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+               0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA
+       }
+};
+
+u32 rl_pattern[LEN_STD_PATTERN] __aligned(32) = {
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x01010101, 0x01010101, 0x01010101, 0x01010101
+};
+
+u32 killer_pattern_32b[DQ_NUM][LEN_KILLER_PATTERN] __aligned(32) = {
+       {
+               0x01010101, 0x00000000, 0x01010101, 0xFFFFFFFF,
+               0x01010101, 0x00000000, 0x01010101, 0xFFFFFFFF,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0xFEFEFEFE,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0xFEFEFEFE,
+               0x01010101, 0xFEFEFEFE, 0x01010101, 0x01010101,
+               0x01010101, 0xFEFEFEFE, 0x01010101, 0x01010101,
+               0xFEFEFEFE, 0x01010101, 0xFEFEFEFE, 0x00000000,
+               0xFEFEFEFE, 0x01010101, 0xFEFEFEFE, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x01010101,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x01010101,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0xFEFEFEFE,
+               0x00000000, 0x00000000, 0x00000000, 0xFEFEFEFE,
+               0xFEFEFEFE, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFEFEFEFE, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFEFEFEFE, 0x00000000, 0xFEFEFEFE, 0x00000000,
+               0xFEFEFEFE, 0x00000000, 0xFEFEFEFE, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x01010101,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x01010101,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x00000000,
+               0x01010101, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE,
+               0x01010101, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE
+       },
+       {
+               0x02020202, 0x00000000, 0x02020202, 0xFFFFFFFF,
+               0x02020202, 0x00000000, 0x02020202, 0xFFFFFFFF,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0xFDFDFDFD,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0xFDFDFDFD,
+               0x02020202, 0xFDFDFDFD, 0x02020202, 0x02020202,
+               0x02020202, 0xFDFDFDFD, 0x02020202, 0x02020202,
+               0xFDFDFDFD, 0x02020202, 0xFDFDFDFD, 0x00000000,
+               0xFDFDFDFD, 0x02020202, 0xFDFDFDFD, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x02020202,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x02020202,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0xFDFDFDFD,
+               0x00000000, 0x00000000, 0x00000000, 0xFDFDFDFD,
+               0xFDFDFDFD, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFDFDFDFD, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFDFDFDFD, 0x00000000, 0xFDFDFDFD, 0x00000000,
+               0xFDFDFDFD, 0x00000000, 0xFDFDFDFD, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x02020202,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x02020202,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x00000000,
+               0x02020202, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD,
+               0x02020202, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD
+       },
+       {
+               0x04040404, 0x00000000, 0x04040404, 0xFFFFFFFF,
+               0x04040404, 0x00000000, 0x04040404, 0xFFFFFFFF,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0xFBFBFBFB,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0xFBFBFBFB,
+               0x04040404, 0xFBFBFBFB, 0x04040404, 0x04040404,
+               0x04040404, 0xFBFBFBFB, 0x04040404, 0x04040404,
+               0xFBFBFBFB, 0x04040404, 0xFBFBFBFB, 0x00000000,
+               0xFBFBFBFB, 0x04040404, 0xFBFBFBFB, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x04040404,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x04040404,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0xFBFBFBFB,
+               0x00000000, 0x00000000, 0x00000000, 0xFBFBFBFB,
+               0xFBFBFBFB, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFBFBFBFB, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFBFBFBFB, 0x00000000, 0xFBFBFBFB, 0x00000000,
+               0xFBFBFBFB, 0x00000000, 0xFBFBFBFB, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x04040404,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x04040404,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x00000000,
+               0x04040404, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB,
+               0x04040404, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB
+       },
+       {
+               0x08080808, 0x00000000, 0x08080808, 0xFFFFFFFF,
+               0x08080808, 0x00000000, 0x08080808, 0xFFFFFFFF,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0xF7F7F7F7,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0xF7F7F7F7,
+               0x08080808, 0xF7F7F7F7, 0x08080808, 0x08080808,
+               0x08080808, 0xF7F7F7F7, 0x08080808, 0x08080808,
+               0xF7F7F7F7, 0x08080808, 0xF7F7F7F7, 0x00000000,
+               0xF7F7F7F7, 0x08080808, 0xF7F7F7F7, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x08080808,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x08080808,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0xF7F7F7F7,
+               0x00000000, 0x00000000, 0x00000000, 0xF7F7F7F7,
+               0xF7F7F7F7, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xF7F7F7F7, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xF7F7F7F7, 0x00000000, 0xF7F7F7F7, 0x00000000,
+               0xF7F7F7F7, 0x00000000, 0xF7F7F7F7, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x08080808,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x08080808,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x00000000,
+               0x08080808, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7,
+               0x08080808, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7
+       },
+       {
+               0x10101010, 0x00000000, 0x10101010, 0xFFFFFFFF,
+               0x10101010, 0x00000000, 0x10101010, 0xFFFFFFFF,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0xEFEFEFEF,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0xEFEFEFEF,
+               0x10101010, 0xEFEFEFEF, 0x10101010, 0x10101010,
+               0x10101010, 0xEFEFEFEF, 0x10101010, 0x10101010,
+               0xEFEFEFEF, 0x10101010, 0xEFEFEFEF, 0x00000000,
+               0xEFEFEFEF, 0x10101010, 0xEFEFEFEF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x10101010,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x10101010,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0xEFEFEFEF,
+               0x00000000, 0x00000000, 0x00000000, 0xEFEFEFEF,
+               0xEFEFEFEF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xEFEFEFEF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xEFEFEFEF, 0x00000000, 0xEFEFEFEF, 0x00000000,
+               0xEFEFEFEF, 0x00000000, 0xEFEFEFEF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x10101010,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x10101010,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x00000000,
+               0x10101010, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF,
+               0x10101010, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF
+       },
+       {
+               0x20202020, 0x00000000, 0x20202020, 0xFFFFFFFF,
+               0x20202020, 0x00000000, 0x20202020, 0xFFFFFFFF,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0xDFDFDFDF,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0xDFDFDFDF,
+               0x20202020, 0xDFDFDFDF, 0x20202020, 0x20202020,
+               0x20202020, 0xDFDFDFDF, 0x20202020, 0x20202020,
+               0xDFDFDFDF, 0x20202020, 0xDFDFDFDF, 0x00000000,
+               0xDFDFDFDF, 0x20202020, 0xDFDFDFDF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x20202020,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x20202020,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0xDFDFDFDF,
+               0x00000000, 0x00000000, 0x00000000, 0xDFDFDFDF,
+               0xDFDFDFDF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xDFDFDFDF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xDFDFDFDF, 0x00000000, 0xDFDFDFDF, 0x00000000,
+               0xDFDFDFDF, 0x00000000, 0xDFDFDFDF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x20202020,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x20202020,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x00000000,
+               0x20202020, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF,
+               0x20202020, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF
+       },
+       {
+               0x40404040, 0x00000000, 0x40404040, 0xFFFFFFFF,
+               0x40404040, 0x00000000, 0x40404040, 0xFFFFFFFF,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0xBFBFBFBF,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0xBFBFBFBF,
+               0x40404040, 0xBFBFBFBF, 0x40404040, 0x40404040,
+               0x40404040, 0xBFBFBFBF, 0x40404040, 0x40404040,
+               0xBFBFBFBF, 0x40404040, 0xBFBFBFBF, 0x00000000,
+               0xBFBFBFBF, 0x40404040, 0xBFBFBFBF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x40404040,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x40404040,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0xBFBFBFBF,
+               0x00000000, 0x00000000, 0x00000000, 0xBFBFBFBF,
+               0xBFBFBFBF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xBFBFBFBF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xBFBFBFBF, 0x00000000, 0xBFBFBFBF, 0x00000000,
+               0xBFBFBFBF, 0x00000000, 0xBFBFBFBF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x40404040,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x40404040,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x00000000,
+               0x40404040, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF,
+               0x40404040, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF
+       },
+       {
+               0x80808080, 0x00000000, 0x80808080, 0xFFFFFFFF,
+               0x80808080, 0x00000000, 0x80808080, 0xFFFFFFFF,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x7F7F7F7F,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x7F7F7F7F,
+               0x80808080, 0x7F7F7F7F, 0x80808080, 0x80808080,
+               0x80808080, 0x7F7F7F7F, 0x80808080, 0x80808080,
+               0x7F7F7F7F, 0x80808080, 0x7F7F7F7F, 0x00000000,
+               0x7F7F7F7F, 0x80808080, 0x7F7F7F7F, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x80808080,
+               0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x80808080,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x7F7F7F7F,
+               0x00000000, 0x00000000, 0x00000000, 0x7F7F7F7F,
+               0x7F7F7F7F, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x7F7F7F7F, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
+               0x7F7F7F7F, 0x00000000, 0x7F7F7F7F, 0x00000000,
+               0x7F7F7F7F, 0x00000000, 0x7F7F7F7F, 0x00000000,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x80808080,
+               0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x80808080,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x00000000,
+               0x80808080, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x80808080, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F
+       }
+};
+
+u32 killer_pattern_64b[DQ_NUM][LEN_KILLER_PATTERN] __aligned(32) = {
+       {
+               0x01010101, 0x01010101, 0x00000000, 0x00000000,
+               0x01010101, 0x01010101, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE,
+               0x01010101, 0x01010101, 0xFEFEFEFE, 0xFEFEFEFE,
+               0x01010101, 0x01010101, 0xFEFEFEFE, 0xFEFEFEFE,
+               0x01010101, 0x01010101, 0x01010101, 0x01010101,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0x01010101,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x01010101,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFEFEFEFE, 0xFEFEFEFE,
+               0xFEFEFEFE, 0xFEFEFEFE, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x00000000, 0x00000000,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x01010101,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x01010101, 0x01010101, 0x00000000, 0x00000000,
+               0x01010101, 0x01010101, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE
+       },
+       {
+               0x02020202, 0x02020202, 0x00000000, 0x00000000,
+               0x02020202, 0x02020202, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD,
+               0x02020202, 0x02020202, 0xFDFDFDFD, 0xFDFDFDFD,
+               0x02020202, 0x02020202, 0xFDFDFDFD, 0xFDFDFDFD,
+               0x02020202, 0x02020202, 0x02020202, 0x02020202,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0x02020202,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x02020202,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFDFDFDFD, 0xFDFDFDFD,
+               0xFDFDFDFD, 0xFDFDFDFD, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x00000000, 0x00000000,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x02020202,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x02020202, 0x02020202, 0x00000000, 0x00000000,
+               0x02020202, 0x02020202, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD
+       },
+       {
+               0x04040404, 0x04040404, 0x00000000, 0x00000000,
+               0x04040404, 0x04040404, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB,
+               0x04040404, 0x04040404, 0xFBFBFBFB, 0xFBFBFBFB,
+               0x04040404, 0x04040404, 0xFBFBFBFB, 0xFBFBFBFB,
+               0x04040404, 0x04040404, 0x04040404, 0x04040404,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0x04040404,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x04040404,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFBFBFBFB, 0xFBFBFBFB,
+               0xFBFBFBFB, 0xFBFBFBFB, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x00000000, 0x00000000,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x04040404,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x04040404, 0x04040404, 0x00000000, 0x00000000,
+               0x04040404, 0x04040404, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB
+       },
+       {
+               0x08080808, 0x08080808, 0x00000000, 0x00000000,
+               0x08080808, 0x08080808, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7,
+               0x08080808, 0x08080808, 0xF7F7F7F7, 0xF7F7F7F7,
+               0x08080808, 0x08080808, 0xF7F7F7F7, 0xF7F7F7F7,
+               0x08080808, 0x08080808, 0x08080808, 0x08080808,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0x08080808,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x08080808,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xF7F7F7F7, 0xF7F7F7F7,
+               0xF7F7F7F7, 0xF7F7F7F7, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x00000000, 0x00000000,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x08080808,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x08080808, 0x08080808, 0x00000000, 0x00000000,
+               0x08080808, 0x08080808, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7
+       },
+       {
+               0x10101010, 0x10101010, 0x00000000, 0x00000000,
+               0x10101010, 0x10101010, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF,
+               0x10101010, 0x10101010, 0xEFEFEFEF, 0xEFEFEFEF,
+               0x10101010, 0x10101010, 0xEFEFEFEF, 0xEFEFEFEF,
+               0x10101010, 0x10101010, 0x10101010, 0x10101010,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0x10101010,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x10101010,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xEFEFEFEF, 0xEFEFEFEF,
+               0xEFEFEFEF, 0xEFEFEFEF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x00000000, 0x00000000,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x10101010,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x10101010, 0x10101010, 0x00000000, 0x00000000,
+               0x10101010, 0x10101010, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF
+       },
+       {
+               0x20202020, 0x20202020, 0x00000000, 0x00000000,
+               0x20202020, 0x20202020, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF,
+               0x20202020, 0x20202020, 0xDFDFDFDF, 0xDFDFDFDF,
+               0x20202020, 0x20202020, 0xDFDFDFDF, 0xDFDFDFDF,
+               0x20202020, 0x20202020, 0x20202020, 0x20202020,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0x20202020,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x20202020,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xDFDFDFDF, 0xDFDFDFDF,
+               0xDFDFDFDF, 0xDFDFDFDF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x00000000, 0x00000000,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x20202020,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x20202020, 0x20202020, 0x00000000, 0x00000000,
+               0x20202020, 0x20202020, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF
+       },
+       {
+               0x40404040, 0x40404040, 0x00000000, 0x00000000,
+               0x40404040, 0x40404040, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF,
+               0x40404040, 0x40404040, 0xBFBFBFBF, 0xBFBFBFBF,
+               0x40404040, 0x40404040, 0xBFBFBFBF, 0xBFBFBFBF,
+               0x40404040, 0x40404040, 0x40404040, 0x40404040,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0x40404040,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x40404040,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xBFBFBFBF, 0xBFBFBFBF,
+               0xBFBFBFBF, 0xBFBFBFBF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x00000000, 0x00000000,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x40404040,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x40404040, 0x40404040, 0x00000000, 0x00000000,
+               0x40404040, 0x40404040, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF
+       },
+       {
+               0x80808080, 0x80808080, 0x00000000, 0x00000000,
+               0x80808080, 0x80808080, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x80808080, 0x80808080, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x80808080, 0x80808080, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x80808080, 0x80808080, 0x80808080, 0x80808080,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x80808080,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x80808080,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x7F7F7F7F, 0x7F7F7F7F, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x00000000, 0x00000000,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x80808080,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x80808080, 0x80808080, 0x00000000, 0x00000000,
+               0x80808080, 0x80808080, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F
+       }
+};
+
+u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN] __aligned(32) = {
+       {
+               0x00000000, 0x00000000, 0x01010101, 0x01010101,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0x01010101,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0x01010101,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x01010101, 0x01010101,
+               0x01010101, 0x01010101, 0xFEFEFEFE, 0xFEFEFEFE,
+               0x01010101, 0x01010101, 0xFEFEFEFE, 0xFEFEFEFE,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x01010101, 0x01010101, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE, 0xFEFEFEFE,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE,
+               0x00000000, 0x00000000, 0xFEFEFEFE, 0xFEFEFEFE,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x01010101, 0x01010101, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x01010101, 0x01010101,
+               0x00000000, 0x00000000, 0x01010101, 0x01010101,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFEFEFEFE, 0xFEFEFEFE,
+               0xFEFEFEFE, 0xFEFEFEFE, 0x00000000, 0x00000000
+       },
+       {
+               0x00000000, 0x00000000, 0x02020202, 0x02020202,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0x02020202,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0x02020202,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x02020202, 0x02020202,
+               0x02020202, 0x02020202, 0xFDFDFDFD, 0xFDFDFDFD,
+               0x02020202, 0x02020202, 0xFDFDFDFD, 0xFDFDFDFD,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x02020202, 0x02020202, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD, 0xFDFDFDFD,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD,
+               0x00000000, 0x00000000, 0xFDFDFDFD, 0xFDFDFDFD,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x02020202, 0x02020202, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x02020202, 0x02020202,
+               0x00000000, 0x00000000, 0x02020202, 0x02020202,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFDFDFDFD, 0xFDFDFDFD,
+               0xFDFDFDFD, 0xFDFDFDFD, 0x00000000, 0x00000000
+       },
+       {
+               0x00000000, 0x00000000, 0x04040404, 0x04040404,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0x04040404,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0x04040404,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x04040404, 0x04040404,
+               0x04040404, 0x04040404, 0xFBFBFBFB, 0xFBFBFBFB,
+               0x04040404, 0x04040404, 0xFBFBFBFB, 0xFBFBFBFB,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x04040404, 0x04040404, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB, 0xFBFBFBFB,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB,
+               0x00000000, 0x00000000, 0xFBFBFBFB, 0xFBFBFBFB,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x04040404, 0x04040404, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x04040404, 0x04040404,
+               0x00000000, 0x00000000, 0x04040404, 0x04040404,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFBFBFBFB, 0xFBFBFBFB,
+               0xFBFBFBFB, 0xFBFBFBFB, 0x00000000, 0x00000000
+       },
+       {
+               0x00000000, 0x00000000, 0x08080808, 0x08080808,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0x08080808,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0x08080808,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x08080808, 0x08080808,
+               0x08080808, 0x08080808, 0xF7F7F7F7, 0xF7F7F7F7,
+               0x08080808, 0x08080808, 0xF7F7F7F7, 0xF7F7F7F7,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x08080808, 0x08080808, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7, 0xF7F7F7F7,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7,
+               0x00000000, 0x00000000, 0xF7F7F7F7, 0xF7F7F7F7,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x08080808, 0x08080808, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x08080808, 0x08080808,
+               0x00000000, 0x00000000, 0x08080808, 0x08080808,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xF7F7F7F7, 0xF7F7F7F7,
+               0xF7F7F7F7, 0xF7F7F7F7, 0x00000000, 0x00000000
+       },
+       {
+               0x00000000, 0x00000000, 0x10101010, 0x10101010,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0x10101010,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0x10101010,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x10101010, 0x10101010,
+               0x10101010, 0x10101010, 0xEFEFEFEF, 0xEFEFEFEF,
+               0x10101010, 0x10101010, 0xEFEFEFEF, 0xEFEFEFEF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x10101010, 0x10101010, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF, 0xEFEFEFEF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF,
+               0x00000000, 0x00000000, 0xEFEFEFEF, 0xEFEFEFEF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x10101010, 0x10101010, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x10101010, 0x10101010,
+               0x00000000, 0x00000000, 0x10101010, 0x10101010,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xEFEFEFEF, 0xEFEFEFEF,
+               0xEFEFEFEF, 0xEFEFEFEF, 0x00000000, 0x00000000
+       },
+       {
+               0x00000000, 0x00000000, 0x20202020, 0x20202020,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0x20202020,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0x20202020,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x20202020, 0x20202020,
+               0x20202020, 0x20202020, 0xDFDFDFDF, 0xDFDFDFDF,
+               0x20202020, 0x20202020, 0xDFDFDFDF, 0xDFDFDFDF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x20202020, 0x20202020, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF, 0xDFDFDFDF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF,
+               0x00000000, 0x00000000, 0xDFDFDFDF, 0xDFDFDFDF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x20202020, 0x20202020, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x20202020, 0x20202020,
+               0x00000000, 0x00000000, 0x20202020, 0x20202020,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xDFDFDFDF, 0xDFDFDFDF,
+               0xDFDFDFDF, 0xDFDFDFDF, 0x00000000, 0x00000000
+       },
+       {
+               0x00000000, 0x00000000, 0x40404040, 0x40404040,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0x40404040,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0x40404040,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x40404040, 0x40404040,
+               0x40404040, 0x40404040, 0xBFBFBFBF, 0xBFBFBFBF,
+               0x40404040, 0x40404040, 0xBFBFBFBF, 0xBFBFBFBF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x40404040, 0x40404040, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF, 0xBFBFBFBF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF,
+               0x00000000, 0x00000000, 0xBFBFBFBF, 0xBFBFBFBF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x40404040, 0x40404040, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x40404040, 0x40404040,
+               0x00000000, 0x00000000, 0x40404040, 0x40404040,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xBFBFBFBF, 0xBFBFBFBF,
+               0xBFBFBFBF, 0xBFBFBFBF, 0x00000000, 0x00000000
+       },
+       {
+               0x00000000, 0x00000000, 0x80808080, 0x80808080,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x80808080,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x80808080,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x80808080, 0x80808080,
+               0x80808080, 0x80808080, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x80808080, 0x80808080, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x80808080, 0x80808080, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x00000000, 0x00000000, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x00000000, 0x00000000, 0x00000000, 0x00000000,
+               0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+               0x80808080, 0x80808080, 0xFFFFFFFF, 0xFFFFFFFF,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x80808080, 0x80808080,
+               0x00000000, 0x00000000, 0x80808080, 0x80808080,
+               0xFFFFFFFF, 0xFFFFFFFF, 0x7F7F7F7F, 0x7F7F7F7F,
+               0x7F7F7F7F, 0x7F7F7F7F, 0x00000000, 0x00000000
+       }
+};
+
+/* Fabric ratios table */
+u32 fabric_ratio[FAB_OPT] = {
+       0x04010204,
+       0x04020202,
+       0x08020306,
+       0x08020303,
+       0x04020303,
+       0x04020204,
+       0x04010202,
+       0x08030606,
+       0x08030505,
+       0x04020306,
+       0x0804050A,
+       0x04030606,
+       0x04020404,
+       0x04030306,
+       0x04020505,
+       0x08020505,
+       0x04010303,
+       0x08050A0A,
+       0x04030408,
+       0x04010102,
+       0x08030306
+};
+
+u32 pbs_dq_mapping[PUP_NUM_64BIT + 1][DQ_NUM] = {
+       {3, 2, 5, 7, 1, 0, 6, 4},
+       {2, 3, 6, 7, 1, 0, 4, 5},
+       {1, 3, 5, 6, 0, 2, 4, 7},
+       {0, 2, 4, 7, 1, 3, 5, 6},
+       {3, 0, 4, 6, 1, 2, 5, 7},
+       {0, 3, 5, 7, 1, 2, 4, 6},
+       {2, 3, 5, 7, 1, 0, 4, 6},
+       {0, 2, 5, 4, 1, 3, 6, 7},
+       {2, 3, 4, 7, 0, 1, 5, 6}
+};
+
+#endif /* __DDR3_PATTERNS_64_H */
diff --git a/drivers/ddr/mvebu/ddr3_pbs.c b/drivers/ddr/mvebu/ddr3_pbs.c
new file mode 100644 (file)
index 0000000..00ea3fd
--- /dev/null
@@ -0,0 +1,1592 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_PBS_FULL_C(s, d, l) \
+       DEBUG_PBS_FULL_S(s); DEBUG_PBS_FULL_D(d, l); DEBUG_PBS_FULL_S("\n")
+#define DEBUG_PBS_C(s, d, l) \
+       DEBUG_PBS_S(s); DEBUG_PBS_D(d, l); DEBUG_PBS_S("\n")
+
+#ifdef MV_DEBUG_PBS
+#define DEBUG_PBS_S(s)                 puts(s)
+#define DEBUG_PBS_D(d, l)              printf("%x", d)
+#else
+#define DEBUG_PBS_S(s)
+#define DEBUG_PBS_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_FULL_PBS
+#define DEBUG_PBS_FULL_S(s)            puts(s)
+#define DEBUG_PBS_FULL_D(d, l)         printf("%x", d)
+#else
+#define DEBUG_PBS_FULL_S(s)
+#define DEBUG_PBS_FULL_D(d, l)
+#endif
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+
+/* Temp array for skew data storage */
+static u32 skew_array[(MAX_PUP_NUM) * DQ_NUM] = { 0 };
+
+/* PBS locked dq (per pup) */
+extern u32 pbs_locked_dq[MAX_PUP_NUM][DQ_NUM];
+extern u32 pbs_locked_dm[MAX_PUP_NUM];
+extern u32 pbs_locked_value[MAX_PUP_NUM][DQ_NUM];
+
+#if defined(MV88F672X)
+extern u32 pbs_pattern[2][LEN_16BIT_PBS_PATTERN];
+extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN];
+#else
+extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN];
+extern u32 pbs_pattern_64b[2][LEN_PBS_PATTERN];
+#endif
+
+extern u32 pbs_dq_mapping[PUP_NUM_64BIT + 1][DQ_NUM];
+
+static int ddr3_tx_shift_dqs_adll_step_before_fail(MV_DRAM_INFO *dram_info,
+               u32 cur_pup, u32 pbs_pattern_idx, u32 ecc);
+static int ddr3_rx_shift_dqs_to_first_fail(MV_DRAM_INFO *dram_info, u32 cur_pup,
+               u32 pbs_pattern_idx, u32 ecc);
+static int ddr3_pbs_per_bit(MV_DRAM_INFO *dram_info, int *start_over, int is_tx,
+               u32 *pcur_pup, u32 pbs_pattern_idx, u32 ecc);
+static int ddr3_set_pbs_results(MV_DRAM_INFO *dram_info, int is_tx);
+static void ddr3_pbs_write_pup_dqs_reg(u32 cs, u32 pup, u32 dqs_delay);
+
+/*
+ * Name:     ddr3_pbs_tx
+ * Desc:     Execute the PBS TX phase.
+ * Args:     dram_info   ddr3 training information struct
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_pbs_tx(MV_DRAM_INFO *dram_info)
+{
+       /* Array of Deskew results */
+
+       /*
+        * Array to hold the total sum of skew from all iterations
+        * (for average purpose)
+        */
+       u32 skew_sum_array[MAX_PUP_NUM][DQ_NUM] = { {0} };
+
+       /*
+        * Array to hold the total average skew from both patterns
+        * (for average purpose)
+        */
+       u32 pattern_skew_array[MAX_PUP_NUM][DQ_NUM] = { {0} };
+
+       u32 pbs_rep_time = 0;   /* counts number of loop in case of fail */
+       /* bit array for unlock pups - used to repeat on the RX operation */
+       u32 cur_pup;
+       u32 max_pup;
+       u32 pbs_retry;
+       u32 pup, dq, pups, cur_max_pup, valid_pup, reg;
+       u32 pattern_idx;
+       u32 ecc;
+       /* indicates whether we need to start the loop again */
+       int start_over;
+
+       DEBUG_PBS_S("DDR3 - PBS TX - Starting PBS TX procedure\n");
+
+       pups = dram_info->num_of_total_pups;
+       max_pup = dram_info->num_of_total_pups;
+
+       /* Enable SW override */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* [0] = 1 - Enable SW override  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+       DEBUG_PBS_S("DDR3 - PBS RX - SW Override Enabled\n");
+
+       reg = 1 << REG_DRAM_TRAINING_AUTO_OFFS;
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       /* Running twice for 2 different patterns. each patterns - 3 times */
+       for (pattern_idx = 0; pattern_idx < COUNT_PBS_PATTERN; pattern_idx++) {
+               DEBUG_PBS_C("DDR3 - PBS TX - Working with pattern - ",
+                           pattern_idx, 1);
+
+               /* Reset sum array */
+               for (pup = 0; pup < pups; pup++) {
+                       for (dq = 0; dq < DQ_NUM; dq++)
+                               skew_sum_array[pup][dq] = 0;
+               }
+
+               /*
+                * Perform PBS several of times (3 for each pattern).
+                * At the end, we'll use the average
+                */
+               /* If there is ECC, do each PBS again with mux change */
+               for (pbs_retry = 0; pbs_retry < COUNT_PBS_REPEAT; pbs_retry++) {
+                       for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
+
+                               /*
+                                * This parameter stores the current PUP
+                                * num - ecc mode dependent - 4-8 / 1 pups
+                                */
+                               cur_max_pup = (1 - ecc) *
+                                       dram_info->num_of_std_pups + ecc;
+
+                               if (ecc) {
+                                       /* Only 1 pup in this case */
+                                       valid_pup = 0x1;
+                               } else if (cur_max_pup > 4) {
+                                       /* 64 bit - 8 pups */
+                                       valid_pup = 0xFF;
+                               } else if (cur_max_pup == 4) {
+                                       /* 32 bit - 4 pups */
+                                       valid_pup = 0xF;
+                               } else {
+                                       /* 16 bit - 2 pups */
+                                       valid_pup = 0x3;
+                               }
+
+                               /* ECC Support - Switch ECC Mux on ecc=1 */
+                               reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+                                       ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg |= (dram_info->ecc_ena * ecc <<
+                                       REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+                               if (ecc)
+                                       DEBUG_PBS_S("DDR3 - PBS Tx - ECC Mux Enabled\n");
+                               else
+                                       DEBUG_PBS_S("DDR3 - PBS Tx - ECC Mux Disabled\n");
+
+                               /* Init iteration values */
+                               /* Clear the locked DQs */
+                               for (pup = 0; pup < cur_max_pup; pup++) {
+                                       for (dq = 0; dq < DQ_NUM; dq++) {
+                                               pbs_locked_dq[
+                                                       pup + ecc *
+                                                       (max_pup - 1)][dq] =
+                                                       0;
+                                       }
+                               }
+
+                               pbs_rep_time = 0;
+                               cur_pup = valid_pup;
+                               start_over = 0;
+
+                               /*
+                                * Run loop On current Pattern and current
+                                * pattern iteration (just to cover the false
+                                * fail problem)
+                                */
+                               do {
+                                       DEBUG_PBS_S("DDR3 - PBS Tx - Pbs Rep Loop is ");
+                                       DEBUG_PBS_D(pbs_rep_time, 1);
+                                       DEBUG_PBS_S(", for Retry No.");
+                                       DEBUG_PBS_D(pbs_retry, 1);
+                                       DEBUG_PBS_S("\n");
+
+                                       /* Set all PBS values to MIN (0) */
+                                       DEBUG_PBS_S("DDR3 - PBS Tx - Set all PBS values to MIN\n");
+
+                                       for (dq = 0; dq < DQ_NUM; dq++) {
+                                               ddr3_write_pup_reg(
+                                                       PUP_PBS_TX +
+                                                       pbs_dq_mapping[pup *
+                                                               (1 - ecc) +
+                                                               ecc * ECC_PUP]
+                                                       [dq], CS0, (1 - ecc) *
+                                                       PUP_BC + ecc * ECC_PUP, 0,
+                                                       0);
+                                       }
+
+                                       /*
+                                        * Shift DQ ADLL right, One step before
+                                        * fail
+                                        */
+                                       DEBUG_PBS_S("DDR3 - PBS Tx - ADLL shift right one phase before fail\n");
+
+                                       if (MV_OK != ddr3_tx_shift_dqs_adll_step_before_fail
+                                           (dram_info, cur_pup, pattern_idx,
+                                            ecc))
+                                               return MV_DDR3_TRAINING_ERR_PBS_ADLL_SHR_1PHASE;
+
+                                       /* PBS For each bit */
+                                       DEBUG_PBS_S("DDR3 - PBS Tx - perform PBS for each bit\n");
+
+                                       /*
+                                        * In this stage - start_over = 0
+                                        */
+                                       if (MV_OK != ddr3_pbs_per_bit(
+                                                   dram_info, &start_over, 1,
+                                                   &cur_pup, pattern_idx, ecc))
+                                               return MV_DDR3_TRAINING_ERR_PBS_TX_PER_BIT;
+
+                               } while ((start_over == 1) &&
+                                        (++pbs_rep_time < COUNT_PBS_STARTOVER));
+
+                               if (pbs_rep_time == COUNT_PBS_STARTOVER &&
+                                   start_over == 1) {
+                                       DEBUG_PBS_S("DDR3 - PBS Tx - FAIL - Adll reach max value\n");
+                                       return MV_DDR3_TRAINING_ERR_PBS_TX_MAX_VAL;
+                               }
+
+                               DEBUG_PBS_FULL_C("DDR3 - PBS TX - values for iteration - ",
+                                                pbs_retry, 1);
+                               for (pup = 0; pup < cur_max_pup; pup++) {
+                                       /*
+                                        * To minimize delay elements, inc
+                                        * from pbs value the min pbs val
+                                        */
+                                       DEBUG_PBS_S("DDR3 - PBS - PUP");
+                                       DEBUG_PBS_D((pup + (ecc * ECC_PUP)), 1);
+                                       DEBUG_PBS_S(": ");
+
+                                       for (dq = 0; dq < DQ_NUM; dq++) {
+                                               /* Set skew value for all dq */
+                                               /*
+                                                * Bit# Deskew <- Bit# Deskew -
+                                                * last / first  failing bit
+                                                * Deskew For all bits (per PUP)
+                                                * (minimize delay elements)
+                                                */
+                                               DEBUG_PBS_S("DQ");
+                                               DEBUG_PBS_D(dq, 1);
+                                               DEBUG_PBS_S("-");
+                                               DEBUG_PBS_D(skew_array
+                                                           [((pup) * DQ_NUM) +
+                                                            dq], 2);
+                                               DEBUG_PBS_S(", ");
+                                       }
+                                       DEBUG_PBS_S("\n");
+                               }
+
+                               /*
+                                * Collect the results we got on this trial
+                                * of PBS
+                                */
+                               for (pup = 0; pup < cur_max_pup; pup++) {
+                                       for (dq = 0; dq < DQ_NUM; dq++) {
+                                               skew_sum_array[pup + (ecc * (max_pup - 1))]
+                                                       [dq] += skew_array
+                                                       [((pup) * DQ_NUM) + dq];
+                                       }
+                               }
+
+                               /* ECC Support - Disable ECC MUX */
+                               reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+                                       ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+                       }
+               }
+
+               DEBUG_PBS_C("DDR3 - PBS TX - values for current pattern - ",
+                           pattern_idx, 1);
+               for (pup = 0; pup < max_pup; pup++) {
+                       /*
+                        * To minimize delay elements, inc from pbs value the
+                        * min pbs val
+                        */
+                       DEBUG_PBS_S("DDR3 - PBS - PUP");
+                       DEBUG_PBS_D(pup, 1);
+                       DEBUG_PBS_S(": ");
+
+                       for (dq = 0; dq < DQ_NUM; dq++) {
+                               /* set skew value for all dq */
+                               /* Bit# Deskew <- Bit# Deskew - last / first  failing bit Deskew For all bits (per PUP) (minimize delay elements) */
+                               DEBUG_PBS_S("DQ");
+                               DEBUG_PBS_D(dq, 1);
+                               DEBUG_PBS_S("-");
+                               DEBUG_PBS_D(skew_sum_array[pup][dq] /
+                                           COUNT_PBS_REPEAT, 2);
+                               DEBUG_PBS_S(", ");
+                       }
+                       DEBUG_PBS_S("\n");
+               }
+
+               /*
+                * Calculate the average skew for current pattern for each
+                * pup and each bit
+                */
+               DEBUG_PBS_C("DDR3 - PBS TX - Average for pattern - ",
+                           pattern_idx, 1);
+
+               for (pup = 0; pup < max_pup; pup++) {
+                       /*
+                        * FOR ECC only :: found min and max value for current
+                        * pattern skew array
+                        */
+                       /* Loop for all dqs */
+                       for (dq = 0; dq < DQ_NUM; dq++) {
+                               pattern_skew_array[pup][dq] +=
+                                       (skew_sum_array[pup][dq] /
+                                        COUNT_PBS_REPEAT);
+                       }
+               }
+       }
+
+       /* Calculate the average skew */
+       for (pup = 0; pup < max_pup; pup++) {
+               for (dq = 0; dq < DQ_NUM; dq++)
+                       skew_array[((pup) * DQ_NUM) + dq] =
+                               pattern_skew_array[pup][dq] / COUNT_PBS_PATTERN;
+       }
+
+       DEBUG_PBS_S("DDR3 - PBS TX - Average for all patterns:\n");
+       for (pup = 0; pup < max_pup; pup++) {
+               /*
+                * To minimize delay elements, inc from pbs value the min
+                * pbs val
+                */
+               DEBUG_PBS_S("DDR3 - PBS - PUP");
+               DEBUG_PBS_D(pup, 1);
+               DEBUG_PBS_S(": ");
+
+               for (dq = 0; dq < DQ_NUM; dq++) {
+                       /* Set skew value for all dq */
+                       /*
+                        * Bit# Deskew <- Bit# Deskew - last / first
+                        * failing bit Deskew For all bits (per PUP)
+                        * (minimize delay elements)
+                        */
+                       DEBUG_PBS_S("DQ");
+                       DEBUG_PBS_D(dq, 1);
+                       DEBUG_PBS_S("-");
+                       DEBUG_PBS_D(skew_array[(pup * DQ_NUM) + dq], 2);
+                       DEBUG_PBS_S(", ");
+               }
+               DEBUG_PBS_S("\n");
+       }
+
+       /* Return ADLL to default value */
+       for (pup = 0; pup < max_pup; pup++) {
+               if (pup == (max_pup - 1) && dram_info->ecc_ena)
+                       pup = ECC_PUP;
+               ddr3_pbs_write_pup_dqs_reg(CS0, pup, INIT_WL_DELAY);
+       }
+
+       /* Set averaged PBS results */
+       ddr3_set_pbs_results(dram_info, 1);
+
+       /* Disable SW override - Must be in a different stage */
+       /* [0]=0 - Enable SW override  */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+               (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+       reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+       DEBUG_PBS_S("DDR3 - PBS Tx - PBS TX ended successfuly\n");
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_tx_shift_dqs_adll_step_before_fail
+ * Desc:     Execute the Tx shift DQ phase.
+ * Args:     dram_info            ddr3 training information struct
+ *           cur_pup              bit array of the function active pups.
+ *           pbs_pattern_idx      Index of PBS pattern
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static int ddr3_tx_shift_dqs_adll_step_before_fail(MV_DRAM_INFO *dram_info,
+                                                  u32 cur_pup,
+                                                  u32 pbs_pattern_idx, u32 ecc)
+{
+       u32 unlock_pup;         /* bit array of unlock pups  */
+       u32 new_lockup_pup;     /* bit array of compare failed pups */
+       u32 adll_val = 4;       /* INIT_WL_DELAY */
+       u32 cur_max_pup, pup;
+       u32 dqs_dly_set[MAX_PUP_NUM] = { 0 };
+       u32 *pattern_ptr;
+
+       /* Choose pattern */
+       switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+       case 16:
+               pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx];
+               break;
+#endif
+       case 32:
+               pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx];
+               break;
+#if defined(MV88F78X60)
+       case 64:
+               pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx];
+               break;
+#endif
+       default:
+               return MV_FAIL;
+       }
+
+       /* Set current pup number */
+       if (cur_pup == 0x1)     /* Ecc mode */
+               cur_max_pup = 1;
+       else
+               cur_max_pup = dram_info->num_of_std_pups;
+
+       unlock_pup = cur_pup;   /* '1' for each unlocked pup */
+
+       /* Loop on all ADLL Vaules */
+       do {
+               /* Loop until found first fail */
+               adll_val++;
+
+               /*
+                * Increment (Move to right - ADLL) DQ TX delay
+                * (broadcast to all Data PUPs)
+                */
+               for (pup = 0; pup < cur_max_pup; pup++)
+                       ddr3_pbs_write_pup_dqs_reg(CS0,
+                                                  pup * (1 - ecc) +
+                                                  ECC_PUP * ecc, adll_val);
+
+               /*
+                * Write and Read, compare results (read was already verified)
+                */
+               /* 0 - all locked */
+               new_lockup_pup = 0;
+
+               if (MV_OK != ddr3_sdram_compare(dram_info, unlock_pup,
+                                               &new_lockup_pup,
+                                               pattern_ptr, LEN_PBS_PATTERN,
+                                               SDRAM_PBS_TX_OFFS, 1, 0,
+                                               NULL,
+                                               0))
+                       return MV_FAIL;
+
+               unlock_pup &= ~new_lockup_pup;
+
+               DEBUG_PBS_FULL_S("Shift DQS by 2 steps for PUPs: ");
+               DEBUG_PBS_FULL_D(unlock_pup, 2);
+               DEBUG_PBS_FULL_C(", Set ADLL value = ", adll_val, 2);
+
+               /* If any PUP failed there is '1' to mark the PUP */
+               if (new_lockup_pup != 0) {
+                       /*
+                        * Decrement (Move Back to Left two steps - ADLL)
+                        * DQ TX delay for current failed pups and save
+                        */
+                       for (pup = 0; pup < cur_max_pup; pup++) {
+                               if (((new_lockup_pup >> pup) & 0x1) &&
+                                   dqs_dly_set[pup] == 0)
+                                       dqs_dly_set[pup] = adll_val - 1;
+                       }
+               }
+       } while ((unlock_pup != 0) && (adll_val != ADLL_MAX));
+
+       if (unlock_pup != 0) {
+               DEBUG_PBS_FULL_S("DDR3 - PBS Tx - Shift DQ - Adll value reached maximum\n");
+
+               for (pup = 0; pup < cur_max_pup; pup++) {
+                       if (((unlock_pup >> pup) & 0x1) &&
+                           dqs_dly_set[pup] == 0)
+                               dqs_dly_set[pup] = adll_val - 1;
+               }
+       }
+
+       DEBUG_PBS_FULL_C("PBS TX one step before fail last pups locked Adll ",
+                        adll_val - 2, 2);
+
+       /* Set the PUP DQS DLY Values */
+       for (pup = 0; pup < cur_max_pup; pup++)
+               ddr3_pbs_write_pup_dqs_reg(CS0, pup * (1 - ecc) + ECC_PUP * ecc,
+                                          dqs_dly_set[pup]);
+
+       /* Found one phase before fail */
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_pbs_rx
+ * Desc:     Execute the PBS RX phase.
+ * Args:     dram_info   ddr3 training information struct
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_pbs_rx(MV_DRAM_INFO *dram_info)
+{
+       /*
+        * Array to hold the total sum of skew from all iterations
+        * (for average purpose)
+        */
+       u32 skew_sum_array[MAX_PUP_NUM][DQ_NUM] = { {0} };
+
+       /*
+        * Array to hold the total average skew from both patterns
+        * (for average purpose)
+        */
+       u32 pattern_skew_array[MAX_PUP_NUM][DQ_NUM] = { {0} };
+
+       u32 pbs_rep_time = 0;   /* counts number of loop in case of fail */
+       /* bit array for unlock pups - used to repeat on the RX operation */
+       u32 cur_pup;
+       u32 max_pup;
+       u32 pbs_retry;
+       u32 pup, dq, pups, cur_max_pup, valid_pup, reg;
+       u32 pattern_idx;
+       u32 ecc;
+       /* indicates whether we need to start the loop again */
+       int start_over;
+       int status;
+
+       DEBUG_PBS_S("DDR3 - PBS RX - Starting PBS RX procedure\n");
+
+       pups = dram_info->num_of_total_pups;
+       max_pup = dram_info->num_of_total_pups;
+
+       /* Enable SW override */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* [0] = 1 - Enable SW override  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+       DEBUG_PBS_FULL_S("DDR3 - PBS RX - SW Override Enabled\n");
+
+       reg = 1 << REG_DRAM_TRAINING_AUTO_OFFS;
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       /* Running twice for 2 different patterns. each patterns - 3 times */
+       for (pattern_idx = 0; pattern_idx < COUNT_PBS_PATTERN; pattern_idx++) {
+               DEBUG_PBS_FULL_C("DDR3 - PBS RX - Working with pattern - ",
+                                pattern_idx, 1);
+
+               /* Reset sum array */
+               for (pup = 0; pup < pups; pup++) {
+                       for (dq = 0; dq < DQ_NUM; dq++)
+                               skew_sum_array[pup][dq] = 0;
+               }
+
+               /*
+                * Perform PBS several of times (3 for each pattern).
+                * At the end, we'll use the average
+                */
+               /* If there is ECC, do each PBS again with mux change */
+               for (pbs_retry = 0; pbs_retry < COUNT_PBS_REPEAT; pbs_retry++) {
+                       for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
+                               /*
+                                * This parameter stores the current PUP
+                                * num - ecc mode dependent - 4-8 / 1 pups
+                                */
+                               cur_max_pup = (1 - ecc) *
+                                       dram_info->num_of_std_pups + ecc;
+
+                               if (ecc) {
+                                       /* Only 1 pup in this case */
+                                       valid_pup = 0x1;
+                               } else if (cur_max_pup > 4) {
+                                       /* 64 bit - 8 pups */
+                                       valid_pup = 0xFF;
+                               } else if (cur_max_pup == 4) {
+                                       /* 32 bit - 4 pups */
+                                       valid_pup = 0xF;
+                               } else {
+                                       /* 16 bit - 2 pups */
+                                       valid_pup = 0x3;
+                               }
+
+                               /* ECC Support - Switch ECC Mux on ecc=1 */
+                               reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+                                       ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg |= (dram_info->ecc_ena * ecc <<
+                                       REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+                               if (ecc)
+                                       DEBUG_PBS_FULL_S("DDR3 - PBS Rx - ECC Mux Enabled\n");
+                               else
+                                       DEBUG_PBS_FULL_S("DDR3 - PBS Rx - ECC Mux Disabled\n");
+
+                               /* Init iteration values */
+                               /* Clear the locked DQs */
+                               for (pup = 0; pup < cur_max_pup; pup++) {
+                                       for (dq = 0; dq < DQ_NUM; dq++) {
+                                               pbs_locked_dq[
+                                                       pup + ecc * (max_pup - 1)][dq] =
+                                                       0;
+                                       }
+                               }
+
+                               pbs_rep_time = 0;
+                               cur_pup = valid_pup;
+                               start_over = 0;
+
+                               /*
+                                * Run loop On current Pattern and current
+                                * pattern iteration (just to cover the false
+                                * fail problem
+                                */
+                               do {
+                                       DEBUG_PBS_FULL_S("DDR3 - PBS Rx - Pbs Rep Loop is ");
+                                       DEBUG_PBS_FULL_D(pbs_rep_time, 1);
+                                       DEBUG_PBS_FULL_S(", for Retry No.");
+                                       DEBUG_PBS_FULL_D(pbs_retry, 1);
+                                       DEBUG_PBS_FULL_S("\n");
+
+                                       /* Set all PBS values to MAX (31) */
+                                       for (pup = 0; pup < cur_max_pup; pup++) {
+                                               for (dq = 0; dq < DQ_NUM; dq++)
+                                                       ddr3_write_pup_reg(
+                                                               PUP_PBS_RX +
+                                                               pbs_dq_mapping[
+                                                               pup * (1 - ecc)
+                                                               + ecc * ECC_PUP]
+                                                               [dq], CS0,
+                                                               pup + ecc * ECC_PUP,
+                                                               0, MAX_PBS);
+                                       }
+
+                                       /* Set all DQS PBS values to MIN (0) */
+                                       for (pup = 0; pup < cur_max_pup; pup++) {
+                                               ddr3_write_pup_reg(PUP_PBS_RX +
+                                                                  DQ_NUM, CS0,
+                                                                  pup +
+                                                                  ecc *
+                                                                  ECC_PUP, 0,
+                                                                  0);
+                                       }
+
+                                       /* Shift DQS, To first Fail */
+                                       DEBUG_PBS_FULL_S("DDR3 - PBS Rx - Shift RX DQS to first fail\n");
+
+                                       status = ddr3_rx_shift_dqs_to_first_fail
+                                               (dram_info, cur_pup,
+                                                pattern_idx, ecc);
+                                       if (MV_OK != status) {
+                                               DEBUG_PBS_S("DDR3 - PBS Rx - ddr3_rx_shift_dqs_to_first_fail failed.\n");
+                                               DEBUG_PBS_D(status, 8);
+                                               DEBUG_PBS_S("\nDDR3 - PBS Rx - SKIP.\n");
+
+                                               /* Reset read FIFO */
+                                               reg = reg_read(REG_DRAM_TRAINING_ADDR);
+                                               /* Start Auto Read Leveling procedure */
+                                               reg |= (1 << REG_DRAM_TRAINING_RL_OFFS);
+                                               /* 0x15B0 - Training Register */
+                                               reg_write(REG_DRAM_TRAINING_ADDR, reg);
+
+                                               reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+                                               reg |= ((1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS)
+                                                       + (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS));
+                                               /* [0] = 1 - Enable SW override, [4] = 1 - FIFO reset  */
+                                               /* 0x15B8 - Training SW 2 Register */
+                                               reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+                                               do {
+                                                       reg = (reg_read(REG_DRAM_TRAINING_2_ADDR))
+                                                               & (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+                                               } while (reg);  /* Wait for '0' */
+
+                                               reg = reg_read(REG_DRAM_TRAINING_ADDR);
+                                               /* Clear Auto Read Leveling procedure */
+                                               reg &= ~(1 << REG_DRAM_TRAINING_RL_OFFS);
+                                               /* 0x15B0 - Training Register */
+                                               reg_write(REG_DRAM_TRAINING_ADDR, reg);
+
+                                               /* Set ADLL to 15 */
+                                               for (pup = 0; pup < max_pup;
+                                                    pup++) {
+                                                       ddr3_write_pup_reg
+                                                           (PUP_DQS_RD, CS0,
+                                                            pup +
+                                                            (ecc * ECC_PUP), 0,
+                                                            15);
+                                               }
+
+                                               /* Set all PBS values to MIN (0) */
+                                               for (pup = 0; pup < cur_max_pup;
+                                                    pup++) {
+                                                       for (dq = 0;
+                                                            dq < DQ_NUM; dq++)
+                                                               ddr3_write_pup_reg
+                                                                   (PUP_PBS_RX +
+                                                                    pbs_dq_mapping
+                                                                    [pup * (1 - ecc) +
+                                                                     ecc * ECC_PUP]
+                                                                    [dq], CS0,
+                                                                    pup + ecc * ECC_PUP,
+                                                                    0, MIN_PBS);
+                                               }
+
+                                               return MV_OK;
+                                       }
+
+                                       /* PBS For each bit */
+                                       DEBUG_PBS_FULL_S("DDR3 - PBS Rx - perform PBS for each bit\n");
+                                       /* in this stage - start_over = 0; */
+                                       if (MV_OK != ddr3_pbs_per_bit(
+                                                   dram_info, &start_over,
+                                                   0, &cur_pup,
+                                                   pattern_idx, ecc)) {
+                                               DEBUG_PBS_S("DDR3 - PBS Rx - ddr3_pbs_per_bit failed.");
+                                               return MV_DDR3_TRAINING_ERR_PBS_RX_PER_BIT;
+                                       }
+
+                               } while ((start_over == 1) &&
+                                        (++pbs_rep_time < COUNT_PBS_STARTOVER));
+
+                               if (pbs_rep_time == COUNT_PBS_STARTOVER &&
+                                   start_over == 1) {
+                                       DEBUG_PBS_FULL_S("DDR3 - PBS Rx - FAIL - Algorithm failed doing RX PBS\n");
+                                       return MV_DDR3_TRAINING_ERR_PBS_RX_MAX_VAL;
+                               }
+
+                               /* Return DQS ADLL to default value - 15 */
+                               /* Set all DQS PBS values to MIN (0) */
+                               for (pup = 0; pup < cur_max_pup; pup++)
+                                       ddr3_write_pup_reg(PUP_DQS_RD, CS0,
+                                                          pup + ecc * ECC_PUP,
+                                                          0, INIT_RL_DELAY);
+
+                               DEBUG_PBS_FULL_C("DDR3 - PBS RX - values for iteration - ",
+                                                pbs_retry, 1);
+                               for (pup = 0; pup < cur_max_pup; pup++) {
+                                       /*
+                                        * To minimize delay elements, inc from
+                                        * pbs value the min pbs val
+                                        */
+                                       DEBUG_PBS_FULL_S("DDR3 - PBS - PUP");
+                                       DEBUG_PBS_FULL_D((pup +
+                                                         (ecc * ECC_PUP)), 1);
+                                       DEBUG_PBS_FULL_S(": ");
+
+                                       for (dq = 0; dq < DQ_NUM; dq++) {
+                                               /* Set skew value for all dq */
+                                               /*
+                                                * Bit# Deskew <- Bit# Deskew -
+                                                * last / first  failing bit
+                                                * Deskew For all bits (per PUP)
+                                                * (minimize delay elements)
+                                                */
+                                               DEBUG_PBS_FULL_S("DQ");
+                                               DEBUG_PBS_FULL_D(dq, 1);
+                                               DEBUG_PBS_FULL_S("-");
+                                               DEBUG_PBS_FULL_D(skew_array
+                                                                [((pup) *
+                                                                  DQ_NUM) +
+                                                                 dq], 2);
+                                               DEBUG_PBS_FULL_S(", ");
+                                       }
+                                       DEBUG_PBS_FULL_S("\n");
+                               }
+
+                               /*
+                                * Collect the results we got on this trial
+                                * of PBS
+                                */
+                               for (pup = 0; pup < cur_max_pup; pup++) {
+                                       for (dq = 0; dq < DQ_NUM; dq++) {
+                                               skew_sum_array
+                                                       [pup + (ecc * (max_pup - 1))]
+                                                       [dq] +=
+                                                       skew_array[((pup) * DQ_NUM) + dq];
+                                       }
+                               }
+
+                               /* ECC Support - Disable ECC MUX */
+                               reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+                                       ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                               reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+                       }
+               }
+
+               /*
+                * Calculate the average skew for current pattern for each
+                * pup and each bit
+                */
+               DEBUG_PBS_FULL_C("DDR3 - PBS RX - Average for pattern - ",
+                                pattern_idx, 1);
+               for (pup = 0; pup < max_pup; pup++) {
+                       /*
+                        * FOR ECC only :: found min and max value for
+                        * current pattern skew array
+                        */
+                       /* Loop for all dqs */
+                       for (dq = 0; dq < DQ_NUM; dq++) {
+                               pattern_skew_array[pup][dq] +=
+                                       (skew_sum_array[pup][dq] /
+                                        COUNT_PBS_REPEAT);
+                       }
+               }
+
+               DEBUG_PBS_C("DDR3 - PBS RX - values for current pattern - ",
+                           pattern_idx, 1);
+               for (pup = 0; pup < max_pup; pup++) {
+                       /*
+                        * To minimize delay elements, inc from pbs value the
+                        * min pbs val
+                        */
+                       DEBUG_PBS_S("DDR3 - PBS RX - PUP");
+                       DEBUG_PBS_D(pup, 1);
+                       DEBUG_PBS_S(": ");
+
+                       for (dq = 0; dq < DQ_NUM; dq++) {
+                               /* Set skew value for all dq */
+                               /*
+                                * Bit# Deskew <- Bit# Deskew - last / first
+                                * failing bit Deskew For all bits (per PUP)
+                                * (minimize delay elements)
+                                */
+                               DEBUG_PBS_S("DQ");
+                               DEBUG_PBS_D(dq, 1);
+                               DEBUG_PBS_S("-");
+                               DEBUG_PBS_D(skew_sum_array[pup][dq] /
+                                           COUNT_PBS_REPEAT, 2);
+                               DEBUG_PBS_S(", ");
+                       }
+                       DEBUG_PBS_S("\n");
+               }
+       }
+
+       /* Calculate the average skew */
+       for (pup = 0; pup < max_pup; pup++) {
+               for (dq = 0; dq < DQ_NUM; dq++)
+                       skew_array[((pup) * DQ_NUM) + dq] =
+                               pattern_skew_array[pup][dq] / COUNT_PBS_PATTERN;
+       }
+
+       DEBUG_PBS_S("DDR3 - PBS RX - Average for all patterns:\n");
+       for (pup = 0; pup < max_pup; pup++) {
+               /*
+                * To minimize delay elements, inc from pbs value the
+                * min pbs val
+                */
+               DEBUG_PBS_S("DDR3 - PBS - PUP");
+               DEBUG_PBS_D(pup, 1);
+               DEBUG_PBS_S(": ");
+
+               for (dq = 0; dq < DQ_NUM; dq++) {
+                       /* Set skew value for all dq */
+                       /*
+                        * Bit# Deskew <- Bit# Deskew - last / first
+                        * failing bit Deskew For all bits (per PUP)
+                        * (minimize delay elements)
+                        */
+                       DEBUG_PBS_S("DQ");
+                       DEBUG_PBS_D(dq, 1);
+                       DEBUG_PBS_S("-");
+                       DEBUG_PBS_D(skew_array[(pup * DQ_NUM) + dq], 2);
+                       DEBUG_PBS_S(", ");
+               }
+               DEBUG_PBS_S("\n");
+       }
+
+       /* Return ADLL to default value */
+       ddr3_write_pup_reg(PUP_DQS_RD, CS0, PUP_BC, 0, INIT_RL_DELAY);
+
+       /* Set averaged PBS results */
+       ddr3_set_pbs_results(dram_info, 0);
+
+       /* Disable SW override - Must be in a different stage */
+       /* [0]=0 - Enable SW override  */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+               (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+       reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+       DEBUG_PBS_FULL_S("DDR3 - PBS RX - ended successfuly\n");
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_rx_shift_dqs_to_first_fail
+ * Desc:     Execute the Rx shift DQ phase.
+ * Args:     dram_info           ddr3 training information struct
+ *           cur_pup             bit array of the function active pups.
+ *           pbs_pattern_idx     Index of PBS pattern
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static int ddr3_rx_shift_dqs_to_first_fail(MV_DRAM_INFO *dram_info, u32 cur_pup,
+                                          u32 pbs_pattern_idx, u32 ecc)
+{
+       u32 unlock_pup;         /* bit array of unlock pups  */
+       u32 new_lockup_pup;     /* bit array of compare failed pups */
+       u32 adll_val = MAX_DELAY;
+       u32 dqs_deskew_val = 0; /* current value of DQS PBS deskew */
+       u32 cur_max_pup, pup, pass_pup;
+       u32 *pattern_ptr;
+
+       /* Choose pattern */
+       switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+       case 16:
+               pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx];
+               break;
+#endif
+       case 32:
+               pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx];
+               break;
+#if defined(MV88F78X60)
+       case 64:
+               pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx];
+               break;
+#endif
+       default:
+               return MV_FAIL;
+       }
+
+       /* Set current pup number */
+       if (cur_pup == 0x1)     /* Ecc mode */
+               cur_max_pup = 1;
+       else
+               cur_max_pup = dram_info->num_of_std_pups;
+
+       unlock_pup = cur_pup;   /* '1' for each unlocked pup */
+
+       DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - Starting...\n");
+
+       /* Set DQS ADLL to MAX */
+       DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - Set DQS ADLL to Max for all PUPs\n");
+       for (pup = 0; pup < cur_max_pup; pup++)
+               ddr3_write_pup_reg(PUP_DQS_RD, CS0, pup + ecc * ECC_PUP, 0,
+                                  MAX_DELAY);
+
+       /* Loop on all ADLL Vaules */
+       do {
+               /* Loop until found fail for all pups */
+               new_lockup_pup = 0;
+               if (MV_OK != ddr3_sdram_compare(dram_info, unlock_pup,
+                                               &new_lockup_pup,
+                                               pattern_ptr, LEN_PBS_PATTERN,
+                                               SDRAM_PBS_I_OFFS +
+                                               pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS,
+                                               0, 0, NULL, 0)) {
+                       DEBUG_PBS_S("DDR3 - PBS Rx - Shift DQS - MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP(ddr3_sdram_compare)\n");
+                       return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP;
+               }
+
+               if ((new_lockup_pup != 0) && (dqs_deskew_val <= 1)) {
+                       /* Fail on start with first deskew value */
+                       /* Decrement DQS ADLL */
+                       --adll_val;
+                       if (adll_val == ADLL_MIN) {
+                               DEBUG_PBS_S("DDR3 - PBS Rx - Shift DQS - fail on start with first deskew value\n");
+                               return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP;
+                       }
+                       ddr3_write_pup_reg(PUP_DQS_RD, CS0, pup + ecc * ECC_PUP,
+                                          0, adll_val);
+                       continue;
+               }
+
+               /* Update all new locked pups */
+               unlock_pup &= ~new_lockup_pup;
+
+               if ((unlock_pup == 0) || (dqs_deskew_val == MAX_PBS)) {
+                       if (dqs_deskew_val == MAX_PBS) {
+                               /*
+                                * Reach max value of dqs deskew or get fail
+                                * for all pups
+                                */
+                               DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - DQS deskew reached maximum value\n");
+                       }
+                       break;
+               }
+
+               DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - Inc DQS deskew for PUPs: ");
+               DEBUG_PBS_FULL_D(unlock_pup, 2);
+               DEBUG_PBS_FULL_C(", deskew = ", dqs_deskew_val, 2);
+
+               /* Increment DQS deskew elements - Only for unlocked pups */
+               dqs_deskew_val++;
+               for (pup = 0; pup < cur_max_pup; pup++) {
+                       if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+                               ddr3_write_pup_reg(PUP_PBS_RX + DQS_DQ_NUM, CS0,
+                                                  pup + ecc * ECC_PUP, 0,
+                                                  dqs_deskew_val);
+                       }
+               }
+       } while (1);
+
+       DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - ADLL shift one step before fail\n");
+       /* Continue to ADLL shift one step before fail */
+       unlock_pup = cur_pup;
+       do {
+               /* Loop until pass compare for all pups */
+               new_lockup_pup = 0;
+               /* Read and compare results  */
+               if (MV_OK != ddr3_sdram_compare(dram_info, unlock_pup, &new_lockup_pup,
+                                               pattern_ptr, LEN_PBS_PATTERN,
+                                               SDRAM_PBS_I_OFFS +
+                                               pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS,
+                                               1, 0, NULL, 0)) {
+                       DEBUG_PBS_S("DDR3 - PBS Rx - Shift DQS - MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP(ddr3_sdram_compare)\n");
+                       return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP;
+               }
+
+               /*
+                * Get mask for pup which passed so their adll will be
+                * changed to 2 steps before fails
+                */
+               pass_pup = unlock_pup & ~new_lockup_pup;
+
+               DEBUG_PBS_FULL_S("Shift DQS by 2 steps for PUPs: ");
+               DEBUG_PBS_FULL_D(pass_pup, 2);
+               DEBUG_PBS_FULL_C(", Set ADLL value = ", (adll_val - 2), 2);
+
+               /* Only for pass pups   */
+               for (pup = 0; pup < cur_max_pup; pup++) {
+                       if (IS_PUP_ACTIVE(pass_pup, pup) == 1) {
+                               ddr3_write_pup_reg(PUP_DQS_RD, CS0,
+                                                  pup + ecc * ECC_PUP, 0,
+                                                  (adll_val - 2));
+                       }
+               }
+
+               /* Locked pups that compare success  */
+               unlock_pup &= new_lockup_pup;
+
+               if (unlock_pup == 0) {
+                       /* All pups locked */
+                       break;
+               }
+
+               /* Found error */
+               if (adll_val == 0) {
+                       DEBUG_PBS_FULL_S("DDR3 - PBS Rx - Shift DQS - Adll reach min value\n");
+                       return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_MAX_VAL;
+               }
+
+               /*
+                * Decrement (Move Back to Left one phase - ADLL) dqs RX delay
+                */
+               adll_val--;
+               for (pup = 0; pup < cur_max_pup; pup++) {
+                       if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
+                               ddr3_write_pup_reg(PUP_DQS_RD, CS0,
+                                                  pup + ecc * ECC_PUP, 0,
+                                                  adll_val);
+                       }
+               }
+       } while (1);
+
+       return MV_OK;
+}
+
+/*
+ * lock_pups() extracted from ddr3_pbs_per_bit(). This just got too
+ * much indented making it hard to read / edit.
+ */
+static void lock_pups(u32 pup, u32 *pup_locked, u8 *unlock_pup_dq_array,
+                     u32 pbs_curr_val, u32 start_pbs, u32 ecc, int is_tx)
+{
+       u32 dq;
+       int idx;
+
+       /* Lock PBS value for all remaining PUPs bits */
+       DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Lock PBS value for all remaining PUPs bits, pup ");
+       DEBUG_PBS_FULL_D(pup, 1);
+       DEBUG_PBS_FULL_C(" pbs value ", pbs_curr_val, 2);
+
+       idx = pup * (1 - ecc) + ecc * ECC_PUP;
+       *pup_locked &= ~(1 << pup);
+
+       for (dq = 0; dq < DQ_NUM; dq++) {
+               if (IS_PUP_ACTIVE(unlock_pup_dq_array[dq], pup) == 1) {
+                       int offs;
+
+                       /* Lock current dq */
+                       unlock_pup_dq_array[dq] &= ~(1 << pup);
+                       skew_array[(pup * DQ_NUM) + dq] = pbs_curr_val;
+
+                       if (is_tx == 1)
+                               offs = PUP_PBS_TX;
+                       else
+                               offs = PUP_PBS_RX;
+
+                       ddr3_write_pup_reg(offs +
+                                          pbs_dq_mapping[idx][dq], CS0,
+                                          idx, 0, start_pbs);
+               }
+       }
+}
+
+/*
+ * Name:     ddr3_pbs_per_bit
+ * Desc:     Execute the Per Bit Skew phase.
+ * Args:     start_over      Return whether need to start over the algorithm
+ *           is_tx           Indicate whether Rx or Tx
+ *           pcur_pup        bit array of the function active pups. return the
+ *                           pups that need to repeat on the PBS
+ *           pbs_pattern_idx Index of PBS pattern
+ *
+ * Notes:    Current implementation supports double activation of this function.
+ *           i.e. in order to activate this function (using start_over) more than
+ *           twice, the implementation should change.
+ *           imlementation limitation are marked using
+ *           ' CHIP-ONLY! - Implementation Limitation '
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static int ddr3_pbs_per_bit(MV_DRAM_INFO *dram_info, int *start_over, int is_tx,
+                           u32 *pcur_pup, u32 pbs_pattern_idx, u32 ecc)
+{
+       /*
+        * Bit array to indicate if we already get fail on bit per pup & dq bit
+        */
+       u8 unlock_pup_dq_array[DQ_NUM] = {
+               *pcur_pup, *pcur_pup, *pcur_pup, *pcur_pup, *pcur_pup,
+               *pcur_pup, *pcur_pup, *pcur_pup
+       };
+
+       u8 cmp_unlock_pup_dq_array[COUNT_PBS_COMP_RETRY_NUM][DQ_NUM];
+       u32 pup, dq;
+       /* value of pbs is according to RX or TX */
+       u32 start_pbs, last_pbs;
+       u32 pbs_curr_val;
+       /* bit array that indicates all dq of the pup locked */
+       u32 pup_locked;
+       u32 first_fail[MAX_PUP_NUM] = { 0 };    /* count first fail per pup */
+       /* indicates whether we get first fail per pup */
+       int first_failed[MAX_PUP_NUM] = { 0 };
+       /* bit array that indicates pup already get fail */
+       u32 sum_pup_fail;
+       /* use to calculate diff between curr pbs to first fail pbs */
+       u32 calc_pbs_diff;
+       u32 pbs_cmp_retry;
+       u32 max_pup;
+
+       /* Set init values for retry array - 8 retry */
+       for (pbs_cmp_retry = 0; pbs_cmp_retry < COUNT_PBS_COMP_RETRY_NUM;
+            pbs_cmp_retry++) {
+               for (dq = 0; dq < DQ_NUM; dq++)
+                       cmp_unlock_pup_dq_array[pbs_cmp_retry][dq] = *pcur_pup;
+       }
+
+       memset(&skew_array, 0, MAX_PUP_NUM * DQ_NUM * sizeof(u32));
+
+       DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Started\n");
+
+       /* The pbs value depends if rx or tx */
+       if (is_tx == 1) {
+               start_pbs = MIN_PBS;
+               last_pbs = MAX_PBS;
+       } else {
+               start_pbs = MAX_PBS;
+               last_pbs = MIN_PBS;
+       }
+
+       pbs_curr_val = start_pbs;
+       pup_locked = *pcur_pup;
+
+       /* Set current pup number */
+       if (pup_locked == 0x1)  /* Ecc mode */
+               max_pup = 1;
+       else
+               max_pup = dram_info->num_of_std_pups;
+
+       do {
+               /* Increment/ decrement PBS for un-lock bits only */
+               if (is_tx == 1)
+                       pbs_curr_val++;
+               else
+                       pbs_curr_val--;
+
+               /* Set Current PBS delay  */
+               for (dq = 0; dq < DQ_NUM; dq++) {
+                       /* Check DQ bits to see if locked in all pups */
+                       if (unlock_pup_dq_array[dq] == 0) {
+                               DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - All pups are locked for DQ ");
+                               DEBUG_PBS_FULL_D(dq, 1);
+                               DEBUG_PBS_FULL_S("\n");
+                               continue;
+                       }
+
+                       for (pup = 0; pup < max_pup; pup++) {
+                               int idx;
+
+                               idx = pup * (1 - ecc) + ecc * ECC_PUP;
+
+                               if (IS_PUP_ACTIVE(unlock_pup_dq_array[dq], pup)
+                                   == 0)
+                                       continue;
+
+                               if (is_tx == 1)
+                                       ddr3_write_pup_reg(
+                                               PUP_PBS_TX + pbs_dq_mapping[idx][dq],
+                                               CS0, idx, 0, pbs_curr_val);
+                               else
+                                       ddr3_write_pup_reg(
+                                               PUP_PBS_RX + pbs_dq_mapping[idx][dq],
+                                               CS0, idx, 0, pbs_curr_val);
+                       }
+               }
+
+               /*
+                * Write Read and compare results - run the test
+                * DDR_PBS_COMP_RETRY_NUM times
+                */
+               /* Run number of read and write to verify */
+               for (pbs_cmp_retry = 0;
+                    pbs_cmp_retry < COUNT_PBS_COMP_RETRY_NUM;
+                    pbs_cmp_retry++) {
+
+                       if (MV_OK !=
+                           ddr3_sdram_pbs_compare(dram_info, pup_locked, is_tx,
+                                                  pbs_pattern_idx,
+                                                  pbs_curr_val, start_pbs,
+                                                  skew_array,
+                                                  cmp_unlock_pup_dq_array
+                                                  [pbs_cmp_retry], ecc))
+                               return MV_FAIL;
+
+                       for (pup = 0; pup < max_pup; pup++) {
+                               for (dq = 0; dq < DQ_NUM; dq++) {
+                                       if ((IS_PUP_ACTIVE(unlock_pup_dq_array[dq],
+                                                          pup) == 1)
+                                           && (IS_PUP_ACTIVE(cmp_unlock_pup_dq_array
+                                             [pbs_cmp_retry][dq],
+                                             pup) == 0)) {
+                                               DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - PbsCurrVal: ");
+                                               DEBUG_PBS_FULL_D(pbs_curr_val, 2);
+                                               DEBUG_PBS_FULL_S(" PUP: ");
+                                               DEBUG_PBS_FULL_D(pup, 1);
+                                               DEBUG_PBS_FULL_S(" DQ: ");
+                                               DEBUG_PBS_FULL_D(dq, 1);
+                                               DEBUG_PBS_FULL_S(" - failed\n");
+                                       }
+                               }
+                       }
+
+                       for (dq = 0; dq < DQ_NUM; dq++) {
+                               unlock_pup_dq_array[dq] &=
+                                   cmp_unlock_pup_dq_array[pbs_cmp_retry][dq];
+                       }
+               }
+
+               pup_locked = 0;
+               sum_pup_fail = *pcur_pup;
+
+               /* Check which DQ is failed */
+               for (dq = 0; dq < DQ_NUM; dq++) {
+                       /* Summarize the locked pup */
+                       pup_locked |= unlock_pup_dq_array[dq];
+
+                       /* Check if get fail */
+                       sum_pup_fail &= unlock_pup_dq_array[dq];
+               }
+
+               /* If all PUPS are locked in all DQ - Break */
+               if (pup_locked == 0) {
+                       /* All pups are locked */
+                       *start_over = 0;
+                       DEBUG_PBS_FULL_S("DDR3 - PBS Per bit -  All bit in all pups are successfully locked\n");
+                       break;
+               }
+
+               /* PBS deskew elements reach max ? */
+               if (pbs_curr_val == last_pbs) {
+                       DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - PBS deskew elements reach max\n");
+                       /* CHIP-ONLY! - Implementation Limitation */
+                       *start_over = (sum_pup_fail != 0) && (!(*start_over));
+                       *pcur_pup = pup_locked;
+
+                       DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - StartOver: ");
+                       DEBUG_PBS_FULL_D(*start_over, 1);
+                       DEBUG_PBS_FULL_S("  pup_locked: ");
+                       DEBUG_PBS_FULL_D(pup_locked, 2);
+                       DEBUG_PBS_FULL_S("  sum_pup_fail: ");
+                       DEBUG_PBS_FULL_D(sum_pup_fail, 2);
+                       DEBUG_PBS_FULL_S("\n");
+
+                       /* Lock PBS value for all remaining  bits */
+                       for (pup = 0; pup < max_pup; pup++) {
+                               /* Check if current pup already received error */
+                               if (IS_PUP_ACTIVE(pup_locked, pup) == 1) {
+                                       /* Valid pup for current function */
+                                       if (IS_PUP_ACTIVE(sum_pup_fail, pup) ==
+                                           1 && (*start_over == 1)) {
+                                               DEBUG_PBS_FULL_C("DDR3 - PBS Per bit - skipping lock of pup (first loop of pbs)",
+                                                                pup, 1);
+                                               continue;
+                                       } else
+                                           if (IS_PUP_ACTIVE(sum_pup_fail, pup)
+                                               == 1) {
+                                               DEBUG_PBS_FULL_C("DDR3 - PBS Per bit - Locking pup %d (even though it wasn't supposed to be locked)",
+                                                                pup, 1);
+                                       }
+
+                                       /* Already got fail on the PUP */
+                                       /* Lock PBS value for all remaining bits */
+                                       DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Locking remaning DQs for pup - ");
+                                       DEBUG_PBS_FULL_D(pup, 1);
+                                       DEBUG_PBS_FULL_S(": ");
+
+                                       for (dq = 0; dq < DQ_NUM; dq++) {
+                                               if (IS_PUP_ACTIVE
+                                                   (unlock_pup_dq_array[dq],
+                                                    pup) == 1) {
+                                                       DEBUG_PBS_FULL_D(dq, 1);
+                                                       DEBUG_PBS_FULL_S(",");
+                                                       /* set current PBS */
+                                                       skew_array[((pup) *
+                                                                   DQ_NUM) +
+                                                                  dq] =
+                                                           pbs_curr_val;
+                                               }
+                                       }
+
+                                       if (*start_over == 1) {
+                                               /*
+                                                * Reset this pup bit - when
+                                                * restart the PBS, ignore this
+                                                * pup
+                                                */
+                                               *pcur_pup &= ~(1 << pup);
+                                       }
+                                       DEBUG_PBS_FULL_S("\n");
+                               } else {
+                                       DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Pup ");
+                                       DEBUG_PBS_FULL_D(pup, 1);
+                                       DEBUG_PBS_FULL_C(" is not set in puplocked - ",
+                                                        pup_locked, 1);
+                               }
+                       }
+
+                       /* Need to start the PBS again */
+                       if (*start_over == 1) {
+                               DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - false fail - returning to start\n");
+                               return MV_OK;
+                       }
+                       break;
+               }
+
+               /* Diff Check */
+               for (pup = 0; pup < max_pup; pup++) {
+                       if (IS_PUP_ACTIVE(pup_locked, pup) == 1) {
+                               /* pup is not locked */
+                               if (first_failed[pup] == 0) {
+                                       /* No first fail until now */
+                                       if (IS_PUP_ACTIVE(sum_pup_fail, pup) ==
+                                           0) {
+                                               /* Get first fail */
+                                               DEBUG_PBS_FULL_C("DDR3 - PBS Per bit - First fail in pup ",
+                                                                pup, 1);
+                                               first_failed[pup] = 1;
+                                               first_fail[pup] = pbs_curr_val;
+                                       }
+                               } else {
+                                       /* Already got first fail */
+                                       if (is_tx == 1) {
+                                               /* TX - inc pbs */
+                                               calc_pbs_diff = pbs_curr_val -
+                                                       first_fail[pup];
+                                       } else {
+                                               /* RX - dec pbs */
+                                               calc_pbs_diff = first_fail[pup] -
+                                                       pbs_curr_val;
+                                       }
+
+                                       if (calc_pbs_diff >= PBS_DIFF_LIMIT) {
+                                               lock_pups(pup, &pup_locked,
+                                                         unlock_pup_dq_array,
+                                                         pbs_curr_val,
+                                                         start_pbs, ecc, is_tx);
+                                       }
+                               }
+                       }
+               }
+       } while (1);
+
+       return MV_OK;
+}
+
+/*
+ * Name:         ddr3_set_pbs_results
+ * Desc:         Set to HW the PBS phase results.
+ * Args:         is_tx       Indicates whether to set Tx or RX results
+ * Notes:
+ * Returns:      MV_OK if success, other error code if fail.
+ */
+static int ddr3_set_pbs_results(MV_DRAM_INFO *dram_info, int is_tx)
+{
+       u32 pup, phys_pup, dq;
+       u32 max_pup;            /* number of valid pups */
+       u32 pbs_min;            /* minimal pbs val per pup */
+       u32 pbs_max;            /* maximum pbs val per pup */
+       u32 val[9];
+
+       max_pup = dram_info->num_of_total_pups;
+       DEBUG_PBS_FULL_S("DDR3 - PBS - ddr3_set_pbs_results:\n");
+
+       /* Loop for all dqs & pups */
+       for (pup = 0; pup < max_pup; pup++) {
+               if (pup == (max_pup - 1) && dram_info->ecc_ena)
+                       phys_pup = ECC_PUP;
+               else
+                       phys_pup = pup;
+
+               /*
+                * To minimize delay elements, inc from pbs value the min
+                * pbs val
+                */
+               pbs_min = MAX_PBS;
+               pbs_max = 0;
+               for (dq = 0; dq < DQ_NUM; dq++) {
+                       if (pbs_min > skew_array[(pup * DQ_NUM) + dq])
+                               pbs_min = skew_array[(pup * DQ_NUM) + dq];
+
+                       if (pbs_max < skew_array[(pup * DQ_NUM) + dq])
+                               pbs_max = skew_array[(pup * DQ_NUM) + dq];
+               }
+
+               pbs_max -= pbs_min;
+
+               DEBUG_PBS_FULL_S("DDR3 - PBS - PUP");
+               DEBUG_PBS_FULL_D(phys_pup, 1);
+               DEBUG_PBS_FULL_S(": Min Val = ");
+               DEBUG_PBS_FULL_D(pbs_min, 2);
+               DEBUG_PBS_FULL_C(", Max Val = ", pbs_max, 2);
+
+               val[pup] = 0;
+
+               for (dq = 0; dq < DQ_NUM; dq++) {
+                       int idx;
+                       int offs;
+
+                       /* Set skew value for all dq */
+                       /*
+                        * Bit# Deskew <- Bit# Deskew - last / first
+                        * failing bit Deskew For all bits (per PUP)
+                        * (minimize delay elements)
+                        */
+
+                       DEBUG_PBS_FULL_S("DQ");
+                       DEBUG_PBS_FULL_D(dq, 1);
+                       DEBUG_PBS_FULL_S("-");
+                       DEBUG_PBS_FULL_D((skew_array[(pup * DQ_NUM) + dq] -
+                                         pbs_min), 2);
+                       DEBUG_PBS_FULL_S(", ");
+
+                       idx = (pup * DQ_NUM) + dq;
+
+                       if (is_tx == 1)
+                               offs = PUP_PBS_TX;
+                       else
+                               offs = PUP_PBS_RX;
+
+                       ddr3_write_pup_reg(offs + pbs_dq_mapping[phys_pup][dq],
+                                          CS0, phys_pup, 0,
+                                          skew_array[idx] - pbs_min);
+
+                       if (is_tx == 1)
+                               val[pup] += skew_array[idx] - pbs_min;
+               }
+
+               DEBUG_PBS_FULL_S("\n");
+
+               /* Set the DQS the half of the Max PBS of the DQs  */
+               if (is_tx == 1) {
+                       ddr3_write_pup_reg(PUP_PBS_TX + 8, CS0, phys_pup, 0,
+                                          pbs_max / 2);
+                       ddr3_write_pup_reg(PUP_PBS_TX + 0xa, CS0, phys_pup, 0,
+                                          val[pup] / 8);
+               } else
+                       ddr3_write_pup_reg(PUP_PBS_RX + 8, CS0, phys_pup, 0,
+                                          pbs_max / 2);
+       }
+
+       return MV_OK;
+}
+
+static void ddr3_pbs_write_pup_dqs_reg(u32 cs, u32 pup, u32 dqs_delay)
+{
+       u32 reg, delay;
+
+       reg = (ddr3_read_pup_reg(PUP_WL_MODE, cs, pup) & 0x3FF);
+       delay = reg & PUP_DELAY_MASK;
+       reg |= ((dqs_delay + delay) << REG_PHY_DQS_REF_DLY_OFFS);
+       reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+       reg |= (pup << REG_PHY_PUP_OFFS);
+       reg |= ((0x4 * cs + PUP_WL_MODE) << REG_PHY_CS_OFFS);
+
+       reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);      /* 0x16A0 */
+       do {
+               reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) &
+                       REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+       } while (reg);  /* Wait for '0' to mark the end of the transaction */
+
+       udelay(10);
+}
+
+/*
+ * Set training patterns
+ */
+int ddr3_load_pbs_patterns(MV_DRAM_INFO *dram_info)
+{
+       u32 cs, cs_count, cs_tmp;
+       u32 sdram_addr;
+       u32 *pattern_ptr0, *pattern_ptr1;
+
+       /* Choose pattern */
+       switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+       case 16:
+               pattern_ptr0 = (u32 *)&pbs_pattern[0];
+               pattern_ptr1 = (u32 *)&pbs_pattern[1];
+               break;
+#endif
+       case 32:
+               pattern_ptr0 = (u32 *)&pbs_pattern_32b[0];
+               pattern_ptr1 = (u32 *)&pbs_pattern_32b[1];
+               break;
+#if defined(MV88F78X60)
+       case 64:
+               pattern_ptr0 = (u32 *)&pbs_pattern_64b[0];
+               pattern_ptr1 = (u32 *)&pbs_pattern_64b[1];
+               break;
+#endif
+       default:
+               return MV_FAIL;
+       }
+
+       /* Loop for each CS */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       cs_count = 0;
+                       for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
+                               if (dram_info->cs_ena & (1 << cs_tmp))
+                                       cs_count++;
+                       }
+
+                       /* Init PBS I pattern */
+                       sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
+                                     SDRAM_PBS_I_OFFS);
+                       if (MV_OK !=
+                           ddr3_sdram_compare(dram_info, (u32) NULL, NULL,
+                                              pattern_ptr0, LEN_STD_PATTERN,
+                                              sdram_addr, 1, 0, NULL,
+                                              0))
+                               return MV_FAIL;
+
+                       /* Init PBS II pattern */
+                       sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
+                                     SDRAM_PBS_II_OFFS);
+                       if (MV_OK !=
+                           ddr3_sdram_compare(dram_info, (u32) NULL, NULL,
+                                              pattern_ptr1, LEN_STD_PATTERN,
+                                              sdram_addr, 1, 0, NULL,
+                                              0))
+                               return MV_FAIL;
+               }
+       }
+
+       return MV_OK;
+}
+#endif
diff --git a/drivers/ddr/mvebu/ddr3_read_leveling.c b/drivers/ddr/mvebu/ddr3_read_leveling.c
new file mode 100644 (file)
index 0000000..4662bde
--- /dev/null
@@ -0,0 +1,1214 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_RL_C(s, d, l) \
+       DEBUG_RL_S(s); DEBUG_RL_D(d, l); DEBUG_RL_S("\n")
+#define DEBUG_RL_FULL_C(s, d, l) \
+       DEBUG_RL_FULL_S(s); DEBUG_RL_FULL_D(d, l); DEBUG_RL_FULL_S("\n")
+
+#ifdef MV_DEBUG_RL
+#define DEBUG_RL_S(s) \
+       debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
+#define DEBUG_RL_D(d, l) \
+       debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
+#else
+#define DEBUG_RL_S(s)
+#define DEBUG_RL_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_RL_FULL
+#define DEBUG_RL_FULL_S(s)             puts(s)
+#define DEBUG_RL_FULL_D(d, l)          printf("%x", d)
+#else
+#define DEBUG_RL_FULL_S(s)
+#define DEBUG_RL_FULL_D(d, l)
+#endif
+
+extern u32 rl_pattern[LEN_STD_PATTERN];
+
+#ifdef RL_MODE
+static int ddr3_read_leveling_single_cs_rl_mode(u32 cs, u32 freq,
+                                               int ratio_2to1, u32 ecc,
+                                               MV_DRAM_INFO *dram_info);
+#else
+static int ddr3_read_leveling_single_cs_window_mode(u32 cs, u32 freq,
+                                                   int ratio_2to1, u32 ecc,
+                                                   MV_DRAM_INFO *dram_info);
+#endif
+
+/*
+ * Name:     ddr3_read_leveling_hw
+ * Desc:     Execute the Read leveling phase by HW
+ * Args:     dram_info - main struct
+ *           freq      - current sequence frequency
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_read_leveling_hw(u32 freq, MV_DRAM_INFO *dram_info)
+{
+       u32 reg;
+
+       /* Debug message - Start Read leveling procedure */
+       DEBUG_RL_S("DDR3 - Read Leveling - Starting HW RL procedure\n");
+
+       /* Start Auto Read Leveling procedure */
+       reg = 1 << REG_DRAM_TRAINING_RL_OFFS;
+       /* Config the retest number */
+       reg |= (COUNT_HW_RL << REG_DRAM_TRAINING_RETEST_OFFS);
+
+       /* Enable CS in the automatic process */
+       reg |= (dram_info->cs_ena << REG_DRAM_TRAINING_CS_OFFS);
+
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) |
+               (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       reg_write(REG_DRAM_TRAINING_SHADOW_ADDR, reg);
+
+       /* Wait */
+       do {
+               reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
+                       (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       } while (reg);          /* Wait for '0' */
+
+       /* Check if Successful */
+       if (reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
+           (1 << REG_DRAM_TRAINING_ERROR_OFFS)) {
+               u32 delay, phase, pup, cs;
+
+               dram_info->rl_max_phase = 0;
+               dram_info->rl_min_phase = 10;
+
+               /* Read results to arrays */
+               for (cs = 0; cs < MAX_CS; cs++) {
+                       if (dram_info->cs_ena & (1 << cs)) {
+                               for (pup = 0;
+                                    pup < dram_info->num_of_total_pups;
+                                    pup++) {
+                                       if (pup == dram_info->num_of_std_pups
+                                           && dram_info->ecc_ena)
+                                               pup = ECC_PUP;
+                                       reg =
+                                           ddr3_read_pup_reg(PUP_RL_MODE, cs,
+                                                             pup);
+                                       phase = (reg >> REG_PHY_PHASE_OFFS) &
+                                               PUP_PHASE_MASK;
+                                       delay = reg & PUP_DELAY_MASK;
+                                       dram_info->rl_val[cs][pup][P] = phase;
+                                       if (phase > dram_info->rl_max_phase)
+                                               dram_info->rl_max_phase = phase;
+                                       if (phase < dram_info->rl_min_phase)
+                                               dram_info->rl_min_phase = phase;
+                                       dram_info->rl_val[cs][pup][D] = delay;
+                                       dram_info->rl_val[cs][pup][S] =
+                                           RL_FINAL_STATE;
+                                       reg =
+                                           ddr3_read_pup_reg(PUP_RL_MODE + 0x1,
+                                                             cs, pup);
+                                       dram_info->rl_val[cs][pup][DQS] =
+                                           (reg & 0x3F);
+                               }
+#ifdef MV_DEBUG_RL
+                               /* Print results */
+                               DEBUG_RL_C("DDR3 - Read Leveling - Results for CS - ",
+                                          (u32) cs, 1);
+
+                               for (pup = 0;
+                                    pup < (dram_info->num_of_total_pups);
+                                    pup++) {
+                                       if (pup == dram_info->num_of_std_pups
+                                           && dram_info->ecc_ena)
+                                               pup = ECC_PUP;
+                                       DEBUG_RL_S("DDR3 - Read Leveling - PUP: ");
+                                       DEBUG_RL_D((u32) pup, 1);
+                                       DEBUG_RL_S(", Phase: ");
+                                       DEBUG_RL_D((u32) dram_info->
+                                                  rl_val[cs][pup][P], 1);
+                                       DEBUG_RL_S(", Delay: ");
+                                       DEBUG_RL_D((u32) dram_info->
+                                                  rl_val[cs][pup][D], 2);
+                                       DEBUG_RL_S("\n");
+                               }
+#endif
+                       }
+               }
+
+               dram_info->rd_rdy_dly =
+                       reg_read(REG_READ_DATA_READY_DELAYS_ADDR) &
+                       REG_READ_DATA_SAMPLE_DELAYS_MASK;
+               dram_info->rd_smpl_dly =
+                       reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR) &
+                       REG_READ_DATA_READY_DELAYS_MASK;
+#ifdef MV_DEBUG_RL
+               DEBUG_RL_C("DDR3 - Read Leveling - Read Sample Delay: ",
+                          dram_info->rd_smpl_dly, 2);
+               DEBUG_RL_C("DDR3 - Read Leveling - Read Ready Delay: ",
+                          dram_info->rd_rdy_dly, 2);
+               DEBUG_RL_S("DDR3 - Read Leveling - HW RL Ended Successfully\n");
+#endif
+               return MV_OK;
+
+       } else {
+               DEBUG_RL_S("DDR3 - Read Leveling - HW RL Error\n");
+               return MV_FAIL;
+       }
+}
+
+/*
+ * Name:     ddr3_read_leveling_sw
+ * Desc:     Execute the Read leveling phase by SW
+ * Args:     dram_info - main struct
+ *           freq      - current sequence frequency
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_read_leveling_sw(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info)
+{
+       u32 reg, cs, ecc, pup_num, phase, delay, pup;
+       int status;
+
+       /* Debug message - Start Read leveling procedure */
+       DEBUG_RL_S("DDR3 - Read Leveling - Starting SW RL procedure\n");
+
+       /* Enable SW Read Leveling */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       reg &= ~(1 << REG_DRAM_TRAINING_2_RL_MODE_OFFS);
+       /* [0]=1 - Enable SW override  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+#ifdef RL_MODE
+       reg = (dram_info->cs_ena << REG_DRAM_TRAINING_CS_OFFS) |
+               (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+#endif
+
+       /* Loop for each CS */
+       for (cs = 0; cs < dram_info->num_cs; cs++) {
+               DEBUG_RL_C("DDR3 - Read Leveling - CS - ", (u32) cs, 1);
+
+               for (ecc = 0; ecc <= (dram_info->ecc_ena); ecc++) {
+                       /* ECC Support - Switch ECC Mux on ecc=1 */
+                       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+                               ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                       reg |= (dram_info->ecc_ena *
+                               ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+                       if (ecc)
+                               DEBUG_RL_S("DDR3 - Read Leveling - ECC Mux Enabled\n");
+                       else
+                               DEBUG_RL_S("DDR3 - Read Leveling - ECC Mux Disabled\n");
+
+                       /* Set current sample delays */
+                       reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+                       reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK <<
+                                (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+                       reg |= (dram_info->cl <<
+                               (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+                       reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, reg);
+
+                       /* Set current Ready delay */
+                       reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+                       reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+                                (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                       if (!ratio_2to1) {
+                               /* 1:1 mode */
+                               reg |= ((dram_info->cl + 1) <<
+                                       (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                       } else {
+                               /* 2:1 mode */
+                               reg |= ((dram_info->cl + 2) <<
+                                       (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                       }
+                       reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+
+                       /* Read leveling Single CS[cs] */
+#ifdef RL_MODE
+                       status =
+                           ddr3_read_leveling_single_cs_rl_mode(cs, freq,
+                                                                ratio_2to1,
+                                                                ecc,
+                                                                dram_info);
+                       if (MV_OK != status)
+                               return status;
+#else
+                       status =
+                           ddr3_read_leveling_single_cs_window_mode(cs, freq,
+                                                                    ratio_2to1,
+                                                                    ecc,
+                                                                    dram_info)
+                           if (MV_OK != status)
+                               return status;
+#endif
+               }
+
+               /* Print results */
+               DEBUG_RL_C("DDR3 - Read Leveling - Results for CS - ", (u32) cs,
+                          1);
+
+               for (pup = 0;
+                    pup < (dram_info->num_of_std_pups + dram_info->ecc_ena);
+                    pup++) {
+                       DEBUG_RL_S("DDR3 - Read Leveling - PUP: ");
+                       DEBUG_RL_D((u32) pup, 1);
+                       DEBUG_RL_S(", Phase: ");
+                       DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][P], 1);
+                       DEBUG_RL_S(", Delay: ");
+                       DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][D], 2);
+                       DEBUG_RL_S("\n");
+               }
+
+               DEBUG_RL_C("DDR3 - Read Leveling - Read Sample Delay: ",
+                          dram_info->rd_smpl_dly, 2);
+               DEBUG_RL_C("DDR3 - Read Leveling - Read Ready Delay: ",
+                          dram_info->rd_rdy_dly, 2);
+
+               /* Configure PHY with average of 3 locked leveling settings */
+               for (pup = 0;
+                    pup < (dram_info->num_of_std_pups + dram_info->ecc_ena);
+                    pup++) {
+                       /* ECC support - bit 8 */
+                       pup_num = (pup == dram_info->num_of_std_pups) ? ECC_BIT : pup;
+
+                       /* For now, set last cnt result */
+                       phase = dram_info->rl_val[cs][pup][P];
+                       delay = dram_info->rl_val[cs][pup][D];
+                       ddr3_write_pup_reg(PUP_RL_MODE, cs, pup_num, phase,
+                                          delay);
+               }
+       }
+
+       /* Reset PHY read FIFO */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       do {
+               reg = (reg_read(REG_DRAM_TRAINING_2_ADDR)) &
+                       (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+       } while (reg);          /* Wait for '0' */
+
+       /* ECC Support - Switch ECC Mux off ecc=0 */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+               ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+#ifdef RL_MODE
+       reg_write(REG_DRAM_TRAINING_ADDR, 0);   /* 0x15B0 - Training Register */
+#endif
+
+       /* Disable SW Read Leveling */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+               ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* [0] = 0 - Disable SW override  */
+       reg = (reg | (0x1 << REG_DRAM_TRAINING_2_RL_MODE_OFFS));
+       /* [3] = 1 - Disable RL MODE */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       DEBUG_RL_S("DDR3 - Read Leveling - Finished RL procedure for all CS\n");
+       return MV_OK;
+}
+
+#ifdef RL_MODE
+/*
+ * overrun() extracted from ddr3_read_leveling_single_cs_rl_mode().
+ * This just got too much indented making it hard to read / edit.
+ */
+static void overrun(u32 cs, MV_DRAM_INFO *info, u32 pup, u32 locked_pups,
+                   u32 *locked_sum, u32 ecc, int *first_octet_locked,
+                   int *counter_in_progress, int final_delay, u32 delay,
+                   u32 phase)
+{
+       /* If no OverRun */
+       if (((~locked_pups >> pup) & 0x1) && (final_delay == 0)) {
+               int idx;
+
+               idx = pup + ecc * ECC_BIT;
+
+               /* PUP passed, start examining */
+               if (info->rl_val[cs][idx][S] == RL_UNLOCK_STATE) {
+                       /* Must be RL_UNLOCK_STATE */
+                       /* Match expected value ? - Update State Machine */
+                       if (info->rl_val[cs][idx][C] < RL_RETRY_COUNT) {
+                               DEBUG_RL_FULL_C("DDR3 - Read Leveling - We have no overrun and a match on pup: ",
+                                               (u32)pup, 1);
+                               info->rl_val[cs][idx][C]++;
+
+                               /* If pup got to last state - lock the delays */
+                               if (info->rl_val[cs][idx][C] == RL_RETRY_COUNT) {
+                                       info->rl_val[cs][idx][C] = 0;
+                                       info->rl_val[cs][idx][DS] = delay;
+                                       info->rl_val[cs][idx][PS] = phase;
+
+                                       /* Go to Final State */
+                                       info->rl_val[cs][idx][S] = RL_FINAL_STATE;
+                                       *locked_sum = *locked_sum + 1;
+                                       DEBUG_RL_FULL_C("DDR3 - Read Leveling - We have locked pup: ",
+                                                       (u32)pup, 1);
+
+                                       /*
+                                        * If first lock - need to lock delays
+                                        */
+                                       if (*first_octet_locked == 0) {
+                                               DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got first lock on pup: ",
+                                                               (u32)pup, 1);
+                                               *first_octet_locked = 1;
+                                       }
+
+                                       /*
+                                        * If pup is in not in final state but
+                                        * there was match - dont increment
+                                        * counter
+                                        */
+                               } else {
+                                       *counter_in_progress = 1;
+                               }
+                       }
+               }
+       }
+}
+
+/*
+ * Name:     ddr3_read_leveling_single_cs_rl_mode
+ * Desc:     Execute Read leveling for single Chip select
+ * Args:     cs        - current chip select
+ *           freq      - current sequence frequency
+ *           ecc       - ecc iteration indication
+ *           dram_info - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+static int ddr3_read_leveling_single_cs_rl_mode(u32 cs, u32 freq,
+                                               int ratio_2to1, u32 ecc,
+                                               MV_DRAM_INFO *dram_info)
+{
+       u32 reg, delay, phase, pup, rd_sample_delay, add, locked_pups,
+               repeat_max_cnt, sdram_offset, locked_sum;
+       u32 phase_min, ui_max_delay;
+       int all_locked, first_octet_locked, counter_in_progress;
+       int final_delay = 0;
+
+       DEBUG_RL_FULL_C("DDR3 - Read Leveling - Single CS - ", (u32) cs, 1);
+
+       /* Init values */
+       phase = 0;
+       delay = 0;
+       rd_sample_delay = dram_info->cl;
+       all_locked = 0;
+       first_octet_locked = 0;
+       repeat_max_cnt = 0;
+       locked_sum = 0;
+
+       for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+            pup++)
+               dram_info->rl_val[cs][pup + ecc * ECC_BIT][S] = 0;
+
+       /* Main loop */
+       while (!all_locked) {
+               counter_in_progress = 0;
+
+               DEBUG_RL_FULL_S("DDR3 - Read Leveling - RdSmplDly = ");
+               DEBUG_RL_FULL_D(rd_sample_delay, 2);
+               DEBUG_RL_FULL_S(", RdRdyDly = ");
+               DEBUG_RL_FULL_D(dram_info->rd_rdy_dly, 2);
+               DEBUG_RL_FULL_S(", Phase = ");
+               DEBUG_RL_FULL_D(phase, 1);
+               DEBUG_RL_FULL_S(", Delay = ");
+               DEBUG_RL_FULL_D(delay, 2);
+               DEBUG_RL_FULL_S("\n");
+
+               /*
+                * Broadcast to all PUPs current RL delays: DQS phase,
+                * leveling delay
+                */
+               ddr3_write_pup_reg(PUP_RL_MODE, cs, PUP_BC, phase, delay);
+
+               /* Reset PHY read FIFO */
+               reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+                       (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+               /* 0x15B8 - Training SW 2 Register */
+               reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+               do {
+                       reg = (reg_read(REG_DRAM_TRAINING_2_ADDR)) &
+                               (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+               } while (reg);  /* Wait for '0' */
+
+               /* Read pattern from SDRAM */
+               sdram_offset = cs * (SDRAM_CS_SIZE + 1) + SDRAM_RL_OFFS;
+               locked_pups = 0;
+               if (MV_OK !=
+                   ddr3_sdram_compare(dram_info, 0xFF, &locked_pups,
+                                      rl_pattern, LEN_STD_PATTERN,
+                                      sdram_offset, 0, 0, NULL, 0))
+                       return MV_DDR3_TRAINING_ERR_RD_LVL_RL_PATTERN;
+
+               /* Octet evaluation */
+               /* pup_num = Q or 1 for ECC */
+               for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc); pup++) {
+                       /* Check Overrun */
+                       if (!((reg_read(REG_DRAM_TRAINING_2_ADDR) >>
+                              (REG_DRAM_TRAINING_2_OVERRUN_OFFS + pup)) & 0x1)) {
+                               overrun(cs, dram_info, pup, locked_pups,
+                                       &locked_sum, ecc, &first_octet_locked,
+                                       &counter_in_progress, final_delay,
+                                       delay, phase);
+                       } else {
+                               DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got overrun on pup: ",
+                                               (u32)pup, 1);
+                       }
+               }
+
+               if (locked_sum == (dram_info->num_of_std_pups *
+                                  (1 - ecc) + ecc)) {
+                       all_locked = 1;
+                       DEBUG_RL_FULL_S("DDR3 - Read Leveling - Single Cs - All pups locked\n");
+               }
+
+               /*
+                * This is a fix for unstable condition where pups are
+                * toggling between match and no match
+                */
+               /*
+                * If some of the pups is >1 <3, check if we did it too
+                * many times
+                */
+               if (counter_in_progress == 1) {
+                       /* Notify at least one Counter is >=1 and < 3 */
+                       if (repeat_max_cnt < RL_RETRY_COUNT) {
+                               repeat_max_cnt++;
+                               counter_in_progress = 1;
+                               DEBUG_RL_FULL_S("DDR3 - Read Leveling - Counter is >=1 and <3\n");
+                               DEBUG_RL_FULL_S("DDR3 - Read Leveling - So we will not increment the delay to see if locked again\n");
+                       } else {
+                               DEBUG_RL_FULL_S("DDR3 - Read Leveling - repeat_max_cnt reached max so now we will increment the delay\n");
+                               counter_in_progress = 0;
+                       }
+               }
+
+               /*
+                * Check some of the pups are in the middle of state machine
+                * and don't increment the delays
+                */
+               if (!counter_in_progress && !all_locked) {
+                       int idx;
+
+                       idx = pup + ecc * ECC_BIT;
+
+                       repeat_max_cnt = 0;
+                       /* if 1:1 mode */
+                       if ((!ratio_2to1) && ((phase == 0) || (phase == 4)))
+                               ui_max_delay = MAX_DELAY_INV;
+                       else
+                               ui_max_delay = MAX_DELAY;
+
+                       /* Increment Delay */
+                       if (delay < ui_max_delay) {
+                               delay++;
+                               /*
+                                * Mark the last delay/pahse place for
+                                * window final place
+                                */
+                               if (delay == ui_max_delay) {
+                                       if ((!ratio_2to1 && phase ==
+                                            MAX_PHASE_RL_L_1TO1)
+                                           || (ratio_2to1 && phase ==
+                                               MAX_PHASE_RL_L_2TO1))
+                                               final_delay = 1;
+                               }
+                       } else {
+                               /* Phase+CL Incrementation */
+                               delay = 0;
+
+                               if (!ratio_2to1) {
+                                       /* 1:1 mode */
+                                       if (first_octet_locked) {
+                                               /* some Pup was Locked */
+                                               if (phase < MAX_PHASE_RL_L_1TO1) {
+                                                       if (phase == 1) {
+                                                               phase = 4;
+                                                       } else {
+                                                               phase++;
+                                                               delay = MIN_DELAY_PHASE_1_LIMIT;
+                                                       }
+                                               } else {
+                                                       DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+                                                       DEBUG_RL_S("1)DDR3 - Read Leveling - ERROR - NOT all PUPs Locked n");
+                                                       return MV_DDR3_TRAINING_ERR_RD_LVL_RL_PUP_UNLOCK;
+                                               }
+                                       } else {
+                                               /* NO Pup was Locked */
+                                               if (phase < MAX_PHASE_RL_UL_1TO1) {
+                                                       phase++;
+                                                       delay =
+                                                           MIN_DELAY_PHASE_1_LIMIT;
+                                               } else {
+                                                       phase = 0;
+                                               }
+                                       }
+                               } else {
+                                       /* 2:1 mode */
+                                       if (first_octet_locked) {
+                                               /* some Pup was Locked */
+                                               if (phase < MAX_PHASE_RL_L_2TO1) {
+                                                       phase++;
+                                               } else {
+                                                       DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+                                                       DEBUG_RL_S("2)DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+                                                       for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc); pup++) {
+                                                               /* pup_num = Q or 1 for ECC */
+                                                               if (dram_info->rl_val[cs][idx][S]
+                                                                   == 0) {
+                                                                       DEBUG_RL_C("Failed byte is = ",
+                                                                                  pup, 1);
+                                                               }
+                                                       }
+                                                       return MV_DDR3_TRAINING_ERR_RD_LVL_RL_PUP_UNLOCK;
+                                               }
+                                       } else {
+                                               /* No Pup was Locked */
+                                               if (phase < MAX_PHASE_RL_UL_2TO1)
+                                                       phase++;
+                                               else
+                                                       phase = 0;
+                                       }
+                               }
+
+                               /*
+                                * If we finished a full Phases cycle (so now
+                                * phase = 0, need to increment rd_sample_dly
+                                */
+                               if (phase == 0 && first_octet_locked == 0) {
+                                       rd_sample_delay++;
+                                       if (rd_sample_delay == 0x10) {
+                                               DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+                                               DEBUG_RL_S("3)DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+                                               for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc); pup++) {
+                                                       /* pup_num = Q or 1 for ECC */
+                                                       if (dram_info->
+                                                           rl_val[cs][idx][S] == 0) {
+                                                               DEBUG_RL_C("Failed byte is = ",
+                                                                          pup, 1);
+                                                       }
+                                               }
+                                               return MV_DDR3_TRAINING_ERR_RD_LVL_PUP_UNLOCK;
+                                       }
+
+                                       /* Set current rd_sample_delay  */
+                                       reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+                                       reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK
+                                             << (REG_READ_DATA_SAMPLE_DELAYS_OFFS
+                                                 * cs));
+                                       reg |= (rd_sample_delay <<
+                                               (REG_READ_DATA_SAMPLE_DELAYS_OFFS *
+                                                cs));
+                                       reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR,
+                                                 reg);
+                               }
+
+                               /*
+                                * Set current rdReadyDelay according to the
+                                * hash table (Need to do this in every phase
+                                * change)
+                                */
+                               if (!ratio_2to1) {
+                                       /* 1:1 mode */
+                                       add = reg_read(REG_TRAINING_DEBUG_2_ADDR);
+                                       switch (phase) {
+                                       case 0:
+                                               add = (add >>
+                                                      REG_TRAINING_DEBUG_2_OFFS);
+                                               break;
+                                       case 1:
+                                               add = (add >>
+                                                      (REG_TRAINING_DEBUG_2_OFFS
+                                                       + 3));
+                                               break;
+                                       case 4:
+                                               add = (add >>
+                                                      (REG_TRAINING_DEBUG_2_OFFS
+                                                       + 6));
+                                               break;
+                                       case 5:
+                                               add = (add >>
+                                                      (REG_TRAINING_DEBUG_2_OFFS
+                                                       + 9));
+                                               break;
+                                       }
+                                       add &= REG_TRAINING_DEBUG_2_MASK;
+                               } else {
+                                       /* 2:1 mode */
+                                       add = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+                                       add = (add >>
+                                              (phase *
+                                               REG_TRAINING_DEBUG_3_OFFS));
+                                       add &= REG_TRAINING_DEBUG_3_MASK;
+                               }
+
+                               reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+                               reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+                                        (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                               reg |= ((rd_sample_delay + add) <<
+                                       (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                               reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+                               dram_info->rd_smpl_dly = rd_sample_delay;
+                               dram_info->rd_rdy_dly = rd_sample_delay + add;
+                       }
+
+                       /* Reset counters for pups with states<RD_STATE_COUNT */
+                       for (pup = 0; pup <
+                                    (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+                            pup++) {
+                               if (dram_info->rl_val[cs][idx][C] < RL_RETRY_COUNT)
+                                       dram_info->rl_val[cs][idx][C] = 0;
+                       }
+               }
+       }
+
+       phase_min = 10;
+
+       for (pup = 0; pup < (dram_info->num_of_std_pups); pup++) {
+               if (dram_info->rl_val[cs][pup][PS] < phase_min)
+                       phase_min = dram_info->rl_val[cs][pup][PS];
+       }
+
+       /*
+        * Set current rdReadyDelay according to the hash table (Need to
+        * do this in every phase change)
+        */
+       if (!ratio_2to1) {
+               /* 1:1 mode */
+               add = reg_read(REG_TRAINING_DEBUG_2_ADDR);
+               switch (phase_min) {
+               case 0:
+                       add = (add >> REG_TRAINING_DEBUG_2_OFFS);
+                       break;
+               case 1:
+                       add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 3));
+                       break;
+               case 4:
+                       add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 6));
+                       break;
+               case 5:
+                       add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 9));
+                       break;
+               }
+               add &= REG_TRAINING_DEBUG_2_MASK;
+       } else {
+               /* 2:1 mode */
+               add = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+               add = (add >> (phase_min * REG_TRAINING_DEBUG_3_OFFS));
+               add &= REG_TRAINING_DEBUG_3_MASK;
+       }
+
+       reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+       reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+                (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+       reg |= ((rd_sample_delay + add) << (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+       reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+       dram_info->rd_rdy_dly = rd_sample_delay + add;
+
+       for (cs = 0; cs < dram_info->num_cs; cs++) {
+               for (pup = 0; pup < dram_info->num_of_total_pups; pup++) {
+                       reg = ddr3_read_pup_reg(PUP_RL_MODE + 0x1, cs, pup);
+                       dram_info->rl_val[cs][pup][DQS] = (reg & 0x3F);
+               }
+       }
+
+       return MV_OK;
+}
+
+#else
+
+/*
+ * Name:     ddr3_read_leveling_single_cs_window_mode
+ * Desc:     Execute Read leveling for single Chip select
+ * Args:     cs        - current chip select
+ *           freq      - current sequence frequency
+ *           ecc       - ecc iteration indication
+ *           dram_info - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+static int ddr3_read_leveling_single_cs_window_mode(u32 cs, u32 freq,
+                                                   int ratio_2to1, u32 ecc,
+                                                   MV_DRAM_INFO *dram_info)
+{
+       u32 reg, delay, phase, sum, pup, rd_sample_delay, add, locked_pups,
+           repeat_max_cnt, sdram_offset, final_sum, locked_sum;
+       u32 delay_s, delay_e, tmp, phase_min, ui_max_delay;
+       int all_locked, first_octet_locked, counter_in_progress;
+       int final_delay = 0;
+
+       DEBUG_RL_FULL_C("DDR3 - Read Leveling - Single CS - ", (u32) cs, 1);
+
+       /* Init values */
+       phase = 0;
+       delay = 0;
+       rd_sample_delay = dram_info->cl;
+       all_locked = 0;
+       first_octet_locked = 0;
+       repeat_max_cnt = 0;
+       sum = 0;
+       final_sum = 0;
+       locked_sum = 0;
+
+       for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+            pup++)
+               dram_info->rl_val[cs][pup + ecc * ECC_BIT][S] = 0;
+
+       /* Main loop */
+       while (!all_locked) {
+               counter_in_progress = 0;
+
+               DEBUG_RL_FULL_S("DDR3 - Read Leveling - RdSmplDly = ");
+               DEBUG_RL_FULL_D(rd_sample_delay, 2);
+               DEBUG_RL_FULL_S(", RdRdyDly = ");
+               DEBUG_RL_FULL_D(dram_info->rd_rdy_dly, 2);
+               DEBUG_RL_FULL_S(", Phase = ");
+               DEBUG_RL_FULL_D(phase, 1);
+               DEBUG_RL_FULL_S(", Delay = ");
+               DEBUG_RL_FULL_D(delay, 2);
+               DEBUG_RL_FULL_S("\n");
+
+               /*
+                * Broadcast to all PUPs current RL delays: DQS phase,leveling
+                * delay
+                */
+               ddr3_write_pup_reg(PUP_RL_MODE, cs, PUP_BC, phase, delay);
+
+               /* Reset PHY read FIFO */
+               reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+                       (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+               /* 0x15B8 - Training SW 2 Register */
+               reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+               do {
+                       reg = (reg_read(REG_DRAM_TRAINING_2_ADDR)) &
+                               (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+               } while (reg);  /* Wait for '0' */
+
+               /* Read pattern from SDRAM */
+               sdram_offset = cs * (SDRAM_CS_SIZE + 1) + SDRAM_RL_OFFS;
+               locked_pups = 0;
+               if (MV_OK !=
+                   ddr3_sdram_compare(dram_info, 0xFF, &locked_pups,
+                                      rl_pattern, LEN_STD_PATTERN,
+                                      sdram_offset, 0, 0, NULL, 0))
+                       return MV_DDR3_TRAINING_ERR_RD_LVL_WIN_PATTERN;
+
+               /* Octet evaluation */
+               for (pup = 0; pup < (dram_info->num_of_std_pups *
+                                    (1 - ecc) + ecc); pup++) {
+                       /* pup_num = Q or 1 for ECC */
+                       int idx;
+
+                       idx = pup + ecc * ECC_BIT;
+
+                       /* Check Overrun */
+                       if (!((reg_read(REG_DRAM_TRAINING_2_ADDR) >>
+                             (REG_DRAM_TRAINING_2_OVERRUN_OFFS +
+                              pup)) & 0x1)) {
+                               /* If no OverRun */
+
+                               /* Inside the window */
+                               if (dram_info->rl_val[cs][idx][S] == RL_WINDOW_STATE) {
+                                       /*
+                                        * Match expected value ? - Update
+                                        * State Machine
+                                        */
+                                       if (((~locked_pups >> pup) & 0x1)
+                                           && (final_delay == 0)) {
+                                               /* Match - Still inside the Window */
+                                               DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got another match inside the window  for pup: ",
+                                                               (u32)pup, 1);
+
+                                       } else {
+                                               /* We got fail -> this is the end of the window */
+                                               dram_info->rl_val[cs][idx][DE] = delay;
+                                               dram_info->rl_val[cs][idx][PE] = phase;
+                                               /* Go to Final State */
+                                               dram_info->rl_val[cs][idx][S]++;
+                                               final_sum++;
+                                               DEBUG_RL_FULL_C("DDR3 - Read Leveling - We finished the window for pup: ",
+                                                               (u32)pup, 1);
+                                       }
+
+                                       /* Before the start of the window */
+                               } else if (dram_info->rl_val[cs][idx][S] ==
+                                          RL_UNLOCK_STATE) {
+                                       /* Must be RL_UNLOCK_STATE */
+                                       /*
+                                        * Match expected value ? - Update
+                                        * State Machine
+                                        */
+                                       if (dram_info->rl_val[cs][idx][C] <
+                                           RL_RETRY_COUNT) {
+                                               if (((~locked_pups >> pup) & 0x1)) {
+                                                       /* Match */
+                                                       DEBUG_RL_FULL_C("DDR3 - Read Leveling - We have no overrun and a match on pup: ",
+                                                                       (u32)pup, 1);
+                                                       dram_info->rl_val[cs][idx][C]++;
+
+                                                       /* If pup got to last state - lock the delays */
+                                                       if (dram_info->rl_val[cs][idx][C] ==
+                                                           RL_RETRY_COUNT) {
+                                                               dram_info->rl_val[cs][idx][C] = 0;
+                                                               dram_info->rl_val[cs][idx][DS] =
+                                                                       delay;
+                                                               dram_info->rl_val[cs][idx][PS] =
+                                                                       phase;
+                                                               dram_info->rl_val[cs][idx][S]++;        /* Go to Window State */
+                                                               locked_sum++;
+                                                               /* Will count the pups that got locked */
+
+                                                               /* IF First lock - need to lock delays */
+                                                               if (first_octet_locked == 0) {
+                                                                       DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got first lock on pup: ",
+                                                                                       (u32)pup, 1);
+                                                                       first_octet_locked
+                                                                           =
+                                                                           1;
+                                                               }
+                                                       }
+
+                                                       /* if pup is in not in final state but there was match - dont increment counter */
+                                                       else {
+                                                               counter_in_progress
+                                                                   = 1;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else {
+                               DEBUG_RL_FULL_C("DDR3 - Read Leveling - We got overrun on pup: ",
+                                               (u32)pup, 1);
+                               counter_in_progress = 1;
+                       }
+               }
+
+               if (final_sum == (dram_info->num_of_std_pups * (1 - ecc) + ecc)) {
+                       all_locked = 1;
+                       DEBUG_RL_FULL_S("DDR3 - Read Leveling - Single Cs - All pups locked\n");
+               }
+
+               /*
+                * This is a fix for unstable condition where pups are
+                * toggling between match and no match
+                */
+               /*
+                * If some of the pups is >1 <3, check if we did it too many
+                * times
+                */
+               if (counter_in_progress == 1) {
+                       if (repeat_max_cnt < RL_RETRY_COUNT) {
+                               /* Notify at least one Counter is >=1 and < 3 */
+                               repeat_max_cnt++;
+                               counter_in_progress = 1;
+                               DEBUG_RL_FULL_S("DDR3 - Read Leveling - Counter is >=1 and <3\n");
+                               DEBUG_RL_FULL_S("DDR3 - Read Leveling - So we will not increment the delay to see if locked again\n");
+                       } else {
+                               DEBUG_RL_FULL_S("DDR3 - Read Leveling - repeat_max_cnt reached max so now we will increment the delay\n");
+                               counter_in_progress = 0;
+                       }
+               }
+
+               /*
+                * Check some of the pups are in the middle of state machine
+                * and don't increment the delays
+                */
+               if (!counter_in_progress && !all_locked) {
+                       repeat_max_cnt = 0;
+                       if (!ratio_2to1)
+                               ui_max_delay = MAX_DELAY_INV;
+                       else
+                               ui_max_delay = MAX_DELAY;
+
+                       /* Increment Delay */
+                       if (delay < ui_max_delay) {
+                               /* Delay Incrementation */
+                               delay++;
+                               if (delay == ui_max_delay) {
+                                       /*
+                                        * Mark the last delay/pahse place
+                                        * for window final place
+                                        */
+                                       if ((!ratio_2to1
+                                            && phase == MAX_PHASE_RL_L_1TO1)
+                                           || (ratio_2to1
+                                               && phase ==
+                                               MAX_PHASE_RL_L_2TO1))
+                                               final_delay = 1;
+                               }
+                       } else {
+                               /* Phase+CL Incrementation */
+                               delay = 0;
+                               if (!ratio_2to1) {
+                                       /* 1:1 mode */
+                                       if (first_octet_locked) {
+                                               /* some pupet was Locked */
+                                               if (phase < MAX_PHASE_RL_L_1TO1) {
+#ifdef RL_WINDOW_WA
+                                                       if (phase == 0)
+#else
+                                                       if (phase == 1)
+#endif
+                                                               phase = 4;
+                                                       else
+                                                               phase++;
+                                               } else {
+                                                       DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+                                                       return MV_DDR3_TRAINING_ERR_RD_LVL_WIN_PUP_UNLOCK;
+                                               }
+                                       } else {
+                                               /* No Pup was Locked */
+                                               if (phase < MAX_PHASE_RL_UL_1TO1) {
+#ifdef RL_WINDOW_WA
+                                                       if (phase == 0)
+                                                               phase = 4;
+#else
+                                                       phase++;
+#endif
+                                               } else
+                                                       phase = 0;
+                                       }
+                               } else {
+                                       /* 2:1 mode */
+                                       if (first_octet_locked) {
+                                               /* Some Pup was Locked */
+                                               if (phase < MAX_PHASE_RL_L_2TO1) {
+                                                       phase++;
+                                               } else {
+                                                       DEBUG_RL_FULL_S("DDR3 - Read Leveling - ERROR - NOT all PUPs Locked\n");
+                                                       return MV_DDR3_TRAINING_ERR_RD_LVL_WIN_PUP_UNLOCK;
+                                               }
+                                       } else {
+                                               /* No Pup was Locked */
+                                               if (phase < MAX_PHASE_RL_UL_2TO1)
+                                                       phase++;
+                                               else
+                                                       phase = 0;
+                                       }
+                               }
+
+                               /*
+                                * If we finished a full Phases cycle (so
+                                * now phase = 0, need to increment
+                                * rd_sample_dly
+                                */
+                               if (phase == 0 && first_octet_locked == 0) {
+                                       rd_sample_delay++;
+
+                                       /* Set current rd_sample_delay  */
+                                       reg = reg_read(REG_READ_DATA_SAMPLE_DELAYS_ADDR);
+                                       reg &= ~(REG_READ_DATA_SAMPLE_DELAYS_MASK <<
+                                                (REG_READ_DATA_SAMPLE_DELAYS_OFFS
+                                                 * cs));
+                                       reg |= (rd_sample_delay <<
+                                               (REG_READ_DATA_SAMPLE_DELAYS_OFFS *
+                                                cs));
+                                       reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR,
+                                                 reg);
+                               }
+
+                               /*
+                                * Set current rdReadyDelay according to the
+                                * hash table (Need to do this in every phase
+                                * change)
+                                */
+                               if (!ratio_2to1) {
+                                       /* 1:1 mode */
+                                       add = reg_read(REG_TRAINING_DEBUG_2_ADDR);
+                                       switch (phase) {
+                                       case 0:
+                                               add = add >>
+                                                       REG_TRAINING_DEBUG_2_OFFS;
+                                               break;
+                                       case 1:
+                                               add = add >>
+                                                       (REG_TRAINING_DEBUG_2_OFFS
+                                                        + 3);
+                                               break;
+                                       case 4:
+                                               add = add >>
+                                                       (REG_TRAINING_DEBUG_2_OFFS
+                                                        + 6);
+                                               break;
+                                       case 5:
+                                               add = add >>
+                                                       (REG_TRAINING_DEBUG_2_OFFS
+                                                        + 9);
+                                               break;
+                                       }
+                               } else {
+                                       /* 2:1 mode */
+                                       add = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+                                       add = (add >> phase *
+                                              REG_TRAINING_DEBUG_3_OFFS);
+                               }
+                               add &= REG_TRAINING_DEBUG_2_MASK;
+                               reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+                               reg &= ~(REG_READ_DATA_READY_DELAYS_MASK <<
+                                        (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                               reg |= ((rd_sample_delay + add) <<
+                                       (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+                               reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+                               dram_info->rd_smpl_dly = rd_sample_delay;
+                               dram_info->rd_rdy_dly = rd_sample_delay + add;
+                       }
+
+                       /* Reset counters for pups with states<RD_STATE_COUNT */
+                       for (pup = 0;
+                            pup <
+                            (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+                            pup++) {
+                               if (dram_info->rl_val[cs][idx][C] < RL_RETRY_COUNT)
+                                       dram_info->rl_val[cs][idx][C] = 0;
+                       }
+               }
+       }
+
+       phase_min = 10;
+
+       for (pup = 0; pup < (dram_info->num_of_std_pups); pup++) {
+               DEBUG_RL_S("DDR3 - Read Leveling - Window info - PUP: ");
+               DEBUG_RL_D((u32) pup, 1);
+               DEBUG_RL_S(", PS: ");
+               DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][PS], 1);
+               DEBUG_RL_S(", DS: ");
+               DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][DS], 2);
+               DEBUG_RL_S(", PE: ");
+               DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][PE], 1);
+               DEBUG_RL_S(", DE: ");
+               DEBUG_RL_D((u32) dram_info->rl_val[cs][pup][DE], 2);
+               DEBUG_RL_S("\n");
+       }
+
+       /* Find center of the window procedure */
+       for (pup = 0; pup < (dram_info->num_of_std_pups * (1 - ecc) + ecc);
+            pup++) {
+#ifdef RL_WINDOW_WA
+               if (!ratio_2to1) {      /* 1:1 mode */
+                       if (dram_info->rl_val[cs][idx][PS] == 4)
+                               dram_info->rl_val[cs][idx][PS] = 1;
+                       if (dram_info->rl_val[cs][idx][PE] == 4)
+                               dram_info->rl_val[cs][idx][PE] = 1;
+
+                       delay_s = dram_info->rl_val[cs][idx][PS] *
+                               MAX_DELAY_INV + dram_info->rl_val[cs][idx][DS];
+                       delay_e = dram_info->rl_val[cs][idx][PE] *
+                               MAX_DELAY_INV + dram_info->rl_val[cs][idx][DE];
+
+                       tmp = (delay_e - delay_s) / 2 + delay_s;
+                       phase = tmp / MAX_DELAY_INV;
+                       if (phase == 1) /* 1:1 mode */
+                               phase = 4;
+
+                       if (phase < phase_min)  /* for the read ready delay */
+                               phase_min = phase;
+
+                       dram_info->rl_val[cs][idx][P] = phase;
+                       dram_info->rl_val[cs][idx][D] = tmp % MAX_DELAY_INV;
+
+               } else {
+                       delay_s = dram_info->rl_val[cs][idx][PS] *
+                               MAX_DELAY + dram_info->rl_val[cs][idx][DS];
+                       delay_e = dram_info->rl_val[cs][idx][PE] *
+                               MAX_DELAY + dram_info->rl_val[cs][idx][DE];
+
+                       tmp = (delay_e - delay_s) / 2 + delay_s;
+                       phase = tmp / MAX_DELAY;
+
+                       if (phase < phase_min)  /* for the read ready delay */
+                               phase_min = phase;
+
+                       dram_info->rl_val[cs][idx][P] = phase;
+                       dram_info->rl_val[cs][idx][D] = tmp % MAX_DELAY;
+               }
+#else
+               if (!ratio_2to1) {      /* 1:1 mode */
+                       if (dram_info->rl_val[cs][idx][PS] > 1)
+                               dram_info->rl_val[cs][idx][PS] -= 2;
+                       if (dram_info->rl_val[cs][idx][PE] > 1)
+                               dram_info->rl_val[cs][idx][PE] -= 2;
+               }
+
+               delay_s = dram_info->rl_val[cs][idx][PS] * MAX_DELAY +
+                       dram_info->rl_val[cs][idx][DS];
+               delay_e = dram_info->rl_val[cs][idx][PE] * MAX_DELAY +
+                       dram_info->rl_val[cs][idx][DE];
+
+               tmp = (delay_e - delay_s) / 2 + delay_s;
+               phase = tmp / MAX_DELAY;
+               if (!ratio_2to1 && phase > 1)   /* 1:1 mode */
+                       phase += 2;
+
+               if (phase < phase_min)  /* for the read ready delay */
+                       phase_min = phase;
+
+               dram_info->rl_val[cs][idx][P] = phase;
+               dram_info->rl_val[cs][idx][D] = tmp % MAX_DELAY;
+#endif
+       }
+
+       /* Set current rdReadyDelay according to the hash table (Need to do this in every phase change) */
+       if (!ratio_2to1) {      /* 1:1 mode */
+               add = reg_read(REG_TRAINING_DEBUG_2_ADDR);
+               switch (phase_min) {
+               case 0:
+                       add = (add >> REG_TRAINING_DEBUG_2_OFFS);
+                       break;
+               case 1:
+                       add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 3));
+                       break;
+               case 4:
+                       add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 6));
+                       break;
+               case 5:
+                       add = (add >> (REG_TRAINING_DEBUG_2_OFFS + 9));
+                       break;
+               }
+       } else {                /* 2:1 mode */
+               add = reg_read(REG_TRAINING_DEBUG_3_ADDR);
+               add = (add >> phase_min * REG_TRAINING_DEBUG_3_OFFS);
+       }
+
+       add &= REG_TRAINING_DEBUG_2_MASK;
+       reg = reg_read(REG_READ_DATA_READY_DELAYS_ADDR);
+       reg &=
+           ~(REG_READ_DATA_READY_DELAYS_MASK <<
+             (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+       reg |=
+           ((rd_sample_delay + add) << (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+       reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+       dram_info->rd_rdy_dly = rd_sample_delay + add;
+
+       for (cs = 0; cs < dram_info->num_cs; cs++) {
+               for (pup = 0; pup < dram_info->num_of_total_pups; pup++) {
+                       reg = ddr3_read_pup_reg(PUP_RL_MODE + 0x1, cs, pup);
+                       dram_info->rl_val[cs][pup][DQS] = (reg & 0x3F);
+               }
+       }
+
+       return MV_OK;
+}
+#endif
diff --git a/drivers/ddr/mvebu/ddr3_sdram.c b/drivers/ddr/mvebu/ddr3_sdram.c
new file mode 100644 (file)
index 0000000..50c1bf8
--- /dev/null
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+#include "xor.h"
+#include "xor_regs.h"
+
+static void ddr3_flush_l1_line(u32 line);
+
+extern u32 pbs_pattern[2][LEN_16BIT_PBS_PATTERN];
+extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN];
+#if defined(MV88F78X60)
+extern u32 pbs_pattern_64b[2][LEN_PBS_PATTERN];
+#endif
+extern u32 pbs_dq_mapping[PUP_NUM_64BIT][DQ_NUM];
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+/* PBS locked dq (per pup) */
+u32 pbs_locked_dq[MAX_PUP_NUM][DQ_NUM] = { { 0 } };
+u32 pbs_locked_dm[MAX_PUP_NUM] = { 0 };
+u32 pbs_locked_value[MAX_PUP_NUM][DQ_NUM] = { { 0 } };
+
+int per_bit_data[MAX_PUP_NUM][DQ_NUM];
+#endif
+
+static u32 sdram_data[LEN_KILLER_PATTERN] __aligned(32) = { 0 };
+
+static struct crc_dma_desc dma_desc __aligned(32) = { 0 };
+
+#define XOR_TIMEOUT 0x8000000
+
+struct xor_channel_t {
+       struct crc_dma_desc *desc;
+       unsigned long desc_phys_addr;
+};
+
+#define XOR_CAUSE_DONE_MASK(chan)      ((0x1 | 0x2) << (chan * 16))
+
+void xor_waiton_eng(int chan)
+{
+       int timeout;
+
+       timeout = 0;
+       while (!(reg_read(XOR_CAUSE_REG(XOR_UNIT(chan))) &
+                XOR_CAUSE_DONE_MASK(XOR_CHAN(chan)))) {
+               if (timeout > XOR_TIMEOUT)
+                       goto timeout;
+
+               timeout++;
+       }
+
+       timeout = 0;
+       while (mv_xor_state_get(chan) != MV_IDLE) {
+               if (timeout > XOR_TIMEOUT)
+                       goto timeout;
+
+               timeout++;
+       }
+
+       /* Clear int */
+       reg_write(XOR_CAUSE_REG(XOR_UNIT(chan)),
+                 ~(XOR_CAUSE_DONE_MASK(XOR_CHAN(chan))));
+
+timeout:
+       return;
+}
+
+static int special_compare_pattern(u32 uj)
+{
+       if ((uj == 30) || (uj == 31) || (uj == 61) || (uj == 62) ||
+           (uj == 93) || (uj == 94) || (uj == 126) || (uj == 127))
+               return 1;
+
+       return 0;
+}
+
+/*
+ * Compare code extracted as its used by multiple functions. This
+ * reduces code-size and makes it easier to maintain it. Additionally
+ * the code is not indented that much and therefore easier to read.
+ */
+static void compare_pattern_v1(u32 uj, u32 *pup, u32 *pattern,
+                              u32 pup_groups, int debug_dqs)
+{
+       u32 val;
+       u32 uk;
+       u32 var1;
+       u32 var2;
+       __maybe_unused u32 dq;
+
+       if (((sdram_data[uj]) != (pattern[uj])) && (*pup != 0xFF)) {
+               for (uk = 0; uk < PUP_NUM_32BIT; uk++) {
+                       val = CMP_BYTE_SHIFT * uk;
+                       var1 = ((sdram_data[uj] >> val) & CMP_BYTE_MASK);
+                       var2 = ((pattern[uj] >> val) & CMP_BYTE_MASK);
+
+                       if (var1 != var2) {
+                               *pup |= (1 << (uk + (PUP_NUM_32BIT *
+                                                    (uj % pup_groups))));
+
+#ifdef MV_DEBUG_DQS
+                               if (!debug_dqs)
+                                       continue;
+
+                               for (dq = 0; dq < DQ_NUM; dq++) {
+                                       val = uk + (PUP_NUM_32BIT *
+                                                   (uj % pup_groups));
+                                       if (((var1 >> dq) & 0x1) !=
+                                           ((var2 >> dq) & 0x1))
+                                               per_bit_data[val][dq] = 1;
+                                       else
+                                               per_bit_data[val][dq] = 0;
+                               }
+#endif
+                       }
+               }
+       }
+}
+
+static void compare_pattern_v2(u32 uj, u32 *pup, u32 *pattern)
+{
+       u32 val;
+       u32 uk;
+       u32 var1;
+       u32 var2;
+
+       if (((sdram_data[uj]) != (pattern[uj])) && (*pup != 0x3)) {
+               /* Found error */
+               for (uk = 0; uk < PUP_NUM_32BIT; uk++) {
+                       val = CMP_BYTE_SHIFT * uk;
+                       var1 = (sdram_data[uj] >> val) & CMP_BYTE_MASK;
+                       var2 = (pattern[uj] >> val) & CMP_BYTE_MASK;
+                       if (var1 != var2)
+                               *pup |= (1 << (uk % PUP_NUM_16BIT));
+               }
+       }
+}
+
+/*
+ * Name:     ddr3_sdram_compare
+ * Desc:     Execute compare per PUP
+ * Args:     unlock_pup      Bit array of the unlock pups
+ *           new_locked_pup  Output  bit array of the pups with failed compare
+ *           pattern         Pattern to compare
+ *           pattern_len     Length of pattern (in bytes)
+ *           sdram_offset    offset address to the SDRAM
+ *           write           write to the SDRAM before read
+ *           mask            compare pattern with mask;
+ *           mask_pattern    Mask to compare pattern
+ *
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_sdram_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+                      u32 *new_locked_pup, u32 *pattern,
+                      u32 pattern_len, u32 sdram_offset, int write,
+                      int mask, u32 *mask_pattern,
+                      int special_compare)
+{
+       u32 uj;
+       __maybe_unused u32 pup_groups;
+       __maybe_unused u32 dq;
+
+#if !defined(MV88F67XX)
+       if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+               pup_groups = 2;
+       else
+               pup_groups = 1;
+#endif
+
+       ddr3_reset_phy_read_fifo();
+
+       /* Check if need to write to sdram before read */
+       if (write == 1)
+               ddr3_dram_sram_burst((u32)pattern, sdram_offset, pattern_len);
+
+       ddr3_dram_sram_burst(sdram_offset, (u32)sdram_data, pattern_len);
+
+       /* Compare read result to write */
+       for (uj = 0; uj < pattern_len; uj++) {
+               if (special_compare && special_compare_pattern(uj))
+                       continue;
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+               compare_pattern_v1(uj, new_locked_pup, pattern, pup_groups, 1);
+#elif defined(MV88F67XX)
+               compare_pattern_v2(uj, new_locked_pup, pattern);
+#endif
+       }
+
+       return MV_OK;
+}
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+/*
+ * Name:     ddr3_sdram_dm_compare
+ * Desc:     Execute compare per PUP
+ * Args:     unlock_pup      Bit array of the unlock pups
+ *           new_locked_pup  Output  bit array of the pups with failed compare
+ *           pattern         Pattern to compare
+ *           pattern_len     Length of pattern (in bytes)
+ *           sdram_offset    offset address to the SDRAM
+ *           write           write to the SDRAM before read
+ *           mask            compare pattern with mask;
+ *           mask_pattern    Mask to compare pattern
+ *
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_sdram_dm_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+                         u32 *new_locked_pup, u32 *pattern,
+                         u32 sdram_offset)
+{
+       u32 uj, uk, var1, var2, pup_groups;
+       u32 val;
+       u32 pup = 0;
+
+       if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+               pup_groups = 2;
+       else
+               pup_groups = 1;
+
+       ddr3_dram_sram_burst((u32)pattern, SDRAM_PBS_TX_OFFS,
+                            LEN_PBS_PATTERN);
+       ddr3_dram_sram_burst(SDRAM_PBS_TX_OFFS, (u32)sdram_data,
+                            LEN_PBS_PATTERN);
+
+       /* Validate the correctness of the results */
+       for (uj = 0; uj < LEN_PBS_PATTERN; uj++)
+               compare_pattern_v1(uj, &pup, pattern, pup_groups, 0);
+
+       /* Test the DM Signals */
+       *(u32 *)(SDRAM_PBS_TX_OFFS + 0x10) = 0x12345678;
+       *(u32 *)(SDRAM_PBS_TX_OFFS + 0x14) = 0x12345678;
+
+       sdram_data[0] = *(u32 *)(SDRAM_PBS_TX_OFFS + 0x10);
+       sdram_data[1] = *(u32 *)(SDRAM_PBS_TX_OFFS + 0x14);
+
+       for (uj = 0; uj < 2; uj++) {
+               if (((sdram_data[uj]) != (pattern[uj])) &&
+                   (*new_locked_pup != 0xFF)) {
+                       for (uk = 0; uk < PUP_NUM_32BIT; uk++) {
+                               val = CMP_BYTE_SHIFT * uk;
+                               var1 = ((sdram_data[uj] >> val) & CMP_BYTE_MASK);
+                               var2 = ((pattern[uj] >> val) & CMP_BYTE_MASK);
+                               if (var1 != var2) {
+                                       *new_locked_pup |= (1 << (uk +
+                                               (PUP_NUM_32BIT * (uj % pup_groups))));
+                                       *new_locked_pup |= pup;
+                               }
+                       }
+               }
+       }
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_sdram_pbs_compare
+ * Desc:     Execute SRAM compare per PUP and DQ.
+ * Args:     pup_locked             bit array of locked pups
+ *           is_tx                  Indicate whether Rx or Tx
+ *           pbs_pattern_idx        Index of PBS pattern
+ *           pbs_curr_val           The PBS value
+ *           pbs_lock_val           The value to set to locked PBS
+ *           skew_array             Global array to update with the compare results
+ *           ai_unlock_pup_dq_array bit array of the locked / unlocked pups per dq.
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_sdram_pbs_compare(MV_DRAM_INFO *dram_info, u32 pup_locked,
+                          int is_tx, u32 pbs_pattern_idx,
+                          u32 pbs_curr_val, u32 pbs_lock_val,
+                          u32 *skew_array, u8 *unlock_pup_dq_array,
+                          u32 ecc)
+{
+       /* bit array failed dq per pup for current compare */
+       u32 pbs_write_pup[DQ_NUM] = { 0 };
+       u32 update_pup; /* pup as HW convention */
+       u32 max_pup;    /* maximal pup index */
+       u32 pup_addr;
+       u32 ui, dq, pup;
+       int var1, var2;
+       u32 sdram_offset, pup_groups, tmp_pup;
+       u32 *pattern_ptr;
+       u32 val;
+
+       /* Choose pattern */
+       switch (dram_info->ddr_width) {
+#if defined(MV88F672X)
+       case 16:
+               pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx];
+               break;
+#endif
+       case 32:
+               pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx];
+               break;
+#if defined(MV88F78X60)
+       case 64:
+               pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx];
+               break;
+#endif
+       default:
+               return MV_FAIL;
+       }
+
+       max_pup = dram_info->num_of_std_pups;
+
+       sdram_offset = SDRAM_PBS_I_OFFS + pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS;
+
+       if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+               pup_groups = 2;
+       else
+               pup_groups = 1;
+
+       ddr3_reset_phy_read_fifo();
+
+       /* Check if need to write to sdram before read */
+       if (is_tx == 1) {
+               ddr3_dram_sram_burst((u32)pattern_ptr, sdram_offset,
+                                    LEN_PBS_PATTERN);
+       }
+
+       ddr3_dram_sram_read(sdram_offset, (u32)sdram_data, LEN_PBS_PATTERN);
+
+       /* Compare read result to write */
+       for (ui = 0; ui < LEN_PBS_PATTERN; ui++) {
+               if ((sdram_data[ui]) != (pattern_ptr[ui])) {
+                       /* found error */
+                       /* error in low pup group */
+                       for (pup = 0; pup < PUP_NUM_32BIT; pup++) {
+                               val = CMP_BYTE_SHIFT * pup;
+                               var1 = ((sdram_data[ui] >> val) &
+                                       CMP_BYTE_MASK);
+                               var2 = ((pattern_ptr[ui] >> val) &
+                                       CMP_BYTE_MASK);
+
+                               if (var1 != var2) {
+                                       if (dram_info->ddr_width > 16) {
+                                               tmp_pup = (pup + PUP_NUM_32BIT *
+                                                          (ui % pup_groups));
+                                       } else {
+                                               tmp_pup = (pup % PUP_NUM_16BIT);
+                                       }
+
+                                       update_pup = (1 << tmp_pup);
+                                       if (ecc && (update_pup != 0x1))
+                                               continue;
+
+                                       /*
+                                        * Pup is failed - Go over all DQs and
+                                        * look for failures
+                                        */
+                                       for (dq = 0; dq < DQ_NUM; dq++) {
+                                               val = tmp_pup * (1 - ecc) +
+                                                       ecc * ECC_PUP;
+                                               if (((var1 >> dq) & 0x1) !=
+                                                   ((var2 >> dq) & 0x1)) {
+                                                       if (pbs_locked_dq[val][dq] == 1 &&
+                                                           pbs_locked_value[val][dq] != pbs_curr_val)
+                                                               continue;
+
+                                                       /*
+                                                        * Activate write to
+                                                        * update PBS to
+                                                        * pbs_lock_val
+                                                        */
+                                                       pbs_write_pup[dq] |=
+                                                               update_pup;
+
+                                                       /*
+                                                        * Update the
+                                                        * unlock_pup_dq_array
+                                                        */
+                                                       unlock_pup_dq_array[dq] &=
+                                                               ~update_pup;
+
+                                                       /*
+                                                        * Lock PBS value for
+                                                        * failed bits in
+                                                        * compare operation
+                                                        */
+                                                       skew_array[tmp_pup * DQ_NUM + dq] =
+                                                               pbs_curr_val;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       pup_addr = (is_tx == 1) ? PUP_PBS_TX : PUP_PBS_RX;
+
+       /* Set last failed bits PBS to min / max pbs value */
+       for (dq = 0; dq < DQ_NUM; dq++) {
+               for (pup = 0; pup < max_pup; pup++) {
+                       if (pbs_write_pup[dq] & (1 << pup)) {
+                               val = pup * (1 - ecc) + ecc * ECC_PUP;
+                               if (pbs_locked_dq[val][dq] == 1 &&
+                                   pbs_locked_value[val][dq] != pbs_curr_val)
+                                       continue;
+
+                               /* Mark the dq as locked */
+                               pbs_locked_dq[val][dq] = 1;
+                               pbs_locked_value[val][dq] = pbs_curr_val;
+                               ddr3_write_pup_reg(pup_addr +
+                                                  pbs_dq_mapping[val][dq],
+                                                  CS0, val, 0, pbs_lock_val);
+                       }
+               }
+       }
+
+       return MV_OK;
+}
+#endif
+
+/*
+ * Name:     ddr3_sdram_direct_compare
+ * Desc:     Execute compare  per PUP without DMA (no burst mode)
+ * Args:     unlock_pup       Bit array of the unlock pups
+ *           new_locked_pup   Output  bit array of the pups with failed compare
+ *           pattern          Pattern to compare
+ *           pattern_len      Length of pattern (in bytes)
+ *           sdram_offset     offset address to the SDRAM
+ *           write            write to the SDRAM before read
+ *           mask             compare pattern with mask;
+ *           auiMaskPatter    Mask to compare pattern
+ *
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_sdram_direct_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+                             u32 *new_locked_pup, u32 *pattern,
+                             u32 pattern_len, u32 sdram_offset,
+                             int write, int mask, u32 *mask_pattern)
+{
+       u32 uj, uk, pup_groups;
+       u32 *sdram_addr;        /* used to read from SDRAM */
+
+       sdram_addr = (u32 *)sdram_offset;
+
+       if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+               pup_groups = 2;
+       else
+               pup_groups = 1;
+
+       /* Check if need to write before read */
+       if (write == 1) {
+               for (uk = 0; uk < pattern_len; uk++) {
+                       *sdram_addr = pattern[uk];
+                       sdram_addr++;
+               }
+       }
+
+       sdram_addr = (u32 *)sdram_offset;
+
+       for (uk = 0; uk < pattern_len; uk++) {
+               sdram_data[uk] = *sdram_addr;
+               sdram_addr++;
+       }
+
+       /* Compare read result to write */
+       for (uj = 0; uj < pattern_len; uj++) {
+               if (dram_info->ddr_width > 16) {
+                       compare_pattern_v1(uj, new_locked_pup, pattern,
+                                          pup_groups, 0);
+               } else {
+                       compare_pattern_v2(uj, new_locked_pup, pattern);
+               }
+       }
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_dram_sram_burst
+ * Desc:     Read from the SDRAM in burst of 64 bytes
+ * Args:     src
+ *           dst
+ * Notes:    Using the XOR mechanism
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+int ddr3_dram_sram_burst(u32 src, u32 dst, u32 len)
+{
+       u32 chan, byte_count, cs_num, byte;
+       struct xor_channel_t channel;
+
+       chan = 0;
+       byte_count = len * 4;
+
+       /* Wait for previous transfer completion */
+       while (mv_xor_state_get(chan) != MV_IDLE)
+               ;
+
+       /* Build the channel descriptor */
+       channel.desc = &dma_desc;
+
+       /* Enable Address Override and set correct src and dst */
+       if (src < SRAM_BASE) {
+               /* src is DRAM CS, dst is SRAM */
+               cs_num = (src / (1 + SDRAM_CS_SIZE));
+               reg_write(XOR_ADDR_OVRD_REG(0, 0),
+                         ((cs_num << 1) | (1 << 0)));
+               channel.desc->src_addr0 = (src % (1 + SDRAM_CS_SIZE));
+               channel.desc->dst_addr = dst;
+       } else {
+               /* src is SRAM, dst is DRAM CS */
+               cs_num = (dst / (1 + SDRAM_CS_SIZE));
+               reg_write(XOR_ADDR_OVRD_REG(0, 0),
+                         ((cs_num << 25) | (1 << 24)));
+               channel.desc->src_addr0 = (src);
+               channel.desc->dst_addr = (dst % (1 + SDRAM_CS_SIZE));
+               channel.desc->src_addr0 = src;
+               channel.desc->dst_addr = (dst % (1 + SDRAM_CS_SIZE));
+       }
+
+       channel.desc->src_addr1 = 0;
+       channel.desc->byte_cnt = byte_count;
+       channel.desc->next_desc_ptr = 0;
+       channel.desc->status = 1 << 31;
+       channel.desc->desc_cmd = 0x0;
+       channel.desc_phys_addr = (unsigned long)&dma_desc;
+
+       ddr3_flush_l1_line((u32)&dma_desc);
+
+       /* Issue the transfer */
+       if (mv_xor_transfer(chan, MV_DMA, channel.desc_phys_addr) != MV_OK)
+               return MV_FAIL;
+
+       /* Wait for completion */
+       xor_waiton_eng(chan);
+
+       if (dst > SRAM_BASE) {
+               for (byte = 0; byte < byte_count; byte += 0x20)
+                       cache_inv(dst + byte);
+       }
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_flush_l1_line
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:  MV_OK if success, other error code if fail.
+ */
+static void ddr3_flush_l1_line(u32 line)
+{
+       u32 reg;
+
+#if defined(MV88F672X)
+       reg = 1;
+#else
+       reg = reg_read(REG_SAMPLE_RESET_LOW_ADDR) &
+               (1 << REG_SAMPLE_RESET_CPU_ARCH_OFFS);
+#ifdef MV88F67XX
+       reg = ~reg & (1 << REG_SAMPLE_RESET_CPU_ARCH_OFFS);
+#endif
+#endif
+
+       if (reg) {
+               /* V7 Arch mode */
+               flush_l1_v7(line);
+               flush_l1_v7(line + CACHE_LINE_SIZE);
+       } else {
+               /* V6 Arch mode */
+               flush_l1_v6(line);
+               flush_l1_v6(line + CACHE_LINE_SIZE);
+       }
+}
+
+int ddr3_dram_sram_read(u32 src, u32 dst, u32 len)
+{
+       u32 ui;
+       u32 *dst_ptr, *src_ptr;
+
+       dst_ptr = (u32 *)dst;
+       src_ptr = (u32 *)src;
+
+       for (ui = 0; ui < len; ui++) {
+               *dst_ptr = *src_ptr;
+               dst_ptr++;
+               src_ptr++;
+       }
+
+       return MV_OK;
+}
+
+int ddr3_sdram_dqs_compare(MV_DRAM_INFO *dram_info, u32 unlock_pup,
+                          u32 *new_locked_pup, u32 *pattern,
+                          u32 pattern_len, u32 sdram_offset, int write,
+                          int mask, u32 *mask_pattern,
+                          int special_compare)
+{
+       u32 uj, pup_groups;
+
+       if (dram_info->num_of_std_pups == PUP_NUM_64BIT)
+               pup_groups = 2;
+       else
+               pup_groups = 1;
+
+       ddr3_reset_phy_read_fifo();
+
+       /* Check if need to write to sdram before read */
+       if (write == 1)
+               ddr3_dram_sram_burst((u32)pattern, sdram_offset, pattern_len);
+
+       ddr3_dram_sram_burst(sdram_offset, (u32)sdram_data, pattern_len);
+
+       /* Compare read result to write */
+       for (uj = 0; uj < pattern_len; uj++) {
+               if (special_compare && special_compare_pattern(uj))
+                       continue;
+
+               if (dram_info->ddr_width > 16) {
+                       compare_pattern_v1(uj, new_locked_pup, pattern,
+                                          pup_groups, 1);
+               } else {
+                       compare_pattern_v2(uj, new_locked_pup, pattern);
+               }
+       }
+
+       return MV_OK;
+}
+
+void ddr3_reset_phy_read_fifo(void)
+{
+       u32 reg;
+
+       /* reset read FIFO */
+       reg = reg_read(REG_DRAM_TRAINING_ADDR);
+       /* Start Auto Read Leveling procedure */
+       reg |= (1 << REG_DRAM_TRAINING_RL_OFFS);
+
+       /* 0x15B0 - Training Register */
+       reg_write(REG_DRAM_TRAINING_ADDR, reg);
+
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg |= ((1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS) +
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS));
+
+       /* [0] = 1 - Enable SW override, [4] = 1 - FIFO reset  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       do {
+               reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+                       (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS);
+       } while (reg);  /* Wait for '0' */
+
+       reg = reg_read(REG_DRAM_TRAINING_ADDR);
+
+       /* Clear Auto Read Leveling procedure */
+       reg &= ~(1 << REG_DRAM_TRAINING_RL_OFFS);
+
+       /* 0x15B0 - Training Register */
+       reg_write(REG_DRAM_TRAINING_ADDR, reg);
+}
diff --git a/drivers/ddr/mvebu/ddr3_spd.c b/drivers/ddr/mvebu/ddr3_spd.c
new file mode 100644 (file)
index 0000000..f4f94c5
--- /dev/null
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_init.h"
+
+#if defined(MV88F78X60)
+#include "ddr3_axp_config.h"
+#elif defined(MV88F67XX)
+#include "ddr3_a370_config.h"
+#endif
+
+#if defined(MV88F672X)
+#include "ddr3_a375_config.h"
+#endif
+
+#ifdef DUNIT_SPD
+
+/* DIMM SPD offsets */
+#define SPD_DEV_TYPE_BYTE              2
+
+#define SPD_MODULE_TYPE_BYTE           3
+#define SPD_MODULE_MASK                        0xf
+#define SPD_MODULE_TYPE_RDIMM          1
+#define SPD_MODULE_TYPE_UDIMM          2
+
+#define SPD_DEV_DENSITY_BYTE           4
+#define SPD_DEV_DENSITY_MASK           0xf
+
+#define SPD_ROW_NUM_BYTE               5
+#define SPD_ROW_NUM_MIN                        12
+#define SPD_ROW_NUM_OFF                        3
+#define SPD_ROW_NUM_MASK               (7 << SPD_ROW_NUM_OFF)
+
+#define SPD_COL_NUM_BYTE               5
+#define SPD_COL_NUM_MIN                        9
+#define SPD_COL_NUM_OFF                        0
+#define SPD_COL_NUM_MASK               (7 << SPD_COL_NUM_OFF)
+
+#define SPD_MODULE_ORG_BYTE            7
+#define SPD_MODULE_SDRAM_DEV_WIDTH_OFF         0
+#define SPD_MODULE_SDRAM_DEV_WIDTH_MASK        (7 << SPD_MODULE_SDRAM_DEV_WIDTH_OFF)
+#define SPD_MODULE_BANK_NUM_MIN                1
+#define SPD_MODULE_BANK_NUM_OFF                3
+#define SPD_MODULE_BANK_NUM_MASK       (7 << SPD_MODULE_BANK_NUM_OFF)
+
+#define SPD_BUS_WIDTH_BYTE             8
+#define SPD_BUS_WIDTH_OFF              0
+#define SPD_BUS_WIDTH_MASK             (7 << SPD_BUS_WIDTH_OFF)
+#define SPD_BUS_ECC_OFF                        3
+#define SPD_BUS_ECC_MASK               (3 << SPD_BUS_ECC_OFF)
+
+#define SPD_MTB_DIVIDEND_BYTE          10
+#define SPD_MTB_DIVISOR_BYTE           11
+#define SPD_TCK_BYTE                   12
+#define SPD_SUP_CAS_LAT_LSB_BYTE       14
+#define SPD_SUP_CAS_LAT_MSB_BYTE       15
+#define SPD_TAA_BYTE                   16
+#define SPD_TWR_BYTE                   17
+#define SPD_TRCD_BYTE                  18
+#define SPD_TRRD_BYTE                  19
+#define SPD_TRP_BYTE                   20
+
+#define SPD_TRAS_MSB_BYTE              21
+#define SPD_TRAS_MSB_MASK              0xf
+
+#define SPD_TRC_MSB_BYTE               21
+#define SPD_TRC_MSB_MASK               0xf0
+
+#define SPD_TRAS_LSB_BYTE              22
+#define SPD_TRC_LSB_BYTE               23
+#define SPD_TRFC_LSB_BYTE              24
+#define SPD_TRFC_MSB_BYTE              25
+#define SPD_TWTR_BYTE                  26
+#define SPD_TRTP_BYTE                  27
+
+#define SPD_TFAW_MSB_BYTE              28
+#define SPD_TFAW_MSB_MASK              0xf
+
+#define SPD_TFAW_LSB_BYTE              29
+#define SPD_OPT_FEATURES_BYTE          30
+#define SPD_THERMAL_REFRESH_OPT_BYTE   31
+
+#define SPD_ADDR_MAP_BYTE              63
+#define SPD_ADDR_MAP_MIRROR_OFFS       0
+
+#define SPD_RDIMM_RC_BYTE              69
+#define SPD_RDIMM_RC_NIBBLE_MASK       0xF
+#define SPD_RDIMM_RC_NUM               16
+
+/* Dimm Memory Type values */
+#define SPD_MEM_TYPE_SDRAM             0x4
+#define SPD_MEM_TYPE_DDR1              0x7
+#define SPD_MEM_TYPE_DDR2              0x8
+#define SPD_MEM_TYPE_DDR3              0xB
+
+#define DIMM_MODULE_MANU_OFFS          64
+#define DIMM_MODULE_MANU_SIZE          8
+#define DIMM_MODULE_VEN_OFFS           73
+#define DIMM_MODULE_VEN_SIZE           25
+#define DIMM_MODULE_ID_OFFS            99
+#define DIMM_MODULE_ID_SIZE            18
+
+/* enumeration for voltage levels. */
+enum dimm_volt_if {
+       TTL_5V_TOLERANT,
+       LVTTL,
+       HSTL_1_5V,
+       SSTL_3_3V,
+       SSTL_2_5V,
+       VOLTAGE_UNKNOWN,
+};
+
+/* enumaration for SDRAM CAS Latencies. */
+enum dimm_sdram_cas {
+       SD_CL_1 = 1,
+       SD_CL_2,
+       SD_CL_3,
+       SD_CL_4,
+       SD_CL_5,
+       SD_CL_6,
+       SD_CL_7,
+       SD_FAULT
+};
+
+/* enumeration for memory types */
+enum memory_type {
+       MEM_TYPE_SDRAM,
+       MEM_TYPE_DDR1,
+       MEM_TYPE_DDR2,
+       MEM_TYPE_DDR3
+};
+
+/* DIMM information structure */
+typedef struct dimm_info {
+       /* DIMM dimensions */
+       u32 num_of_module_ranks;
+       u32 data_width;
+       u32 rank_capacity;
+       u32 num_of_devices;
+
+       u32 sdram_width;
+       u32 num_of_banks_on_each_device;
+       u32 sdram_capacity;
+
+       u32 num_of_row_addr;
+       u32 num_of_col_addr;
+
+       u32 addr_mirroring;
+
+       u32 err_check_type;                     /* ECC , PARITY.. */
+       u32 type_info;                          /* DDR2 only */
+
+       /* DIMM timing parameters */
+       u32 supported_cas_latencies;
+       u32 refresh_interval;
+       u32 min_cycle_time;
+       u32 min_row_precharge_time;
+       u32 min_row_active_to_row_active;
+       u32 min_ras_to_cas_delay;
+       u32 min_write_recovery_time;            /* DDR3/2 only */
+       u32 min_write_to_read_cmd_delay;        /* DDR3/2 only */
+       u32 min_read_to_prech_cmd_delay;        /* DDR3/2 only */
+       u32 min_active_to_precharge;
+       u32 min_refresh_recovery;               /* DDR3/2 only */
+       u32 min_cas_lat_time;
+       u32 min_four_active_win_delay;
+       u8 dimm_rc[SPD_RDIMM_RC_NUM];
+
+       /* DIMM vendor ID */
+       u32 vendor;
+} MV_DIMM_INFO;
+
+static int ddr3_spd_sum_init(MV_DIMM_INFO *info, MV_DIMM_INFO *sum_info,
+                            u32 dimm);
+static u32 ddr3_get_max_val(u32 spd_val, u32 dimm_num, u32 static_val);
+static u32 ddr3_get_min_val(u32 spd_val, u32 dimm_num, u32 static_val);
+static int ddr3_spd_init(MV_DIMM_INFO *info, u32 dimm_addr, u32 dimm_width);
+static u32 ddr3_div(u32 val, u32 divider, u32 sub);
+
+extern u8 spd_data[SPD_SIZE];
+extern u32 odt_config[ODT_OPT];
+extern u16 odt_static[ODT_OPT][MAX_CS];
+extern u16 odt_dynamic[ODT_OPT][MAX_CS];
+
+#if !(defined(DB_88F6710) || defined(DB_88F6710_PCAC) || defined(RD_88F6710))
+/*
+ * Name:     ddr3_get_dimm_num - Find number of dimms and their addresses
+ * Desc:
+ * Args:     dimm_addr - array of dimm addresses
+ * Notes:
+ * Returns:  None.
+ */
+static u32 ddr3_get_dimm_num(u32 *dimm_addr)
+{
+       u32 dimm_cur_addr;
+       u8 data[3];
+       u32 dimm_num = 0;
+       int ret;
+
+       /* Read the dimm eeprom */
+       for (dimm_cur_addr = MAX_DIMM_ADDR; dimm_cur_addr > MIN_DIMM_ADDR;
+            dimm_cur_addr--) {
+               data[SPD_DEV_TYPE_BYTE] = 0;
+
+               /* Far-End DIMM must be connected */
+               if ((dimm_num == 0) && (dimm_cur_addr < FAR_END_DIMM_ADDR))
+                       return 0;
+
+               ret = i2c_read(dimm_cur_addr, 0, 1, (uchar *)data, 3);
+               if (!ret) {
+                       if (data[SPD_DEV_TYPE_BYTE] == SPD_MEM_TYPE_DDR3) {
+                               dimm_addr[dimm_num] = dimm_cur_addr;
+                               dimm_num++;
+                       }
+               }
+       }
+
+       return dimm_num;
+}
+#endif
+
+/*
+ * Name:     dimmSpdInit - Get the SPD parameters.
+ * Desc:     Read the DIMM SPD parameters into given struct parameter.
+ * Args:     dimmNum - DIMM number. See MV_BOARD_DIMM_NUM enumerator.
+ *           info - DIMM information structure.
+ * Notes:
+ * Returns:  MV_OK if function could read DIMM parameters, 0 otherwise.
+ */
+int ddr3_spd_init(MV_DIMM_INFO *info, u32 dimm_addr, u32 dimm_width)
+{
+       u32 tmp;
+       u32 time_base;
+       int ret;
+       __maybe_unused u32 rc;
+       __maybe_unused u8 vendor_high, vendor_low;
+
+       if (dimm_addr != 0) {
+               memset(spd_data, 0, SPD_SIZE * sizeof(u8));
+
+               ret = i2c_read(dimm_addr, 0, 1, (uchar *)spd_data, SPD_SIZE);
+               if (ret)
+                       return MV_DDR3_TRAINING_ERR_TWSI_FAIL;
+       }
+
+       /* Check if DDR3 */
+       if (spd_data[SPD_DEV_TYPE_BYTE] != SPD_MEM_TYPE_DDR3)
+               return MV_DDR3_TRAINING_ERR_TWSI_BAD_TYPE;
+
+       /* Error Check Type */
+       /* No byte for error check in DDR3 SPD, use DDR2 convention */
+       info->err_check_type = 0;
+
+       /* Check if ECC */
+       if ((spd_data[SPD_BUS_WIDTH_BYTE] & 0x18) >> 3)
+               info->err_check_type = 1;
+
+       DEBUG_INIT_FULL_C("DRAM err_check_type ", info->err_check_type, 1);
+       switch (spd_data[SPD_MODULE_TYPE_BYTE]) {
+       case 1:
+               /* support RDIMM */
+               info->type_info = SPD_MODULE_TYPE_RDIMM;
+               break;
+       case 2:
+               /* support UDIMM */
+               info->type_info = SPD_MODULE_TYPE_UDIMM;
+               break;
+       case 11:                /* LRDIMM current not supported */
+       default:
+               info->type_info = (spd_data[SPD_MODULE_TYPE_BYTE]);
+               break;
+       }
+
+       /* Size Calculations: */
+
+       /* Number Of Row Addresses - 12/13/14/15/16 */
+       info->num_of_row_addr =
+               (spd_data[SPD_ROW_NUM_BYTE] & SPD_ROW_NUM_MASK) >>
+               SPD_ROW_NUM_OFF;
+       info->num_of_row_addr += SPD_ROW_NUM_MIN;
+       DEBUG_INIT_FULL_C("DRAM num_of_row_addr ", info->num_of_row_addr, 2);
+
+       /* Number Of Column Addresses - 9/10/11/12 */
+       info->num_of_col_addr =
+               (spd_data[SPD_COL_NUM_BYTE] & SPD_COL_NUM_MASK) >>
+               SPD_COL_NUM_OFF;
+       info->num_of_col_addr += SPD_COL_NUM_MIN;
+       DEBUG_INIT_FULL_C("DRAM num_of_col_addr ", info->num_of_col_addr, 1);
+
+       /* Number Of Ranks = number of CS on Dimm - 1/2/3/4 Ranks */
+       info->num_of_module_ranks =
+               (spd_data[SPD_MODULE_ORG_BYTE] & SPD_MODULE_BANK_NUM_MASK) >>
+               SPD_MODULE_BANK_NUM_OFF;
+       info->num_of_module_ranks += SPD_MODULE_BANK_NUM_MIN;
+       DEBUG_INIT_FULL_C("DRAM numOfModuleBanks ", info->num_of_module_ranks,
+                         1);
+
+       /* Data Width - 8/16/32/64 bits */
+       info->data_width =
+               1 << (3 + (spd_data[SPD_BUS_WIDTH_BYTE] & SPD_BUS_WIDTH_MASK));
+       DEBUG_INIT_FULL_C("DRAM data_width ", info->data_width, 1);
+
+       /* Number Of Banks On Each Device - 8/16/32/64 banks */
+       info->num_of_banks_on_each_device =
+               1 << (3 + ((spd_data[SPD_DEV_DENSITY_BYTE] >> 4) & 0x7));
+       DEBUG_INIT_FULL_C("DRAM num_of_banks_on_each_device ",
+                         info->num_of_banks_on_each_device, 1);
+
+       /* Total SDRAM capacity - 256Mb/512Mb/1Gb/2Gb/4Gb/8Gb/16Gb - MegaBits */
+       info->sdram_capacity =
+               spd_data[SPD_DEV_DENSITY_BYTE] & SPD_DEV_DENSITY_MASK;
+
+       /* Sdram Width - 4/8/16/32 bits */
+       info->sdram_width = 1 << (2 + (spd_data[SPD_MODULE_ORG_BYTE] &
+                                      SPD_MODULE_SDRAM_DEV_WIDTH_MASK));
+       DEBUG_INIT_FULL_C("DRAM sdram_width ", info->sdram_width, 1);
+
+       /* CS (Rank) Capacity - MB */
+       /*
+        * DDR3 device uiDensity val are: (device capacity/8) *
+        * (Module_width/Device_width)
+        */
+       /* Jedec SPD DDR3 - page 7, Save spd_data in Mb  - 2048=2GB */
+       if (dimm_width == 32) {
+               info->rank_capacity =
+                       ((1 << info->sdram_capacity) * 256 *
+                        (info->data_width / info->sdram_width)) << 16;
+               /* CS size = CS size / 2  */
+       } else {
+               info->rank_capacity =
+                       ((1 << info->sdram_capacity) * 256 *
+                        (info->data_width / info->sdram_width) * 0x2) << 16;
+               /* 0x2 =>  0x100000-1Mbit / 8-bit->byte / 0x10000  */
+       }
+       DEBUG_INIT_FULL_C("DRAM rank_capacity[31] ", info->rank_capacity, 1);
+
+       /* Number of devices includeing Error correction */
+       info->num_of_devices =
+               ((info->data_width / info->sdram_width) *
+                info->num_of_module_ranks) + info->err_check_type;
+       DEBUG_INIT_FULL_C("DRAM num_of_devices  ", info->num_of_devices, 1);
+
+       /* Address Mapping from Edge connector to DRAM - mirroring option */
+       info->addr_mirroring =
+               spd_data[SPD_ADDR_MAP_BYTE] & (1 << SPD_ADDR_MAP_MIRROR_OFFS);
+
+       /* Timings - All in ps */
+
+       time_base = (1000 * spd_data[SPD_MTB_DIVIDEND_BYTE]) /
+               spd_data[SPD_MTB_DIVISOR_BYTE];
+
+       /* Minimum Cycle Time At Max CasLatancy */
+       info->min_cycle_time = spd_data[SPD_TCK_BYTE] * time_base;
+       DEBUG_INIT_FULL_C("DRAM tCKmin ", info->min_cycle_time, 1);
+
+       /* Refresh Interval */
+       /* No byte for refresh interval in DDR3 SPD, use DDR2 convention */
+       /*
+        * JEDEC param are 0 <= Tcase <= 85: 7.8uSec, 85 <= Tcase
+        * <= 95: 3.9uSec
+        */
+       info->refresh_interval = 7800000;       /* Set to 7.8uSec */
+       DEBUG_INIT_FULL_C("DRAM refresh_interval ", info->refresh_interval, 1);
+
+       /* Suported Cas Latencies -  DDR 3: */
+
+       /*
+        *         bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 *
+        *******-******-******-******-******-******-******-*******-*******
+        CAS =      11  |  10  |  9   |  8   |  7   |  6   |  5   |  4   *
+        *********************************************************-*******
+        *******-******-******-******-******-******-******-*******-*******
+        *        bit15 |bit14 |bit13 |bit12 |bit11 |bit10 | bit9 | bit8 *
+        *******-******-******-******-******-******-******-*******-*******
+        CAS =     TBD  |  18  |  17  |  16  |  15  |  14  |  13  |  12  *
+       */
+
+       /* DDR3 include 2 byte of CAS support */
+       info->supported_cas_latencies =
+               (spd_data[SPD_SUP_CAS_LAT_MSB_BYTE] << 8) |
+               spd_data[SPD_SUP_CAS_LAT_LSB_BYTE];
+       DEBUG_INIT_FULL_C("DRAM supported_cas_latencies ",
+                         info->supported_cas_latencies, 1);
+
+       /* Minimum Cycle Time At Max CasLatancy */
+       info->min_cas_lat_time = (spd_data[SPD_TAA_BYTE] * time_base);
+       /*
+        * This field divided by the cycleTime will give us the CAS latency
+        * to config
+        */
+
+       /*
+        * For DDR3 and DDR2 includes Write Recovery Time field.
+        * Other SDRAM ignore
+        */
+       info->min_write_recovery_time = spd_data[SPD_TWR_BYTE] * time_base;
+       DEBUG_INIT_FULL_C("DRAM min_write_recovery_time ",
+                         info->min_write_recovery_time, 1);
+
+       /* Mininmum Ras to Cas Delay */
+       info->min_ras_to_cas_delay = spd_data[SPD_TRCD_BYTE] * time_base;
+       DEBUG_INIT_FULL_C("DRAM min_ras_to_cas_delay ",
+                         info->min_ras_to_cas_delay, 1);
+
+       /* Minimum Row Active to Row Active Time */
+       info->min_row_active_to_row_active =
+           spd_data[SPD_TRRD_BYTE] * time_base;
+       DEBUG_INIT_FULL_C("DRAM min_row_active_to_row_active ",
+                         info->min_row_active_to_row_active, 1);
+
+       /* Minimum Row Precharge Delay Time */
+       info->min_row_precharge_time = spd_data[SPD_TRP_BYTE] * time_base;
+       DEBUG_INIT_FULL_C("DRAM min_row_precharge_time ",
+                         info->min_row_precharge_time, 1);
+
+       /* Minimum Active to Precharge Delay Time - tRAS   ps */
+       info->min_active_to_precharge =
+               (spd_data[SPD_TRAS_MSB_BYTE] & SPD_TRAS_MSB_MASK) << 8;
+       info->min_active_to_precharge |= spd_data[SPD_TRAS_LSB_BYTE];
+       info->min_active_to_precharge *= time_base;
+       DEBUG_INIT_FULL_C("DRAM min_active_to_precharge ",
+                         info->min_active_to_precharge, 1);
+
+       /* Minimum Refresh Recovery Delay Time - tRFC  ps */
+       info->min_refresh_recovery = spd_data[SPD_TRFC_MSB_BYTE] << 8;
+       info->min_refresh_recovery |= spd_data[SPD_TRFC_LSB_BYTE];
+       info->min_refresh_recovery *= time_base;
+       DEBUG_INIT_FULL_C("DRAM min_refresh_recovery ",
+                         info->min_refresh_recovery, 1);
+
+       /*
+        * For DDR3 and DDR2 includes Internal Write To Read Command Delay
+        * field.
+        */
+       info->min_write_to_read_cmd_delay = spd_data[SPD_TWTR_BYTE] * time_base;
+       DEBUG_INIT_FULL_C("DRAM min_write_to_read_cmd_delay ",
+                         info->min_write_to_read_cmd_delay, 1);
+
+       /*
+        * For DDR3 and DDR2 includes Internal Read To Precharge Command Delay
+        * field.
+        */
+       info->min_read_to_prech_cmd_delay = spd_data[SPD_TRTP_BYTE] * time_base;
+       DEBUG_INIT_FULL_C("DRAM min_read_to_prech_cmd_delay ",
+                         info->min_read_to_prech_cmd_delay, 1);
+
+       /*
+        * For DDR3 includes Minimum Activate to Activate/Refresh Command
+        * field
+        */
+       tmp = ((spd_data[SPD_TFAW_MSB_BYTE] & SPD_TFAW_MSB_MASK) << 8) |
+               spd_data[SPD_TFAW_LSB_BYTE];
+       info->min_four_active_win_delay = tmp * time_base;
+       DEBUG_INIT_FULL_C("DRAM min_four_active_win_delay ",
+                         info->min_four_active_win_delay, 1);
+
+#if defined(MV88F78X60) || defined(MV88F672X)
+       /* Registered DIMM support */
+       if (info->type_info == SPD_MODULE_TYPE_RDIMM) {
+               for (rc = 2; rc < 6; rc += 2) {
+                       tmp = spd_data[SPD_RDIMM_RC_BYTE + rc / 2];
+                       info->dimm_rc[rc] =
+                               spd_data[SPD_RDIMM_RC_BYTE + rc / 2] &
+                               SPD_RDIMM_RC_NIBBLE_MASK;
+                       info->dimm_rc[rc + 1] =
+                               (spd_data[SPD_RDIMM_RC_BYTE + rc / 2] >> 4) &
+                               SPD_RDIMM_RC_NIBBLE_MASK;
+               }
+
+               vendor_low = spd_data[66];
+               vendor_high = spd_data[65];
+               info->vendor = (vendor_high << 8) + vendor_low;
+               DEBUG_INIT_C("DDR3 Training Sequence - Registered DIMM vendor ID 0x",
+                            info->vendor, 4);
+
+               info->dimm_rc[0] = RDIMM_RC0;
+               info->dimm_rc[1] = RDIMM_RC1;
+               info->dimm_rc[2] = RDIMM_RC2;
+               info->dimm_rc[8] = RDIMM_RC8;
+               info->dimm_rc[9] = RDIMM_RC9;
+               info->dimm_rc[10] = RDIMM_RC10;
+               info->dimm_rc[11] = RDIMM_RC11;
+       }
+#endif
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_spd_sum_init - Get the SPD parameters.
+ * Desc:     Read the DIMM SPD parameters into given struct parameter.
+ * Args:     dimmNum - DIMM number. See MV_BOARD_DIMM_NUM enumerator.
+ *           info - DIMM information structure.
+ * Notes:
+ * Returns:  MV_OK if function could read DIMM parameters, 0 otherwise.
+ */
+int ddr3_spd_sum_init(MV_DIMM_INFO *info, MV_DIMM_INFO *sum_info, u32 dimm)
+{
+       if (dimm == 0) {
+               memcpy(sum_info, info, sizeof(MV_DIMM_INFO));
+               return MV_OK;
+       }
+       if (sum_info->type_info != info->type_info) {
+               DEBUG_INIT_S("DDR3 Dimm Compare - DIMM type does not match - FAIL\n");
+               return MV_DDR3_TRAINING_ERR_DIMM_TYPE_NO_MATCH;
+       }
+       if (sum_info->err_check_type > info->err_check_type) {
+               sum_info->err_check_type = info->err_check_type;
+               DEBUG_INIT_S("DDR3 Dimm Compare - ECC does not match. ECC is disabled\n");
+       }
+       if (sum_info->data_width != info->data_width) {
+               DEBUG_INIT_S("DDR3 Dimm Compare - DRAM bus width does not match - FAIL\n");
+               return MV_DDR3_TRAINING_ERR_BUS_WIDTH_NOT_MATCH;
+       }
+       if (sum_info->min_cycle_time < info->min_cycle_time)
+               sum_info->min_cycle_time = info->min_cycle_time;
+       if (sum_info->refresh_interval < info->refresh_interval)
+               sum_info->refresh_interval = info->refresh_interval;
+       sum_info->supported_cas_latencies &= info->supported_cas_latencies;
+       if (sum_info->min_cas_lat_time < info->min_cas_lat_time)
+               sum_info->min_cas_lat_time = info->min_cas_lat_time;
+       if (sum_info->min_write_recovery_time < info->min_write_recovery_time)
+               sum_info->min_write_recovery_time =
+                   info->min_write_recovery_time;
+       if (sum_info->min_ras_to_cas_delay < info->min_ras_to_cas_delay)
+               sum_info->min_ras_to_cas_delay = info->min_ras_to_cas_delay;
+       if (sum_info->min_row_active_to_row_active <
+           info->min_row_active_to_row_active)
+               sum_info->min_row_active_to_row_active =
+                   info->min_row_active_to_row_active;
+       if (sum_info->min_row_precharge_time < info->min_row_precharge_time)
+               sum_info->min_row_precharge_time = info->min_row_precharge_time;
+       if (sum_info->min_active_to_precharge < info->min_active_to_precharge)
+               sum_info->min_active_to_precharge =
+                   info->min_active_to_precharge;
+       if (sum_info->min_refresh_recovery < info->min_refresh_recovery)
+               sum_info->min_refresh_recovery = info->min_refresh_recovery;
+       if (sum_info->min_write_to_read_cmd_delay <
+           info->min_write_to_read_cmd_delay)
+               sum_info->min_write_to_read_cmd_delay =
+                   info->min_write_to_read_cmd_delay;
+       if (sum_info->min_read_to_prech_cmd_delay <
+           info->min_read_to_prech_cmd_delay)
+               sum_info->min_read_to_prech_cmd_delay =
+                   info->min_read_to_prech_cmd_delay;
+       if (sum_info->min_four_active_win_delay <
+           info->min_four_active_win_delay)
+               sum_info->min_four_active_win_delay =
+                   info->min_four_active_win_delay;
+       if (sum_info->min_write_to_read_cmd_delay <
+           info->min_write_to_read_cmd_delay)
+               sum_info->min_write_to_read_cmd_delay =
+                       info->min_write_to_read_cmd_delay;
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_dunit_setup
+ * Desc:     Set the controller with the timing values.
+ * Args:     ecc_ena - User ECC setup
+ * Notes:
+ * Returns:
+ */
+int ddr3_dunit_setup(u32 ecc_ena, u32 hclk_time, u32 *ddr_width)
+{
+       u32 reg, tmp, cwl;
+       u32 ddr_clk_time;
+       MV_DIMM_INFO dimm_info[2];
+       MV_DIMM_INFO sum_info;
+       u32 stat_val, spd_val;
+       u32 cs, cl, cs_num, cs_ena;
+       u32 dimm_num = 0;
+       int status;
+       u32 rc;
+       __maybe_unused u32 dimm_cnt, cs_count, dimm;
+       __maybe_unused u32 dimm_addr[2] = { 0, 0 };
+
+#if defined(DB_88F6710) || defined(DB_88F6710_PCAC) || defined(RD_88F6710)
+       /* Armada 370 - SPD is not available on DIMM */
+       /*
+        * Set MC registers according to Static SPD values Values -
+        * must be set manually
+        */
+       /*
+        * We only have one optional DIMM for the DB and we already got the
+        * SPD matching values
+        */
+       status = ddr3_spd_init(&dimm_info[0], 0, *ddr_width);
+       if (MV_OK != status)
+               return status;
+
+       dimm_num = 1;
+       /* Use JP8 to enable multiCS support for Armada 370 DB */
+       if (!ddr3_check_config(EEPROM_MODULE_ADDR, CONFIG_MULTI_CS))
+               dimm_info[0].num_of_module_ranks = 1;
+       status = ddr3_spd_sum_init(&dimm_info[0], &sum_info, 0);
+       if (MV_OK != status)
+               return status;
+#else
+       /* Dynamic D-Unit Setup - Read SPD values */
+#ifdef DUNIT_SPD
+       dimm_num = ddr3_get_dimm_num(dimm_addr);
+       if (dimm_num == 0) {
+#ifdef MIXED_DIMM_STATIC
+               DEBUG_INIT_S("DDR3 Training Sequence - No DIMMs detected\n");
+#else
+               DEBUG_INIT_S("DDR3 Training Sequence - FAILED (Wrong DIMMs Setup)\n");
+               return MV_DDR3_TRAINING_ERR_BAD_DIMM_SETUP;
+#endif
+       } else {
+               DEBUG_INIT_C("DDR3 Training Sequence - Number of DIMMs detected: ",
+                            dimm_num, 1);
+       }
+
+       for (dimm = 0; dimm < dimm_num; dimm++) {
+               status = ddr3_spd_init(&dimm_info[dimm], dimm_addr[dimm],
+                                      *ddr_width);
+               if (MV_OK != status)
+                       return status;
+               status = ddr3_spd_sum_init(&dimm_info[dimm], &sum_info, dimm);
+               if (MV_OK != status)
+                       return status;
+       }
+#endif
+#endif
+
+       /* Set number of enabled CS */
+       cs_num = 0;
+#ifdef DUNIT_STATIC
+       cs_num = ddr3_get_cs_num_from_reg();
+#endif
+#ifdef DUNIT_SPD
+       for (dimm = 0; dimm < dimm_num; dimm++)
+               cs_num += dimm_info[dimm].num_of_module_ranks;
+#endif
+       if (cs_num > MAX_CS) {
+               DEBUG_INIT_C("DDR3 Training Sequence - Number of CS exceed limit -  ",
+                            MAX_CS, 1);
+               return MV_DDR3_TRAINING_ERR_MAX_CS_LIMIT;
+       }
+
+       /* Set bitmap of enabled CS */
+       cs_ena = 0;
+#ifdef DUNIT_STATIC
+       cs_ena = ddr3_get_cs_ena_from_reg();
+#endif
+#ifdef DUNIT_SPD
+       dimm = 0;
+
+       if (dimm_num) {
+               for (cs = 0; cs < MAX_CS; cs += 2) {
+                       if (((1 << cs) & DIMM_CS_BITMAP) &&
+                           !(cs_ena & (1 << cs))) {
+                               if (dimm_info[dimm].num_of_module_ranks == 1)
+                                       cs_ena |= (0x1 << cs);
+                               else if (dimm_info[dimm].num_of_module_ranks == 2)
+                                       cs_ena |= (0x3 << cs);
+                               else if (dimm_info[dimm].num_of_module_ranks == 3)
+                                       cs_ena |= (0x7 << cs);
+                               else if (dimm_info[dimm].num_of_module_ranks == 4)
+                                       cs_ena |= (0xF << cs);
+
+                               dimm++;
+                               if (dimm == dimm_num)
+                                       break;
+                       }
+               }
+       }
+#endif
+
+       if (cs_ena > 0xF) {
+               DEBUG_INIT_C("DDR3 Training Sequence - Number of enabled CS exceed limit -  ",
+                            MAX_CS, 1);
+               return MV_DDR3_TRAINING_ERR_MAX_ENA_CS_LIMIT;
+       }
+
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - Number of CS = ", cs_num, 1);
+
+       /* Check Ratio - '1' - 2:1, '0' - 1:1 */
+       if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS))
+               ddr_clk_time = hclk_time / 2;
+       else
+               ddr_clk_time = hclk_time;
+
+#ifdef DUNIT_STATIC
+       /* Get target CL value from set register */
+       reg = (reg_read(REG_DDR3_MR0_ADDR) >> 2);
+       reg = ((((reg >> 1) & 0xE)) | (reg & 0x1)) & 0xF;
+
+       cl = ddr3_get_max_val(ddr3_div(sum_info.min_cas_lat_time,
+                                      ddr_clk_time, 0),
+                             dimm_num, ddr3_valid_cl_to_cl(reg));
+#else
+       cl = ddr3_div(sum_info.min_cas_lat_time, ddr_clk_time, 0);
+#endif
+       if (cl < 5)
+               cl = 5;
+
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - Cas Latency = ", cl, 1);
+
+       /* {0x00001400} -   DDR SDRAM Configuration Register */
+       reg = 0x73004000;
+       stat_val = ddr3_get_static_mc_value(
+               REG_SDRAM_CONFIG_ADDR, REG_SDRAM_CONFIG_ECC_OFFS, 0x1, 0, 0);
+       if (ecc_ena && ddr3_get_min_val(sum_info.err_check_type, dimm_num,
+                                       stat_val)) {
+               reg |= (1 << REG_SDRAM_CONFIG_ECC_OFFS);
+               reg |= (1 << REG_SDRAM_CONFIG_IERR_OFFS);
+               DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - ECC Enabled\n");
+       } else {
+               DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - ECC Disabled\n");
+       }
+
+       if (sum_info.type_info == SPD_MODULE_TYPE_RDIMM) {
+#ifdef DUNIT_STATIC
+               DEBUG_INIT_S("DDR3 Training Sequence - FAIL - Illegal R-DIMM setup\n");
+               return MV_DDR3_TRAINING_ERR_BAD_R_DIMM_SETUP;
+#endif
+               reg |= (1 << REG_SDRAM_CONFIG_REGDIMM_OFFS);
+               DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - R-DIMM\n");
+       } else {
+               DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - U-DIMM\n");
+       }
+
+#ifndef MV88F67XX
+#ifdef DUNIT_STATIC
+       if (ddr3_get_min_val(sum_info.data_width, dimm_num, BUS_WIDTH) == 64) {
+#else
+       if (*ddr_width == 64) {
+#endif
+               reg |= (1 << REG_SDRAM_CONFIG_WIDTH_OFFS);
+               DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 64Bits\n");
+       } else {
+               DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 32Bits\n");
+       }
+#else
+       DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 16Bits\n");
+#endif
+
+#if defined(MV88F672X)
+       if (*ddr_width == 32) {
+               reg |= (1 << REG_SDRAM_CONFIG_WIDTH_OFFS);
+               DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 32Bits\n");
+       } else {
+               DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 16Bits\n");
+       }
+#endif
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_CONFIG_ADDR, 0,
+                                              REG_SDRAM_CONFIG_RFRS_MASK, 0, 0);
+       tmp = ddr3_get_min_val(sum_info.refresh_interval / hclk_time,
+                              dimm_num, stat_val);
+
+#ifdef TREFI_USER_EN
+       tmp = min(TREFI_USER / hclk_time, tmp);
+#endif
+
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - RefreshInterval/Hclk = ", tmp, 4);
+       reg |= tmp;
+
+       if (cl != 3)
+               reg |= (1 << 16);       /*  If 2:1 need to set P2DWr */
+
+#if defined(MV88F672X)
+       reg |= (1 << 27);       /* PhyRfRST = Disable */
+#endif
+       reg_write(REG_SDRAM_CONFIG_ADDR, reg);
+
+       /*{0x00001404}  -   DDR SDRAM Configuration Register */
+       reg = 0x3630B800;
+#ifdef DUNIT_SPD
+       reg |= (DRAM_2T << REG_DUNIT_CTRL_LOW_2T_OFFS);
+#endif
+       reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+
+       /* {0x00001408}  -   DDR SDRAM Timing (Low) Register */
+       reg = 0x0;
+
+       /* tRAS - (0:3,20) */
+       spd_val = ddr3_div(sum_info.min_active_to_precharge,
+                           ddr_clk_time, 1);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+                                           0, 0xF, 16, 0x10);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRAS-1 = ", tmp, 1);
+       reg |= (tmp & 0xF);
+       reg |= ((tmp & 0x10) << 16);    /* to bit 20 */
+
+       /* tRCD - (4:7) */
+       spd_val = ddr3_div(sum_info.min_ras_to_cas_delay, ddr_clk_time, 1);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+                                           4, 0xF, 0, 0);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRCD-1 = ", tmp, 1);
+       reg |= ((tmp & 0xF) << 4);
+
+       /* tRP - (8:11) */
+       spd_val = ddr3_div(sum_info.min_row_precharge_time, ddr_clk_time, 1);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+                                           8, 0xF, 0, 0);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRP-1 = ", tmp, 1);
+       reg |= ((tmp & 0xF) << 8);
+
+       /* tWR - (12:15) */
+       spd_val = ddr3_div(sum_info.min_write_recovery_time, ddr_clk_time, 1);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+                                           12, 0xF, 0, 0);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tWR-1 = ", tmp, 1);
+       reg |= ((tmp & 0xF) << 12);
+
+       /* tWTR - (16:19) */
+       spd_val = ddr3_div(sum_info.min_write_to_read_cmd_delay, ddr_clk_time, 1);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+                                           16, 0xF, 0, 0);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tWTR-1 = ", tmp, 1);
+       reg |= ((tmp & 0xF) << 16);
+
+       /* tRRD - (24:27) */
+       spd_val = ddr3_div(sum_info.min_row_active_to_row_active, ddr_clk_time, 1);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+                                           24, 0xF, 0, 0);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRRD-1 = ", tmp, 1);
+       reg |= ((tmp & 0xF) << 24);
+
+       /* tRTP - (28:31) */
+       spd_val = ddr3_div(sum_info.min_read_to_prech_cmd_delay, ddr_clk_time, 1);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR,
+                                           28, 0xF, 0, 0);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRTP-1 = ", tmp, 1);
+       reg |= ((tmp & 0xF) << 28);
+
+       if (cl < 7)
+               reg = 0x33137663;
+
+       reg_write(REG_SDRAM_TIMING_LOW_ADDR, reg);
+
+       /*{0x0000140C}  -   DDR SDRAM Timing (High) Register */
+       /* Add cycles to R2R W2W */
+       reg = 0x39F8FF80;
+
+       /* tRFC - (0:6,16:18) */
+       spd_val = ddr3_div(sum_info.min_refresh_recovery, ddr_clk_time, 1);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_HIGH_ADDR,
+                                           0, 0x7F, 9, 0x380);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRFC-1 = ", tmp, 1);
+       reg |= (tmp & 0x7F);
+       reg |= ((tmp & 0x380) << 9);    /* to bit 16 */
+       reg_write(REG_SDRAM_TIMING_HIGH_ADDR, reg);
+
+       /*{0x00001410}  -   DDR SDRAM Address Control Register */
+       reg = 0x000F0000;
+
+       /* tFAW - (24:28)  */
+#if (defined(MV88F78X60) || defined(MV88F672X))
+       tmp = sum_info.min_four_active_win_delay;
+       spd_val = ddr3_div(tmp, ddr_clk_time, 0);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_ADDRESS_CTRL_ADDR,
+                                           24, 0x3F, 0, 0);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tFAW = ", tmp, 1);
+       reg |= ((tmp & 0x3F) << 24);
+#else
+       tmp = sum_info.min_four_active_win_delay -
+               4 * (sum_info.min_row_active_to_row_active);
+       spd_val = ddr3_div(tmp, ddr_clk_time, 0);
+       stat_val = ddr3_get_static_mc_value(REG_SDRAM_ADDRESS_CTRL_ADDR,
+                                           24, 0x1F, 0, 0);
+       tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val);
+       DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tFAW-4*tRRD = ", tmp, 1);
+       reg |= ((tmp & 0x1F) << 24);
+#endif
+
+       /* SDRAM device capacity */
+#ifdef DUNIT_STATIC
+       reg |= (reg_read(REG_SDRAM_ADDRESS_CTRL_ADDR) & 0xF0FFFF);
+#endif
+
+#ifdef DUNIT_SPD
+       cs_count = 0;
+       dimm_cnt = 0;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs) & DIMM_CS_BITMAP) {
+                       if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) {
+                               dimm_cnt++;
+                               cs_count = 0;
+                       }
+                       cs_count++;
+                       if (dimm_info[dimm_cnt].sdram_capacity < 0x3) {
+                               reg |= ((dimm_info[dimm_cnt].sdram_capacity + 1) <<
+                                       (REG_SDRAM_ADDRESS_SIZE_OFFS +
+                                        (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs)));
+                       } else if (dimm_info[dimm_cnt].sdram_capacity > 0x3) {
+                               reg |= ((dimm_info[dimm_cnt].sdram_capacity & 0x3) <<
+                                       (REG_SDRAM_ADDRESS_SIZE_OFFS +
+                                        (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs)));
+                               reg |= ((dimm_info[dimm_cnt].sdram_capacity & 0x4) <<
+                                       (REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS + cs));
+                       }
+               }
+       }
+
+       /* SDRAM device structure */
+       cs_count = 0;
+       dimm_cnt = 0;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs) & DIMM_CS_BITMAP) {
+                       if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) {
+                               dimm_cnt++;
+                               cs_count = 0;
+                       }
+                       cs_count++;
+                       if (dimm_info[dimm_cnt].sdram_width == 16)
+                               reg |= (1 << (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs));
+               }
+       }
+#endif
+       reg_write(REG_SDRAM_ADDRESS_CTRL_ADDR, reg);
+
+       /*{0x00001418}  -   DDR SDRAM Operation Register */
+       reg = 0xF00;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs))
+                       reg &= ~(1 << (cs + REG_SDRAM_OPERATION_CS_OFFS));
+       }
+       reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+       /*{0x00001420}  -   DDR SDRAM Extended Mode Register */
+       reg = 0x00000004;
+       reg_write(REG_SDRAM_EXT_MODE_ADDR, reg);
+
+       /*{0x00001424}  -   DDR Controller Control (High) Register */
+#if (defined(MV88F78X60) || defined(MV88F672X))
+       reg = 0x0000D3FF;
+#else
+       reg = 0x0100D1FF;
+#endif
+       reg_write(REG_DDR_CONT_HIGH_ADDR, reg);
+
+       /*{0x0000142C}  -   DDR3 Timing Register */
+       reg = 0x014C2F38;
+#if defined(MV88F78X60) || defined(MV88F672X)
+       reg = 0x1FEC2F38;
+#endif
+       reg_write(0x142C, reg);
+
+       /*{0x00001484}  - MBus CPU Block Register */
+#ifdef MV88F67XX
+       if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS))
+               reg_write(REG_MBUS_CPU_BLOCK_ADDR, 0x0000E907);
+#endif
+
+       /*
+        * In case of mixed dimm and on-board devices setup paramters will
+        * be taken statically
+        */
+       /*{0x00001494}  -   DDR SDRAM ODT Control (Low) Register */
+       reg = odt_config[cs_ena];
+       reg_write(REG_SDRAM_ODT_CTRL_LOW_ADDR, reg);
+
+       /*{0x00001498}  -   DDR SDRAM ODT Control (High) Register */
+       reg = 0x00000000;
+       reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, reg);
+
+       /*{0x0000149C}  -   DDR Dunit ODT Control Register */
+       reg = cs_ena;
+       reg_write(REG_DUNIT_ODT_CTRL_ADDR, reg);
+
+       /*{0x000014A0}  -   DDR Dunit ODT Control Register */
+#if defined(MV88F672X)
+       reg = 0x000006A9;
+       reg_write(REG_DRAM_FIFO_CTRL_ADDR, reg);
+#endif
+
+       /*{0x000014C0}  -   DRAM address and Control Driving Strenght */
+       reg_write(REG_DRAM_ADDR_CTRL_DRIVE_STRENGTH_ADDR, 0x192435e9);
+
+       /*{0x000014C4}  -   DRAM Data and DQS Driving Strenght */
+       reg_write(REG_DRAM_DATA_DQS_DRIVE_STRENGTH_ADDR, 0xB2C35E9);
+
+#if (defined(MV88F78X60) || defined(MV88F672X))
+       /*{0x000014CC}  -   DRAM Main Pads Calibration Machine Control Register */
+       reg = reg_read(REG_DRAM_MAIN_PADS_CAL_ADDR);
+       reg_write(REG_DRAM_MAIN_PADS_CAL_ADDR, reg | (1 << 0));
+#endif
+
+#if defined(MV88F672X)
+       /* DRAM Main Pads Calibration Machine Control Register */
+       /* 0x14CC[4:3] - CalUpdateControl = IntOnly */
+       reg = reg_read(REG_DRAM_MAIN_PADS_CAL_ADDR);
+       reg &= 0xFFFFFFE7;
+       reg |= (1 << 3);
+       reg_write(REG_DRAM_MAIN_PADS_CAL_ADDR, reg);
+#endif
+
+#ifdef DUNIT_SPD
+       cs_count = 0;
+       dimm_cnt = 0;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if ((1 << cs) & DIMM_CS_BITMAP) {
+                       if ((1 << cs) & cs_ena) {
+                               if (dimm_info[dimm_cnt].num_of_module_ranks ==
+                                   cs_count) {
+                                       dimm_cnt++;
+                                       cs_count = 0;
+                               }
+                               cs_count++;
+                               reg_write(REG_CS_SIZE_SCRATCH_ADDR + (cs * 0x8),
+                                         dimm_info[dimm_cnt].rank_capacity - 1);
+                       } else {
+                               reg_write(REG_CS_SIZE_SCRATCH_ADDR + (cs * 0x8), 0);
+                       }
+               }
+       }
+#endif
+
+       /*{0x00020184}  -   Close FastPath - 2G */
+       reg_write(REG_FASTPATH_WIN_0_CTRL_ADDR, 0);
+
+       /*{0x00001538}  -    Read Data Sample Delays Register */
+       reg = 0;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs))
+                       reg |= (cl << (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs));
+       }
+
+       reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, reg);
+       DEBUG_INIT_FULL_C("DDR3 - SPD-SET - Read Data Sample Delays = ", reg,
+                         1);
+
+       /*{0x0000153C}  -   Read Data Ready Delay Register */
+       reg = 0;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs)) {
+                       reg |= ((cl + 2) <<
+                               (REG_READ_DATA_READY_DELAYS_OFFS * cs));
+               }
+       }
+       reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg);
+       DEBUG_INIT_FULL_C("DDR3 - SPD-SET - Read Data Ready Delays = ", reg, 1);
+
+       /* Set MR registers */
+       /* MR0 */
+       reg = 0x00000600;
+       tmp = ddr3_cl_to_valid_cl(cl);
+       reg |= ((tmp & 0x1) << 2);
+       reg |= ((tmp & 0xE) << 3);      /* to bit 4 */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs)) {
+                       reg_write(REG_DDR3_MR0_CS_ADDR +
+                                 (cs << MR_CS_ADDR_OFFS), reg);
+               }
+       }
+
+       /* MR1 */
+       reg = 0x00000044 & REG_DDR3_MR1_ODT_MASK;
+       if (cs_num > 1)
+               reg = 0x00000046 & REG_DDR3_MR1_ODT_MASK;
+
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs)) {
+                       reg |= odt_static[cs_ena][cs];
+                       reg_write(REG_DDR3_MR1_CS_ADDR +
+                                 (cs << MR_CS_ADDR_OFFS), reg);
+               }
+       }
+
+       /* MR2 */
+       if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS))
+               tmp = hclk_time / 2;
+       else
+               tmp = hclk_time;
+
+       if (tmp >= 2500)
+               cwl = 5;        /* CWL = 5 */
+       else if (tmp >= 1875 && tmp < 2500)
+               cwl = 6;        /* CWL = 6 */
+       else if (tmp >= 1500 && tmp < 1875)
+               cwl = 7;        /* CWL = 7 */
+       else if (tmp >= 1250 && tmp < 1500)
+               cwl = 8;        /* CWL = 8 */
+       else if (tmp >= 1070 && tmp < 1250)
+               cwl = 9;        /* CWL = 9 */
+       else if (tmp >= 935 && tmp < 1070)
+               cwl = 10;       /* CWL = 10 */
+       else if (tmp >= 833 && tmp < 935)
+               cwl = 11;       /* CWL = 11 */
+       else if (tmp >= 750 && tmp < 833)
+               cwl = 12;       /* CWL = 12 */
+       else {
+               cwl = 12;       /* CWL = 12 */
+               printf("Unsupported hclk %d MHz\n", tmp);
+       }
+
+       reg = ((cwl - 5) << REG_DDR3_MR2_CWL_OFFS);
+
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs)) {
+                       reg &= REG_DDR3_MR2_ODT_MASK;
+                       reg |= odt_dynamic[cs_ena][cs];
+                       reg_write(REG_DDR3_MR2_CS_ADDR +
+                                 (cs << MR_CS_ADDR_OFFS), reg);
+               }
+       }
+
+       /* MR3 */
+       reg = 0x00000000;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs)) {
+                       reg_write(REG_DDR3_MR3_CS_ADDR +
+                                 (cs << MR_CS_ADDR_OFFS), reg);
+               }
+       }
+
+       /* {0x00001428}  -   DDR ODT Timing (Low) Register */
+       reg = 0;
+       reg |= (((cl - cwl + 1) & 0xF) << 4);
+       reg |= (((cl - cwl + 6) & 0xF) << 8);
+       reg |= ((((cl - cwl + 6) >> 4) & 0x1) << 21);
+       reg |= (((cl - 1) & 0xF) << 12);
+       reg |= (((cl + 6) & 0x1F) << 16);
+       reg_write(REG_ODT_TIME_LOW_ADDR, reg);
+
+       /* {0x0000147C}  -   DDR ODT Timing (High) Register */
+       reg = 0x00000071;
+       reg |= ((cwl - 1) << 8);
+       reg |= ((cwl + 5) << 12);
+       reg_write(REG_ODT_TIME_HIGH_ADDR, reg);
+
+#ifdef DUNIT_SPD
+       /*{0x000015E0} - DDR3 Rank Control Register */
+       reg = cs_ena;
+       cs_count = 0;
+       dimm_cnt = 0;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (cs_ena & (1 << cs) & DIMM_CS_BITMAP) {
+                       if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) {
+                               dimm_cnt++;
+                               cs_count = 0;
+                       }
+                       cs_count++;
+
+                       if (dimm_info[dimm_cnt].addr_mirroring &&
+                           (cs == 1 || cs == 3) &&
+                           (sum_info.type_info != SPD_MODULE_TYPE_RDIMM)) {
+                               reg |= (1 << (REG_DDR3_RANK_CTRL_MIRROR_OFFS + cs));
+                               DEBUG_INIT_FULL_C("DDR3 - SPD-SET - Setting Address Mirroring for CS = ",
+                                                 cs, 1);
+                       }
+               }
+       }
+       reg_write(REG_DDR3_RANK_CTRL_ADDR, reg);
+#endif
+
+       /*{0xD00015E4}  -   ZQDS Configuration Register */
+       reg = 0x00203c18;
+       reg_write(REG_ZQC_CONF_ADDR, reg);
+
+       /* {0x00015EC}  -   DDR PHY */
+#if defined(MV88F78X60)
+       reg = 0xF800AAA5;
+       if (mv_ctrl_rev_get() == MV_78XX0_B0_REV)
+               reg = 0xF800A225;
+#else
+       reg = 0xDE000025;
+#if defined(MV88F672X)
+       reg = 0xF800A225;
+#endif
+#endif
+       reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg);
+
+#if (defined(MV88F78X60) || defined(MV88F672X))
+       /* Registered DIMM support - supported only in AXP A0 devices */
+       /* Currently supported for SPD detection only */
+       /*
+        * Flow is according to the Registered DIMM chapter in the
+        * Functional Spec
+        */
+       if (sum_info.type_info == SPD_MODULE_TYPE_RDIMM) {
+               DEBUG_INIT_S("DDR3 Training Sequence - Registered DIMM detected\n");
+
+               /* Set commands parity completion */
+               reg = reg_read(REG_REGISTERED_DRAM_CTRL_ADDR);
+               reg &= ~REG_REGISTERED_DRAM_CTRL_PARITY_MASK;
+               reg |= 0x8;
+               reg_write(REG_REGISTERED_DRAM_CTRL_ADDR, reg);
+
+               /* De-assert M_RESETn and assert M_CKE */
+               reg_write(REG_SDRAM_INIT_CTRL_ADDR,
+                         1 << REG_SDRAM_INIT_CKE_ASSERT_OFFS);
+               do {
+                       reg = (reg_read(REG_SDRAM_INIT_CTRL_ADDR)) &
+                               (1 << REG_SDRAM_INIT_CKE_ASSERT_OFFS);
+               } while (reg);
+
+               for (rc = 0; rc < SPD_RDIMM_RC_NUM; rc++) {
+                       if (rc != 6 && rc != 7) {
+                               /* Set CWA Command */
+                               reg = (REG_SDRAM_OPERATION_CMD_CWA &
+                                      ~(0xF << REG_SDRAM_OPERATION_CS_OFFS));
+                               reg |= ((dimm_info[0].dimm_rc[rc] &
+                                        REG_SDRAM_OPERATION_CWA_DATA_MASK) <<
+                                       REG_SDRAM_OPERATION_CWA_DATA_OFFS);
+                               reg |= rc << REG_SDRAM_OPERATION_CWA_RC_OFFS;
+                               /* Configure - Set Delay - tSTAB/tMRD */
+                               if (rc == 2 || rc == 10)
+                                       reg |= (0x1 << REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS);
+                               /* 0x1418 - SDRAM Operation Register */
+                               reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                               /*
+                                * Poll the "cmd" field in the SDRAM OP
+                                * register for 0x0
+                                */
+                               do {
+                                       reg = reg_read(REG_SDRAM_OPERATION_ADDR) &
+                                               (REG_SDRAM_OPERATION_CMD_MASK);
+                               } while (reg);
+                       }
+               }
+       }
+#endif
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_div - this function divides integers
+ * Desc:
+ * Args:     val - the value
+ *           divider - the divider
+ *           sub - substruction value
+ * Notes:
+ * Returns:  required value
+ */
+u32 ddr3_div(u32 val, u32 divider, u32 sub)
+{
+       return val / divider + (val % divider > 0 ? 1 : 0) - sub;
+}
+
+/*
+ * Name:     ddr3_get_max_val
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:
+ */
+u32 ddr3_get_max_val(u32 spd_val, u32 dimm_num, u32 static_val)
+{
+#ifdef DUNIT_STATIC
+       if (dimm_num > 0) {
+               if (spd_val >= static_val)
+                       return spd_val;
+               else
+                       return static_val;
+       } else {
+               return static_val;
+       }
+#else
+       return spd_val;
+#endif
+}
+
+/*
+ * Name:     ddr3_get_min_val
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns:
+ */
+u32 ddr3_get_min_val(u32 spd_val, u32 dimm_num, u32 static_val)
+{
+#ifdef DUNIT_STATIC
+       if (dimm_num > 0) {
+               if (spd_val <= static_val)
+                       return spd_val;
+               else
+                       return static_val;
+       } else
+               return static_val;
+#else
+       return spd_val;
+#endif
+}
+#endif
diff --git a/drivers/ddr/mvebu/ddr3_write_leveling.c b/drivers/ddr/mvebu/ddr3_write_leveling.c
new file mode 100644 (file)
index 0000000..df3a3df
--- /dev/null
@@ -0,0 +1,1366 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "ddr3_hw_training.h"
+
+/*
+ * Debug
+ */
+#define DEBUG_WL_C(s, d, l) \
+       DEBUG_WL_S(s); DEBUG_WL_D(d, l); DEBUG_WL_S("\n")
+#define DEBUG_WL_FULL_C(s, d, l) \
+       DEBUG_WL_FULL_S(s); DEBUG_WL_FULL_D(d, l); DEBUG_WL_FULL_S("\n")
+
+#ifdef MV_DEBUG_WL
+#define DEBUG_RL_S(s) \
+       debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
+#define DEBUG_RL_D(d, l) \
+       debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
+#else
+#define DEBUG_WL_S(s)
+#define DEBUG_WL_D(d, l)
+#endif
+
+#ifdef MV_DEBUG_WL_FULL
+#define DEBUG_WL_FULL_S(s)             puts(s)
+#define DEBUG_WL_FULL_D(d, l)          printf("%x", d)
+#else
+#define DEBUG_WL_FULL_S(s)
+#define DEBUG_WL_FULL_D(d, l)
+#endif
+
+#define WL_SUP_EXPECTED_DATA           0x21
+#define WL_SUP_READ_DRAM_ENTRY         0x8
+
+static int ddr3_write_leveling_single_cs(u32 cs, u32 freq, int ratio_2to1,
+                                        u32 *result,
+                                        MV_DRAM_INFO *dram_info);
+static void ddr3_write_ctrl_pup_reg(int bc_acc, u32 pup, u32 reg_addr,
+                                   u32 data);
+
+extern u16 odt_static[ODT_OPT][MAX_CS];
+extern u16 odt_dynamic[ODT_OPT][MAX_CS];
+extern u32 wl_sup_pattern[LEN_WL_SUP_PATTERN];
+
+/*
+ * Name:     ddr3_write_leveling_hw
+ * Desc:     Execute Write leveling phase by HW
+ * Args:     freq      - current sequence frequency
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_write_leveling_hw(u32 freq, MV_DRAM_INFO *dram_info)
+{
+       u32 reg, phase, delay, cs, pup;
+#ifdef MV88F67XX
+       int dpde_flag = 0;
+#endif
+       /* Debug message - Start Read leveling procedure */
+       DEBUG_WL_S("DDR3 - Write Leveling - Starting HW WL procedure\n");
+
+#ifdef MV88F67XX
+       /* Dynamic pad issue (BTS669) during WL */
+       reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+       if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
+               dpde_flag = 1;
+               reg_write(REG_DUNIT_CTRL_LOW_ADDR,
+                         reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
+       }
+#endif
+
+       reg = 1 << REG_DRAM_TRAINING_WL_OFFS;
+       /* Config the retest number */
+       reg |= (COUNT_HW_WL << REG_DRAM_TRAINING_RETEST_OFFS);
+       reg |= (dram_info->cs_ena << (REG_DRAM_TRAINING_CS_OFFS));
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       reg =  reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) |
+               (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       reg_write(REG_DRAM_TRAINING_SHADOW_ADDR, reg);
+
+       /* Wait */
+       do {
+               reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
+                       (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       } while (reg);          /* Wait for '0' */
+
+       reg = reg_read(REG_DRAM_TRAINING_ADDR);
+       /* Check if Successful */
+       if (reg & (1 << REG_DRAM_TRAINING_ERROR_OFFS)) {
+               /*
+                * Read results to arrays - Results are required for WL
+                * High freq Supplement and DQS Centralization
+                */
+               for (cs = 0; cs < MAX_CS; cs++) {
+                       if (dram_info->cs_ena & (1 << cs)) {
+                               for (pup = 0;
+                                    pup < dram_info->num_of_total_pups;
+                                    pup++) {
+                                       if (pup == dram_info->num_of_std_pups
+                                           && dram_info->ecc_ena)
+                                               pup = ECC_PUP;
+                                       reg =
+                                           ddr3_read_pup_reg(PUP_WL_MODE, cs,
+                                                             pup);
+                                       phase =
+                                           (reg >> REG_PHY_PHASE_OFFS) &
+                                           PUP_PHASE_MASK;
+                                       delay = reg & PUP_DELAY_MASK;
+                                       dram_info->wl_val[cs][pup][P] = phase;
+                                       dram_info->wl_val[cs][pup][D] = delay;
+                                       dram_info->wl_val[cs][pup][S] =
+                                           WL_HI_FREQ_STATE - 1;
+                                       reg =
+                                           ddr3_read_pup_reg(PUP_WL_MODE + 0x1,
+                                                             cs, pup);
+                                       dram_info->wl_val[cs][pup][DQS] =
+                                           (reg & 0x3F);
+                               }
+
+#ifdef MV_DEBUG_WL
+                               /* Debug message - Print res for cs[i]: cs,PUP,Phase,Delay */
+                               DEBUG_WL_S("DDR3 - Write Leveling - Write Leveling Cs - ");
+                               DEBUG_WL_D((u32) cs, 1);
+                               DEBUG_WL_S(" Results:\n");
+                               for (pup = 0;
+                                    pup < dram_info->num_of_total_pups;
+                                    pup++) {
+                                       if (pup == dram_info->num_of_std_pups
+                                           && dram_info->ecc_ena)
+                                               pup = ECC_PUP;
+                                       DEBUG_WL_S("DDR3 - Write Leveling - PUP: ");
+                                       DEBUG_WL_D((u32) pup, 1);
+                                       DEBUG_WL_S(", Phase: ");
+                                       DEBUG_WL_D((u32)
+                                                  dram_info->wl_val[cs][pup]
+                                                  [P], 1);
+                                       DEBUG_WL_S(", Delay: ");
+                                       DEBUG_WL_D((u32)
+                                                  dram_info->wl_val[cs][pup]
+                                                  [D], 2);
+                                       DEBUG_WL_S("\n");
+                               }
+#endif
+                       }
+               }
+
+               /* Dynamic pad issue (BTS669) during WL */
+#ifdef MV88F67XX
+               if (dpde_flag) {
+                       reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
+                               (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
+                       reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+               }
+#endif
+
+               DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
+
+               return MV_OK;
+       } else {
+               DEBUG_WL_S("DDR3 - Write Leveling - HW WL Error\n");
+               return MV_FAIL;
+       }
+}
+
+/*
+ * Name:     ddr3_wl_supplement
+ * Desc:     Write Leveling Supplement
+ * Args:     dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_wl_supplement(MV_DRAM_INFO *dram_info)
+{
+       u32 cs, cnt, pup_num, sum, phase, delay, max_pup_num, pup, sdram_offset;
+       u32 tmp_count, ecc, reg;
+       u32 ddr_width, tmp_pup, idx;
+       u32 sdram_pup_val, uj;
+       u32 one_clk_err = 0, align_err = 0, no_err = 0, err = 0, err_n = 0;
+       u32 sdram_data[LEN_WL_SUP_PATTERN] __aligned(32) = { 0 };
+
+       ddr_width = dram_info->ddr_width;
+       no_err = 0;
+
+       DEBUG_WL_S("DDR3 - Write Leveling Hi-Freq Supplement - Starting\n");
+
+       switch (ddr_width) {
+               /* Data error from pos-adge to pos-adge */
+       case 16:
+               one_clk_err = 4;
+               align_err = 4;
+               break;
+       case 32:
+               one_clk_err = 8;
+               align_err = 8;
+               break;
+       case 64:
+               one_clk_err = 0x10;
+               align_err = 0x10;
+               break;
+       default:
+               DEBUG_WL_S("Error - bus width!!!\n");
+               return MV_FAIL;
+       }
+
+       /* Enable SW override */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+
+       /* [0] = 1 - Enable SW override  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+       DEBUG_WL_S("DDR3 - Write Leveling Hi-Freq Supplement - SW Override Enabled\n");
+       reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+       tmp_count = 0;
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       sum = 0;
+                       /*
+                        * 2 iterations loop: 1)actual WL results 2) fix WL
+                        * if needed
+                        */
+                       for (cnt = 0; cnt < COUNT_WL_HI_FREQ; cnt++) {
+                               DEBUG_WL_C("COUNT = ", cnt, 1);
+                               for (ecc = 0; ecc < (dram_info->ecc_ena + 1);
+                                    ecc++) {
+                                       if (ecc) {
+                                               DEBUG_WL_S("ECC PUP:\n");
+                                       } else {
+                                               DEBUG_WL_S("DATA PUP:\n");
+                                       }
+
+                                       max_pup_num =
+                                           dram_info->num_of_std_pups * (1 -
+                                                                         ecc) +
+                                           ecc;
+                                       /* ECC Support - Switch ECC Mux on ecc=1 */
+                                       reg =
+                                           (reg_read(REG_DRAM_TRAINING_2_ADDR)
+                                            & ~(1 <<
+                                                REG_DRAM_TRAINING_2_ECC_MUX_OFFS));
+                                       reg |=
+                                           (dram_info->ecc_ena *
+                                            ecc <<
+                                            REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
+                                       reg_write(REG_DRAM_TRAINING_2_ADDR,
+                                                 reg);
+                                       ddr3_reset_phy_read_fifo();
+
+                                       /* Write to memory */
+                                       sdram_offset =
+                                           tmp_count * (SDRAM_CS_SIZE + 1) +
+                                           0x200;
+                                       if (MV_OK != ddr3_dram_sram_burst((u32)
+                                                                         wl_sup_pattern,
+                                                                         sdram_offset,
+                                                                         LEN_WL_SUP_PATTERN))
+                                               return MV_FAIL;
+
+                                       /* Read from memory */
+                                       if (MV_OK !=
+                                           ddr3_dram_sram_burst(sdram_offset,
+                                                                (u32)
+                                                                sdram_data,
+                                                                LEN_WL_SUP_PATTERN))
+                                               return MV_FAIL;
+
+                                       /* Print the buffer */
+                                       for (uj = 0; uj < LEN_WL_SUP_PATTERN;
+                                            uj++) {
+                                               if ((uj % 4 == 0) && (uj != 0)) {
+                                                       DEBUG_WL_S("\n");
+                                               }
+                                               DEBUG_WL_D(sdram_data[uj],
+                                                          8);
+                                               DEBUG_WL_S(" ");
+                                       }
+
+                                       /* Check pup which DQS/DATA is error */
+                                       for (pup = 0; pup < max_pup_num; pup++) {
+                                               /* ECC support - bit 8 */
+                                               pup_num = (ecc) ? ECC_PUP : pup;
+                                               if (pup < 4) {  /* lower 32 bit */
+                                                       tmp_pup = pup;
+                                                       idx =
+                                                           WL_SUP_READ_DRAM_ENTRY;
+                                               } else {        /* higher 32 bit */
+                                                       tmp_pup = pup - 4;
+                                                       idx =
+                                                           WL_SUP_READ_DRAM_ENTRY
+                                                           + 1;
+                                               }
+                                               DEBUG_WL_S("\nCS: ");
+                                               DEBUG_WL_D((u32) cs, 1);
+                                               DEBUG_WL_S(" PUP: ");
+                                               DEBUG_WL_D((u32) pup_num, 1);
+                                               DEBUG_WL_S("\n");
+                                               sdram_pup_val =
+                                                   ((sdram_data[idx] >>
+                                                     ((tmp_pup) * 8)) & 0xFF);
+                                               DEBUG_WL_C("Actual Data = ",
+                                                          sdram_pup_val, 2);
+                                               DEBUG_WL_C("Expected Data = ",
+                                                          (WL_SUP_EXPECTED_DATA
+                                                           + pup), 2);
+                                               /*
+                                                * ALINGHMENT: calculate
+                                                * expected data vs actual data
+                                                */
+                                               err =
+                                                   (WL_SUP_EXPECTED_DATA +
+                                                    pup) - sdram_pup_val;
+                                               /*
+                                                * CLOCK LONG: calculate
+                                                * expected data vs actual data
+                                                */
+                                               err_n =
+                                                   sdram_pup_val -
+                                                   (WL_SUP_EXPECTED_DATA +
+                                                    pup);
+                                               DEBUG_WL_C("err = ", err, 2);
+                                               DEBUG_WL_C("err_n = ", err_n,
+                                                          2);
+                                               if (err == no_err) {
+                                                       /* PUP is correct - increment State */
+                                                       dram_info->wl_val[cs]
+                                                           [pup_num]
+                                                           [S] = 1;
+                                               } else if (err_n == one_clk_err) {
+                                                       /* clock is longer than DQS */
+                                                       phase =
+                                                           ((dram_info->wl_val
+                                                             [cs]
+                                                             [pup_num][P] +
+                                                             WL_HI_FREQ_SHIFT)
+                                                            % MAX_PHASE_2TO1);
+                                                       dram_info->wl_val[cs]
+                                                           [pup_num]
+                                                           [P] = phase;
+                                                       delay =
+                                                           dram_info->wl_val
+                                                           [cs][pup_num]
+                                                           [D];
+                                                       DEBUG_WL_S("#### Clock is longer than DQS more than one clk cycle ####\n");
+                                                       ddr3_write_pup_reg
+                                                           (PUP_WL_MODE, cs,
+                                                            pup * (1 - ecc) +
+                                                            ECC_PUP * ecc,
+                                                            phase, delay);
+                                               } else if (err == align_err) {
+                                                       /* clock is align to DQS */
+                                                       phase =
+                                                           dram_info->wl_val
+                                                           [cs][pup_num]
+                                                           [P];
+                                                       delay =
+                                                           dram_info->wl_val
+                                                           [cs][pup_num]
+                                                           [D];
+                                                       DEBUG_WL_S("#### Alignment PUPS problem ####\n");
+                                                       if ((phase == 0)
+                                                           || ((phase == 1)
+                                                               && (delay <=
+                                                                   0x10))) {
+                                                               DEBUG_WL_S("#### Warning - Possible Layout Violation (DQS is longer than CLK)####\n");
+                                                       }
+
+                                                       phase = 0x0;
+                                                       delay = 0x0;
+                                                       dram_info->wl_val[cs]
+                                                           [pup_num]
+                                                           [P] = phase;
+                                                       dram_info->wl_val[cs]
+                                                           [pup_num]
+                                                           [D] = delay;
+                                                       ddr3_write_pup_reg
+                                                           (PUP_WL_MODE, cs,
+                                                            pup * (1 - ecc) +
+                                                            ECC_PUP * ecc,
+                                                            phase, delay);
+                                               }
+                                               /* Stop condition for ECC phase */
+                                               pup = (ecc) ? max_pup_num : pup;
+                                       }
+
+                                       /* ECC Support - Disable ECC MUX */
+                                       reg =
+                                           (reg_read(REG_DRAM_TRAINING_2_ADDR)
+                                            & ~(1 <<
+                                                REG_DRAM_TRAINING_2_ECC_MUX_OFFS));
+                                       reg_write(REG_DRAM_TRAINING_2_ADDR,
+                                                 reg);
+                               }
+                       }
+
+                       for (pup = 0; pup < dram_info->num_of_std_pups; pup++)
+                               sum += dram_info->wl_val[cs][pup][S];
+
+                       if (dram_info->ecc_ena)
+                               sum += dram_info->wl_val[cs][ECC_PUP][S];
+
+                       /* Checks if any pup is not locked after the change */
+                       if (sum < (WL_HI_FREQ_STATE * (dram_info->num_of_total_pups))) {
+                               DEBUG_WL_C("DDR3 - Write Leveling Hi-Freq Supplement - didn't work for Cs - ",
+                                          (u32) cs, 1);
+                               return MV_FAIL;
+                       }
+                       tmp_count++;
+               }
+       }
+
+       dram_info->wl_max_phase = 0;
+       dram_info->wl_min_phase = 10;
+
+       /*
+        * Read results to arrays - Results are required for DQS Centralization
+        */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       for (pup = 0; pup < dram_info->num_of_total_pups; pup++) {
+                               if (pup == dram_info->num_of_std_pups
+                                   && dram_info->ecc_ena)
+                                       pup = ECC_PUP;
+                               reg = ddr3_read_pup_reg(PUP_WL_MODE, cs, pup);
+                               phase =
+                                   (reg >> REG_PHY_PHASE_OFFS) &
+                                   PUP_PHASE_MASK;
+                               if (phase > dram_info->wl_max_phase)
+                                       dram_info->wl_max_phase = phase;
+                               if (phase < dram_info->wl_min_phase)
+                                       dram_info->wl_min_phase = phase;
+                       }
+               }
+       }
+
+       /* Disable SW override - Must be in a different stage */
+       /* [0]=0 - Enable SW override  */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
+               (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
+       reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
+
+       DEBUG_WL_S("DDR3 - Write Leveling Hi-Freq Supplement - Ended Successfully\n");
+
+       return MV_OK;
+}
+
+/*
+ * Name:     ddr3_write_leveling_hw_reg_dimm
+ * Desc:     Execute Write leveling phase by HW
+ * Args:     freq      - current sequence frequency
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_write_leveling_hw_reg_dimm(u32 freq, MV_DRAM_INFO *dram_info)
+{
+       u32 reg, phase, delay, cs, pup, pup_num;
+       __maybe_unused int dpde_flag = 0;
+
+       /* Debug message - Start Read leveling procedure */
+       DEBUG_WL_S("DDR3 - Write Leveling - Starting HW WL procedure\n");
+
+       if (dram_info->num_cs > 2) {
+               DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
+               return MV_NO_CHANGE;
+       }
+
+       /* If target freq = 400 move clock start point */
+       /* Write to control PUP to Control Deskew Regs */
+       if (freq <= DDR_400) {
+               for (pup = 0; pup <= dram_info->num_of_total_pups; pup++) {
+                       /* PUP_DELAY_MASK 0x1F */
+                       /* reg = 0x0C10001F + (uj << 16); */
+                       ddr3_write_ctrl_pup_reg(1, pup, CNTRL_PUP_DESKEW + pup,
+                                               0x1F);
+               }
+       }
+
+#ifdef MV88F67XX
+       /* Dynamic pad issue (BTS669) during WL */
+       reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+       if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
+               dpde_flag = 1;
+               reg_write(REG_DUNIT_CTRL_LOW_ADDR,
+                         reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
+       }
+#endif
+
+       reg = (1 << REG_DRAM_TRAINING_WL_OFFS);
+       /* Config the retest number */
+       reg |= (COUNT_HW_WL << REG_DRAM_TRAINING_RETEST_OFFS);
+       reg |= (dram_info->cs_ena << (REG_DRAM_TRAINING_CS_OFFS));
+       reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
+
+       reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) |
+               (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       reg_write(REG_DRAM_TRAINING_SHADOW_ADDR, reg);
+
+       /* Wait */
+       do {
+               reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
+                       (1 << REG_DRAM_TRAINING_AUTO_OFFS);
+       } while (reg);          /* Wait for '0' */
+
+       reg = reg_read(REG_DRAM_TRAINING_ADDR);
+       /* Check if Successful */
+       if (reg & (1 << REG_DRAM_TRAINING_ERROR_OFFS)) {
+               /*
+                * Read results to arrays - Results are required for WL High
+                * freq Supplement and DQS Centralization
+                */
+               for (cs = 0; cs < MAX_CS; cs++) {
+                       if (dram_info->cs_ena & (1 << cs)) {
+                               for (pup = 0;
+                                    pup < dram_info->num_of_total_pups;
+                                    pup++) {
+                                       if (pup == dram_info->num_of_std_pups
+                                           && dram_info->ecc_ena)
+                                               pup = ECC_BIT;
+                                       reg =
+                                           ddr3_read_pup_reg(PUP_WL_MODE, cs,
+                                                             pup);
+                                       phase =
+                                           (reg >> REG_PHY_PHASE_OFFS) &
+                                           PUP_PHASE_MASK;
+                                       delay = reg & PUP_DELAY_MASK;
+                                       dram_info->wl_val[cs][pup][P] = phase;
+                                       dram_info->wl_val[cs][pup][D] = delay;
+                                       if ((phase == 1) && (delay >= 0x1D)) {
+                                               /*
+                                                * Need to do it here for
+                                                * uncorrect WL values
+                                                */
+                                               ddr3_write_pup_reg(PUP_WL_MODE,
+                                                                  cs, pup, 0,
+                                                                  0);
+                                               dram_info->wl_val[cs][pup][P] =
+                                                   0;
+                                               dram_info->wl_val[cs][pup][D] =
+                                                   0;
+                                       }
+                                       dram_info->wl_val[cs][pup][S] =
+                                           WL_HI_FREQ_STATE - 1;
+                                       reg =
+                                           ddr3_read_pup_reg(PUP_WL_MODE + 0x1,
+                                                             cs, pup);
+                                       dram_info->wl_val[cs][pup][DQS] =
+                                           (reg & 0x3F);
+                               }
+#ifdef MV_DEBUG_WL
+                               /*
+                                * Debug message - Print res for cs[i]:
+                                * cs,PUP,Phase,Delay
+                                */
+                               DEBUG_WL_S("DDR3 - Write Leveling - Write Leveling Cs - ");
+                               DEBUG_WL_D((u32) cs, 1);
+                               DEBUG_WL_S(" Results:\n");
+                               for (pup = 0;
+                                    pup < dram_info->num_of_total_pups;
+                                    pup++) {
+                                       DEBUG_WL_S
+                                           ("DDR3 - Write Leveling - PUP: ");
+                                       DEBUG_WL_D((u32) pup, 1);
+                                       DEBUG_WL_S(", Phase: ");
+                                       DEBUG_WL_D((u32)
+                                                  dram_info->wl_val[cs][pup]
+                                                  [P], 1);
+                                       DEBUG_WL_S(", Delay: ");
+                                       DEBUG_WL_D((u32)
+                                                  dram_info->wl_val[cs][pup]
+                                                  [D], 2);
+                                       DEBUG_WL_S("\n");
+                               }
+#endif
+                       }
+               }
+
+#ifdef MV88F67XX
+               /* Dynamic pad issue (BTS669) during WL */
+               if (dpde_flag) {
+                       reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
+                               (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
+                       reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+               }
+#endif
+               DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
+
+               /* If target freq = 400 move clock back */
+               /* Write to control PUP to Control Deskew Regs */
+               if (freq <= DDR_400) {
+                       for (pup = 0; pup <= dram_info->num_of_total_pups;
+                            pup++) {
+                               ddr3_write_ctrl_pup_reg(1, pup,
+                                                       CNTRL_PUP_DESKEW + pup, 0);
+                       }
+               }
+
+               return MV_OK;
+       } else {
+               /* Configure Each PUP with locked leveling settings */
+               for (cs = 0; cs < MAX_CS; cs++) {
+                       if (dram_info->cs_ena & (1 << cs)) {
+                               for (pup = 0;
+                                    pup < dram_info->num_of_total_pups;
+                                    pup++) {
+                                       /* ECC support - bit 8 */
+                                       pup_num = (pup == dram_info->num_of_std_pups) ?
+                                               ECC_BIT : pup;
+                                       ddr3_write_pup_reg(PUP_WL_MODE, cs,
+                                                          pup_num, 0, 0);
+                               }
+                       }
+               }
+
+               reg_write(REG_DRAM_TRAINING_ADDR, 0);
+
+               /* If target freq = 400 move clock back */
+               /* Write to control PUP to Control Deskew Regs */
+               if (freq <= DDR_400) {
+                       for (pup = 0; pup <= dram_info->num_of_total_pups;
+                            pup++) {
+                               ddr3_write_ctrl_pup_reg(1, pup,
+                                                       CNTRL_PUP_DESKEW + pup, 0);
+                       }
+               }
+
+               DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
+               return MV_NO_CHANGE;
+       }
+}
+
+/*
+ * Name:     ddr3_write_leveling_sw
+ * Desc:     Execute Write leveling phase by SW
+ * Args:     freq      - current sequence frequency
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_write_leveling_sw(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info)
+{
+       u32 reg, cs, cnt, pup, max_pup_num;
+       u32 res[MAX_CS];
+       max_pup_num = dram_info->num_of_total_pups;
+       __maybe_unused int dpde_flag = 0;
+
+       /* Debug message - Start Write leveling procedure */
+       DEBUG_WL_S("DDR3 - Write Leveling - Starting SW WL procedure\n");
+
+#ifdef MV88F67XX
+       /* Dynamic pad issue (BTS669) during WL */
+       reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+       if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
+               dpde_flag = 1;
+               reg_write(REG_DUNIT_CTRL_LOW_ADDR,
+                         reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
+       }
+#endif
+
+       /* Set Output buffer-off to all CS and correct ODT values */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       reg = reg_read(REG_DDR3_MR1_ADDR) &
+                               REG_DDR3_MR1_ODT_MASK;
+                       reg |= odt_static[dram_info->cs_ena][cs];
+                       reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
+
+                       /* 0x15D0 - DDR3 MR0 Register */
+                       reg_write(REG_DDR3_MR1_ADDR, reg);
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR1 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       udelay(MRS_DELAY);
+               }
+       }
+
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling - Qoff and RTT Values are set for all Cs\n");
+
+       /* Enable SW override */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* [0] = 1 - Enable SW override  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling - SW Override Enabled\n");
+
+       /* Enable PHY write leveling mode */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+               ~(1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
+       /* [2] = 0 - TrnWLMode - Enable */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+       /* Reset WL results arry */
+       memset(dram_info->wl_val, 0, sizeof(u32) * MAX_CS * MAX_PUP_NUM * 7);
+
+       /* Loop for each cs */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       DEBUG_WL_FULL_C("DDR3 - Write Leveling - Starting working with Cs - ",
+                                       (u32) cs, 1);
+                       /* Refresh X9 current cs */
+                       DEBUG_WL_FULL_S("DDR3 - Write Leveling - Refresh X9\n");
+                       for (cnt = 0; cnt < COUNT_WL_RFRS; cnt++) {
+                               reg =
+                                   REG_SDRAM_OPERATION_CMD_RFRS & ~(1 <<
+                                                                    (REG_SDRAM_OPERATION_CS_OFFS
+                                                                     + cs));
+                               /* [3-0] = 0x2 - refresh, [11-8] - enable current cs */
+                               reg_write(REG_SDRAM_OPERATION_ADDR, reg);       /* 0x1418 - SDRAM Operation Register */
+
+                               do {
+                                       reg =
+                                           ((reg_read
+                                             (REG_SDRAM_OPERATION_ADDR)) &
+                                            REG_SDRAM_OPERATION_CMD_RFRS_DONE);
+                               } while (reg);  /* Wait for '0' */
+                       }
+
+                       /* Configure MR1 in Cs[CsNum] - write leveling on, output buffer on */
+                       DEBUG_WL_FULL_S("DDR3 - Write Leveling - Configure MR1 for current Cs: WL-on,OB-on\n");
+                       reg = reg_read(REG_DDR3_MR1_ADDR) &
+                               REG_DDR3_MR1_OUTBUF_WL_MASK;
+                       /* Set ODT Values */
+                       reg &= REG_DDR3_MR1_ODT_MASK;
+                       reg |= odt_static[dram_info->cs_ena][cs];
+                       /* Enable WL MODE */
+                       reg |= (1 << REG_DDR3_MR1_WL_ENA_OFFS);
+                       /* [7]=1, [12]=0 - Output Buffer and write leveling enabled */
+                       reg_write(REG_DDR3_MR1_ADDR, reg);      /* 0x15D4 - DDR3 MR1 Register */
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR1 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       udelay(MRS_DELAY);
+
+                       /* Write leveling  cs[cs] */
+                       if (MV_OK !=
+                           ddr3_write_leveling_single_cs(cs, freq, ratio_2to1,
+                                                         (u32 *)(res + cs),
+                                                         dram_info)) {
+                               DEBUG_WL_FULL_C("DDR3 - Write Leveling single Cs - FAILED -  Cs - ",
+                                               (u32) cs, 1);
+                               for (pup = 0; pup < max_pup_num; pup++) {
+                                       if (((res[cs] >> pup) & 0x1) == 0) {
+                                               DEBUG_WL_C("Failed Byte : ",
+                                                          pup, 1);
+                                       }
+                               }
+                               return MV_FAIL;
+                       }
+
+                       /* Set TrnWLDeUpd - After each CS is done */
+                       reg = reg_read(REG_TRAINING_WL_ADDR) |
+                               (1 << REG_TRAINING_WL_CS_DONE_OFFS);
+                       /* 0x16AC - Training Write leveling register */
+                       reg_write(REG_TRAINING_WL_ADDR, reg);
+
+                       /*
+                        * Debug message - Finished Write leveling cs[cs] -
+                        * each PUP Fail/Success
+                        */
+                       DEBUG_WL_FULL_C("DDR3 - Write Leveling - Finished Cs - ", (u32) cs,
+                                       1);
+                       DEBUG_WL_FULL_C("DDR3 - Write Leveling - The Results: 1-PUP locked, 0-PUP failed -",
+                                       (u32) res[cs], 3);
+
+                       /*
+                        * Configure MR1 in cs[cs] - write leveling off (0),
+                        * output buffer off (1)
+                        */
+                       reg = reg_read(REG_DDR3_MR1_ADDR) &
+                               REG_DDR3_MR1_OUTBUF_WL_MASK;
+                       reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
+                       /* No need to sort ODT since it is same CS */
+                       /* 0x15D4 - DDR3 MR1 Register */
+                       reg_write(REG_DDR3_MR1_ADDR, reg);
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR1 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       udelay(MRS_DELAY);
+               }
+       }
+
+       /* Disable WL Mode */
+       /* [2]=1 - TrnWLMode - Disable */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg |= (1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       /* Disable SW override - Must be in a different stage */
+       /* [0]=0 - Enable SW override  */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       /* Set Output buffer-on to all CS and correct ODT values */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       reg = reg_read(REG_DDR3_MR1_ADDR) &
+                               REG_DDR3_MR1_ODT_MASK;
+                       reg &= REG_DDR3_MR1_OUTBUF_WL_MASK;
+                       reg |= odt_static[dram_info->cs_ena][cs];
+
+                       /* 0x15D0 - DDR3 MR1 Register */
+                       reg_write(REG_DDR3_MR1_ADDR, reg);
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR1 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       udelay(MRS_DELAY);
+               }
+       }
+
+#ifdef MV88F67XX
+       /* Dynamic pad issue (BTS669) during WL */
+       if (dpde_flag) {
+               reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
+                       (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
+               reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+       }
+#endif
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling - Finished WL procedure for all Cs\n");
+
+       return MV_OK;
+}
+
+#if !defined(MV88F672X)
+/*
+ * Name:     ddr3_write_leveling_sw
+ * Desc:     Execute Write leveling phase by SW
+ * Args:     freq        - current sequence frequency
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+int ddr3_write_leveling_sw_reg_dimm(u32 freq, int ratio_2to1,
+                                   MV_DRAM_INFO *dram_info)
+{
+       u32 reg, cs, cnt, pup;
+       u32 res[MAX_CS];
+       __maybe_unused int dpde_flag = 0;
+
+       /* Debug message - Start Write leveling procedure */
+       DEBUG_WL_S("DDR3 - Write Leveling - Starting SW WL procedure\n");
+
+#ifdef MV88F67XX
+       /* Dynamic pad issue (BTS669) during WL */
+       reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+       if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
+               dpde_flag = 1;
+               reg_write(REG_DUNIT_CTRL_LOW_ADDR,
+                         reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
+       }
+#endif
+
+       /* If target freq = 400 move clock start point */
+       /* Write to control PUP to Control Deskew Regs */
+       if (freq <= DDR_400) {
+               for (pup = 0; pup <= dram_info->num_of_total_pups; pup++) {
+                       /* PUP_DELAY_MASK 0x1F */
+                       /* reg = 0x0C10001F + (uj << 16); */
+                       ddr3_write_ctrl_pup_reg(1, pup, CNTRL_PUP_DESKEW + pup,
+                                               0x1F);
+               }
+       }
+
+       /* Set Output buffer-off to all CS and correct ODT values */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       reg = reg_read(REG_DDR3_MR1_ADDR) &
+                               REG_DDR3_MR1_ODT_MASK;
+                       reg |= odt_static[dram_info->cs_ena][cs];
+                       reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
+
+                       /* 0x15D0 - DDR3 MR0 Register */
+                       reg_write(REG_DDR3_MR1_ADDR, reg);
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR1 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       udelay(MRS_DELAY);
+               }
+       }
+
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling - Qoff and RTT Values are set for all Cs\n");
+
+       /* Enable SW override */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
+               (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* [0] = 1 - Enable SW override  */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling - SW Override Enabled\n");
+
+       /* Enable PHY write leveling mode */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
+               ~(1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
+       /* [2] = 0 - TrnWLMode - Enable */
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       /* Loop for each cs */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       DEBUG_WL_FULL_C("DDR3 - Write Leveling - Starting working with Cs - ",
+                                       (u32) cs, 1);
+
+                       /* Refresh X9 current cs */
+                       DEBUG_WL_FULL_S("DDR3 - Write Leveling - Refresh X9\n");
+                       for (cnt = 0; cnt < COUNT_WL_RFRS; cnt++) {
+                               reg =
+                                   REG_SDRAM_OPERATION_CMD_RFRS & ~(1 <<
+                                                                    (REG_SDRAM_OPERATION_CS_OFFS
+                                                                     + cs));
+                               /* [3-0] = 0x2 - refresh, [11-8] - enable current cs */
+                               reg_write(REG_SDRAM_OPERATION_ADDR, reg);       /* 0x1418 - SDRAM Operation Register */
+
+                               do {
+                                       reg =
+                                           ((reg_read
+                                             (REG_SDRAM_OPERATION_ADDR)) &
+                                            REG_SDRAM_OPERATION_CMD_RFRS_DONE);
+                               } while (reg);  /* Wait for '0' */
+                       }
+
+                       /*
+                        * Configure MR1 in Cs[CsNum] - write leveling on,
+                        * output buffer on
+                        */
+                       DEBUG_WL_FULL_S("DDR3 - Write Leveling - Configure MR1 for current Cs: WL-on,OB-on\n");
+                       reg = reg_read(REG_DDR3_MR1_ADDR) &
+                               REG_DDR3_MR1_OUTBUF_WL_MASK;
+                       /* Set ODT Values */
+                       reg &= REG_DDR3_MR1_ODT_MASK;
+                       reg |= odt_static[dram_info->cs_ena][cs];
+                       /* Enable WL MODE */
+                       reg |= (1 << REG_DDR3_MR1_WL_ENA_OFFS);
+                       /*
+                        * [7]=1, [12]=0 - Output Buffer and write leveling
+                        * enabled
+                        */
+                       /* 0x15D4 - DDR3 MR1 Register */
+                       reg_write(REG_DDR3_MR1_ADDR, reg);
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR1 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       udelay(MRS_DELAY);
+
+                       /* Write leveling  cs[cs] */
+                       if (MV_OK !=
+                           ddr3_write_leveling_single_cs(cs, freq, ratio_2to1,
+                                                         (u32 *)(res + cs),
+                                                         dram_info)) {
+                               DEBUG_WL_FULL_C("DDR3 - Write Leveling single Cs - FAILED -  Cs - ",
+                                               (u32) cs, 1);
+                               return MV_FAIL;
+                       }
+
+                       /* Set TrnWLDeUpd - After each CS is done */
+                       reg = reg_read(REG_TRAINING_WL_ADDR) |
+                               (1 << REG_TRAINING_WL_CS_DONE_OFFS);
+                       /* 0x16AC - Training Write leveling register */
+                       reg_write(REG_TRAINING_WL_ADDR, reg);
+
+                       /*
+                        * Debug message - Finished Write leveling cs[cs] -
+                        * each PUP Fail/Success
+                        */
+                       DEBUG_WL_FULL_C("DDR3 - Write Leveling - Finished Cs - ", (u32) cs,
+                                       1);
+                       DEBUG_WL_FULL_C("DDR3 - Write Leveling - The Results: 1-PUP locked, 0-PUP failed -",
+                                       (u32) res[cs], 3);
+
+                       /* Configure MR1 in cs[cs] - write leveling off (0), output buffer off (1) */
+                       reg = reg_read(REG_DDR3_MR1_ADDR) &
+                               REG_DDR3_MR1_OUTBUF_WL_MASK;
+                       reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
+                       /* No need to sort ODT since it is same CS */
+                       /* 0x15D4 - DDR3 MR1 Register */
+                       reg_write(REG_DDR3_MR1_ADDR, reg);
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR1 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       udelay(MRS_DELAY);
+               }
+       }
+
+       /* Disable WL Mode */
+       /* [2]=1 - TrnWLMode - Disable */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg |= (1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       /* Disable SW override - Must be in a different stage */
+       /* [0]=0 - Enable SW override  */
+       reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
+       reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
+       /* 0x15B8 - Training SW 2 Register */
+       reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
+
+       /* Set Output buffer-on to all CS and correct ODT values */
+       for (cs = 0; cs < MAX_CS; cs++) {
+               if (dram_info->cs_ena & (1 << cs)) {
+                       reg = reg_read(REG_DDR3_MR1_ADDR) &
+                               REG_DDR3_MR1_ODT_MASK;
+                       reg &= REG_DDR3_MR1_OUTBUF_WL_MASK;
+                       reg |= odt_static[dram_info->cs_ena][cs];
+
+                       /* 0x15D0 - DDR3 MR1 Register */
+                       reg_write(REG_DDR3_MR1_ADDR, reg);
+                       /* Issue MRS Command to current cs */
+                       reg = REG_SDRAM_OPERATION_CMD_MR1 &
+                               ~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
+                       /*
+                        * [3-0] = 0x4 - MR1 Command, [11-8] -
+                        * enable current cs
+                        */
+                       /* 0x1418 - SDRAM Operation Register */
+                       reg_write(REG_SDRAM_OPERATION_ADDR, reg);
+
+                       udelay(MRS_DELAY);
+               }
+       }
+
+#ifdef MV88F67XX
+       /* Dynamic pad issue (BTS669) during WL */
+       if (dpde_flag) {
+               reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
+                       (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
+               reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
+       }
+#endif
+
+       /* If target freq = 400 move clock back */
+       /* Write to control PUP to Control Deskew Regs */
+       if (freq <= DDR_400) {
+               for (pup = 0; pup <= dram_info->num_of_total_pups; pup++) {
+                       ddr3_write_ctrl_pup_reg(1, pup, CNTRL_PUP_DESKEW + pup,
+                                               0);
+               }
+       }
+
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling - Finished WL procedure for all Cs\n");
+       return MV_OK;
+}
+#endif
+
+/*
+ * Name:     ddr3_write_leveling_single_cs
+ * Desc:     Execute Write leveling for single Chip select
+ * Args:     cs          - current chip select
+ *           freq        - current sequence frequency
+ *           result      - res array
+ *           dram_info   - main struct
+ * Notes:
+ * Returns:  MV_OK if success, MV_FAIL if fail.
+ */
+static int ddr3_write_leveling_single_cs(u32 cs, u32 freq, int ratio_2to1,
+                                        u32 *result, MV_DRAM_INFO *dram_info)
+{
+       u32 reg, pup_num, delay, phase, phaseMax, max_pup_num, pup,
+               max_pup_mask;
+
+       max_pup_num = dram_info->num_of_total_pups;
+       *result = 0;
+       u32 flag[MAX_PUP_NUM] = { 0 };
+
+       DEBUG_WL_FULL_C("DDR3 - Write Leveling Single Cs - WL for Cs - ",
+                       (u32) cs, 1);
+
+       switch (max_pup_num) {
+       case 2:
+               max_pup_mask = 0x3;
+               break;
+       case 4:
+               max_pup_mask = 0xf;
+               DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
+               break;
+       case 5:
+               max_pup_mask = 0x1f;
+               DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
+               break;
+       case 8:
+               max_pup_mask = 0xff;
+               DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
+               break;
+       case 9:
+               max_pup_mask = 0x1ff;
+               DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
+               break;
+       default:
+               DEBUG_WL_C("ddr3_write_leveling_single_cs wrong max_pup_num =  ",
+                          max_pup_num, 3);
+               return MV_FAIL;
+       }
+
+       /* CS ODT Override */
+       reg = reg_read(REG_SDRAM_ODT_CTRL_HIGH_ADDR) &
+               REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK;
+       reg |= (REG_SDRAM_ODT_CTRL_HIGH_OVRD_ENA << (2 * cs));
+       /* Set 0x3 - Enable ODT on the curent cs and disable on other cs */
+       /* 0x1498 - SDRAM ODT Control high */
+       reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, reg);
+
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - ODT Asserted for current Cs\n");
+
+       /* tWLMRD Delay */
+       /* Delay of minimum 40 Dram clock cycles - 20 Tclk cycles */
+       udelay(1);
+
+       /* [1:0] - current cs number */
+       reg = (reg_read(REG_TRAINING_WL_ADDR) & REG_TRAINING_WL_CS_MASK) | cs;
+       reg |= (1 << REG_TRAINING_WL_UPD_OFFS); /* [2] - trnWLCsUpd */
+       /* 0x16AC - Training Write leveling register */
+       reg_write(REG_TRAINING_WL_ADDR, reg);
+
+       /* Broadcast to all PUPs: Reset DQS phase, reset leveling delay */
+       ddr3_write_pup_reg(PUP_WL_MODE, cs, PUP_BC, 0, 0);
+
+       /* Seek Edge */
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge - Current Cs\n");
+
+       /* Drive DQS high for one cycle - All data PUPs */
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge - Driving DQS high for one cycle\n");
+       if (!ratio_2to1) {
+               reg = (reg_read(REG_TRAINING_WL_ADDR) &
+                      REG_TRAINING_WL_RATIO_MASK) | REG_TRAINING_WL_1TO1;
+       } else {
+               reg = (reg_read(REG_TRAINING_WL_ADDR) &
+                      REG_TRAINING_WL_RATIO_MASK) | REG_TRAINING_WL_2TO1;
+       }
+       /* 0x16AC - Training Write leveling register */
+       reg_write(REG_TRAINING_WL_ADDR, reg);
+
+       /* Wait tWLdelay */
+       do {
+               /* [29] - trnWLDelayExp */
+               reg = (reg_read(REG_TRAINING_WL_ADDR)) &
+                       REG_TRAINING_WL_DELAYEXP_MASK;
+       } while (reg == 0x0);   /* Wait for '1' */
+
+       /* Read WL res */
+       reg = (reg_read(REG_TRAINING_WL_ADDR) >> REG_TRAINING_WL_RESULTS_OFFS) &
+               REG_TRAINING_WL_RESULTS_MASK;
+       /* [28:20] - TrnWLResult */
+
+       if (!ratio_2to1) /* Different phase options for 2:1 or 1:1 modes */
+               phaseMax = MAX_PHASE_1TO1;
+       else
+               phaseMax = MAX_PHASE_2TO1;
+
+       DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge - Shift DQS + Octet Leveling\n");
+
+       /* Shift DQS + Octet leveling */
+       for (phase = 0; phase < phaseMax; phase++) {
+               for (delay = 0; delay < MAX_DELAY; delay++) {
+                       /*  Broadcast to all PUPs: DQS phase,leveling delay */
+                       ddr3_write_pup_reg(PUP_WL_MODE, cs, PUP_BC, phase,
+                                          delay);
+
+                       udelay(1);      /* Delay of  3 Tclk cycles */
+
+                       DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge: Phase = ");
+                       DEBUG_WL_FULL_D((u32) phase, 1);
+                       DEBUG_WL_FULL_S(", Delay = ");
+                       DEBUG_WL_FULL_D((u32) delay, 1);
+                       DEBUG_WL_FULL_S(", Counter = ");
+                       DEBUG_WL_FULL_D((u32) i, 1);
+                       DEBUG_WL_FULL_S("\n");
+
+                       /* Drive DQS high for one cycle - All data PUPs */
+                       if (!ratio_2to1) {
+                               reg = (reg_read(REG_TRAINING_WL_ADDR) &
+                                      REG_TRAINING_WL_RATIO_MASK) |
+                                       REG_TRAINING_WL_1TO1;
+                       } else {
+                               reg = (reg_read(REG_TRAINING_WL_ADDR) &
+                                      REG_TRAINING_WL_RATIO_MASK) |
+                                       REG_TRAINING_WL_2TO1;
+                       }
+                       reg_write(REG_TRAINING_WL_ADDR, reg);   /* 0x16AC  */
+
+                       /* Wait tWLdelay */
+                       do {
+                               reg = (reg_read(REG_TRAINING_WL_ADDR)) &
+                                       REG_TRAINING_WL_DELAYEXP_MASK;
+                       } while (reg == 0x0);   /* [29] Wait for '1' */
+
+                       /* Read WL res */
+                       reg = reg_read(REG_TRAINING_WL_ADDR);
+                       reg = (reg >> REG_TRAINING_WL_RESULTS_OFFS) &
+                               REG_TRAINING_WL_RESULTS_MASK;   /* [28:20] */
+
+                       DEBUG_WL_FULL_C("DDR3 - Write Leveling Single Cs - Seek Edge: Results =  ",
+                                       (u32) reg, 3);
+
+                       /* Update State machine */
+                       for (pup = 0; pup < (max_pup_num); pup++) {
+                               /* ECC support - bit 8 */
+                               pup_num = (pup == dram_info->num_of_std_pups) ?
+                                       ECC_BIT : pup;
+                               if (dram_info->wl_val[cs][pup][S] == 0) {
+                                       /* Update phase to PUP */
+                                       dram_info->wl_val[cs][pup][P] = phase;
+                                       /* Update delay to PUP */
+                                       dram_info->wl_val[cs][pup][D] = delay;
+                               }
+
+                               if (((reg >> pup_num) & 0x1) == 0)
+                                       flag[pup_num] = 1;
+
+                               if (((reg >> pup_num) & 0x1)
+                                   && (flag[pup_num] == 1)
+                                   && (dram_info->wl_val[cs][pup][S] == 0)) {
+                                       /*
+                                        * If the PUP is locked now and in last
+                                        * counter states
+                                        */
+                                       /* Go to next state */
+                                       dram_info->wl_val[cs][pup][S] = 1;
+                                       /* Set res */
+                                       *result = *result | (1 << pup_num);
+                               }
+                       }
+
+                       /* If all locked - Break the loops - Finished */
+                       if (*result == max_pup_mask) {
+                               phase = phaseMax;
+                               delay = MAX_DELAY;
+                               DEBUG_WL_S("DDR3 - Write Leveling Single Cs - Seek Edge: All Locked\n");
+                       }
+               }
+       }
+
+       /* Debug message - Print res for cs[i]: cs,PUP,Phase,Delay */
+       DEBUG_WL_C("DDR3 - Write Leveling - Results for CS - ", (u32) cs, 1);
+       for (pup = 0; pup < (max_pup_num); pup++) {
+               DEBUG_WL_S("DDR3 - Write Leveling - PUP: ");
+               DEBUG_WL_D((u32) pup, 1);
+               DEBUG_WL_S(", Phase: ");
+               DEBUG_WL_D((u32) dram_info->wl_val[cs][pup][P], 1);
+               DEBUG_WL_S(", Delay: ");
+               DEBUG_WL_D((u32) dram_info->wl_val[cs][pup][D], 2);
+               DEBUG_WL_S("\n");
+       }
+
+       /* Check if some not locked and return error */
+       if (*result != max_pup_mask) {
+               DEBUG_WL_S("DDR3 - Write Leveling - ERROR - not all PUPS were locked\n");
+               return MV_FAIL;
+       }
+
+       /* Configure Each PUP with locked leveling settings */
+       for (pup = 0; pup < (max_pup_num); pup++) {
+               /* ECC support - bit 8 */
+               pup_num = (pup == dram_info->num_of_std_pups) ? ECC_BIT : pup;
+               phase = dram_info->wl_val[cs][pup][P];
+               delay = dram_info->wl_val[cs][pup][D];
+               ddr3_write_pup_reg(PUP_WL_MODE, cs, pup_num, phase, delay);
+       }
+
+       /* CS ODT Override */
+       reg =  reg_read(REG_SDRAM_ODT_CTRL_HIGH_ADDR) &
+               REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK;
+       /* 0x1498 - SDRAM ODT Control high */
+       reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, reg);
+
+       return MV_OK;
+}
+
+/*
+ * Perform DDR3 Control PUP Indirect Write
+ */
+static void ddr3_write_ctrl_pup_reg(int bc_acc, u32 pup, u32 reg_addr, u32 data)
+{
+       u32 reg = 0;
+
+       /* Store value for write */
+       reg = (data & 0xFFFF);
+
+       /* Set bit 26 for control PHY access */
+       reg |= (1 << REG_PHY_CNTRL_OFFS);
+
+       /* Configure BC or UC access to PHYs */
+       if (bc_acc == 1)
+               reg |= (1 << REG_PHY_BC_OFFS);
+       else
+               reg |= (pup << REG_PHY_PUP_OFFS);
+
+       /* Set PHY register address to write to */
+       reg |= (reg_addr << REG_PHY_CS_OFFS);
+
+       reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);      /* 0x16A0 */
+       reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
+       reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);      /* 0x16A0 */
+
+       do {
+               reg = (reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR)) &
+                       REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
+       } while (reg);          /* Wait for '0' to mark the end of the transaction */
+}
diff --git a/drivers/ddr/mvebu/xor.c b/drivers/ddr/mvebu/xor.c
new file mode 100644 (file)
index 0000000..66c96ae
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "xor.h"
+#include "xor_regs.h"
+
+static u32 xor_regs_ctrl_backup;
+static u32 xor_regs_base_backup[MAX_CS];
+static u32 xor_regs_mask_backup[MAX_CS];
+
+static void mv_xor_hal_init(u32 chan_num);
+static int mv_xor_cmd_set(u32 chan, int command);
+static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl);
+
+void mv_sys_xor_init(MV_DRAM_INFO *dram_info)
+{
+       u32 reg, ui, base, cs_count;
+
+       xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0));
+       for (ui = 0; ui < MAX_CS; ui++)
+               xor_regs_base_backup[ui] = reg_read(XOR_BASE_ADDR_REG(0, ui));
+       for (ui = 0; ui < MAX_CS; ui++)
+               xor_regs_mask_backup[ui] = reg_read(XOR_SIZE_MASK_REG(0, ui));
+
+       reg = 0;
+       for (ui = 0; ui < (dram_info->num_cs + 1); ui++) {
+               /* Enable Window x for each CS */
+               reg |= (0x1 << (ui));
+               /* Enable Window x for each CS */
+               reg |= (0x3 << ((ui * 2) + 16));
+       }
+
+       reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg);
+
+       /* Last window - Base - 0x40000000, Attribute 0x1E - SRAM */
+       base = (SRAM_BASE & 0xFFFF0000) | 0x1E00;
+       reg_write(XOR_BASE_ADDR_REG(0, dram_info->num_cs), base);
+       /* Last window - Size - 64 MB */
+       reg_write(XOR_SIZE_MASK_REG(0, dram_info->num_cs), 0x03FF0000);
+
+       cs_count = 0;
+       for (ui = 0; ui < MAX_CS; ui++) {
+               if (dram_info->cs_ena & (1 << ui)) {
+                       /*
+                        * Window x - Base - 0x00000000, Attribute 0x0E - DRAM
+                        */
+                       base = 0;
+                       switch (ui) {
+                       case 0:
+                               base |= 0xE00;
+                               break;
+                       case 1:
+                               base |= 0xD00;
+                               break;
+                       case 2:
+                               base |= 0xB00;
+                               break;
+                       case 3:
+                               base |= 0x700;
+                               break;
+                       }
+
+                       reg_write(XOR_BASE_ADDR_REG(0, cs_count), base);
+
+                       /* Window x - Size - 256 MB */
+                       reg_write(XOR_SIZE_MASK_REG(0, cs_count), 0x0FFF0000);
+                       cs_count++;
+               }
+       }
+
+       mv_xor_hal_init(1);
+
+       return;
+}
+
+void mv_sys_xor_finish(void)
+{
+       u32 ui;
+
+       reg_write(XOR_WINDOW_CTRL_REG(0, 0), xor_regs_ctrl_backup);
+       for (ui = 0; ui < MAX_CS; ui++)
+               reg_write(XOR_BASE_ADDR_REG(0, ui), xor_regs_base_backup[ui]);
+       for (ui = 0; ui < MAX_CS; ui++)
+               reg_write(XOR_SIZE_MASK_REG(0, ui), xor_regs_mask_backup[ui]);
+
+       reg_write(XOR_ADDR_OVRD_REG(0, 0), 0);
+}
+
+/*
+ * mv_xor_hal_init - Initialize XOR engine
+ *
+ * DESCRIPTION:
+ *               This function initialize XOR unit.
+ * INPUT:
+ *       None.
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+ */
+static void mv_xor_hal_init(u32 chan_num)
+{
+       u32 i;
+
+       /* Abort any XOR activity & set default configuration */
+       for (i = 0; i < chan_num; i++) {
+               mv_xor_cmd_set(i, MV_STOP);
+               mv_xor_ctrl_set(i, (1 << XEXCR_REG_ACC_PROTECT_OFFS) |
+                               (4 << XEXCR_DST_BURST_LIMIT_OFFS) |
+                               (4 << XEXCR_SRC_BURST_LIMIT_OFFS));
+       }
+}
+
+/*
+ * mv_xor_ctrl_set - Set XOR channel control registers
+ *
+ * DESCRIPTION:
+ *
+ * INPUT:
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+ * NOTE:
+ *    This function does not modify the OperationMode field of control register.
+ *
+ */
+static int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl)
+{
+       u32 val;
+
+       /* Update the XOR Engine [0..1] Configuration Registers (XExCR) */
+       val = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)))
+           & XEXCR_OPERATION_MODE_MASK;
+       xor_ctrl &= ~XEXCR_OPERATION_MODE_MASK;
+       xor_ctrl |= val;
+       reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xor_ctrl);
+
+       return MV_OK;
+}
+
+int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size, u32 init_val_high,
+                   u32 init_val_low)
+{
+       u32 tmp;
+
+       /* Parameter checking */
+       if (chan >= MV_XOR_MAX_CHAN)
+               return MV_BAD_PARAM;
+
+       if (MV_ACTIVE == mv_xor_state_get(chan))
+               return MV_BUSY;
+
+       if ((block_size < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
+           (block_size > XEXBSR_BLOCK_SIZE_MAX_VALUE))
+               return MV_BAD_PARAM;
+
+       /* Set the operation mode to Memory Init */
+       tmp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+       tmp &= ~XEXCR_OPERATION_MODE_MASK;
+       tmp |= XEXCR_OPERATION_MODE_MEM_INIT;
+       reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), tmp);
+
+       /*
+        * Update the start_ptr field in XOR Engine [0..1] Destination Pointer
+        * Register (XExDPR0)
+        */
+       reg_write(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), start_ptr);
+
+       /*
+        * Update the BlockSize field in the XOR Engine[0..1] Block Size
+        * Registers (XExBSR)
+        */
+       reg_write(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                 block_size);
+
+       /*
+        * Update the field InitValL in the XOR Engine Initial Value Register
+        * Low (XEIVRL)
+        */
+       reg_write(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), init_val_low);
+
+       /*
+        * Update the field InitValH in the XOR Engine Initial Value Register
+        * High (XEIVRH)
+        */
+       reg_write(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), init_val_high);
+
+       /* Start transfer */
+       reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                   XEXACTR_XESTART_MASK);
+
+       return MV_OK;
+}
+
+/*
+ * mv_xor_transfer - Transfer data from source to destination on one of
+ *                 three modes (XOR,CRC32,DMA)
+ *
+ * DESCRIPTION:
+ *       This function initiates XOR channel, according to function parameters,
+ *       in order to perform XOR or CRC32 or DMA transaction.
+ *       To gain maximum performance the user is asked to keep the following
+ *       restrictions:
+ *       1) Selected engine is available (not busy).
+ *       1) This module does not take into consideration CPU MMU issues.
+ *          In order for the XOR engine to access the appropreate source
+ *          and destination, address parameters must be given in system
+ *          physical mode.
+ *       2) This API does not take care of cache coherency issues. The source,
+ *          destination and in case of chain the descriptor list are assumed
+ *          to be cache coherent.
+ *       4) Parameters validity. For example, does size parameter exceeds
+ *          maximum byte count of descriptor mode (16M or 64K).
+ *
+ * INPUT:
+ *       chan          - XOR channel number. See MV_XOR_CHANNEL enumerator.
+ *       xor_type      - One of three: XOR, CRC32 and DMA operations.
+ *       xor_chain_ptr - address of chain pointer
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURS:
+ *       MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+ *
+ */
+int mv_xor_transfer(u32 chan, int xor_type, u32 xor_chain_ptr)
+{
+       u32 tmp;
+
+       /* Parameter checking */
+       if (chan >= MV_XOR_MAX_CHAN) {
+               debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
+               return MV_BAD_PARAM;
+       }
+
+       if (MV_ACTIVE == mv_xor_state_get(chan)) {
+               debug("%s: ERR. Channel is already active\n", __func__);
+               return MV_BUSY;
+       }
+
+       if (0x0 == xor_chain_ptr) {
+               debug("%s: ERR. xor_chain_ptr is NULL pointer\n", __func__);
+               return MV_BAD_PARAM;
+       }
+
+       /* Read configuration register and mask the operation mode field */
+       tmp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+       tmp &= ~XEXCR_OPERATION_MODE_MASK;
+
+       switch (xor_type) {
+       case MV_XOR:
+               if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_XOR_MASK)) {
+                       debug("%s: ERR. Invalid chain pointer (bits [5:0] must be cleared)\n",
+                             __func__);
+                       return MV_BAD_PARAM;
+               }
+
+               /* Set the operation mode to XOR */
+               tmp |= XEXCR_OPERATION_MODE_XOR;
+               break;
+
+       case MV_DMA:
+               if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_DMA_MASK)) {
+                       debug("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
+                             __func__);
+                       return MV_BAD_PARAM;
+               }
+
+               /* Set the operation mode to DMA */
+               tmp |= XEXCR_OPERATION_MODE_DMA;
+               break;
+
+       case MV_CRC32:
+               if (0 != (xor_chain_ptr & XEXDPR_DST_PTR_CRC_MASK)) {
+                       debug("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
+                             __func__);
+                       return MV_BAD_PARAM;
+               }
+
+               /* Set the operation mode to CRC32 */
+               tmp |= XEXCR_OPERATION_MODE_CRC;
+               break;
+
+       default:
+               return MV_BAD_PARAM;
+       }
+
+       /* Write the operation mode to the register */
+       reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), tmp);
+
+       /*
+        * Update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor
+        * Pointer Register (XExNDPR)
+        */
+       reg_write(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                 xor_chain_ptr);
+
+       /* Start transfer */
+       reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                   XEXACTR_XESTART_MASK);
+
+       return MV_OK;
+}
+
+/*
+ * mv_xor_state_get - Get XOR channel state.
+ *
+ * DESCRIPTION:
+ *       XOR channel activity state can be active, idle, paused.
+ *       This function retrunes the channel activity state.
+ *
+ * INPUT:
+ *       chan     - the channel number
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       XOR_CHANNEL_IDLE    - If the engine is idle.
+ *       XOR_CHANNEL_ACTIVE  - If the engine is busy.
+ *       XOR_CHANNEL_PAUSED  - If the engine is paused.
+ *       MV_UNDEFINED_STATE  - If the engine state is undefind or there is no
+ *                             such engine
+ *
+ */
+int mv_xor_state_get(u32 chan)
+{
+       u32 state;
+
+       /* Parameter checking */
+       if (chan >= MV_XOR_MAX_CHAN) {
+               debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
+               return MV_UNDEFINED_STATE;
+       }
+
+       /* Read the current state */
+       state = reg_read(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+       state &= XEXACTR_XESTATUS_MASK;
+
+       /* Return the state */
+       switch (state) {
+       case XEXACTR_XESTATUS_IDLE:
+               return MV_IDLE;
+       case XEXACTR_XESTATUS_ACTIVE:
+               return MV_ACTIVE;
+       case XEXACTR_XESTATUS_PAUSED:
+               return MV_PAUSED;
+       }
+
+       return MV_UNDEFINED_STATE;
+}
+
+/*
+ * mv_xor_cmd_set - Set command of XOR channel
+ *
+ * DESCRIPTION:
+ *       XOR channel can be started, idle, paused and restarted.
+ *       Paused can be set only if channel is active.
+ *       Start can be set only if channel is idle or paused.
+ *       Restart can be set only if channel is paused.
+ *       Stop can be set only if channel is active.
+ *
+ * INPUT:
+ *       chan     - The channel number
+ *       command  - The command type (start, stop, restart, pause)
+ *
+ * OUTPUT:
+ *       None.
+ *
+ * RETURN:
+ *       MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on
+ *       undefind XOR engine mode
+ *
+ */
+static int mv_xor_cmd_set(u32 chan, int command)
+{
+       int state;
+
+       /* Parameter checking */
+       if (chan >= MV_XOR_MAX_CHAN) {
+               debug("%s: ERR. Invalid chan num %d\n", __func__, chan);
+               return MV_BAD_PARAM;
+       }
+
+       /* Get the current state */
+       state = mv_xor_state_get(chan);
+
+       /* Command is start and current state is idle */
+       if ((command == MV_START) && (state == MV_IDLE)) {
+               reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                           XEXACTR_XESTART_MASK);
+               return MV_OK;
+       }
+       /* Command is stop and current state is active */
+       else if ((command == MV_STOP) && (state == MV_ACTIVE)) {
+               reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                           XEXACTR_XESTOP_MASK);
+               return MV_OK;
+       }
+       /* Command is paused and current state is active */
+       else if ((command == MV_PAUSED) && (state == MV_ACTIVE)) {
+               reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                           XEXACTR_XEPAUSE_MASK);
+               return MV_OK;
+       }
+       /* Command is restart and current state is paused */
+       else if ((command == MV_RESTART) && (state == MV_PAUSED)) {
+               reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+                           XEXACTR_XERESTART_MASK);
+               return MV_OK;
+       }
+       /* Command is stop and current state is active */
+       else if ((command == MV_STOP) && (state == MV_IDLE))
+               return MV_OK;
+
+       /* Illegal command */
+       debug("%s: ERR. Illegal command\n", __func__);
+
+       return MV_BAD_PARAM;
+}
diff --git a/drivers/ddr/mvebu/xor.h b/drivers/ddr/mvebu/xor.h
new file mode 100644 (file)
index 0000000..3536487
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __XOR_H
+#define __XOR_H
+
+#include "ddr3_hw_training.h"
+
+#define MV_XOR_MAX_CHAN         4 /* total channels for all units together */
+
+/*
+ * This enumerator describes the type of functionality the XOR channel
+ * can have while using the same data structures.
+ */
+enum xor_type {
+       MV_XOR,         /* XOR channel functions as XOR accelerator     */
+       MV_DMA,         /* XOR channel functions as IDMA channel        */
+       MV_CRC32        /* XOR channel functions as CRC 32 calculator   */
+};
+
+/*
+ * This enumerator describes the set of commands that can be applied on
+ * an engine (e.g. IDMA, XOR). Appling a comman depends on the current
+ * status (see MV_STATE enumerator)
+ * Start can be applied only when status is IDLE
+ * Stop can be applied only when status is IDLE, ACTIVE or PAUSED
+ * Pause can be applied only when status is ACTIVE
+ * Restart can be applied only when status is PAUSED
+ */
+enum mv_command {
+       MV_START,               /* Start     */
+       MV_STOP,                /* Stop     */
+       MV_PAUSE,               /* Pause    */
+       MV_RESTART              /* Restart  */
+};
+
+/*
+ * This enumerator describes the set of state conditions.
+ * Moving from one state to other is stricted.
+ */
+enum mv_state {
+       MV_IDLE,
+       MV_ACTIVE,
+       MV_PAUSED,
+       MV_UNDEFINED_STATE
+};
+
+/* XOR descriptor structure for CRC and DMA descriptor */
+struct crc_dma_desc {
+       u32 status;             /* Successful descriptor execution indication */
+       u32 crc32_result;       /* Result of CRC-32 calculation */
+       u32 desc_cmd;           /* type of operation to be carried out on the data */
+       u32 next_desc_ptr;      /* Next descriptor address pointer */
+       u32 byte_cnt;           /* Size of source block part represented by the descriptor */
+       u32 dst_addr;           /* Destination Block address pointer (not used in CRC32 */
+       u32 src_addr0;          /* Mode: Source Block address pointer */
+       u32 src_addr1;          /* Mode: Source Block address pointer */
+} __packed;
+
+int mv_xor_state_get(u32 chan);
+void mv_sys_xor_init(MV_DRAM_INFO *dram_info);
+void mv_sys_xor_finish(void);
+int mv_xor_transfer(u32 chan, int xor_type, u32 xor_chain_ptr);
+int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size, u32 init_val_high,
+                   u32 init_val_low);
+
+#endif /* __XOR_H */
diff --git a/drivers/ddr/mvebu/xor_regs.h b/drivers/ddr/mvebu/xor_regs.h
new file mode 100644 (file)
index 0000000..884aa15
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef __XOR_REGS_H
+#define __XOR_REGS_H
+
+/*
+ * For controllers that have two XOR units, then chans 2 & 3 will be mapped
+ * to channels 0 & 1 of unit 1
+ */
+#define XOR_UNIT(chan)                 ((chan) >> 1)
+#define XOR_CHAN(chan)                 ((chan) & 1)
+
+#define MV_XOR_REGS_OFFSET(unit)       (0x60900)
+#define MV_XOR_REGS_BASE(unit)         (MV_XOR_REGS_OFFSET(unit))
+
+/* XOR Engine Control Register Map */
+#define XOR_CHANNEL_ARBITER_REG(unit)  (MV_XOR_REGS_BASE(unit))
+#define XOR_CONFIG_REG(unit, chan)     (MV_XOR_REGS_BASE(unit) + (0x10 + ((chan) * 4)))
+#define XOR_ACTIVATION_REG(unit, chan) (MV_XOR_REGS_BASE(unit) + (0x20 + ((chan) * 4)))
+
+/* XOR Engine Interrupt Register Map */
+#define XOR_CAUSE_REG(unit)            (MV_XOR_REGS_BASE(unit) + 0x30)
+#define XOR_MASK_REG(unit)             (MV_XOR_REGS_BASE(unit) + 0x40)
+#define XOR_ERROR_CAUSE_REG(unit)      (MV_XOR_REGS_BASE(unit) + 0x50)
+#define XOR_ERROR_ADDR_REG(unit)       (MV_XOR_REGS_BASE(unit) + 0x60)
+
+/* XOR Engine Descriptor Register Map */
+#define XOR_NEXT_DESC_PTR_REG(unit, chan)      (MV_XOR_REGS_BASE(unit) + (0x200 + ((chan) * 4)))
+#define XOR_CURR_DESC_PTR_REG(unit, chan)      (MV_XOR_REGS_BASE(unit) + (0x210 + ((chan) * 4)))
+#define XOR_BYTE_COUNT_REG(unit, chan)         (MV_XOR_REGS_BASE(unit) + (0x220 + ((chan) * 4)))
+
+#define XOR_DST_PTR_REG(unit, chan)            (MV_XOR_REGS_BASE(unit) + (0x2B0 + ((chan) * 4)))
+#define XOR_BLOCK_SIZE_REG(unit, chan)         (MV_XOR_REGS_BASE(unit) + (0x2C0 + ((chan) * 4)))
+#define XOR_TIMER_MODE_CTRL_REG(unit)          (MV_XOR_REGS_BASE(unit) + 0x2D0)
+#define XOR_TIMER_MODE_INIT_VAL_REG(unit)      (MV_XOR_REGS_BASE(unit) + 0x2D4)
+#define XOR_TIMER_MODE_CURR_VAL_REG(unit)      (MV_XOR_REGS_BASE(unit) + 0x2D8)
+#define XOR_INIT_VAL_LOW_REG(unit)             (MV_XOR_REGS_BASE(unit) + 0x2E0)
+#define XOR_INIT_VAL_HIGH_REG(unit)            (MV_XOR_REGS_BASE(unit) + 0x2E4)
+
+/* XOR register fileds */
+
+/* XOR Engine [0..1] Configuration Registers (XExCR) */
+#define XEXCR_OPERATION_MODE_OFFS      (0)
+#define XEXCR_OPERATION_MODE_MASK      (7 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_XOR       (0 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_CRC       (1 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_DMA       (2 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_ECC       (3 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_MEM_INIT  (4 << XEXCR_OPERATION_MODE_OFFS)
+
+#define XEXCR_SRC_BURST_LIMIT_OFFS     (4)
+#define XEXCR_SRC_BURST_LIMIT_MASK     (7 << XEXCR_SRC_BURST_LIMIT_OFFS)
+#define XEXCR_DST_BURST_LIMIT_OFFS     (8)
+#define XEXCR_DST_BURST_LIMIT_MASK     (7 << XEXCR_DST_BURST_LIMIT_OFFS)
+#define XEXCR_DRD_RES_SWP_OFFS         (12)
+#define XEXCR_DRD_RES_SWP_MASK         (1 << XEXCR_DRD_RES_SWP_OFFS)
+#define XEXCR_DWR_REQ_SWP_OFFS         (13)
+#define XEXCR_DWR_REQ_SWP_MASK         (1 << XEXCR_DWR_REQ_SWP_OFFS)
+#define XEXCR_DES_SWP_OFFS             (14)
+#define XEXCR_DES_SWP_MASK             (1 << XEXCR_DES_SWP_OFFS)
+#define XEXCR_REG_ACC_PROTECT_OFFS     (15)
+#define XEXCR_REG_ACC_PROTECT_MASK     (1 << XEXCR_REG_ACC_PROTECT_OFFS)
+
+/* XOR Engine [0..1] Activation Registers (XExACTR) */
+#define XEXACTR_XESTART_OFFS           (0)
+#define XEXACTR_XESTART_MASK           (1 << XEXACTR_XESTART_OFFS)
+#define XEXACTR_XESTOP_OFFS            (1)
+#define XEXACTR_XESTOP_MASK            (1 << XEXACTR_XESTOP_OFFS)
+#define XEXACTR_XEPAUSE_OFFS           (2)
+#define XEXACTR_XEPAUSE_MASK           (1 << XEXACTR_XEPAUSE_OFFS)
+#define XEXACTR_XERESTART_OFFS         (3)
+#define XEXACTR_XERESTART_MASK         (1 << XEXACTR_XERESTART_OFFS)
+#define XEXACTR_XESTATUS_OFFS          (4)
+#define XEXACTR_XESTATUS_MASK          (3 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_IDLE          (0 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_ACTIVE                (1 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_PAUSED                (2 << XEXACTR_XESTATUS_OFFS)
+
+/* XOR Engine [0..1] Destination Pointer Register (XExDPR0) */
+#define XEXDPR_DST_PTR_OFFS            (0)
+#define XEXDPR_DST_PTR_MASK            (0xFFFFFFFF << XEXDPR_DST_PTR_OFFS)
+#define XEXDPR_DST_PTR_XOR_MASK                (0x3F)
+#define XEXDPR_DST_PTR_DMA_MASK                (0x1F)
+#define XEXDPR_DST_PTR_CRC_MASK                (0x1F)
+
+/* XOR Engine[0..1] Block Size Registers (XExBSR) */
+#define XEXBSR_BLOCK_SIZE_OFFS         (0)
+#define XEXBSR_BLOCK_SIZE_MASK         (0xFFFFFFFF << XEXBSR_BLOCK_SIZE_OFFS)
+#define XEXBSR_BLOCK_SIZE_MIN_VALUE    (128)
+#define XEXBSR_BLOCK_SIZE_MAX_VALUE    (0xFFFFFFFF)
+
+/* XOR Engine Address Decoding Register Map */
+#define XOR_WINDOW_CTRL_REG(unit, chan)        (MV_XOR_REGS_BASE(unit) + (0x240 + ((chan) * 4)))
+#define XOR_BASE_ADDR_REG(unit, win)   (MV_XOR_REGS_BASE(unit) + (0x250 + ((win) * 4)))
+#define XOR_SIZE_MASK_REG(unit, win)   (MV_XOR_REGS_BASE(unit) + (0x270 + ((win) * 4)))
+#define XOR_HIGH_ADDR_REMAP_REG(unit, win) (MV_XOR_REGS_BASE(unit) + (0x290 + ((win) * 4)))
+#define XOR_ADDR_OVRD_REG(unit, win)   (MV_XOR_REGS_BASE(unit) + (0x2A0 + ((win) * 4)))
+
+#endif /* __XOR_REGS_H */
index 97c8f79fc7375706c07af06c752c424e196a083d..91294547f5cfe1314067a4e1dd8ffa394d0b6b29 100644 (file)
@@ -183,6 +183,7 @@ typedef void (interrupt_handler_t)(void *);
 /*
  * Function Prototypes
  */
+int dram_init(void);
 
 void   hang            (void) __attribute__ ((noreturn));
 
diff --git a/include/configs/arcangel4-be.h b/include/configs/arcangel4-be.h
deleted file mode 100644 (file)
index 76163ab..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier:    GPL-2.0+
- */
-
-#ifndef _CONFIG_ARCANGEL4_H_
-#define _CONFIG_ARCANGEL4_H_
-
-/*
- *  CPU configuration
- */
-#define CONFIG_SYS_BIG_ENDIAN
-#define CONFIG_ARC700
-#define CONFIG_ARC_MMU_VER             3
-#define CONFIG_SYS_CACHELINE_SIZE      64
-#define CONFIG_SYS_TIMER_RATE          CONFIG_SYS_CLK_FREQ
-
-/*
- * Board configuration
- */
-#define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_SKIP_LOWLEVEL_INIT      /* U-Boot is in RAM already */
-
-#define CONFIG_ARCH_EARLY_INIT_R
-
-/*
- * Memory configuration
- */
-#define CONFIG_SYS_TEXT_BASE           0x81000000
-#define CONFIG_SYS_MONITOR_BASE                CONFIG_SYS_TEXT_BASE
-
-#define CONFIG_SYS_DDR_SDRAM_BASE      0x80000000
-#define CONFIG_SYS_SDRAM_BASE          CONFIG_SYS_DDR_SDRAM_BASE
-#define CONFIG_SYS_SDRAM_SIZE          0x10000000      /* 256 Mb */
-
-#define CONFIG_SYS_INIT_SP_ADDR                \
-       (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
-
-#define CONFIG_SYS_MALLOC_LEN          0x200000        /* 2 MB */
-#define CONFIG_SYS_BOOTM_LEN           0x2000000       /* 32 MB */
-#define CONFIG_SYS_LOAD_ADDR           0x82000000
-
-#define CONFIG_SYS_NO_FLASH
-
-/*
- * UART configuration
- *
- */
-#define CONFIG_ARC_SERIAL
-#define CONFIG_ARC_UART_BASE           0xC0FC1000
-#define CONFIG_BAUDRATE                        115200
-
-/*
- * Command line configuration
- */
-#include <config_cmd_default.h>
-
-#define CONFIG_CMD_ELF
-
-#define CONFIG_OF_LIBFDT
-
-#define CONFIG_AUTO_COMPLETE
-#define CONFIG_SYS_MAXARGS             16
-
-/*
- * Environment settings
- */
-#define CONFIG_ENV_IS_NOWHERE
-#define CONFIG_ENV_SIZE                        0x00200         /* 512 bytes */
-#define CONFIG_ENV_OFFSET              0
-
-/*
- * Environment configuration
- */
-#define CONFIG_BOOTDELAY               3
-#define CONFIG_BOOTFILE                        "uImage"
-#define CONFIG_BOOTARGS                        "console=ttyARC0,115200n8"
-#define CONFIG_LOADADDR                        CONFIG_SYS_LOAD_ADDR
-
-/*
- * Console configuration
- */
-#define CONFIG_SYS_LONGHELP
-#define CONFIG_SYS_PROMPT              "arcangel4# "
-#define CONFIG_SYS_CBSIZE              256
-#define CONFIG_SYS_BARGSIZE            CONFIG_SYS_CBSIZE
-#define CONFIG_SYS_PBSIZE              (CONFIG_SYS_CBSIZE + \
-                                               sizeof(CONFIG_SYS_PROMPT) + 16)
-
-#endif /* _CONFIG_ARCANGEL4_H_ */
index 81934a45a8852282d20d653f826a528633e35450..5e4097fb82e1c9fcf665058c52f8f673e2237338 100644 (file)
 /*
  *  CPU configuration
  */
-#define CONFIG_ARC700
-#define CONFIG_ARC_MMU_VER             3
-#define CONFIG_SYS_CACHELINE_SIZE      64
 #define CONFIG_SYS_TIMER_RATE          CONFIG_SYS_CLK_FREQ
 
-/*
- * Board configuration
- */
-#define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_SKIP_LOWLEVEL_INIT      /* U-Boot is in RAM already */
-
-#define CONFIG_ARCH_EARLY_INIT_R
-
 /*
  * Memory configuration
  */
-#define CONFIG_SYS_TEXT_BASE           0x81000000
 #define CONFIG_SYS_MONITOR_BASE                CONFIG_SYS_TEXT_BASE
 
 #define CONFIG_SYS_DDR_SDRAM_BASE      0x80000000
index e6a08df4ba7de13082e4df476120b3743a5a6a51..3066fd030e4163e8798793a207515e1b2f5fe91b 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * (C) Copyright 2015
  * (C) Copyright 2014
  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
  *
@@ -24,8 +25,7 @@
 #include <asm/imx-common/gpio.h>
 
 #define CONFIG_MACH_TYPE       4501
-#define CONFIG_MMCROOT         "/dev/mmcblk0p2"
-#define CONFIG_DEFAULT_FDT_FILE        "aristainetos.dtb"
+#define CONFIG_MMCROOT         "/dev/mmcblk0p1"
 #define CONFIG_HOSTNAME                aristainetos
 #define PHYS_SDRAM_SIZE                (1u * 1024 * 1024 * 1024)
 
@@ -81,7 +81,6 @@
 #define CONFIG_SF_DEFAULT_SPEED                20000000
 #define CONFIG_SF_DEFAULT_MODE         SPI_MODE_0
 #define CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
-
 /* allow to overwrite serial and ethaddr */
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_CONS_INDEX              1
 #define CONFIG_SYS_TEXT_BASE           0x17800000
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
-       "uimage=uImage\0" \
-       "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \
-       "fdt_addr_r=0x11000000\0" \
-       "kernel_addr_r=0x12000000\0" \
-       "kernel_file=uImage\0" \
-       "boot_fdt=try\0" \
-       "ip_dyn=yes\0" \
+       "script=u-boot.scr\0" \
+       "fit_file=/boot/system.itb\0" \
+       "loadaddr=0x12000000\0" \
+       "fit_addr_r=0x14000000\0" \
+       "uboot=/boot/u-boot.imx\0" \
+       "uboot_sz=d0000\0" \
+       "rescue_sys_addr=f0000\0" \
+       "rescue_sys_length=f10000\0" \
+       "board_type=aristainetos7@1\0" \
+       "panel=lb07wv8\0" \
+       "splashpos=m,m\0" \
        "console=" CONFIG_CONSOLE_DEV "\0" \
        "fdt_high=0xffffffff\0"   \
        "initrd_high=0xffffffff\0" \
+       "mtdids=nand0=gpmi-nand,nor0=spi3.0\0" \
+       "mtdparts=mtdparts=spi3.0:832k(u-boot),64k(env),64k(env-red)," \
+               "-(rescue-system);gpmi-nand:-(ubi)\0" \
+       "addmisc=setenv bootargs ${bootargs} consoleblank=0\0" \
+       "addmtd=setenv bootargs ${bootargs} ${mtdparts}\0" \
+       "set_fit_default=fdt addr ${fit_addr_r};fdt set /configurations " \
+               "default ${board_type}\0" \
+       "get_env=mw ${loadaddr} 0 0x20000;" \
+               "mmc rescan;" \
+               "ext2load mmc ${mmcdev}:${mmcpart} ${loadaddr} env.txt;" \
+               "env import -t ${loadaddr}\0" \
+       "default_env=mw ${loadaddr} 0 0x20000;" \
+               "env export -t ${loadaddr} serial# ethaddr eth1addr " \
+               "board_type panel;" \
+               "env default -a;" \
+               "env import -t ${loadaddr}\0" \
+       "loadbootscript=" \
+               "ext2load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
+       "bootscript=echo Running bootscript from mmc ...; " \
+               "source\0" \
        "mmcpart=1\0" \
-       "mmcdev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) "\0" \
+       "mmcdev=0\0" \
        "mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \
        "mmcargs=setenv bootargs console=${console},${baudrate} " \
                "root=${mmcroot}\0" \
-       "loadimage=fatload mmc ${mmcdev}:${mmcpart} ${kernel_addr_r} " \
-               "${uimage}\0" \
-       "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} " \
-               "${fdt_file}\0" \
        "mmcboot=echo Booting from mmc ...; " \
-               "run mmcargs;run loadimage loadfdt fdt_setup;" \
-               "bootm ${kernel_addr_r} - ${fdt_addr_r};\0" \
-       "rootpath=/opt/eldk-5.5/armv7a-hf/rootfs-sato-sdk\0" \
-       "nfsopts=nfsvers=3 nolock rw\0" \
-       "netdev=eth0\0" \
-       "fdt_setup=fdt addr ${fdt_addr_r};fdt resize;fdt chosen;fdt board\0"\
-       "load_fdt=tftp ${fdt_addr_r} ${fdt_file}\0" \
-       "load_kernel=tftp ${kernel_addr_r} ${kernel_file}\0" \
-       "addmtd=setenv bootargs ${bootargs} ${mtdparts}\0" \
-       "get_env=mw ${loadaddr} 0x00000000 0x20000;" \
-               "tftp ${loadaddr} /tftpboot/aristainetos/env.txt;" \
-               "env import -t ${loadaddr}\0" \
-       "addmisc=setenv bootargs ${bootargs} maxcpus=1 loglevel=8\0" \
-       "bootargs_defaults=setenv bootargs ${console} ${mtdoops} " \
-               "${optargs}\0" \
-       "net_args=run bootargs_defaults;setenv bootargs ${bootargs} " \
-               "root=/dev/nfs nfsroot=${serverip}:${rootpath},${nfsopts} " \
-               "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:" \
-               "${hostname}:${netdev}:off\0" \
-       "net_nfs=run load_kernel load_fdt;run net_args addmtd addmisc;" \
-               "run fdt_setup;bootm ${kernel_addr_r} - ${fdt_addr_r}\0" \
-       "uboot=/tftpboot/aristainetos/u-boot.imx\0" \
-       "load_uboot=tftp ${loadaddr} ${uboot}\0" \
-       "uboot_sz=c0000\0" \
-       "upd_uboot=mw.b ${loadaddr} 0xff ${uboot_sz};" \
-               "mw.b 10200000 0x00 ${uboot_sz};" \
-               "run load_uboot;sf probe;sf erase 0 ${uboot_sz};" \
+               "run mmcargs addmtd addmisc set_fit_default;" \
+               "bootm ${fit_addr_r}\0" \
+       "mmc_load_fit=ext2load mmc ${mmcdev}:${mmcpart} ${fit_addr_r} " \
+               "${fit_file}\0" \
+       "mmc_load_uboot=ext2load mmc ${mmcdev}:${mmcpart} ${loadaddr} " \
+               "${uboot}\0" \
+       "mmc_upd_uboot=mw.b ${loadaddr} 0xff ${uboot_sz};" \
+               "setexpr cmp_buf ${loadaddr} + ${uboot_sz};" \
+               "setexpr uboot_maxsize ${uboot_sz} - 400;" \
+               "mw.b ${cmp_buf} 0x00 ${uboot_sz};" \
+               "run mmc_load_uboot;sf probe;sf erase 0 ${uboot_sz};" \
                "sf write ${loadaddr} 400 ${filesize};" \
-               "sf read 10200000 400 ${uboot_sz};" \
-               "cmp.b ${loadaddr} 10200000 bc000\0" \
-       "ubi_prep=ubi part ubi 2048;ubifsmount ubi:kernel\0" \
-       "load_kernel_ubi=ubifsload ${kernel_addr_r} uImage\0" \
-       "load_fdt_ubi=ubifsload ${fdt_addr_r} aristainetos.dtb\0" \
-       "ubi_nfs=run ubiprep load_kernel_ubi load_fdt_ubi;" \
-               "run net_args addmtd addmisc;run fdt_setup;" \
-               "bootm ${kernel_addr_r} - ${fdt_addr_r}\0" \
-       "rootfsname=rootfs\0" \
-       "ubi_args=run bootargs_defaults;setenv bootargs ${bootargs} " \
-               "ubi.mtd=0,2048 root=ubi0:${rootfsname} rootfstype=ubifs " \
-               "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:" \
-               "${hostname}:${netdev}:off\0" \
-       "ubi_ubi=run ubi_prep load_kernel_ubi load_fdt_ubi;" \
-               "run bootargs_defaults ubi_args addmtd addmisc;" \
-               "run fdt_setup;bootm ${kernel_addr_r} - ${fdt_addr_r}\0" \
-       "ubirootfs_file=/tftpboot/aristainetos/rootfs-minimal.ubifs\0" \
-       "upd_ubirootfs=run ubi_prep;tftp ${loadaddr} ${ubirootfs_file};" \
-               "ubi write ${loadaddr} rootfs ${filesize}\0" \
-       "ksz=800000\0" \
-       "rootsz=2000000\0" \
-       "usersz=8000000\0" \
-       "ubi_make=run ubi_prep;ubi create kernel ${ksz};" \
-               "ubi create rootfs ${rootsz};ubi create userfs ${usersz}\0"
+               "sf read ${cmp_buf} 400 ${uboot_sz};" \
+               "cmp.b ${loadaddr} ${cmp_buf} ${uboot_maxsize}\0" \
+       "ubiargs=setenv bootargs console=${console},${baudrate} " \
+               "ubi.mtd=0,2048 root=ubi0:rootfs rootfstype=ubifs\0 " \
+       "ubiboot=echo Booting from ubi ...; " \
+               "run ubiargs addmtd addmisc set_fit_default;" \
+               "bootm ${fit_addr_r}\0" \
+       "ubifs_load_fit=sf probe;ubi part ubi 2048;ubifsmount ubi:rootfs;" \
+               "ubifsload ${fit_addr_r} /boot/system.itb; " \
+               "imi ${fit_addr_r}\0 " \
+       "rescueargs=setenv bootargs console=${console},${baudrate} " \
+               "root=/dev/ram rw\0 " \
+       "rescueboot=echo Booting rescue system from NOR ...; " \
+               "run rescueargs addmtd addmisc set_fit_default;" \
+               "bootm ${fit_addr_r}\0" \
+       "rescue_load_fit=sf probe;sf read ${fit_addr_r} ${rescue_sys_addr} " \
+               "${rescue_sys_length}; imi ${fit_addr_r}\0 "
 
 #define CONFIG_BOOTCOMMAND \
        "mmc dev ${mmcdev};" \
        "if mmc rescan; then " \
-               "run mmcboot;" \
-       "else run ubi_ubi; fi"
+               "if run loadbootscript; then " \
+                       "run bootscript; " \
+               "else " \
+                       "if run mmc_load_fit; then " \
+                               "run mmcboot; " \
+                       "else " \
+                               "if run ubifs_load_fit; then " \
+                                       "run ubiboot; " \
+                               "else " \
+                                       "if run rescue_load_fit; then " \
+                                               "run rescueboot; " \
+                                       "else " \
+                                               "echo RESCUE SYSTEM BOOT " \
+                                                       "FAILURE;" \
+                                       "fi; " \
+                               "fi; " \
+                       "fi; " \
+               "fi; " \
+       "else " \
+               "if run ubifs_load_fit; then " \
+                       "run ubiboot; " \
+               "else " \
+                       "if run rescue_load_fit; then " \
+                               "run rescueboot; " \
+                       "else " \
+                               "echo RESCUE SYSTEM BOOT FAILURE;" \
+                       "fi; " \
+               "fi; " \
+       "fi"
 
 #define CONFIG_ARP_TIMEOUT             200UL
 
 #define CONFIG_ENV_SPI_MAX_HZ          CONFIG_SF_DEFAULT_SPEED
 #define CONFIG_ENV_SPI_MODE            CONFIG_SF_DEFAULT_MODE
 #define CONFIG_ENV_SECT_SIZE           (0x010000)
-#define CONFIG_ENV_OFFSET              (0x0c0000)
-#define CONFIG_ENV_OFFSET_REDUND       (0x0d0000)
+#define CONFIG_ENV_OFFSET              (0x0d0000)
+#define CONFIG_ENV_OFFSET_REDUND       (0x0e0000)
 
 #define CONFIG_OF_LIBFDT
 
 #define CONFIG_CMD_UBI
 #define CONFIG_CMD_UBIFS
 
-#define MTDIDS_DEFAULT                  "nand0=gpmi-nand"
-#define MTDPARTS_DEFAULT                "mtdparts=gpmi-nand:-(ubi)"
-
 #define CONFIG_MTD_UBI_FASTMAP
 #define CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT     1
 
 
 #define CONFIG_PWM_IMX
 #define CONFIG_IMX6_PWM_PER_CLK        66000000
-
 #endif                         /* __ARISTAINETOS_CONFIG_H */
index c61ddd6fb77c46560d82dc6a1a1e4b9216fab1d8..5fb8aca4bca95f3fa307407649e2d084b65ff2af 100644 (file)
 /*
  *  CPU configuration
  */
-#define CONFIG_ARC700
-#define CONFIG_ARC_MMU_VER             3
-#define CONFIG_SYS_CACHELINE_SIZE      32
 #define CONFIG_SYS_TIMER_RATE          CONFIG_SYS_CLK_FREQ
 
-/* NAND controller DMA doesn't work correctly with D$ enabled */
-#define CONFIG_SYS_DCACHE_OFF
-
-/*
- * Board configuration
- */
-#define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_SKIP_LOWLEVEL_INIT      /* U-Boot is in RAM already */
-
-#define CONFIG_ARCH_EARLY_INIT_R
-
 #define ARC_FPGA_PERIPHERAL_BASE       0xE0000000
 #define ARC_APB_PERIPHERAL_BASE                0xF0000000
 #define ARC_DWMMC_BASE                 (ARC_FPGA_PERIPHERAL_BASE + 0x15000)
@@ -34,7 +20,6 @@
 /*
  * Memory configuration
  */
-#define CONFIG_SYS_TEXT_BASE           0x81000000
 #define CONFIG_SYS_MONITOR_BASE                CONFIG_SYS_TEXT_BASE
 
 #define CONFIG_SYS_DDR_SDRAM_BASE      0x80000000
index f7277eb1d17a0d5f3a4c613d6033bd682c3491dd..1f6449505511c1f6001a8d5bbe846e8d827145cc 100644 (file)
 #define CONFIG_ENV_OFFSET              (768 * 1024)
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
-       "kernel=uImage-cm-fx6\0" \
+       "stdin=serial,usbkbd\0" \
+       "stdout=serial,vga\0" \
+       "stderr=serial,vga\0" \
+       "panel=HDMI\0" \
        "autoload=no\0" \
+       "kernel=uImage-cm-fx6\0" \
+       "script=boot.scr\0" \
+       "dtb=cm-fx6.dtb\0" \
+       "bootm_low=18000000\0" \
        "loadaddr=0x10800000\0" \
        "fdtaddr=0x11000000\0" \
        "console=ttymxc3,115200\0" \
        "ethprime=FEC0\0" \
-       "bootscr=boot.scr\0" \
-       "bootm_low=18000000\0" \
        "video_hdmi=mxcfb0:dev=hdmi,1920x1080M-32@50,if=RGB32\0" \
        "video_dvi=mxcfb0:dev=dvi,1280x800M-32@50,if=RGB32\0" \
-       "fdtfile=cm-fx6.dtb\0" \
        "doboot=bootm ${loadaddr}\0" \
-       "loadfdt=false\0" \
+       "doloadfdt=false\0" \
        "setboottypez=setenv kernel zImage-cm-fx6;" \
                "setenv doboot bootz ${loadaddr} - ${fdtaddr};" \
-               "setenv loadfdt true;\0" \
+               "setenv doloadfdt true;\0" \
        "setboottypem=setenv kernel uImage-cm-fx6;" \
                "setenv doboot bootm ${loadaddr};" \
-               "setenv loadfdt false;\0"\
-       "run_eboot=echo Starting EBOOT ...; "\
-               "mmc dev ${mmcdev} && " \
-               "mmc rescan && mmc read 10042000 a 400 && go 10042000\0" \
-       "mmcdev=2\0" \
+               "setenv doloadfdt false;\0"\
        "mmcroot=/dev/mmcblk0p2 rw rootwait\0" \
-       "loadmmcbootscript=load mmc ${mmcdev} ${loadaddr} ${bootscr}\0" \
-       "mmcbootscript=echo Running bootscript from mmc ...; "\
-               "source ${loadaddr}\0" \
-       "mmcargs=setenv bootargs console=${console} " \
-               "root=${mmcroot} " \
-               "${video}\0" \
-       "mmcloadkernel=load mmc ${mmcdev} ${loadaddr} ${kernel}\0" \
-       "mmcloadfdt=load mmc ${mmcdev} ${fdtaddr} ${fdtfile}\0" \
-       "mmcboot=echo Booting from mmc ...; " \
-               "run mmcargs; " \
-               "run doboot\0" \
-       "satadev=0\0" \
        "sataroot=/dev/sda2 rw rootwait\0" \
-       "sataargs=setenv bootargs console=${console} " \
-               "root=${sataroot} " \
-               "${video}\0" \
-       "loadsatabootscript=load sata ${satadev} ${loadaddr} ${bootscr}\0" \
-       "satabootscript=echo Running bootscript from sata ...; " \
-               "source ${loadaddr}\0" \
-       "sataloadkernel=load sata ${satadev} ${loadaddr} ${kernel}\0" \
-       "sataloadfdt=load sata ${satadev} ${fdtaddr} ${fdtfile}\0" \
-       "sataboot=echo Booting from sata ...; "\
-               "run sataargs; " \
-               "run doboot\0" \
        "nandroot=/dev/mtdblock4 rw\0" \
        "nandrootfstype=ubifs\0" \
+       "mmcargs=setenv bootargs console=${console} root=${mmcroot} " \
+               "${video}\0" \
+       "sataargs=setenv bootargs console=${console} root=${sataroot} " \
+               "${video}\0" \
        "nandargs=setenv bootargs console=${console} " \
                "root=${nandroot} " \
                "rootfstype=${nandrootfstype} " \
                "${video}\0" \
-       "nandloadfdt=nand read ${fdtaddr} 780000 80000;\0" \
-       "nandboot=echo Booting from nand ...; " \
-               "run nandargs; " \
-               "nand read ${loadaddr} 0 780000; " \
-               "if ${loadfdt}; then " \
+       "nandboot=if run nandloadkernel; then " \
                        "run nandloadfdt;" \
-               "fi; " \
-               "run doboot\0" \
-       "boot=mmc dev ${mmcdev}; " \
-               "if mmc rescan; then " \
-                       "if run loadmmcbootscript; then " \
-                               "run mmcbootscript;" \
-                       "else " \
-                               "if run mmcloadkernel; then " \
-                                       "if ${loadfdt}; then " \
-                                               "run mmcloadfdt;" \
-                                       "fi;" \
-                                       "run mmcboot;" \
-                               "fi;" \
-                       "fi;" \
+                       "run setboottypem;" \
+                       "run storagebootcmd;" \
+                       "run setboottypez;" \
+                       "run storagebootcmd;" \
+               "fi;\0" \
+       "run_eboot=echo Starting EBOOT ...; "\
+               "mmc dev 2 && " \
+               "mmc rescan && mmc read 10042000 a 400 && go 10042000\0" \
+       "loadscript=load ${storagetype} ${storagedev} ${loadaddr} ${script};\0"\
+       "loadkernel=load ${storagetype} ${storagedev} ${loadaddr} ${kernel};\0"\
+       "loadfdt=load ${storagetype} ${storagedev} ${fdtaddr} ${dtb};\0" \
+       "bootscript=echo Running bootscript from ${storagetype} ...;" \
+                  "source ${loadaddr};\0" \
+       "nandloadkernel=nand read ${loadaddr} 0 780000;\0" \
+       "nandloadfdt=nand read ${fdtaddr} 780000 80000;\0" \
+       "setupmmcboot=setenv storagetype mmc; setenv storagedev 2;\0" \
+       "setupsataboot=setenv storagetype sata; setenv storagedev 0;\0" \
+       "setupnandboot=setenv storagetype nand;\0" \
+       "setupusbboot=setenv storagetype usb; setenv storagedev 0;\0" \
+       "storagebootcmd=echo Booting from ${storagetype} ...;" \
+                       "run ${storagetype}args; run doboot;\0" \
+       "trybootk=if run loadkernel; then " \
+               "if ${doloadfdt}; then " \
+                       "run loadfdt;" \
                "fi;" \
-               "if sata init; then " \
-                       "if run loadsatabootscript; then " \
-                               "run satabootscript;" \
-                       "else "\
-                               "if run sataloadkernel; then " \
-                                       "if ${loadfdt}; then " \
-                                               "run sataloadfdt; " \
-                                       "fi;" \
-                                       "run sataboot;" \
-                               "fi;" \
-                       "fi;" \
+               "run storagebootcmd;" \
+               "fi;\0" \
+       "trybootsmz=if run loadscript; then " \
+                       "run bootscript;" \
                "fi;" \
-               "run nandboot\0"
+               "run setboottypem;" \
+               "run trybootk;" \
+               "run setboottypez;" \
+               "run trybootk;\0"
 
 #define CONFIG_BOOTCOMMAND \
-       "run setboottypem; run boot"
+       "run setupmmcboot;" \
+       "mmc dev ${storagedev};" \
+       "if mmc rescan; then " \
+               "run trybootsmz;" \
+       "fi;" \
+       "run setupusbboot;" \
+       "if usb start; then "\
+               "if run loadscript; then " \
+                       "run bootscript;" \
+               "fi;" \
+       "fi;" \
+       "run setupsataboot;" \
+       "if sata init; then " \
+               "run trybootsmz;" \
+       "fi;" \
+       "run setupnandboot;" \
+       "run nandboot;"
+
+#define CONFIG_PREBOOT         "usb start"
 
 /* SPI */
 #define CONFIG_SPI
 #define CONFIG_MXC_USB_FLAGS           0
 #define CONFIG_USB_MAX_CONTROLLER_COUNT        2
 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET       /* For OTG port */
+#define CONFIG_USB_KEYBOARD
+#define CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP
+#define CONFIG_SYS_STDIO_DEREGISTER
 
 /* I2C */
 #define CONFIG_CMD_I2C
 /* misc */
 #define CONFIG_SYS_GENERIC_BOARD
 #define CONFIG_STACKSIZE                       (128 * 1024)
-#define CONFIG_SYS_MALLOC_LEN                  (2 * 1024 * 1024)
+#define CONFIG_SYS_MALLOC_LEN                  (10 * 1024 * 1024)
 #define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS     800 /* 400 KB */
 #define CONFIG_OF_BOARD_SETUP
 
 #define CONFIG_SYS_SPI_U_BOOT_OFFS     (64 * 1024)
 #define CONFIG_SPL_SPI_LOAD
 
+/* Display */
+#define CONFIG_VIDEO
+#define CONFIG_VIDEO_IPUV3
+#define CONFIG_IPUV3_CLK          260000000
+#define CONFIG_IMX_HDMI
+#define CONFIG_IMX_VIDEO_SKIP
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_VIDEO_SW_CURSOR
+
+#define CONFIG_SPLASH_SCREEN
+#define CONFIG_SPLASH_SOURCE
+#define CONFIG_CMD_BMP
+#define CONFIG_VIDEO_BMP_RLE8
+
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_VIDEO_BMP_LOGO
+
 #endif /* __CONFIG_CM_FX6_H */
index 9767512a5cf03771a5008932433b417cdacfbe56..b2a9f35797093a7698b6e4db9464849962d51dbe 100644 (file)
 
 #define CONFIG_LCD
 #define CONFIG_SPLASH_SCREEN
+#define CONFIG_SPLASH_SOURCE
 #define CONFIG_CMD_BMP
 #define CONFIG_BMP_16BPP
 #define CONFIG_SCF0403_LCD
index cb03e33b6e133a71f6b5d962dae32abeaf981bdf..1683a1582f4e0dd7ea4299ef8f67bfc937d54fb5 100644 (file)
@@ -11,6 +11,8 @@
  * High Level Configuration Options (easy to change)
  */
 #define CONFIG_ARMADA_XP               /* SOC Family Name */
+#define CONFIG_DB_784MP_GP             /* Board target name for DDR training */
+
 #define CONFIG_SKIP_LOWLEVEL_INIT      /* disable board lowlevel_init */
 #define CONFIG_SYS_GENERIC_BOARD
 #define CONFIG_DISPLAY_BOARDINFO_LATE
  */
 #include "mv-common.h"
 
+/*
+ * Memory layout while starting into the bin_hdr via the
+ * BootROM:
+ *
+ * 0x4000.4000 - 0x4003.4000   headers space (192KiB)
+ * 0x4000.4030                 bin_hdr start address
+ * 0x4003.4000 - 0x4004.7c00   BootROM memory allocations (15KiB)
+ * 0x4007.fffc                 BootROM stack top
+ *
+ * The address space between 0x4007.fffc and 0x400f.fff is not locked in
+ * L2 cache thus cannot be used.
+ */
+
+/* SPL */
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE           0x40004030
+#define CONFIG_SPL_MAX_SIZE            ((128 << 10) - 0x4030)
+
+#define CONFIG_SPL_BSS_START_ADDR      (0x40000000 + (128 << 10))
+#define CONFIG_SPL_BSS_MAX_SIZE                (16 << 10)
+
+#define CONFIG_SYS_SPL_MALLOC_START    (CONFIG_SPL_BSS_START_ADDR + \
+                                        CONFIG_SPL_BSS_MAX_SIZE)
+#define CONFIG_SYS_SPL_MALLOC_SIZE     (16 << 10)
+
+#define CONFIG_SPL_STACK               (0x40000000 + ((192 - 16) << 10))
+#define CONFIG_SPL_BOOTROM_SAVE                (CONFIG_SPL_STACK + 4)
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+#define CONFIG_SPL_LDSCRIPT            "arch/arm/mvebu-common/u-boot-spl.lds"
+
+/* SPL related SPI defines */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_BUS             0
+#define CONFIG_SPL_SPI_CS              0
+#define CONFIG_SYS_SPI_U_BOOT_OFFS     0x20000
+
+/* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */
+#define CONFIG_SYS_MVEBU_DDR
+#define CONFIG_SPD_EEPROM              0x4e
+
 #endif /* _CONFIG_DB_MV7846MP_GP_H */
index 1b9c2773beb8240af44ca465d249f904ac1ae1b2..21c5dce0978fa49caf50fb849f0e14ab292b3a86 100644 (file)
 #define CONFIG_SPL_LIBDISK_SUPPORT
 #endif
 
+#if defined(CONFIG_MX6SX)
+#define CONFIG_SPL_BSS_START_ADDR      0x88200000
+#define CONFIG_SPL_BSS_MAX_SIZE        0x100000        /* 1 MB */
+#define CONFIG_SYS_SPL_MALLOC_START    0x88300000
+#define CONFIG_SYS_SPL_MALLOC_SIZE     0x3200000       /* 50 MB */
+#define CONFIG_SYS_TEXT_BASE           0x87800000
+#else
 #define CONFIG_SPL_BSS_START_ADDR      0x18200000
 #define CONFIG_SPL_BSS_MAX_SIZE                0x100000        /* 1 MB */
 #define CONFIG_SYS_SPL_MALLOC_START    0x18300000
 #define CONFIG_SYS_SPL_MALLOC_SIZE     0x3200000       /* 50 MB */
 #define CONFIG_SYS_TEXT_BASE           0x17800000
 #endif
+#endif
 
 #endif
index 72217bdb574b8c7f71206cb206abb36305414387..5999d6014678afe35743118a91238ed89db5b48b 100644 (file)
@@ -43,6 +43,8 @@
 #define CONFIG_SF_DEFAULT_SPEED                1000000
 #define CONFIG_SF_DEFAULT_MODE         SPI_MODE_3
 #define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SPI_FLASH_SPANSION
+#define CONFIG_SPI_FLASH_BAR
 
 /* Environment in SPI NOR flash */
 #define CONFIG_ENV_IS_IN_SPI_FLASH
  */
 #include "mv-common.h"
 
+/*
+ * Memory layout while starting into the bin_hdr via the
+ * BootROM:
+ *
+ * 0x4000.4000 - 0x4003.4000   headers space (192KiB)
+ * 0x4000.4030                 bin_hdr start address
+ * 0x4003.4000 - 0x4004.7c00   BootROM memory allocations (15KiB)
+ * 0x4007.fffc                 BootROM stack top
+ *
+ * The address space between 0x4007.fffc and 0x400f.fff is not locked in
+ * L2 cache thus cannot be used.
+ */
+
+/* SPL */
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE           0x40004030
+#define CONFIG_SPL_MAX_SIZE            ((128 << 10) - 0x4030)
+
+#define CONFIG_SPL_BSS_START_ADDR      (0x40000000 + (128 << 10))
+#define CONFIG_SPL_BSS_MAX_SIZE                (16 << 10)
+
+#define CONFIG_SYS_SPL_MALLOC_START    (CONFIG_SPL_BSS_START_ADDR + \
+                                        CONFIG_SPL_BSS_MAX_SIZE)
+#define CONFIG_SYS_SPL_MALLOC_SIZE     (16 << 10)
+
+#define CONFIG_SPL_STACK               (0x40000000 + ((192 - 16) << 10))
+#define CONFIG_SPL_BOOTROM_SAVE                (CONFIG_SPL_STACK + 4)
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+#define CONFIG_SPL_LDSCRIPT            "arch/arm/mvebu-common/u-boot-spl.lds"
+
+/* SPL related SPI defines */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_BUS             0
+#define CONFIG_SPL_SPI_CS              0
+#define CONFIG_SYS_SPI_U_BOOT_OFFS     0x20000
+
+/* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */
+#define CONFIG_SYS_MVEBU_DDR
+#define CONFIG_DDR_FIXED_SIZE          (1 << 20)       /* 1GiB */
+
 #endif /* _CONFIG_DB_MV7846MP_GP_H */
index bb070600021b4a7da9728aaaafd3c9ba132ddf5c..166ab4f05654e9e1a1a970989cb0be808c7e4c68 100644 (file)
 # define CONFIG_XILINX_TB_WATCHDOG
 #endif
 
-/*
- * memory layout - Example
- * CONFIG_SYS_TEXT_BASE = 0x1200_0000; defined in config.mk
- * CONFIG_SYS_SRAM_BASE = 0x1000_0000;
- * CONFIG_SYS_SRAM_SIZE = 0x0400_0000; 64MB
- *
- * CONFIG_SYS_MONITOR_LEN = 0x40000
- * CONFIG_SYS_MALLOC_LEN = 3 * CONFIG_SYS_MONITOR_LEN = 0xC0000
- *
- * CONFIG_SYS_GBL_DATA_OFFSET = 0x1000_0000 + 0x0400_0000 - 0x1000 = 0x13FF_F000
- * CONFIG_SYS_MONITOR_BASE = 0x13FF_F000 - CONFIG_SYS_MONITOR_LEN = 0x13FB_F000
- * CONFIG_SYS_MALLOC_BASE = 0x13FB_F000 - CONFIG_SYS_MALLOC_LEN = 0x13EF_F000
- *
- * 0x1000_0000 CONFIG_SYS_SDRAM_BASE
- *                                     MEMTEST_AREA     64kB
- *                                     FREE
- * 0x1200_0000 CONFIG_SYS_TEXT_BASE
- *             U-BOOT code
- * 0x1202_0000
- *                                     FREE
- *
- *                                     STACK
- * 0x13EF_F000 CONFIG_SYS_MALLOC_BASE
- *                                     MALLOC_AREA     768kB   Alloc
- * 0x13FB_F000 CONFIG_SYS_MONITOR_BASE
- *                                     MONITOR_CODE    256kB   Env
- * 0x13FF_F000 CONFIG_SYS_GBL_DATA_OFFSET
- *                                     GLOBAL_DATA     4kB     bd, gd
- * 0x1400_0000 CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE
- */
-
+#ifndef CONFIG_OF_CONTROL
 /* ddr sdram - main memory */
-#define        CONFIG_SYS_SDRAM_BASE           XILINX_RAM_START
-#define        CONFIG_SYS_SDRAM_SIZE           XILINX_RAM_SIZE
-#define        CONFIG_SYS_MEMTEST_START        CONFIG_SYS_SDRAM_BASE
-#define        CONFIG_SYS_MEMTEST_END          (CONFIG_SYS_SDRAM_BASE + 0x1000)
-
-/* global pointer */
-/* start of global data */
-#define        CONFIG_SYS_GBL_DATA_OFFSET \
-               (CONFIG_SYS_SDRAM_SIZE - GENERATED_GBL_DATA_SIZE)
-
-/* monitor code */
-#define        SIZE                            0x40000
-#define        CONFIG_SYS_MONITOR_LEN          SIZE
-#define        CONFIG_SYS_MONITOR_BASE \
-               (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET \
-                       - CONFIG_SYS_MONITOR_LEN - GENERATED_BD_INFO_SIZE)
-#define        CONFIG_SYS_MONITOR_END \
-                       (CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)
-#define        CONFIG_SYS_MALLOC_LEN           (SIZE * 3)
-#define        CONFIG_SYS_MALLOC_BASE \
-                       (CONFIG_SYS_MONITOR_BASE - CONFIG_SYS_MALLOC_LEN)
-
-/* stack */
-#define        CONFIG_SYS_INIT_SP_OFFSET       CONFIG_SYS_MALLOC_BASE
+# define CONFIG_SYS_SDRAM_BASE XILINX_RAM_START
+# define CONFIG_SYS_SDRAM_SIZE XILINX_RAM_SIZE
+#endif
+
+#define CONFIG_SYS_MALLOC_LEN  0xC0000
+#ifndef CONFIG_SPL_BUILD
+# define CONFIG_SYS_MALLOC_F_LEN       1024
+#else
+# define CONFIG_SYS_MALLOC_SIMPLE
+# define CONFIG_SYS_MALLOC_F_LEN       0x150
+#endif
+
+/* Stack location before relocation */
+#define CONFIG_SYS_INIT_SP_OFFSET      CONFIG_SYS_TEXT_BASE
 
 /*
  * CFI flash memory layout - Example
 #define CONFIG_SPL_LDSCRIPT    "arch/microblaze/cpu/u-boot-spl.lds"
 
 #define CONFIG_SPL_RAM_DEVICE
-#define CONFIG_SPL_NOR_SUPPORT
+#ifdef CONFIG_SYS_FLASH_BASE
+# define CONFIG_SPL_NOR_SUPPORT
+# define CONFIG_SYS_UBOOT_BASE         CONFIG_SYS_FLASH_BASE
+#endif
 
 /* for booting directly linux */
 #define CONFIG_SPL_OS_BOOT
 /* BRAM start */
 #define CONFIG_SYS_INIT_RAM_ADDR       0x0
 /* BRAM size - will be generated */
-#define CONFIG_SYS_INIT_RAM_SIZE       0x10000
-/* Stack pointer prior relocation, must situated at on-chip RAM */
-#define CONFIG_SYS_SPL_MALLOC_END      (CONFIG_SYS_INIT_RAM_ADDR + \
-                                        CONFIG_SYS_INIT_RAM_SIZE - \
-                                        GENERATED_GBL_DATA_SIZE)
-
-#define CONFIG_SYS_SPL_MALLOC_SIZE     0x100
+#define CONFIG_SYS_INIT_RAM_SIZE       0x100000
 
-/*
- * The main reason to do it in this way is that MALLOC_START
- * can't be defined - common/spl/spl.c
- */
-#if (CONFIG_SYS_SPL_MALLOC_SIZE != 0)
-# define CONFIG_SYS_SPL_MALLOC_START   (CONFIG_SYS_SPL_MALLOC_END - \
-                                        CONFIG_SYS_SPL_MALLOC_SIZE)
-# define CONFIG_SPL_STACK_ADDR         CONFIG_SYS_SPL_MALLOC_START
-#else
-# define CONFIG_SPL_STACK_ADDR         CONFIG_SYS_SPL_MALLOC_END
-#endif
+# define CONFIG_SPL_STACK_ADDR         (CONFIG_SYS_INIT_RAM_ADDR + \
+                                        CONFIG_SYS_INIT_RAM_SIZE - \
+                                        CONFIG_SYS_MALLOC_F_LEN)
 
 /* Just for sure that there is a space for stack */
 #define CONFIG_SPL_STACK_SIZE          0x100
 
-#define CONFIG_SYS_UBOOT_BASE          CONFIG_SYS_FLASH_BASE
 #define CONFIG_SYS_UBOOT_START         CONFIG_SYS_TEXT_BASE
 
 #define CONFIG_SPL_MAX_FOOTPRINT       (CONFIG_SYS_INIT_RAM_SIZE - \
                                         CONFIG_SYS_INIT_RAM_ADDR - \
-                                        GENERATED_GBL_DATA_SIZE - \
-                                        CONFIG_SYS_SPL_MALLOC_SIZE - \
+                                        CONFIG_SYS_MALLOC_F_LEN - \
                                         CONFIG_SPL_STACK_SIZE)
 
 #endif /* __CONFIG_H */
index e6c41306a36001a52ef62e96704253eb283dd376..c567d9dbb68144b406c0e4bcab4e0c1b4fa1048b 100644 (file)
 #define CONFIG_ENV_SPI_MODE             CONFIG_SF_DEFAULT_MODE
 #define CONFIG_ENV_SPI_MAX_HZ           CONFIG_SF_DEFAULT_SPEED
 #else
-#define CONFIG_ENV_OFFSET              (6 * SZ_64K)
+#define CONFIG_ENV_OFFSET              (8 * SZ_64K)
 #define CONFIG_ENV_IS_IN_MMC
 #endif
 
index fbaae3f505b577d9ce124dc21d1da4215eff12a0..404b922d39cfeaf7790eef60e81cfc261c100033 100644 (file)
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
 
+#ifdef CONFIG_SPL
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+#include "imx6_spl.h"
+#endif
+
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
 #define CONFIG_INITRD_TAG
@@ -28,7 +34,6 @@
 #define CONFIG_SYS_MALLOC_LEN          (3 * SZ_1M)
 
 #define CONFIG_BOARD_EARLY_INIT_F
-#define CONFIG_BOARD_LATE_INIT
 #define CONFIG_MXC_GPIO
 
 #define CONFIG_MXC_UART
 #define FSL_QSPI_FLASH_NUM             2
 #endif
 
-#define CONFIG_ENV_OFFSET              (6 * SZ_64K)
+#define CONFIG_ENV_OFFSET              (8 * SZ_64K)
 #define CONFIG_ENV_SIZE                        SZ_8K
 #define CONFIG_ENV_IS_IN_MMC
 
index 255c933baa4be2a2440e831f7fdbe97ee32627bd..c061e93534ff5b601f7ffd65bd811a93fe63c47e 100644 (file)
 #endif
 
 
+/* SPL */
+#ifdef CONFIG_SPL
+#include "imx6_spl.h"
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SYS_SPI_U_BOOT_OFFS     (64 * 1024)
+#define CONFIG_SPL_SPI_LOAD
+#endif
+
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_MII
 /* Physical Memory Map */
 #define CONFIG_NR_DRAM_BANKS           1
 #define PHYS_SDRAM                     MMDC0_ARB_BASE_ADDR
-#define PHYS_SDRAM_SIZE                (1u * 1024 * 1024 * 1024)
 
 #define CONFIG_SYS_SDRAM_BASE          PHYS_SDRAM
 #define CONFIG_SYS_INIT_RAM_ADDR       IRAM_BASE_ADDR
diff --git a/include/configs/platinum.h b/include/configs/platinum.h
new file mode 100644 (file)
index 0000000..134bb45
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __PLATINUM_CONFIG_H__
+#define __PLATINUM_CONFIG_H__
+
+#define CONFIG_SYS_GENERIC_BOARD
+
+/* SPL */
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+
+/* Location in NAND to read U-Boot from */
+#define CONFIG_SYS_NAND_U_BOOT_OFFS     (14 * 1024 * 1024)
+
+#include "imx6_spl.h"                  /* common IMX6 SPL configuration */
+#include "mx6_common.h"
+#include <asm/arch/imx-regs.h>
+#include <asm/imx-common/gpio.h>
+
+/*
+ * Console configuration
+ */
+
+#include <config_cmd_default.h>
+#define CONFIG_CMD_BMODE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_FUSE
+#define CONFIG_CMD_GPIO
+#define CONFIG_CMD_I2C
+#undef  CONFIG_CMD_IMLS
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_NAND_TRIMFFS
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_TIME
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_CMD_USB
+
+/*
+ * Hardware configuration
+ */
+
+/* GPIO config */
+#define CONFIG_MXC_GPIO
+
+/* UART config */
+#define CONFIG_MXC_UART
+#define CONFIG_MXC_UART_BASE                   UART1_BASE
+#define CONFIG_BAUDRATE                                115200
+#define CONFIG_CONS_INDEX                      1
+
+/* I2C config */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_I2C_SPEED                   100000
+
+/* MMC config */
+#define CONFIG_FSL_ESDHC
+#define CONFIG_FSL_USDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR              0
+#define CONFIG_SYS_FSL_USDHC_NUM               1
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_DOS_PARTITION
+
+/* Ethernet config */
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define IMX_FEC_BASE                           ENET_BASE_ADDR
+
+#define CONFIG_PHYLIB
+
+/* USB config */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_MX6
+#define CONFIG_USB_STORAGE
+#define CONFIG_MXC_USB_PORT                    1
+#define CONFIG_MXC_USB_PORTSC                  (PORT_PTS_UTMI | PORT_PTS_PTW)
+#define CONFIG_MXC_USB_FLAGS                   0
+
+/* Memory config */
+#define CONFIG_NR_DRAM_BANKS                   1
+#define PHYS_SDRAM                             MMDC0_ARB_BASE_ADDR
+#ifndef PHYS_SDRAM_SIZE
+#define PHYS_SDRAM_SIZE                                (1024 << 20)
+#endif
+
+#define CONFIG_SYS_SDRAM_BASE                  PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR               IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE               IRAM_SIZE
+
+#define CONFIG_SYS_INIT_SP_OFFSET              (CONFIG_SYS_INIT_RAM_SIZE - \
+                                                GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR                        (CONFIG_SYS_INIT_RAM_ADDR + \
+                                                CONFIG_SYS_INIT_SP_OFFSET)
+
+#define CONFIG_SYS_MALLOC_LEN                  (16 * 1024 * 1024)
+
+/* FLASH and environment organization */
+#define CONFIG_SYS_NO_FLASH
+
+#ifdef CONFIG_CMD_NAND
+
+/* NAND config */
+#define CONFIG_NAND_MXS
+#ifndef CONFIG_SYS_NAND_MAX_CHIPS
+#define CONFIG_SYS_NAND_MAX_CHIPS              2
+#endif
+#define CONFIG_SYS_MAX_NAND_DEVICE             1
+#define CONFIG_SYS_NAND_BASE                   0x40000000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+
+/* DMA config, needed for GPMI/MXS NAND support */
+#define CONFIG_APBH_DMA
+#define CONFIG_APBH_DMA_BURST
+#define CONFIG_APBH_DMA_BURST8
+
+/* Fuse support */
+#define CONFIG_MXC_OCOTP
+
+/* Environment in NAND */
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_OFFSET              (16 << 20)
+#define CONFIG_ENV_SECT_SIZE           (128 << 10)
+#define CONFIG_ENV_SIZE                        CONFIG_ENV_SECT_SIZE
+#define CONFIG_ENV_OFFSET_REDUND       (CONFIG_ENV_OFFSET + (512 << 10))
+#define CONFIG_ENV_SIZE_REDUND         CONFIG_ENV_SIZE
+
+#else /* CONFIG_CMD_NAND */
+
+/* Environment in MMC */
+#define CONFIG_ENV_SIZE                        (8 << 10)
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_ENV_OFFSET              (6 * 64 * 1024)
+#define CONFIG_SYS_MMC_ENV_DEV         0
+
+#endif /* CONFIG_CMD_NAND */
+
+/*
+ * U-Boot configuration
+ */
+
+/* Console boot messages */
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+
+/* Tag config */
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_REVISION_TAG
+
+/* Board startup config */
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_MISC_INIT_R
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+/* Device tree support */
+#define CONFIG_OF_LIBFDT
+
+#define CONFIG_LOADADDR                                0x12000000
+#define CONFIG_SYS_TEXT_BASE                   0x17800000
+
+#define CONFIG_SYS_MEMTEST_START               PHYS_SDRAM
+#define CONFIG_SYS_MEMTEST_END                 (CONFIG_SYS_MEMTEST_START + \
+                                                PHYS_SDRAM_SIZE - (12 << 20))
+
+#define CONFIG_BOOTDELAY                       3
+#define CONFIG_BOOTCOMMAND                     "run bootubi_scr"
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_HUSH_PARSER
+
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_PREBOOT
+
+#define CONFIG_SYS_CBSIZE                      256
+
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE                      (CONFIG_SYS_CBSIZE + \
+                                                sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS                     16
+#define CONFIG_SYS_BARGSIZE                    CONFIG_SYS_CBSIZE
+
+#define CONFIG_SYS_LOAD_ADDR                   CONFIG_LOADADDR
+
+/* MTD/UBI/UBIFS config */
+#define CONFIG_LZO
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_RBTREE
+
+#if (CONFIG_SYS_NAND_MAX_CHIPS == 1)
+#define MTDIDS_DEFAULT         "nand0=gpmi-nand"
+#define MTDPARTS_DEFAULT       "mtdparts=gpmi-nand:14M(spl),2M(uboot)," \
+                               "512k(env1),512k(env2),-(ubi)"
+#elif (CONFIG_SYS_NAND_MAX_CHIPS == 2)
+#define MTDIDS_DEFAULT         "nand0=gpmi-nand"
+#define MTDPARTS_DEFAULT       "mtdparts=gpmi-nand:14M(spl),2M(uboot)," \
+                               "512k(env1),512k(env2),495M(ubi0)," \
+                               "14M(res0),2M(res1)," \
+                               "512k(res2),512k(res3),-(ubi1)"
+#endif
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+#define CONFIG_CMD_CACHE
+#endif
+
+/*
+ * Environment configuration
+ */
+
+#if (CONFIG_SYS_NAND_MAX_CHIPS == 1)
+#define CONFIG_COMMON_ENV_UBI                                          \
+       "setubipartition=env set ubipartition ubi\0"                    \
+       "setubirfs=env set ubirfs $ubipartition:rootfs$boot_vol\0"
+#elif (CONFIG_SYS_NAND_MAX_CHIPS == 2)
+#define CONFIG_COMMON_ENV_UBI                                          \
+       "setubipartition=env set ubipartition ubi$boot_vol\0"           \
+       "setubirfs=env set ubirfs ubi0:rootfs\0"
+#endif
+
+#define CONFIG_COMMON_ENV_MISC                                         \
+       "user=user\0"                                                   \
+       "project="CONFIG_PLATINUM_PROJECT"\0"                           \
+       "uimage=uImage\0"                                               \
+       "dtb="CONFIG_PLATINUM_CPU"-platinum-"CONFIG_PLATINUM_PROJECT".dtb\0" \
+       "serverip=serverip\0"                                           \
+       "memaddrlinux=0x10800000\0"                                     \
+       "memaddrsrc=0x11000000\0"                                       \
+       "memaddrdtb=0x12000000\0"                                       \
+       "console=ttymxc0\0"                                             \
+       "baudrate=115200\0"                                             \
+       "boot_scr=boot.uboot\0"                                         \
+       "boot_vol=0\0"                                                  \
+       "mtdids="MTDIDS_DEFAULT"\0"                                     \
+       "mtdparts="MTDPARTS_DEFAULT"\0"                                 \
+       "mmcfs=ext2\0"                                                  \
+       "mmcrootpart=1\0"                                               \
+       \
+       "setnfspath=env set nfspath /home/nfs/$user/$project/root\0"    \
+       "settftpfilelinux=env set tftpfilelinux $user/$project/$uimage\0" \
+       "settftpfiledtb=env set tftpfiledtb $user/$project/$dtb\0"      \
+       "setubifilelinux=env set ubifilelinux boot/$uimage\0"           \
+       "setubipfiledtb=env set ubifiledtb boot/$dtb\0"                 \
+       "setmmcrootdev=env set mmcrootdev /dev/mmcblk0p$mmcrootpart\0"  \
+       "setmmcfilelinux=env set mmcfilelinux /boot/$uimage\0"          \
+       "setmmcfiledtb=env set mmcfiledtb /boot/$dtb\0"                 \
+       \
+       "loadtftpkernel=dhcp $memaddrlinux $tftpfilelinux\0"            \
+       "loadtftpdtb=dhcp $memaddrdtb $tftpfiledtb\0"                   \
+       "loadubikernel=ubifsload $memaddrlinux $ubifilelinux\0"         \
+       "loadubidtb=ubifsload $memaddrdtb $ubifiledtb\0"                \
+       "loadmmckernel=${mmcfs}load mmc 0:$mmcrootpart $memaddrlinux "  \
+               "$mmcfilelinux\0"                                       \
+       "loadmmcdtb=${mmcfs}load mmc 0:$mmcrootpart $memaddrdtb "       \
+               "$mmcfiledtb\0"                                         \
+       \
+       "ubipart=ubi part $ubipartition\0"                              \
+       "ubimount=ubifsmount $ubirfs\0"                                 \
+       \
+       "setbootargscommon=env set bootargs $bootargs "                 \
+               "console=$console,$baudrate enable_wait_mode=off\0"     \
+       "setbootargsmtd=env set bootargs $bootargs $mtdparts\0"         \
+       "setbootargsdhcp=env set bootargs $bootargs ip=dhcp\0"          \
+       "setbootargsubirfs=env set bootargs $bootargs "                 \
+               "ubi.mtd=$ubipartition root=$ubirfs rootfstype=ubifs\0" \
+       "setbootargsnfsrfs=env set bootargs $bootargs root=/dev/nfs "   \
+               "nfsroot=$serverip:$nfspath,v3,tcp\0"                   \
+       "setbootargsmmcrfs=env set bootargs $bootargs "                 \
+               "root=$mmcrootdev rootwait rw\0"                        \
+       \
+       "bootnet=run settftpfilelinux settftpfiledtb setnfspath "       \
+               "setbootargscommon setbootargsmtd setbootargsdhcp "     \
+                       "setbootargsnfsrfs;"                            \
+                       "run loadtftpkernel loadtftpdtb;"               \
+                       "bootm $memaddrlinux - $memaddrdtb\0"           \
+       "bootnet_ubirfs=run settftpfilelinux settftpfiledtb;"           \
+                       "run setubipartition setubirfs;"                \
+                       "run setbootargscommon setbootargsmtd "         \
+                               "setbootargsubirfs;"                    \
+                       "run loadtftpkernel loadtftpdtb;"               \
+                       "bootm $memaddrlinux - $memaddrdtb\0"           \
+       "bootubi=run setubipartition setubirfs setubifilelinux "        \
+                               "setubipfiledtb;"                       \
+                       "run setbootargscommon setbootargsmtd "         \
+                               "setbootargsubirfs;"                    \
+                       "run ubipart ubimount loadubikernel loadubidtb;" \
+                       "bootm $memaddrlinux - $memaddrdtb\0"           \
+       "bootubi_scr=run setubipartition setubirfs;"                    \
+                       "run ubipart ubimount;"                         \
+                       "if ubifsload ${memaddrsrc} boot/${boot_scr}; " \
+                       "then source ${memaddrsrc}; else run bootubi; fi\0" \
+       "bootmmc=run setmmcrootdev setmmcfilelinux setmmcfiledtb "      \
+                       "setbootargscommon setbootargsmmcrfs;"          \
+                       "run loadmmckernel loadmmcdtb;"                 \
+                       "bootm $memaddrlinux - $memaddrdtb\0"           \
+       \
+       "bootcmd="CONFIG_BOOTCOMMAND"\0"
+
+#define CONFIG_COMMON_ENV_SETTINGS                     CONFIG_COMMON_ENV_MISC \
+                                                       CONFIG_COMMON_ENV_UBI
+#endif /* __PLATINUM_CONFIG_H__ */
diff --git a/include/configs/platinum_picon.h b/include/configs/platinum_picon.h
new file mode 100644 (file)
index 0000000..4590df5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __PLATINUM_PICON_CONFIG_H__
+#define __PLATINUM_PICON_CONFIG_H__
+
+#define CONFIG_PLATINUM_PICON
+#define CONFIG_PLATINUM_BOARD                  "Barco Picon"
+#define CONFIG_PLATINUM_PROJECT                        "picon"
+#define CONFIG_PLATINUM_CPU                    "imx6dl"
+
+#define CONFIG_MX6
+
+#include <configs/platinum.h>
+
+#define CONFIG_FEC_XCV_TYPE                    RMII
+#define CONFIG_FEC_MXC_PHYADDR                 0
+
+#define CONFIG_HOSTNAME                                picon
+
+#define CONFIG_SYS_PROMPT                      "picon > "
+
+#define CONFIG_PLATFORM_ENV_SETTINGS           "\0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS              CONFIG_COMMON_ENV_SETTINGS \
+                                               CONFIG_PLATFORM_ENV_SETTINGS
+
+#endif /* __PLATINUM_PICON_CONFIG_H__ */
diff --git a/include/configs/platinum_titanium.h b/include/configs/platinum_titanium.h
new file mode 100644 (file)
index 0000000..6789655
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014, Barco (www.barco.com)
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __PLATINUM_TITANIUM_CONFIG_H__
+#define __PLATINUM_TITANIUM_CONFIG_H__
+
+#define CONFIG_PLATINUM_TITANIUM
+#define CONFIG_PLATINUM_BOARD                  "Barco Titanium"
+#define CONFIG_PLATINUM_PROJECT                        "titanium"
+#define CONFIG_PLATINUM_CPU                    "imx6q"
+
+#define CONFIG_MX6
+
+#define PHYS_SDRAM_SIZE                                (512 << 20)
+#define CONFIG_SYS_NAND_MAX_CHIPS              1
+
+#include <configs/platinum.h>
+
+#define CONFIG_FEC_XCV_TYPE                    RGMII
+#define CONFIG_FEC_MXC_PHYADDR                 4
+
+#define CONFIG_PHY_MICREL
+#define CONFIG_PHY_MICREL_KSZ9021
+#define CONFIG_PHY_RESET_DELAY                 1000
+
+#define CONFIG_HOSTNAME                                titanium
+
+#define CONFIG_SYS_PROMPT                      "titanium > "
+
+#define CONFIG_PLATFORM_ENV_SETTINGS           "\0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS              CONFIG_COMMON_ENV_SETTINGS \
+                                               CONFIG_PLATFORM_ENV_SETTINGS
+
+#endif /* __PLATINUM_TITANIUM_CONFIG_H__ */
index 21c8bda9f30452b0c8f3de97673563a3001ce2b6..84029cb39927779cf49a8acfaaa3025a48112499 100644 (file)
 #define CONFIG_LZMA
 #define CONFIG_LZO
 
+/*
+ * Enable device tree support
+ */
+#define CONFIG_OF_LIBFDT
+
 /*
  * Miscellaneous configurable options
  */
@@ -51,6 +56,7 @@
 #define CONFIG_CMD_NAND
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_USB
+
 /*
  * mv-common.h should be defined after CMD configs since it used them
  * to enable certain macros
 #define CONFIG_MTD_DEVICE               /* needed for mtdparts commands */
 #define CONFIG_MTD_PARTITIONS
 #define CONFIG_CMD_MTDPARTS
-#define CONFIG_LZO
 
 #endif /* _CONFIG_SHEEVAPLUG_H */
index e9218f7d819ef88b9b2f57feac83f85e89933323..46df40661da631bbabb3d629982daf6cb0f7f0f5 100644 (file)
 /*
  *  CPU configuration
  */
-#define CONFIG_ARC700
-#define CONFIG_ARC_MMU_VER             3
-#define CONFIG_SYS_CACHELINE_SIZE      32
 #define CONFIG_SYS_TIMER_RATE          CONFIG_SYS_CLK_FREQ
 
-/*
- * Board configuration
- */
-#define CONFIG_SYS_GENERIC_BOARD
-#define CONFIG_ARCH_EARLY_INIT_R
-
 /*
  * Memory configuration
  */
-#define CONFIG_SYS_TEXT_BASE           0x84000000
 #define CONFIG_SYS_MONITOR_BASE                CONFIG_SYS_TEXT_BASE
 
 #define CONFIG_SYS_DDR_SDRAM_BASE      0x80000000
index 9ad47f6933eaac0f8a4ffa1817e0be6773ef146d..9420e6b48b80911f5e044bc4593af4054be40afd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2014 Panasonic Corporation
+ * Copyright (C) 2012-2015 Panasonic Corporation
  *   Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
@@ -95,6 +95,8 @@
 
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
+#define CONFIG_MISC_INIT_F
+#define CONFIG_BOARD_EARLY_INIT_F
 #define CONFIG_BOARD_EARLY_INIT_R
 #define CONFIG_BOARD_LATE_INIT
 
        "image_offset=0x00080000\0"             \
        "image_size=0x00f00000\0"               \
        "verify=n\0"                            \
-       "norboot=run add_default_bootargs;"                             \
+       "nandupdate=nand erase 0 0x100000 &&"                           \
+                  "tftpboot u-boot-spl.bin &&"                         \
+                  "nand write $loadaddr 0 0x10000 &&"                  \
+                  "tftpboot u-boot-dtb.img &&"                         \
+                  "nand write $loadaddr 0x10000 0xf0000\0"             \
+       "norboot=run add_default_bootargs &&"                           \
                "bootm $image_offset\0"                                 \
-       "nandboot=run add_default_bootargs;"                            \
-               "nand read $loadaddr $image_offset $image_size;"        \
-               "bootm\0"                                               \
+       "nandboot=run add_default_bootargs &&"                          \
+                "nand read $loadaddr $image_offset $image_size &&"     \
+                "bootm\0"                                              \
        "add_default_bootargs=setenv bootargs $bootargs"                \
                " console=ttyS0,$baudrate\0"                            \
 
 #define CONFIG_SPL_TEXT_BASE           0x00100000
 #endif
 
-#define CONFIG_BOARD_POSTCLK_INIT
-
 #ifndef CONFIG_SPL_BUILD
 #define CONFIG_SKIP_LOWLEVEL_INIT
 #endif
index 809017c5fe225278c87619e237fd0905b9c1dcf1..117d1f7087a98dff85c861d2ebbee0db9c9053e1 100644 (file)
                "if i2c probe 0x10; then " \
                        "setenv bootargs ${bootargs} " \
                                "video=mxcfb${nextcon}:dev=lcd,800x480@60," \
-                                       "if=RGB666; " \
+                                       "if=RGB666,bpp=32; " \
                        "if test 0 -eq ${nextcon}; then " \
                                "setenv fbmem fbmem=10M; " \
                        "else " \
index 11184893bfb99966e9e6fd089344911175b47ca9..d304658b9a4c30fdcbbb0a3610e36efccb1250bf 100644 (file)
@@ -16,14 +16,34 @@ enum {
 
        PFUZE100_SW1ABVOL       = 0x20,
        PFUZE100_SW1ABSTBY      = 0x21,
+       PFUZE100_SW1ABOFF       = 0x22,
+       PFUZE100_SW1ABMODE      = 0x23,
        PUZE_100_SW1ABCONF      = 0x24,
        PFUZE100_SW1CVOL        = 0x2e,
        PFUZE100_SW1CSTBY       = 0x2f,
+       PFUZE100_SW1COFF        = 0x30,
+       PFUZE100_SW1CMODE       = 0x31,
        PFUZE100_SW1CCONF       = 0x32,
        PFUZE100_SW2VOL         = 0x35,
+       PFUZE100_SW2STBY        = 0x36,
+       PFUZE100_SW2OFF         = 0x37,
+       PFUZE100_SW2MODE        = 0x38,
+       PFUZE100_SW2CONF        = 0x39,
        PFUZE100_SW3AVOL        = 0x3c,
+       PFUZE100_SW3ASTBY       = 0x3D,
+       PFUZE100_SW3AOFF        = 0x3E,
+       PFUZE100_SW3AMODE       = 0x3F,
+       PFUZE100_SW3ACONF       = 0x40,
        PFUZE100_SW3BVOL        = 0x43,
+       PFUZE100_SW3BSTBY       = 0x44,
+       PFUZE100_SW3BOFF        = 0x45,
+       PFUZE100_SW3BMODE       = 0x46,
+       PFUZE100_SW3BCONF       = 0x47,
        PFUZE100_SW4VOL         = 0x4a,
+       PFUZE100_SW4STBY        = 0x4b,
+       PFUZE100_SW4OFF         = 0x4c,
+       PFUZE100_SW4MODE        = 0x4d,
+       PFUZE100_SW4CONF        = 0x4e,
        PFUZE100_SWBSTCON1      = 0x66,
        PFUZE100_VREFDDRCON     = 0x6a,
        PFUZE100_VSNVSVOL       = 0x6b,
@@ -41,6 +61,8 @@ enum {
  * Buck Regulators
  */
 
+#define PFUZE100_SW1ABC_SETP(x)        ((x - 3000) / 250)
+
 /* SW1A/B/C Output Voltage Configuration */
 #define SW1x_0_300V 0
 #define SW1x_0_325V 1
@@ -177,5 +199,38 @@ enum {
 #define SWBST_MODE_AUTO        (2 << 2)
 #define SWBST_MODE_APS (2 << 3)
 
+/*
+ * Regulator Mode Control
+ *
+ * OFF: The regulator is switched off and the output voltage is discharged.
+ * PFM: In this mode, the regulator is always in PFM mode, which is useful
+ *      at light loads for optimized efficiency.
+ * PWM: In this mode, the regulator is always in PWM mode operation
+ *     regardless of load conditions.
+ * APS: In this mode, the regulator moves automatically between pulse
+ *     skipping mode and PWM mode depending on load conditions.
+ *
+ * SWxMODE[3:0]
+ * Normal Mode  |  Standby Mode        |      value
+ *   OFF               OFF             0x0
+ *   PWM               OFF             0x1
+ *   PFM               OFF             0x3
+ *   APS               OFF             0x4
+ *   PWM               PWM             0x5
+ *   PWM               APS             0x6
+ *   APS               APS             0x8
+ *   APS               PFM             0xc
+ *   PWM               PFM             0xd
+ */
+#define OFF_OFF                0x0
+#define PWM_OFF                0x1
+#define PFM_OFF                0x3
+#define APS_OFF                0x4
+#define PWM_PWM                0x5
+#define PWM_APS                0x6
+#define APS_APS                0x8
+#define APS_PFM                0xc
+#define PWM_PFM                0xd
+
 int power_pfuze100_init(unsigned char bus);
 #endif
index 4dbf754ace94052e4540692e78ee676d95c77531..7ae7a686888c8e94b4051e38789ee3b48adce098 100644 (file)
 
 #ifndef _SPLASH_H_
 #define _SPLASH_H_
+
 #include <errno.h>
 
+enum splash_storage {
+       SPLASH_STORAGE_NAND,
+       SPLASH_STORAGE_SF,
+};
+
+struct splash_location {
+       char *name;
+       enum splash_storage storage;
+       u32 offset;     /* offset from start of storage */
+};
+
+int splash_source_load(struct splash_location *locations, uint size);
 int splash_screen_prepare(void);
 
 #ifdef CONFIG_SPLASH_SCREEN_ALIGN
index ecf3037cb89b032712f6ba9c9bf673664ed4fa96..e4b98811867da5d6ce753cbe578d187caaaf60b5 100644 (file)
@@ -57,6 +57,7 @@ libs-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/
 libs-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/
 libs-$(CONFIG_SPL_MMC_SUPPORT) += drivers/mmc/
 libs-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += drivers/ddr/fsl/
+libs-$(CONFIG_SYS_MVEBU_DDR) += drivers/ddr/mvebu/
 libs-$(CONFIG_SPL_SERIAL_SUPPORT) += drivers/serial/
 libs-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += drivers/mtd/spi/
 libs-$(CONFIG_SPL_SPI_SUPPORT) += drivers/spi/
index 6e1ce79f2f45cd33cc3e99ca278a330adb0f75bd..e4b23eb5b814c12a3cca4ecb5da978d682ebd77b 100644 (file)
@@ -115,6 +115,10 @@ ifdef CONFIG_FIT_SIGNATURE
 HOST_EXTRACFLAGS       += -DCONFIG_FIT_SIGNATURE
 endif
 
+ifdef CONFIG_SYS_SPI_U_BOOT_OFFS
+HOSTCFLAGS_kwbimage.o += -DCONFIG_SYS_SPI_U_BOOT_OFFS=$(CONFIG_SYS_SPI_U_BOOT_OFFS)
+endif
+
 # MXSImage needs LibSSL
 ifneq ($(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_FIT_SIGNATURE),)
 HOSTLOADLIBES_mkimage += -lssl -lcrypto
index 3d3759188692b91323e88603d5a2503714f3b39b..6f469ae6336c064cd0ceb2534929b6396f22f1c1 100644 (file)
@@ -38,6 +38,7 @@ static table_entry_t imximage_boot_offset[] = {
        {FLASH_OFFSET_SATA,     "sata",         "SATA Disk",    },
        {FLASH_OFFSET_SD,       "sd",           "SD Card",      },
        {FLASH_OFFSET_SPI,      "spi",          "SPI Flash",    },
+       {FLASH_OFFSET_QSPI,     "qspi",         "QSPI NOR Flash",},
        {-1,                    "",             "Invalid",      },
 };
 
@@ -52,6 +53,7 @@ static table_entry_t imximage_boot_loadsize[] = {
        {FLASH_LOADSIZE_SATA,           "sata",         "SATA Disk",    },
        {FLASH_LOADSIZE_SD,             "sd",           "SD Card",      },
        {FLASH_LOADSIZE_SPI,            "spi",          "SPI Flash",    },
+       {FLASH_LOADSIZE_QSPI,           "qspi",         "QSPI NOR Flash",},
        {-1,                            "",             "Invalid",      },
 };
 
index 5b5ad0edf46a64d3c1ce9ed788ac50285a9ee6f8..36fe0958fee3023763b8fb4860d5c1fe98c69616 100644 (file)
@@ -29,6 +29,7 @@
 #define FLASH_OFFSET_ONENAND   0x100
 #define FLASH_OFFSET_NOR       0x1000
 #define FLASH_OFFSET_SATA      FLASH_OFFSET_STANDARD
+#define FLASH_OFFSET_QSPI      0x1000
 
 /* Initial Load Region Size */
 #define FLASH_LOADSIZE_UNDEFINED       0xFFFFFFFF
@@ -39,6 +40,7 @@
 #define FLASH_LOADSIZE_ONENAND         0x400
 #define FLASH_LOADSIZE_NOR             0x0 /* entire image */
 #define FLASH_LOADSIZE_SATA            FLASH_LOADSIZE_STANDARD
+#define FLASH_LOADSIZE_QSPI            0x0 /* entire image */
 
 #define IVT_HEADER_TAG 0xD1
 #define IVT_VERSION 0x40
index 66f459ad6b1c7f2b65eb612349e6a2e647c8238e..de5c80847e3f8d2ee4c8a9aeda595d0c3b1adb56 100644 (file)
@@ -868,6 +868,16 @@ static int kwbimage_generate(struct image_tool_params *params,
                        sizeof(struct ext_hdr_v0);
        } else {
                alloc_len = image_headersz_v1(params, NULL);
+#if defined(CONFIG_SYS_SPI_U_BOOT_OFFS)
+               if (alloc_len > CONFIG_SYS_SPI_U_BOOT_OFFS) {
+                       fprintf(stderr, "Error: Image header (incl. SPL image) too big!\n");
+                       fprintf(stderr, "header=0x%x CONFIG_SYS_SPI_U_BOOT_OFFS=0x%x!\n",
+                               alloc_len, CONFIG_SYS_SPI_U_BOOT_OFFS);
+                       fprintf(stderr, "Increase CONFIG_SYS_SPI_U_BOOT_OFFS!\n");
+               } else {
+                       alloc_len = CONFIG_SYS_SPI_U_BOOT_OFFS;
+               }
+#endif
        }
 
        hdr = malloc(alloc_len);
diff --git a/tools/logos/compulab.bmp b/tools/logos/compulab.bmp
new file mode 100644 (file)
index 0000000..df5435c
Binary files /dev/null and b/tools/logos/compulab.bmp differ
index 90b21737b92f80bba2a78e41bb066dd40724ff94..6d48cfb3e43473caa4c88d5271e60676f207ca70 100644 (file)
@@ -142,6 +142,9 @@ static inline uint32_t mx28_nand_get_ecc_strength(uint32_t page_data_size,
 
                if (page_oob_size == 218)
                        return 16;
+
+               if (page_oob_size == 224)
+                       return 16;
        }
 
        return 0;
@@ -269,6 +272,9 @@ static struct mx28_nand_fcb *mx28_nand_get_fcb(uint32_t size)
                } else if (nand_oobsize == 218) {
                        fcb->ecc_block_n_ecc_type =     8;
                        fcb->ecc_block_0_ecc_type =     8;
+               } else if (nand_oobsize == 224) {
+                       fcb->ecc_block_n_ecc_type =     8;
+                       fcb->ecc_block_0_ecc_type =     8;
                }
        }