GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+247
@@ -0,0 +1,247 @@
|
||||
#
|
||||
# Copyright (C) 2018-2021 Marvell International Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# https://spdx.org/licenses
|
||||
#
|
||||
|
||||
MARVELL_PLAT_BASE := plat/marvell/armada
|
||||
MARVELL_PLAT_INCLUDE_BASE := include/plat/marvell/armada
|
||||
PLAT_FAMILY := a3k
|
||||
PLAT_FAMILY_BASE := $(MARVELL_PLAT_BASE)/$(PLAT_FAMILY)
|
||||
PLAT_INCLUDE_BASE := $(MARVELL_PLAT_INCLUDE_BASE)/$(PLAT_FAMILY)
|
||||
PLAT_COMMON_BASE := $(PLAT_FAMILY_BASE)/common
|
||||
MARVELL_DRV_BASE := drivers/marvell
|
||||
MARVELL_COMMON_BASE := $(MARVELL_PLAT_BASE)/common
|
||||
ERRATA_A53_1530924 := 1
|
||||
|
||||
include plat/marvell/marvell.mk
|
||||
|
||||
#*********** A3700 *************
|
||||
|
||||
# GICV3
|
||||
$(eval $(call add_define,CONFIG_GICV3))
|
||||
|
||||
# CCI-400
|
||||
$(eval $(call add_define,USE_CCI))
|
||||
|
||||
# Include GICv3 driver files
|
||||
include drivers/arm/gic/v3/gicv3.mk
|
||||
|
||||
MARVELL_GIC_SOURCES := ${GICV3_SOURCES} \
|
||||
plat/common/plat_gicv3.c
|
||||
|
||||
PLAT_INCLUDES := -I$(PLAT_FAMILY_BASE)/$(PLAT) \
|
||||
-I$(PLAT_COMMON_BASE)/include \
|
||||
-I$(PLAT_INCLUDE_BASE)/common \
|
||||
-I$(MARVELL_DRV_BASE) \
|
||||
-I$/drivers/arm/gic/common/
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := $(PLAT_COMMON_BASE)/aarch64/a3700_common.c \
|
||||
$(PLAT_COMMON_BASE)/aarch64/a3700_clock.S \
|
||||
$(MARVELL_DRV_BASE)/uart/a3700_console.S
|
||||
|
||||
BL1_SOURCES += $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
|
||||
lib/cpus/aarch64/cortex_a53.S
|
||||
|
||||
MARVELL_DRV := $(MARVELL_DRV_BASE)/comphy/phy-comphy-3700.c
|
||||
|
||||
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
|
||||
$(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
|
||||
$(PLAT_COMMON_BASE)/plat_cci.c \
|
||||
$(PLAT_COMMON_BASE)/plat_pm.c \
|
||||
$(PLAT_COMMON_BASE)/dram_win.c \
|
||||
$(PLAT_COMMON_BASE)/io_addr_dec.c \
|
||||
$(PLAT_COMMON_BASE)/marvell_plat_config.c \
|
||||
$(PLAT_FAMILY_BASE)/$(PLAT)/plat_bl31_setup.c \
|
||||
$(MARVELL_COMMON_BASE)/marvell_cci.c \
|
||||
$(MARVELL_COMMON_BASE)/marvell_ddr_info.c \
|
||||
$(MARVELL_COMMON_BASE)/marvell_gicv3.c \
|
||||
$(MARVELL_GIC_SOURCES) \
|
||||
drivers/arm/cci/cci.c \
|
||||
$(PLAT_COMMON_BASE)/a3700_sip_svc.c \
|
||||
$(MARVELL_DRV)
|
||||
|
||||
ifeq ($(HANDLE_EA_EL3_FIRST_NS),1)
|
||||
BL31_SOURCES += $(PLAT_COMMON_BASE)/a3700_ea.c
|
||||
endif
|
||||
|
||||
ifeq ($(CM3_SYSTEM_RESET),1)
|
||||
BL31_SOURCES += $(PLAT_COMMON_BASE)/cm3_system_reset.c
|
||||
endif
|
||||
|
||||
ifeq ($(A3720_DB_PM_WAKEUP_SRC),1)
|
||||
BL31_SOURCES += $(PLAT_FAMILY_BASE)/$(PLAT)/board/pm_src.c
|
||||
endif
|
||||
|
||||
ifdef WTP
|
||||
|
||||
# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
|
||||
$(if $(wildcard $(value WTP)/*),,$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' directory does not exist"))
|
||||
$(if $(shell git -C $(value WTP) rev-parse --show-cdup 2>&1),$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' does not contain valid A3700-utils-marvell git repository"))
|
||||
|
||||
TBB := $(WTP)/wtptp/src/TBB_Linux/release/TBB_linux
|
||||
|
||||
BUILD_UART := uart-images
|
||||
UART_IMAGE := $(BUILD_UART).tgz.bin
|
||||
|
||||
ifeq ($(MARVELL_SECURE_BOOT),1)
|
||||
TIM_CFG := $(BUILD_PLAT)/atf-tim.txt
|
||||
TIM_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-tim.txt
|
||||
IMAGESPATH := $(WTP)/tim/trusted
|
||||
TIMN_CFG := $(BUILD_PLAT)/atf-timN.txt
|
||||
TIMN_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-timN.txt
|
||||
TIMN_SIG := $(IMAGESPATH)/timnsign.txt
|
||||
TIM2IMGARGS := -i $(TIM_CFG) -n $(TIMN_CFG)
|
||||
TIMN_UART_IMAGE := $$(grep "Image Filename:" -m 1 $(TIMN_UART_CFG) | cut -c 17-)
|
||||
else #MARVELL_SECURE_BOOT
|
||||
TIM_CFG := $(BUILD_PLAT)/atf-ntim.txt
|
||||
TIM_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-ntim.txt
|
||||
IMAGESPATH := $(WTP)/tim/untrusted
|
||||
TIM2IMGARGS := -i $(TIM_CFG)
|
||||
endif #MARVELL_SECURE_BOOT
|
||||
|
||||
TIM_UART_IMAGE := $$(grep "Image Filename:" -m 1 $(TIM_UART_CFG) | cut -c 17-)
|
||||
|
||||
TIMBUILD := $(WTP)/script/buildtim.sh
|
||||
TIM2IMG := $(WTP)/script/tim2img.pl
|
||||
TIMDDRTOOL := $(WTP)/tim/ddr/ddr_tool
|
||||
|
||||
$(TIMBUILD): $(TIMDDRTOOL)
|
||||
|
||||
# WTMI_IMG is used to specify the customized RTOS image running over
|
||||
# Service CPU (CM3 processor). By the default, it points to a
|
||||
# baremetal binary of fuse programming in A3700_utils.
|
||||
WTMI_IMG := $(WTP)/wtmi/fuse/build/fuse.bin
|
||||
|
||||
# WTMI_MULTI_IMG is composed of CM3 RTOS image (WTMI_IMG)
|
||||
# and sys-init image.
|
||||
WTMI_MULTI_IMG := $(WTP)/wtmi/build/wtmi.bin
|
||||
|
||||
WTMI_ENC_IMG := wtmi-enc.bin
|
||||
|
||||
SRCPATH := $(dir $(BL33))
|
||||
|
||||
CLOCKSPRESET ?= CPU_800_DDR_800
|
||||
|
||||
DDR_TOPOLOGY ?= 0
|
||||
|
||||
BOOTDEV ?= SPINOR
|
||||
PARTNUM ?= 0
|
||||
|
||||
TIMBLDARGS := $(MARVELL_SECURE_BOOT) $(BOOTDEV) $(IMAGESPATH) $(WTP) $(CLOCKSPRESET) \
|
||||
$(DDR_TOPOLOGY) $(PARTNUM) $(DEBUG) $(TIM_CFG) $(TIMN_CFG) $(TIMN_SIG) 1
|
||||
TIMBLDUARTARGS := $(MARVELL_SECURE_BOOT) UART $(IMAGESPATH) $(WTP) $(CLOCKSPRESET) \
|
||||
$(DDR_TOPOLOGY) 0 0 $(TIM_UART_CFG) $(TIMN_UART_CFG) $(TIMN_SIG) 0
|
||||
|
||||
UART_IMAGES := $(BUILD_UART)/$(TIM_UART_IMAGE)
|
||||
ifeq ($(MARVELL_SECURE_BOOT),1)
|
||||
UART_IMAGES += $(BUILD_UART)/$(TIMN_UART_IMAGE)
|
||||
endif
|
||||
UART_IMAGES += $(BUILD_UART)/wtmi_h.bin $(BUILD_UART)/boot-image_h.bin
|
||||
|
||||
CRYPTOPP_LIBDIR ?= $(CRYPTOPP_PATH)
|
||||
CRYPTOPP_INCDIR ?= $(CRYPTOPP_PATH)
|
||||
|
||||
$(TBB): FORCE
|
||||
# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
|
||||
$(if $(CRYPTOPP_LIBDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_LIBDIR. Please set CRYPTOPP_PATH or CRYPTOPP_LIBDIR to point to the right directory"))
|
||||
$(if $(CRYPTOPP_INCDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_INCDIR. Please set CRYPTOPP_PATH or CRYPTOPP_INCDIR to point to the right directory"))
|
||||
$(if $(wildcard $(CRYPTOPP_LIBDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_LIB' was set to '$(CRYPTOPP_LIBDIR)', but '$(CRYPTOPP_LIBDIR)' does not exist"))
|
||||
$(if $(wildcard $(CRYPTOPP_INCDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_INCDIR' was set to '$(CRYPTOPP_INCDIR)', but '$(CRYPTOPP_INCDIR)' does not exist"))
|
||||
ifdef CRYPTOPP_PATH
|
||||
$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile
|
||||
endif
|
||||
$(Q)$(MAKE) --no-print-directory -C $(WTP)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_LIBDIR) INCDIR=$(CRYPTOPP_INCDIR)
|
||||
|
||||
$(WTMI_MULTI_IMG): FORCE
|
||||
$(Q)$(MAKE) --no-print-directory -C $(WTP) WTMI_IMG=$(WTMI_IMG) DDR_TOPOLOGY=$(DDR_TOPOLOGY) CLOCKSPRESET=$(CLOCKSPRESET) WTMI
|
||||
|
||||
$(BUILD_PLAT)/wtmi.bin: $(WTMI_MULTI_IMG)
|
||||
$(Q)cp -a $(WTMI_MULTI_IMG) $(BUILD_PLAT)/wtmi.bin
|
||||
|
||||
$(TIMDDRTOOL): FORCE
|
||||
# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
|
||||
$(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for ddr tool requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
|
||||
$(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
|
||||
$(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
|
||||
$(Q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) DDR_TOPOLOGY=$(DDR_TOPOLOGY) mv_ddr
|
||||
|
||||
$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL)
|
||||
@$(ECHO_BLANK_LINE)
|
||||
@echo "Building uart images"
|
||||
$(Q)mkdir -p $(BUILD_PLAT)/$(BUILD_UART)
|
||||
$(Q)cp -a $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/$(BUILD_UART)/wtmi.bin
|
||||
$(Q)cp -a $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/$(BUILD_UART)/$(BOOT_IMAGE)
|
||||
$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TIMBUILD) $(TIMBLDUARTARGS)
|
||||
$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIM_UART_CFG)
|
||||
$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIM_UART_CFG)
|
||||
ifeq ($(MARVELL_SECURE_BOOT),1)
|
||||
$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMN_UART_CFG)
|
||||
$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMN_UART_CFG)
|
||||
endif
|
||||
$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TBB) -r $(TIM_UART_CFG) -v -D
|
||||
ifeq ($(MARVELL_SECURE_BOOT),1)
|
||||
$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TBB) -r $(TIMN_UART_CFG)
|
||||
endif
|
||||
$(Q)tar czf $(BUILD_PLAT)/$(UART_IMAGE) -C $(BUILD_PLAT) $(UART_IMAGES)
|
||||
@$(ECHO_BLANK_LINE)
|
||||
@echo "Built $@ successfully"
|
||||
@$(ECHO_BLANK_LINE)
|
||||
|
||||
$(BUILD_PLAT)/$(FLASH_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL) $(TIM2IMG)
|
||||
@$(ECHO_BLANK_LINE)
|
||||
@echo "Building flash image"
|
||||
$(Q)cd $(BUILD_PLAT) && $(TIMBUILD) $(TIMBLDARGS)
|
||||
$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIM_CFG)
|
||||
$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIM_CFG)
|
||||
ifeq ($(MARVELL_SECURE_BOOT),1)
|
||||
$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMN_CFG)
|
||||
$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMN_CFG)
|
||||
@$(ECHO_BLANK_LINE)
|
||||
@echo "=======================================================";
|
||||
@echo " Secure boot. Encrypting wtmi and boot-image";
|
||||
@echo "=======================================================";
|
||||
@$(ECHO_BLANK_LINE)
|
||||
$(Q)cp $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/wtmi-align.bin
|
||||
$(Q)truncate -s %16 $(BUILD_PLAT)/wtmi-align.bin
|
||||
$(Q)${OPENSSL_BIN_PATH}/openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/wtmi-align.bin \
|
||||
-out $(BUILD_PLAT)/$(WTMI_ENC_IMG) \
|
||||
-K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \
|
||||
-iv `cat $(IMAGESPATH)/iv.txt` -p
|
||||
$(Q)truncate -s %16 $(BUILD_PLAT)/$(BOOT_IMAGE);
|
||||
$(Q)${OPENSSL_BIN_PATH}/openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/$(BOOT_IMAGE) \
|
||||
-out $(BUILD_PLAT)/$(BOOT_ENC_IMAGE) \
|
||||
-K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \
|
||||
-iv `cat $(IMAGESPATH)/iv.txt` -p
|
||||
endif
|
||||
$(Q)cd $(BUILD_PLAT) && $(TBB) -r $(TIM_CFG) -v -D
|
||||
ifeq ($(MARVELL_SECURE_BOOT),1)
|
||||
$(Q)cd $(BUILD_PLAT) && $(TBB) -r $(TIMN_CFG)
|
||||
$(Q)sed -i 's|wtmi.bin|$(WTMI_ENC_IMG)|1' $(TIMN_CFG)
|
||||
$(Q)sed -i 's|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1' $(TIMN_CFG)
|
||||
endif
|
||||
$(Q)cd $(BUILD_PLAT) && $(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE)
|
||||
@$(ECHO_BLANK_LINE)
|
||||
@echo "Built $@ successfully"
|
||||
@$(ECHO_BLANK_LINE)
|
||||
|
||||
clean realclean distclean: mrvl_clean
|
||||
|
||||
.PHONY: mrvl_clean
|
||||
mrvl_clean:
|
||||
-$(Q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) clean
|
||||
-$(Q)$(MAKE) --no-print-directory -C $(WTP)/wtptp/src/TBB_Linux -f TBB_linux.mak clean
|
||||
ifdef CRYPTOPP_PATH
|
||||
-$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile clean
|
||||
endif
|
||||
|
||||
else # WTP
|
||||
|
||||
$(BUILD_PLAT)/$(UART_IMAGE) $(BUILD_PLAT)/$(FLASH_IMAGE):
|
||||
$(error "Platform '${PLAT}' for target '$@' requires WTP. Please set WTP to point to the right directory")
|
||||
|
||||
endif # WTP
|
||||
|
||||
.PHONY: mrvl_uart
|
||||
mrvl_uart: $(BUILD_PLAT)/$(UART_IMAGE)
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Repk repk@triplefau.lt
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <bl31/ea_handle.h>
|
||||
|
||||
#define A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS 0xbf000002
|
||||
|
||||
/*
|
||||
* This source file with custom plat_ea_handler function is compiled only when
|
||||
* building TF-A with compile option HANDLE_EA_EL3_FIRST_NS=1
|
||||
*/
|
||||
void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
|
||||
void *handle, uint64_t flags)
|
||||
{
|
||||
unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
|
||||
|
||||
/*
|
||||
* Asynchronous External Abort with syndrome 0xbf000002 on Cortex A53
|
||||
* core means SError interrupt caused by AXI SLVERR on external access.
|
||||
*
|
||||
* In most cases this indicates a bug in U-Boot or Linux kernel driver
|
||||
* pci-aardvark.c which implements access to A3700 PCIe config space.
|
||||
* Driver does not wait for PCIe PIO transfer completion and try to
|
||||
* start a new PCIe PIO transfer while previous has not finished yet.
|
||||
* A3700 PCIe controller in this case sends SLVERR via AXI which results
|
||||
* in a fatal Asynchronous SError interrupt on Cortex A53 CPU.
|
||||
*
|
||||
* Following patches fix that bug in U-Boot and Linux kernel drivers:
|
||||
* https://source.denx.de/u-boot/u-boot/-/commit/eccbd4ad8e4e182638eafbfb87ac139c04f24a01
|
||||
* https://git.kernel.org/stable/c/f18139966d072dab8e4398c95ce955a9742e04f7
|
||||
*
|
||||
* As a hacky workaround for unpatched U-Boot and Linux kernel drivers
|
||||
* ignore all asynchronous aborts with that syndrome value received on
|
||||
* CPU from level lower than EL3.
|
||||
*
|
||||
* Because these aborts are delivered on CPU asynchronously, they are
|
||||
* imprecise and we cannot check the real reason of abort and neither
|
||||
* who and why sent this abort. We expect that on A3700 it is always
|
||||
* PCIe controller.
|
||||
*
|
||||
* Hence ignoring all aborts with this syndrome value is just a giant
|
||||
* hack that we need only because of bugs in old U-Boot and Linux kernel
|
||||
* versions and because it was decided that TF-A would implement this
|
||||
* hack for U-Boot and Linux kernel it in this way. New patched U-Boot
|
||||
* and kernel versions do not need it anymore.
|
||||
*
|
||||
* Links to discussion about this workaround:
|
||||
* https://lore.kernel.org/linux-pci/20190316161243.29517-1-repk@triplefau.lt/
|
||||
* https://lore.kernel.org/linux-pci/971be151d24312cc533989a64bd454b4@www.loen.fr/
|
||||
* https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/1541
|
||||
*/
|
||||
if (level < MODE_EL3 && ea_reason == ERROR_EA_ASYNC &&
|
||||
syndrome == A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS) {
|
||||
ERROR_NL();
|
||||
ERROR("Ignoring Asynchronous External Abort with"
|
||||
" syndrome 0x%" PRIx64 " received on 0x%lx from %s\n",
|
||||
syndrome, read_mpidr_el1(), get_el_str(level));
|
||||
ERROR("SError interrupt: AXI SLVERR on external access\n");
|
||||
ERROR("This indicates a bug in pci-aardvark.c driver\n");
|
||||
ERROR("Please update U-Boot/Linux to the latest version\n");
|
||||
ERROR_NL();
|
||||
console_flush();
|
||||
return;
|
||||
}
|
||||
|
||||
plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/runtime_svc.h>
|
||||
#include <lib/smccc.h>
|
||||
|
||||
#include <marvell_plat_priv.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
#include "comphy/phy-comphy-3700.h"
|
||||
|
||||
/* Comphy related FID's */
|
||||
#define MV_SIP_COMPHY_POWER_ON 0x82000001
|
||||
#define MV_SIP_COMPHY_POWER_OFF 0x82000002
|
||||
#define MV_SIP_COMPHY_PLL_LOCK 0x82000003
|
||||
|
||||
/* Miscellaneous FID's' */
|
||||
#define MV_SIP_DRAM_SIZE 0x82000010
|
||||
|
||||
/* This macro is used to identify COMPHY related calls from SMC function ID */
|
||||
#define is_comphy_fid(fid) \
|
||||
((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_PLL_LOCK)
|
||||
|
||||
uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
|
||||
u_register_t x1,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
u_register_t flags)
|
||||
{
|
||||
u_register_t ret;
|
||||
|
||||
VERBOSE("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx\n",
|
||||
__func__, smc_fid, x1, x2);
|
||||
if (is_comphy_fid(smc_fid)) {
|
||||
if (x1 >= MAX_LANE_NR) {
|
||||
ERROR("%s: Wrong smc (0x%x) lane nr: %lx\n",
|
||||
__func__, smc_fid, x2);
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
}
|
||||
}
|
||||
|
||||
switch (smc_fid) {
|
||||
/* Comphy related FID's */
|
||||
case MV_SIP_COMPHY_POWER_ON:
|
||||
/* x1: comphy_index, x2: comphy_mode */
|
||||
ret = mvebu_3700_comphy_power_on(x1, x2);
|
||||
SMC_RET1(handle, ret);
|
||||
case MV_SIP_COMPHY_POWER_OFF:
|
||||
/* x1: comphy_index, x2: comphy_mode */
|
||||
ret = mvebu_3700_comphy_power_off(x1, x2);
|
||||
SMC_RET1(handle, ret);
|
||||
case MV_SIP_COMPHY_PLL_LOCK:
|
||||
/* x1: comphy_index, x2: comphy_mode */
|
||||
ret = mvebu_3700_comphy_is_pll_locked(x1, x2);
|
||||
SMC_RET1(handle, ret);
|
||||
/* Miscellaneous FID's' */
|
||||
case MV_SIP_DRAM_SIZE:
|
||||
/* x1: ap_base_addr */
|
||||
ret = mvebu_get_dram_size(MVEBU_REGS_BASE);
|
||||
SMC_RET1(handle, ret);
|
||||
|
||||
default:
|
||||
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Define a runtime service descriptor for fast SMC calls */
|
||||
DECLARE_RT_SVC(
|
||||
marvell_sip_svc,
|
||||
OEN_SIP_START,
|
||||
OEN_SIP_END,
|
||||
SMC_TYPE_FAST,
|
||||
NULL,
|
||||
mrvl_sip_smc_handler
|
||||
);
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* Below address in used only for reading, therefore no problem with concurrent
|
||||
* Linux access.
|
||||
*/
|
||||
#define MVEBU_TEST_PIN_LATCH_N (MVEBU_NB_GPIO_REG_BASE + 0x8)
|
||||
#define MVEBU_XTAL_MODE_MASK BIT(9)
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* uint32_t get_ref_clk (void);
|
||||
*
|
||||
* returns reference clock in MHz (25 or 40)
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
.globl get_ref_clk
|
||||
func get_ref_clk
|
||||
mov_imm x0, MVEBU_TEST_PIN_LATCH_N
|
||||
ldr w0, [x0]
|
||||
tst w0, #MVEBU_XTAL_MODE_MASK
|
||||
bne 40
|
||||
mov w0, #25
|
||||
ret
|
||||
40:
|
||||
mov w0, #40
|
||||
ret
|
||||
endfunc get_ref_clk
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
#include <plat_marvell.h>
|
||||
|
||||
/* MMU entry for internal (register) space access */
|
||||
#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
|
||||
DEVICE0_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
/*
|
||||
* Table of regions for various BL stages to map using the MMU.
|
||||
*/
|
||||
#if IMAGE_BL1
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MARVELL_MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#if IMAGE_BL2
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MARVELL_MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
MARVELL_MAP_DRAM,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#if IMAGE_BL2U
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MAP_DEVICE0,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#if IMAGE_BL31
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MARVELL_MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
MARVELL_MAP_DRAM,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#if IMAGE_BL32
|
||||
const mmap_region_t plat_marvell_mmap[] = {
|
||||
MAP_DEVICE0,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
MARVELL_CASSERT_MMAP;
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* This function performs any platform specific actions
|
||||
* needed for a secondary cpu after a cold reset. Right
|
||||
* now this is a stub function.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
mov x0, #0
|
||||
ret
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned long plat_get_my_entrypoint (void);
|
||||
*
|
||||
* Main job of this routine is to distinguish between cold and warm boot
|
||||
* For a cold boot, return 0.
|
||||
* For a warm boot, read the mailbox and return the address it contains.
|
||||
* A magic number is placed before entrypoint to avoid mistake caused by
|
||||
* uninitialized mailbox data area.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
/* Read first word and compare it with magic num */
|
||||
mov_imm x0, PLAT_MARVELL_MAILBOX_BASE
|
||||
ldr x1, [x0]
|
||||
mov_imm x2, PLAT_MARVELL_MAILBOX_MAGIC_NUM
|
||||
cmp x1, x2
|
||||
/* If compare failed, return 0, i.e. cold boot */
|
||||
beq entrypoint
|
||||
mov x0, #0
|
||||
ret
|
||||
entrypoint:
|
||||
/* Second word contains the jump address */
|
||||
add x0, x0, #8
|
||||
ldr x0, [x0]
|
||||
ret
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
|
||||
cmp x0, #MVEBU_PRIMARY_CPU
|
||||
cset w0, eq
|
||||
ret
|
||||
endfunc plat_is_my_cpu_primary
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Marek Behun, CZ.NIC
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mvebu_def.h>
|
||||
|
||||
/* Cortex-M3 Secure Processor Mailbox Registers */
|
||||
#define MVEBU_RWTM_PARAM0_REG (MVEBU_RWTM_REG_BASE)
|
||||
#define MVEBU_RWTM_CMD_REG (MVEBU_RWTM_REG_BASE + 0x40)
|
||||
#define MVEBU_RWTM_HOST_INT_RESET_REG (MVEBU_RWTM_REG_BASE + 0xC8)
|
||||
#define MVEBU_RWTM_HOST_INT_MASK_REG (MVEBU_RWTM_REG_BASE + 0xCC)
|
||||
#define MVEBU_RWTM_HOST_INT_SP_COMPLETE BIT(0)
|
||||
|
||||
#define MVEBU_RWTM_REBOOT_CMD 0x0009
|
||||
#define MVEBU_RWTM_REBOOT_MAGIC 0xDEADBEEF
|
||||
|
||||
static inline bool rwtm_completed(void)
|
||||
{
|
||||
return (mmio_read_32(MVEBU_RWTM_HOST_INT_RESET_REG) &
|
||||
MVEBU_RWTM_HOST_INT_SP_COMPLETE) != 0;
|
||||
}
|
||||
|
||||
static bool rwtm_wait(int ms)
|
||||
{
|
||||
while (ms && !rwtm_completed()) {
|
||||
mdelay(1);
|
||||
--ms;
|
||||
}
|
||||
|
||||
return rwtm_completed();
|
||||
}
|
||||
|
||||
void cm3_system_reset(void)
|
||||
{
|
||||
int tries = 5;
|
||||
|
||||
for (; tries > 0; --tries) {
|
||||
mmio_clrbits_32(MVEBU_RWTM_HOST_INT_RESET_REG,
|
||||
MVEBU_RWTM_HOST_INT_SP_COMPLETE);
|
||||
|
||||
mmio_write_32(MVEBU_RWTM_PARAM0_REG, MVEBU_RWTM_REBOOT_MAGIC);
|
||||
mmio_write_32(MVEBU_RWTM_CMD_REG, MVEBU_RWTM_REBOOT_CMD);
|
||||
|
||||
if (rwtm_wait(10)) {
|
||||
break;
|
||||
}
|
||||
|
||||
mdelay(100);
|
||||
}
|
||||
|
||||
/* If we reach here, the command is not implemented. */
|
||||
WARN("System reset command not implemented in WTMI firmware!\n");
|
||||
}
|
||||
+282
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <dram_win.h>
|
||||
#include <marvell_plat_priv.h>
|
||||
#include <mvebu.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
/* Armada 3700 has 5 configurable windows */
|
||||
#define MV_CPU_WIN_NUM 5
|
||||
|
||||
#define CPU_WIN_DISABLED 0
|
||||
#define CPU_WIN_ENABLED 1
|
||||
|
||||
/*
|
||||
* There are 2 different cpu decode window configuration cases:
|
||||
* - DRAM size is not over 2GB;
|
||||
* - DRAM size is 4GB.
|
||||
*/
|
||||
enum cpu_win_config_num {
|
||||
CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB = 0,
|
||||
CPU_WIN_CONFIG_DRAM_4GB,
|
||||
CPU_WIN_CONFIG_MAX
|
||||
};
|
||||
|
||||
enum cpu_win_target {
|
||||
CPU_WIN_TARGET_DRAM = 0,
|
||||
CPU_WIN_TARGET_INTERNAL_REG,
|
||||
CPU_WIN_TARGET_PCIE,
|
||||
CPU_WIN_TARGET_PCIE_OVER_MCI,
|
||||
CPU_WIN_TARGET_BOOT_ROM,
|
||||
CPU_WIN_TARGET_MCI_EXTERNAL,
|
||||
CPU_WIN_TARGET_RWTM_RAM = 7,
|
||||
CPU_WIN_TARGET_CCI400_REG
|
||||
};
|
||||
|
||||
struct cpu_win_configuration {
|
||||
uint32_t enabled;
|
||||
enum cpu_win_target target;
|
||||
uint64_t base_addr;
|
||||
uint64_t size;
|
||||
uint64_t remap_addr;
|
||||
};
|
||||
|
||||
struct cpu_win_configuration mv_cpu_wins[CPU_WIN_CONFIG_MAX][MV_CPU_WIN_NUM] = {
|
||||
/*
|
||||
* When total dram size is not over 2GB:
|
||||
* DDR window 0 is configured in tim header, its size may be not 512MB,
|
||||
* but the actual dram size, no need to configure it again;
|
||||
* other cpu windows are kept as default.
|
||||
*/
|
||||
{
|
||||
/* enabled
|
||||
* target
|
||||
* base
|
||||
* size
|
||||
* remap
|
||||
*/
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_DRAM,
|
||||
0x0,
|
||||
0x08000000,
|
||||
0x0},
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_MCI_EXTERNAL,
|
||||
0xe0000000,
|
||||
0x08000000,
|
||||
0xe0000000},
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_PCIE,
|
||||
0xe8000000,
|
||||
0x08000000,
|
||||
0xe8000000},
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_RWTM_RAM,
|
||||
0xf0000000,
|
||||
0x00020000,
|
||||
0x1fff0000},
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_PCIE_OVER_MCI,
|
||||
0x80000000,
|
||||
0x10000000,
|
||||
0x80000000},
|
||||
},
|
||||
|
||||
/*
|
||||
* If total DRAM size is more than 2GB, now there is only one case:
|
||||
* 4GB of DRAM; to better utilize address space (for maximization of
|
||||
* DRAM usage), we will use the configuration of CPU windows below:
|
||||
* - Internal Regs and Boot ROM windows are kept as default;
|
||||
* - CCI-400 is moved from its default address to another address
|
||||
* (this is actually done even if DRAM size is not more than 2 GB,
|
||||
* because the firmware is compiled with that address as a
|
||||
* constant);
|
||||
* - PCIe window is moved to another address;
|
||||
* - Use 4 CPU decode windows for DRAM, which cover 3.75GB DRAM;
|
||||
* DDR window 0 is configured in tim header with 2G B size, no need
|
||||
* to configure it again here;
|
||||
*
|
||||
* 0xFFFFFFFF ---> +-----------------------+
|
||||
* | Boot ROM | 1 MB
|
||||
* | AP Boot ROM - 16 KB: |
|
||||
* | 0xFFFF0000-0xFFFF4000 |
|
||||
* 0xFFF00000 ---> +-----------------------+
|
||||
* : :
|
||||
* 0xFE010000 ---> +-----------------------+
|
||||
* | CCI Regs | 64 KB
|
||||
* 0xFE000000 ---> +-----------------------+
|
||||
* : :
|
||||
* 0xFA000000 ---> +-----------------------+
|
||||
* | PCIE | 128 MB
|
||||
* 0xF2000000 ---> +-----------------------+
|
||||
* | DDR window 3 | 512 MB
|
||||
* 0xD2000000 ---> +-----------------------+
|
||||
* | Internal Regs | 32 MB
|
||||
* 0xD0000000 ---> |-----------------------|
|
||||
* | DDR window 2 | 256 MB
|
||||
* 0xC0000000 ---> |-----------------------|
|
||||
* | |
|
||||
* | DDR window 1 | 1 GB
|
||||
* | |
|
||||
* 0x80000000 ---> |-----------------------|
|
||||
* | |
|
||||
* | |
|
||||
* | DDR window 0 | 2 GB
|
||||
* | |
|
||||
* | |
|
||||
* 0x00000000 ---> +-----------------------+
|
||||
*/
|
||||
{
|
||||
/* win_id
|
||||
* target
|
||||
* base
|
||||
* size
|
||||
* remap
|
||||
*/
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_DRAM,
|
||||
0x0,
|
||||
0x80000000,
|
||||
0x0},
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_DRAM,
|
||||
0x80000000,
|
||||
0x40000000,
|
||||
0x80000000},
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_DRAM,
|
||||
0xc0000000,
|
||||
0x10000000,
|
||||
0xc0000000},
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_DRAM,
|
||||
0xd2000000,
|
||||
0x20000000,
|
||||
0xd2000000},
|
||||
{CPU_WIN_ENABLED,
|
||||
CPU_WIN_TARGET_PCIE,
|
||||
0xf2000000,
|
||||
0x08000000,
|
||||
0xf2000000},
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* dram_win_map_build
|
||||
*
|
||||
* This function builds cpu dram windows mapping
|
||||
* which includes base address and window size by
|
||||
* reading cpu dram decode windows registers.
|
||||
*
|
||||
* @input: N/A
|
||||
*
|
||||
* @output:
|
||||
* - win_map: cpu dram windows mapping
|
||||
*
|
||||
* @return: N/A
|
||||
*/
|
||||
void dram_win_map_build(struct dram_win_map *win_map)
|
||||
{
|
||||
int32_t win_id;
|
||||
struct dram_win *win;
|
||||
uint32_t base_reg, ctrl_reg, size_reg, enabled, target;
|
||||
|
||||
memset(win_map, 0, sizeof(struct dram_win_map));
|
||||
for (win_id = 0; win_id < DRAM_WIN_MAP_NUM_MAX; win_id++) {
|
||||
ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
|
||||
target = (ctrl_reg & CPU_DEC_CR_WIN_TARGET_MASK) >>
|
||||
CPU_DEC_CR_WIN_TARGET_OFFS;
|
||||
enabled = ctrl_reg & CPU_DEC_CR_WIN_ENABLE;
|
||||
/* Ignore invalid and non-dram windows*/
|
||||
if ((enabled == 0) || (target != DRAM_CPU_DEC_TARGET_NUM))
|
||||
continue;
|
||||
|
||||
win = win_map->dram_windows + win_map->dram_win_num;
|
||||
base_reg = mmio_read_32(CPU_DEC_WIN_BASE_REG(win_id));
|
||||
size_reg = mmio_read_32(CPU_DEC_WIN_SIZE_REG(win_id));
|
||||
/* Base reg [15:0] corresponds to transaction address [39:16] */
|
||||
win->base_addr = (base_reg & CPU_DEC_BR_BASE_MASK) >>
|
||||
CPU_DEC_BR_BASE_OFFS;
|
||||
win->base_addr *= CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
|
||||
/*
|
||||
* Size reg [15:0] is programmed from LSB to MSB as a sequence
|
||||
* of 1s followed by a sequence of 0s and the number of 1s
|
||||
* specifies the size of the window in 64 KB granularity,
|
||||
* for example, a value of 00FFh specifies 256 x 64 KB = 16 MB
|
||||
*/
|
||||
win->win_size = (size_reg & CPU_DEC_CR_WIN_SIZE_MASK) >>
|
||||
CPU_DEC_CR_WIN_SIZE_OFFS;
|
||||
win->win_size = (win->win_size + 1) *
|
||||
CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
|
||||
|
||||
win_map->dram_win_num++;
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_win_set(uint32_t win_id, struct cpu_win_configuration *win_cfg)
|
||||
{
|
||||
uint32_t base_reg, ctrl_reg, size_reg, remap_reg;
|
||||
|
||||
/* Disable window */
|
||||
ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
|
||||
ctrl_reg &= ~CPU_DEC_CR_WIN_ENABLE;
|
||||
mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
|
||||
|
||||
/* For an disabled window, only disable it. */
|
||||
if (!win_cfg->enabled)
|
||||
return;
|
||||
|
||||
/* Set Base Register */
|
||||
base_reg = (uint32_t)(win_cfg->base_addr /
|
||||
CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
|
||||
base_reg <<= CPU_DEC_BR_BASE_OFFS;
|
||||
base_reg &= CPU_DEC_BR_BASE_MASK;
|
||||
mmio_write_32(CPU_DEC_WIN_BASE_REG(win_id), base_reg);
|
||||
|
||||
/* Set Remap Register with the same value
|
||||
* as the <Base> field in Base Register
|
||||
*/
|
||||
remap_reg = (uint32_t)(win_cfg->remap_addr /
|
||||
CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
|
||||
remap_reg <<= CPU_DEC_RLR_REMAP_LOW_OFFS;
|
||||
remap_reg &= CPU_DEC_RLR_REMAP_LOW_MASK;
|
||||
mmio_write_32(CPU_DEC_REMAP_LOW_REG(win_id), remap_reg);
|
||||
|
||||
/* Set Size Register */
|
||||
size_reg = (win_cfg->size / CPU_DEC_CR_WIN_SIZE_ALIGNMENT) - 1;
|
||||
size_reg <<= CPU_DEC_CR_WIN_SIZE_OFFS;
|
||||
size_reg &= CPU_DEC_CR_WIN_SIZE_MASK;
|
||||
mmio_write_32(CPU_DEC_WIN_SIZE_REG(win_id), size_reg);
|
||||
|
||||
/* Set Control Register - set target id and enable window */
|
||||
ctrl_reg &= ~CPU_DEC_CR_WIN_TARGET_MASK;
|
||||
ctrl_reg |= (win_cfg->target << CPU_DEC_CR_WIN_TARGET_OFFS);
|
||||
ctrl_reg |= CPU_DEC_CR_WIN_ENABLE;
|
||||
mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
|
||||
}
|
||||
|
||||
void cpu_wins_init(void)
|
||||
{
|
||||
uint32_t cfg_idx, win_id;
|
||||
|
||||
if (mvebu_get_dram_size(MVEBU_REGS_BASE) <= _2GB_)
|
||||
cfg_idx = CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB;
|
||||
else
|
||||
cfg_idx = CPU_WIN_CONFIG_DRAM_4GB;
|
||||
|
||||
/* Window 0 is configured always for DRAM in tim header
|
||||
* already, no need to configure it again here
|
||||
*/
|
||||
for (win_id = 1; win_id < MV_CPU_WIN_NUM; win_id++)
|
||||
cpu_win_set(win_id, &mv_cpu_wins[cfg_idx][win_id]);
|
||||
}
|
||||
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef A3700_PLAT_DEF_H
|
||||
#define A3700_PLAT_DEF_H
|
||||
|
||||
#include <marvell_def.h>
|
||||
|
||||
|
||||
#define MVEBU_MAX_CPUS_PER_CLUSTER 2
|
||||
|
||||
#define MVEBU_PRIMARY_CPU 0x0
|
||||
|
||||
/*
|
||||
* The counter on A3700 is always fed from reference 25M clock (XTAL).
|
||||
* However minimal CPU counter prescaler is 2, so the counter
|
||||
* frequency will be divided by 2, the number is 12.5M
|
||||
*/
|
||||
#define COUNTER_FREQUENCY 12500000
|
||||
|
||||
#define MVEBU_REGS_BASE 0xD0000000
|
||||
|
||||
/*****************************************************************************
|
||||
* MVEBU memory map related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
/* Aggregate of all devices in the first GB */
|
||||
#define DEVICE0_BASE MVEBU_REGS_BASE
|
||||
#define DEVICE0_SIZE 0x10000000
|
||||
|
||||
/*****************************************************************************
|
||||
* GIC-500 & interrupt handling related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
/* Base MVEBU compatible GIC memory map */
|
||||
#define MVEBU_GICD_BASE 0x1D00000
|
||||
#define MVEBU_GICR_BASE 0x1D40000
|
||||
#define MVEBU_GICC_BASE 0x1D80000
|
||||
|
||||
/*
|
||||
* CCI-400 base address
|
||||
* This address is absolute, not relative to MVEBU_REGS_BASE.
|
||||
* This is not the default CCI base address (that would be 0xD8000000).
|
||||
* Rather we remap CCI to this address to better utilize the address space.
|
||||
* (The remapping is done in plat/marvell/armada/a3k/common/plat_cci.c)
|
||||
*/
|
||||
#define MVEBU_CCI_BASE 0xFE000000
|
||||
|
||||
/*****************************************************************************
|
||||
* North and south bridge reset registers
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_NB_RESET_REG (MVEBU_REGS_BASE + 0x12400)
|
||||
#define MVEBU_NB_RESET_I2C1_N (1 << 0)
|
||||
#define MVEBU_NB_RESET_1WIRE_N (1 << 1)
|
||||
#define MVEBU_NB_RESET_SPI_N (1 << 2)
|
||||
#define MVEBU_NB_RESET_UART_N (1 << 3)
|
||||
#define MVEBU_NB_RESET_XTL_N (1 << 4)
|
||||
#define MVEBU_NB_RESET_I2C2_N (1 << 5)
|
||||
#define MVEBU_NB_RESET_UART2_N (1 << 6)
|
||||
#define MVEBU_NB_RESET_AVS_N (1 << 7)
|
||||
#define MVEBU_NB_RESET_DDR_N (1 << 10)
|
||||
#define MVEBU_NB_RESET_SETM_N (1 << 11)
|
||||
#define MVEBU_NB_RESET_DMA_N (1 << 12)
|
||||
#define MVEBU_NB_RESET_TSECM_N (1 << 13)
|
||||
#define MVEBU_NB_RESET_SDIO_N (1 << 14)
|
||||
#define MVEBU_NB_RESET_SATA_N (1 << 15)
|
||||
#define MVEBU_NB_RESET_PWRMGT_N (1 << 16)
|
||||
#define MVEBU_NB_RESET_OTP_N (1 << 17)
|
||||
#define MVEBU_NB_RESET_EIP_N (1 << 18)
|
||||
#define MVEBU_SB_RESET_REG (MVEBU_REGS_BASE + 0x18600)
|
||||
#define MVEBU_SB_RESET_MCIPHY (1 << 1)
|
||||
#define MVEBU_SB_RESET_SDIO_N (1 << 2)
|
||||
#define MVEBU_SB_RESET_PCIE_N (1 << 3)
|
||||
#define MVEBU_SB_RESET_GBE1_N (1 << 4)
|
||||
#define MVEBU_SB_RESET_GBE0_N (1 << 5)
|
||||
#define MVEBU_SB_RESET_USB2PHY (1 << 6)
|
||||
#define MVEBU_SB_RESET_USB2HPHY (1 << 7)
|
||||
#define MVEBU_SB_RESET_MCI_N (1 << 8)
|
||||
#define MVEBU_SB_RESET_PWRMGT_N (1 << 9)
|
||||
#define MVEBU_SB_RESET_EBM_N (1 << 10)
|
||||
#define MVEBU_SB_RESET_OTP_N (1 << 11)
|
||||
|
||||
/*****************************************************************************
|
||||
* North and south bridge register base
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_NB_REGS_BASE (MVEBU_REGS_BASE + 0x13000)
|
||||
#define MVEBU_SB_REGS_BASE (MVEBU_REGS_BASE + 0x18000)
|
||||
|
||||
/*****************************************************************************
|
||||
* GPIO registers related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
/* North and south bridge GPIO register base address */
|
||||
#define MVEBU_NB_GPIO_REG_BASE (MVEBU_NB_REGS_BASE + 0x800)
|
||||
#define MVEBU_NB_GPIO_IRQ_REG_BASE (MVEBU_NB_REGS_BASE + 0xC00)
|
||||
#define MVEBU_SB_GPIO_REG_BASE (MVEBU_SB_REGS_BASE + 0x800)
|
||||
#define MVEBU_SB_GPIO_IRQ_REG_BASE (MVEBU_SB_REGS_BASE + 0xC00)
|
||||
#define MVEBU_NB_SB_IRQ_REG_BASE (MVEBU_REGS_BASE + 0x8A00)
|
||||
|
||||
/* North Bridge GPIO selection register */
|
||||
#define MVEBU_NB_GPIO_SEL_REG (MVEBU_NB_GPIO_REG_BASE + 0x30)
|
||||
#define MVEBU_NB_GPIO_OUTPUT_EN_HIGH_REG (MVEBU_NB_GPIO_REG_BASE + 0x04)
|
||||
/* I2C1 GPIO Enable bit offset */
|
||||
#define MVEBU_GPIO_TW1_GPIO_EN_OFF (10)
|
||||
/* SPI pins mode bit offset */
|
||||
#define MVEBU_GPIO_NB_SPI_PIN_MODE_OFF (28)
|
||||
|
||||
/*****************************************************************************
|
||||
* DRAM registers related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_DRAM_REG_BASE (MVEBU_REGS_BASE)
|
||||
|
||||
/*****************************************************************************
|
||||
* SB wake-up registers related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_SB_WAKEUP_REG_BASE (MVEBU_REGS_BASE + 0x19000)
|
||||
|
||||
/*****************************************************************************
|
||||
* PMSU registers related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_PMSU_REG_BASE (MVEBU_REGS_BASE + 0x14000)
|
||||
|
||||
/*****************************************************************************
|
||||
* North Bridge Step-Down Registers
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_NB_STEP_DOWN_REG_BASE (MVEBU_REGS_BASE + 0x12800)
|
||||
|
||||
/*****************************************************************************
|
||||
* DRAM CS memory map register base
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_CS_MMAP_REG_BASE (MVEBU_REGS_BASE + 0x200)
|
||||
|
||||
/*****************************************************************************
|
||||
* CPU decoder window registers related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_CPU_DEC_WIN_REG_BASE (MVEBU_REGS_BASE + 0xCF00)
|
||||
|
||||
/*****************************************************************************
|
||||
* AVS registers related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_AVS_REG_BASE (MVEBU_REGS_BASE + 0x11500)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* AVS registers related constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_COMPHY_REG_BASE (MVEBU_REGS_BASE + 0x18300)
|
||||
|
||||
/*****************************************************************************
|
||||
* Cortex-M3 Secure Processor Mailbox constants
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MVEBU_RWTM_REG_BASE (MVEBU_REGS_BASE + 0xB0000)
|
||||
|
||||
#endif /* A3700_PLAT_DEF_H */
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2020 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef A3700_PM_H
|
||||
#define A3700_PM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* supported wake up sources */
|
||||
enum pm_wake_up_src_type {
|
||||
WAKE_UP_SRC_GPIO,
|
||||
/* FOLLOWING SRC NOT SUPPORTED YET */
|
||||
WAKE_UP_SRC_TIMER,
|
||||
WAKE_UP_SRC_UART0,
|
||||
WAKE_UP_SRC_UART1,
|
||||
WAKE_UP_SRC_MAX,
|
||||
};
|
||||
|
||||
struct pm_gpio_data {
|
||||
/*
|
||||
* bank 0: North bridge GPIO
|
||||
* bank 1: South bridge GPIO
|
||||
*/
|
||||
uint32_t bank_num;
|
||||
uint32_t gpio_num;
|
||||
};
|
||||
|
||||
union pm_wake_up_src_data {
|
||||
struct pm_gpio_data gpio_data;
|
||||
/* delay in seconds */
|
||||
uint32_t timer_delay;
|
||||
};
|
||||
|
||||
struct pm_wake_up_src {
|
||||
enum pm_wake_up_src_type wake_up_src_type;
|
||||
|
||||
union pm_wake_up_src_data wake_up_data;
|
||||
};
|
||||
|
||||
struct pm_wake_up_src_config {
|
||||
uint32_t wake_up_src_num;
|
||||
struct pm_wake_up_src wake_up_src[WAKE_UP_SRC_MAX];
|
||||
};
|
||||
|
||||
struct pm_wake_up_src_config *mv_wake_up_src_config_get(void);
|
||||
|
||||
void cm3_system_reset(void);
|
||||
|
||||
#endif /* A3700_PM_H */
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef DDR_INFO_H
|
||||
#define DDR_INFO_H
|
||||
|
||||
#define DRAM_MAX_IFACE 1
|
||||
#define DRAM_CH0_MMAP_LOW_OFFSET 0x200
|
||||
|
||||
#endif /* DDR_INFO_H */
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef DRAM_WIN_H
|
||||
#define DRAM_WIN_H
|
||||
|
||||
#include <common/bl_common.h>
|
||||
|
||||
#include <io_addr_dec.h>
|
||||
|
||||
void dram_win_map_build(struct dram_win_map *win_map);
|
||||
void cpu_wins_init(void);
|
||||
|
||||
#endif /* DRAM_WIN_H */
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef IO_ADDR_DEC_H
|
||||
#define IO_ADDR_DEC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* There are 5 configurable cpu decoder windows. */
|
||||
#define DRAM_WIN_MAP_NUM_MAX 5
|
||||
/* Target number for dram in cpu decoder windows. */
|
||||
#define DRAM_CPU_DEC_TARGET_NUM 0
|
||||
|
||||
/*
|
||||
* Not all configurable decode windows could be used for dram, some units have
|
||||
* to reserve one decode window for other unit they have to communicate with;
|
||||
* for example, DMA engineer has 3 configurable windows, but only two could be
|
||||
* for dram while the last one has to be for pcie, so for DMA, its max_dram_win
|
||||
* is 2.
|
||||
*/
|
||||
struct dec_win_config {
|
||||
uint32_t dec_reg_base; /* IO address decoder register base address */
|
||||
uint32_t win_attr; /* IO address decoder windows attributes */
|
||||
/* How many configurable dram decoder windows that this unit has; */
|
||||
uint32_t max_dram_win;
|
||||
/* The decoder windows number including remapping that this unit has */
|
||||
uint32_t max_remap;
|
||||
/* The offset between continuous decode windows
|
||||
* within the same unit, typically 0x10
|
||||
*/
|
||||
uint32_t win_offset;
|
||||
};
|
||||
|
||||
struct dram_win {
|
||||
uintptr_t base_addr;
|
||||
uintptr_t win_size;
|
||||
};
|
||||
|
||||
struct dram_win_map {
|
||||
int dram_win_num;
|
||||
struct dram_win dram_windows[DRAM_WIN_MAP_NUM_MAX];
|
||||
};
|
||||
|
||||
/*
|
||||
* init_io_addr_dec
|
||||
*
|
||||
* This function initializes io address decoder windows by
|
||||
* cpu dram window mapping information
|
||||
*
|
||||
* @input: N/A
|
||||
* - dram_wins_map: cpu dram windows mapping
|
||||
* - io_dec_config: io address decoder windows configuration
|
||||
* - io_unit_num: io address decoder unit number
|
||||
* @output: N/A
|
||||
*
|
||||
* @return: 0 on success and others on failure
|
||||
*/
|
||||
int init_io_addr_dec(struct dram_win_map *dram_wins_map,
|
||||
struct dec_win_config *io_dec_config,
|
||||
uint32_t io_unit_num);
|
||||
|
||||
#endif /* IO_ADDR_DEC_H */
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef PLAT_MACROS_S
|
||||
#define PLAT_MACROS_S
|
||||
|
||||
#include <marvell_macros.S>
|
||||
|
||||
/* ---------------------------------------------
|
||||
* The below macro prints out relevant GIC and
|
||||
* CCI registers registers whenever an unhandled
|
||||
* exception is taken in BL31.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
mov_imm x17, MVEBU_GICC_BASE
|
||||
mov_imm x16, MVEBU_GICD_BASE
|
||||
marvell_print_gic_regs
|
||||
print_cci_regs
|
||||
.endm
|
||||
|
||||
#endif /* PLAT_MACROS_S */
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2021 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <stdio.h>
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#include <board_marvell_def.h>
|
||||
#include <mvebu_def.h>
|
||||
|
||||
/*
|
||||
* Most platform porting definitions provided by included headers
|
||||
*/
|
||||
|
||||
/*
|
||||
* DRAM Memory layout:
|
||||
* +-----------------------+
|
||||
* : :
|
||||
* : Linux :
|
||||
* 0x04X00000-->+-----------------------+
|
||||
* | BL3-3(u-boot) |>>}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
* |-----------------------| } |
|
||||
* | BL3-[0,1, 2] | }---------------------------------> |
|
||||
* |-----------------------| } || |
|
||||
* | BL2 | }->FIP (loaded by || |
|
||||
* |-----------------------| } BootROM to DRAM) || |
|
||||
* | FIP_TOC | } || |
|
||||
* 0x04120000-->|-----------------------| || |
|
||||
* | BL1 (RO) | || |
|
||||
* 0x04100000-->+-----------------------+ || |
|
||||
* : : || |
|
||||
* : Trusted SRAM section : \/ |
|
||||
* 0x04040000-->+-----------------------+ Replaced by BL2 +----------------+ |
|
||||
* | BL1 (RW) | <<<<<<<<<<<<<<<< | BL3-1 NOBITS | |
|
||||
* 0x04037000-->|-----------------------| <<<<<<<<<<<<<<<< |----------------| |
|
||||
* | | <<<<<<<<<<<<<<<< | BL3-1 PROGBITS | |
|
||||
* 0x04023000-->|-----------------------| +----------------+ |
|
||||
* | BL2 | |
|
||||
* |-----------------------| |
|
||||
* | | |
|
||||
* 0x04001000-->|-----------------------| |
|
||||
* | Shared | |
|
||||
* 0x04000000-->+-----------------------+ |
|
||||
* : : |
|
||||
* : Linux : |
|
||||
* : : |
|
||||
* |-----------------------| |
|
||||
* | | U-Boot(BL3-3) Loaded by BL2 |
|
||||
* | U-Boot | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
* 0x00000000-->+-----------------------+
|
||||
*
|
||||
* Trusted SRAM section 0x4000000..0x4200000:
|
||||
* ----------------------------------------
|
||||
* SRAM_BASE = 0x4001000
|
||||
* BL2_BASE = 0x4006000
|
||||
* BL2_LIMIT = BL31_BASE
|
||||
* BL31_BASE = 0x4023000 = (64MB + 256KB - 0x1D000)
|
||||
* BL31_PROGBITS_LIMIT = BL1_RW_BASE
|
||||
* BL1_RW_BASE = 0x4037000 = (64MB + 256KB - 0x9000)
|
||||
* BL1_RW_LIMIT = BL31_LIMIT = 0x4040000
|
||||
*
|
||||
*
|
||||
* PLAT_MARVELL_FIP_BASE = 0x4120000
|
||||
*/
|
||||
|
||||
/*
|
||||
* Since BL33 is loaded by BL2 (and validated by BL31) to DRAM offset 0,
|
||||
* it is allowed to load/copy images to 'NULL' pointers
|
||||
*/
|
||||
#if defined(IMAGE_BL2) || defined(IMAGE_BL31)
|
||||
#define PLAT_ALLOW_ZERO_ADDR_COPY
|
||||
#endif
|
||||
|
||||
#define PLAT_MARVELL_ATF_BASE 0x4000000
|
||||
#define PLAT_MARVELL_ATF_LOAD_ADDR \
|
||||
(PLAT_MARVELL_ATF_BASE + 0x100000)
|
||||
|
||||
#define PLAT_MARVELL_FIP_BASE \
|
||||
(PLAT_MARVELL_ATF_LOAD_ADDR + 0x20000)
|
||||
#define PLAT_MARVELL_FIP_MAX_SIZE 0x4000000
|
||||
|
||||
#define PLAT_MARVELL_CLUSTER_CORE_COUNT U(2)
|
||||
/* DRAM[2MB..66MB] is used as Trusted ROM */
|
||||
#define PLAT_MARVELL_TRUSTED_ROM_BASE PLAT_MARVELL_ATF_LOAD_ADDR
|
||||
/* 4 MB for FIP image */
|
||||
#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x00400000
|
||||
/* Reserve 12M for SCP (Secure PayLoad) Trusted RAM
|
||||
* OP-TEE SHMEM follows this region
|
||||
*/
|
||||
#define PLAT_MARVELL_TRUSTED_RAM_BASE 0x04400000
|
||||
#define PLAT_MARVELL_TRUSTED_RAM_SIZE 0x00C00000 /* 12 MB DRAM */
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
|
||||
* plus a little space for growth.
|
||||
*/
|
||||
#define PLAT_MARVELL_MAX_BL1_RW_SIZE 0xA000
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
|
||||
* little space for growth.
|
||||
*/
|
||||
#define PLAT_MARVELL_MAX_BL2_SIZE 0xF000
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
|
||||
* little space for growth.
|
||||
*/
|
||||
#define PLAT_MARVEL_MAX_BL31_SIZE 0x5D000
|
||||
|
||||
#define PLAT_MARVELL_CPU_ENTRY_ADDR BL1_RO_BASE
|
||||
|
||||
/* GIC related definitions */
|
||||
#define PLAT_MARVELL_GICD_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE)
|
||||
#define PLAT_MARVELL_GICR_BASE (MVEBU_REGS_BASE + MVEBU_GICR_BASE)
|
||||
#define PLAT_MARVELL_GICC_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE)
|
||||
|
||||
#define PLAT_MARVELL_G0_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL)
|
||||
|
||||
#define PLAT_MARVELL_G1S_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_PHY_TIMER, \
|
||||
GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
||||
GIC_INTR_CFG_LEVEL)
|
||||
|
||||
|
||||
#define PLAT_MARVELL_SHARED_RAM_CACHED 1
|
||||
|
||||
/* CCI related constants */
|
||||
#define PLAT_MARVELL_CCI_BASE MVEBU_CCI_BASE
|
||||
#define PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX 3
|
||||
#define PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX 4
|
||||
|
||||
/*
|
||||
* Load address of BL3-3 for this platform port
|
||||
*/
|
||||
#define PLAT_MARVELL_NS_IMAGE_OFFSET 0x0
|
||||
|
||||
/* System Reference Clock*/
|
||||
#define PLAT_REF_CLK_IN_HZ COUNTER_FREQUENCY
|
||||
|
||||
/*
|
||||
* PL011 related constants
|
||||
*/
|
||||
#define PLAT_MARVELL_UART_BASE (MVEBU_REGS_BASE + 0x12000)
|
||||
|
||||
/* Required platform porting definitions */
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
|
||||
|
||||
/* System timer related constants */
|
||||
#define PLAT_MARVELL_NSTIMER_FRAME_ID 1
|
||||
|
||||
/* Mailbox base address */
|
||||
#define PLAT_MARVELL_MAILBOX_BASE (MARVELL_SHARED_RAM_BASE + 0x400)
|
||||
#define PLAT_MARVELL_MAILBOX_SIZE 0x100
|
||||
#define PLAT_MARVELL_MAILBOX_MAGIC_NUM 0x6D72766C /* mrvl */
|
||||
|
||||
/* DRAM CS memory map registers related constants */
|
||||
#define MVEBU_CS_MMAP_LOW(cs_num) \
|
||||
(MVEBU_CS_MMAP_REG_BASE + (cs_num) * 0x8)
|
||||
#define MVEBU_CS_MMAP_ENABLE 0x1
|
||||
#define MVEBU_CS_MMAP_AREA_LEN_OFFS 16
|
||||
#define MVEBU_CS_MMAP_AREA_LEN_MASK \
|
||||
(0x1f << MVEBU_CS_MMAP_AREA_LEN_OFFS)
|
||||
#define MVEBU_CS_MMAP_START_ADDR_LOW_OFFS 23
|
||||
#define MVEBU_CS_MMAP_START_ADDR_LOW_MASK \
|
||||
(0x1ff << MVEBU_CS_MMAP_START_ADDR_LOW_OFFS)
|
||||
|
||||
#define MVEBU_CS_MMAP_HIGH(cs_num) \
|
||||
(MVEBU_CS_MMAP_REG_BASE + 0x4 + (cs_num) * 0x8)
|
||||
|
||||
/* DRAM max CS number */
|
||||
#define MVEBU_MAX_CS_MMAP_NUM (2)
|
||||
|
||||
/* CPU decoder window related constants */
|
||||
#define CPU_DEC_WIN_CTRL_REG(win_num) \
|
||||
(MVEBU_CPU_DEC_WIN_REG_BASE + (win_num) * 0x10)
|
||||
#define CPU_DEC_CR_WIN_ENABLE 0x1
|
||||
#define CPU_DEC_CR_WIN_TARGET_OFFS 4
|
||||
#define CPU_DEC_CR_WIN_TARGET_MASK \
|
||||
(0xf << CPU_DEC_CR_WIN_TARGET_OFFS)
|
||||
|
||||
#define CPU_DEC_WIN_SIZE_REG(win_num) \
|
||||
(MVEBU_CPU_DEC_WIN_REG_BASE + 0x4 + (win_num) * 0x10)
|
||||
#define CPU_DEC_CR_WIN_SIZE_OFFS 0
|
||||
#define CPU_DEC_CR_WIN_SIZE_MASK \
|
||||
(0xffff << CPU_DEC_CR_WIN_SIZE_OFFS)
|
||||
#define CPU_DEC_CR_WIN_SIZE_ALIGNMENT 0x10000
|
||||
|
||||
#define CPU_DEC_WIN_BASE_REG(win_num) \
|
||||
(MVEBU_CPU_DEC_WIN_REG_BASE + 0x8 + (win_num) * 0x10)
|
||||
#define CPU_DEC_BR_BASE_OFFS 0
|
||||
#define CPU_DEC_BR_BASE_MASK \
|
||||
(0xffff << CPU_DEC_BR_BASE_OFFS)
|
||||
|
||||
#define CPU_DEC_REMAP_LOW_REG(win_num) \
|
||||
(MVEBU_CPU_DEC_WIN_REG_BASE + 0xC + (win_num) * 0x10)
|
||||
#define CPU_DEC_RLR_REMAP_LOW_OFFS 0
|
||||
#define CPU_DEC_RLR_REMAP_LOW_MASK \
|
||||
(0xffff << CPU_DEC_BR_BASE_OFFS)
|
||||
|
||||
#define CPU_DEC_CCI_BASE_REG (MVEBU_CPU_DEC_WIN_REG_BASE + 0xe0)
|
||||
|
||||
/* Securities */
|
||||
#define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <io_addr_dec.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
#define MVEBU_DEC_WIN_CTRL_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
|
||||
(win) * (off))
|
||||
#define MVEBU_DEC_WIN_BASE_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
|
||||
(win) * (off) + 0x4)
|
||||
#define MVEBU_DEC_WIN_REMAP_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
|
||||
(win) * (off) + 0x8)
|
||||
|
||||
#define MVEBU_DEC_WIN_CTRL_SIZE_OFF (16)
|
||||
#define MVEBU_DEC_WIN_ENABLE (0x1)
|
||||
#define MVEBU_DEC_WIN_CTRL_ATTR_OFF (8)
|
||||
#define MVEBU_DEC_WIN_CTRL_TARGET_OFF (4)
|
||||
#define MVEBU_DEC_WIN_CTRL_EN_OFF (0)
|
||||
#define MVEBU_DEC_WIN_BASE_OFF (16)
|
||||
|
||||
#define MVEBU_WIN_BASE_SIZE_ALIGNMENT (0x10000)
|
||||
|
||||
/* There are up to 14 IO unit which need address decode in Armada-3700 */
|
||||
#define IO_UNIT_NUM_MAX (14)
|
||||
|
||||
#define MVEBU_MAX_ADDRSS_4GB (0x100000000ULL)
|
||||
|
||||
|
||||
static void set_io_addr_dec_win(int win_id, uintptr_t base_addr,
|
||||
uintptr_t win_size,
|
||||
struct dec_win_config *dec_win)
|
||||
{
|
||||
uint32_t ctrl = 0;
|
||||
uint32_t base = 0;
|
||||
|
||||
/* set size */
|
||||
ctrl = ((win_size / MVEBU_WIN_BASE_SIZE_ALIGNMENT) - 1) <<
|
||||
MVEBU_DEC_WIN_CTRL_SIZE_OFF;
|
||||
/* set attr according to IO decode window */
|
||||
ctrl |= dec_win->win_attr << MVEBU_DEC_WIN_CTRL_ATTR_OFF;
|
||||
/* set target */
|
||||
ctrl |= DRAM_CPU_DEC_TARGET_NUM << MVEBU_DEC_WIN_CTRL_TARGET_OFF;
|
||||
/* set base */
|
||||
base = (base_addr / MVEBU_WIN_BASE_SIZE_ALIGNMENT) <<
|
||||
MVEBU_DEC_WIN_BASE_OFF;
|
||||
|
||||
/* set base address*/
|
||||
mmio_write_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
|
||||
win_id, dec_win->win_offset),
|
||||
base);
|
||||
/* set remap window, some unit does not have remap window */
|
||||
if (win_id < dec_win->max_remap)
|
||||
mmio_write_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
|
||||
win_id, dec_win->win_offset), base);
|
||||
/* set control register */
|
||||
mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
|
||||
win_id, dec_win->win_offset), ctrl);
|
||||
/* enable the address decode window at last to make it effective */
|
||||
ctrl |= MVEBU_DEC_WIN_ENABLE << MVEBU_DEC_WIN_CTRL_EN_OFF;
|
||||
mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
|
||||
win_id, dec_win->win_offset), ctrl);
|
||||
|
||||
INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x) remap(0x%x)\n",
|
||||
win_id, mmio_read_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
|
||||
win_id, dec_win->win_offset)),
|
||||
mmio_read_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
|
||||
win_id, dec_win->win_offset)),
|
||||
(win_id < dec_win->max_remap) ?
|
||||
mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
|
||||
win_id, dec_win->win_offset)) : 0);
|
||||
}
|
||||
|
||||
/* Set io decode window */
|
||||
static int set_io_addr_dec(struct dram_win_map *win_map,
|
||||
struct dec_win_config *dec_win)
|
||||
{
|
||||
struct dram_win *win;
|
||||
int id;
|
||||
|
||||
/* disable all windows first */
|
||||
for (id = 0; id < dec_win->max_dram_win; id++)
|
||||
mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, id,
|
||||
dec_win->win_offset), 0);
|
||||
|
||||
/* configure IO decode windows for DRAM, inheritate DRAM size,
|
||||
* base and target from CPU-DRAM decode window and others
|
||||
* from hard coded IO decode window settings array.
|
||||
*/
|
||||
if (win_map->dram_win_num > dec_win->max_dram_win) {
|
||||
/*
|
||||
* If cpu dram windows number exceeds the io decode windows
|
||||
* max number, then fill the first io decode window
|
||||
* with base(0) and size(4GB).
|
||||
*/
|
||||
set_io_addr_dec_win(0, 0, MVEBU_MAX_ADDRSS_4GB, dec_win);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (id = 0; id < win_map->dram_win_num; id++, win++) {
|
||||
win = &win_map->dram_windows[id];
|
||||
set_io_addr_dec_win(id, win->base_addr, win->win_size, dec_win);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_io_addr_dec
|
||||
*
|
||||
* This function initializes io address decoder windows by
|
||||
* cpu dram window mapping information
|
||||
*
|
||||
* @input: N/A
|
||||
* - dram_wins_map: cpu dram windows mapping
|
||||
* - io_dec_config: io address decoder windows configuration
|
||||
* - io_unit_num: io address decoder unit number
|
||||
* @output: N/A
|
||||
*
|
||||
* @return: 0 on success and others on failure
|
||||
*/
|
||||
int init_io_addr_dec(struct dram_win_map *dram_wins_map,
|
||||
struct dec_win_config *io_dec_config, uint32_t io_unit_num)
|
||||
{
|
||||
int32_t index;
|
||||
struct dec_win_config *io_dec_win;
|
||||
int32_t ret;
|
||||
|
||||
INFO("Initializing IO address decode windows\n");
|
||||
|
||||
if (io_dec_config == NULL || io_unit_num == 0) {
|
||||
ERROR("No IO address decoder windows configurations!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (io_unit_num > IO_UNIT_NUM_MAX) {
|
||||
ERROR("IO address decoder windows number %d is over max %d\n",
|
||||
io_unit_num, IO_UNIT_NUM_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dram_wins_map == NULL) {
|
||||
ERROR("No cpu dram decoder windows map!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (index = 0; index < dram_wins_map->dram_win_num; index++)
|
||||
INFO("DRAM mapping %d base(0x%lx) size(0x%lx)\n",
|
||||
index, dram_wins_map->dram_windows[index].base_addr,
|
||||
dram_wins_map->dram_windows[index].win_size);
|
||||
|
||||
/* Set address decode window for each IO */
|
||||
for (index = 0; index < io_unit_num; index++) {
|
||||
io_dec_win = io_dec_config + index;
|
||||
ret = set_io_addr_dec(dram_wins_map, io_dec_win);
|
||||
if (ret) {
|
||||
ERROR("Failed to set IO address decode\n");
|
||||
return -1;
|
||||
}
|
||||
INFO("Set IO decode window successfully, base(0x%x)"
|
||||
" win_attr(%x) max_dram_win(%d) max_remap(%d)"
|
||||
" win_offset(%d)\n", io_dec_win->dec_reg_base,
|
||||
io_dec_win->win_attr, io_dec_win->max_dram_win,
|
||||
io_dec_win->max_remap, io_dec_win->win_offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <common/bl_common.h>
|
||||
|
||||
#include <io_addr_dec.h>
|
||||
#include <mvebu_def.h>
|
||||
|
||||
struct dec_win_config io_dec_win_conf[] = {
|
||||
/* dec_reg_base win_attr max_dram_win max_remap win_offset */
|
||||
{0xc000, 0x3d, 2, 0, 0x08}, /* USB */
|
||||
{0xc100, 0x3d, 3, 0, 0x10}, /* USB3 */
|
||||
{0xc200, 0x3d, 2, 0, 0x10}, /* DMA */
|
||||
{0xc300, 0x3d, 2, 0, 0x10}, /* NETA0 */
|
||||
{0xc400, 0x3d, 2, 0, 0x10}, /* NETA1 */
|
||||
{0xc500, 0x3d, 2, 0, 0x10}, /* PCIe */
|
||||
{0xc800, 0x3d, 3, 0, 0x10}, /* SATA */
|
||||
{0xca00, 0x3d, 3, 0, 0x08}, /* SD */
|
||||
{0xcb00, 0x3d, 3, 0, 0x10}, /* eMMC */
|
||||
{0xce00, 0x3d, 2, 0, 0x08}, /* EIP97 */
|
||||
};
|
||||
|
||||
int marvell_get_io_dec_win_conf(struct dec_win_config **win, uint32_t *size)
|
||||
{
|
||||
*win = io_dec_win_conf;
|
||||
*size = sizeof(io_dec_win_conf)/sizeof(struct dec_win_config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Marek Behun <marek.behun@nic.cz>
|
||||
*
|
||||
* Based on plat/marvell/armada/common/marvell_cci.c
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <drivers/arm/cci.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <plat_marvell.h>
|
||||
|
||||
static const int cci_map[] = {
|
||||
PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX,
|
||||
PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX
|
||||
};
|
||||
|
||||
/*
|
||||
* This redefines the weak definition in
|
||||
* plat/marvell/armada/common/marvell_cci.c
|
||||
*/
|
||||
void plat_marvell_interconnect_init(void)
|
||||
{
|
||||
/*
|
||||
* To better utilize the address space, we remap CCI base address from
|
||||
* the default (0xD8000000) to MVEBU_CCI_BASE.
|
||||
* This has to be done here, rather than in cpu_wins_init(), because
|
||||
* cpu_wins_init() is called later.
|
||||
*/
|
||||
mmio_write_32(CPU_DEC_CCI_BASE_REG, MVEBU_CCI_BASE >> 20);
|
||||
|
||||
cci_init(PLAT_MARVELL_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
|
||||
}
|
||||
+822
@@ -0,0 +1,822 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Marvell International Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#ifdef USE_CCI
|
||||
#include <drivers/arm/cci.h>
|
||||
#endif
|
||||
#include <lib/psci/psci.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <a3700_pm.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <armada_common.h>
|
||||
#include <dram_win.h>
|
||||
#include <io_addr_dec.h>
|
||||
#include <mvebu.h>
|
||||
#include <mvebu_def.h>
|
||||
#include <marvell_plat_priv.h>
|
||||
#include <plat_marvell.h>
|
||||
|
||||
/* Warm reset register */
|
||||
#define MVEBU_WARM_RESET_REG (MVEBU_NB_REGS_BASE + 0x840)
|
||||
#define MVEBU_WARM_RESET_MAGIC 0x1D1E
|
||||
|
||||
/* North Bridge GPIO1 SEL register */
|
||||
#define MVEBU_NB_GPIO1_SEL_REG (MVEBU_NB_REGS_BASE + 0x830)
|
||||
#define MVEBU_NB_GPIO1_UART1_SEL BIT(19)
|
||||
#define MVEBU_NB_GPIO1_GPIO_25_26_EN BIT(17)
|
||||
#define MVEBU_NB_GPIO1_GPIO_19_EN BIT(14)
|
||||
#define MVEBU_NB_GPIO1_GPIO_18_EN BIT(13)
|
||||
|
||||
/* CPU 1 reset register */
|
||||
#define MVEBU_CPU_1_RESET_VECTOR (MVEBU_REGS_BASE + 0x14044)
|
||||
#define MVEBU_CPU_1_RESET_REG (MVEBU_REGS_BASE + 0xD00C)
|
||||
#define MVEBU_CPU_1_RESET_BIT 31
|
||||
|
||||
/* IRQ register */
|
||||
#define MVEBU_NB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE)
|
||||
#define MVEBU_NB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
|
||||
0x10)
|
||||
#define MVEBU_NB_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
|
||||
0x18)
|
||||
#define MVEBU_SB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
|
||||
0x40)
|
||||
#define MVEBU_SB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
|
||||
0x50)
|
||||
#define MVEBU_NB_GPIO_IRQ_MASK_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
|
||||
0xC8)
|
||||
#define MVEBU_NB_GPIO_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
|
||||
0xD8)
|
||||
#define MVEBU_SB_GPIO_IRQ_MASK_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
|
||||
0xE8)
|
||||
#define MVEBU_NB_GPIO_IRQ_EN_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE)
|
||||
#define MVEBU_NB_GPIO_IRQ_EN_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
|
||||
0x04)
|
||||
#define MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
|
||||
0x10)
|
||||
#define MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
|
||||
0x14)
|
||||
#define MVEBU_NB_GPIO_IRQ_WK_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
|
||||
0x18)
|
||||
#define MVEBU_NB_GPIO_IRQ_WK_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
|
||||
0x1C)
|
||||
#define MVEBU_SB_GPIO_IRQ_EN_REG (MVEBU_SB_GPIO_IRQ_REG_BASE)
|
||||
#define MVEBU_SB_GPIO_IRQ_STATUS_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \
|
||||
0x10)
|
||||
#define MVEBU_SB_GPIO_IRQ_WK_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \
|
||||
0x18)
|
||||
|
||||
/* PMU registers */
|
||||
#define MVEBU_PM_NB_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE)
|
||||
#define MVEBU_PM_PWR_DN_CNT_SEL BIT(28)
|
||||
#define MVEBU_PM_SB_PWR_DWN BIT(4)
|
||||
#define MVEBU_PM_INTERFACE_IDLE BIT(0)
|
||||
#define MVEBU_PM_NB_CPU_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x4)
|
||||
#define MVEBU_PM_L2_FLUSH_EN BIT(22)
|
||||
#define MVEBU_PM_NB_PWR_OPTION_REG (MVEBU_PMSU_REG_BASE + 0x8)
|
||||
#define MVEBU_PM_DDR_SR_EN BIT(29)
|
||||
#define MVEBU_PM_DDR_CLK_DIS_EN BIT(28)
|
||||
#define MVEBU_PM_WARM_RESET_EN BIT(27)
|
||||
#define MVEBU_PM_DDRPHY_PWRDWN_EN BIT(23)
|
||||
#define MVEBU_PM_DDRPHY_PAD_PWRDWN_EN BIT(22)
|
||||
#define MVEBU_PM_OSC_OFF_EN BIT(21)
|
||||
#define MVEBU_PM_TBG_OFF_EN BIT(20)
|
||||
#define MVEBU_PM_CPU_VDDV_OFF_EN BIT(19)
|
||||
#define MVEBU_PM_AVS_DISABLE_MODE BIT(14)
|
||||
#define MVEBU_PM_AVS_VDD2_MODE BIT(13)
|
||||
#define MVEBU_PM_AVS_HOLD_MODE BIT(12)
|
||||
#define MVEBU_PM_L2_SRAM_LKG_PD_EN BIT(8)
|
||||
#define MVEBU_PM_EIP_SRAM_LKG_PD_EN BIT(7)
|
||||
#define MVEBU_PM_DDRMC_SRAM_LKG_PD_EN BIT(6)
|
||||
#define MVEBU_PM_MCI_SRAM_LKG_PD_EN BIT(5)
|
||||
#define MVEBU_PM_MMC_SRAM_LKG_PD_EN BIT(4)
|
||||
#define MVEBU_PM_SATA_SRAM_LKG_PD_EN BIT(3)
|
||||
#define MVEBU_PM_DMA_SRAM_LKG_PD_EN BIT(2)
|
||||
#define MVEBU_PM_SEC_SRAM_LKG_PD_EN BIT(1)
|
||||
#define MVEBU_PM_CPU_SRAM_LKG_PD_EN BIT(0)
|
||||
#define MVEBU_PM_NB_SRAM_LKG_PD_EN (MVEBU_PM_L2_SRAM_LKG_PD_EN |\
|
||||
MVEBU_PM_EIP_SRAM_LKG_PD_EN | MVEBU_PM_DDRMC_SRAM_LKG_PD_EN |\
|
||||
MVEBU_PM_MCI_SRAM_LKG_PD_EN | MVEBU_PM_MMC_SRAM_LKG_PD_EN |\
|
||||
MVEBU_PM_SATA_SRAM_LKG_PD_EN | MVEBU_PM_DMA_SRAM_LKG_PD_EN |\
|
||||
MVEBU_PM_SEC_SRAM_LKG_PD_EN | MVEBU_PM_CPU_SRAM_LKG_PD_EN)
|
||||
#define MVEBU_PM_NB_PWR_DEBUG_REG (MVEBU_PMSU_REG_BASE + 0xC)
|
||||
#define MVEBU_PM_NB_FORCE_CLK_ON BIT(30)
|
||||
#define MVEBU_PM_IGNORE_CM3_SLEEP BIT(21)
|
||||
#define MVEBU_PM_IGNORE_CM3_DEEP BIT(20)
|
||||
#define MVEBU_PM_NB_WAKE_UP_EN_REG (MVEBU_PMSU_REG_BASE + 0x2C)
|
||||
#define MVEBU_PM_SB_WKP_NB_EN BIT(31)
|
||||
#define MVEBU_PM_NB_GPIO_WKP_EN BIT(27)
|
||||
#define MVEBU_PM_SOC_TIMER_WKP_EN BIT(26)
|
||||
#define MVEBU_PM_UART_WKP_EN BIT(25)
|
||||
#define MVEBU_PM_UART2_WKP_EN BIT(19)
|
||||
#define MVEBU_PM_CPU_TIMER_WKP_EN BIT(17)
|
||||
#define MVEBU_PM_NB_WKP_EN BIT(16)
|
||||
#define MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN BIT(13)
|
||||
#define MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN BIT(12)
|
||||
#define MVEBU_PM_CPU_0_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x34)
|
||||
#define MVEBU_PM_CPU_1_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x38)
|
||||
#define MVEBU_PM_CORE_SOC_PD BIT(2)
|
||||
#define MVEBU_PM_CORE_PROC_PD BIT(1)
|
||||
#define MVEBU_PM_CORE_PD BIT(0)
|
||||
#define MVEBU_PM_CORE_1_RETURN_ADDR_REG (MVEBU_PMSU_REG_BASE + 0x44)
|
||||
#define MVEBU_PM_CPU_VDD_OFF_INFO_1_REG (MVEBU_PMSU_REG_BASE + 0x48)
|
||||
#define MVEBU_PM_CPU_VDD_OFF_INFO_2_REG (MVEBU_PMSU_REG_BASE + 0x4C)
|
||||
#define MVEBU_PM_LOW_POWER_STATE BIT(0)
|
||||
#define MVEBU_PM_CPU_WAKE_UP_CONF_REG (MVEBU_PMSU_REG_BASE + 0x54)
|
||||
#define MVEBU_PM_CORE1_WAKEUP BIT(13)
|
||||
#define MVEBU_PM_CORE0_WAKEUP BIT(12)
|
||||
#define MVEBU_PM_WAIT_DDR_RDY_VALUE (0x15)
|
||||
#define MVEBU_PM_SB_CPU_PWR_CTRL_REG (MVEBU_SB_WAKEUP_REG_BASE)
|
||||
#define MVEBU_PM_SB_PM_START BIT(0)
|
||||
#define MVEBU_PM_SB_PWR_OPTION_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x4)
|
||||
#define MVEBU_PM_SDIO_PHY_PDWN_EN BIT(17)
|
||||
#define MVEBU_PM_SB_VDDV_OFF_EN BIT(16)
|
||||
#define MVEBU_PM_EBM_SRAM_LKG_PD_EN BIT(11)
|
||||
#define MVEBU_PM_PCIE_SRAM_LKG_PD_EN BIT(10)
|
||||
#define MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN BIT(9)
|
||||
#define MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN BIT(8)
|
||||
#define MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN BIT(7)
|
||||
#define MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN BIT(6)
|
||||
#define MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN BIT(5)
|
||||
#define MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN BIT(4)
|
||||
#define MVEBU_PM_SDIO_SRAM_LKG_PD_EN BIT(3)
|
||||
#define MVEBU_PM_USB2_SRAM_LKG_PD_EN BIT(2)
|
||||
#define MVEBU_PM_USB3_H_SRAM_LKG_PD_EN BIT(1)
|
||||
#define MVEBU_PM_SB_SRAM_LKG_PD_EN (MVEBU_PM_EBM_SRAM_LKG_PD_EN |\
|
||||
MVEBU_PM_PCIE_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN |\
|
||||
MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN |\
|
||||
MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN | MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN |\
|
||||
MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN | MVEBU_PM_SDIO_SRAM_LKG_PD_EN |\
|
||||
MVEBU_PM_USB2_SRAM_LKG_PD_EN | MVEBU_PM_USB3_H_SRAM_LKG_PD_EN)
|
||||
#define MVEBU_PM_SB_WK_EN_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x10)
|
||||
#define MVEBU_PM_SB_GPIO_WKP_EN BIT(24)
|
||||
#define MVEBU_PM_SB_WKP_EN BIT(20)
|
||||
|
||||
/* DRAM registers */
|
||||
#define MVEBU_DRAM_STATS_CH0_REG (MVEBU_DRAM_REG_BASE + 0x4)
|
||||
#define MVEBU_DRAM_WCP_EMPTY BIT(19)
|
||||
#define MVEBU_DRAM_CMD_0_REG (MVEBU_DRAM_REG_BASE + 0x20)
|
||||
#define MVEBU_DRAM_CH0_CMD0 BIT(28)
|
||||
#define MVEBU_DRAM_CS_CMD0 BIT(24)
|
||||
#define MVEBU_DRAM_WCB_DRAIN_REQ BIT(1)
|
||||
#define MVEBU_DRAM_PWR_CTRL_REG (MVEBU_DRAM_REG_BASE + 0x54)
|
||||
#define MVEBU_DRAM_PHY_CLK_GATING_EN BIT(1)
|
||||
#define MVEBU_DRAM_PHY_AUTO_AC_OFF_EN BIT(0)
|
||||
|
||||
/* AVS registers */
|
||||
#define MVEBU_AVS_CTRL_2_REG (MVEBU_AVS_REG_BASE + 0x8)
|
||||
#define MVEBU_LOW_VDD_MODE_EN BIT(6)
|
||||
|
||||
/* Clock registers */
|
||||
#define MVEBU_NB_CLOCK_SEL_REG (MVEBU_NB_REGS_BASE + 0x10)
|
||||
#define MVEBU_A53_CPU_CLK_SEL BIT(15)
|
||||
|
||||
/* North Bridge Step-Down Registers */
|
||||
#define MVEBU_NB_STEP_DOWN_INT_EN_REG MVEBU_NB_STEP_DOWN_REG_BASE
|
||||
#define MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK BIT(8)
|
||||
|
||||
#define MVEBU_NB_GPIO_18 18
|
||||
#define MVEBU_NB_GPIO_19 19
|
||||
#define MVEBU_NB_GPIO_25 25
|
||||
#define MVEBU_NB_GPIO_26 26
|
||||
|
||||
typedef int (*wake_up_src_func)(union pm_wake_up_src_data *);
|
||||
|
||||
struct wake_up_src_func_map {
|
||||
enum pm_wake_up_src_type type;
|
||||
wake_up_src_func func;
|
||||
};
|
||||
|
||||
void marvell_psci_arch_init(int die_index)
|
||||
{
|
||||
}
|
||||
|
||||
static void a3700_pm_ack_irq(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_1_REG);
|
||||
if (reg)
|
||||
mmio_write_32(MVEBU_NB_IRQ_STATUS_1_REG, reg);
|
||||
|
||||
reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_2_REG);
|
||||
if (reg)
|
||||
mmio_write_32(MVEBU_NB_IRQ_STATUS_2_REG, reg);
|
||||
|
||||
reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_1_REG);
|
||||
if (reg)
|
||||
mmio_write_32(MVEBU_SB_IRQ_STATUS_1_REG, reg);
|
||||
|
||||
reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_2_REG);
|
||||
if (reg)
|
||||
mmio_write_32(MVEBU_SB_IRQ_STATUS_2_REG, reg);
|
||||
|
||||
reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG);
|
||||
if (reg)
|
||||
mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG, reg);
|
||||
|
||||
reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG);
|
||||
if (reg)
|
||||
mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG, reg);
|
||||
|
||||
reg = mmio_read_32(MVEBU_SB_GPIO_IRQ_STATUS_REG);
|
||||
if (reg)
|
||||
mmio_write_32(MVEBU_SB_GPIO_IRQ_STATUS_REG, reg);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handler called to check the validity of the power state
|
||||
* parameter.
|
||||
*****************************************************************************
|
||||
*/
|
||||
int a3700_validate_power_state(unsigned int power_state,
|
||||
psci_power_state_t *req_state)
|
||||
{
|
||||
ERROR("%s needs to be implemented\n", __func__);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handler called when a CPU is about to enter standby.
|
||||
*****************************************************************************
|
||||
*/
|
||||
void a3700_cpu_standby(plat_local_state_t cpu_state)
|
||||
{
|
||||
ERROR("%s needs to be implemented\n", __func__);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handler called when a power domain is about to be turned on. The
|
||||
* mpidr determines the CPU to be turned on.
|
||||
*****************************************************************************
|
||||
*/
|
||||
int a3700_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
/* Set barrier */
|
||||
dsbsy();
|
||||
|
||||
/* Set the cpu start address to BL1 entry point */
|
||||
mmio_write_32(MVEBU_CPU_1_RESET_VECTOR,
|
||||
PLAT_MARVELL_CPU_ENTRY_ADDR >> 2);
|
||||
|
||||
/* Get the cpu out of reset */
|
||||
mmio_clrbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT));
|
||||
mmio_setbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handler called to validate the entry point.
|
||||
*****************************************************************************
|
||||
*/
|
||||
int a3700_validate_ns_entrypoint(uintptr_t entrypoint)
|
||||
{
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handler called when a power domain is about to be turned off. The
|
||||
* target_state encodes the power state that each level should transition to.
|
||||
*****************************************************************************
|
||||
*/
|
||||
void a3700_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
plat_marvell_gic_cpuif_disable();
|
||||
|
||||
/* Core can not be powered down with pending IRQ,
|
||||
* acknowledge all the pending IRQ
|
||||
*/
|
||||
a3700_pm_ack_irq();
|
||||
}
|
||||
|
||||
static void a3700_set_gen_pwr_off_option(void)
|
||||
{
|
||||
/* Enable L2 flush -> processor state-machine option */
|
||||
mmio_setbits_32(MVEBU_PM_NB_CPU_PWR_CTRL_REG, MVEBU_PM_L2_FLUSH_EN);
|
||||
|
||||
/*
|
||||
* North bridge cannot be VDD off (always ON).
|
||||
* The NB state machine support low power mode by its state machine.
|
||||
* This bit MUST be set for north bridge power down, e.g.,
|
||||
* OSC input cutoff(NOT TEST), SRAM power down, PMIC, etc.
|
||||
* It is not related to CPU VDD OFF!!
|
||||
*/
|
||||
mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_CPU_VDDV_OFF_EN);
|
||||
|
||||
/*
|
||||
* MUST: Switch CPU/AXI clock to OSC
|
||||
* NB state machine clock is always connected to OSC (slow clock).
|
||||
* But Core0/1/processor state machine's clock are connected to AXI
|
||||
* clock. Now, AXI clock takes the TBG as clock source.
|
||||
* If using AXI clock, Core0/1/processor state machine may much faster
|
||||
* than NB state machine. It will cause problem in this case if cores
|
||||
* are released before north bridge gets ready.
|
||||
*/
|
||||
mmio_clrbits_32(MVEBU_NB_CLOCK_SEL_REG, MVEBU_A53_CPU_CLK_SEL);
|
||||
|
||||
/*
|
||||
* These register bits will trigger north bridge
|
||||
* power-down state machine regardless CM3 status.
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_SLEEP);
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_DEEP);
|
||||
|
||||
/*
|
||||
* SRAM => controlled by north bridge state machine.
|
||||
* Core VDD OFF is not related to CPU SRAM power down.
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_NB_SRAM_LKG_PD_EN);
|
||||
|
||||
/*
|
||||
* Idle AXI interface in order to get L2_WFI
|
||||
* L2 WFI is only asserted after CORE-0 and CORE-1 WFI asserted.
|
||||
* (only both core-0/1in WFI, L2 WFI will be issued by CORE.)
|
||||
* Once L2 WFI asserted, this bit is used for signalling assertion
|
||||
* to AXI IO masters.
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_INTERFACE_IDLE);
|
||||
|
||||
/* Enable core0 and core1 VDD_OFF */
|
||||
mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PD);
|
||||
mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PD);
|
||||
|
||||
/* Enable North bridge power down -
|
||||
* Both Cores MUST enable this bit to power down north bridge!
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD);
|
||||
mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD);
|
||||
|
||||
/* CA53 (processor domain) power down */
|
||||
mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD);
|
||||
mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD);
|
||||
}
|
||||
|
||||
static void a3700_en_ddr_self_refresh(void)
|
||||
{
|
||||
/*
|
||||
* Both count is 16 bits and configurable. By default, osc stb cnt
|
||||
* is 0xFFF for lower 12 bits.
|
||||
* Thus, powerdown count is smaller than osc count.
|
||||
* This count is used for exiting DDR SR mode on wakeup event.
|
||||
* The powerdown count also has impact on the following
|
||||
* state changes: idle -> count-down -> ... (power-down, vdd off, etc)
|
||||
* Here, make stable counter shorter
|
||||
* Use power down count value instead of osc_stb_cnt to speed up
|
||||
* DDR self refresh exit
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_PWR_DN_CNT_SEL);
|
||||
|
||||
/*
|
||||
* Enable DDR SR mode => controlled by north bridge state machine
|
||||
* Therefore, we must powerdown north bridge to trigger the DDR SR
|
||||
* mode switching.
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_SR_EN);
|
||||
/* Disable DDR clock, otherwise DDR will not enter into SR mode. */
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_CLK_DIS_EN);
|
||||
/* Power down DDR PHY (PAD) */
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDRPHY_PWRDWN_EN);
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG,
|
||||
MVEBU_PM_DDRPHY_PAD_PWRDWN_EN);
|
||||
|
||||
/* Set wait time for DDR ready in ROM code */
|
||||
mmio_write_32(MVEBU_PM_CPU_VDD_OFF_INFO_1_REG,
|
||||
MVEBU_PM_WAIT_DDR_RDY_VALUE);
|
||||
|
||||
/* DDR flush write buffer - mandatory */
|
||||
mmio_write_32(MVEBU_DRAM_CMD_0_REG, MVEBU_DRAM_CH0_CMD0 |
|
||||
MVEBU_DRAM_CS_CMD0 | MVEBU_DRAM_WCB_DRAIN_REQ);
|
||||
while ((mmio_read_32(MVEBU_DRAM_STATS_CH0_REG) &
|
||||
MVEBU_DRAM_WCP_EMPTY) != MVEBU_DRAM_WCP_EMPTY)
|
||||
;
|
||||
|
||||
/* Trigger PHY reset after ddr out of self refresh =>
|
||||
* supply reset pulse for DDR phy after wake up
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_DRAM_PWR_CTRL_REG, MVEBU_DRAM_PHY_CLK_GATING_EN |
|
||||
MVEBU_DRAM_PHY_AUTO_AC_OFF_EN);
|
||||
}
|
||||
|
||||
static void a3700_pwr_dn_avs(void)
|
||||
{
|
||||
/*
|
||||
* AVS power down - controlled by north bridge statemachine
|
||||
* Enable AVS power down by clear the AVS disable bit.
|
||||
*/
|
||||
mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_DISABLE_MODE);
|
||||
/*
|
||||
* Should set BIT[12:13] to powerdown AVS.
|
||||
* 1. Enable AVS VDD2 mode
|
||||
* 2. After power down AVS, we must hold AVS output voltage.
|
||||
* 3. We can choose the lower VDD for AVS power down.
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_VDD2_MODE);
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_HOLD_MODE);
|
||||
|
||||
/* Enable low VDD mode, AVS will set CPU to lowest core VDD 747mV */
|
||||
mmio_setbits_32(MVEBU_AVS_CTRL_2_REG, MVEBU_LOW_VDD_MODE_EN);
|
||||
}
|
||||
|
||||
static void a3700_pwr_dn_tbg(void)
|
||||
{
|
||||
/* Power down TBG */
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_TBG_OFF_EN);
|
||||
}
|
||||
|
||||
static void a3700_pwr_dn_sb(void)
|
||||
{
|
||||
/* Enable south bridge power down option */
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_SB_PWR_DWN);
|
||||
|
||||
/* Enable SDIO_PHY_PWRDWN */
|
||||
mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SDIO_PHY_PDWN_EN);
|
||||
|
||||
/* Enable SRAM LRM on SB */
|
||||
mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_SRAM_LKG_PD_EN);
|
||||
|
||||
/* Enable SB Power Off */
|
||||
mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_VDDV_OFF_EN);
|
||||
|
||||
/* Kick off South Bridge Power Off */
|
||||
mmio_setbits_32(MVEBU_PM_SB_CPU_PWR_CTRL_REG, MVEBU_PM_SB_PM_START);
|
||||
}
|
||||
|
||||
static void a3700_set_pwr_off_option(void)
|
||||
{
|
||||
/* Set general power off option */
|
||||
a3700_set_gen_pwr_off_option();
|
||||
|
||||
/* Enable DDR self refresh in low power mode */
|
||||
a3700_en_ddr_self_refresh();
|
||||
|
||||
/* Power down AVS */
|
||||
a3700_pwr_dn_avs();
|
||||
|
||||
/* Power down TBG */
|
||||
a3700_pwr_dn_tbg();
|
||||
|
||||
/* Power down south bridge, pay attention south bridge setting
|
||||
* should be done before
|
||||
*/
|
||||
a3700_pwr_dn_sb();
|
||||
}
|
||||
|
||||
static void a3700_set_wake_up_option(void)
|
||||
{
|
||||
/*
|
||||
* Enable the wakeup event for NB SOC => north-bridge
|
||||
* state-machine enablement on wake-up event
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_WKP_EN);
|
||||
|
||||
/* Enable both core0 and core1 wakeup on demand */
|
||||
mmio_setbits_32(MVEBU_PM_CPU_WAKE_UP_CONF_REG,
|
||||
MVEBU_PM_CORE1_WAKEUP | MVEBU_PM_CORE0_WAKEUP);
|
||||
|
||||
/* Enable warm reset in low power mode */
|
||||
mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_WARM_RESET_EN);
|
||||
}
|
||||
|
||||
static void a3700_pm_en_nb_gpio(uint32_t gpio)
|
||||
{
|
||||
/* For GPIO1 interrupt -- North bridge only */
|
||||
if (gpio >= 32) {
|
||||
/* GPIO int mask */
|
||||
mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_2_REG, BIT(gpio - 32));
|
||||
|
||||
/* NB_CPU_WAKE-up ENABLE GPIO int */
|
||||
mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_HIGH_REG, BIT(gpio - 32));
|
||||
} else {
|
||||
/* GPIO int mask */
|
||||
mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_1_REG, BIT(gpio));
|
||||
|
||||
/* NB_CPU_WAKE-up ENABLE GPIO int */
|
||||
mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_LOW_REG, BIT(gpio));
|
||||
}
|
||||
|
||||
mmio_setbits_32(MVEBU_NB_STEP_DOWN_INT_EN_REG,
|
||||
MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK);
|
||||
|
||||
/* Enable using GPIO as wakeup event
|
||||
* (actually not only for north bridge)
|
||||
*/
|
||||
mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_GPIO_WKP_EN |
|
||||
MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN |
|
||||
MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN);
|
||||
}
|
||||
|
||||
static void a3700_pm_en_sb_gpio(uint32_t gpio)
|
||||
{
|
||||
/* Enable using GPIO as wakeup event */
|
||||
mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_SB_WKP_NB_EN |
|
||||
MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN |
|
||||
MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN);
|
||||
|
||||
/* SB GPIO Wake UP | South Bridge Wake Up Enable */
|
||||
mmio_setbits_32(MVEBU_PM_SB_WK_EN_REG, MVEBU_PM_SB_GPIO_WKP_EN |
|
||||
MVEBU_PM_SB_GPIO_WKP_EN);
|
||||
|
||||
/* GPIO int mask */
|
||||
mmio_clrbits_32(MVEBU_SB_GPIO_IRQ_MASK_REG, BIT(gpio));
|
||||
|
||||
/* NB_CPU_WAKE-up ENABLE GPIO int */
|
||||
mmio_setbits_32(MVEBU_SB_GPIO_IRQ_EN_REG, BIT(gpio));
|
||||
}
|
||||
|
||||
int a3700_pm_src_gpio(union pm_wake_up_src_data *src_data)
|
||||
{
|
||||
if (src_data->gpio_data.bank_num == 0)
|
||||
/* North Bridge GPIO */
|
||||
a3700_pm_en_nb_gpio(src_data->gpio_data.gpio_num);
|
||||
else
|
||||
a3700_pm_en_sb_gpio(src_data->gpio_data.gpio_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int a3700_pm_src_uart1(union pm_wake_up_src_data *src_data)
|
||||
{
|
||||
/* Clear Uart1 select */
|
||||
mmio_clrbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_UART1_SEL);
|
||||
/* set pin 19 gpio usage*/
|
||||
mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_19_EN);
|
||||
/* Enable gpio wake-up*/
|
||||
a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_19);
|
||||
/* set pin 18 gpio usage*/
|
||||
mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_18_EN);
|
||||
/* Enable gpio wake-up*/
|
||||
a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_18);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int a3700_pm_src_uart0(union pm_wake_up_src_data *src_data)
|
||||
{
|
||||
/* set pin 25/26 gpio usage*/
|
||||
mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_25_26_EN);
|
||||
/* Enable gpio wake-up*/
|
||||
a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_25);
|
||||
/* Enable gpio wake-up*/
|
||||
a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_26);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct wake_up_src_func_map src_func_table[WAKE_UP_SRC_MAX] = {
|
||||
{WAKE_UP_SRC_GPIO, a3700_pm_src_gpio},
|
||||
{WAKE_UP_SRC_UART1, a3700_pm_src_uart1},
|
||||
{WAKE_UP_SRC_UART0, a3700_pm_src_uart0},
|
||||
/* FOLLOWING SRC NOT SUPPORTED YET */
|
||||
{WAKE_UP_SRC_TIMER, NULL}
|
||||
};
|
||||
|
||||
static wake_up_src_func a3700_get_wake_up_src_func(
|
||||
enum pm_wake_up_src_type type)
|
||||
{
|
||||
uint32_t loop;
|
||||
|
||||
for (loop = 0; loop < WAKE_UP_SRC_MAX; loop++) {
|
||||
if (src_func_table[loop].type == type)
|
||||
return src_func_table[loop].func;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#pragma weak mv_wake_up_src_config_get
|
||||
struct pm_wake_up_src_config *mv_wake_up_src_config_get(void)
|
||||
{
|
||||
static struct pm_wake_up_src_config wake_up_src_cfg = {};
|
||||
return &wake_up_src_cfg;
|
||||
}
|
||||
|
||||
static void a3700_set_wake_up_source(void)
|
||||
{
|
||||
struct pm_wake_up_src_config *wake_up_src;
|
||||
uint32_t loop;
|
||||
wake_up_src_func src_func = NULL;
|
||||
|
||||
wake_up_src = mv_wake_up_src_config_get();
|
||||
for (loop = 0; loop < wake_up_src->wake_up_src_num; loop++) {
|
||||
src_func = a3700_get_wake_up_src_func(
|
||||
wake_up_src->wake_up_src[loop].wake_up_src_type);
|
||||
if (src_func)
|
||||
src_func(
|
||||
&(wake_up_src->wake_up_src[loop].wake_up_data));
|
||||
}
|
||||
}
|
||||
|
||||
static void a3700_pm_save_lp_flag(void)
|
||||
{
|
||||
/* Save the flag for enter the low power mode */
|
||||
mmio_setbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG,
|
||||
MVEBU_PM_LOW_POWER_STATE);
|
||||
}
|
||||
|
||||
static void a3700_pm_clear_lp_flag(void)
|
||||
{
|
||||
/* Clear the flag for enter the low power mode */
|
||||
mmio_clrbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG,
|
||||
MVEBU_PM_LOW_POWER_STATE);
|
||||
}
|
||||
|
||||
static uint32_t a3700_pm_get_lp_flag(void)
|
||||
{
|
||||
/* Get the flag for enter the low power mode */
|
||||
return mmio_read_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG) &
|
||||
MVEBU_PM_LOW_POWER_STATE;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handler called when a power domain is about to be suspended. The
|
||||
* target_state encodes the power state that each level should transition to.
|
||||
*****************************************************************************
|
||||
*/
|
||||
void a3700_pwr_domain_suspend(const psci_power_state_t *target_state)
|
||||
{
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
plat_marvell_gic_cpuif_disable();
|
||||
|
||||
/* Save IRQ states */
|
||||
plat_marvell_gic_irq_save();
|
||||
|
||||
/* Set wake up options */
|
||||
a3700_set_wake_up_option();
|
||||
|
||||
/* Set wake up sources */
|
||||
a3700_set_wake_up_source();
|
||||
|
||||
/* SoC can not be powered down with pending IRQ,
|
||||
* acknowledge all the pending IRQ
|
||||
*/
|
||||
a3700_pm_ack_irq();
|
||||
|
||||
/* Set power off options */
|
||||
a3700_set_pwr_off_option();
|
||||
|
||||
/* Save the flag for enter the low power mode */
|
||||
a3700_pm_save_lp_flag();
|
||||
|
||||
isb();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handler called when a power domain has just been powered on after
|
||||
* being turned off earlier. The target_state encodes the low power state that
|
||||
* each level has woken up from.
|
||||
*****************************************************************************
|
||||
*/
|
||||
void a3700_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
/* arch specific configuration */
|
||||
marvell_psci_arch_init(0);
|
||||
|
||||
/* Per-CPU interrupt initialization */
|
||||
plat_marvell_gic_pcpu_init();
|
||||
plat_marvell_gic_cpuif_enable();
|
||||
|
||||
/* Restore the per-cpu IRQ state */
|
||||
if (a3700_pm_get_lp_flag())
|
||||
plat_marvell_gic_irq_pcpu_restore();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handler called when a power domain has just been powered on after
|
||||
* having been suspended earlier. The target_state encodes the low power state
|
||||
* that each level has woken up from.
|
||||
* TODO: At the moment we reuse the on finisher and reinitialize the secure
|
||||
* context. Need to implement a separate suspend finisher.
|
||||
*****************************************************************************
|
||||
*/
|
||||
void a3700_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
struct dec_win_config *io_dec_map;
|
||||
uint32_t dec_win_num;
|
||||
struct dram_win_map dram_wins_map;
|
||||
|
||||
/* arch specific configuration */
|
||||
marvell_psci_arch_init(0);
|
||||
|
||||
/* Interrupt initialization */
|
||||
plat_marvell_gic_init();
|
||||
|
||||
/* Restore IRQ states */
|
||||
plat_marvell_gic_irq_restore();
|
||||
|
||||
/*
|
||||
* Initialize CCI for this cluster after resume from suspend state.
|
||||
* No need for locks as no other CPU is active.
|
||||
*/
|
||||
plat_marvell_interconnect_init();
|
||||
/*
|
||||
* Enable CCI coherency for the primary CPU's cluster.
|
||||
* Platform specific PSCI code will enable coherency for other
|
||||
* clusters.
|
||||
*/
|
||||
plat_marvell_interconnect_enter_coherency();
|
||||
|
||||
/* CPU address decoder windows initialization. */
|
||||
cpu_wins_init();
|
||||
|
||||
/* fetch CPU-DRAM window mapping information by reading
|
||||
* CPU-DRAM decode windows (only the enabled ones)
|
||||
*/
|
||||
dram_win_map_build(&dram_wins_map);
|
||||
|
||||
/* Get IO address decoder windows */
|
||||
if (marvell_get_io_dec_win_conf(&io_dec_map, &dec_win_num)) {
|
||||
printf("No IO address decoder windows configurations found!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* IO address decoder init */
|
||||
if (init_io_addr_dec(&dram_wins_map, io_dec_map, dec_win_num)) {
|
||||
printf("IO address decoder windows initialization failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear low power mode flag */
|
||||
a3700_pm_clear_lp_flag();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND
|
||||
* call to get the `power_state` parameter. This allows the platform to encode
|
||||
* the appropriate State-ID field within the `power_state` parameter which can
|
||||
* be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
|
||||
*****************************************************************************
|
||||
*/
|
||||
void a3700_get_sys_suspend_power_state(psci_power_state_t *req_state)
|
||||
{
|
||||
/* lower affinities use PLAT_MAX_OFF_STATE */
|
||||
for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
|
||||
req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handlers to shutdown/reboot the system
|
||||
*****************************************************************************
|
||||
*/
|
||||
static void __dead2 a3700_system_off(void)
|
||||
{
|
||||
ERROR("%s needs to be implemented\n", __func__);
|
||||
panic();
|
||||
}
|
||||
|
||||
#pragma weak cm3_system_reset
|
||||
void cm3_system_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* A3700 handlers to reset the system
|
||||
*****************************************************************************
|
||||
*/
|
||||
static void __dead2 a3700_system_reset(void)
|
||||
{
|
||||
/* Clean the mailbox magic number to let it as act like cold boot */
|
||||
mmio_write_32(PLAT_MARVELL_MAILBOX_BASE, 0x0);
|
||||
|
||||
dsbsy();
|
||||
|
||||
/* Flush data cache if the mail box shared RAM is cached */
|
||||
#if PLAT_MARVELL_SHARED_RAM_CACHED
|
||||
flush_dcache_range((uintptr_t)PLAT_MARVELL_MAILBOX_BASE,
|
||||
2 * sizeof(uint64_t));
|
||||
#endif
|
||||
|
||||
/* Use Cortex-M3 secure coprocessor for system reset */
|
||||
cm3_system_reset();
|
||||
|
||||
/* Trigger the warm reset */
|
||||
mmio_write_32(MVEBU_WARM_RESET_REG, MVEBU_WARM_RESET_MAGIC);
|
||||
|
||||
/* Shouldn't get to this point */
|
||||
panic();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
|
||||
* platform layer will take care of registering the handlers with PSCI.
|
||||
*****************************************************************************
|
||||
*/
|
||||
const plat_psci_ops_t plat_arm_psci_pm_ops = {
|
||||
.cpu_standby = a3700_cpu_standby,
|
||||
.pwr_domain_on = a3700_pwr_domain_on,
|
||||
.pwr_domain_off = a3700_pwr_domain_off,
|
||||
.pwr_domain_suspend = a3700_pwr_domain_suspend,
|
||||
.pwr_domain_on_finish = a3700_pwr_domain_on_finish,
|
||||
.pwr_domain_suspend_finish = a3700_pwr_domain_suspend_finish,
|
||||
.get_sys_suspend_power_state = a3700_get_sys_suspend_power_state,
|
||||
.system_off = a3700_system_off,
|
||||
.system_reset = a3700_system_reset,
|
||||
.validate_power_state = a3700_validate_power_state,
|
||||
.validate_ns_entrypoint = a3700_validate_ns_entrypoint
|
||||
};
|
||||
Reference in New Issue
Block a user