summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig15
-rw-r--r--arch/arm/cpu/arm926ejs/mxs/spl_boot.c6
-rw-r--r--arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c13
-rw-r--r--arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c18
-rw-r--r--arch/arm/cpu/arm926ejs/mxs/spl_power_init.c110
-rw-r--r--arch/arm/cpu/armv7/armada-xp/Makefile2
-rw-r--r--arch/arm/cpu/armv7/armada-xp/lowlevel_spl.S62
-rw-r--r--arch/arm/cpu/armv7/armada-xp/spl.c38
-rw-r--r--arch/arm/cpu/armv7/mx6/ddr.c96
-rw-r--r--arch/arm/cpu/armv7/mx6/soc.c2
-rw-r--r--arch/arm/cpu/armv7/uniphier/Kconfig11
-rw-r--r--arch/arm/cpu/armv7/uniphier/Makefile27
-rw-r--r--arch/arm/cpu/armv7/uniphier/board_early_init_f.c22
-rw-r--r--arch/arm/cpu/armv7/uniphier/board_postclk_init.c47
-rw-r--r--arch/arm/cpu/armv7/uniphier/cmd_pinmon.c15
-rw-r--r--arch/arm/cpu/armv7/uniphier/dram_init.c23
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile14
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile13
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-pro4/board_info.c16
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c6
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile14
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-sld8/board_info.c16
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c9
-rw-r--r--arch/arm/cpu/armv7/uniphier/print_misc_info.c (renamed from arch/arm/cpu/armv7/uniphier/ph1-ld4/board_info.c)7
-rw-r--r--arch/arm/cpu/armv7/uniphier/spl.c52
-rw-r--r--arch/arm/dts/uniphier-ph1-ld4-ref.dts7
-rw-r--r--arch/arm/dts/uniphier-ph1-pro4-ref.dts7
-rw-r--r--arch/arm/dts/uniphier-ph1-sld3-ref.dts7
-rw-r--r--arch/arm/dts/uniphier-ph1-sld8-ref.dts7
-rw-r--r--arch/arm/dts/uniphier-ref-daughter.dtsi16
-rw-r--r--arch/arm/include/asm/arch-armada-xp/config.h4
-rw-r--r--arch/arm/include/asm/arch-armada-xp/cpu.h16
-rw-r--r--arch/arm/include/asm/arch-mx6/imx-regs.h16
-rw-r--r--arch/arm/include/asm/arch-mx6/mx6-ddr.h46
-rw-r--r--arch/arm/include/asm/arch-mxs/sys_proto.h17
-rw-r--r--arch/arm/include/asm/arch-uniphier/boot-device.h2
-rw-r--r--arch/arm/include/asm/arch-uniphier/gpio.h6
-rw-r--r--arch/arm/include/asm/u-boot-arm.h1
-rw-r--r--arch/arm/mvebu-common/Makefile2
-rw-r--r--arch/arm/mvebu-common/serdes/Makefile6
-rw-r--r--arch/arm/mvebu-common/serdes/board_env_spec.h262
-rw-r--r--arch/arm/mvebu-common/serdes/high_speed_env_lib.c1572
-rw-r--r--arch/arm/mvebu-common/serdes/high_speed_env_spec.c185
-rw-r--r--arch/arm/mvebu-common/serdes/high_speed_env_spec.h87
-rw-r--r--arch/arm/mvebu-common/u-boot-spl.lds57
45 files changed, 2762 insertions, 215 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5cfca1b..1f1ccad 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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"
@@ -646,6 +648,7 @@ config TARGET_MX6SLEVK
config TARGET_MX6SXSABRESD
bool "Support mx6sxsabresd"
select CPU_V7
+ select SUPPORT_SPL
config TARGET_GW_VENTANA
bool "Support gw_ventana"
@@ -672,6 +675,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"
@@ -887,6 +901,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"
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
index d29b9aa..d7956e5 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
@@ -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 */
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
index cdfcddd..96bd32f 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
@@ -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");
}
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
index 97ef67d..a744e5d 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
@@ -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);
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
index 1c54ab7..c342217 100644
--- a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
+++ b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
@@ -14,6 +14,13 @@
#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))
;
}
diff --git a/arch/arm/cpu/armv7/armada-xp/Makefile b/arch/arm/cpu/armv7/armada-xp/Makefile
index 885dcee..737159b 100644
--- a/arch/arm/cpu/armv7/armada-xp/Makefile
+++ b/arch/arm/cpu/armv7/armada-xp/Makefile
@@ -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
index 0000000..1febd7b
--- /dev/null
+++ b/arch/arm/cpu/armv7/armada-xp/lowlevel_spl.S
@@ -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
index 0000000..402e520
--- /dev/null
+++ b/arch/arm/cpu/armv7/armada-xp/spl.c
@@ -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);
+}
diff --git a/arch/arm/cpu/armv7/mx6/ddr.c b/arch/arm/cpu/armv7/mx6/ddr.c
index 7a9b03a..fef2231 100644
--- a/arch/arm/cpu/armv7/mx6/ddr.c
+++ b/arch/arm/cpu/armv7/mx6/ddr.c
@@ -12,6 +12,65 @@
#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 */
diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
index 5f5f497..e599a12 100644
--- a/arch/arm/cpu/armv7/mx6/soc.c
+++ b/arch/arm/cpu/armv7/mx6/soc.c
@@ -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
/*
diff --git a/arch/arm/cpu/armv7/uniphier/Kconfig b/arch/arm/cpu/armv7/uniphier/Kconfig
index 0556e4b..5c5a84f 100644
--- a/arch/arm/cpu/armv7/uniphier/Kconfig
+++ b/arch/arm/cpu/armv7/uniphier/Kconfig
@@ -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"
diff --git a/arch/arm/cpu/armv7/uniphier/Makefile b/arch/arm/cpu/armv7/uniphier/Makefile
index 0546232..df418dd 100644
--- a/arch/arm/cpu/armv7/uniphier/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/Makefile
@@ -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
index 0000000..d25bbae
--- /dev/null
+++ b/arch/arm/cpu/armv7/uniphier/board_early_init_f.c
@@ -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
index 89e44bb..0000000
--- a/arch/arm/cpu/armv7/uniphier/board_postclk_init.c
+++ /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;
-}
diff --git a/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c b/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c
index 3561b40..3c1b325 100644
--- a/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c
+++ b/arch/arm/cpu/armv7/uniphier/cmd_pinmon.c
@@ -11,20 +11,17 @@
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;
}
diff --git a/arch/arm/cpu/armv7/uniphier/dram_init.c b/arch/arm/cpu/armv7/uniphier/dram_init.c
index 7de657b..4b8c938 100644
--- a/arch/arm/cpu/armv7/uniphier/dram_init.c
+++ b/arch/arm/cpu/armv7/uniphier/dram_init.c
@@ -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;
}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
index 0752906..72f4663 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
@@ -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-pro4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
index 8206e2a..e330fda 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
@@ -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
index 325a4f6..0000000
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/board_info.c
+++ /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();
-}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c
index 33bccff..c31b74b 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/boot-mode.c
@@ -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;
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
index 0752906..72f4663 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
@@ -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
index 15dc289..0000000
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/board_info.c
+++ /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();
-}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c
index 2b6403f..5e80335 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/pinctrl.c
@@ -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/ph1-ld4/board_info.c b/arch/arm/cpu/armv7/uniphier/print_misc_info.c
index 27d772e..69cfab5 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/board_info.c
+++ b/arch/arm/cpu/armv7/uniphier/print_misc_info.c
@@ -1,16 +1,13 @@
/*
- * Copyright (C) 2012-2014 Panasonic Corporation
+ * Copyright (C) 2015 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)
+int misc_init_f(void)
{
- puts("Board: PH1-LD4 Board\n");
-
return check_support_card();
}
diff --git a/arch/arm/cpu/armv7/uniphier/spl.c b/arch/arm/cpu/armv7/uniphier/spl.c
index 40d28ad..8a4eafc 100644
--- a/arch/arm/cpu/armv7/uniphier/spl.c
+++ b/arch/arm/cpu/armv7/uniphier/spl.c
@@ -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, , );
}
diff --git a/arch/arm/dts/uniphier-ph1-ld4-ref.dts b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
index 6855878..d479be1 100644
--- a/arch/arm/dts/uniphier-ph1-ld4-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
@@ -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";
@@ -46,10 +47,6 @@
&i2c0 {
status = "okay";
- eeprom {
- compatible = "i2c-eeprom";
- reg = <0x50>;
- };
};
&usb0 {
diff --git a/arch/arm/dts/uniphier-ph1-pro4-ref.dts b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
index 1227b62..d9e7a8c 100644
--- a/arch/arm/dts/uniphier-ph1-pro4-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
@@ -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";
@@ -48,10 +49,6 @@
&i2c0 {
status = "okay";
- eeprom {
- compatible = "i2c-eeprom";
- reg = <0x50>;
- };
};
&usb0 {
diff --git a/arch/arm/dts/uniphier-ph1-sld3-ref.dts b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
index fefc592..8a7f90a 100644
--- a/arch/arm/dts/uniphier-ph1-sld3-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
@@ -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";
@@ -45,10 +46,6 @@
&i2c0 {
status = "okay";
- eeprom {
- compatible = "i2c-eeprom";
- reg = <0x50>;
- };
};
&usb0 {
diff --git a/arch/arm/dts/uniphier-ph1-sld8-ref.dts b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
index 9b6d95c..0cb9c47 100644
--- a/arch/arm/dts/uniphier-ph1-sld8-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
@@ -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";
@@ -46,10 +47,6 @@
&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
index 0000000..0145b51
--- /dev/null
+++ b/arch/arm/dts/uniphier-ref-daughter.dtsi
@@ -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>;
+ };
+};
diff --git a/arch/arm/include/asm/arch-armada-xp/config.h b/arch/arm/include/asm/arch-armada-xp/config.h
index 00ee775..f9fd424 100644
--- a/arch/arm/include/asm/arch-armada-xp/config.h
+++ b/arch/arm/include/asm/arch-armada-xp/config.h
@@ -31,7 +31,11 @@
#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
diff --git a/arch/arm/include/asm/arch-armada-xp/cpu.h b/arch/arm/include/asm/arch-armada-xp/cpu.h
index 6b60c21..4f5ff96 100644
--- a/arch/arm/include/asm/arch-armada-xp/cpu.h
+++ b/arch/arm/include/asm/arch-armada-xp/cpu.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h
index c968600..ae88b6e 100644
--- a/arch/arm/include/asm/arch-mx6/imx-regs.h
+++ b/arch/arm/include/asm/arch-mx6/imx-regs.h
@@ -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
diff --git a/arch/arm/include/asm/arch-mx6/mx6-ddr.h b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
index 5ebabfa..8e0d7d1 100644
--- a/arch/arm/include/asm/arch-mx6/mx6-ddr.h
+++ b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
@@ -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 *,
diff --git a/arch/arm/include/asm/arch-mxs/sys_proto.h b/arch/arm/include/asm/arch-mxs/sys_proto.h
index 062f3de..4678723 100644
--- a/arch/arm/include/asm/arch-mxs/sys_proto.h
+++ b/arch/arm/include/asm/arch-mxs/sys_proto.h
@@ -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;
diff --git a/arch/arm/include/asm/arch-uniphier/boot-device.h b/arch/arm/include/asm/arch-uniphier/boot-device.h
index 6987f57..7a10f1c 100644
--- a/arch/arm/include/asm/arch-uniphier/boot-device.h
+++ b/arch/arm/include/asm/arch-uniphier/boot-device.h
@@ -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
index 1fc4e19..0000000
--- a/arch/arm/include/asm/arch-uniphier/gpio.h
+++ /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.
- */
diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h
index f97f3dd..414042d 100644
--- a/arch/arm/include/asm/u-boot-arm.h
+++ b/arch/arm/include/asm/u-boot-arm.h
@@ -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 */
diff --git a/arch/arm/mvebu-common/Makefile b/arch/arm/mvebu-common/Makefile
index 9dcab69..de243fe 100644
--- a/arch/arm/mvebu-common/Makefile
+++ b/arch/arm/mvebu-common/Makefile
@@ -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
index 0000000..a380fee
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/Makefile
@@ -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
index 0000000..36e0ed8
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/board_env_spec.h
@@ -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
index 0000000..702273a
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/high_speed_env_lib.c
@@ -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
index 0000000..115ec2c
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/high_speed_env_spec.c
@@ -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
index 0000000..e5aa1b0
--- /dev/null
+++ b/arch/arm/mvebu-common/serdes/high_speed_env_spec.h
@@ -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
index 0000000..eee1db4
--- /dev/null
+++ b/arch/arm/mvebu-common/u-boot-spl.lds
@@ -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
+}