GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,282 @@
|
||||
if ARCH_MVEBU
|
||||
|
||||
config HAVE_MVEBU_EFUSE
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARMADA_32BIT
|
||||
bool
|
||||
select ARCH_MISC_INIT
|
||||
select BOARD_EARLY_INIT_F
|
||||
select CPU_V7A
|
||||
select SPL_DM if SPL
|
||||
select SPL_DM_SEQ_ALIAS if SPL
|
||||
select SPL_OF_CONTROL if SPL
|
||||
select SPL_SIMPLE_BUS if SPL
|
||||
select SUPPORT_SPL
|
||||
select TRANSLATION_OFFSET
|
||||
|
||||
config ARMADA_64BIT
|
||||
bool
|
||||
select ARM64
|
||||
|
||||
# ARMv7 SoCs...
|
||||
config ARMADA_375
|
||||
bool
|
||||
select ARMADA_32BIT
|
||||
|
||||
config ARMADA_38X
|
||||
bool
|
||||
select ARMADA_32BIT
|
||||
select HAVE_MVEBU_EFUSE
|
||||
|
||||
config ARMADA_XP
|
||||
bool
|
||||
select ARMADA_32BIT
|
||||
|
||||
# ARMv8 SoCs...
|
||||
config ARMADA_3700
|
||||
bool
|
||||
select ARM64
|
||||
|
||||
# Armada 7K and 8K are very similar - use only one Kconfig symbol for both
|
||||
config ARMADA_8K
|
||||
bool
|
||||
select ARM64
|
||||
|
||||
# Armada PLL frequency (used for NAND clock generation)
|
||||
config SYS_MVEBU_PLL_CLOCK
|
||||
int
|
||||
default "2000000000" if ARMADA_XP || ARMADA_3700 || ARMADA_8K || ARMADA_MSYS
|
||||
default "1000000000" if ARMADA_38X || ARMADA_375
|
||||
|
||||
# Armada XP/38x SoC types...
|
||||
config MV78230
|
||||
bool
|
||||
select ARMADA_XP
|
||||
|
||||
config MV78260
|
||||
bool
|
||||
select ARMADA_XP
|
||||
imply CMD_SATA
|
||||
|
||||
config MV78460
|
||||
bool
|
||||
select ARMADA_XP
|
||||
|
||||
config ARMADA_MSYS
|
||||
bool
|
||||
select ARMADA_32BIT
|
||||
|
||||
config 98DX4251
|
||||
bool
|
||||
select ARMADA_MSYS
|
||||
|
||||
config 98DX3336
|
||||
bool
|
||||
select ARMADA_MSYS
|
||||
|
||||
config 98DX3236
|
||||
bool
|
||||
select ARMADA_MSYS
|
||||
|
||||
config 88F6820
|
||||
bool
|
||||
select ARMADA_38X
|
||||
|
||||
choice
|
||||
prompt "Armada XP/375/38x/3700/7K/8K board select"
|
||||
optional
|
||||
|
||||
config TARGET_CLEARFOG
|
||||
bool "Support ClearFog"
|
||||
select 88F6820
|
||||
|
||||
config TARGET_HELIOS4
|
||||
bool "Support Helios4"
|
||||
select 88F6820
|
||||
|
||||
config TARGET_MVEBU_ARMADA_37XX
|
||||
bool "Support Armada 37xx platforms"
|
||||
select ARMADA_3700
|
||||
imply SCSI
|
||||
|
||||
config TARGET_DB_88F6720
|
||||
bool "Support DB-88F6720 Armada 375"
|
||||
select ARMADA_375
|
||||
|
||||
config TARGET_DB_88F6820_GP
|
||||
bool "Support DB-88F6820-GP"
|
||||
select 88F6820
|
||||
|
||||
config TARGET_DB_88F6820_AMC
|
||||
bool "Support DB-88F6820-AMC"
|
||||
select 88F6820
|
||||
|
||||
config TARGET_TURRIS_OMNIA
|
||||
bool "Support Turris Omnia"
|
||||
select 88F6820
|
||||
select BOARD_LATE_INIT
|
||||
select DM_I2C
|
||||
select I2C_MUX
|
||||
select I2C_MUX_PCA954x
|
||||
select SPL_I2C_MUX
|
||||
select SYS_I2C_MVTWSI
|
||||
select ATSHA204A
|
||||
|
||||
config TARGET_TURRIS_MOX
|
||||
bool "Support Turris Mox"
|
||||
select ARMADA_3700
|
||||
|
||||
config TARGET_MVEBU_ARMADA_8K
|
||||
bool "Support Armada 7k/8k platforms"
|
||||
select ARMADA_8K
|
||||
select BOARD_LATE_INIT
|
||||
imply SCSI
|
||||
|
||||
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 BOARD_LATE_INIT if USB
|
||||
select MV78260
|
||||
imply CMD_SATA
|
||||
|
||||
config TARGET_CONTROLCENTERDC
|
||||
bool "Support CONTROLCENTERDC"
|
||||
select 88F6820
|
||||
|
||||
config TARGET_X530
|
||||
bool "Support Allied Telesis x530"
|
||||
select 88F6820
|
||||
|
||||
config TARGET_DB_XC3_24G4XG
|
||||
bool "Support DB-XC3-24G4XG"
|
||||
select 98DX3336
|
||||
|
||||
config TARGET_CRS305_1G_4S
|
||||
bool "Support CRS305-1G-4S"
|
||||
select 98DX3236
|
||||
|
||||
endchoice
|
||||
|
||||
config SYS_BOARD
|
||||
default "clearfog" if TARGET_CLEARFOG
|
||||
default "helios4" if TARGET_HELIOS4
|
||||
default "mvebu_armada-37xx" if TARGET_MVEBU_ARMADA_37XX
|
||||
default "db-88f6720" if TARGET_DB_88F6720
|
||||
default "db-88f6820-gp" if TARGET_DB_88F6820_GP
|
||||
default "db-88f6820-amc" if TARGET_DB_88F6820_AMC
|
||||
default "turris_omnia" if TARGET_TURRIS_OMNIA
|
||||
default "turris_mox" if TARGET_TURRIS_MOX
|
||||
default "mvebu_armada-8k" if TARGET_MVEBU_ARMADA_8K
|
||||
default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
|
||||
default "ds414" if TARGET_DS414
|
||||
default "maxbcm" if TARGET_MAXBCM
|
||||
default "theadorable" if TARGET_THEADORABLE
|
||||
default "a38x" if TARGET_CONTROLCENTERDC
|
||||
default "x530" if TARGET_X530
|
||||
default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG
|
||||
default "crs305-1g-4s" if TARGET_CRS305_1G_4S
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "clearfog" if TARGET_CLEARFOG
|
||||
default "helios4" if TARGET_HELIOS4
|
||||
default "mvebu_armada-37xx" if TARGET_MVEBU_ARMADA_37XX
|
||||
default "db-88f6720" if TARGET_DB_88F6720
|
||||
default "db-88f6820-gp" if TARGET_DB_88F6820_GP
|
||||
default "db-88f6820-amc" if TARGET_DB_88F6820_AMC
|
||||
default "mvebu_armada-8k" if TARGET_MVEBU_ARMADA_8K
|
||||
default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
|
||||
default "ds414" if TARGET_DS414
|
||||
default "maxbcm" if TARGET_MAXBCM
|
||||
default "theadorable" if TARGET_THEADORABLE
|
||||
default "turris_omnia" if TARGET_TURRIS_OMNIA
|
||||
default "turris_mox" if TARGET_TURRIS_MOX
|
||||
default "controlcenterdc" if TARGET_CONTROLCENTERDC
|
||||
default "x530" if TARGET_X530
|
||||
default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG
|
||||
default "crs305-1g-4s" if TARGET_CRS305_1G_4S
|
||||
|
||||
config SYS_VENDOR
|
||||
default "Marvell" if TARGET_DB_MV784MP_GP
|
||||
default "Marvell" if TARGET_MVEBU_ARMADA_37XX
|
||||
default "Marvell" if TARGET_DB_88F6720
|
||||
default "Marvell" if TARGET_DB_88F6820_GP
|
||||
default "Marvell" if TARGET_DB_88F6820_AMC
|
||||
default "Marvell" if TARGET_MVEBU_ARMADA_8K
|
||||
default "Marvell" if TARGET_DB_XC3_24G4XG
|
||||
default "Marvell" if TARGET_MVEBU_DB_88F7040
|
||||
default "solidrun" if TARGET_CLEARFOG
|
||||
default "kobol" if TARGET_HELIOS4
|
||||
default "Synology" if TARGET_DS414
|
||||
default "CZ.NIC" if TARGET_TURRIS_OMNIA
|
||||
default "CZ.NIC" if TARGET_TURRIS_MOX
|
||||
default "gdsys" if TARGET_CONTROLCENTERDC
|
||||
default "alliedtelesis" if TARGET_X530
|
||||
default "mikrotik" if TARGET_CRS305_1G_4S
|
||||
|
||||
config SYS_SOC
|
||||
default "mvebu"
|
||||
|
||||
choice
|
||||
prompt "Boot method"
|
||||
|
||||
config MVEBU_SPL_BOOT_DEVICE_SPI
|
||||
bool "SPI NOR flash"
|
||||
|
||||
config MVEBU_SPL_BOOT_DEVICE_MMC
|
||||
bool "SDIO/MMC card"
|
||||
select SPL_LIBDISK_SUPPORT
|
||||
|
||||
config MVEBU_SPL_BOOT_DEVICE_SATA
|
||||
bool "SATA"
|
||||
select SPL_SATA_SUPPORT
|
||||
select SPL_LIBDISK_SUPPORT
|
||||
|
||||
config MVEBU_SPL_BOOT_DEVICE_UART
|
||||
bool "UART"
|
||||
|
||||
endchoice
|
||||
|
||||
config MVEBU_EFUSE
|
||||
bool "Enable eFuse support"
|
||||
default n
|
||||
depends on HAVE_MVEBU_EFUSE
|
||||
help
|
||||
Enable support for reading and writing eFuses on mvebu SoCs.
|
||||
|
||||
config MVEBU_EFUSE_FAKE
|
||||
bool "Fake eFuse access (dry run)"
|
||||
default n
|
||||
depends on MVEBU_EFUSE
|
||||
help
|
||||
This enables a "dry run" mode where eFuses are not really programmed.
|
||||
Instead the eFuse accesses are emulated by writing to and reading
|
||||
from a memory block.
|
||||
This is can be used for testing prog scripts.
|
||||
|
||||
config SECURED_MODE_IMAGE
|
||||
bool "Build image for trusted boot"
|
||||
default false
|
||||
depends on 88F6820
|
||||
help
|
||||
Build an image that employs the ARMADA SoC's trusted boot framework
|
||||
for securely booting images.
|
||||
|
||||
config SECURED_MODE_CSK_INDEX
|
||||
int "Index of active CSK"
|
||||
default 0
|
||||
depends on SECURED_MODE_IMAGE
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,77 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2014-2016 Stefan Roese <sr@denx.de>
|
||||
|
||||
ifdef CONFIG_ARM64
|
||||
|
||||
obj-$(CONFIG_ARMADA_3700) += armada3700/
|
||||
obj-$(CONFIG_ARMADA_8K) += armada8k/
|
||||
obj-y += arm64-common.o
|
||||
|
||||
else # CONFIG_ARM64
|
||||
|
||||
ifdef CONFIG_KIRKWOOD
|
||||
|
||||
obj-y = dram.o
|
||||
obj-y += gpio.o
|
||||
obj-y += mbus.o
|
||||
obj-y += timer.o
|
||||
|
||||
else # CONFIG_KIRKWOOD
|
||||
|
||||
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
|
||||
obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
|
||||
obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
|
||||
|
||||
extra-y += kwbimage.cfg
|
||||
|
||||
KWB_REPLACE += BOOT_FROM
|
||||
ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_SPI),)
|
||||
KWB_CFG_BOOT_FROM=spi
|
||||
endif
|
||||
ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_MMC),)
|
||||
KWB_CFG_BOOT_FROM=sdio
|
||||
endif
|
||||
ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_SATA),)
|
||||
KWB_CFG_BOOT_FROM=sata
|
||||
endif
|
||||
ifneq ($(CONFIG_MVEBU_SPL_BOOT_DEVICE_UART),)
|
||||
KWB_CFG_BOOT_FROM=uart
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_SECURED_MODE_IMAGE),)
|
||||
KWB_REPLACE += CSK_INDEX
|
||||
KWB_CFG_CSK_INDEX = $(CONFIG_SECURED_MODE_CSK_INDEX)
|
||||
|
||||
KWB_REPLACE += SEC_BOOT_DEV
|
||||
KWB_CFG_SEC_BOOT_DEV=$(patsubst "%",%, \
|
||||
$(if $(findstring BOOT_SPI_NOR_FLASH,$(CONFIG_SPL_BOOT_DEVICE)),0x34) \
|
||||
$(if $(findstring BOOT_SDIO_MMC_CARD,$(CONFIG_SPL_BOOT_DEVICE)),0x31) \
|
||||
)
|
||||
|
||||
KWB_REPLACE += SEC_FUSE_DUMP
|
||||
KWB_CFG_SEC_FUSE_DUMP = a38x
|
||||
endif
|
||||
|
||||
$(obj)/kwbimage.cfg: $(src)/kwbimage.cfg.in include/autoconf.mk \
|
||||
include/config/auto.conf
|
||||
$(Q)sed -ne '$(foreach V,$(KWB_REPLACE),s/^#@$(V)/$(V) $(KWB_CFG_$(V))/;)p' \
|
||||
<$< >$(dir $@)$(@F)
|
||||
|
||||
endif # CONFIG_SPL_BUILD
|
||||
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 # CONFIG_KIRKWOOD
|
||||
endif # CONFIG_ARM64
|
||||
@@ -0,0 +1,147 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2016 Stefan Roese <sr@denx.de>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <init.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <pci.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* Not all memory is mapped in the MMU. So we need to restrict the
|
||||
* memory size so that U-Boot does not try to access it. Also, the
|
||||
* internal registers are located at 0xf000.0000 - 0xffff.ffff.
|
||||
* Currently only 2GiB are mapped for system memory. This is what
|
||||
* we pass to the U-Boot subsystem here.
|
||||
*/
|
||||
#define USABLE_RAM_SIZE 0x80000000
|
||||
|
||||
ulong board_get_usable_ram_top(ulong total_size)
|
||||
{
|
||||
if (gd->ram_size > USABLE_RAM_SIZE)
|
||||
return USABLE_RAM_SIZE;
|
||||
|
||||
return gd->ram_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* On ARMv8, MBus is not configured in U-Boot. To enable compilation
|
||||
* of the already implemented drivers, lets add a dummy version of
|
||||
* this function so that linking does not fail.
|
||||
*/
|
||||
const struct mbus_dram_target_info *mvebu_mbus_dram_info(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* DRAM init code ... */
|
||||
|
||||
#define MV_SIP_DRAM_SIZE 0x82000010
|
||||
|
||||
static u64 a8k_dram_scan_ap_sz(void)
|
||||
{
|
||||
struct pt_regs pregs;
|
||||
|
||||
pregs.regs[0] = MV_SIP_DRAM_SIZE;
|
||||
pregs.regs[1] = SOC_REGS_PHY_BASE;
|
||||
smc_call(&pregs);
|
||||
|
||||
return pregs.regs[0];
|
||||
}
|
||||
|
||||
static void a8k_dram_init_banksize(void)
|
||||
{
|
||||
/*
|
||||
* The firmware (ATF) leaves a 1G whole above the 3G mark for IO
|
||||
* devices. Higher RAM is mapped at 4G.
|
||||
*
|
||||
* Config 2 DRAM banks:
|
||||
* Bank 0 - max size 4G - 1G
|
||||
* Bank 1 - ram size - 4G + 1G
|
||||
*/
|
||||
phys_size_t max_bank0_size = SZ_4G - SZ_1G;
|
||||
|
||||
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
|
||||
if (gd->ram_size <= max_bank0_size) {
|
||||
gd->bd->bi_dram[0].size = gd->ram_size;
|
||||
return;
|
||||
}
|
||||
|
||||
gd->bd->bi_dram[0].size = max_bank0_size;
|
||||
if (CONFIG_NR_DRAM_BANKS > 1) {
|
||||
gd->bd->bi_dram[1].start = SZ_4G;
|
||||
gd->bd->bi_dram[1].size = gd->ram_size - max_bank0_size;
|
||||
}
|
||||
}
|
||||
|
||||
__weak int dram_init_banksize(void)
|
||||
{
|
||||
if (CONFIG_IS_ENABLED(ARMADA_8K))
|
||||
a8k_dram_init_banksize();
|
||||
else
|
||||
fdtdec_setup_memory_banksize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int dram_init(void)
|
||||
{
|
||||
if (CONFIG_IS_ENABLED(ARMADA_8K)) {
|
||||
gd->ram_size = a8k_dram_scan_ap_sz();
|
||||
if (gd->ram_size != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fdtdec_setup_mem_size_base() != 0)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
/* Nothing to do (yet) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_early_init_r(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Loop over all MISC uclass drivers to call the comphy code
|
||||
* and init all CP110 devices enabled in the DT
|
||||
*/
|
||||
i = 0;
|
||||
while (1) {
|
||||
/* Call the comphy code via the MISC uclass driver */
|
||||
ret = uclass_get_device(UCLASS_MISC, i++, &dev);
|
||||
|
||||
/* We're done, once no further CP110 device is found */
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cause the SATA device to do its early init */
|
||||
uclass_first_device(UCLASS_AHCI, &dev);
|
||||
|
||||
#ifdef CONFIG_DM_PCI
|
||||
/* Trigger PCIe devices detection */
|
||||
pci_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2016 Stefan Roese <sr@denx.de>
|
||||
|
||||
obj-y = cpu.o
|
||||
@@ -0,0 +1,86 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2016 Stefan Roese <sr@denx.de>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
|
||||
/* Armada 3700 */
|
||||
#define MVEBU_GPIO_NB_REG_BASE (MVEBU_REGISTER(0x13800))
|
||||
|
||||
#define MVEBU_TEST_PIN_LATCH_N (MVEBU_GPIO_NB_REG_BASE + 0x8)
|
||||
#define MVEBU_XTAL_MODE_MASK BIT(9)
|
||||
#define MVEBU_XTAL_MODE_OFFS 9
|
||||
#define MVEBU_XTAL_CLOCK_25MHZ 0x0
|
||||
#define MVEBU_XTAL_CLOCK_40MHZ 0x1
|
||||
|
||||
#define MVEBU_NB_WARM_RST_REG (MVEBU_GPIO_NB_REG_BASE + 0x40)
|
||||
#define MVEBU_NB_WARM_RST_MAGIC_NUM 0x1d1e
|
||||
|
||||
static struct mm_region mvebu_mem_map[] = {
|
||||
{
|
||||
/* RAM */
|
||||
.phys = 0x0UL,
|
||||
.virt = 0x0UL,
|
||||
.size = 0x80000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
|
||||
PTE_BLOCK_INNER_SHARE
|
||||
},
|
||||
{
|
||||
/* SRAM, MMIO regions */
|
||||
.phys = 0xd0000000UL,
|
||||
.virt = 0xd0000000UL,
|
||||
.size = 0x02000000UL, /* 32MiB internal registers */
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE
|
||||
},
|
||||
{
|
||||
/* PCI regions */
|
||||
.phys = 0xe8000000UL,
|
||||
.virt = 0xe8000000UL,
|
||||
.size = 0x02000000UL, /* 32MiB master PCI space */
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE
|
||||
},
|
||||
{
|
||||
/* List terminator */
|
||||
0,
|
||||
}
|
||||
};
|
||||
|
||||
struct mm_region *mem_map = mvebu_mem_map;
|
||||
|
||||
void reset_cpu(ulong ignored)
|
||||
{
|
||||
/*
|
||||
* Write magic number of 0x1d1e to North Bridge Warm Reset register
|
||||
* to trigger warm reset
|
||||
*/
|
||||
writel(MVEBU_NB_WARM_RST_MAGIC_NUM, MVEBU_NB_WARM_RST_REG);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_ref_clk
|
||||
*
|
||||
* return: reference clock in MHz (25 or 40)
|
||||
*/
|
||||
u32 get_ref_clk(void)
|
||||
{
|
||||
u32 regval;
|
||||
|
||||
regval = (readl(MVEBU_TEST_PIN_LATCH_N) & MVEBU_XTAL_MODE_MASK) >>
|
||||
MVEBU_XTAL_MODE_OFFS;
|
||||
|
||||
if (regval == MVEBU_XTAL_CLOCK_25MHZ)
|
||||
return 25;
|
||||
else
|
||||
return 40;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2016 Stefan Roese <sr@denx.de>
|
||||
|
||||
obj-y = cpu.o
|
||||
obj-y += cache_llc.o
|
||||
@@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2016 Marvell International Ltd.
|
||||
*/
|
||||
|
||||
#include <asm/arch-armada8k/cache_llc.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
/*
|
||||
* int __asm_flush_l3_dcache
|
||||
*
|
||||
* flush Armada-8K last level cache.
|
||||
*
|
||||
*/
|
||||
ENTRY(__asm_flush_l3_dcache)
|
||||
/* flush cache */
|
||||
mov x0, #LLC_BASE_ADDR
|
||||
add x0, x0, #LLC_FLUSH_BY_WAY
|
||||
movk x0, #MVEBU_A8K_REGS_BASE_MSB, lsl #16
|
||||
mov w1, #LLC_WAY_MASK
|
||||
str w1, [x0]
|
||||
/* sync cache */
|
||||
mov x0, #LLC_BASE_ADDR
|
||||
add x0, x0, #LLC_CACHE_SYNC
|
||||
movk x0, #MVEBU_A8K_REGS_BASE_MSB, lsl #16
|
||||
str wzr, [x0]
|
||||
/* check that cache sync completed */
|
||||
mov x0, #LLC_BASE_ADDR
|
||||
add x0, x0, #LLC_CACHE_SYNC_COMPLETE
|
||||
movk x0, #MVEBU_A8K_REGS_BASE_MSB, lsl #16
|
||||
1: ldr w1, [x0]
|
||||
and w1, w1, #LLC_CACHE_SYNC_MASK
|
||||
cbnz w1, 1b
|
||||
/* return success */
|
||||
mov x0, #0
|
||||
ret
|
||||
ENDPROC(__asm_flush_l3_dcache)
|
||||
@@ -0,0 +1,152 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2016 Stefan Roese <sr@denx.de>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <cpu_func.h>
|
||||
#include <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <asm/armv8/mmu.h>
|
||||
|
||||
/* Armada 7k/8k */
|
||||
#define MVEBU_RFU_BASE (MVEBU_REGISTER(0x6f0000))
|
||||
#define RFU_GLOBAL_SW_RST (MVEBU_RFU_BASE + 0x84)
|
||||
#define RFU_SW_RESET_OFFSET 0
|
||||
|
||||
#define SAR0_REG (MVEBU_REGISTER(0x2400200))
|
||||
#define BOOT_MODE_MASK 0x3f
|
||||
#define BOOT_MODE_OFFSET 4
|
||||
|
||||
/*
|
||||
* The following table includes all memory regions for Armada 7k and
|
||||
* 8k SoCs. The Armada 7k is missing the CP110 slave regions here. Lets
|
||||
* define these regions at the beginning of the struct so that they
|
||||
* can be easier removed later dynamically if an Armada 7k device is detected.
|
||||
* For a detailed memory map, please see doc/mvebu/armada-8k-memory.txt
|
||||
*/
|
||||
#define ARMADA_7K8K_COMMON_REGIONS_START 2
|
||||
static struct mm_region mvebu_mem_map[] = {
|
||||
/* Armada 80x0 memory regions include the CP1 (slave) units */
|
||||
{
|
||||
/* SRAM, MMIO regions - CP110 slave region */
|
||||
.phys = 0xf4000000UL,
|
||||
.virt = 0xf4000000UL,
|
||||
.size = 0x02000000UL, /* 32MiB internal registers */
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE
|
||||
},
|
||||
{
|
||||
/* PCI CP1 regions */
|
||||
.phys = 0xfa000000UL,
|
||||
.virt = 0xfa000000UL,
|
||||
.size = 0x04000000UL, /* 64MiB CP110 slave PCI space */
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE
|
||||
},
|
||||
/* Armada 80x0 and 70x0 common memory regions start here */
|
||||
{
|
||||
/* RAM */
|
||||
.phys = 0x0UL,
|
||||
.virt = 0x0UL,
|
||||
.size = 0x80000000UL,
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
|
||||
PTE_BLOCK_INNER_SHARE
|
||||
},
|
||||
{
|
||||
/* SRAM, MMIO regions - AP806 region */
|
||||
.phys = 0xf0000000UL,
|
||||
.virt = 0xf0000000UL,
|
||||
.size = 0x01000000UL, /* 16MiB internal registers */
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE
|
||||
},
|
||||
{
|
||||
/* SRAM, MMIO regions - CP110 master region */
|
||||
.phys = 0xf2000000UL,
|
||||
.virt = 0xf2000000UL,
|
||||
.size = 0x02000000UL, /* 32MiB internal registers */
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE
|
||||
},
|
||||
{
|
||||
/* PCI CP0 regions */
|
||||
.phys = 0xf6000000UL,
|
||||
.virt = 0xf6000000UL,
|
||||
.size = 0x04000000UL, /* 64MiB CP110 master PCI space */
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE
|
||||
},
|
||||
{
|
||||
0,
|
||||
}
|
||||
};
|
||||
|
||||
struct mm_region *mem_map = mvebu_mem_map;
|
||||
|
||||
void enable_caches(void)
|
||||
{
|
||||
/*
|
||||
* Armada 7k is not equipped with the CP110 slave CP. In case this
|
||||
* code runs on an Armada 7k device, lets remove the CP110 slave
|
||||
* entries from the memory mapping by moving the start to the
|
||||
* common regions.
|
||||
*/
|
||||
if (of_machine_is_compatible("marvell,armada7040"))
|
||||
mem_map = &mvebu_mem_map[ARMADA_7K8K_COMMON_REGIONS_START];
|
||||
|
||||
icache_enable();
|
||||
dcache_enable();
|
||||
}
|
||||
|
||||
void reset_cpu(ulong ignored)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = readl(RFU_GLOBAL_SW_RST);
|
||||
reg &= ~(1 << RFU_SW_RESET_OFFSET);
|
||||
writel(reg, RFU_GLOBAL_SW_RST);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO - implement this functionality using platform
|
||||
* clock driver once it gets available
|
||||
* Return NAND clock in Hz
|
||||
*/
|
||||
u32 mvebu_get_nand_clock(void)
|
||||
{
|
||||
unsigned long NAND_FLASH_CLK_CTRL = 0xF2440700UL;
|
||||
unsigned long NF_CLOCK_SEL_MASK = 0x1;
|
||||
u32 reg;
|
||||
|
||||
reg = readl(NAND_FLASH_CLK_CTRL);
|
||||
if (reg & NF_CLOCK_SEL_MASK)
|
||||
return 400 * 1000000;
|
||||
else
|
||||
return 250 * 1000000;
|
||||
}
|
||||
|
||||
int mmc_get_env_dev(void)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int boot_mode;
|
||||
|
||||
reg = readl(SAR0_REG);
|
||||
boot_mode = (reg >> BOOT_MODE_OFFSET) & BOOT_MODE_MASK;
|
||||
|
||||
switch (boot_mode) {
|
||||
case 0x28:
|
||||
case 0x2a:
|
||||
return 0;
|
||||
case 0x29:
|
||||
case 0x2b:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return CONFIG_SYS_MMC_ENV_DEV;
|
||||
}
|
||||
@@ -0,0 +1,685 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Stefan Roese <sr@denx.de>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <ahci.h>
|
||||
#include <cpu_func.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 },
|
||||
|
||||
#ifdef CONFIG_ARMADA_MSYS
|
||||
/* DFX */
|
||||
{ MBUS_DFX_BASE, MBUS_DFX_SIZE, CPU_TARGET_DFX, 0 },
|
||||
#endif
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
case SOC_98DX3236_ID:
|
||||
case SOC_98DX3336_ID:
|
||||
case SOC_98DX4251_ID:
|
||||
return MVEBU_SOC_MSYS;
|
||||
}
|
||||
|
||||
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 },
|
||||
{ 0x10, 0x0, 1866, 933, 933 },
|
||||
{ 0x13, 0x0, 2000, 1000, 933 },
|
||||
{ 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */
|
||||
};
|
||||
#elif defined(CONFIG_ARMADA_MSYS)
|
||||
static const struct sar_freq_modes sar_freq_tab[] = {
|
||||
{ 0x0, 0x0, 400, 400, 400 },
|
||||
{ 0x2, 0x0, 667, 333, 667 },
|
||||
{ 0x3, 0x0, 800, 400, 800 },
|
||||
{ 0x5, 0x0, 800, 400, 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) || defined(CONFIG_ARMADA_MSYS)
|
||||
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) || defined(CONFIG_ARMADA_MSYS)
|
||||
*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;
|
||||
case SOC_98DX3236_ID:
|
||||
puts("98DX3236-");
|
||||
break;
|
||||
case SOC_98DX3336_ID:
|
||||
puts("98DX3336-");
|
||||
break;
|
||||
case SOC_98DX4251_ID:
|
||||
puts("98DX4251-");
|
||||
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;
|
||||
case MV_88F68XX_B0_ID:
|
||||
puts("B0");
|
||||
break;
|
||||
default:
|
||||
printf("?? (%x)", revid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mvebu_soc_family() == MVEBU_SOC_MSYS) {
|
||||
switch (revid) {
|
||||
case 3:
|
||||
puts("A0");
|
||||
break;
|
||||
case 4:
|
||||
puts("A1");
|
||||
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 SPL before the
|
||||
* main payload (U-Boot) is executed.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (mvebu_soc_family() == MVEBU_SOC_A38X)
|
||||
reg = MVEBU_DFX_DIV_CLK_CTRL(1);
|
||||
else if (mvebu_soc_family() == MVEBU_SOC_MSYS)
|
||||
reg = MVEBU_DFX_DIV_CLK_CTRL(8);
|
||||
else
|
||||
reg = MVEBU_CORE_DIV_CLK_CTRL(1);
|
||||
|
||||
return CONFIG_SYS_MVEBU_PLL_CLOCK /
|
||||
((readl(reg) &
|
||||
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 */
|
||||
|
||||
#if defined(CONFIG_MMC_SDHCI_MV) && !defined(CONFIG_DM_MMC)
|
||||
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
|
||||
|
||||
#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;
|
||||
|
||||
/* mbus is not initialized in SPL; keep the ROM settings */
|
||||
if (IS_ENABLED(CONFIG_SPL_BUILD))
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int board_ahci_enable(void)
|
||||
{
|
||||
ahci_mvebu_mbus_config((void __iomem *)MVEBU_SATA0_BASE);
|
||||
ahci_mvebu_regret_option((void __iomem *)MVEBU_SATA0_BASE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSI_AHCI_PLAT
|
||||
void scsi_init(void)
|
||||
{
|
||||
printf("MVEBU SATA INIT\n");
|
||||
board_ahci_enable();
|
||||
ahci_init((void __iomem *)MVEBU_SATA0_BASE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_XHCI_MVEBU
|
||||
#define USB3_MAX_WINDOWS 4
|
||||
#define USB3_WIN_CTRL(w) (0x0 + ((w) * 8))
|
||||
#define USB3_WIN_BASE(w) (0x4 + ((w) * 8))
|
||||
|
||||
static void xhci_mvebu_mbus_config(void __iomem *base,
|
||||
const struct mbus_dram_target_info *dram)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < USB3_MAX_WINDOWS; i++) {
|
||||
writel(0, base + USB3_WIN_CTRL(i));
|
||||
writel(0, base + USB3_WIN_BASE(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < dram->num_cs; i++) {
|
||||
const struct mbus_dram_window *cs = dram->cs + i;
|
||||
|
||||
/* Write size, attributes and target id to control register */
|
||||
writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
|
||||
(dram->mbus_dram_target_id << 4) | 1,
|
||||
base + USB3_WIN_CTRL(i));
|
||||
|
||||
/* Write base address to base register */
|
||||
writel((cs->base & 0xffff0000), base + USB3_WIN_BASE(i));
|
||||
}
|
||||
}
|
||||
|
||||
int board_xhci_enable(fdt_addr_t base)
|
||||
{
|
||||
const struct mbus_dram_target_info *dram;
|
||||
|
||||
printf("MVEBU XHCI INIT controller @ 0x%lx\n", base);
|
||||
|
||||
dram = mvebu_mbus_dram_info();
|
||||
xhci_mvebu_mbus_config((void __iomem *)base, dram);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2009
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*/
|
||||
|
||||
#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)
|
||||
|
||||
#ifndef MVEBU_SDRAM_SIZE_MAX
|
||||
#define MVEBU_SDRAM_SIZE_MAX 0xc0000000
|
||||
#endif
|
||||
|
||||
#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);
|
||||
if (size == 0)
|
||||
continue;
|
||||
|
||||
total = (u64)size;
|
||||
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 - 1,
|
||||
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;
|
||||
}
|
||||
|
||||
/* Return the width of the DRAM bus, or 0 for unknown. */
|
||||
static int bus_width(void)
|
||||
{
|
||||
int full_width = 0;
|
||||
|
||||
if (reg_read(REG_SDRAM_CONFIG_ADDR) & (1 << REG_SDRAM_CONFIG_WIDTH_OFFS))
|
||||
full_width = 1;
|
||||
|
||||
switch (mvebu_soc_family()) {
|
||||
case MVEBU_SOC_AXP:
|
||||
return full_width ? 64 : 32;
|
||||
break;
|
||||
case MVEBU_SOC_A375:
|
||||
case MVEBU_SOC_A38X:
|
||||
case MVEBU_SOC_MSYS:
|
||||
return full_width ? 32 : 16;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int cycle_mode(void)
|
||||
{
|
||||
int val = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
|
||||
|
||||
return (val >> REG_DUNIT_CTRL_LOW_2T_OFFS) & REG_DUNIT_CTRL_LOW_2T_MASK;
|
||||
}
|
||||
|
||||
#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 > MVEBU_SDRAM_SIZE_MAX)
|
||||
size = MVEBU_SDRAM_SIZE_MAX;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
int 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 > MVEBU_SDRAM_SIZE_MAX)
|
||||
mvebu_sdram_bs_set(i, 0x40000000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_MVEBU)
|
||||
void board_add_ram_info(int use_default)
|
||||
{
|
||||
struct sar_freq_modes sar_freq;
|
||||
int mode;
|
||||
int width;
|
||||
|
||||
get_sar_freq(&sar_freq);
|
||||
printf(" (%d MHz, ", sar_freq.d_clk);
|
||||
|
||||
width = bus_width();
|
||||
if (width)
|
||||
printf("%d-bit, ", width);
|
||||
|
||||
mode = cycle_mode();
|
||||
/* Mode 0 = Single cycle
|
||||
* Mode 1 = Two cycles (2T)
|
||||
* Mode 2 = Three cycles (3T)
|
||||
*/
|
||||
if (mode == 1)
|
||||
printf("2T, ");
|
||||
if (mode == 2)
|
||||
printf("3T, ");
|
||||
|
||||
if (ecc_enabled())
|
||||
printf("ECC");
|
||||
else
|
||||
printf("ECC not");
|
||||
printf(" enabled)");
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,263 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Reinhard Pfau <reinhard.pfau@gdsys.cc>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/efuse.h>
|
||||
#include <asm/arch/soc.h>
|
||||
#include <linux/mbus.h>
|
||||
|
||||
#if defined(CONFIG_MVEBU_EFUSE_FAKE)
|
||||
#define DRY_RUN
|
||||
#else
|
||||
#undef DRY_RUN
|
||||
#endif
|
||||
|
||||
#define MBUS_EFUSE_BASE 0xF6000000
|
||||
#define MBUS_EFUSE_SIZE BIT(20)
|
||||
|
||||
#define MVEBU_EFUSE_CONTROL (MVEBU_REGISTER(0xE4008))
|
||||
|
||||
enum {
|
||||
MVEBU_EFUSE_CTRL_PROGRAM_ENABLE = (1 << 31),
|
||||
};
|
||||
|
||||
struct mvebu_hd_efuse {
|
||||
u32 bits_31_0;
|
||||
u32 bits_63_32;
|
||||
u32 bit64;
|
||||
u32 reserved0;
|
||||
};
|
||||
|
||||
#ifndef DRY_RUN
|
||||
static struct mvebu_hd_efuse *efuses =
|
||||
(struct mvebu_hd_efuse *)(MBUS_EFUSE_BASE + 0xF9000);
|
||||
#else
|
||||
static struct mvebu_hd_efuse efuses[EFUSE_LINE_MAX + 1];
|
||||
#endif
|
||||
|
||||
static int efuse_initialised;
|
||||
|
||||
static struct mvebu_hd_efuse *get_efuse_line(int nr)
|
||||
{
|
||||
if (nr < 0 || nr > 63 || !efuse_initialised)
|
||||
return NULL;
|
||||
|
||||
return efuses + nr;
|
||||
}
|
||||
|
||||
static void enable_efuse_program(void)
|
||||
{
|
||||
#ifndef DRY_RUN
|
||||
setbits_le32(MVEBU_EFUSE_CONTROL, MVEBU_EFUSE_CTRL_PROGRAM_ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void disable_efuse_program(void)
|
||||
{
|
||||
#ifndef DRY_RUN
|
||||
clrbits_le32(MVEBU_EFUSE_CONTROL, MVEBU_EFUSE_CTRL_PROGRAM_ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int do_prog_efuse(struct mvebu_hd_efuse *efuse,
|
||||
struct efuse_val *new_val, u32 mask0, u32 mask1)
|
||||
{
|
||||
struct efuse_val val;
|
||||
|
||||
val.dwords.d[0] = readl(&efuse->bits_31_0);
|
||||
val.dwords.d[1] = readl(&efuse->bits_63_32);
|
||||
val.lock = readl(&efuse->bit64);
|
||||
|
||||
if (val.lock & 1)
|
||||
return -EPERM;
|
||||
|
||||
val.dwords.d[0] |= (new_val->dwords.d[0] & mask0);
|
||||
val.dwords.d[1] |= (new_val->dwords.d[1] & mask1);
|
||||
val.lock |= new_val->lock;
|
||||
|
||||
writel(val.dwords.d[0], &efuse->bits_31_0);
|
||||
mdelay(1);
|
||||
writel(val.dwords.d[1], &efuse->bits_63_32);
|
||||
mdelay(1);
|
||||
writel(val.lock, &efuse->bit64);
|
||||
mdelay(5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prog_efuse(int nr, struct efuse_val *new_val, u32 mask0, u32 mask1)
|
||||
{
|
||||
struct mvebu_hd_efuse *efuse;
|
||||
int res = 0;
|
||||
|
||||
res = mvebu_efuse_init_hw();
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
efuse = get_efuse_line(nr);
|
||||
if (!efuse)
|
||||
return -ENODEV;
|
||||
|
||||
if (!new_val)
|
||||
return -EINVAL;
|
||||
|
||||
/* only write a fuse line with lock bit */
|
||||
if (!new_val->lock)
|
||||
return -EINVAL;
|
||||
|
||||
/* according to specs ECC protection bits must be 0 on write */
|
||||
if (new_val->bytes.d[7] & 0xFE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!new_val->dwords.d[0] && !new_val->dwords.d[1] && (mask0 | mask1))
|
||||
return 0;
|
||||
|
||||
enable_efuse_program();
|
||||
|
||||
res = do_prog_efuse(efuse, new_val, mask0, mask1);
|
||||
|
||||
disable_efuse_program();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int mvebu_efuse_init_hw(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (efuse_initialised)
|
||||
return 0;
|
||||
|
||||
ret = mvebu_mbus_add_window_by_id(
|
||||
CPU_TARGET_SATA23_DFX, 0xA, MBUS_EFUSE_BASE, MBUS_EFUSE_SIZE);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
efuse_initialised = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mvebu_read_efuse(int nr, struct efuse_val *val)
|
||||
{
|
||||
struct mvebu_hd_efuse *efuse;
|
||||
int res;
|
||||
|
||||
res = mvebu_efuse_init_hw();
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
efuse = get_efuse_line(nr);
|
||||
if (!efuse)
|
||||
return -ENODEV;
|
||||
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
val->dwords.d[0] = readl(&efuse->bits_31_0);
|
||||
val->dwords.d[1] = readl(&efuse->bits_63_32);
|
||||
val->lock = readl(&efuse->bit64);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mvebu_write_efuse(int nr, struct efuse_val *val)
|
||||
{
|
||||
return prog_efuse(nr, val, ~0, ~0);
|
||||
}
|
||||
|
||||
int mvebu_lock_efuse(int nr)
|
||||
{
|
||||
struct efuse_val val = {
|
||||
.lock = 1,
|
||||
};
|
||||
|
||||
return prog_efuse(nr, &val, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* wrapper funcs providing the fuse API
|
||||
*
|
||||
* we use the following mapping:
|
||||
* "bank" -> eFuse line
|
||||
* "word" -> 0: bits 0-31
|
||||
* 1: bits 32-63
|
||||
* 2: bit 64 (lock)
|
||||
*/
|
||||
|
||||
static struct efuse_val prog_val;
|
||||
static int valid_prog_words;
|
||||
|
||||
int fuse_read(u32 bank, u32 word, u32 *val)
|
||||
{
|
||||
struct efuse_val fuse_line;
|
||||
int res;
|
||||
|
||||
if (bank < EFUSE_LINE_MIN || bank > EFUSE_LINE_MAX || word > 2)
|
||||
return -EINVAL;
|
||||
|
||||
res = mvebu_read_efuse(bank, &fuse_line);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
if (word < 2)
|
||||
*val = fuse_line.dwords.d[word];
|
||||
else
|
||||
*val = fuse_line.lock;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_sense(u32 bank, u32 word, u32 *val)
|
||||
{
|
||||
/* not supported */
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int fuse_prog(u32 bank, u32 word, u32 val)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
/*
|
||||
* NOTE: Fuse line should be written as whole.
|
||||
* So how can we do that with this API?
|
||||
* For now: remember values for word == 0 and word == 1 and write the
|
||||
* whole line when word == 2.
|
||||
* This implies that we always require all 3 fuse prog cmds (one for
|
||||
* for each word) to write a single fuse line.
|
||||
* Exception is a single write to word 2 which will lock the fuse line.
|
||||
*
|
||||
* Hope that will be OK.
|
||||
*/
|
||||
|
||||
if (bank < EFUSE_LINE_MIN || bank > EFUSE_LINE_MAX || word > 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (word < 2) {
|
||||
prog_val.dwords.d[word] = val;
|
||||
valid_prog_words |= (1 << word);
|
||||
} else if ((valid_prog_words & 3) == 0 && val) {
|
||||
res = mvebu_lock_efuse(bank);
|
||||
valid_prog_words = 0;
|
||||
} else if ((valid_prog_words & 3) != 3 || !val) {
|
||||
res = -EINVAL;
|
||||
} else {
|
||||
prog_val.lock = val != 0;
|
||||
res = mvebu_write_efuse(bank, &prog_val);
|
||||
valid_prog_words = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_override(u32 bank, u32 word, u32 val)
|
||||
{
|
||||
/* not supported */
|
||||
return -ENOSYS;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2009
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2011
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Lei Wen <leiwen@marvell.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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) || defined(CONFIG_ARMADA_MSYS)
|
||||
/*
|
||||
* 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_L2_PL310
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
#define CONFIG_SKIP_LOWLEVEL_INIT /* disable board lowlevel_init */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* By default the generated mvebu kwbimage.cfg 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 arch/arm/mach-mvebu/kwbimage.cfg
|
||||
#endif /* CONFIG_SYS_KWD_CONFIG */
|
||||
|
||||
/* end of 16M scrubbed by training in bootrom */
|
||||
#define CONFIG_SYS_INIT_SP_ADDR 0x00FF0000
|
||||
|
||||
#define MV_UART_CONSOLE_BASE MVEBU_UART0_BASE
|
||||
|
||||
/* Needed for SPI NOR booting in SPL */
|
||||
#define CONFIG_DM_SEQ_ALIAS 1
|
||||
|
||||
/*
|
||||
* Ethernet Driver configuration
|
||||
*/
|
||||
#ifdef CONFIG_CMD_NET
|
||||
#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */
|
||||
#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 */
|
||||
@@ -0,0 +1,181 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2009
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*/
|
||||
|
||||
#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_DFX = 0x8,
|
||||
CPU_TARGET_SASRAM = 0x9,
|
||||
CPU_TARGET_SATA01 = 0xa, /* A38X */
|
||||
CPU_TARGET_NAND = 0xd,
|
||||
CPU_TARGET_SATA23_DFX = 0xe, /* A38X */
|
||||
};
|
||||
|
||||
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_MSYS,
|
||||
MVEBU_SOC_UNKNOWN,
|
||||
};
|
||||
|
||||
#define MVEBU_SDRAM_SIZE_MAX 0xc0000000
|
||||
|
||||
/*
|
||||
* Default Device Address MAP BAR values
|
||||
*/
|
||||
#define MBUS_PCI_MEM_BASE MVEBU_SDRAM_SIZE_MAX
|
||||
#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_DFX_BASE 0xF6000000
|
||||
#define MBUS_DFX_SIZE (1 << 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);
|
||||
|
||||
#ifndef CONFIG_DM_MMC
|
||||
int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks);
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
/* Auto Voltage Scaling */
|
||||
#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X)
|
||||
void mv_avs_init(void);
|
||||
#else
|
||||
static inline void mv_avs_init(void) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* get_ref_clk
|
||||
*
|
||||
* return: reference clock in MHz (25 or 40)
|
||||
*/
|
||||
u32 get_ref_clk(void);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _MVEBU_CPU_H */
|
||||
@@ -0,0 +1,68 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2015 Reinhard Pfau <reinhard.pfau@gdsys.cc>
|
||||
*/
|
||||
|
||||
#ifndef _MVEBU_EFUSE_H
|
||||
#define _MVEBU_EFUSE_H
|
||||
|
||||
#include <common.h>
|
||||
|
||||
struct efuse_val {
|
||||
union {
|
||||
struct {
|
||||
u8 d[8];
|
||||
} bytes;
|
||||
struct {
|
||||
u16 d[4];
|
||||
} words;
|
||||
struct {
|
||||
u32 d[2];
|
||||
} dwords;
|
||||
};
|
||||
u32 lock;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_ARMADA_38X)
|
||||
|
||||
enum efuse_line {
|
||||
EFUSE_LINE_SECURE_BOOT = 24,
|
||||
EFUSE_LINE_PUBKEY_DIGEST_0 = 26,
|
||||
EFUSE_LINE_PUBKEY_DIGEST_1 = 27,
|
||||
EFUSE_LINE_PUBKEY_DIGEST_2 = 28,
|
||||
EFUSE_LINE_PUBKEY_DIGEST_3 = 29,
|
||||
EFUSE_LINE_PUBKEY_DIGEST_4 = 30,
|
||||
EFUSE_LINE_CSK_0_VALID = 31,
|
||||
EFUSE_LINE_CSK_1_VALID = 32,
|
||||
EFUSE_LINE_CSK_2_VALID = 33,
|
||||
EFUSE_LINE_CSK_3_VALID = 34,
|
||||
EFUSE_LINE_CSK_4_VALID = 35,
|
||||
EFUSE_LINE_CSK_5_VALID = 36,
|
||||
EFUSE_LINE_CSK_6_VALID = 37,
|
||||
EFUSE_LINE_CSK_7_VALID = 38,
|
||||
EFUSE_LINE_CSK_8_VALID = 39,
|
||||
EFUSE_LINE_CSK_9_VALID = 40,
|
||||
EFUSE_LINE_CSK_10_VALID = 41,
|
||||
EFUSE_LINE_CSK_11_VALID = 42,
|
||||
EFUSE_LINE_CSK_12_VALID = 43,
|
||||
EFUSE_LINE_CSK_13_VALID = 44,
|
||||
EFUSE_LINE_CSK_14_VALID = 45,
|
||||
EFUSE_LINE_CSK_15_VALID = 46,
|
||||
EFUSE_LINE_FLASH_ID = 47,
|
||||
EFUSE_LINE_BOX_ID = 48,
|
||||
|
||||
EFUSE_LINE_MIN = 0,
|
||||
EFUSE_LINE_MAX = 63,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int mvebu_efuse_init_hw(void);
|
||||
|
||||
int mvebu_read_efuse(int nr, struct efuse_val *val);
|
||||
|
||||
int mvebu_write_efuse(int nr, struct efuse_val *val);
|
||||
|
||||
int mvebu_lock_efuse(int nr);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
#ifndef __MACH_MVEBU_GPIO_H
|
||||
#define __MACH_MVEBU_GPIO_H
|
||||
|
||||
/* Empty file - sdhci requires this. */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,206 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2009
|
||||
* Marvell Semiconductor <www.marvell.com>
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*
|
||||
* Header file for the Marvell's Feroceon CPU core.
|
||||
*/
|
||||
|
||||
#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
|
||||
#define SOC_98DX3236_ID 0xf410
|
||||
#define SOC_98DX3336_ID 0xf400
|
||||
#define SOC_98DX4251_ID 0xfc00
|
||||
|
||||
/* A375 revisions */
|
||||
#define MV_88F67XX_A0_ID 0x3
|
||||
|
||||
/* A38x revisions */
|
||||
#define MV_88F68XX_Z1_ID 0x0
|
||||
#define MV_88F68XX_A0_ID 0x4
|
||||
#define MV_88F68XX_B0_ID 0xa
|
||||
|
||||
/* TCLK Core Clock definition */
|
||||
#ifndef CONFIG_SYS_TCLK
|
||||
#define CONFIG_SYS_TCLK 250000000 /* 250MHz */
|
||||
#endif
|
||||
|
||||
/* SOC specific definations */
|
||||
#define INTREG_BASE 0xd0000000
|
||||
#define INTREG_BASE_ADDR_REG (INTREG_BASE + 0x20080)
|
||||
#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_ARMADA_3700)
|
||||
/*
|
||||
* 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
|
||||
#elif defined(CONFIG_ARMADA_8K)
|
||||
#define SOC_REGS_PHY_BASE 0xf0000000
|
||||
#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_REG_PCIE0_BASE (MVEBU_REGISTER(0x80000))
|
||||
#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))
|
||||
#ifdef CONFIG_ARMADA_MSYS
|
||||
#define MVEBU_DFX_BASE (MBUS_DFX_BASE)
|
||||
#else
|
||||
#define MVEBU_DFX_BASE (MVEBU_REGISTER(0xe4000))
|
||||
#endif
|
||||
|
||||
#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))
|
||||
#ifdef CONFIG_ARMADA_MSYS
|
||||
#define MVEBU_DFX_DIV_CLK_CTRL(i) (MVEBU_DFX_BASE + 0xf8000 + 0x250 + ((i) * 0x4))
|
||||
#define NAND_ECC_DIVCKL_RATIO_OFFS 6
|
||||
#define NAND_ECC_DIVCKL_RATIO_MASK (0xF << NAND_ECC_DIVCKL_RATIO_OFFS)
|
||||
#else
|
||||
#define MVEBU_DFX_DIV_CLK_CTRL(i) (MVEBU_DFX_BASE + 0x250 + ((i) * 0x4))
|
||||
#endif
|
||||
#ifdef CONFIG_ARMADA_MSYS
|
||||
#define NAND_ECC_DIVCKL_RATIO_OFFS 6
|
||||
#define NAND_ECC_DIVCKL_RATIO_MASK (0xF << NAND_ECC_DIVCKL_RATIO_OFFS)
|
||||
#else
|
||||
#define NAND_ECC_DIVCKL_RATIO_OFFS 8
|
||||
#define NAND_ECC_DIVCKL_RATIO_MASK (0x3F << NAND_ECC_DIVCKL_RATIO_OFFS)
|
||||
#endif
|
||||
|
||||
#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
|
||||
#define BOOTROM_ERR_CODE_OFFS 0
|
||||
#define BOOTROM_ERR_CODE_MASK (0xf << BOOTROM_ERR_CODE_OFFS)
|
||||
|
||||
#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_NAND 0x0A
|
||||
#define BOOT_FROM_SATA 0x22
|
||||
#define BOOT_FROM_UART 0x28
|
||||
#define BOOT_FROM_SATA_ALT 0x2A
|
||||
#define BOOT_FROM_UART_ALT 0x3f
|
||||
#define BOOT_FROM_SPI 0x32
|
||||
#define BOOT_FROM_MMC 0x30
|
||||
#define BOOT_FROM_MMC_ALT 0x31
|
||||
#elif defined(CONFIG_ARMADA_MSYS)
|
||||
/* SAR values for MSYS */
|
||||
#define CONFIG_SAR_REG (MBUS_DFX_BASE + 0xf8200)
|
||||
#define CONFIG_SAR2_REG (MBUS_DFX_BASE + 0xf8204)
|
||||
|
||||
#define SAR_CPU_FREQ_OFFS 18
|
||||
#define SAR_CPU_FREQ_MASK (0x7 << SAR_CPU_FREQ_OFFS)
|
||||
#define SAR_BOOT_DEVICE_OFFS 11
|
||||
#define SAR_BOOT_DEVICE_MASK (0x7 << SAR_BOOT_DEVICE_OFFS)
|
||||
|
||||
#define BOOT_DEV_SEL_OFFS 11
|
||||
#define BOOT_DEV_SEL_MASK (0x7 << BOOT_DEV_SEL_OFFS)
|
||||
|
||||
#define BOOT_FROM_NAND 0x1
|
||||
#define BOOT_FROM_UART 0x2
|
||||
#define BOOT_FROM_SPI 0x3
|
||||
#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 */
|
||||
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Copyright (C) 2014 Stefan Roese <sr@denx.de>
|
||||
#
|
||||
|
||||
# Armada 38x uses version 1 image format
|
||||
VERSION 1
|
||||
|
||||
# Boot Media configurations
|
||||
#@BOOT_FROM
|
||||
|
||||
# Binary Header (bin_hdr) with DDR3 training code
|
||||
BINARY spl/u-boot-spl.bin 0000005b 00000068
|
||||
@@ -0,0 +1,69 @@
|
||||
/* 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
|
||||
@@ -0,0 +1,529 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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 <linux/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;
|
||||
|
||||
#if defined(CONFIG_ARMADA_MSYS)
|
||||
/* Disable MBUS Err Prop - in order to avoid data aborts */
|
||||
clrbits_le32(mbus->mbuswins_base + 0x200, BIT(8));
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_KIRKWOOD
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_KIRKWOOD
|
||||
/*
|
||||
* 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);
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# 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
|
||||
@@ -0,0 +1,353 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
__weak void board_pex_config(void)
|
||||
{
|
||||
/* nothing in this weak default implementation */
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
board_pex_config();
|
||||
|
||||
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 capabilities\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;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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
|
||||
#define PEX_CFG_DIRECT_ACCESS(if, reg) (PEX_IF_REGS_BASE(if) + (reg))
|
||||
|
||||
/* 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);
|
||||
|
||||
void board_pex_config(void);
|
||||
|
||||
#endif
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
+2201
File diff suppressed because it is too large
Load Diff
+250
@@ -0,0 +1,250 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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 */
|
||||
@@ -0,0 +1,168 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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*/
|
||||
@@ -0,0 +1,284 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
#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_TARGET_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_env_device_rev_get - Get Marvell controller device revision number
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* This function returns 8bit describing the device revision as defined
|
||||
* Revision ID Register.
|
||||
*
|
||||
* INPUT:
|
||||
* None.
|
||||
*
|
||||
* OUTPUT:
|
||||
* None.
|
||||
*
|
||||
* RETURN:
|
||||
* 8bit desscribing Marvell controller revision number
|
||||
*/
|
||||
u8 sys_env_device_rev_get(void)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
value = reg_read(DEV_VERSION_ID_REG);
|
||||
return (value & (REVISON_ID_MASK)) >> REVISON_ID_OFFS;
|
||||
}
|
||||
|
||||
void mv_avs_init(void)
|
||||
{
|
||||
u32 sar_freq;
|
||||
|
||||
if (!(IS_ENABLED(CONFIG_ARMADA_38X) || IS_ENABLED(CONFIG_ARMADA_39X)))
|
||||
return;
|
||||
|
||||
reg_write(AVS_DEBUG_CNTR_REG, AVS_DEBUG_CNTR_DEFAULT_VALUE);
|
||||
reg_write(AVS_DEBUG_CNTR_REG, AVS_DEBUG_CNTR_DEFAULT_VALUE);
|
||||
|
||||
sar_freq = reg_read(DEVICE_SAMPLE_AT_RESET1_REG);
|
||||
sar_freq = sar_freq >> SAR_FREQ_OFFSET & SAR_FREQ_MASK;
|
||||
|
||||
/* Set AVS value only for core frequency of 1600MHz or less.
|
||||
* For higher frequency leave the default value.
|
||||
*/
|
||||
if (sar_freq <= 0xd) {
|
||||
u32 avs_reg_data = reg_read(AVS_ENABLED_CONTROL);
|
||||
|
||||
avs_reg_data &= ~(AVS_LOW_VDD_LIMIT_MASK
|
||||
| AVS_HIGH_VDD_LIMIT_MASK);
|
||||
avs_reg_data |= AVS_LOW_VDD_SLOW_VAL | AVS_HIGH_VDD_SLOW_VAL;
|
||||
reg_write(AVS_ENABLED_CONTROL, avs_reg_data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#ifndef _SYS_ENV_LIB_H
|
||||
#define _SYS_ENV_LIB_H
|
||||
|
||||
#include "../../../drivers/ddr/marvell/a38x/ddr3_init.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_FREQ_OFFSET 10
|
||||
#define SAR_FREQ_MASK 0x1f
|
||||
#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_CFG0_REG 0xa0600
|
||||
#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_LOW_VDD_SLOW_VAL (0x23 << 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)
|
||||
#define AVS_HIGH_VDD_SLOW_VAL (0x23 << 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
|
||||
#define MV_88F68XX_B0_ID 0xa
|
||||
/* 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 */
|
||||
@@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
obj-$(CONFIG_SPL_BUILD) = high_speed_env_lib.o
|
||||
obj-$(CONFIG_SPL_BUILD) += high_speed_env_spec.o
|
||||
@@ -0,0 +1,261 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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 */
|
||||
+1610
File diff suppressed because it is too large
Load Diff
+183
@@ -0,0 +1,183 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
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 };
|
||||
@@ -0,0 +1,86 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
*/
|
||||
|
||||
#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 */
|
||||
@@ -0,0 +1,153 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Stefan Roese <sr@denx.de>
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
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;
|
||||
|
||||
#ifdef CONFIG_ARMADA_38X
|
||||
/*
|
||||
* If the bootrom error code contains any other than zeros it's an
|
||||
* error condition and the bootROM has fallen back to UART boot
|
||||
*/
|
||||
boot_device = (val & BOOTROM_ERR_CODE_MASK) >> BOOTROM_ERR_CODE_OFFS;
|
||||
if (boot_device)
|
||||
return BOOT_DEVICE_UART;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
#if defined(CONFIG_ARMADA_38X)
|
||||
case BOOT_FROM_NAND:
|
||||
return BOOT_DEVICE_NAND;
|
||||
#endif
|
||||
#ifdef CONFIG_SPL_MMC_SUPPORT
|
||||
case BOOT_FROM_MMC:
|
||||
case BOOT_FROM_MMC_ALT:
|
||||
return BOOT_DEVICE_MMC1;
|
||||
#endif
|
||||
case BOOT_FROM_UART:
|
||||
#ifdef BOOT_FROM_UART_ALT
|
||||
case BOOT_FROM_UART_ALT:
|
||||
#endif
|
||||
return BOOT_DEVICE_UART;
|
||||
#ifdef BOOT_FROM_SATA
|
||||
case BOOT_FROM_SATA:
|
||||
case BOOT_FROM_SATA_ALT:
|
||||
return BOOT_DEVICE_SATA;
|
||||
#endif
|
||||
case BOOT_FROM_SPI:
|
||||
default:
|
||||
return BOOT_DEVICE_SPI;
|
||||
};
|
||||
}
|
||||
|
||||
u32 spl_boot_device(void)
|
||||
{
|
||||
return get_boot_device();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Use special translation offset for SPL. This needs to be
|
||||
* configured *before* spl_init() is called as this function
|
||||
* calls dm_init() which calls the bind functions of the
|
||||
* device drivers. Here the base address needs to be configured
|
||||
* (translated) correctly.
|
||||
*/
|
||||
gd->translation_offset = 0xd0000000 - 0xf1000000;
|
||||
|
||||
ret = spl_init();
|
||||
if (ret) {
|
||||
debug("spl_init() failed: %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
/* Initialize Auto Voltage Scaling */
|
||||
mv_avs_init();
|
||||
|
||||
/*
|
||||
* 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 booting from NAND lets let the BootROM load the
|
||||
* rest of the bootloader.
|
||||
*/
|
||||
switch (get_boot_device()) {
|
||||
case BOOT_DEVICE_UART:
|
||||
#if defined(CONFIG_ARMADA_38X)
|
||||
case BOOT_DEVICE_NAND:
|
||||
#endif
|
||||
return_to_bootrom();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) Marvell International Ltd. and its affiliates
|
||||
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
||||
*
|
||||
* Copyright (C) 2015 Stefan Roese <sr@denx.de>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/soc.h>
|
||||
|
||||
#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