avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
90
u-boot/arch/arm/mach-mvebu/Kconfig
Normal file
90
u-boot/arch/arm/mach-mvebu/Kconfig
Normal file
@@ -0,0 +1,90 @@
|
||||
if ARCH_MVEBU
|
||||
|
||||
config ARMADA_375
|
||||
bool
|
||||
|
||||
config ARMADA_38X
|
||||
bool
|
||||
|
||||
config ARMADA_XP
|
||||
bool
|
||||
|
||||
config MV78230
|
||||
bool
|
||||
select ARMADA_XP
|
||||
|
||||
config MV78260
|
||||
bool
|
||||
select ARMADA_XP
|
||||
|
||||
config MV78460
|
||||
bool
|
||||
select ARMADA_XP
|
||||
|
||||
config DB_88F6820_GP
|
||||
bool
|
||||
select ARMADA_38X
|
||||
|
||||
choice
|
||||
prompt "Marvell MVEBU (Armada XP/375/38x) board select"
|
||||
optional
|
||||
|
||||
config TARGET_CLEARFOG
|
||||
bool "Support ClearFog"
|
||||
select DB_88F6820_GP
|
||||
|
||||
config TARGET_DB_88F6720
|
||||
bool "Support DB-88F6720 Armada 375"
|
||||
select ARMADA_375
|
||||
|
||||
config TARGET_DB_88F6820_GP
|
||||
bool "Support DB-88F6820-GP"
|
||||
select DB_88F6820_GP
|
||||
|
||||
config TARGET_DB_MV784MP_GP
|
||||
bool "Support db-mv784mp-gp"
|
||||
select MV78460
|
||||
|
||||
config TARGET_DS414
|
||||
bool "Support Synology DS414"
|
||||
select MV78230
|
||||
|
||||
config TARGET_MAXBCM
|
||||
bool "Support maxbcm"
|
||||
select MV78460
|
||||
|
||||
config TARGET_THEADORABLE
|
||||
bool "Support theadorable Armada XP"
|
||||
select MV78260
|
||||
|
||||
endchoice
|
||||
|
||||
config SYS_BOARD
|
||||
default "clearfog" if TARGET_CLEARFOG
|
||||
default "db-88f6720" if TARGET_DB_88F6720
|
||||
default "db-88f6820-gp" if TARGET_DB_88F6820_GP
|
||||
default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
|
||||
default "ds414" if TARGET_DS414
|
||||
default "maxbcm" if TARGET_MAXBCM
|
||||
default "theadorable" if TARGET_THEADORABLE
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "clearfog" if TARGET_CLEARFOG
|
||||
default "db-88f6720" if TARGET_DB_88F6720
|
||||
default "db-88f6820-gp" if TARGET_DB_88F6820_GP
|
||||
default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
|
||||
default "ds414" if TARGET_DS414
|
||||
default "maxbcm" if TARGET_MAXBCM
|
||||
default "theadorable" if TARGET_THEADORABLE
|
||||
|
||||
config SYS_VENDOR
|
||||
default "Marvell" if TARGET_DB_MV784MP_GP
|
||||
default "Marvell" if TARGET_DB_88F6720
|
||||
default "Marvell" if TARGET_DB_88F6820_GP
|
||||
default "solidrun" if TARGET_CLEARFOG
|
||||
default "Synology" if TARGET_DS414
|
||||
|
||||
config SYS_SOC
|
||||
default "mvebu"
|
||||
|
||||
endif
|
||||
31
u-boot/arch/arm/mach-mvebu/Makefile
Normal file
31
u-boot/arch/arm/mach-mvebu/Makefile
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Copyright (C) 2014-2015 Stefan Roese <sr@denx.de>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
ifdef CONFIG_KIRKWOOD
|
||||
|
||||
obj-y = dram.o
|
||||
obj-y += gpio.o
|
||||
obj-y += timer.o
|
||||
|
||||
else
|
||||
|
||||
obj-y = cpu.o
|
||||
obj-y += dram.o
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
|
||||
obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
|
||||
obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
|
||||
endif
|
||||
obj-y += gpio.o
|
||||
obj-y += mbus.o
|
||||
obj-y += timer.o
|
||||
obj-$(CONFIG_SPL_BUILD) += spl.o
|
||||
obj-$(CONFIG_SPL_BUILD) += lowlevel_spl.o
|
||||
|
||||
obj-$(CONFIG_ARMADA_38X) += serdes/a38x/
|
||||
obj-$(CONFIG_ARMADA_XP) += serdes/axp/
|
||||
|
||||
endif
|
||||
580
u-boot/arch/arm/mach-mvebu/cpu.c
Normal file
580
u-boot/arch/arm/mach-mvebu/cpu.c
Normal file
@@ -0,0 +1,580 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Stefan Roese <sr@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <ahci.h>
|
||||
#include <linux/mbus.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/pl310.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <sdhci.h>
|
||||
|
||||
#define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3))
|
||||
#define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3))
|
||||
|
||||
static struct mbus_win windows[] = {
|
||||
/* SPI */
|
||||
{ MBUS_SPI_BASE, MBUS_SPI_SIZE,
|
||||
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPIFLASH },
|
||||
|
||||
/* NOR */
|
||||
{ MBUS_BOOTROM_BASE, MBUS_BOOTROM_SIZE,
|
||||
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_BOOTROM },
|
||||
};
|
||||
|
||||
void lowlevel_init(void)
|
||||
{
|
||||
/*
|
||||
* Dummy implementation, we only need LOWLEVEL_INIT
|
||||
* on Armada to configure CP15 in start.S / cpu_init_cp15()
|
||||
*/
|
||||
}
|
||||
|
||||
void reset_cpu(unsigned long ignored)
|
||||
{
|
||||
struct mvebu_system_registers *reg =
|
||||
(struct mvebu_system_registers *)MVEBU_SYSTEM_REG_BASE;
|
||||
|
||||
writel(readl(®->rstoutn_mask) | 1, ®->rstoutn_mask);
|
||||
writel(readl(®->sys_soft_rst) | 1, ®->sys_soft_rst);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
int mvebu_soc_family(void)
|
||||
{
|
||||
u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff;
|
||||
|
||||
switch (devid) {
|
||||
case SOC_MV78230_ID:
|
||||
case SOC_MV78260_ID:
|
||||
case SOC_MV78460_ID:
|
||||
return MVEBU_SOC_AXP;
|
||||
|
||||
case SOC_88F6720_ID:
|
||||
return MVEBU_SOC_A375;
|
||||
|
||||
case SOC_88F6810_ID:
|
||||
case SOC_88F6820_ID:
|
||||
case SOC_88F6828_ID:
|
||||
return MVEBU_SOC_A38X;
|
||||
}
|
||||
|
||||
return MVEBU_SOC_UNKNOWN;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO)
|
||||
|
||||
#if defined(CONFIG_ARMADA_375)
|
||||
/* SAR frequency values for Armada 375 */
|
||||
static const struct sar_freq_modes sar_freq_tab[] = {
|
||||
{ 0, 0x0, 266, 133, 266 },
|
||||
{ 1, 0x0, 333, 167, 167 },
|
||||
{ 2, 0x0, 333, 167, 222 },
|
||||
{ 3, 0x0, 333, 167, 333 },
|
||||
{ 4, 0x0, 400, 200, 200 },
|
||||
{ 5, 0x0, 400, 200, 267 },
|
||||
{ 6, 0x0, 400, 200, 400 },
|
||||
{ 7, 0x0, 500, 250, 250 },
|
||||
{ 8, 0x0, 500, 250, 334 },
|
||||
{ 9, 0x0, 500, 250, 500 },
|
||||
{ 10, 0x0, 533, 267, 267 },
|
||||
{ 11, 0x0, 533, 267, 356 },
|
||||
{ 12, 0x0, 533, 267, 533 },
|
||||
{ 13, 0x0, 600, 300, 300 },
|
||||
{ 14, 0x0, 600, 300, 400 },
|
||||
{ 15, 0x0, 600, 300, 600 },
|
||||
{ 16, 0x0, 666, 333, 333 },
|
||||
{ 17, 0x0, 666, 333, 444 },
|
||||
{ 18, 0x0, 666, 333, 666 },
|
||||
{ 19, 0x0, 800, 400, 267 },
|
||||
{ 20, 0x0, 800, 400, 400 },
|
||||
{ 21, 0x0, 800, 400, 534 },
|
||||
{ 22, 0x0, 900, 450, 300 },
|
||||
{ 23, 0x0, 900, 450, 450 },
|
||||
{ 24, 0x0, 900, 450, 600 },
|
||||
{ 25, 0x0, 1000, 500, 500 },
|
||||
{ 26, 0x0, 1000, 500, 667 },
|
||||
{ 27, 0x0, 1000, 333, 500 },
|
||||
{ 28, 0x0, 400, 400, 400 },
|
||||
{ 29, 0x0, 1100, 550, 550 },
|
||||
{ 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */
|
||||
};
|
||||
#elif defined(CONFIG_ARMADA_38X)
|
||||
/* SAR frequency values for Armada 38x */
|
||||
static const struct sar_freq_modes sar_freq_tab[] = {
|
||||
{ 0x0, 0x0, 666, 333, 333 },
|
||||
{ 0x2, 0x0, 800, 400, 400 },
|
||||
{ 0x4, 0x0, 1066, 533, 533 },
|
||||
{ 0x6, 0x0, 1200, 600, 600 },
|
||||
{ 0x8, 0x0, 1332, 666, 666 },
|
||||
{ 0xc, 0x0, 1600, 800, 800 },
|
||||
{ 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */
|
||||
};
|
||||
#else
|
||||
/* SAR frequency values for Armada XP */
|
||||
static const struct sar_freq_modes sar_freq_tab[] = {
|
||||
{ 0xa, 0x5, 800, 400, 400 },
|
||||
{ 0x1, 0x5, 1066, 533, 533 },
|
||||
{ 0x2, 0x5, 1200, 600, 600 },
|
||||
{ 0x2, 0x9, 1200, 600, 400 },
|
||||
{ 0x3, 0x5, 1333, 667, 667 },
|
||||
{ 0x4, 0x5, 1500, 750, 750 },
|
||||
{ 0x4, 0x9, 1500, 750, 500 },
|
||||
{ 0xb, 0x9, 1600, 800, 533 },
|
||||
{ 0xb, 0xa, 1600, 800, 640 },
|
||||
{ 0xb, 0x5, 1600, 800, 800 },
|
||||
{ 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */
|
||||
};
|
||||
#endif
|
||||
|
||||
void get_sar_freq(struct sar_freq_modes *sar_freq)
|
||||
{
|
||||
u32 val;
|
||||
u32 freq;
|
||||
int i;
|
||||
|
||||
#if defined(CONFIG_ARMADA_375)
|
||||
val = readl(CONFIG_SAR2_REG); /* SAR - Sample At Reset */
|
||||
#else
|
||||
val = readl(CONFIG_SAR_REG); /* SAR - Sample At Reset */
|
||||
#endif
|
||||
freq = (val & SAR_CPU_FREQ_MASK) >> SAR_CPU_FREQ_OFFS;
|
||||
#if defined(SAR2_CPU_FREQ_MASK)
|
||||
/*
|
||||
* Shift CPU0 clock frequency select bit from SAR2 register
|
||||
* into correct position
|
||||
*/
|
||||
freq |= ((readl(CONFIG_SAR2_REG) & SAR2_CPU_FREQ_MASK)
|
||||
>> SAR2_CPU_FREQ_OFFS) << 3;
|
||||
#endif
|
||||
for (i = 0; sar_freq_tab[i].val != 0xff; i++) {
|
||||
if (sar_freq_tab[i].val == freq) {
|
||||
#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_38X)
|
||||
*sar_freq = sar_freq_tab[i];
|
||||
return;
|
||||
#else
|
||||
int k;
|
||||
u8 ffc;
|
||||
|
||||
ffc = (val & SAR_FFC_FREQ_MASK) >>
|
||||
SAR_FFC_FREQ_OFFS;
|
||||
for (k = i; sar_freq_tab[k].ffc != 0xff; k++) {
|
||||
if (sar_freq_tab[k].ffc == ffc) {
|
||||
*sar_freq = sar_freq_tab[k];
|
||||
return;
|
||||
}
|
||||
}
|
||||
i = k;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* SAR value not found, return 0 for frequencies */
|
||||
*sar_freq = sar_freq_tab[i - 1];
|
||||
}
|
||||
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff;
|
||||
u8 revid = readl(MVEBU_REG_PCIE_REVID) & 0xff;
|
||||
struct sar_freq_modes sar_freq;
|
||||
|
||||
puts("SoC: ");
|
||||
|
||||
switch (devid) {
|
||||
case SOC_MV78230_ID:
|
||||
puts("MV78230-");
|
||||
break;
|
||||
case SOC_MV78260_ID:
|
||||
puts("MV78260-");
|
||||
break;
|
||||
case SOC_MV78460_ID:
|
||||
puts("MV78460-");
|
||||
break;
|
||||
case SOC_88F6720_ID:
|
||||
puts("MV88F6720-");
|
||||
break;
|
||||
case SOC_88F6810_ID:
|
||||
puts("MV88F6810-");
|
||||
break;
|
||||
case SOC_88F6820_ID:
|
||||
puts("MV88F6820-");
|
||||
break;
|
||||
case SOC_88F6828_ID:
|
||||
puts("MV88F6828-");
|
||||
break;
|
||||
default:
|
||||
puts("Unknown-");
|
||||
break;
|
||||
}
|
||||
|
||||
if (mvebu_soc_family() == MVEBU_SOC_AXP) {
|
||||
switch (revid) {
|
||||
case 1:
|
||||
puts("A0");
|
||||
break;
|
||||
case 2:
|
||||
puts("B0");
|
||||
break;
|
||||
default:
|
||||
printf("?? (%x)", revid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mvebu_soc_family() == MVEBU_SOC_A375) {
|
||||
switch (revid) {
|
||||
case MV_88F67XX_A0_ID:
|
||||
puts("A0");
|
||||
break;
|
||||
default:
|
||||
printf("?? (%x)", revid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mvebu_soc_family() == MVEBU_SOC_A38X) {
|
||||
switch (revid) {
|
||||
case MV_88F68XX_Z1_ID:
|
||||
puts("Z1");
|
||||
break;
|
||||
case MV_88F68XX_A0_ID:
|
||||
puts("A0");
|
||||
break;
|
||||
default:
|
||||
printf("?? (%x)", revid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
get_sar_freq(&sar_freq);
|
||||
printf(" at %d MHz\n", sar_freq.p_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DISPLAY_CPUINFO */
|
||||
|
||||
/*
|
||||
* This function initialize Controller DRAM Fastpath windows.
|
||||
* It takes the CS size information from the 0x1500 scratch registers
|
||||
* and sets the correct windows sizes and base addresses accordingly.
|
||||
*
|
||||
* These values are set in the scratch registers by the Marvell
|
||||
* DDR3 training code, which is executed by the BootROM before the
|
||||
* main payload (U-Boot) is executed. This training code is currently
|
||||
* only available in the Marvell U-Boot version. It needs to be
|
||||
* ported to mainline U-Boot SPL at some point.
|
||||
*/
|
||||
static void update_sdram_window_sizes(void)
|
||||
{
|
||||
u64 base = 0;
|
||||
u32 size, temp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SDRAM_MAX_CS; i++) {
|
||||
size = readl((MVEBU_SDRAM_SCRATCH + (i * 8))) & SDRAM_ADDR_MASK;
|
||||
if (size != 0) {
|
||||
size |= ~(SDRAM_ADDR_MASK);
|
||||
|
||||
/* Set Base Address */
|
||||
temp = (base & 0xFF000000ll) | ((base >> 32) & 0xF);
|
||||
writel(temp, MVEBU_SDRAM_BASE + DDR_BASE_CS_OFF(i));
|
||||
|
||||
/*
|
||||
* Check if out of max window size and resize
|
||||
* the window
|
||||
*/
|
||||
temp = (readl(MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i)) &
|
||||
~(SDRAM_ADDR_MASK)) | 1;
|
||||
temp |= (size & SDRAM_ADDR_MASK);
|
||||
writel(temp, MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i));
|
||||
|
||||
base += ((u64)size + 1);
|
||||
} else {
|
||||
/*
|
||||
* Disable window if not used, otherwise this
|
||||
* leads to overlapping enabled windows with
|
||||
* pretty strange results
|
||||
*/
|
||||
clrbits_le32(MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mmu_disable(void)
|
||||
{
|
||||
asm volatile(
|
||||
"mrc p15, 0, r0, c1, c0, 0\n"
|
||||
"bic r0, #1\n"
|
||||
"mcr p15, 0, r0, c1, c0, 0\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_CPU_INIT
|
||||
static void set_cbar(u32 addr)
|
||||
{
|
||||
asm("mcr p15, 4, %0, c15, c0" : : "r" (addr));
|
||||
}
|
||||
|
||||
#define MV_USB_PHY_BASE (MVEBU_AXP_USB_BASE + 0x800)
|
||||
#define MV_USB_PHY_PLL_REG(reg) (MV_USB_PHY_BASE | (((reg) & 0xF) << 2))
|
||||
#define MV_USB_X3_BASE(addr) (MVEBU_AXP_USB_BASE | BIT(11) | \
|
||||
(((addr) & 0xF) << 6))
|
||||
#define MV_USB_X3_PHY_CHANNEL(dev, reg) (MV_USB_X3_BASE((dev) + 1) | \
|
||||
(((reg) & 0xF) << 2))
|
||||
|
||||
static void setup_usb_phys(void)
|
||||
{
|
||||
int dev;
|
||||
|
||||
/*
|
||||
* USB PLL init
|
||||
*/
|
||||
|
||||
/* Setup PLL frequency */
|
||||
/* USB REF frequency = 25 MHz */
|
||||
clrsetbits_le32(MV_USB_PHY_PLL_REG(1), 0x3ff, 0x605);
|
||||
|
||||
/* Power up PLL and PHY channel */
|
||||
setbits_le32(MV_USB_PHY_PLL_REG(2), BIT(9));
|
||||
|
||||
/* Assert VCOCAL_START */
|
||||
setbits_le32(MV_USB_PHY_PLL_REG(1), BIT(21));
|
||||
|
||||
mdelay(1);
|
||||
|
||||
/*
|
||||
* USB PHY init (change from defaults) specific for 40nm (78X30 78X60)
|
||||
*/
|
||||
|
||||
for (dev = 0; dev < 3; dev++) {
|
||||
setbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 3), BIT(15));
|
||||
|
||||
/* Assert REG_RCAL_START in channel REG 1 */
|
||||
setbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12));
|
||||
udelay(40);
|
||||
clrbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is not called from the SPL U-Boot version
|
||||
*/
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
struct pl310_regs *const pl310 =
|
||||
(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
|
||||
|
||||
/*
|
||||
* Only with disabled MMU its possible to switch the base
|
||||
* register address on Armada 38x. Without this the SDRAM
|
||||
* located at >= 0x4000.0000 is also not accessible, as its
|
||||
* still locked to cache.
|
||||
*/
|
||||
mmu_disable();
|
||||
|
||||
/* Linux expects the internal registers to be at 0xf1000000 */
|
||||
writel(SOC_REGS_PHY_BASE, INTREG_BASE_ADDR_REG);
|
||||
set_cbar(SOC_REGS_PHY_BASE + 0xC000);
|
||||
|
||||
/*
|
||||
* From this stage on, the SoC detection is working. As we have
|
||||
* configured the internal register base to the value used
|
||||
* in the macros / defines in the U-Boot header (soc.h).
|
||||
*/
|
||||
|
||||
if (mvebu_soc_family() == MVEBU_SOC_A38X) {
|
||||
/*
|
||||
* To fully release / unlock this area from cache, we need
|
||||
* to flush all caches and disable the L2 cache.
|
||||
*/
|
||||
icache_disable();
|
||||
dcache_disable();
|
||||
clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to call mvebu_mbus_probe() before calling
|
||||
* update_sdram_window_sizes() as it disables all previously
|
||||
* configured mbus windows and then configures them as
|
||||
* required for U-Boot. Calling update_sdram_window_sizes()
|
||||
* without this configuration will not work, as the internal
|
||||
* registers can't be accessed reliably because of potenial
|
||||
* double mapping.
|
||||
* After updating the SDRAM access windows we need to call
|
||||
* mvebu_mbus_probe() again, as this now correctly configures
|
||||
* the SDRAM areas that are later used by the MVEBU drivers
|
||||
* (e.g. USB, NETA).
|
||||
*/
|
||||
|
||||
/*
|
||||
* First disable all windows
|
||||
*/
|
||||
mvebu_mbus_probe(NULL, 0);
|
||||
|
||||
if (mvebu_soc_family() == MVEBU_SOC_AXP) {
|
||||
/*
|
||||
* Now the SDRAM access windows can be reconfigured using
|
||||
* the information in the SDRAM scratch pad registers
|
||||
*/
|
||||
update_sdram_window_sizes();
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally the mbus windows can be configured with the
|
||||
* updated SDRAM sizes
|
||||
*/
|
||||
mvebu_mbus_probe(windows, ARRAY_SIZE(windows));
|
||||
|
||||
if (mvebu_soc_family() == MVEBU_SOC_AXP) {
|
||||
/* Enable GBE0, GBE1, LCD and NFC PUP */
|
||||
clrsetbits_le32(ARMADA_XP_PUP_ENABLE, 0,
|
||||
GE0_PUP_EN | GE1_PUP_EN | LCD_PUP_EN |
|
||||
NAND_PUP_EN | SPI_PUP_EN);
|
||||
|
||||
/* Configure USB PLL and PHYs on AXP */
|
||||
setup_usb_phys();
|
||||
}
|
||||
|
||||
/* Enable NAND and NAND arbiter */
|
||||
clrsetbits_le32(MVEBU_SOC_DEV_MUX_REG, 0, NAND_EN | NAND_ARBITER_EN);
|
||||
|
||||
/* Disable MBUS error propagation */
|
||||
clrsetbits_le32(SOC_COHERENCY_FABRIC_CTRL_REG, MBUS_ERR_PROP_EN, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ARCH_CPU_INIT */
|
||||
|
||||
u32 mvebu_get_nand_clock(void)
|
||||
{
|
||||
return CONFIG_SYS_MVEBU_PLL_CLOCK /
|
||||
((readl(MVEBU_CORE_DIV_CLK_CTRL(1)) &
|
||||
NAND_ECC_DIVCKL_RATIO_MASK) >> NAND_ECC_DIVCKL_RATIO_OFFS);
|
||||
}
|
||||
|
||||
/*
|
||||
* SOC specific misc init
|
||||
*/
|
||||
#if defined(CONFIG_ARCH_MISC_INIT)
|
||||
int arch_misc_init(void)
|
||||
{
|
||||
/* Nothing yet, perhaps we need something here later */
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ARCH_MISC_INIT */
|
||||
|
||||
#ifdef CONFIG_MV_SDHCI
|
||||
int board_mmc_init(bd_t *bis)
|
||||
{
|
||||
mv_sdh_init(MVEBU_SDIO_BASE, 0, 0,
|
||||
SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCSI_AHCI_PLAT
|
||||
#define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0
|
||||
#define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4
|
||||
|
||||
#define AHCI_WINDOW_CTRL(win) (0x60 + ((win) << 4))
|
||||
#define AHCI_WINDOW_BASE(win) (0x64 + ((win) << 4))
|
||||
#define AHCI_WINDOW_SIZE(win) (0x68 + ((win) << 4))
|
||||
|
||||
static void ahci_mvebu_mbus_config(void __iomem *base)
|
||||
{
|
||||
const struct mbus_dram_target_info *dram;
|
||||
int i;
|
||||
|
||||
dram = mvebu_mbus_dram_info();
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
writel(0, base + AHCI_WINDOW_CTRL(i));
|
||||
writel(0, base + AHCI_WINDOW_BASE(i));
|
||||
writel(0, base + AHCI_WINDOW_SIZE(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < dram->num_cs; i++) {
|
||||
const struct mbus_dram_window *cs = dram->cs + i;
|
||||
|
||||
writel((cs->mbus_attr << 8) |
|
||||
(dram->mbus_dram_target_id << 4) | 1,
|
||||
base + AHCI_WINDOW_CTRL(i));
|
||||
writel(cs->base >> 16, base + AHCI_WINDOW_BASE(i));
|
||||
writel(((cs->size - 1) & 0xffff0000),
|
||||
base + AHCI_WINDOW_SIZE(i));
|
||||
}
|
||||
}
|
||||
|
||||
static void ahci_mvebu_regret_option(void __iomem *base)
|
||||
{
|
||||
/*
|
||||
* Enable the regret bit to allow the SATA unit to regret a
|
||||
* request that didn't receive an acknowlegde and avoid a
|
||||
* deadlock
|
||||
*/
|
||||
writel(0x4, base + AHCI_VENDOR_SPECIFIC_0_ADDR);
|
||||
writel(0x80, base + AHCI_VENDOR_SPECIFIC_0_DATA);
|
||||
}
|
||||
|
||||
void scsi_init(void)
|
||||
{
|
||||
printf("MVEBU SATA INIT\n");
|
||||
ahci_mvebu_mbus_config((void __iomem *)MVEBU_SATA0_BASE);
|
||||
ahci_mvebu_regret_option((void __iomem *)MVEBU_SATA0_BASE);
|
||||
ahci_init((void __iomem *)MVEBU_SATA0_BASE);
|
||||
}
|
||||
#endif
|
||||
|
||||
void enable_caches(void)
|
||||
{
|
||||
/* Avoid problem with e.g. neta ethernet driver */
|
||||
invalidate_dcache_all();
|
||||
|
||||
/*
|
||||
* Armada 375 still has some problems with d-cache enabled in the
|
||||
* ethernet driver (mvpp2). So lets keep the d-cache disabled
|
||||
* until this is solved.
|
||||
*/
|
||||
if (mvebu_soc_family() != MVEBU_SOC_A375) {
|
||||
/* Enable D-cache. I-cache is already enabled in start.S */
|
||||
dcache_enable();
|
||||
}
|
||||
}
|
||||
|
||||
void v7_outer_cache_enable(void)
|
||||
{
|
||||
if (mvebu_soc_family() == MVEBU_SOC_AXP) {
|
||||
struct pl310_regs *const pl310 =
|
||||
(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
|
||||
u32 u;
|
||||
|
||||
/* The L2 cache is already disabled at this point */
|
||||
|
||||
/*
|
||||
* For Aurora cache in no outer mode, enable via the CP15
|
||||
* coprocessor broadcasting of cache commands to L2.
|
||||
*/
|
||||
asm volatile("mrc p15, 1, %0, c15, c2, 0" : "=r" (u));
|
||||
u |= BIT(8); /* Set the FW bit */
|
||||
asm volatile("mcr p15, 1, %0, c15, c2, 0" : : "r" (u));
|
||||
|
||||
isb();
|
||||
|
||||
/* Enable the L2 cache */
|
||||
setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
|
||||
}
|
||||
}
|
||||
|
||||
void v7_outer_cache_disable(void)
|
||||
{
|
||||
struct pl310_regs *const pl310 =
|
||||
(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
|
||||
|
||||
clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
|
||||
}
|
||||
306
u-boot/arch/arm/mach-mvebu/dram.c
Normal file
306
u-boot/arch/arm/mach-mvebu/dram.c
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* (C) Copyright 2009
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
#if defined(CONFIG_ARCH_MVEBU)
|
||||
/* Use common XOR definitions for A3x and AXP */
|
||||
#include "../../../drivers/ddr/marvell/axp/xor.h"
|
||||
#include "../../../drivers/ddr/marvell/axp/xor_regs.h"
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct sdram_bank {
|
||||
u32 win_bar;
|
||||
u32 win_sz;
|
||||
};
|
||||
|
||||
struct sdram_addr_dec {
|
||||
struct sdram_bank sdram_bank[4];
|
||||
};
|
||||
|
||||
#define REG_CPUCS_WIN_ENABLE (1 << 0)
|
||||
#define REG_CPUCS_WIN_WR_PROTECT (1 << 1)
|
||||
#define REG_CPUCS_WIN_WIN0_CS(x) (((x) & 0x3) << 2)
|
||||
#define REG_CPUCS_WIN_SIZE(x) (((x) & 0xff) << 24)
|
||||
|
||||
#define SDRAM_SIZE_MAX 0xc0000000
|
||||
|
||||
#define SCRUB_MAGIC 0xbeefdead
|
||||
|
||||
#define SCRB_XOR_UNIT 0
|
||||
#define SCRB_XOR_CHAN 1
|
||||
#define SCRB_XOR_WIN 0
|
||||
|
||||
#define XEBARX_BASE_OFFS 16
|
||||
|
||||
/*
|
||||
* mvebu_sdram_bar - reads SDRAM Base Address Register
|
||||
*/
|
||||
u32 mvebu_sdram_bar(enum memory_bank bank)
|
||||
{
|
||||
struct sdram_addr_dec *base =
|
||||
(struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
|
||||
u32 result = 0;
|
||||
u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
|
||||
|
||||
if ((!enable) || (bank > BANK3))
|
||||
return 0;
|
||||
|
||||
result = readl(&base->sdram_bank[bank].win_bar);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* mvebu_sdram_bs_set - writes SDRAM Bank size
|
||||
*/
|
||||
static void mvebu_sdram_bs_set(enum memory_bank bank, u32 size)
|
||||
{
|
||||
struct sdram_addr_dec *base =
|
||||
(struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
|
||||
/* Read current register value */
|
||||
u32 reg = readl(&base->sdram_bank[bank].win_sz);
|
||||
|
||||
/* Clear window size */
|
||||
reg &= ~REG_CPUCS_WIN_SIZE(0xFF);
|
||||
|
||||
/* Set new window size */
|
||||
reg |= REG_CPUCS_WIN_SIZE((size - 1) >> 24);
|
||||
|
||||
writel(reg, &base->sdram_bank[bank].win_sz);
|
||||
}
|
||||
|
||||
/*
|
||||
* mvebu_sdram_bs - reads SDRAM Bank size
|
||||
*/
|
||||
u32 mvebu_sdram_bs(enum memory_bank bank)
|
||||
{
|
||||
struct sdram_addr_dec *base =
|
||||
(struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
|
||||
u32 result = 0;
|
||||
u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
|
||||
|
||||
if ((!enable) || (bank > BANK3))
|
||||
return 0;
|
||||
result = 0xff000000 & readl(&base->sdram_bank[bank].win_sz);
|
||||
result += 0x01000000;
|
||||
return result;
|
||||
}
|
||||
|
||||
void mvebu_sdram_size_adjust(enum memory_bank bank)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
/* probe currently equipped RAM size */
|
||||
size = get_ram_size((void *)mvebu_sdram_bar(bank),
|
||||
mvebu_sdram_bs(bank));
|
||||
|
||||
/* adjust SDRAM window size accordingly */
|
||||
mvebu_sdram_bs_set(bank, size);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_MVEBU)
|
||||
static u32 xor_ctrl_save;
|
||||
static u32 xor_base_save;
|
||||
static u32 xor_mask_save;
|
||||
|
||||
static void mv_xor_init2(u32 cs)
|
||||
{
|
||||
u32 reg, base, size, base2;
|
||||
u32 bank_attr[4] = { 0xe00, 0xd00, 0xb00, 0x700 };
|
||||
|
||||
xor_ctrl_save = reg_read(XOR_WINDOW_CTRL_REG(SCRB_XOR_UNIT,
|
||||
SCRB_XOR_CHAN));
|
||||
xor_base_save = reg_read(XOR_BASE_ADDR_REG(SCRB_XOR_UNIT,
|
||||
SCRB_XOR_WIN));
|
||||
xor_mask_save = reg_read(XOR_SIZE_MASK_REG(SCRB_XOR_UNIT,
|
||||
SCRB_XOR_WIN));
|
||||
|
||||
/* Enable Window x for each CS */
|
||||
reg = 0x1;
|
||||
reg |= (0x3 << 16);
|
||||
reg_write(XOR_WINDOW_CTRL_REG(SCRB_XOR_UNIT, SCRB_XOR_CHAN), reg);
|
||||
|
||||
base = 0;
|
||||
size = mvebu_sdram_bs(cs) - 1;
|
||||
if (size) {
|
||||
base2 = ((base / (64 << 10)) << XEBARX_BASE_OFFS) |
|
||||
bank_attr[cs];
|
||||
reg_write(XOR_BASE_ADDR_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN),
|
||||
base2);
|
||||
|
||||
base += size + 1;
|
||||
size = (size / (64 << 10)) << 16;
|
||||
/* Window x - size - 256 MB */
|
||||
reg_write(XOR_SIZE_MASK_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN), size);
|
||||
}
|
||||
|
||||
mv_xor_hal_init(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void mv_xor_finish2(void)
|
||||
{
|
||||
reg_write(XOR_WINDOW_CTRL_REG(SCRB_XOR_UNIT, SCRB_XOR_CHAN),
|
||||
xor_ctrl_save);
|
||||
reg_write(XOR_BASE_ADDR_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN),
|
||||
xor_base_save);
|
||||
reg_write(XOR_SIZE_MASK_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN),
|
||||
xor_mask_save);
|
||||
}
|
||||
|
||||
static void dram_ecc_scrubbing(void)
|
||||
{
|
||||
int cs;
|
||||
u32 size, temp;
|
||||
u32 total_mem = 0;
|
||||
u64 total;
|
||||
u32 start_addr;
|
||||
|
||||
/*
|
||||
* The DDR training code from the bin_hdr / SPL already
|
||||
* scrubbed the DDR till 0x1000000. And the main U-Boot
|
||||
* is loaded to an address < 0x1000000. So we need to
|
||||
* skip this range to not re-scrub this area again.
|
||||
*/
|
||||
temp = reg_read(REG_SDRAM_CONFIG_ADDR);
|
||||
temp |= (1 << REG_SDRAM_CONFIG_IERR_OFFS);
|
||||
reg_write(REG_SDRAM_CONFIG_ADDR, temp);
|
||||
|
||||
for (cs = 0; cs < CONFIG_NR_DRAM_BANKS; cs++) {
|
||||
size = mvebu_sdram_bs(cs) - 1;
|
||||
if (size == 0)
|
||||
continue;
|
||||
|
||||
total = (u64)size + 1;
|
||||
total_mem += (u32)(total / (1 << 30));
|
||||
start_addr = 0;
|
||||
mv_xor_init2(cs);
|
||||
|
||||
/* Skip first 16 MiB */
|
||||
if (0 == cs) {
|
||||
start_addr = 0x1000000;
|
||||
size -= start_addr;
|
||||
}
|
||||
|
||||
mv_xor_mem_init(SCRB_XOR_CHAN, start_addr, size,
|
||||
SCRUB_MAGIC, SCRUB_MAGIC);
|
||||
|
||||
/* Wait for previous transfer completion */
|
||||
while (mv_xor_state_get(SCRB_XOR_CHAN) != MV_IDLE)
|
||||
;
|
||||
|
||||
mv_xor_finish2();
|
||||
}
|
||||
|
||||
temp = reg_read(REG_SDRAM_CONFIG_ADDR);
|
||||
temp &= ~(1 << REG_SDRAM_CONFIG_IERR_OFFS);
|
||||
reg_write(REG_SDRAM_CONFIG_ADDR, temp);
|
||||
}
|
||||
|
||||
static int ecc_enabled(void)
|
||||
{
|
||||
if (reg_read(REG_SDRAM_CONFIG_ADDR) & (1 << REG_SDRAM_CONFIG_ECC_OFFS))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static void dram_ecc_scrubbing(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int ecc_enabled(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
u64 size = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
||||
/*
|
||||
* It is assumed that all memory banks are consecutive
|
||||
* and without gaps.
|
||||
* If the gap is found, ram_size will be reported for
|
||||
* consecutive memory only
|
||||
*/
|
||||
if (mvebu_sdram_bar(i) != size)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Don't report more than 3GiB of SDRAM, otherwise there is no
|
||||
* address space left for the internal registers etc.
|
||||
*/
|
||||
size += mvebu_sdram_bs(i);
|
||||
if (size > SDRAM_SIZE_MAX)
|
||||
size = SDRAM_SIZE_MAX;
|
||||
}
|
||||
|
||||
for (; i < CONFIG_NR_DRAM_BANKS; i++) {
|
||||
/* If above loop terminated prematurely, we need to set
|
||||
* remaining banks' start address & size as 0. Otherwise other
|
||||
* u-boot functions and Linux kernel gets wrong values which
|
||||
* could result in crash */
|
||||
gd->bd->bi_dram[i].start = 0;
|
||||
gd->bd->bi_dram[i].size = 0;
|
||||
}
|
||||
|
||||
|
||||
if (ecc_enabled())
|
||||
dram_ecc_scrubbing();
|
||||
|
||||
gd->ram_size = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this function is not defined here,
|
||||
* board.c alters dram bank zero configuration defined above.
|
||||
*/
|
||||
void dram_init_banksize(void)
|
||||
{
|
||||
u64 size = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
||||
gd->bd->bi_dram[i].start = mvebu_sdram_bar(i);
|
||||
gd->bd->bi_dram[i].size = mvebu_sdram_bs(i);
|
||||
|
||||
/* Clip the banksize to 1GiB if it exceeds the max size */
|
||||
size += gd->bd->bi_dram[i].size;
|
||||
if (size > SDRAM_SIZE_MAX)
|
||||
mvebu_sdram_bs_set(i, 0x40000000);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_MVEBU)
|
||||
void board_add_ram_info(int use_default)
|
||||
{
|
||||
struct sar_freq_modes sar_freq;
|
||||
|
||||
get_sar_freq(&sar_freq);
|
||||
printf(" (%d MHz, ", sar_freq.d_clk);
|
||||
|
||||
if (ecc_enabled())
|
||||
printf("ECC");
|
||||
else
|
||||
printf("ECC not");
|
||||
printf(" enabled)");
|
||||
}
|
||||
#endif
|
||||
30
u-boot/arch/arm/mach-mvebu/gpio.c
Normal file
30
u-boot/arch/arm/mach-mvebu/gpio.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* (C) Copyright 2009
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
/*
|
||||
* mvebu_config_gpio - GPIO configuration
|
||||
*/
|
||||
void mvebu_config_gpio(u32 gpp0_oe_val, u32 gpp1_oe_val,
|
||||
u32 gpp0_oe, u32 gpp1_oe)
|
||||
{
|
||||
struct kwgpio_registers *gpio0reg =
|
||||
(struct kwgpio_registers *)MVEBU_GPIO0_BASE;
|
||||
struct kwgpio_registers *gpio1reg =
|
||||
(struct kwgpio_registers *)MVEBU_GPIO1_BASE;
|
||||
|
||||
/* Init GPIOS to default values as per board requirement */
|
||||
writel(gpp0_oe_val, &gpio0reg->dout);
|
||||
writel(gpp1_oe_val, &gpio1reg->dout);
|
||||
writel(gpp0_oe, &gpio0reg->oe);
|
||||
writel(gpp1_oe, &gpio1reg->oe);
|
||||
}
|
||||
107
u-boot/arch/arm/mach-mvebu/include/mach/config.h
Normal file
107
u-boot/arch/arm/mach-mvebu/include/mach/config.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* (C) Copyright 2011
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Lei Wen <leiwen@marvell.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file should be included in board config header file.
|
||||
*
|
||||
* It supports common definitions for MVEBU platforms
|
||||
*/
|
||||
|
||||
#ifndef _MVEBU_CONFIG_H
|
||||
#define _MVEBU_CONFIG_H
|
||||
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
#if defined(CONFIG_ARMADA_XP) || defined(CONFIG_ARMADA_375) \
|
||||
|| defined(CONFIG_ARMADA_38X)
|
||||
/*
|
||||
* Set this for the common xor register definitions needed in dram.c
|
||||
* for A38x as well here.
|
||||
*/
|
||||
#define MV88F78X60 /* for the DDR training bin_hdr code */
|
||||
#endif
|
||||
|
||||
#define CONFIG_SYS_CACHELINE_SIZE 32
|
||||
|
||||
#define CONFIG_SYS_L2_PL310
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* By default kwbimage.cfg from board specific folder is used
|
||||
* If for some board, different configuration file need to be used,
|
||||
* CONFIG_SYS_KWD_CONFIG should be defined in board specific header file
|
||||
*/
|
||||
#ifndef CONFIG_SYS_KWD_CONFIG
|
||||
#define CONFIG_SYS_KWD_CONFIG $(CONFIG_BOARDDIR)/kwbimage.cfg
|
||||
#endif /* CONFIG_SYS_KWD_CONFIG */
|
||||
|
||||
/* Add target to build it automatically upon "make" */
|
||||
#ifdef CONFIG_SPL
|
||||
#define CONFIG_BUILD_TARGET "u-boot-spl.kwb"
|
||||
#endif
|
||||
|
||||
/* end of 16M scrubbed by training in bootrom */
|
||||
#define CONFIG_SYS_INIT_SP_ADDR 0x00FF0000
|
||||
#define CONFIG_NR_DRAM_BANKS_MAX 2
|
||||
|
||||
#define MV_UART_CONSOLE_BASE MVEBU_UART0_BASE
|
||||
|
||||
/*
|
||||
* SPI Flash configuration
|
||||
*/
|
||||
#ifdef CONFIG_CMD_SF
|
||||
#define CONFIG_KIRKWOOD_SPI
|
||||
#ifndef CONFIG_ENV_SPI_BUS
|
||||
# define CONFIG_ENV_SPI_BUS 0
|
||||
#endif
|
||||
#ifndef CONFIG_ENV_SPI_CS
|
||||
# define CONFIG_ENV_SPI_CS 0
|
||||
#endif
|
||||
#ifndef CONFIG_ENV_SPI_MAX_HZ
|
||||
# define CONFIG_ENV_SPI_MAX_HZ 50000000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Needed for SPI NOR booting in SPL */
|
||||
#define CONFIG_DM_SEQ_ALIAS 1
|
||||
|
||||
/*
|
||||
* Ethernet Driver configuration
|
||||
*/
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#define CONFIG_MII /* expose smi ove miiphy interface */
|
||||
#if !defined(CONFIG_ARMADA_375)
|
||||
#define CONFIG_MVNETA /* Enable Marvell Gbe Controller Driver */
|
||||
#define CONFIG_PHYLIB
|
||||
#endif
|
||||
#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */
|
||||
#define CONFIG_PHY_GIGE /* GbE speed/duplex detect */
|
||||
#define CONFIG_ARP_TIMEOUT 200
|
||||
#define CONFIG_NET_RETRY_COUNT 50
|
||||
#endif /* CONFIG_CMD_NET */
|
||||
|
||||
/*
|
||||
* I2C related stuff
|
||||
*/
|
||||
#ifdef CONFIG_CMD_I2C
|
||||
#ifndef CONFIG_SYS_I2C_SOFT
|
||||
#define CONFIG_I2C_MVTWSI
|
||||
#endif
|
||||
#define CONFIG_SYS_I2C_SLAVE 0x0
|
||||
#define CONFIG_SYS_I2C_SPEED 100000
|
||||
#endif
|
||||
|
||||
/* Use common timer */
|
||||
#define CONFIG_SYS_TIMER_COUNTS_DOWN
|
||||
#define CONFIG_SYS_TIMER_COUNTER (MVEBU_TIMER_BASE + 0x14)
|
||||
#define CONFIG_SYS_TIMER_RATE 25000000
|
||||
|
||||
#endif /* __MVEBU_CONFIG_H */
|
||||
170
u-boot/arch/arm/mach-mvebu/include/mach/cpu.h
Normal file
170
u-boot/arch/arm/mach-mvebu/include/mach/cpu.h
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* (C) Copyright 2009
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _MVEBU_CPU_H
|
||||
#define _MVEBU_CPU_H
|
||||
|
||||
#include <asm/system.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#define MVEBU_REG_PCIE_DEVID (MVEBU_REG_PCIE_BASE + 0x00)
|
||||
#define MVEBU_REG_PCIE_REVID (MVEBU_REG_PCIE_BASE + 0x08)
|
||||
|
||||
enum memory_bank {
|
||||
BANK0,
|
||||
BANK1,
|
||||
BANK2,
|
||||
BANK3
|
||||
};
|
||||
|
||||
enum cpu_winen {
|
||||
CPU_WIN_DISABLE,
|
||||
CPU_WIN_ENABLE
|
||||
};
|
||||
|
||||
enum cpu_target {
|
||||
CPU_TARGET_DRAM = 0x0,
|
||||
CPU_TARGET_DEVICEBUS_BOOTROM_SPI = 0x1,
|
||||
CPU_TARGET_ETH23 = 0x3,
|
||||
CPU_TARGET_PCIE02 = 0x4,
|
||||
CPU_TARGET_ETH01 = 0x7,
|
||||
CPU_TARGET_PCIE13 = 0x8,
|
||||
CPU_TARGET_SASRAM = 0x9,
|
||||
CPU_TARGET_NAND = 0xd,
|
||||
};
|
||||
|
||||
enum cpu_attrib {
|
||||
CPU_ATTR_SASRAM = 0x01,
|
||||
CPU_ATTR_DRAM_CS0 = 0x0e,
|
||||
CPU_ATTR_DRAM_CS1 = 0x0d,
|
||||
CPU_ATTR_DRAM_CS2 = 0x0b,
|
||||
CPU_ATTR_DRAM_CS3 = 0x07,
|
||||
CPU_ATTR_NANDFLASH = 0x2f,
|
||||
CPU_ATTR_SPIFLASH = 0x1e,
|
||||
CPU_ATTR_SPI0_CS0 = 0x1e,
|
||||
CPU_ATTR_SPI0_CS1 = 0x5e,
|
||||
CPU_ATTR_SPI1_CS2 = 0x9a,
|
||||
CPU_ATTR_BOOTROM = 0x1d,
|
||||
CPU_ATTR_PCIE_IO = 0xe0,
|
||||
CPU_ATTR_PCIE_MEM = 0xe8,
|
||||
CPU_ATTR_DEV_CS0 = 0x3e,
|
||||
CPU_ATTR_DEV_CS1 = 0x3d,
|
||||
CPU_ATTR_DEV_CS2 = 0x3b,
|
||||
CPU_ATTR_DEV_CS3 = 0x37,
|
||||
};
|
||||
|
||||
enum {
|
||||
MVEBU_SOC_AXP,
|
||||
MVEBU_SOC_A375,
|
||||
MVEBU_SOC_A38X,
|
||||
MVEBU_SOC_UNKNOWN,
|
||||
};
|
||||
|
||||
/*
|
||||
* Default Device Address MAP BAR values
|
||||
*/
|
||||
#define MBUS_PCI_MEM_BASE 0xE8000000
|
||||
#define MBUS_PCI_MEM_SIZE (128 << 20)
|
||||
#define MBUS_PCI_IO_BASE 0xF1100000
|
||||
#define MBUS_PCI_IO_SIZE (64 << 10)
|
||||
#define MBUS_SPI_BASE 0xF4000000
|
||||
#define MBUS_SPI_SIZE (8 << 20)
|
||||
#define MBUS_BOOTROM_BASE 0xF8000000
|
||||
#define MBUS_BOOTROM_SIZE (8 << 20)
|
||||
|
||||
struct mbus_win {
|
||||
u32 base;
|
||||
u32 size;
|
||||
u8 target;
|
||||
u8 attr;
|
||||
};
|
||||
|
||||
/*
|
||||
* System registers
|
||||
* Ref: Datasheet sec:A.28
|
||||
*/
|
||||
struct mvebu_system_registers {
|
||||
#if defined(CONFIG_ARMADA_375)
|
||||
u8 pad1[0x54];
|
||||
#else
|
||||
u8 pad1[0x60];
|
||||
#endif
|
||||
u32 rstoutn_mask; /* 0x60 */
|
||||
u32 sys_soft_rst; /* 0x64 */
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO Registers
|
||||
* Ref: Datasheet sec:A.19
|
||||
*/
|
||||
struct kwgpio_registers {
|
||||
u32 dout;
|
||||
u32 oe;
|
||||
u32 blink_en;
|
||||
u32 din_pol;
|
||||
u32 din;
|
||||
u32 irq_cause;
|
||||
u32 irq_mask;
|
||||
u32 irq_level;
|
||||
};
|
||||
|
||||
struct sar_freq_modes {
|
||||
u8 val;
|
||||
u8 ffc; /* Fabric Frequency Configuration */
|
||||
u32 p_clk;
|
||||
u32 nb_clk;
|
||||
u32 d_clk;
|
||||
};
|
||||
|
||||
/* Needed for dynamic (board-specific) mbus configuration */
|
||||
extern struct mvebu_mbus_state mbus_state;
|
||||
|
||||
/*
|
||||
* functions
|
||||
*/
|
||||
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);
|
||||
int mvebu_soc_family(void);
|
||||
u32 mvebu_get_nand_clock(void);
|
||||
|
||||
void return_to_bootrom(void);
|
||||
|
||||
int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks);
|
||||
|
||||
void get_sar_freq(struct sar_freq_modes *sar_freq);
|
||||
|
||||
/*
|
||||
* 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/marvell
|
||||
*/
|
||||
int ddr3_init(void);
|
||||
|
||||
struct mvebu_lcd_info {
|
||||
u32 fb_base;
|
||||
int x_res;
|
||||
int y_res;
|
||||
int x_fp; /* frontporch */
|
||||
int y_fp;
|
||||
int x_bp; /* backporch */
|
||||
int y_bp;
|
||||
};
|
||||
|
||||
int mvebu_lcd_register_init(struct mvebu_lcd_info *lcd_info);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _MVEBU_CPU_H */
|
||||
10
u-boot/arch/arm/mach-mvebu/include/mach/gpio.h
Normal file
10
u-boot/arch/arm/mach-mvebu/include/mach/gpio.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __MACH_MVEBU_GPIO_H
|
||||
#define __MACH_MVEBU_GPIO_H
|
||||
|
||||
/* Empty file - sdhci requires this. */
|
||||
|
||||
#endif
|
||||
164
u-boot/arch/arm/mach-mvebu/include/mach/soc.h
Normal file
164
u-boot/arch/arm/mach-mvebu/include/mach/soc.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* (C) Copyright 2009
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*
|
||||
* Header file for the Marvell's Feroceon CPU core.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _MVEBU_SOC_H
|
||||
#define _MVEBU_SOC_H
|
||||
|
||||
#define SOC_MV78230_ID 0x7823
|
||||
#define SOC_MV78260_ID 0x7826
|
||||
#define SOC_MV78460_ID 0x7846
|
||||
#define SOC_88F6720_ID 0x6720
|
||||
#define SOC_88F6810_ID 0x6810
|
||||
#define SOC_88F6820_ID 0x6820
|
||||
#define SOC_88F6828_ID 0x6828
|
||||
|
||||
/* A375 revisions */
|
||||
#define MV_88F67XX_A0_ID 0x3
|
||||
|
||||
/* A38x revisions */
|
||||
#define MV_88F68XX_Z1_ID 0x0
|
||||
#define MV_88F68XX_A0_ID 0x4
|
||||
|
||||
/* TCLK Core Clock definition */
|
||||
#ifndef CONFIG_SYS_TCLK
|
||||
#define CONFIG_SYS_TCLK 250000000 /* 250MHz */
|
||||
#endif
|
||||
|
||||
/* Armada XP PLL frequency (used for NAND clock generation) */
|
||||
#define CONFIG_SYS_MVEBU_PLL_CLOCK 2000000000
|
||||
|
||||
/* SOC specific definations */
|
||||
#define INTREG_BASE 0xd0000000
|
||||
#define INTREG_BASE_ADDR_REG (INTREG_BASE + 0x20080)
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
/*
|
||||
* The SPL U-Boot version still runs with the default
|
||||
* address for the internal registers, configured by
|
||||
* the BootROM. Only the main U-Boot version uses the
|
||||
* new internal register base address, that also is
|
||||
* required for the Linux kernel.
|
||||
*/
|
||||
#define SOC_REGS_PHY_BASE 0xd0000000
|
||||
#else
|
||||
#define SOC_REGS_PHY_BASE 0xf1000000
|
||||
#endif
|
||||
#define MVEBU_REGISTER(x) (SOC_REGS_PHY_BASE + x)
|
||||
|
||||
#define MVEBU_SDRAM_SCRATCH (MVEBU_REGISTER(0x01504))
|
||||
#define MVEBU_L2_CACHE_BASE (MVEBU_REGISTER(0x08000))
|
||||
#define CONFIG_SYS_PL310_BASE MVEBU_L2_CACHE_BASE
|
||||
#define MVEBU_TWSI_BASE (MVEBU_REGISTER(0x11000))
|
||||
#define MVEBU_TWSI1_BASE (MVEBU_REGISTER(0x11100))
|
||||
#define MVEBU_MPP_BASE (MVEBU_REGISTER(0x18000))
|
||||
#define MVEBU_GPIO0_BASE (MVEBU_REGISTER(0x18100))
|
||||
#define MVEBU_GPIO1_BASE (MVEBU_REGISTER(0x18140))
|
||||
#define MVEBU_GPIO2_BASE (MVEBU_REGISTER(0x18180))
|
||||
#define MVEBU_SYSTEM_REG_BASE (MVEBU_REGISTER(0x18200))
|
||||
#define MVEBU_CLOCK_BASE (MVEBU_REGISTER(0x18700))
|
||||
#define MVEBU_CPU_WIN_BASE (MVEBU_REGISTER(0x20000))
|
||||
#define MVEBU_SDRAM_BASE (MVEBU_REGISTER(0x20180))
|
||||
#define MVEBU_TIMER_BASE (MVEBU_REGISTER(0x20300))
|
||||
#define MVEBU_REG_PCIE_BASE (MVEBU_REGISTER(0x40000))
|
||||
#define MVEBU_AXP_USB_BASE (MVEBU_REGISTER(0x50000))
|
||||
#define MVEBU_USB20_BASE (MVEBU_REGISTER(0x58000))
|
||||
#define MVEBU_AXP_SATA_BASE (MVEBU_REGISTER(0xa0000))
|
||||
#define MVEBU_SATA0_BASE (MVEBU_REGISTER(0xa8000))
|
||||
#define MVEBU_NAND_BASE (MVEBU_REGISTER(0xd0000))
|
||||
#define MVEBU_SDIO_BASE (MVEBU_REGISTER(0xd8000))
|
||||
#define MVEBU_LCD_BASE (MVEBU_REGISTER(0xe0000))
|
||||
|
||||
#define SOC_COHERENCY_FABRIC_CTRL_REG (MVEBU_REGISTER(0x20200))
|
||||
#define MBUS_ERR_PROP_EN (1 << 8)
|
||||
|
||||
#define MBUS_BRIDGE_WIN_CTRL_REG (MVEBU_REGISTER(0x20250))
|
||||
#define MBUS_BRIDGE_WIN_BASE_REG (MVEBU_REGISTER(0x20254))
|
||||
|
||||
#define MVEBU_SOC_DEV_MUX_REG (MVEBU_SYSTEM_REG_BASE + 0x08)
|
||||
#define NAND_EN BIT(0)
|
||||
#define NAND_ARBITER_EN BIT(27)
|
||||
|
||||
#define ARMADA_XP_PUP_ENABLE (MVEBU_SYSTEM_REG_BASE + 0x44c)
|
||||
#define GE0_PUP_EN BIT(0)
|
||||
#define GE1_PUP_EN BIT(1)
|
||||
#define LCD_PUP_EN BIT(2)
|
||||
#define NAND_PUP_EN BIT(4)
|
||||
#define SPI_PUP_EN BIT(5)
|
||||
|
||||
#define MVEBU_CORE_DIV_CLK_CTRL(i) (MVEBU_CLOCK_BASE + ((i) * 0x8))
|
||||
#define NAND_ECC_DIVCKL_RATIO_OFFS 8
|
||||
#define NAND_ECC_DIVCKL_RATIO_MASK (0x3F << NAND_ECC_DIVCKL_RATIO_OFFS)
|
||||
|
||||
#define SDRAM_MAX_CS 4
|
||||
#define SDRAM_ADDR_MASK 0xFF000000
|
||||
|
||||
/* MVEBU CPU memory windows */
|
||||
#define MVCPU_WIN_CTRL_DATA CPU_WIN_CTRL_DATA
|
||||
#define MVCPU_WIN_ENABLE CPU_WIN_ENABLE
|
||||
#define MVCPU_WIN_DISABLE CPU_WIN_DISABLE
|
||||
|
||||
#define COMPHY_REFCLK_ALIGNMENT (MVEBU_REGISTER(0x182f8))
|
||||
|
||||
/* BootROM error register (also includes some status infos) */
|
||||
#define CONFIG_BOOTROM_ERR_REG (MVEBU_REGISTER(0x182d0))
|
||||
#define BOOTROM_ERR_MODE_OFFS 28
|
||||
#define BOOTROM_ERR_MODE_MASK (0xf << BOOTROM_ERR_MODE_OFFS)
|
||||
#define BOOTROM_ERR_MODE_UART 0x6
|
||||
|
||||
#if defined(CONFIG_ARMADA_375)
|
||||
/* SAR values for Armada 375 */
|
||||
#define CONFIG_SAR_REG (MVEBU_REGISTER(0xe8200))
|
||||
#define CONFIG_SAR2_REG (MVEBU_REGISTER(0xe8204))
|
||||
|
||||
#define SAR_CPU_FREQ_OFFS 17
|
||||
#define SAR_CPU_FREQ_MASK (0x1f << SAR_CPU_FREQ_OFFS)
|
||||
|
||||
#define BOOT_DEV_SEL_OFFS 3
|
||||
#define BOOT_DEV_SEL_MASK (0x3f << BOOT_DEV_SEL_OFFS)
|
||||
|
||||
#define BOOT_FROM_UART 0x30
|
||||
#define BOOT_FROM_SPI 0x38
|
||||
#elif defined(CONFIG_ARMADA_38X)
|
||||
/* SAR values for Armada 38x */
|
||||
#define CONFIG_SAR_REG (MVEBU_REGISTER(0x18600))
|
||||
|
||||
#define SAR_CPU_FREQ_OFFS 10
|
||||
#define SAR_CPU_FREQ_MASK (0x1f << SAR_CPU_FREQ_OFFS)
|
||||
#define SAR_BOOT_DEVICE_OFFS 4
|
||||
#define SAR_BOOT_DEVICE_MASK (0x1f << SAR_BOOT_DEVICE_OFFS)
|
||||
|
||||
#define BOOT_DEV_SEL_OFFS 4
|
||||
#define BOOT_DEV_SEL_MASK (0x3f << BOOT_DEV_SEL_OFFS)
|
||||
|
||||
#define BOOT_FROM_UART 0x28
|
||||
#define BOOT_FROM_SPI 0x32
|
||||
#define BOOT_FROM_MMC 0x30
|
||||
#define BOOT_FROM_MMC_ALT 0x31
|
||||
#else
|
||||
/* SAR values for Armada XP */
|
||||
#define CONFIG_SAR_REG (MVEBU_REGISTER(0x18230))
|
||||
#define CONFIG_SAR2_REG (MVEBU_REGISTER(0x18234))
|
||||
|
||||
#define SAR_CPU_FREQ_OFFS 21
|
||||
#define SAR_CPU_FREQ_MASK (0x7 << SAR_CPU_FREQ_OFFS)
|
||||
#define SAR_FFC_FREQ_OFFS 24
|
||||
#define SAR_FFC_FREQ_MASK (0xf << SAR_FFC_FREQ_OFFS)
|
||||
#define SAR2_CPU_FREQ_OFFS 20
|
||||
#define SAR2_CPU_FREQ_MASK (0x1 << SAR2_CPU_FREQ_OFFS)
|
||||
#define SAR_BOOT_DEVICE_OFFS 5
|
||||
#define SAR_BOOT_DEVICE_MASK (0xf << SAR_BOOT_DEVICE_OFFS)
|
||||
|
||||
#define BOOT_DEV_SEL_OFFS 5
|
||||
#define BOOT_DEV_SEL_MASK (0xf << BOOT_DEV_SEL_OFFS)
|
||||
|
||||
#define BOOT_FROM_UART 0x2
|
||||
#define BOOT_FROM_SPI 0x3
|
||||
#endif
|
||||
|
||||
#endif /* _MVEBU_SOC_H */
|
||||
71
u-boot/arch/arm/mach-mvebu/lowlevel_spl.S
Normal file
71
u-boot/arch/arm/mach-mvebu/lowlevel_spl.S
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
ENTRY(save_boot_params)
|
||||
stmfd sp!, {r0 - r12, lr} /* @ save registers on stack */
|
||||
ldr r12, =CONFIG_SPL_BOOTROM_SAVE
|
||||
str sp, [r12]
|
||||
b save_boot_params_ret
|
||||
ENDPROC(save_boot_params)
|
||||
|
||||
ENTRY(return_to_bootrom)
|
||||
ldr r12, =CONFIG_SPL_BOOTROM_SAVE
|
||||
ldr sp, [r12]
|
||||
mov r0, #0x0 /* @ return value: 0x0 NO_ERR */
|
||||
ldmfd sp!, {r0 - r12, pc} /* @ restore regs and return */
|
||||
ENDPROC(return_to_bootrom)
|
||||
|
||||
/*
|
||||
* 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
|
||||
521
u-boot/arch/arm/mach-mvebu/mbus.c
Normal file
521
u-boot/arch/arm/mach-mvebu/mbus.c
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Address map functions for Marvell EBU SoCs (Kirkwood, Armada
|
||||
* 370/XP, Dove, Orion5x and MV78xx0)
|
||||
*
|
||||
* Ported from the Barebox version to U-Boot by:
|
||||
* Stefan Roese <sr@denx.de>
|
||||
*
|
||||
* The Barebox version is:
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
*
|
||||
* based on mbus driver from Linux
|
||||
* (C) Copyright 2008 Marvell Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* The Marvell EBU SoCs have a configurable physical address space:
|
||||
* the physical address at which certain devices (PCIe, NOR, NAND,
|
||||
* etc.) sit can be configured. The configuration takes place through
|
||||
* two sets of registers:
|
||||
*
|
||||
* - One to configure the access of the CPU to the devices. Depending
|
||||
* on the families, there are between 8 and 20 configurable windows,
|
||||
* each can be use to create a physical memory window that maps to a
|
||||
* specific device. Devices are identified by a tuple (target,
|
||||
* attribute).
|
||||
*
|
||||
* - One to configure the access to the CPU to the SDRAM. There are
|
||||
* either 2 (for Dove) or 4 (for other families) windows to map the
|
||||
* SDRAM into the physical address space.
|
||||
*
|
||||
* This driver:
|
||||
*
|
||||
* - Reads out the SDRAM address decoding windows at initialization
|
||||
* time, and fills the mbus_dram_info structure with these
|
||||
* informations. The exported function mv_mbus_dram_info() allow
|
||||
* device drivers to get those informations related to the SDRAM
|
||||
* address decoding windows. This is because devices also have their
|
||||
* own windows (configured through registers that are part of each
|
||||
* device register space), and therefore the drivers for Marvell
|
||||
* devices have to configure those device -> SDRAM windows to ensure
|
||||
* that DMA works properly.
|
||||
*
|
||||
* - Provides an API for platform code or device drivers to
|
||||
* dynamically add or remove address decoding windows for the CPU ->
|
||||
* device accesses. This API is mvebu_mbus_add_window_by_id(),
|
||||
* mvebu_mbus_add_window_remap_by_id() and
|
||||
* mvebu_mbus_del_window().
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/mbus.h>
|
||||
|
||||
/* DDR target is the same on all platforms */
|
||||
#define TARGET_DDR 0
|
||||
|
||||
/* CPU Address Decode Windows registers */
|
||||
#define WIN_CTRL_OFF 0x0000
|
||||
#define WIN_CTRL_ENABLE BIT(0)
|
||||
#define WIN_CTRL_TGT_MASK 0xf0
|
||||
#define WIN_CTRL_TGT_SHIFT 4
|
||||
#define WIN_CTRL_ATTR_MASK 0xff00
|
||||
#define WIN_CTRL_ATTR_SHIFT 8
|
||||
#define WIN_CTRL_SIZE_MASK 0xffff0000
|
||||
#define WIN_CTRL_SIZE_SHIFT 16
|
||||
#define WIN_BASE_OFF 0x0004
|
||||
#define WIN_BASE_LOW 0xffff0000
|
||||
#define WIN_BASE_HIGH 0xf
|
||||
#define WIN_REMAP_LO_OFF 0x0008
|
||||
#define WIN_REMAP_LOW 0xffff0000
|
||||
#define WIN_REMAP_HI_OFF 0x000c
|
||||
|
||||
#define ATTR_HW_COHERENCY (0x1 << 4)
|
||||
|
||||
#define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3))
|
||||
#define DDR_BASE_CS_HIGH_MASK 0xf
|
||||
#define DDR_BASE_CS_LOW_MASK 0xff000000
|
||||
#define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3))
|
||||
#define DDR_SIZE_ENABLED BIT(0)
|
||||
#define DDR_SIZE_CS_MASK 0x1c
|
||||
#define DDR_SIZE_CS_SHIFT 2
|
||||
#define DDR_SIZE_MASK 0xff000000
|
||||
|
||||
#define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4)
|
||||
|
||||
struct mvebu_mbus_state;
|
||||
|
||||
struct mvebu_mbus_soc_data {
|
||||
unsigned int num_wins;
|
||||
unsigned int num_remappable_wins;
|
||||
unsigned int (*win_cfg_offset)(const int win);
|
||||
void (*setup_cpu_target)(struct mvebu_mbus_state *s);
|
||||
};
|
||||
|
||||
struct mvebu_mbus_state mbus_state
|
||||
__attribute__ ((section(".data")));
|
||||
static struct mbus_dram_target_info mbus_dram_info
|
||||
__attribute__ ((section(".data")));
|
||||
|
||||
/*
|
||||
* Functions to manipulate the address decoding windows
|
||||
*/
|
||||
|
||||
static void mvebu_mbus_read_window(struct mvebu_mbus_state *mbus,
|
||||
int win, int *enabled, u64 *base,
|
||||
u32 *size, u8 *target, u8 *attr,
|
||||
u64 *remap)
|
||||
{
|
||||
void __iomem *addr = mbus->mbuswins_base +
|
||||
mbus->soc->win_cfg_offset(win);
|
||||
u32 basereg = readl(addr + WIN_BASE_OFF);
|
||||
u32 ctrlreg = readl(addr + WIN_CTRL_OFF);
|
||||
|
||||
if (!(ctrlreg & WIN_CTRL_ENABLE)) {
|
||||
*enabled = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*enabled = 1;
|
||||
*base = ((u64)basereg & WIN_BASE_HIGH) << 32;
|
||||
*base |= (basereg & WIN_BASE_LOW);
|
||||
*size = (ctrlreg | ~WIN_CTRL_SIZE_MASK) + 1;
|
||||
|
||||
if (target)
|
||||
*target = (ctrlreg & WIN_CTRL_TGT_MASK) >> WIN_CTRL_TGT_SHIFT;
|
||||
|
||||
if (attr)
|
||||
*attr = (ctrlreg & WIN_CTRL_ATTR_MASK) >> WIN_CTRL_ATTR_SHIFT;
|
||||
|
||||
if (remap) {
|
||||
if (win < mbus->soc->num_remappable_wins) {
|
||||
u32 remap_low = readl(addr + WIN_REMAP_LO_OFF);
|
||||
u32 remap_hi = readl(addr + WIN_REMAP_HI_OFF);
|
||||
*remap = ((u64)remap_hi << 32) | remap_low;
|
||||
} else {
|
||||
*remap = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus,
|
||||
int win)
|
||||
{
|
||||
void __iomem *addr;
|
||||
|
||||
addr = mbus->mbuswins_base + mbus->soc->win_cfg_offset(win);
|
||||
|
||||
writel(0, addr + WIN_BASE_OFF);
|
||||
writel(0, addr + WIN_CTRL_OFF);
|
||||
if (win < mbus->soc->num_remappable_wins) {
|
||||
writel(0, addr + WIN_REMAP_LO_OFF);
|
||||
writel(0, addr + WIN_REMAP_HI_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks whether the given window number is available */
|
||||
static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus,
|
||||
const int win)
|
||||
{
|
||||
void __iomem *addr = mbus->mbuswins_base +
|
||||
mbus->soc->win_cfg_offset(win);
|
||||
u32 ctrl = readl(addr + WIN_CTRL_OFF);
|
||||
return !(ctrl & WIN_CTRL_ENABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether the given (base, base+size) area doesn't overlap an
|
||||
* existing region
|
||||
*/
|
||||
static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
|
||||
phys_addr_t base, size_t size,
|
||||
u8 target, u8 attr)
|
||||
{
|
||||
u64 end = (u64)base + size;
|
||||
int win;
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++) {
|
||||
u64 wbase, wend;
|
||||
u32 wsize;
|
||||
u8 wtarget, wattr;
|
||||
int enabled;
|
||||
|
||||
mvebu_mbus_read_window(mbus, win,
|
||||
&enabled, &wbase, &wsize,
|
||||
&wtarget, &wattr, NULL);
|
||||
|
||||
if (!enabled)
|
||||
continue;
|
||||
|
||||
wend = wbase + wsize;
|
||||
|
||||
/*
|
||||
* Check if the current window overlaps with the
|
||||
* proposed physical range
|
||||
*/
|
||||
if ((u64)base < wend && end > wbase)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Check if target/attribute conflicts
|
||||
*/
|
||||
if (target == wtarget && attr == wattr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mvebu_mbus_find_window(struct mvebu_mbus_state *mbus,
|
||||
phys_addr_t base, size_t size)
|
||||
{
|
||||
int win;
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++) {
|
||||
u64 wbase;
|
||||
u32 wsize;
|
||||
int enabled;
|
||||
|
||||
mvebu_mbus_read_window(mbus, win,
|
||||
&enabled, &wbase, &wsize,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (!enabled)
|
||||
continue;
|
||||
|
||||
if (base == wbase && size == wsize)
|
||||
return win;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus,
|
||||
int win, phys_addr_t base, size_t size,
|
||||
phys_addr_t remap, u8 target,
|
||||
u8 attr)
|
||||
{
|
||||
void __iomem *addr = mbus->mbuswins_base +
|
||||
mbus->soc->win_cfg_offset(win);
|
||||
u32 ctrl, remap_addr;
|
||||
|
||||
ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) |
|
||||
(attr << WIN_CTRL_ATTR_SHIFT) |
|
||||
(target << WIN_CTRL_TGT_SHIFT) |
|
||||
WIN_CTRL_ENABLE;
|
||||
|
||||
writel(base & WIN_BASE_LOW, addr + WIN_BASE_OFF);
|
||||
writel(ctrl, addr + WIN_CTRL_OFF);
|
||||
if (win < mbus->soc->num_remappable_wins) {
|
||||
if (remap == MVEBU_MBUS_NO_REMAP)
|
||||
remap_addr = base;
|
||||
else
|
||||
remap_addr = remap;
|
||||
writel(remap_addr & WIN_REMAP_LOW, addr + WIN_REMAP_LO_OFF);
|
||||
writel(0, addr + WIN_REMAP_HI_OFF);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mvebu_mbus_alloc_window(struct mvebu_mbus_state *mbus,
|
||||
phys_addr_t base, size_t size,
|
||||
phys_addr_t remap, u8 target,
|
||||
u8 attr)
|
||||
{
|
||||
int win;
|
||||
|
||||
if (remap == MVEBU_MBUS_NO_REMAP) {
|
||||
for (win = mbus->soc->num_remappable_wins;
|
||||
win < mbus->soc->num_wins; win++)
|
||||
if (mvebu_mbus_window_is_free(mbus, win))
|
||||
return mvebu_mbus_setup_window(mbus, win, base,
|
||||
size, remap,
|
||||
target, attr);
|
||||
}
|
||||
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++)
|
||||
if (mvebu_mbus_window_is_free(mbus, win))
|
||||
return mvebu_mbus_setup_window(mbus, win, base, size,
|
||||
remap, target, attr);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* SoC-specific functions and definitions
|
||||
*/
|
||||
|
||||
static unsigned int armada_370_xp_mbus_win_offset(int win)
|
||||
{
|
||||
/* The register layout is a bit annoying and the below code
|
||||
* tries to cope with it.
|
||||
* - At offset 0x0, there are the registers for the first 8
|
||||
* windows, with 4 registers of 32 bits per window (ctrl,
|
||||
* base, remap low, remap high)
|
||||
* - Then at offset 0x80, there is a hole of 0x10 bytes for
|
||||
* the internal registers base address and internal units
|
||||
* sync barrier register.
|
||||
* - Then at offset 0x90, there the registers for 12
|
||||
* windows, with only 2 registers of 32 bits per window
|
||||
* (ctrl, base).
|
||||
*/
|
||||
if (win < 8)
|
||||
return win << 4;
|
||||
else
|
||||
return 0x90 + ((win - 8) << 3);
|
||||
}
|
||||
|
||||
static unsigned int orion5x_mbus_win_offset(int win)
|
||||
{
|
||||
return win << 4;
|
||||
}
|
||||
|
||||
static void mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
||||
{
|
||||
int i;
|
||||
int cs;
|
||||
|
||||
mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
|
||||
|
||||
for (i = 0, cs = 0; i < 4; i++) {
|
||||
u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
|
||||
u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
|
||||
|
||||
/*
|
||||
* We only take care of entries for which the chip
|
||||
* select is enabled, and that don't have high base
|
||||
* address bits set (devices can only access the first
|
||||
* 32 bits of the memory).
|
||||
*/
|
||||
if ((size & DDR_SIZE_ENABLED) &&
|
||||
!(base & DDR_BASE_CS_HIGH_MASK)) {
|
||||
struct mbus_dram_window *w;
|
||||
|
||||
w = &mbus_dram_info.cs[cs++];
|
||||
w->cs_index = i;
|
||||
w->mbus_attr = 0xf & ~(1 << i);
|
||||
w->base = base & DDR_BASE_CS_LOW_MASK;
|
||||
w->size = (size | ~DDR_SIZE_MASK) + 1;
|
||||
}
|
||||
}
|
||||
mbus_dram_info.num_cs = cs;
|
||||
}
|
||||
|
||||
static const struct mvebu_mbus_soc_data
|
||||
armada_370_xp_mbus_data __maybe_unused = {
|
||||
.num_wins = 20,
|
||||
.num_remappable_wins = 8,
|
||||
.win_cfg_offset = armada_370_xp_mbus_win_offset,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
};
|
||||
|
||||
static const struct mvebu_mbus_soc_data
|
||||
kirkwood_mbus_data __maybe_unused = {
|
||||
.num_wins = 8,
|
||||
.num_remappable_wins = 4,
|
||||
.win_cfg_offset = orion5x_mbus_win_offset,
|
||||
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
|
||||
};
|
||||
|
||||
/*
|
||||
* Public API of the driver
|
||||
*/
|
||||
const struct mbus_dram_target_info *mvebu_mbus_dram_info(void)
|
||||
{
|
||||
return &mbus_dram_info;
|
||||
}
|
||||
|
||||
int mvebu_mbus_add_window_remap_by_id(unsigned int target,
|
||||
unsigned int attribute,
|
||||
phys_addr_t base, size_t size,
|
||||
phys_addr_t remap)
|
||||
{
|
||||
struct mvebu_mbus_state *s = &mbus_state;
|
||||
|
||||
if (!mvebu_mbus_window_conflicts(s, base, size, target, attribute)) {
|
||||
printf("Cannot add window '%x:%x', conflicts with another window\n",
|
||||
target, attribute);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mvebu_mbus_alloc_window(s, base, size, remap, target, attribute);
|
||||
}
|
||||
|
||||
int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
|
||||
phys_addr_t base, size_t size)
|
||||
{
|
||||
return mvebu_mbus_add_window_remap_by_id(target, attribute, base,
|
||||
size, MVEBU_MBUS_NO_REMAP);
|
||||
}
|
||||
|
||||
int mvebu_mbus_del_window(phys_addr_t base, size_t size)
|
||||
{
|
||||
int win;
|
||||
|
||||
win = mvebu_mbus_find_window(&mbus_state, base, size);
|
||||
if (win < 0)
|
||||
return win;
|
||||
|
||||
mvebu_mbus_disable_window(&mbus_state, win);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mvebu_mbus_get_lowest_base(struct mvebu_mbus_state *mbus,
|
||||
phys_addr_t *base)
|
||||
{
|
||||
int win;
|
||||
*base = 0xffffffff;
|
||||
|
||||
for (win = 0; win < mbus->soc->num_wins; win++) {
|
||||
u64 wbase;
|
||||
u32 wsize;
|
||||
u8 wtarget, wattr;
|
||||
int enabled;
|
||||
|
||||
mvebu_mbus_read_window(mbus, win,
|
||||
&enabled, &wbase, &wsize,
|
||||
&wtarget, &wattr, NULL);
|
||||
|
||||
if (!enabled)
|
||||
continue;
|
||||
|
||||
if (wbase < *base)
|
||||
*base = wbase;
|
||||
}
|
||||
}
|
||||
|
||||
static void mvebu_config_mbus_bridge(struct mvebu_mbus_state *mbus)
|
||||
{
|
||||
phys_addr_t base;
|
||||
u32 val;
|
||||
u32 size;
|
||||
|
||||
/* Set MBUS bridge base/ctrl */
|
||||
mvebu_mbus_get_lowest_base(&mbus_state, &base);
|
||||
|
||||
size = 0xffffffff - base + 1;
|
||||
if (!is_power_of_2(size)) {
|
||||
/* Round up to next power of 2 */
|
||||
size = 1 << (ffs(base) + 1);
|
||||
base = 0xffffffff - size + 1;
|
||||
}
|
||||
|
||||
/* Now write base and size */
|
||||
writel(base, MBUS_BRIDGE_WIN_BASE_REG);
|
||||
/* Align window size to 64KiB */
|
||||
val = (size / (64 << 10)) - 1;
|
||||
writel((val << 16) | 0x1, MBUS_BRIDGE_WIN_CTRL_REG);
|
||||
}
|
||||
|
||||
int mbus_dt_setup_win(struct mvebu_mbus_state *mbus,
|
||||
u32 base, u32 size, u8 target, u8 attr)
|
||||
{
|
||||
if (!mvebu_mbus_window_conflicts(mbus, base, size, target, attr)) {
|
||||
printf("Cannot add window '%04x:%04x', conflicts with another window\n",
|
||||
target, attr);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* In U-Boot we first try to add the mbus window to the remap windows.
|
||||
* If this fails, lets try to add the windows to the non-remap windows.
|
||||
*/
|
||||
if (mvebu_mbus_alloc_window(mbus, base, size, base, target, attr)) {
|
||||
if (mvebu_mbus_alloc_window(mbus, base, size,
|
||||
MVEBU_MBUS_NO_REMAP, target, attr))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-configure the mbus bridge registers each time this function
|
||||
* is called. Since it may get called from the board code in
|
||||
* later boot stages as well.
|
||||
*/
|
||||
mvebu_config_mbus_bridge(mbus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mvebu_mbus_probe(struct mbus_win windows[], int count)
|
||||
{
|
||||
int win;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
#if defined(CONFIG_KIRKWOOD)
|
||||
mbus_state.soc = &kirkwood_mbus_data;
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_MVEBU)
|
||||
mbus_state.soc = &armada_370_xp_mbus_data;
|
||||
#endif
|
||||
|
||||
mbus_state.mbuswins_base = (void __iomem *)MVEBU_CPU_WIN_BASE;
|
||||
mbus_state.sdramwins_base = (void __iomem *)MVEBU_SDRAM_BASE;
|
||||
|
||||
for (win = 0; win < mbus_state.soc->num_wins; win++)
|
||||
mvebu_mbus_disable_window(&mbus_state, win);
|
||||
|
||||
mbus_state.soc->setup_cpu_target(&mbus_state);
|
||||
|
||||
/* Setup statically declared windows in the DT */
|
||||
for (i = 0; i < count; i++) {
|
||||
u32 base, size;
|
||||
u8 target, attr;
|
||||
|
||||
target = windows[i].target;
|
||||
attr = windows[i].attr;
|
||||
base = windows[i].base;
|
||||
size = windows[i].size;
|
||||
ret = mbus_dt_setup_win(&mbus_state, base, size, target, attr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
9
u-boot/arch/arm/mach-mvebu/serdes/a38x/Makefile
Normal file
9
u-boot/arch/arm/mach-mvebu/serdes/a38x/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-$(CONFIG_SPL_BUILD) = ctrl_pex.o
|
||||
obj-$(CONFIG_SPL_BUILD) += high_speed_env_spec.o
|
||||
obj-$(CONFIG_SPL_BUILD) += high_speed_env_spec-38x.o
|
||||
obj-$(CONFIG_SPL_BUILD) += seq_exec.o
|
||||
obj-$(CONFIG_SPL_BUILD) += sys_env_lib.o
|
||||
346
u-boot/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
Normal file
346
u-boot/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
Normal file
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* 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>
|
||||
|
||||
#include "ctrl_pex.h"
|
||||
#include "sys_env_lib.h"
|
||||
|
||||
int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
|
||||
{
|
||||
u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg,
|
||||
temp_reg, addr, dev_id, ctrl_mode;
|
||||
enum serdes_type serdes_type;
|
||||
u32 idx;
|
||||
|
||||
DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
/* configuration for PEX only */
|
||||
if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
|
||||
(serdes_type != PEX2) && (serdes_type != PEX3))
|
||||
continue;
|
||||
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
pex_idx = serdes_type - PEX0;
|
||||
tmp = reg_read(PEX_CAPABILITIES_REG(pex_idx));
|
||||
tmp &= ~(0xf << 20);
|
||||
tmp |= (0x4 << 20);
|
||||
reg_write(PEX_CAPABILITIES_REG(pex_idx), tmp);
|
||||
}
|
||||
|
||||
tmp = reg_read(SOC_CTRL_REG);
|
||||
tmp &= ~0x03;
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (serdes_type) {
|
||||
case PEX0:
|
||||
tmp |= 0x1 << PCIE0_ENABLE_OFFS;
|
||||
break;
|
||||
case PEX1:
|
||||
tmp |= 0x1 << PCIE1_ENABLE_OFFS;
|
||||
break;
|
||||
case PEX2:
|
||||
tmp |= 0x1 << PCIE2_ENABLE_OFFS;
|
||||
break;
|
||||
case PEX3:
|
||||
tmp |= 0x1 << PCIE3_ENABLE_OFFS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
reg_write(SOC_CTRL_REG, tmp);
|
||||
|
||||
/* Support gen1/gen2 */
|
||||
DEBUG_INIT_FULL_S("Support gen1/gen2\n");
|
||||
next_busno = 0;
|
||||
mdelay(150);
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
DEBUG_INIT_FULL_S(" serdes_type=0x");
|
||||
DEBUG_INIT_FULL_D(serdes_type, 8);
|
||||
DEBUG_INIT_FULL_S("\n");
|
||||
DEBUG_INIT_FULL_S(" idx=0x");
|
||||
DEBUG_INIT_FULL_D(idx, 8);
|
||||
DEBUG_INIT_FULL_S("\n");
|
||||
|
||||
/* Configuration for PEX only */
|
||||
if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
|
||||
(serdes_type != PEX2) && (serdes_type != PEX3))
|
||||
continue;
|
||||
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
pex_idx = serdes_type - PEX0;
|
||||
tmp = reg_read(PEX_DBG_STATUS_REG(pex_idx));
|
||||
|
||||
first_busno = next_busno;
|
||||
if ((tmp & 0x7f) != 0x7e) {
|
||||
DEBUG_INIT_S("PCIe, Idx ");
|
||||
DEBUG_INIT_D(pex_idx, 1);
|
||||
DEBUG_INIT_S(": detected no link\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
next_busno++;
|
||||
temp_pex_reg = reg_read((PEX_CFG_DIRECT_ACCESS
|
||||
(pex_idx, PEX_LINK_CAPABILITY_REG)));
|
||||
temp_pex_reg &= 0xf;
|
||||
if (temp_pex_reg != 0x2)
|
||||
continue;
|
||||
|
||||
temp_reg = (reg_read(PEX_CFG_DIRECT_ACCESS(
|
||||
pex_idx,
|
||||
PEX_LINK_CTRL_STAT_REG)) &
|
||||
0xf0000) >> 16;
|
||||
|
||||
/* Check if the link established is GEN1 */
|
||||
DEBUG_INIT_FULL_S
|
||||
("Checking if the link established is gen1\n");
|
||||
if (temp_reg != 0x1)
|
||||
continue;
|
||||
|
||||
pex_local_bus_num_set(pex_idx, first_busno);
|
||||
pex_local_dev_num_set(pex_idx, 1);
|
||||
DEBUG_INIT_FULL_S("PCIe, Idx ");
|
||||
DEBUG_INIT_FULL_D(pex_idx, 1);
|
||||
|
||||
DEBUG_INIT_S(":** Link is Gen1, check the EP capability\n");
|
||||
/* link is Gen1, check the EP capability */
|
||||
addr = pex_config_read(pex_idx, first_busno, 0, 0, 0x34) & 0xff;
|
||||
DEBUG_INIT_FULL_C("pex_config_read: return addr=0x%x", addr, 4);
|
||||
if (addr == 0xff) {
|
||||
DEBUG_INIT_FULL_C
|
||||
("pex_config_read: return 0xff -->PCIe (%d): Detected No Link.",
|
||||
pex_idx, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((pex_config_read(pex_idx, first_busno, 0, 0, addr)
|
||||
& 0xff) != 0x10) {
|
||||
addr = (pex_config_read(pex_idx, first_busno, 0,
|
||||
0, addr) & 0xff00) >> 8;
|
||||
}
|
||||
|
||||
/* Check for Gen2 and above */
|
||||
if ((pex_config_read(pex_idx, first_busno, 0, 0,
|
||||
addr + 0xc) & 0xf) < 0x2) {
|
||||
DEBUG_INIT_S("PCIe, Idx ");
|
||||
DEBUG_INIT_D(pex_idx, 1);
|
||||
DEBUG_INIT_S(": remains Gen1\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp = reg_read(PEX_LINK_CTRL_STATUS2_REG(pex_idx));
|
||||
DEBUG_RD_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
|
||||
tmp &= ~(BIT(0) | BIT(1));
|
||||
tmp |= BIT(1);
|
||||
tmp |= BIT(6); /* Select Deemphasize (-3.5d_b) */
|
||||
reg_write(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
|
||||
DEBUG_WR_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
|
||||
|
||||
tmp = reg_read(PEX_CTRL_REG(pex_idx));
|
||||
DEBUG_RD_REG(PEX_CTRL_REG(pex_idx), tmp);
|
||||
tmp |= BIT(10);
|
||||
reg_write(PEX_CTRL_REG(pex_idx), tmp);
|
||||
DEBUG_WR_REG(PEX_CTRL_REG(pex_idx), tmp);
|
||||
|
||||
/*
|
||||
* We need to wait 10ms before reading the PEX_DBG_STATUS_REG
|
||||
* in order not to read the status of the former state
|
||||
*/
|
||||
mdelay(10);
|
||||
|
||||
DEBUG_INIT_S("PCIe, Idx ");
|
||||
DEBUG_INIT_D(pex_idx, 1);
|
||||
DEBUG_INIT_S
|
||||
(": Link upgraded to Gen2 based on client cpabilities\n");
|
||||
}
|
||||
|
||||
/* Update pex DEVICE ID */
|
||||
ctrl_mode = sys_env_model_get();
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
serdes_type = serdes_map[idx].serdes_type;
|
||||
/* configuration for PEX only */
|
||||
if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
|
||||
(serdes_type != PEX2) && (serdes_type != PEX3))
|
||||
continue;
|
||||
|
||||
if ((serdes_type != PEX0) &&
|
||||
((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
|
||||
(serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
|
||||
/* for PEX by4 - relevant for the first port only */
|
||||
continue;
|
||||
}
|
||||
|
||||
pex_idx = serdes_type - PEX0;
|
||||
dev_id = reg_read(PEX_CFG_DIRECT_ACCESS
|
||||
(pex_idx, PEX_DEVICE_AND_VENDOR_ID));
|
||||
dev_id &= 0xffff;
|
||||
dev_id |= ((ctrl_mode << 16) & 0xffff0000);
|
||||
reg_write(PEX_CFG_DIRECT_ACCESS
|
||||
(pex_idx, PEX_DEVICE_AND_VENDOR_ID), dev_id);
|
||||
}
|
||||
DEBUG_INIT_FULL_C("Update PEX Device ID ", ctrl_mode, 4);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int pex_local_bus_num_set(u32 pex_if, u32 bus_num)
|
||||
{
|
||||
u32 pex_status;
|
||||
|
||||
DEBUG_INIT_FULL_S("\n### pex_local_bus_num_set ###\n");
|
||||
|
||||
if (bus_num >= MAX_PEX_BUSSES) {
|
||||
DEBUG_INIT_C("pex_local_bus_num_set: Illegal bus number %d\n",
|
||||
bus_num, 4);
|
||||
return MV_BAD_PARAM;
|
||||
}
|
||||
|
||||
pex_status = reg_read(PEX_STATUS_REG(pex_if));
|
||||
pex_status &= ~PXSR_PEX_BUS_NUM_MASK;
|
||||
pex_status |=
|
||||
(bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
|
||||
reg_write(PEX_STATUS_REG(pex_if), pex_status);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int pex_local_dev_num_set(u32 pex_if, u32 dev_num)
|
||||
{
|
||||
u32 pex_status;
|
||||
|
||||
DEBUG_INIT_FULL_S("\n### pex_local_dev_num_set ###\n");
|
||||
|
||||
pex_status = reg_read(PEX_STATUS_REG(pex_if));
|
||||
pex_status &= ~PXSR_PEX_DEV_NUM_MASK;
|
||||
pex_status |=
|
||||
(dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
|
||||
reg_write(PEX_STATUS_REG(pex_if), pex_status);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* pex_config_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 pex_local_bus_num_get(). 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.
|
||||
* reg_offs - Register offset.
|
||||
*
|
||||
* OUTPUT:
|
||||
* None.
|
||||
*
|
||||
* RETURN:
|
||||
* 32bit register data, 0xffffffff on error
|
||||
*/
|
||||
u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off)
|
||||
{
|
||||
u32 pex_data = 0;
|
||||
u32 local_dev, local_bus;
|
||||
u32 pex_status;
|
||||
|
||||
pex_status = reg_read(PEX_STATUS_REG(pex_if));
|
||||
local_dev =
|
||||
((pex_status & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS);
|
||||
local_bus =
|
||||
((pex_status & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
/* Legacy register space */
|
||||
pex_data |= (reg_off & PXCAR_REG_NUM_MASK);
|
||||
/* Extended register space */
|
||||
pex_data |= (((reg_off & 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;
|
||||
}
|
||||
86
u-boot/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
Normal file
86
u-boot/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _CTRL_PEX_H
|
||||
#define _CTRL_PEX_H
|
||||
|
||||
#include "high_speed_env_spec.h"
|
||||
|
||||
/* Sample at Reset */
|
||||
#define MPP_SAMPLE_AT_RESET(id) (0xe4200 + (id * 4))
|
||||
|
||||
/* PCI Express Control and Status Registers */
|
||||
#define MAX_PEX_BUSSES 256
|
||||
|
||||
#define MISC_REGS_OFFSET 0x18200
|
||||
#define MV_MISC_REGS_BASE MISC_REGS_OFFSET
|
||||
#define SOC_CTRL_REG (MV_MISC_REGS_BASE + 0x4)
|
||||
|
||||
#define PEX_IF_REGS_OFFSET(if) ((if) > 0 ? \
|
||||
(0x40000 + ((if) - 1) * 0x4000) : \
|
||||
0x80000)
|
||||
#define PEX_IF_REGS_BASE(if) (PEX_IF_REGS_OFFSET(if))
|
||||
#define PEX_CAPABILITIES_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x60)
|
||||
#define PEX_LINK_CTRL_STATUS2_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x90)
|
||||
#define PEX_CTRL_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x1a00)
|
||||
#define PEX_STATUS_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x1a04)
|
||||
#define PEX_DBG_STATUS_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x1a64)
|
||||
#define PEX_LINK_CAPABILITY_REG 0x6c
|
||||
#define PEX_LINK_CTRL_STAT_REG 0x70
|
||||
#define PXSR_PEX_DEV_NUM_OFFS 16 /* Device Number Indication */
|
||||
#define PXSR_PEX_DEV_NUM_MASK (0x1f << PXSR_PEX_DEV_NUM_OFFS)
|
||||
#define PXSR_PEX_BUS_NUM_OFFS 8 /* Bus Number Indication */
|
||||
#define PXSR_PEX_BUS_NUM_MASK (0xff << PXSR_PEX_BUS_NUM_OFFS)
|
||||
|
||||
/* PEX_CAPABILITIES_REG fields */
|
||||
#define PCIE0_ENABLE_OFFS 0
|
||||
#define PCIE0_ENABLE_MASK (0x1 << PCIE0_ENABLE_OFFS)
|
||||
#define PCIE1_ENABLE_OFFS 1
|
||||
#define PCIE1_ENABLE_MASK (0x1 << PCIE1_ENABLE_OFFS)
|
||||
#define PCIE2_ENABLE_OFFS 2
|
||||
#define PCIE2_ENABLE_MASK (0x1 << PCIE2_ENABLE_OFFS)
|
||||
#define PCIE3_ENABLE_OFFS 3
|
||||
#define PCIE4_ENABLE_MASK (0x1 << PCIE3_ENABLE_OFFS)
|
||||
|
||||
/* Controller revision info */
|
||||
#define PEX_DEVICE_AND_VENDOR_ID 0x000
|
||||
|
||||
/* PCI Express Configuration Address Register */
|
||||
#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 PEX_CFG_ADDR_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x18f8)
|
||||
#define PEX_CFG_DATA_REG(if) ((PEX_IF_REGS_BASE(if)) + 0x18fc)
|
||||
|
||||
#define PXCAR_REAL_EXT_REG_NUM_OFFS 8
|
||||
#define PXCAR_REAL_EXT_REG_NUM_MASK (0xf << PXCAR_REAL_EXT_REG_NUM_OFFS)
|
||||
|
||||
#define PXCAR_CONFIG_EN BIT(31)
|
||||
#define PEX_STATUS_AND_COMMAND 0x004
|
||||
#define PXSAC_MABORT BIT(29) /* Recieved Master Abort */
|
||||
|
||||
int hws_pex_config(const struct serdes_map *serdes_map, u8 count);
|
||||
int pex_local_bus_num_set(u32 pex_if, u32 bus_num);
|
||||
int pex_local_dev_num_set(u32 pex_if, u32 dev_num);
|
||||
u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off);
|
||||
|
||||
#endif
|
||||
157
u-boot/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec-38x.c
Normal file
157
u-boot/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec-38x.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* 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>
|
||||
|
||||
#include "high_speed_env_spec.h"
|
||||
#include "sys_env_lib.h"
|
||||
|
||||
#define SERDES_VERION "2.0"
|
||||
|
||||
u8 selectors_serdes_rev1_map[LAST_SERDES_TYPE][MAX_SERDES_LANES] = {
|
||||
/* 0 1 2 3 4 5 */
|
||||
{0x1, 0x1, NA, NA, NA, NA}, /* PEX0 */
|
||||
{NA, 0x2, 0x1, NA, 0x1, NA}, /* PEX1 */
|
||||
{NA, NA, 0x2, NA, NA, 0x1}, /* PEX2 */
|
||||
{NA, NA, NA, 0x1, NA, NA}, /* PEX3 */
|
||||
{0x2, 0x3, NA, NA, NA, NA}, /* SATA0 */
|
||||
{NA, NA, 0x3, NA, 0x2, NA}, /* SATA1 */
|
||||
{NA, NA, NA, NA, 0x6, 0x2}, /* SATA2 */
|
||||
{NA, NA, NA, 0x3, NA, NA}, /* SATA3 */
|
||||
{0x3, 0x4, NA, NA, NA, NA}, /* SGMII0 */
|
||||
{NA, 0x5, 0x4, NA, 0x3, NA}, /* SGMII1 */
|
||||
{NA, NA, NA, 0x4, NA, 0x3}, /* SGMII2 */
|
||||
{NA, 0x7, NA, NA, NA, NA}, /* QSGMII */
|
||||
{NA, 0x6, NA, NA, 0x4, NA}, /* USB3_HOST0 */
|
||||
{NA, NA, NA, 0x5, NA, 0x4}, /* USB3_HOST1 */
|
||||
{NA, NA, NA, 0x6, 0x5, 0x5}, /* USB3_DEVICE */
|
||||
{0x0, 0x0, 0x0, 0x0, 0x0, 0x0} /* DEFAULT_SERDES */
|
||||
};
|
||||
|
||||
int hws_serdes_seq_init(void)
|
||||
{
|
||||
DEBUG_INIT_FULL_S("\n### serdes_seq_init ###\n");
|
||||
|
||||
if (hws_serdes_seq_db_init() != MV_OK) {
|
||||
printf("hws_serdes_seq_init: Error: Serdes initialization fail\n");
|
||||
return MV_FAIL;
|
||||
}
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int serdes_power_up_ctrl_ext(u32 serdes_num, int serdes_power_up,
|
||||
enum serdes_type serdes_type,
|
||||
enum serdes_speed baud_rate,
|
||||
enum serdes_mode serdes_mode,
|
||||
enum ref_clock ref_clock)
|
||||
{
|
||||
return MV_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
u32 hws_serdes_silicon_ref_clock_get(void)
|
||||
{
|
||||
DEBUG_INIT_FULL_S("\n### hws_serdes_silicon_ref_clock_get ###\n");
|
||||
|
||||
return REF_CLOCK_25MHZ;
|
||||
}
|
||||
|
||||
u32 hws_serdes_get_max_lane(void)
|
||||
{
|
||||
switch (sys_env_device_id_get()) {
|
||||
case MV_6811: /* A381/A3282: 6811/6821: single/dual cpu */
|
||||
return 4;
|
||||
case MV_6810:
|
||||
return 5;
|
||||
case MV_6820:
|
||||
case MV_6828:
|
||||
return 6;
|
||||
default: /* not the right module */
|
||||
printf("%s: Device ID Error, using 4 SerDes lanes\n",
|
||||
__func__);
|
||||
return 4;
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
|
||||
int hws_is_serdes_active(u8 lane_num)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
/* Maximum lane count for A388 (6828) is 6 */
|
||||
if (lane_num > 6)
|
||||
ret = 0;
|
||||
|
||||
/* 4th Lane (#4 on Device 6810 is not Active */
|
||||
if (sys_env_device_id_get() == MV_6810 && lane_num == 4) {
|
||||
printf("%s: Error: Lane#4 on Device 6810 is not Active.\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 6th Lane (#5) on Device 6810 is Active, even though 6810
|
||||
* has only 5 lanes
|
||||
*/
|
||||
if (sys_env_device_id_get() == MV_6810 && lane_num == 5)
|
||||
return 1;
|
||||
|
||||
if (lane_num >= hws_serdes_get_max_lane())
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hws_get_ext_base_addr(u32 serdes_num, u32 base_addr, u32 unit_base_offset,
|
||||
u32 *unit_base_reg, u32 *unit_offset)
|
||||
{
|
||||
*unit_base_reg = base_addr;
|
||||
*unit_offset = unit_base_offset;
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* hws_serdes_get_phy_selector_val
|
||||
*
|
||||
* DESCRIPTION: Get the mapping of Serdes Selector values according to the
|
||||
* Serdes revision number
|
||||
* INPUT: serdes_num - Serdes number
|
||||
* serdes_type - Serdes type
|
||||
* OUTPUT: None
|
||||
* RETURN:
|
||||
* Mapping of Serdes Selector values
|
||||
*/
|
||||
u32 hws_serdes_get_phy_selector_val(int serdes_num,
|
||||
enum serdes_type serdes_type)
|
||||
{
|
||||
if (serdes_type >= LAST_SERDES_TYPE)
|
||||
return 0xff;
|
||||
|
||||
if (hws_ctrl_serdes_rev_get() == MV_SERDES_REV_1_2) {
|
||||
return selectors_serdes_rev1_map
|
||||
[serdes_type][serdes_num];
|
||||
} else
|
||||
return selectors_serdes_rev2_map
|
||||
[serdes_type][serdes_num];
|
||||
}
|
||||
|
||||
u32 hws_get_physical_serdes_num(u32 serdes_num)
|
||||
{
|
||||
if ((serdes_num == 4) && (sys_env_device_id_get() == MV_6810)) {
|
||||
/*
|
||||
* For 6810, there are 5 Serdes and Serdes Num 4 doesn't
|
||||
* exist. Instead Serdes Num 5 is connected.
|
||||
*/
|
||||
return 5;
|
||||
} else {
|
||||
return serdes_num;
|
||||
}
|
||||
}
|
||||
2199
u-boot/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
Normal file
2199
u-boot/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
Normal file
File diff suppressed because it is too large
Load Diff
251
u-boot/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h
Normal file
251
u-boot/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _HIGH_SPEED_ENV_SPEC_H
|
||||
#define _HIGH_SPEED_ENV_SPEC_H
|
||||
|
||||
#include "seq_exec.h"
|
||||
|
||||
/*
|
||||
* For setting or clearing a certain bit (bit is a number between 0 and 31)
|
||||
* in the data
|
||||
*/
|
||||
#define SET_BIT(data, bit) ((data) | (0x1 << (bit)))
|
||||
#define CLEAR_BIT(data, bit) ((data) & (~(0x1 << (bit))))
|
||||
|
||||
#define MAX_SERDES_LANES 7 /* as in a39x */
|
||||
|
||||
/* Serdes revision */
|
||||
/* Serdes revision 1.2 (for A38x-Z1) */
|
||||
#define MV_SERDES_REV_1_2 0x0
|
||||
/* Serdes revision 2.1 (for A39x-Z1, A38x-A0) */
|
||||
#define MV_SERDES_REV_2_1 0x1
|
||||
#define MV_SERDES_REV_NA 0xff
|
||||
|
||||
#define SERDES_REGS_LANE_BASE_OFFSET(lane) (0x800 * (lane))
|
||||
|
||||
#define PEX_X4_ENABLE_OFFS \
|
||||
(hws_ctrl_serdes_rev_get() == MV_SERDES_REV_1_2 ? 18 : 31)
|
||||
|
||||
/* Serdes lane types */
|
||||
enum serdes_type {
|
||||
PEX0,
|
||||
PEX1,
|
||||
PEX2,
|
||||
PEX3,
|
||||
SATA0,
|
||||
SATA1,
|
||||
SATA2,
|
||||
SATA3,
|
||||
SGMII0,
|
||||
SGMII1,
|
||||
SGMII2,
|
||||
QSGMII,
|
||||
USB3_HOST0,
|
||||
USB3_HOST1,
|
||||
USB3_DEVICE,
|
||||
SGMII3,
|
||||
XAUI,
|
||||
RXAUI,
|
||||
DEFAULT_SERDES,
|
||||
LAST_SERDES_TYPE
|
||||
};
|
||||
|
||||
/* Serdes baud rates */
|
||||
enum serdes_speed {
|
||||
SERDES_SPEED_1_25_GBPS,
|
||||
SERDES_SPEED_1_5_GBPS,
|
||||
SERDES_SPEED_2_5_GBPS,
|
||||
SERDES_SPEED_3_GBPS,
|
||||
SERDES_SPEED_3_125_GBPS,
|
||||
SERDES_SPEED_5_GBPS,
|
||||
SERDES_SPEED_6_GBPS,
|
||||
SERDES_SPEED_6_25_GBPS,
|
||||
LAST_SERDES_SPEED
|
||||
};
|
||||
|
||||
/* Serdes modes */
|
||||
enum serdes_mode {
|
||||
PEX_ROOT_COMPLEX_X1,
|
||||
PEX_ROOT_COMPLEX_X4,
|
||||
PEX_END_POINT_X1,
|
||||
PEX_END_POINT_X4,
|
||||
|
||||
SERDES_DEFAULT_MODE, /* not pex */
|
||||
|
||||
SERDES_LAST_MODE
|
||||
};
|
||||
|
||||
struct serdes_map {
|
||||
enum serdes_type serdes_type;
|
||||
enum serdes_speed serdes_speed;
|
||||
enum serdes_mode serdes_mode;
|
||||
int swap_rx;
|
||||
int swap_tx;
|
||||
};
|
||||
|
||||
/* Serdes ref clock options */
|
||||
enum ref_clock {
|
||||
REF_CLOCK_25MHZ,
|
||||
REF_CLOCK_100MHZ,
|
||||
REF_CLOCK_40MHZ,
|
||||
REF_CLOCK_UNSUPPORTED
|
||||
};
|
||||
|
||||
/* Serdes sequences */
|
||||
enum serdes_seq {
|
||||
SATA_PORT_0_ONLY_POWER_UP_SEQ,
|
||||
SATA_PORT_1_ONLY_POWER_UP_SEQ,
|
||||
SATA_POWER_UP_SEQ,
|
||||
SATA_1_5_SPEED_CONFIG_SEQ,
|
||||
SATA_3_SPEED_CONFIG_SEQ,
|
||||
SATA_6_SPEED_CONFIG_SEQ,
|
||||
SATA_ELECTRICAL_CONFIG_SEQ,
|
||||
SATA_TX_CONFIG_SEQ1,
|
||||
SATA_PORT_0_ONLY_TX_CONFIG_SEQ,
|
||||
SATA_PORT_1_ONLY_TX_CONFIG_SEQ,
|
||||
SATA_TX_CONFIG_SEQ2,
|
||||
|
||||
SGMII_POWER_UP_SEQ,
|
||||
SGMII_1_25_SPEED_CONFIG_SEQ,
|
||||
SGMII_3_125_SPEED_CONFIG_SEQ,
|
||||
SGMII_ELECTRICAL_CONFIG_SEQ,
|
||||
SGMII_TX_CONFIG_SEQ1,
|
||||
SGMII_TX_CONFIG_SEQ2,
|
||||
|
||||
PEX_POWER_UP_SEQ,
|
||||
PEX_2_5_SPEED_CONFIG_SEQ,
|
||||
PEX_5_SPEED_CONFIG_SEQ,
|
||||
PEX_ELECTRICAL_CONFIG_SEQ,
|
||||
PEX_TX_CONFIG_SEQ1,
|
||||
PEX_TX_CONFIG_SEQ2,
|
||||
PEX_TX_CONFIG_SEQ3,
|
||||
PEX_BY_4_CONFIG_SEQ,
|
||||
PEX_CONFIG_REF_CLOCK_25MHZ_SEQ,
|
||||
PEX_CONFIG_REF_CLOCK_100MHZ_SEQ,
|
||||
PEX_CONFIG_REF_CLOCK_40MHZ_SEQ,
|
||||
|
||||
USB3_POWER_UP_SEQ,
|
||||
USB3_HOST_SPEED_CONFIG_SEQ,
|
||||
USB3_DEVICE_SPEED_CONFIG_SEQ,
|
||||
USB3_ELECTRICAL_CONFIG_SEQ,
|
||||
USB3_TX_CONFIG_SEQ1,
|
||||
USB3_TX_CONFIG_SEQ2,
|
||||
USB3_TX_CONFIG_SEQ3,
|
||||
USB3_DEVICE_CONFIG_SEQ,
|
||||
|
||||
USB2_POWER_UP_SEQ,
|
||||
|
||||
SERDES_POWER_DOWN_SEQ,
|
||||
|
||||
SGMII3_POWER_UP_SEQ,
|
||||
SGMII3_1_25_SPEED_CONFIG_SEQ,
|
||||
SGMII3_TX_CONFIG_SEQ1,
|
||||
SGMII3_TX_CONFIG_SEQ2,
|
||||
|
||||
QSGMII_POWER_UP_SEQ,
|
||||
QSGMII_5_SPEED_CONFIG_SEQ,
|
||||
QSGMII_ELECTRICAL_CONFIG_SEQ,
|
||||
QSGMII_TX_CONFIG_SEQ1,
|
||||
QSGMII_TX_CONFIG_SEQ2,
|
||||
|
||||
XAUI_POWER_UP_SEQ,
|
||||
XAUI_3_125_SPEED_CONFIG_SEQ,
|
||||
XAUI_ELECTRICAL_CONFIG_SEQ,
|
||||
XAUI_TX_CONFIG_SEQ1,
|
||||
XAUI_TX_CONFIG_SEQ2,
|
||||
|
||||
RXAUI_POWER_UP_SEQ,
|
||||
RXAUI_6_25_SPEED_CONFIG_SEQ,
|
||||
RXAUI_ELECTRICAL_CONFIG_SEQ,
|
||||
RXAUI_TX_CONFIG_SEQ1,
|
||||
RXAUI_TX_CONFIG_SEQ2,
|
||||
|
||||
SERDES_LAST_SEQ
|
||||
};
|
||||
|
||||
/* The different sequence types for PEX and USB3 */
|
||||
enum {
|
||||
PEX,
|
||||
USB3,
|
||||
LAST_PEX_USB_SEQ_TYPE
|
||||
};
|
||||
|
||||
enum {
|
||||
PEXSERDES_SPEED_2_5_GBPS,
|
||||
PEXSERDES_SPEED_5_GBPS,
|
||||
USB3SERDES_SPEED_5_GBPS_HOST,
|
||||
USB3SERDES_SPEED_5_GBPS_DEVICE,
|
||||
LAST_PEX_USB_SPEED_SEQ_TYPE
|
||||
};
|
||||
|
||||
/* The different sequence types for SATA and SGMII */
|
||||
enum {
|
||||
SATA,
|
||||
SGMII,
|
||||
SGMII_3_125,
|
||||
LAST_SATA_SGMII_SEQ_TYPE
|
||||
};
|
||||
|
||||
enum {
|
||||
QSGMII_SEQ_IDX,
|
||||
LAST_QSGMII_SEQ_TYPE
|
||||
};
|
||||
|
||||
enum {
|
||||
XAUI_SEQ_IDX,
|
||||
RXAUI_SEQ_IDX,
|
||||
LAST_XAUI_RXAUI_SEQ_TYPE
|
||||
};
|
||||
|
||||
enum {
|
||||
SATASERDES_SPEED_1_5_GBPS,
|
||||
SATASERDES_SPEED_3_GBPS,
|
||||
SATASERDES_SPEED_6_GBPS,
|
||||
SGMIISERDES_SPEED_1_25_GBPS,
|
||||
SGMIISERDES_SPEED_3_125_GBPS,
|
||||
LAST_SATA_SGMII_SPEED_SEQ_TYPE
|
||||
};
|
||||
|
||||
extern u8 selectors_serdes_rev1_map[LAST_SERDES_TYPE][MAX_SERDES_LANES];
|
||||
extern u8 selectors_serdes_rev2_map[LAST_SERDES_TYPE][MAX_SERDES_LANES];
|
||||
|
||||
u8 hws_ctrl_serdes_rev_get(void);
|
||||
int mv_update_serdes_select_phy_mode_seq(void);
|
||||
int hws_board_topology_load(struct serdes_map **serdes_map, u8 *count);
|
||||
enum serdes_seq serdes_type_and_speed_to_speed_seq(enum serdes_type serdes_type,
|
||||
enum serdes_speed baud_rate);
|
||||
int hws_serdes_seq_init(void);
|
||||
int hws_serdes_seq_db_init(void);
|
||||
int hws_power_up_serdes_lanes(struct serdes_map *serdes_map, u8 count);
|
||||
int hws_ctrl_high_speed_serdes_phy_config(void);
|
||||
int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
|
||||
enum serdes_type serdes_type,
|
||||
enum serdes_speed baud_rate,
|
||||
enum serdes_mode serdes_mode,
|
||||
enum ref_clock ref_clock);
|
||||
int serdes_power_up_ctrl_ext(u32 serdes_num, int serdes_power_up,
|
||||
enum serdes_type serdes_type,
|
||||
enum serdes_speed baud_rate,
|
||||
enum serdes_mode serdes_mode,
|
||||
enum ref_clock ref_clock);
|
||||
u32 hws_serdes_silicon_ref_clock_get(void);
|
||||
int hws_serdes_pex_ref_clock_get(enum serdes_type serdes_type,
|
||||
enum ref_clock *ref_clock);
|
||||
int hws_ref_clock_set(u32 serdes_num, enum serdes_type serdes_type,
|
||||
enum ref_clock ref_clock);
|
||||
int hws_update_serdes_phy_selectors(struct serdes_map *serdes_map, u8 count);
|
||||
u32 hws_serdes_get_phy_selector_val(int serdes_num,
|
||||
enum serdes_type serdes_type);
|
||||
u32 hws_serdes_get_ref_clock_val(enum serdes_type serdes_type);
|
||||
u32 hws_serdes_get_max_lane(void);
|
||||
int hws_get_ext_base_addr(u32 serdes_num, u32 base_addr, u32 unit_base_offset,
|
||||
u32 *unit_base_reg, u32 *unit_offset);
|
||||
int hws_pex_tx_config_seq(const struct serdes_map *serdes_map, u8 count);
|
||||
u32 hws_get_physical_serdes_num(u32 serdes_num);
|
||||
int hws_is_serdes_active(u8 lane_num);
|
||||
|
||||
#endif /* _HIGH_SPEED_ENV_SPEC_H */
|
||||
169
u-boot/arch/arm/mach-mvebu/serdes/a38x/seq_exec.c
Normal file
169
u-boot/arch/arm/mach-mvebu/serdes/a38x/seq_exec.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* 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>
|
||||
|
||||
#include "seq_exec.h"
|
||||
#include "high_speed_env_spec.h"
|
||||
|
||||
#include "../../../drivers/ddr/marvell/a38x/ddr3_init.h"
|
||||
|
||||
#if defined(MV_DEBUG_INIT_FULL) || defined(MV_DEBUG)
|
||||
#define DB(x) x
|
||||
#else
|
||||
#define DB(x)
|
||||
#endif
|
||||
|
||||
/* Array for mapping the operation (write, poll or delay) functions */
|
||||
op_execute_func_ptr op_execute_func_arr[] = {
|
||||
write_op_execute,
|
||||
delay_op_execute,
|
||||
poll_op_execute
|
||||
};
|
||||
|
||||
int write_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
|
||||
{
|
||||
u32 unit_base_reg, unit_offset, data, mask, reg_data, reg_addr;
|
||||
|
||||
/* Getting write op params from the input parameter */
|
||||
data = params->data[data_arr_idx];
|
||||
mask = params->mask;
|
||||
|
||||
/* an empty operation */
|
||||
if (data == NO_DATA)
|
||||
return MV_OK;
|
||||
|
||||
/* get updated base address since it can be different between Serdes */
|
||||
CHECK_STATUS(hws_get_ext_base_addr(serdes_num, params->unit_base_reg,
|
||||
params->unit_offset,
|
||||
&unit_base_reg, &unit_offset));
|
||||
|
||||
/* Address calculation */
|
||||
reg_addr = unit_base_reg + unit_offset * serdes_num;
|
||||
|
||||
#ifdef SEQ_DEBUG
|
||||
printf("Write: 0x%x: 0x%x (mask 0x%x) - ", reg_addr, data, mask);
|
||||
#endif
|
||||
/* Reading old value */
|
||||
reg_data = reg_read(reg_addr);
|
||||
reg_data &= (~mask);
|
||||
|
||||
/* Writing new data */
|
||||
data &= mask;
|
||||
reg_data |= data;
|
||||
reg_write(reg_addr, reg_data);
|
||||
|
||||
#ifdef SEQ_DEBUG
|
||||
printf(" - 0x%x\n", reg_data);
|
||||
#endif
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int delay_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
|
||||
{
|
||||
u32 delay;
|
||||
|
||||
/* Getting delay op params from the input parameter */
|
||||
delay = params->wait_time;
|
||||
#ifdef SEQ_DEBUG
|
||||
printf("Delay: %d\n", delay);
|
||||
#endif
|
||||
mdelay(delay);
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx)
|
||||
{
|
||||
u32 unit_base_reg, unit_offset, data, mask, num_of_loops, wait_time;
|
||||
u32 poll_counter = 0;
|
||||
u32 reg_addr, reg_data;
|
||||
|
||||
/* Getting poll op params from the input parameter */
|
||||
data = params->data[data_arr_idx];
|
||||
mask = params->mask;
|
||||
num_of_loops = params->num_of_loops;
|
||||
wait_time = params->wait_time;
|
||||
|
||||
/* an empty operation */
|
||||
if (data == NO_DATA)
|
||||
return MV_OK;
|
||||
|
||||
/* get updated base address since it can be different between Serdes */
|
||||
CHECK_STATUS(hws_get_ext_base_addr(serdes_num, params->unit_base_reg,
|
||||
params->unit_offset,
|
||||
&unit_base_reg, &unit_offset));
|
||||
|
||||
/* Address calculation */
|
||||
reg_addr = unit_base_reg + unit_offset * serdes_num;
|
||||
|
||||
/* Polling */
|
||||
#ifdef SEQ_DEBUG
|
||||
printf("Poll: 0x%x: 0x%x (mask 0x%x)\n", reg_addr, data, mask);
|
||||
#endif
|
||||
|
||||
do {
|
||||
reg_data = reg_read(reg_addr) & mask;
|
||||
poll_counter++;
|
||||
udelay(wait_time);
|
||||
} while ((reg_data != data) && (poll_counter < num_of_loops));
|
||||
|
||||
if ((poll_counter >= num_of_loops) && (reg_data != data)) {
|
||||
DEBUG_INIT_S("poll_op_execute: TIMEOUT\n");
|
||||
return MV_TIMEOUT;
|
||||
}
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
|
||||
enum mv_op get_cfg_seq_op(struct op_params *params)
|
||||
{
|
||||
if (params->wait_time == 0)
|
||||
return WRITE_OP;
|
||||
else if (params->num_of_loops == 0)
|
||||
return DELAY_OP;
|
||||
|
||||
return POLL_OP;
|
||||
}
|
||||
|
||||
int mv_seq_exec(u32 serdes_num, u32 seq_id)
|
||||
{
|
||||
u32 seq_idx;
|
||||
struct op_params *seq_arr;
|
||||
u32 seq_size;
|
||||
u32 data_arr_idx;
|
||||
enum mv_op curr_op;
|
||||
|
||||
DB(printf("\n### mv_seq_exec ###\n"));
|
||||
DB(printf("seq id: %d\n", seq_id));
|
||||
|
||||
if (hws_is_serdes_active(serdes_num) != 1) {
|
||||
printf("mv_seq_exec_ext:Error: SerDes lane %d is not valid\n",
|
||||
serdes_num);
|
||||
return MV_BAD_PARAM;
|
||||
}
|
||||
|
||||
seq_arr = serdes_seq_db[seq_id].op_params_ptr;
|
||||
seq_size = serdes_seq_db[seq_id].cfg_seq_size;
|
||||
data_arr_idx = serdes_seq_db[seq_id].data_arr_idx;
|
||||
|
||||
DB(printf("seq_size: %d\n", seq_size));
|
||||
DB(printf("data_arr_idx: %d\n", data_arr_idx));
|
||||
|
||||
/* Executing the sequence operations */
|
||||
for (seq_idx = 0; seq_idx < seq_size; seq_idx++) {
|
||||
curr_op = get_cfg_seq_op(&seq_arr[seq_idx]);
|
||||
op_execute_func_arr[curr_op](serdes_num, &seq_arr[seq_idx],
|
||||
data_arr_idx);
|
||||
}
|
||||
|
||||
return MV_OK;
|
||||
}
|
||||
65
u-boot/arch/arm/mach-mvebu/serdes/a38x/seq_exec.h
Normal file
65
u-boot/arch/arm/mach-mvebu/serdes/a38x/seq_exec.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SEQ_EXEC_H
|
||||
#define _SEQ_EXEC_H
|
||||
|
||||
#define NA 0xff
|
||||
#define DEFAULT_PARAM 0
|
||||
#define MV_BOARD_TCLK_ERROR 0xffffffff
|
||||
|
||||
#define NO_DATA 0xffffffff
|
||||
#define MAX_DATA_ARRAY 5
|
||||
#define FIRST_CELL 0
|
||||
|
||||
/* Operation types */
|
||||
enum mv_op {
|
||||
WRITE_OP,
|
||||
DELAY_OP,
|
||||
POLL_OP,
|
||||
};
|
||||
|
||||
/* Operation parameters */
|
||||
struct op_params {
|
||||
u32 unit_base_reg;
|
||||
u32 unit_offset;
|
||||
u32 mask;
|
||||
u32 data[MAX_DATA_ARRAY]; /* data array */
|
||||
u8 wait_time; /* msec */
|
||||
u16 num_of_loops; /* for polling only */
|
||||
};
|
||||
|
||||
/*
|
||||
* Sequence parameters. Each sequence contains:
|
||||
* 1. Sequence id.
|
||||
* 2. Sequence size (total amount of operations during the sequence)
|
||||
* 3. a series of operations. operations can be write, poll or delay
|
||||
* 4. index in the data array (the entry where the relevant data sits)
|
||||
*/
|
||||
struct cfg_seq {
|
||||
struct op_params *op_params_ptr;
|
||||
u8 cfg_seq_size;
|
||||
u8 data_arr_idx;
|
||||
};
|
||||
|
||||
extern struct cfg_seq serdes_seq_db[];
|
||||
|
||||
/*
|
||||
* A generic function type for executing an operation (write, poll or delay)
|
||||
*/
|
||||
typedef int (*op_execute_func_ptr)(u32 serdes_num, struct op_params *params,
|
||||
u32 data_arr_idx);
|
||||
|
||||
/* Specific functions for executing each operation */
|
||||
int write_op_execute(u32 serdes_num, struct op_params *params,
|
||||
u32 data_arr_idx);
|
||||
int delay_op_execute(u32 serdes_num, struct op_params *params,
|
||||
u32 data_arr_idx);
|
||||
int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx);
|
||||
enum mv_op get_cfg_seq_op(struct op_params *params);
|
||||
int mv_seq_exec(u32 serdes_num, u32 seq_id);
|
||||
|
||||
#endif /*_SEQ_EXEC_H*/
|
||||
237
u-boot/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c
Normal file
237
u-boot/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* 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>
|
||||
|
||||
#include "seq_exec.h"
|
||||
#include "sys_env_lib.h"
|
||||
|
||||
#include "../../../drivers/ddr/marvell/a38x/ddr3_a38x.h"
|
||||
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
enum unit_id sys_env_soc_unit_nums[MAX_UNITS_ID][MAX_DEV_ID_NUM] = {
|
||||
/* 6820 6810 6811 6828 */
|
||||
/* PEX_UNIT_ID */ { 4, 3, 3, 4},
|
||||
/* ETH_GIG_UNIT_ID */ { 3, 2, 3, 3},
|
||||
/* USB3H_UNIT_ID */ { 2, 2, 2, 2},
|
||||
/* USB3D_UNIT_ID */ { 1, 1, 1, 1},
|
||||
/* SATA_UNIT_ID */ { 2, 2, 2, 4},
|
||||
/* QSGMII_UNIT_ID */ { 1, 0, 0, 1},
|
||||
/* XAUI_UNIT_ID */ { 0, 0, 0, 0},
|
||||
/* RXAUI_UNIT_ID */ { 0, 0, 0, 0}
|
||||
};
|
||||
#else /* if (CONFIG_ARMADA_39X) */
|
||||
enum unit_id sys_env_soc_unit_nums[MAX_UNITS_ID][MAX_DEV_ID_NUM] = {
|
||||
/* 6920 6928 */
|
||||
/* PEX_UNIT_ID */ { 4, 4},
|
||||
/* ETH_GIG_UNIT_ID */ { 3, 4},
|
||||
/* USB3H_UNIT_ID */ { 1, 2},
|
||||
/* USB3D_UNIT_ID */ { 0, 1},
|
||||
/* SATA_UNIT_ID */ { 0, 4},
|
||||
/* QSGMII_UNIT_ID */ { 0, 1},
|
||||
/* XAUI_UNIT_ID */ { 1, 1},
|
||||
/* RXAUI_UNIT_ID */ { 1, 1}
|
||||
};
|
||||
#endif
|
||||
|
||||
u32 g_dev_id = -1;
|
||||
|
||||
u32 mv_board_id_get(void)
|
||||
{
|
||||
#if defined(CONFIG_DB_88F6820_GP)
|
||||
return DB_GP_68XX_ID;
|
||||
#else
|
||||
/*
|
||||
* Return 0 here for custom board as this should not be used
|
||||
* for custom boards.
|
||||
*/
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 mv_board_tclk_get(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
value = (reg_read(DEVICE_SAMPLE_AT_RESET1_REG) >> 15) & 0x1;
|
||||
|
||||
switch (value) {
|
||||
case (0x0):
|
||||
return 250000000;
|
||||
case (0x1):
|
||||
return 200000000;
|
||||
default:
|
||||
return 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
u32 mv_board_id_index_get(u32 board_id)
|
||||
{
|
||||
/*
|
||||
* Marvell Boards use 0x10 as base for Board ID:
|
||||
* mask MSB to receive index for board ID
|
||||
*/
|
||||
return board_id & (MARVELL_BOARD_ID_MASK - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_env_suspend_wakeup_check
|
||||
* DESCRIPTION: Reads GPIO input for suspend-wakeup indication.
|
||||
* INPUT: None.
|
||||
* OUTPUT:
|
||||
* RETURNS: u32 indicating suspend wakeup status:
|
||||
* 0 - Not supported,
|
||||
* 1 - supported: read magic word detect wakeup,
|
||||
* 2 - detected wakeup from GPIO.
|
||||
*/
|
||||
enum suspend_wakeup_status sys_env_suspend_wakeup_check(void)
|
||||
{
|
||||
u32 reg, board_id_index, gpio;
|
||||
struct board_wakeup_gpio board_gpio[] = MV_BOARD_WAKEUP_GPIO_INFO;
|
||||
|
||||
board_id_index = mv_board_id_index_get(mv_board_id_get());
|
||||
if (!(sizeof(board_gpio) / sizeof(struct board_wakeup_gpio) >
|
||||
board_id_index)) {
|
||||
printf("\n_failed loading Suspend-Wakeup information (invalid board ID)\n");
|
||||
return SUSPEND_WAKEUP_DISABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* - Detect if Suspend-Wakeup is supported on current board
|
||||
* - Fetch the GPIO number for wakeup status input indication
|
||||
*/
|
||||
if (board_gpio[board_id_index].gpio_num == -1) {
|
||||
/* Suspend to RAM is not supported */
|
||||
return SUSPEND_WAKEUP_DISABLED;
|
||||
} else if (board_gpio[board_id_index].gpio_num == -2) {
|
||||
/*
|
||||
* Suspend to RAM is supported but GPIO indication is
|
||||
* not implemented - Skip
|
||||
*/
|
||||
return SUSPEND_WAKEUP_ENABLED;
|
||||
} else {
|
||||
gpio = board_gpio[board_id_index].gpio_num;
|
||||
}
|
||||
|
||||
/* Initialize MPP for GPIO (set MPP = 0x0) */
|
||||
reg = reg_read(MPP_CONTROL_REG(MPP_REG_NUM(gpio)));
|
||||
/* reset MPP21 to 0x0, keep rest of MPP settings*/
|
||||
reg &= ~MPP_MASK(gpio);
|
||||
reg_write(MPP_CONTROL_REG(MPP_REG_NUM(gpio)), reg);
|
||||
|
||||
/* Initialize GPIO as input */
|
||||
reg = reg_read(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)));
|
||||
reg |= GPP_MASK(gpio);
|
||||
reg_write(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)), reg);
|
||||
|
||||
/*
|
||||
* Check GPP for input status from PIC: 0 - regular init,
|
||||
* 1 - suspend wakeup
|
||||
*/
|
||||
reg = reg_read(GPP_DATA_IN_REG(GPP_REG_NUM(gpio)));
|
||||
|
||||
/* if GPIO is ON: wakeup from S2RAM indication detected */
|
||||
return (reg & GPP_MASK(gpio)) ? SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED :
|
||||
SUSPEND_WAKEUP_DISABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* mv_ctrl_dev_id_index_get
|
||||
*
|
||||
* DESCRIPTION: return SOC device index
|
||||
* INPUT: None
|
||||
* OUTPUT: None
|
||||
* RETURN:
|
||||
* return SOC device index
|
||||
*/
|
||||
u32 sys_env_id_index_get(u32 ctrl_model)
|
||||
{
|
||||
switch (ctrl_model) {
|
||||
case MV_6820_DEV_ID:
|
||||
return MV_6820_INDEX;
|
||||
case MV_6810_DEV_ID:
|
||||
return MV_6810_INDEX;
|
||||
case MV_6811_DEV_ID:
|
||||
return MV_6811_INDEX;
|
||||
case MV_6828_DEV_ID:
|
||||
return MV_6828_INDEX;
|
||||
case MV_6920_DEV_ID:
|
||||
return MV_6920_INDEX;
|
||||
case MV_6928_DEV_ID:
|
||||
return MV_6928_INDEX;
|
||||
default:
|
||||
return MV_6820_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
u32 sys_env_unit_max_num_get(enum unit_id unit)
|
||||
{
|
||||
u32 dev_id_index;
|
||||
|
||||
if (unit >= MAX_UNITS_ID) {
|
||||
printf("%s: Error: Wrong unit type (%u)\n", __func__, unit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_id_index = sys_env_id_index_get(sys_env_model_get());
|
||||
return sys_env_soc_unit_nums[unit][dev_id_index];
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_env_model_get
|
||||
* DESCRIPTION: Returns 16bit describing the device model (ID) as defined
|
||||
* in Vendor ID configuration register
|
||||
*/
|
||||
u16 sys_env_model_get(void)
|
||||
{
|
||||
u32 default_ctrl_id, ctrl_id = reg_read(DEV_ID_REG);
|
||||
ctrl_id = (ctrl_id & (DEV_ID_REG_DEVICE_ID_MASK)) >>
|
||||
DEV_ID_REG_DEVICE_ID_OFFS;
|
||||
|
||||
switch (ctrl_id) {
|
||||
case MV_6820_DEV_ID:
|
||||
case MV_6810_DEV_ID:
|
||||
case MV_6811_DEV_ID:
|
||||
case MV_6828_DEV_ID:
|
||||
case MV_6920_DEV_ID:
|
||||
case MV_6928_DEV_ID:
|
||||
return ctrl_id;
|
||||
default:
|
||||
/* Device ID Default for A38x: 6820 , for A39x: 6920 */
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
default_ctrl_id = MV_6820_DEV_ID;
|
||||
#else
|
||||
default_ctrl_id = MV_6920_DEV_ID;
|
||||
#endif
|
||||
printf("%s: Error retrieving device ID (%x), using default ID = %x\n",
|
||||
__func__, ctrl_id, default_ctrl_id);
|
||||
return default_ctrl_id;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_env_device_id_get
|
||||
* DESCRIPTION: Returns enum (0..7) index of the device model (ID)
|
||||
*/
|
||||
u32 sys_env_device_id_get(void)
|
||||
{
|
||||
char *device_id_str[7] = {
|
||||
"6810", "6820", "6811", "6828", "NONE", "6920", "6928"
|
||||
};
|
||||
|
||||
if (g_dev_id != -1)
|
||||
return g_dev_id;
|
||||
|
||||
g_dev_id = reg_read(DEVICE_SAMPLE_AT_RESET1_REG);
|
||||
g_dev_id = g_dev_id >> SAR_DEV_ID_OFFS & SAR_DEV_ID_MASK;
|
||||
printf("Detected Device ID %s\n", device_id_str[g_dev_id]);
|
||||
|
||||
return g_dev_id;
|
||||
}
|
||||
369
u-boot/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h
Normal file
369
u-boot/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h
Normal file
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SYS_ENV_LIB_H
|
||||
#define _SYS_ENV_LIB_H
|
||||
|
||||
#include "../../../drivers/ddr/marvell/a38x/ddr3_init.h"
|
||||
#include "../../../drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h"
|
||||
|
||||
/* Serdes definitions */
|
||||
#define COMMON_PHY_BASE_ADDR 0x18300
|
||||
|
||||
#define DEVICE_CONFIGURATION_REG0 0x18284
|
||||
#define DEVICE_CONFIGURATION_REG1 0x18288
|
||||
#define COMMON_PHY_CONFIGURATION1_REG 0x18300
|
||||
#define COMMON_PHY_CONFIGURATION2_REG 0x18304
|
||||
#define COMMON_PHY_CONFIGURATION4_REG 0x1830c
|
||||
#define COMMON_PHY_STATUS1_REG 0x18318
|
||||
#define COMMON_PHYS_SELECTORS_REG 0x183fc
|
||||
#define SOC_CONTROL_REG1 0x18204
|
||||
#define GENERAL_PURPOSE_RESERVED0_REG 0x182e0
|
||||
#define GBE_CONFIGURATION_REG 0x18460
|
||||
#define DEVICE_SAMPLE_AT_RESET1_REG 0x18600
|
||||
#define DEVICE_SAMPLE_AT_RESET2_REG 0x18604
|
||||
#define DEV_ID_REG 0x18238
|
||||
|
||||
#define CORE_PLL_PARAMETERS_REG 0xe42e0
|
||||
#define CORE_PLL_CONFIG_REG 0xe42e4
|
||||
|
||||
#define QSGMII_CONTROL_REG1 0x18494
|
||||
|
||||
#define DEV_ID_REG_DEVICE_ID_OFFS 16
|
||||
#define DEV_ID_REG_DEVICE_ID_MASK 0xffff0000
|
||||
|
||||
#define SAR_DEV_ID_OFFS 27
|
||||
#define SAR_DEV_ID_MASK 0x7
|
||||
|
||||
#define POWER_AND_PLL_CTRL_REG 0xa0004
|
||||
#define CALIBRATION_CTRL_REG 0xa0008
|
||||
#define DFE_REG0 0xa001c
|
||||
#define DFE_REG3 0xa0028
|
||||
#define RESET_DFE_REG 0xa0148
|
||||
#define LOOPBACK_REG 0xa008c
|
||||
#define SYNC_PATTERN_REG 0xa0090
|
||||
#define INTERFACE_REG 0xa0094
|
||||
#define ISOLATE_REG 0xa0098
|
||||
#define MISC_REG 0xa013c
|
||||
#define GLUE_REG 0xa0140
|
||||
#define GENERATION_DIVIDER_FORCE_REG 0xa0144
|
||||
#define PCIE_REG0 0xa0120
|
||||
#define LANE_ALIGN_REG0 0xa0124
|
||||
#define SQUELCH_FFE_SETTING_REG 0xa0018
|
||||
#define G1_SETTINGS_0_REG 0xa0034
|
||||
#define G1_SETTINGS_1_REG 0xa0038
|
||||
#define G1_SETTINGS_3_REG 0xa0440
|
||||
#define G1_SETTINGS_4_REG 0xa0444
|
||||
#define G2_SETTINGS_0_REG 0xa003c
|
||||
#define G2_SETTINGS_1_REG 0xa0040
|
||||
#define G2_SETTINGS_2_REG 0xa00f8
|
||||
#define G2_SETTINGS_3_REG 0xa0448
|
||||
#define G2_SETTINGS_4_REG 0xa044c
|
||||
#define G3_SETTINGS_0_REG 0xa0044
|
||||
#define G3_SETTINGS_1_REG 0xa0048
|
||||
#define G3_SETTINGS_3_REG 0xa0450
|
||||
#define G3_SETTINGS_4_REG 0xa0454
|
||||
#define VTHIMPCAL_CTRL_REG 0xa0104
|
||||
#define REF_REG0 0xa0134
|
||||
#define CAL_REG6 0xa0168
|
||||
#define RX_REG2 0xa0184
|
||||
#define RX_REG3 0xa0188
|
||||
#define PCIE_REG1 0xa0288
|
||||
#define PCIE_REG3 0xa0290
|
||||
#define LANE_CFG1_REG 0xa0604
|
||||
#define LANE_CFG4_REG 0xa0620
|
||||
#define LANE_CFG5_REG 0xa0624
|
||||
#define GLOBAL_CLK_CTRL 0xa0704
|
||||
#define GLOBAL_MISC_CTRL 0xa0718
|
||||
#define GLOBAL_CLK_SRC_HI 0xa0710
|
||||
|
||||
#define GLOBAL_CLK_CTRL 0xa0704
|
||||
#define GLOBAL_MISC_CTRL 0xa0718
|
||||
#define GLOBAL_PM_CTRL 0xa0740
|
||||
|
||||
/* SATA registers */
|
||||
#define SATA_CTRL_REG_IND_ADDR 0xa80a0
|
||||
#define SATA_CTRL_REG_IND_DATA 0xa80a4
|
||||
|
||||
#define SATA_VENDOR_PORT_0_REG_ADDR 0xa8178
|
||||
#define SATA_VENDOR_PORT_1_REG_ADDR 0xa81f8
|
||||
#define SATA_VENDOR_PORT_0_REG_DATA 0xa817c
|
||||
#define SATA_VENDOR_PORT_1_REG_DATA 0xa81fc
|
||||
|
||||
/* Reference clock values and mask */
|
||||
#define POWER_AND_PLL_CTRL_REG_100MHZ_VAL 0x0
|
||||
#define POWER_AND_PLL_CTRL_REG_25MHZ_VAL_1 0x1
|
||||
#define POWER_AND_PLL_CTRL_REG_25MHZ_VAL_2 0x2
|
||||
#define POWER_AND_PLL_CTRL_REG_40MHZ_VAL 0x3
|
||||
#define GLOBAL_PM_CTRL_REG_25MHZ_VAL 0x7
|
||||
#define GLOBAL_PM_CTRL_REG_40MHZ_VAL 0xc
|
||||
#define LANE_CFG4_REG_25MHZ_VAL 0x200
|
||||
#define LANE_CFG4_REG_40MHZ_VAL 0x300
|
||||
|
||||
#define POWER_AND_PLL_CTRL_REG_MASK (~(0x1f))
|
||||
#define GLOBAL_PM_CTRL_REG_MASK (~(0xff))
|
||||
#define LANE_CFG4_REG_MASK (~(0x1f00))
|
||||
|
||||
#define REF_CLK_SELECTOR_VAL_PEX0(reg_val) (reg_val >> 2) & 0x1
|
||||
#define REF_CLK_SELECTOR_VAL_PEX1(reg_val) (reg_val >> 3) & 0x1
|
||||
#define REF_CLK_SELECTOR_VAL_PEX2(reg_val) (reg_val >> 30) & 0x1
|
||||
#define REF_CLK_SELECTOR_VAL_PEX3(reg_val) (reg_val >> 31) & 0x1
|
||||
#define REF_CLK_SELECTOR_VAL(reg_val) (reg_val & 0x1)
|
||||
|
||||
#define MAX_SELECTOR_VAL 10
|
||||
|
||||
/* TWSI addresses */
|
||||
/* starting from A38x A0, i2c address of EEPROM is 0x57 */
|
||||
#ifdef CONFIG_ARMADA_39X
|
||||
#define EEPROM_I2C_ADDR 0x50
|
||||
#else
|
||||
#define EEPROM_I2C_ADDR (sys_env_device_rev_get() == \
|
||||
MV_88F68XX_Z1_ID ? 0x50 : 0x57)
|
||||
#endif
|
||||
#define RD_GET_MODE_ADDR 0x4c
|
||||
#define DB_GET_MODE_SLM1363_ADDR 0x25
|
||||
#define DB_GET_MODE_SLM1364_ADDR 0x24
|
||||
#define DB381_GET_MODE_SLM1426_1427_ADDR 0x56
|
||||
|
||||
/* DB-BP Board 'SatR' mapping */
|
||||
#define SATR_DB_LANE1_MAX_OPTIONS 7
|
||||
#define SATR_DB_LANE1_CFG_MASK 0x7
|
||||
#define SATR_DB_LANE1_CFG_OFFSET 0
|
||||
#define SATR_DB_LANE2_MAX_OPTIONS 4
|
||||
#define SATR_DB_LANE2_CFG_MASK 0x38
|
||||
#define SATR_DB_LANE2_CFG_OFFSET 3
|
||||
|
||||
/* GP Board 'SatR' mapping */
|
||||
#define SATR_GP_LANE1_CFG_MASK 0x4
|
||||
#define SATR_GP_LANE1_CFG_OFFSET 2
|
||||
#define SATR_GP_LANE2_CFG_MASK 0x8
|
||||
#define SATR_GP_LANE2_CFG_OFFSET 3
|
||||
|
||||
/* For setting MPP2 and MPP3 to be TWSI mode and MPP 0,1 to UART mode */
|
||||
#define MPP_CTRL_REG 0x18000
|
||||
#define MPP_SET_MASK (~(0xffff))
|
||||
#define MPP_SET_DATA (0x1111)
|
||||
#define MPP_UART1_SET_MASK (~(0xff000))
|
||||
#define MPP_UART1_SET_DATA (0x66000)
|
||||
|
||||
#define AVS_DEBUG_CNTR_REG 0xe4124
|
||||
#define AVS_DEBUG_CNTR_DEFAULT_VALUE 0x08008073
|
||||
|
||||
#define AVS_ENABLED_CONTROL 0xe4130
|
||||
#define AVS_LOW_VDD_LIMIT_OFFS 4
|
||||
#define AVS_LOW_VDD_LIMIT_MASK (0xff << AVS_LOW_VDD_LIMIT_OFFS)
|
||||
#define AVS_LOW_VDD_LIMIT_VAL (0x27 << AVS_LOW_VDD_LIMIT_OFFS)
|
||||
|
||||
#define AVS_HIGH_VDD_LIMIT_OFFS 12
|
||||
#define AVS_HIGH_VDD_LIMIT_MASK (0xff << AVS_HIGH_VDD_LIMIT_OFFS)
|
||||
#define AVS_HIGH_VDD_LIMIT_VAL (0x27 << AVS_HIGH_VDD_LIMIT_OFFS)
|
||||
|
||||
/* Board ID numbers */
|
||||
#define MARVELL_BOARD_ID_MASK 0x10
|
||||
/* Customer boards for A38x */
|
||||
#define A38X_CUSTOMER_BOARD_ID_BASE 0x0
|
||||
#define A38X_CUSTOMER_BOARD_ID0 (A38X_CUSTOMER_BOARD_ID_BASE + 0)
|
||||
#define A38X_CUSTOMER_BOARD_ID1 (A38X_CUSTOMER_BOARD_ID_BASE + 1)
|
||||
#define A38X_MV_MAX_CUSTOMER_BOARD_ID (A38X_CUSTOMER_BOARD_ID_BASE + 2)
|
||||
#define A38X_MV_CUSTOMER_BOARD_NUM (A38X_MV_MAX_CUSTOMER_BOARD_ID - \
|
||||
A38X_CUSTOMER_BOARD_ID_BASE)
|
||||
|
||||
/* Marvell boards for A38x */
|
||||
#define A38X_MARVELL_BOARD_ID_BASE 0x10
|
||||
#define RD_NAS_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 0)
|
||||
#define DB_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 1)
|
||||
#define RD_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 2)
|
||||
#define DB_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 3)
|
||||
#define DB_GP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 4)
|
||||
#define DB_BP_6821_ID (A38X_MARVELL_BOARD_ID_BASE + 5)
|
||||
#define DB_AMC_6820_ID (A38X_MARVELL_BOARD_ID_BASE + 6)
|
||||
#define A38X_MV_MAX_MARVELL_BOARD_ID (A38X_MARVELL_BOARD_ID_BASE + 7)
|
||||
#define A38X_MV_MARVELL_BOARD_NUM (A38X_MV_MAX_MARVELL_BOARD_ID - \
|
||||
A38X_MARVELL_BOARD_ID_BASE)
|
||||
|
||||
/* Customer boards for A39x */
|
||||
#define A39X_CUSTOMER_BOARD_ID_BASE 0x20
|
||||
#define A39X_CUSTOMER_BOARD_ID0 (A39X_CUSTOMER_BOARD_ID_BASE + 0)
|
||||
#define A39X_CUSTOMER_BOARD_ID1 (A39X_CUSTOMER_BOARD_ID_BASE + 1)
|
||||
#define A39X_MV_MAX_CUSTOMER_BOARD_ID (A39X_CUSTOMER_BOARD_ID_BASE + 2)
|
||||
#define A39X_MV_CUSTOMER_BOARD_NUM (A39X_MV_MAX_CUSTOMER_BOARD_ID - \
|
||||
A39X_CUSTOMER_BOARD_ID_BASE)
|
||||
|
||||
/* Marvell boards for A39x */
|
||||
#define A39X_MARVELL_BOARD_ID_BASE 0x30
|
||||
#define A39X_DB_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 0)
|
||||
#define A39X_RD_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 1)
|
||||
#define A39X_MV_MAX_MARVELL_BOARD_ID (A39X_MARVELL_BOARD_ID_BASE + 2)
|
||||
#define A39X_MV_MARVELL_BOARD_NUM (A39X_MV_MAX_MARVELL_BOARD_ID - \
|
||||
A39X_MARVELL_BOARD_ID_BASE)
|
||||
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
#define CUTOMER_BOARD_ID_BASE A38X_CUSTOMER_BOARD_ID_BASE
|
||||
#define CUSTOMER_BOARD_ID0 A38X_CUSTOMER_BOARD_ID0
|
||||
#define CUSTOMER_BOARD_ID1 A38X_CUSTOMER_BOARD_ID1
|
||||
#define MV_MAX_CUSTOMER_BOARD_ID A38X_MV_MAX_CUSTOMER_BOARD_ID
|
||||
#define MV_CUSTOMER_BOARD_NUM A38X_MV_CUSTOMER_BOARD_NUM
|
||||
#define MARVELL_BOARD_ID_BASE A38X_MARVELL_BOARD_ID_BASE
|
||||
#define MV_MAX_MARVELL_BOARD_ID A38X_MV_MAX_MARVELL_BOARD_ID
|
||||
#define MV_MARVELL_BOARD_NUM A38X_MV_MARVELL_BOARD_NUM
|
||||
#define MV_DEFAULT_BOARD_ID DB_68XX_ID
|
||||
#define MV_DEFAULT_DEVICE_ID MV_6811
|
||||
#elif defined(CONFIG_ARMADA_39X)
|
||||
#define CUTOMER_BOARD_ID_BASE A39X_CUSTOMER_BOARD_ID_BASE
|
||||
#define CUSTOMER_BOARD_ID0 A39X_CUSTOMER_BOARD_ID0
|
||||
#define CUSTOMER_BOARD_ID1 A39X_CUSTOMER_BOARD_ID1
|
||||
#define MV_MAX_CUSTOMER_BOARD_ID A39X_MV_MAX_CUSTOMER_BOARD_ID
|
||||
#define MV_CUSTOMER_BOARD_NUM A39X_MV_CUSTOMER_BOARD_NUM
|
||||
#define MARVELL_BOARD_ID_BASE A39X_MARVELL_BOARD_ID_BASE
|
||||
#define MV_MAX_MARVELL_BOARD_ID A39X_MV_MAX_MARVELL_BOARD_ID
|
||||
#define MV_MARVELL_BOARD_NUM A39X_MV_MARVELL_BOARD_NUM
|
||||
#define MV_DEFAULT_BOARD_ID A39X_DB_69XX_ID
|
||||
#define MV_DEFAULT_DEVICE_ID MV_6920
|
||||
#endif
|
||||
|
||||
#define MV_INVALID_BOARD_ID 0xffffffff
|
||||
|
||||
/* device revesion */
|
||||
#define DEV_VERSION_ID_REG 0x1823c
|
||||
#define REVISON_ID_OFFS 8
|
||||
#define REVISON_ID_MASK 0xf00
|
||||
|
||||
/* A38x revisions */
|
||||
#define MV_88F68XX_Z1_ID 0x0
|
||||
#define MV_88F68XX_A0_ID 0x4
|
||||
/* A39x revisions */
|
||||
#define MV_88F69XX_Z1_ID 0x2
|
||||
|
||||
#define MPP_CONTROL_REG(id) (0x18000 + (id * 4))
|
||||
#define GPP_DATA_OUT_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x00)
|
||||
#define GPP_DATA_OUT_EN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x04)
|
||||
#define GPP_DATA_IN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x10)
|
||||
#define MV_GPP_REGS_BASE(unit) (0x18100 + ((unit) * 0x40))
|
||||
|
||||
#define MPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 8)
|
||||
#define MPP_MASK(GPIO_NUM) (0xf << 4 * (GPIO_NUM - \
|
||||
(MPP_REG_NUM(GPIO_NUM) * 8)));
|
||||
#define GPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 32)
|
||||
#define GPP_MASK(GPIO_NUM) (1 << GPIO_NUM % 32)
|
||||
|
||||
/* device ID */
|
||||
/* Armada 38x Family */
|
||||
#define MV_6810_DEV_ID 0x6810
|
||||
#define MV_6811_DEV_ID 0x6811
|
||||
#define MV_6820_DEV_ID 0x6820
|
||||
#define MV_6828_DEV_ID 0x6828
|
||||
/* Armada 39x Family */
|
||||
#define MV_6920_DEV_ID 0x6920
|
||||
#define MV_6928_DEV_ID 0x6928
|
||||
|
||||
enum {
|
||||
MV_6810,
|
||||
MV_6820,
|
||||
MV_6811,
|
||||
MV_6828,
|
||||
MV_NONE,
|
||||
MV_6920,
|
||||
MV_6928,
|
||||
MV_MAX_DEV_ID,
|
||||
};
|
||||
|
||||
#define MV_6820_INDEX 0
|
||||
#define MV_6810_INDEX 1
|
||||
#define MV_6811_INDEX 2
|
||||
#define MV_6828_INDEX 3
|
||||
|
||||
#define MV_6920_INDEX 0
|
||||
#define MV_6928_INDEX 1
|
||||
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
#define MAX_DEV_ID_NUM 4
|
||||
#else
|
||||
#define MAX_DEV_ID_NUM 2
|
||||
#endif
|
||||
|
||||
#define MV_6820_INDEX 0
|
||||
#define MV_6810_INDEX 1
|
||||
#define MV_6811_INDEX 2
|
||||
#define MV_6828_INDEX 3
|
||||
#define MV_6920_INDEX 0
|
||||
#define MV_6928_INDEX 1
|
||||
|
||||
enum unit_id {
|
||||
PEX_UNIT_ID,
|
||||
ETH_GIG_UNIT_ID,
|
||||
USB3H_UNIT_ID,
|
||||
USB3D_UNIT_ID,
|
||||
SATA_UNIT_ID,
|
||||
QSGMII_UNIT_ID,
|
||||
XAUI_UNIT_ID,
|
||||
RXAUI_UNIT_ID,
|
||||
MAX_UNITS_ID
|
||||
};
|
||||
|
||||
struct board_wakeup_gpio {
|
||||
u32 board_id;
|
||||
int gpio_num;
|
||||
};
|
||||
|
||||
enum suspend_wakeup_status {
|
||||
SUSPEND_WAKEUP_DISABLED,
|
||||
SUSPEND_WAKEUP_ENABLED,
|
||||
SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED,
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO status indication for Suspend Wakeup:
|
||||
* If suspend to RAM is supported and GPIO inidcation is implemented,
|
||||
* set the gpio number
|
||||
* If suspend to RAM is supported but GPIO indication is not implemented
|
||||
* set '-2'
|
||||
* If suspend to RAM is not supported set '-1'
|
||||
*/
|
||||
#ifdef CONFIG_CUSTOMER_BOARD_SUPPORT
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
#define MV_BOARD_WAKEUP_GPIO_INFO { \
|
||||
{A38X_CUSTOMER_BOARD_ID0, -1 }, \
|
||||
{A38X_CUSTOMER_BOARD_ID0, -1 }, \
|
||||
};
|
||||
#else
|
||||
#define MV_BOARD_WAKEUP_GPIO_INFO { \
|
||||
{A39X_CUSTOMER_BOARD_ID0, -1 }, \
|
||||
{A39X_CUSTOMER_BOARD_ID0, -1 }, \
|
||||
};
|
||||
#endif /* CONFIG_ARMADA_38X */
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
#define MV_BOARD_WAKEUP_GPIO_INFO { \
|
||||
{RD_NAS_68XX_ID, -2 }, \
|
||||
{DB_68XX_ID, -1 }, \
|
||||
{RD_AP_68XX_ID, -2 }, \
|
||||
{DB_AP_68XX_ID, -2 }, \
|
||||
{DB_GP_68XX_ID, -2 }, \
|
||||
{DB_BP_6821_ID, -2 }, \
|
||||
{DB_AMC_6820_ID, -2 }, \
|
||||
};
|
||||
#else
|
||||
#define MV_BOARD_WAKEUP_GPIO_INFO { \
|
||||
{A39X_RD_69XX_ID, -1 }, \
|
||||
{A39X_DB_69XX_ID, -1 }, \
|
||||
};
|
||||
#endif /* CONFIG_ARMADA_38X */
|
||||
#endif /* CONFIG_CUSTOMER_BOARD_SUPPORT */
|
||||
|
||||
u32 mv_board_tclk_get(void);
|
||||
u32 mv_board_id_get(void);
|
||||
u32 mv_board_id_index_get(u32 board_id);
|
||||
u32 sys_env_unit_max_num_get(enum unit_id unit);
|
||||
enum suspend_wakeup_status sys_env_suspend_wakeup_check(void);
|
||||
u8 sys_env_device_rev_get(void);
|
||||
u32 sys_env_device_id_get(void);
|
||||
u16 sys_env_model_get(void);
|
||||
struct dlb_config *sys_env_dlb_config_ptr_get(void);
|
||||
u32 sys_env_get_cs_ena_from_reg(void);
|
||||
|
||||
#endif /* _SYS_ENV_LIB_H */
|
||||
6
u-boot/arch/arm/mach-mvebu/serdes/axp/Makefile
Normal file
6
u-boot/arch/arm/mach-mvebu/serdes/axp/Makefile
Normal file
@@ -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
|
||||
262
u-boot/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h
Normal file
262
u-boot/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h
Normal file
@@ -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 + 1)
|
||||
#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_BOARD_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 */
|
||||
1580
u-boot/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c
Normal file
1580
u-boot/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c
Normal file
File diff suppressed because it is too large
Load Diff
185
u-boot/arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.c
Normal file
185
u-boot/arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.c
Normal file
@@ -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 };
|
||||
87
u-boot/arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h
Normal file
87
u-boot/arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h
Normal file
@@ -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/marvell/axp/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 */
|
||||
124
u-boot/arch/arm/mach-mvebu/spl.c
Normal file
124
u-boot/arch/arm/mach-mvebu/spl.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Stefan Roese <sr@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <debug_uart.h>
|
||||
#include <fdtdec.h>
|
||||
#include <spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static u32 get_boot_device(void)
|
||||
{
|
||||
u32 val;
|
||||
u32 boot_device;
|
||||
|
||||
/*
|
||||
* First check, if UART boot-mode is active. This can only
|
||||
* be done, via the bootrom error register. Here the
|
||||
* MSB marks if the UART mode is active.
|
||||
*/
|
||||
val = readl(CONFIG_BOOTROM_ERR_REG);
|
||||
boot_device = (val & BOOTROM_ERR_MODE_MASK) >> BOOTROM_ERR_MODE_OFFS;
|
||||
debug("BOOTROM_REG=0x%08x boot_device=0x%x\n", val, boot_device);
|
||||
if (boot_device == BOOTROM_ERR_MODE_UART)
|
||||
return BOOT_DEVICE_UART;
|
||||
|
||||
/*
|
||||
* Now check the SAR register for the strapped boot-device
|
||||
*/
|
||||
val = readl(CONFIG_SAR_REG); /* SAR - Sample At Reset */
|
||||
boot_device = (val & BOOT_DEV_SEL_MASK) >> BOOT_DEV_SEL_OFFS;
|
||||
debug("SAR_REG=0x%08x boot_device=0x%x\n", val, boot_device);
|
||||
switch (boot_device) {
|
||||
#ifdef CONFIG_SPL_MMC_SUPPORT
|
||||
case BOOT_FROM_MMC:
|
||||
case BOOT_FROM_MMC_ALT:
|
||||
return BOOT_DEVICE_MMC1;
|
||||
#endif
|
||||
case BOOT_FROM_UART:
|
||||
return BOOT_DEVICE_UART;
|
||||
case BOOT_FROM_SPI:
|
||||
default:
|
||||
return BOOT_DEVICE_SPI;
|
||||
};
|
||||
}
|
||||
|
||||
u32 spl_boot_device(void)
|
||||
{
|
||||
return get_boot_device();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_MMC_SUPPORT
|
||||
u32 spl_boot_mode(const u32 boot_device)
|
||||
{
|
||||
return MMCSD_MODE_RAW;
|
||||
}
|
||||
#endif
|
||||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Pin muxing needs to be done before UART output, since
|
||||
* on A38x the UART pins need some re-muxing for output
|
||||
* to work.
|
||||
*/
|
||||
board_early_init_f();
|
||||
|
||||
/* Example code showing how to enable the debug UART on MVEBU */
|
||||
#ifdef EARLY_UART
|
||||
/*
|
||||
* Debug UART can be used from here if required:
|
||||
*
|
||||
* debug_uart_init();
|
||||
* printch('a');
|
||||
* printhex8(0x1234);
|
||||
* printascii("string");
|
||||
*/
|
||||
#endif
|
||||
|
||||
ret = spl_init();
|
||||
if (ret) {
|
||||
debug("spl_init() failed: %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
|
||||
/* Use special translation offset for SPL */
|
||||
dm_set_translation_offset(0xd0000000 - 0xf1000000);
|
||||
|
||||
preloader_console_init();
|
||||
|
||||
timer_init();
|
||||
|
||||
/* Armada 375 does not support SerDes and DDR3 init yet */
|
||||
#if !defined(CONFIG_ARMADA_375)
|
||||
/* First init the serdes PHY's */
|
||||
serdes_phy_config();
|
||||
|
||||
/* Setup DDR */
|
||||
ddr3_init();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return to the BootROM to continue the Marvell xmodem
|
||||
* UART boot protocol. As initiated by the kwboot tool.
|
||||
*
|
||||
* This can only be done by the BootROM and not by the
|
||||
* U-Boot SPL infrastructure, since the beginning of the
|
||||
* image is already read and interpreted by the BootROM.
|
||||
* SPL has no chance to receive this information. So we
|
||||
* need to return to the BootROM to enable this xmodem
|
||||
* UART download.
|
||||
*/
|
||||
if (get_boot_device() == BOOT_DEVICE_UART)
|
||||
return_to_bootrom();
|
||||
}
|
||||
42
u-boot/arch/arm/mach-mvebu/timer.c
Normal file
42
u-boot/arch/arm/mach-mvebu/timer.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*
|
||||
* Copyright (C) 2015 Stefan Roese <sr@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define TIMER_LOAD_VAL 0xffffffff
|
||||
|
||||
static int init_done __attribute__((section(".data"))) = 0;
|
||||
|
||||
/*
|
||||
* Timer initialization
|
||||
*/
|
||||
int timer_init(void)
|
||||
{
|
||||
/* Only init the timer once */
|
||||
if (init_done)
|
||||
return 0;
|
||||
init_done = 1;
|
||||
|
||||
/* load value into timer */
|
||||
writel(TIMER_LOAD_VAL, MVEBU_TIMER_BASE + 0x10);
|
||||
writel(TIMER_LOAD_VAL, MVEBU_TIMER_BASE + 0x14);
|
||||
|
||||
#if defined(CONFIG_ARCH_MVEBU)
|
||||
/* On Armada XP / 38x ..., the 25MHz clock source needs to be enabled */
|
||||
setbits_le32(MVEBU_TIMER_BASE + 0x00, BIT(11));
|
||||
#endif
|
||||
/* enable timer in auto reload mode */
|
||||
setbits_le32(MVEBU_TIMER_BASE + 0x00, 0x3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user