Commit 1502c4e1 authored by davidcunado-arm's avatar davidcunado-arm Committed by GitHub
Browse files

Merge pull request #974 from masahir0y/uniphier

UniPhier Initial Support
parents 42fb35a8 63b3a28e
......@@ -7,6 +7,8 @@ Linaro Limited
NVIDIA Corporation
Socionext Inc.
Xilinx, Inc.
Individuals
......
ARM Trusted Firmware for Socionext UniPhier SoCs
================================================
Socionext UniPhier ARMv8-A SoCs use ARM Trusted Firmware as the secure world
firmware, supporting BL1, BL2, and BL31.
UniPhier SoC family implements its internal boot ROM, so BL1 is used as pseudo
ROM (i.e. runs in RAM). The internal boot ROM loads 64KB [1] image from a
non-volatile storage to the on-chip SRAM. Unfortunately, BL1 does not fit in
the 64KB limit if [Trusted Board Boot] (TBB) is enabled. To solve this problem,
Socionext provides a first stage loader called [UniPhier BL]. This loader runs
in the on-chip SRAM, initializes the DRAM, expands BL1 there, and hands the
control over to it. Therefore, all images of ARM Trusted Firmware run in DRAM.
The UniPhier platform works with/without TBB. See below for the build process
of each case. The image authentication for the UniPhier platform fully
complies with the Trusted Board Boot Requirements (TBBR) specification.
The UniPhier BL does not implement the authentication functionality, that is,
it can not verify the BL1 image by itself. Instead, the UniPhier BL assures
the BL1 validity in a different way; BL1 is GZIP-compressed and appended to
the UniPhier BL. The concatenation of the UniPhier BL and the compressed BL1
fits in the 64KB limit. The concatenated image is loaded by the boot ROM
(and verified if the chip fuses are blown).
[1]: Some SoCs can load 80KB, but the software implementation must be aligned
to the lowest common denominator.
[Trusted Board Boot]: ../trusted-board-boot.md
[UniPhier BL]: https://github.com/uniphier/uniphier-bl
Boot Flow
---------
1. The Boot ROM
This is hard-wired ROM, so never corrupted. It loads the UniPhier BL (with
compressed-BL1 appended) into the on-chip SRAM. If the SoC fuses are blown,
the image is verified by the SoC's own method.
2. UniPhier BL
This runs in the on-chip SRAM. After the minimum SoC initialization and DRAM
setup, it decompresses the appended BL1 image into the DRAM, then jumps to
the BL1 entry.
3. BL1
This runs in the DRAM. It extracts BL2 from FIP (Firmware Image Package).
If TBB is enabled, the BL2 is authenticated by the standard mechanism of ARM
Trusted Firmware.
4. BL2, BL31, and more
They all run in the DRAM, and are authenticated by the standard mechanism if
TBB is enabled. See [Firmware Design] for details.
[Firmware Design]: ../firmware-design.md
Basic Build
-----------
BL1 must be compressed for the reason above. The UniPhier's platform makefile
provides a build target `bl1_gzip` for this.
For a non-secure boot loader (aka BL33), U-Boot is well supported for UniPhier
SoCs. The U-Boot image (`u-boot.bin`) must be built in advance. For the build
procedure of U-Boot, refer to the document in the [U-Boot] project.
[U-Boot]: https://www.denx.de/wiki/U-Boot
To build minimum functionality for UniPhier (without TBB):
```
make CROSS_COMPILE=<gcc-prefix> PLAT=uniphier BL33=<path-to-BL33> bl1_gzip fip
```
Output images:
- `bl1.bin.gzip`
- `fip.bin`
Optional features
-----------------
- Trusted Board Boot
[mbed TLS] is needed as the cryptographic and image parser modules.
Refer to the [User Guide] for the appropriate version of mbed TLS.
To enable TBB, add the following options to the build command:
```
TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=<path-to-mbedtls>
```
[mbed TLS]: https://tls.mbed.org/
[User Guide]: ../user-guide.md
- System Control Processor (SCP)
If desired, FIP can include an SCP BL2 image. If BL2 finds an SCP BL2 image
in FIP, BL2 loads it into DRAM and kicks the SCP. Most of UniPhier boards
still work without SCP, but SCP provides better power management support.
To include SCP_BL2, add the following option to the build command:
```
SCP_BL2=<path-to-SCP>
```
- BL32 (Secure Payload)
To enable BL32, add the following option to the build command:
```
SPD=<spd> BL32=<path-to-BL32>
```
If you use TSP for BL32, `BL32=<path-to-BL32>` is not required. Just add the
following:
```
SPD=tspd
```
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __PLAT_MACROS_S__
#define __PLAT_MACROS_S__
.macro plat_crash_print_regs
.endm
#endif /* __PLAT_MACROS_S__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __PLATFORM_DEF_H__
#define __PLATFORM_DEF_H__
#include <common_def.h>
#include <tbbr/tbbr_img_def.h>
#define PLATFORM_STACK_SIZE 0x1000
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << (CACHE_WRITEBACK_SHIFT))
/* topology */
#define UNIPHIER_MAX_CPUS_PER_CLUSTER 4
#define UNIPHIER_CLUSTER_COUNT 2
#define PLATFORM_CORE_COUNT \
((UNIPHIER_MAX_CPUS_PER_CLUSTER) * (UNIPHIER_CLUSTER_COUNT))
#define PLAT_MAX_PWR_LVL 1
#define PLAT_MAX_OFF_STATE 2
#define PLAT_MAX_RET_STATE 1
#define UNIPHIER_SEC_DRAM_BASE 0x81000000
#define UNIPHIER_SEC_DRAM_LIMIT 0x82000000
#define UNIPHIER_SEC_DRAM_SIZE ((UNIPHIER_SEC_DRAM_LIMIT) - \
(UNIPHIER_SEC_DRAM_BASE))
#define BL1_RO_BASE 0x80000000
#define BL1_RO_LIMIT 0x80018000
#define BL1_RW_LIMIT (UNIPHIER_SEC_DRAM_LIMIT)
#define BL1_RW_BASE ((BL1_RW_LIMIT) - 0x00040000)
#define BL2_LIMIT (BL1_RW_BASE)
#define BL2_BASE ((BL2_LIMIT) - 0x00040000)
#define BL31_BASE (UNIPHIER_SEC_DRAM_BASE)
#define BL31_LIMIT ((BL31_BASE) + 0x00080000)
#define BL32_BASE (BL31_LIMIT)
#define BL32_LIMIT (UNIPHIER_SEC_DRAM_LIMIT)
#define UNIPHIER_BLOCK_BUF_SIZE 0x00400000
#define UNIPHIER_BLOCK_BUF_BASE ((BL2_LIMIT) - \
(UNIPHIER_BLOCK_BUF_SIZE))
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
#define PLAT_XLAT_TABLES_DYNAMIC 1
#define MAX_XLAT_TABLES 7
#define MAX_MMAP_REGIONS 6
#define MAX_IO_HANDLES 2
#define MAX_IO_DEVICES 2
#define MAX_IO_BLOCK_DEVICES 1
#define TSP_SEC_MEM_BASE (BL32_BASE)
#define TSP_SEC_MEM_SIZE ((BL32_LIMIT) - (BL32_BASE))
#define TSP_PROGBITS_LIMIT (UNIPHIER_BLOCK_BUF_BASE)
#define TSP_IRQ_SEC_PHY_TIMER 29
#endif /* __PLATFORM_DEF_H__ */
#
# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
override COLD_BOOT_SINGLE_CPU := 1
override ENABLE_PLAT_COMPAT := 0
override ERROR_DEPRECATED := 1
override LOAD_IMAGE_V2 := 1
override USE_COHERENT_MEM := 1
override USE_TBBR_DEFS := 1
# Cortex-A53 revision r0p4-51rel0
# needed for LD20, unneeded for LD11, PXs3 (no ACE)
ERRATA_A53_855873 := 1
FIP_ALIGN := 512
ifeq ($(NEED_BL32),yes)
$(eval $(call add_define,UNIPHIER_LOAD_BL32))
endif
PLAT_PATH := plat/socionext/uniphier
PLAT_INCLUDES := -I$(PLAT_PATH)/include
# IO sources for BL1, BL2
IO_SOURCES := drivers/io/io_block.c \
drivers/io/io_fip.c \
drivers/io/io_memmap.c \
drivers/io/io_storage.c \
$(PLAT_PATH)/uniphier_boot_device.c \
$(PLAT_PATH)/uniphier_emmc.c \
$(PLAT_PATH)/uniphier_io_storage.c \
$(PLAT_PATH)/uniphier_nand.c \
$(PLAT_PATH)/uniphier_usb.c
# common sources for BL1, BL2, BL31
PLAT_BL_COMMON_SOURCES += drivers/console/aarch64/console.S \
lib/xlat_tables_v2/aarch64/xlat_tables_arch.c \
lib/xlat_tables_v2/xlat_tables_common.c \
lib/xlat_tables_v2/xlat_tables_internal.c \
$(PLAT_PATH)/uniphier_console.S \
$(PLAT_PATH)/uniphier_helpers.S \
$(PLAT_PATH)/uniphier_soc_info.c \
$(PLAT_PATH)/uniphier_xlat_setup.c
BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a72.S \
$(PLAT_PATH)/uniphier_bl1_helpers.S \
$(PLAT_PATH)/uniphier_bl1_setup.c \
$(IO_SOURCES)
BL2_SOURCES += common/desc_image_load.c \
$(PLAT_PATH)/uniphier_bl2_setup.c \
$(PLAT_PATH)/uniphier_image_desc.c \
$(PLAT_PATH)/uniphier_scp.c \
$(IO_SOURCES)
BL31_SOURCES += drivers/arm/cci/cci.c \
drivers/arm/gic/common/gic_common.c \
drivers/arm/gic/v3/gicv3_helpers.c \
drivers/arm/gic/v3/gicv3_main.c \
lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a72.S \
plat/common/plat_gicv3.c \
plat/common/plat_psci_common.c \
$(PLAT_PATH)/uniphier_bl31_setup.c \
$(PLAT_PATH)/uniphier_cci.c \
$(PLAT_PATH)/uniphier_gicv3.c \
$(PLAT_PATH)/uniphier_psci.c \
$(PLAT_PATH)/uniphier_scp.c \
$(PLAT_PATH)/uniphier_smp.S \
$(PLAT_PATH)/uniphier_syscnt.c \
$(PLAT_PATH)/uniphier_topology.c
ifeq (${TRUSTED_BOARD_BOOT},1)
include drivers/auth/mbedtls/mbedtls_crypto.mk
include drivers/auth/mbedtls/mbedtls_x509.mk
PLAT_INCLUDES += -Iinclude/common/tbbr
TBB_SOURCES := drivers/auth/auth_mod.c \
drivers/auth/crypto_mod.c \
drivers/auth/img_parser_mod.c \
drivers/auth/tbbr/tbbr_cot.c \
plat/common/tbbr/plat_tbbr.c \
$(PLAT_PATH)/uniphier_tbbr.c
BL1_SOURCES += $(TBB_SOURCES)
BL2_SOURCES += $(TBB_SOURCES)
endif
.PHONY: bl1_gzip
bl1_gzip: $(BUILD_PLAT)/bl1.bin.gzip
%.gzip: %
@echo " GZIP $@"
$(Q)(cat $< | gzip -n -f -9 > $@) || (rm -f $@ || false)
#
# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
BL32_SOURCES += plat/common/plat_gicv3.c \
plat/common/aarch64/platform_mp_stack.S \
$(PLAT_PATH)/tsp/uniphier_tsp_setup.c
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <xlat_mmu_helpers.h>
#include "../uniphier.h"
#define BL32_END (unsigned long)(&__BL32_END__)
#define BL32_SIZE ((BL32_END) - (BL32_BASE))
void tsp_early_platform_setup(void)
{
uniphier_console_setup();
}
void tsp_platform_setup(void)
{
}
void tsp_plat_arch_setup(void)
{
uniphier_mmap_setup(BL32_BASE, BL32_SIZE, NULL);
enable_mmu_el1(0);
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __UNIPHIER_H__
#define __UNIPHIER_H__
#include <stdint.h>
#include <types.h>
unsigned int uniphier_get_soc_type(void);
unsigned int uniphier_get_soc_model(void);
unsigned int uniphier_get_soc_revision(void);
unsigned int uniphier_get_soc_id(void);
#define UNIPHIER_SOC_LD11 0
#define UNIPHIER_SOC_LD20 1
#define UNIPHIER_SOC_PXS3 2
#define UNIPHIER_SOC_UNKNOWN 0xffffffff
unsigned int uniphier_get_boot_device(unsigned int soc);
#define UNIPHIER_BOOT_DEVICE_EMMC 0
#define UNIPHIER_BOOT_DEVICE_NAND 1
#define UNIPHIER_BOOT_DEVICE_NOR 2
#define UNIPHIER_BOOT_DEVICE_USB 3
#define UNIPHIER_BOOT_DEVICE_RSV 0xffffffff
unsigned int uniphier_get_boot_master(unsigned int soc);
#define UNIPHIER_BOOT_MASTER_THIS 0
#define UNIPHIER_BOOT_MASTER_SCP 1
#define UNIPHIER_BOOT_MASTER_EXT 2
void uniphier_console_setup(void);
int uniphier_emmc_init(uintptr_t *block_dev_spec);
int uniphier_nand_init(uintptr_t *block_dev_spec);
int uniphier_usb_init(unsigned int soc, uintptr_t *block_dev_spec);
int uniphier_io_setup(unsigned int soc);
int uniphier_check_image(unsigned int image_id);
void uniphier_image_descs_fixup(void);
int uniphier_scp_is_running(void);
void uniphier_scp_start(void);
void uniphier_scp_open_com(void);
void uniphier_scp_system_off(void);
void uniphier_scp_system_reset(void);
struct mmap_region;
void uniphier_mmap_setup(uintptr_t total_base, size_t total_size,
const struct mmap_region *mmap);
void uniphier_cci_init(unsigned int soc);
void uniphier_cci_enable(void);
void uniphier_cci_disable(void);
void uniphier_gic_driver_init(unsigned int soc);
void uniphier_gic_init(void);
void uniphier_gic_cpuif_enable(void);
void uniphier_gic_cpuif_disable(void);
void uniphier_gic_pcpu_init(void);
unsigned int uniphier_calc_core_pos(u_register_t mpidr);
#define UNIPHIER_NS_DRAM_BASE 0x84000000
#define UNIPHIER_NS_DRAM_SIZE 0x01000000
#define UNIPHIER_BL33_BASE (UNIPHIER_NS_DRAM_BASE)
#define UNIPHIER_BL33_MAX_SIZE 0x00100000
#define UNIPHIER_SCP_BASE ((UNIPHIER_BL33_BASE) + \
(UNIPHIER_BL33_MAX_SIZE))
#define UNIPHIER_SCP_MAX_SIZE 0x00020000
#endif /* __UNIPHIER_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
.globl plat_get_my_entrypoint
func plat_get_my_entrypoint
mov x0, #0
ret
endfunc plat_get_my_entrypoint
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <bl_common.h>
#include <console.h>
#include <debug.h>
#include <errno.h>
#include <platform.h>
#include <platform_def.h>
#include <xlat_mmu_helpers.h>
#include "uniphier.h"
void bl1_early_platform_setup(void)
{
uniphier_console_setup();
}
void bl1_plat_arch_setup(void)
{
uniphier_mmap_setup(UNIPHIER_SEC_DRAM_BASE, UNIPHIER_SEC_DRAM_SIZE,
NULL);
enable_mmu_el3(0);
}
void bl1_platform_setup(void)
{
unsigned int soc;
int ret;
soc = uniphier_get_soc_id();
if (soc == UNIPHIER_SOC_UNKNOWN) {
ERROR("unsupported SoC\n");
plat_error_handler(-ENOTSUP);
}
ret = uniphier_io_setup(soc);
if (ret) {
ERROR("failed to setup io devices\n");
plat_error_handler(ret);
}
}
static meminfo_t uniphier_tzram_layout = {
.total_base = UNIPHIER_SEC_DRAM_BASE,
.total_size = UNIPHIER_SEC_DRAM_SIZE,
};
meminfo_t *bl1_plat_sec_mem_layout(void)
{
return &uniphier_tzram_layout;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <bl_common.h>
#include <debug.h>
#include <desc_image_load.h>
#include <errno.h>
#include <io/io_storage.h>
#include <platform.h>
#include <platform_def.h>
#include <xlat_tables_v2.h>
#include "uniphier.h"
static meminfo_t uniphier_bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
static int uniphier_bl2_kick_scp;
void bl2_early_platform_setup(meminfo_t *mem_layout)
{
uniphier_bl2_tzram_layout = *mem_layout;
uniphier_console_setup();
}
static const struct mmap_region uniphier_bl2_mmap[] = {
/* for SCP, BL33 */
MAP_REGION_FLAT(UNIPHIER_NS_DRAM_BASE, UNIPHIER_NS_DRAM_SIZE,
MT_MEMORY | MT_RW | MT_NS),
{ .size = 0 },
};
void bl2_plat_arch_setup(void)
{
unsigned int soc;
int skip_scp = 0;
int ret;
uniphier_mmap_setup(UNIPHIER_SEC_DRAM_BASE, UNIPHIER_SEC_DRAM_SIZE,
uniphier_bl2_mmap);
enable_mmu_el1(0);
soc = uniphier_get_soc_id();
if (soc == UNIPHIER_SOC_UNKNOWN) {
ERROR("unsupported SoC\n");
plat_error_handler(-ENOTSUP);
}
ret = uniphier_io_setup(soc);
if (ret) {
ERROR("failed to setup io devices\n");
plat_error_handler(ret);
}
switch (uniphier_get_boot_master(soc)) {
case UNIPHIER_BOOT_MASTER_THIS:
INFO("Booting from this SoC\n");
skip_scp = 1;
break;
case UNIPHIER_BOOT_MASTER_SCP:
INFO("Booting from on-chip SCP\n");
if (uniphier_scp_is_running()) {
INFO("SCP is already running. SCP_BL2 load will be skipped.\n");
skip_scp = 1;
}
/*
* SCP must be kicked every time even if it is already running
* because it polls this event after the reboot of the backend.
*/
uniphier_bl2_kick_scp = 1;
break;
case UNIPHIER_BOOT_MASTER_EXT:
INFO("Booting from external SCP\n");
skip_scp = 1;
break;
default:
plat_error_handler(-ENOTSUP);
}
if (!skip_scp) {
ret = uniphier_check_image(SCP_BL2_IMAGE_ID);
if (ret) {
WARN("SCP_BL2 image not found. SCP_BL2 load will be skipped.\n");
WARN("You must setup SCP by other means.\n");
skip_scp = 1;
uniphier_bl2_kick_scp = 0;
}
}
if (skip_scp)
uniphier_image_descs_fixup();
}
void bl2_platform_setup(void)
{
}
void plat_flush_next_bl_params(void)
{
flush_bl_params_desc();
}
bl_load_info_t *plat_get_bl_image_load_info(void)
{
return get_bl_load_info_from_mem_params_desc();
}
bl_params_t *plat_get_next_bl_params(void)
{
return get_next_bl_params_from_mem_params_desc();
}
int bl2_plat_handle_post_image_load(unsigned int image_id)
{
if (image_id == SCP_BL2_IMAGE_ID && uniphier_bl2_kick_scp)
uniphier_scp_start();
return 0;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <assert.h>
#include <bl_common.h>
#include <console.h>
#include <debug.h>
#include <errno.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <xlat_mmu_helpers.h>
#include "uniphier.h"
#define BL31_END (unsigned long)(&__BL31_END__)
#define BL31_SIZE ((BL31_END) - (BL31_BASE))
static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
{
assert(sec_state_is_valid(type));
return type == NON_SECURE ? &bl33_image_ep_info : &bl32_image_ep_info;
}
void bl31_early_platform_setup(void *from_bl2, void *plat_params_from_bl2)
{
bl_params_node_t *bl_params = ((bl_params_t *)from_bl2)->head;
uniphier_console_setup();
while (bl_params) {
if (bl_params->image_id == BL32_IMAGE_ID)
bl32_image_ep_info = *bl_params->ep_info;
if (bl_params->image_id == BL33_IMAGE_ID)
bl33_image_ep_info = *bl_params->ep_info;
bl_params = bl_params->next_params_info;
}
if (bl33_image_ep_info.pc == 0)
panic();
}
#define UNIPHIER_SYS_CNTCTL_BASE 0x60E00000
void bl31_platform_setup(void)
{
unsigned int soc;
soc = uniphier_get_soc_id();
if (soc == UNIPHIER_SOC_UNKNOWN) {
ERROR("unsupported SoC\n");
plat_error_handler(-ENOTSUP);
}
uniphier_cci_init(soc);
uniphier_cci_enable();
/* Initialize the GIC driver, cpu and distributor interfaces */
uniphier_gic_driver_init(soc);
uniphier_gic_init();
/* Enable and initialize the System level generic timer */
mmio_write_32(UNIPHIER_SYS_CNTCTL_BASE + CNTCR_OFF,
CNTCR_FCREQ(0) | CNTCR_EN);
}
void bl31_plat_arch_setup(void)
{
uniphier_mmap_setup(BL31_BASE, BL31_SIZE, NULL);
enable_mmu_el3(0);
}
void bl31_plat_runtime_setup(void)
{
/* Suppress any runtime logs unless DEBUG is defined */
#if !DEBUG
console_uninit();
#endif
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <mmio.h>
#include <stdbool.h>
#include <stddef.h>
#include <utils_def.h>
#include "uniphier.h"
#define UNIPHIER_PINMON0 0x5f900100
#define UNIPHIER_PINMON2 0x5f900108
static int uniphier_ld11_is_usb_boot(uint32_t pinmon)
{
return !!(~pinmon & 0x00000080);
}
static int uniphier_ld20_is_usb_boot(uint32_t pinmon)
{
return !!(~pinmon & 0x00000780);
}
static int uniphier_pxs3_is_usb_boot(uint32_t pinmon)
{
uint32_t pinmon2 = mmio_read_32(UNIPHIER_PINMON2);
return !!(pinmon2 & BIT(31));
}
static const unsigned int uniphier_ld11_boot_device_table[] = {
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_NOR,
};
static unsigned int uniphier_ld11_get_boot_device(uint32_t pinmon)
{
unsigned int boot_sel = (pinmon >> 1) & 0x1f;
assert(boot_sel < ARRAY_SIZE(uniphier_ld11_boot_device_table));
return uniphier_ld11_boot_device_table[boot_sel];
}
static const unsigned int uniphier_pxs3_boot_device_table[] = {
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
};
static unsigned int uniphier_pxs3_get_boot_device(uint32_t pinmon)
{
unsigned int boot_sel = (pinmon >> 1) & 0xf;
assert(boot_sel < ARRAY_SIZE(uniphier_pxs3_boot_device_table));
return uniphier_pxs3_boot_device_table[boot_sel];
}
struct uniphier_boot_device_info {
int (*is_usb_boot)(uint32_t pinmon);
unsigned int (*get_boot_device)(uint32_t pinmon);
};
static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
[UNIPHIER_SOC_LD11] = {
.is_usb_boot = uniphier_ld11_is_usb_boot,
.get_boot_device = uniphier_ld11_get_boot_device,
},
[UNIPHIER_SOC_LD20] = {
.is_usb_boot = uniphier_ld20_is_usb_boot,
.get_boot_device = uniphier_ld11_get_boot_device,
},
[UNIPHIER_SOC_PXS3] = {
.is_usb_boot = uniphier_pxs3_is_usb_boot,
.get_boot_device = uniphier_pxs3_get_boot_device,
},
};
unsigned int uniphier_get_boot_device(unsigned int soc)
{
const struct uniphier_boot_device_info *info;
uint32_t pinmon;
assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
info = &uniphier_boot_device_info[soc];
pinmon = mmio_read_32(UNIPHIER_PINMON0);
if (!(pinmon & BIT(29)))
return UNIPHIER_BOOT_DEVICE_NOR;
if (info->is_usb_boot(pinmon))
return UNIPHIER_BOOT_DEVICE_USB;
return info->get_boot_device(pinmon);
}
static const bool uniphier_have_onchip_scp[] = {
[UNIPHIER_SOC_LD11] = true,
[UNIPHIER_SOC_LD20] = true,
[UNIPHIER_SOC_PXS3] = false,
};
unsigned int uniphier_get_boot_master(unsigned int soc)
{
assert(soc < ARRAY_SIZE(uniphier_have_onchip_scp));
if (uniphier_have_onchip_scp[soc]) {
if (mmio_read_32(UNIPHIER_PINMON0) & BIT(27))
return UNIPHIER_BOOT_MASTER_THIS;
else
return UNIPHIER_BOOT_MASTER_SCP;
} else {
return UNIPHIER_BOOT_MASTER_EXT;
}
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <cci.h>
#include <stddef.h>
#include <utils_def.h>
#include "uniphier.h"
#define UNIPHIER_CCI500_BASE 0x5FD00000
static const int uniphier_cci_map[] = {0, 1};
static void __uniphier_cci_init(void)
{
cci_init(UNIPHIER_CCI500_BASE, uniphier_cci_map,
ARRAY_SIZE(uniphier_cci_map));
}
static void __uniphier_cci_enable(void)
{
cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
}
static void __uniphier_cci_disable(void)
{
cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
}
struct uniphier_cci_ops {
void (*init)(void);
void (*enable)(void);
void (*disable)(void);
};
static const struct uniphier_cci_ops uniphier_cci_ops_table[] = {
[UNIPHIER_SOC_LD11] = {
.init = NULL,
.enable = NULL,
.disable = NULL,
},
[UNIPHIER_SOC_LD20] = {
.init = __uniphier_cci_init,
.enable = __uniphier_cci_enable,
.disable = __uniphier_cci_disable,
},
[UNIPHIER_SOC_PXS3] = {
.init = NULL,
.enable = NULL,
.disable = NULL,
},
};
static struct uniphier_cci_ops uniphier_cci_ops;
void uniphier_cci_init(unsigned int soc)
{
uniphier_cci_ops = uniphier_cci_ops_table[soc];
flush_dcache_range((uint64_t)&uniphier_cci_ops,
sizeof(uniphier_cci_ops));
if (uniphier_cci_ops.init)
uniphier_cci_ops.init();
}
void uniphier_cci_enable(void)
{
if (uniphier_cci_ops.enable)
uniphier_cci_ops.enable();
}
void uniphier_cci_disable(void)
{
if (uniphier_cci_ops.disable)
uniphier_cci_ops.disable();
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <asm_macros.S>
#define UNIPHIER_UART_BASE 0x54006800
#define UNIPHIER_UART_END 0x54006c00
#define UNIPHIER_UART_OFFSET 0x100
#define UNIPHIER_UART_RX 0x00 /* In: Receive buffer */
#define UNIPHIER_UART_TX 0x00 /* Out: Transmit buffer */
#define UNIPHIER_UART_FCR 0x0c /* Char/FIFO Control Register */
#define UNIPHIER_UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
#define UNIPHIER_UART_LCR_MCR 0x10 /* Line/Modem Control Register */
#define UNIPHIER_UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
#define UNIPHIER_UART_LSR 0x14 /* Line Status Register */
#define UNIPHIER_UART_LSR_TEMT_BIT 6 /* Transmitter empty */
#define UNIPHIER_UART_LSR_THRE_BIT 5 /* Transmit-hold-register empty */
#define UNIPHIER_UART_LSR_DR_BIT 0 /* Receiver data ready */
#define UNIPHIER_UART_DLR 0x24 /* Divisor Latch Register */
/*
* Uncomment for debug
*/
/* #define UNIPHIER_UART_INIT_DIVISOR */
#define UNIPHIER_UART_DEFAULT_BASE (UNIPHIER_UART_BASE)
#define UNIPHIER_UART_CLK_RATE 58820000
#define UNIPHIER_UART_DEFAULT_BAUDRATE 115200
/*
* In: x0 - console base address
* w1 - uart clock in Hz
* w2 - baud rate
* Out: return 1 on success, or 0 on error
*/
.globl console_core_init
func console_core_init
cbz x0, 1f
#ifdef UNIPHIER_UART_INIT_DIVISOR
cbz w1, 1f
cbz w2, 1f
/* divisor = uart_clock / (16 * baud_rate) */
udiv w2, w1, w2
lsr w2, w2, #4
#endif
/* Make sure the transmitter is empty before the divisor set/change */
0: ldr w1, [x0, #UNIPHIER_UART_LSR]
tbz w1, #UNIPHIER_UART_LSR_TEMT_BIT, 0b
#ifdef UNIPHIER_UART_INIT_DIVISOR
str w2, [x0, #UNIPHIER_UART_DLR]
#endif
mov w2, #UNIPHIER_UART_FCR_ENABLE_FIFO
str w2, [x0, #UNIPHIER_UART_FCR]
mov w2, #(UNIPHIER_UART_LCR_WLEN8 << 8)
str w2, [x0, #UNIPHIER_UART_LCR_MCR]
mov w0, #1
ret
1: mov w0, #0
ret
endfunc console_core_init
/*
* In: w0 - character to be printed
* x1 - console base address
* Out: return the character written, or -1 on error
* Clobber: x2
*/
.globl console_core_putc
func console_core_putc
/* Error out if the console is not initialized */
cbz x1, 2f
/* Wait until the transmitter FIFO gets empty */
0: ldr w2, [x1, #UNIPHIER_UART_LSR]
tbz w2, #UNIPHIER_UART_LSR_THRE_BIT, 0b
mov w2, w0
1: str w2, [x1, #UNIPHIER_UART_TX]
cmp w2, #'\n'
b.ne 3f
mov w2, #'\r' /* Append '\r' to '\n' */
b 1b
2: mov w0, #-1
3: ret
endfunc console_core_putc
/*
* In: x0 - console base address
* Out: return the character read
* Clobber: x1
*/
.globl console_core_getc
func console_core_getc
/* Error out if the console is not initialized */
cbz x0, 1f
/* Wait while the receiver FIFO is empty */
0: ldr w1, [x0, #UNIPHIER_UART_LSR]
tbz w1, #UNIPHIER_UART_LSR_DR_BIT, 0b
ldr w0, [x0, #UNIPHIER_UART_RX]
ret
1: mov w0, #-1
ret
endfunc console_core_getc
/*
* In: x0 - console base address
* Out: return 0, or -1 on error
* Clobber: x1
*/
.global console_core_flush
func console_core_flush
/* Error out if the console is not initialized */
cbz x0, 1f
/* wait until the transmitter gets empty */
0: ldr w1, [x0, #UNIPHIER_UART_LSR]
tbz w1, #UNIPHIER_UART_LSR_TEMT_BIT, 0b
mov w0, #0
ret
1: mov w0, #-1
ret
endfunc console_core_flush
/* find initialized UART port */
.macro uniphier_console_get_base base, tmpx, tmpw
ldr \base, =UNIPHIER_UART_BASE
0000: ldr \tmpw, [\base, #UNIPHIER_UART_DLR]
mvn \tmpw, \tmpw
uxth \tmpw, \tmpw
cbnz \tmpw, 0001f
add \base, \base, #UNIPHIER_UART_OFFSET
ldr \tmpx, =UNIPHIER_UART_END
cmp \base, \tmpx
b.lo 0000b
mov \base, #0
0001:
.endm
/*
* int plat_crash_console_init(void)
* Clobber: x0-x2
*/
.globl plat_crash_console_init
func plat_crash_console_init
#ifdef UNIPHIER_UART_INIT_DIVISOR
ldr x0, =UNIPHIER_UART_DEFAULT_BASE
ldr x1, =UNIPHIER_UART_CLK_RATE
ldr x2, =UNIPHIER_UART_DEFAULT_BAUDRATE
b console_core_init
#else
ret
#endif
endfunc plat_crash_console_init
/*
* int plat_crash_console_putc(int c)
* Clobber: x1, x2
*/
.globl plat_crash_console_putc
func plat_crash_console_putc
#ifdef UNIPHIER_UART_INIT_DIVISOR
ldr x1, =UNIPHIER_UART_DEFAULT_BASE
#else
uniphier_console_get_base x1, x2, w2
#endif
b console_core_putc
endfunc plat_crash_console_putc
/*
* int plat_crash_console_flush(void)
* Clobber: x0, x1
*/
.global plat_crash_console_flush
func plat_crash_console_flush
#ifdef UNIPHIER_UART_INIT_DIVISOR
ldr x0, =UNIPHIER_UART_DEFAULT_BASE
#else
uniphier_console_get_base x0, x1, w1
#endif
b console_core_flush
endfunc plat_crash_console_flush
/*
* void uniphier_console_setup(void)
* Clobber: x0-x2
*/
.globl uniphier_console_setup
func uniphier_console_setup
#ifdef UNIPHIER_UART_INIT_DIVISOR
ldr x0, =UNIPHIER_UART_DEFAULT_BASE
ldr w1, =UNIPHIER_UART_CLK_RATE
ldr w2, =UNIPHIER_UART_DEFAULT_BAUDRATE
#else
uniphier_console_get_base x0, x1, w1
mov w1, #0
mov w2, #0
#endif
b console_init
endfunc uniphier_console_setup
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <io/io_block.h>
#include <mmio.h>
#include <platform_def.h>
#include <sys/types.h>
#include <utils_def.h>
#include "uniphier.h"
#define MMC_CMD_SWITCH 6
#define MMC_CMD_SELECT_CARD 7
#define MMC_CMD_SEND_CSD 9
#define MMC_CMD_READ_MULTIPLE_BLOCK 18
#define EXT_CSD_PART_CONF 179 /* R/W */
#define MMC_RSP_PRESENT BIT(0)
#define MMC_RSP_136 BIT(1) /* 136 bit response */
#define MMC_RSP_CRC BIT(2) /* expect valid crc */
#define MMC_RSP_BUSY BIT(3) /* card may send busy */
#define MMC_RSP_OPCODE BIT(4) /* response contains opcode */
#define MMC_RSP_NONE (0)
#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
#define MMC_RSP_R1b (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | \
MMC_RSP_BUSY)
#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
#define MMC_RSP_R3 (MMC_RSP_PRESENT)
#define MMC_RSP_R4 (MMC_RSP_PRESENT)
#define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
#define SDHCI_DMA_ADDRESS 0x00
#define SDHCI_BLOCK_SIZE 0x04
#define SDHCI_MAKE_BLKSZ(dma, blksz) ((((dma) & 0x7) << 12) | ((blksz) & 0xFFF))
#define SDHCI_BLOCK_COUNT 0x06
#define SDHCI_ARGUMENT 0x08
#define SDHCI_TRANSFER_MODE 0x0C
#define SDHCI_TRNS_DMA BIT(0)
#define SDHCI_TRNS_BLK_CNT_EN BIT(1)
#define SDHCI_TRNS_ACMD12 BIT(2)
#define SDHCI_TRNS_READ BIT(4)
#define SDHCI_TRNS_MULTI BIT(5)
#define SDHCI_COMMAND 0x0E
#define SDHCI_CMD_RESP_MASK 0x03
#define SDHCI_CMD_CRC 0x08
#define SDHCI_CMD_INDEX 0x10
#define SDHCI_CMD_DATA 0x20
#define SDHCI_CMD_ABORTCMD 0xC0
#define SDHCI_CMD_RESP_NONE 0x00
#define SDHCI_CMD_RESP_LONG 0x01
#define SDHCI_CMD_RESP_SHORT 0x02
#define SDHCI_CMD_RESP_SHORT_BUSY 0x03
#define SDHCI_MAKE_CMD(c, f) ((((c) & 0xff) << 8) | ((f) & 0xff))
#define SDHCI_RESPONSE 0x10
#define SDHCI_HOST_CONTROL 0x28
#define SDHCI_CTRL_DMA_MASK 0x18
#define SDHCI_CTRL_SDMA 0x00
#define SDHCI_BLOCK_GAP_CONTROL 0x2A
#define SDHCI_SOFTWARE_RESET 0x2F
#define SDHCI_RESET_CMD 0x02
#define SDHCI_RESET_DATA 0x04
#define SDHCI_INT_STATUS 0x30
#define SDHCI_INT_RESPONSE BIT(0)
#define SDHCI_INT_DATA_END BIT(1)
#define SDHCI_INT_DMA_END BIT(3)
#define SDHCI_INT_ERROR BIT(15)
#define SDHCI_SIGNAL_ENABLE 0x38
/* RCA assigned by Boot ROM */
#define UNIPHIER_EMMC_RCA 0x1000
struct uniphier_mmc_cmd {
unsigned int cmdidx;
unsigned int resp_type;
unsigned int cmdarg;
unsigned int is_data;
};
static int uniphier_emmc_block_addressing;
static int uniphier_emmc_send_cmd(uintptr_t host_base,
struct uniphier_mmc_cmd *cmd)
{
uint32_t mode = 0;
uint32_t end_bit;
uint32_t stat, flags, dma_addr;
mmio_write_32(host_base + SDHCI_INT_STATUS, -1);
mmio_write_32(host_base + SDHCI_SIGNAL_ENABLE, 0);
mmio_write_32(host_base + SDHCI_ARGUMENT, cmd->cmdarg);
if (cmd->is_data)
mode = SDHCI_TRNS_DMA | SDHCI_TRNS_BLK_CNT_EN |
SDHCI_TRNS_ACMD12 | SDHCI_TRNS_READ |
SDHCI_TRNS_MULTI;
mmio_write_16(host_base + SDHCI_TRANSFER_MODE, mode);
if (!(cmd->resp_type & MMC_RSP_PRESENT))
flags = SDHCI_CMD_RESP_NONE;
else if (cmd->resp_type & MMC_RSP_136)
flags = SDHCI_CMD_RESP_LONG;
else if (cmd->resp_type & MMC_RSP_BUSY)
flags = SDHCI_CMD_RESP_SHORT_BUSY;
else
flags = SDHCI_CMD_RESP_SHORT;
if (cmd->resp_type & MMC_RSP_CRC)
flags |= SDHCI_CMD_CRC;
if (cmd->resp_type & MMC_RSP_OPCODE)
flags |= SDHCI_CMD_INDEX;
if (cmd->is_data)
flags |= SDHCI_CMD_DATA;
if (cmd->resp_type & MMC_RSP_BUSY || cmd->is_data)
end_bit = SDHCI_INT_DATA_END;
else
end_bit = SDHCI_INT_RESPONSE;
mmio_write_16(host_base + SDHCI_COMMAND,
SDHCI_MAKE_CMD(cmd->cmdidx, flags));
do {
stat = mmio_read_32(host_base + SDHCI_INT_STATUS);
if (stat & SDHCI_INT_ERROR)
return -EIO;
if (stat & SDHCI_INT_DMA_END) {
mmio_write_32(host_base + SDHCI_INT_STATUS, stat);
dma_addr = mmio_read_32(host_base + SDHCI_DMA_ADDRESS);
mmio_write_32(host_base + SDHCI_DMA_ADDRESS, dma_addr);
}
} while (!(stat & end_bit));
return 0;
}
static int uniphier_emmc_switch_part(uintptr_t host_base, int part_num)
{
struct uniphier_mmc_cmd cmd = {0};
cmd.cmdidx = MMC_CMD_SWITCH;
cmd.resp_type = MMC_RSP_R1b;
cmd.cmdarg = (EXT_CSD_PART_CONF << 16) | (part_num << 8) | (3 << 24);
return uniphier_emmc_send_cmd(host_base, &cmd);
}
static int uniphier_emmc_is_over_2gb(uintptr_t host_base)
{
struct uniphier_mmc_cmd cmd = {0};
uint32_t csd40, csd72; /* CSD[71:40], CSD[103:72] */
int ret;
cmd.cmdidx = MMC_CMD_SEND_CSD;
cmd.resp_type = MMC_RSP_R2;
cmd.cmdarg = UNIPHIER_EMMC_RCA << 16;
ret = uniphier_emmc_send_cmd(host_base, &cmd);
if (ret)
return ret;
csd40 = mmio_read_32(host_base + SDHCI_RESPONSE + 4);
csd72 = mmio_read_32(host_base + SDHCI_RESPONSE + 8);
return !(~csd40 & 0xffc00380) && !(~csd72 & 0x3);
}
static int uniphier_emmc_load_image(uintptr_t host_base,
uint32_t dev_addr,
unsigned long load_addr,
uint32_t block_cnt)
{
struct uniphier_mmc_cmd cmd = {0};
uint8_t tmp;
assert((load_addr >> 32) == 0);
mmio_write_32(host_base + SDHCI_DMA_ADDRESS, load_addr);
mmio_write_16(host_base + SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(7, 512));
mmio_write_16(host_base + SDHCI_BLOCK_COUNT, block_cnt);
tmp = mmio_read_8(host_base + SDHCI_HOST_CONTROL);
tmp &= ~SDHCI_CTRL_DMA_MASK;
tmp |= SDHCI_CTRL_SDMA;
mmio_write_8(host_base + SDHCI_HOST_CONTROL, tmp);
tmp = mmio_read_8(host_base + SDHCI_BLOCK_GAP_CONTROL);
tmp &= ~1; /* clear Stop At Block Gap Request */
mmio_write_8(host_base + SDHCI_BLOCK_GAP_CONTROL, tmp);
cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = dev_addr;
cmd.is_data = 1;
return uniphier_emmc_send_cmd(host_base, &cmd);
}
static size_t uniphier_emmc_read(int lba, uintptr_t buf, size_t size)
{
uintptr_t host_base = 0x5a000200;
int ret;
inv_dcache_range(buf, size);
if (!uniphier_emmc_block_addressing)
lba *= 512;
ret = uniphier_emmc_load_image(host_base, lba, buf, size / 512);
inv_dcache_range(buf, size);
return ret ? 0 : size;
}
static const struct io_block_dev_spec uniphier_emmc_dev_spec = {
.buffer = {
.offset = UNIPHIER_BLOCK_BUF_BASE,
.length = UNIPHIER_BLOCK_BUF_SIZE,
},
.ops = {
.read = uniphier_emmc_read,
},
.block_size = 512,
};
static int uniphier_emmc_hw_init(void)
{
uintptr_t host_base = 0x5a000200;
struct uniphier_mmc_cmd cmd = {0};
int ret;
/*
* deselect card before SEND_CSD command.
* Do not check the return code. It fails, but it is OK.
*/
cmd.cmdidx = MMC_CMD_SELECT_CARD;
cmd.resp_type = MMC_RSP_R1;
uniphier_emmc_send_cmd(host_base, &cmd); /* CMD7 (arg=0) */
/* reset CMD Line */
mmio_write_8(host_base + SDHCI_SOFTWARE_RESET,
SDHCI_RESET_CMD | SDHCI_RESET_DATA);
while (mmio_read_8(host_base + SDHCI_SOFTWARE_RESET))
;
ret = uniphier_emmc_is_over_2gb(host_base);
if (ret < 0)
return ret;
uniphier_emmc_block_addressing = ret;
cmd.cmdarg = UNIPHIER_EMMC_RCA << 16;
/* select card again */
ret = uniphier_emmc_send_cmd(host_base, &cmd);
if (ret)
return ret;
/* switch to Boot Partition 1 */
ret = uniphier_emmc_switch_part(host_base, 1);
if (ret)
return ret;
return 0;
}
int uniphier_emmc_init(uintptr_t *block_dev_spec)
{
int ret;
ret = uniphier_emmc_hw_init();
if (ret)
return ret;
*block_dev_spec = (uintptr_t)&uniphier_emmc_dev_spec;
return 0;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <gicv3.h>
#include <platform.h>
#include <platform_def.h>
#include "uniphier.h"
static uintptr_t uniphier_rdistif_base_addrs[PLATFORM_CORE_COUNT];
static const unsigned int g0_interrupt_array[] = {
8, /* SGI0 */
14, /* SGI6 */
};
static const unsigned int g1s_interrupt_array[] = {
29, /* Timer */
9, /* SGI1 */
10, /* SGI2 */
11, /* SGI3 */
12, /* SGI4 */
13, /* SGI5 */
15, /* SGI7 */
};
static unsigned int uniphier_mpidr_to_core_pos(u_register_t mpidr)
{
return plat_core_pos_by_mpidr(mpidr);
}
static const struct gicv3_driver_data uniphier_gic_driver_data[] = {
[UNIPHIER_SOC_LD11] = {
.gicd_base = 0x5fe00000,
.gicr_base = 0x5fe40000,
.g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
.g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array),
.g0_interrupt_array = g0_interrupt_array,
.g1s_interrupt_array = g1s_interrupt_array,
.rdistif_num = PLATFORM_CORE_COUNT,
.rdistif_base_addrs = uniphier_rdistif_base_addrs,
.mpidr_to_core_pos = uniphier_mpidr_to_core_pos,
},
[UNIPHIER_SOC_LD20] = {
.gicd_base = 0x5fe00000,
.gicr_base = 0x5fe80000,
.g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
.g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array),
.g0_interrupt_array = g0_interrupt_array,
.g1s_interrupt_array = g1s_interrupt_array,
.rdistif_num = PLATFORM_CORE_COUNT,
.rdistif_base_addrs = uniphier_rdistif_base_addrs,
.mpidr_to_core_pos = uniphier_mpidr_to_core_pos,
},
[UNIPHIER_SOC_PXS3] = {
.gicd_base = 0x5fe00000,
.gicr_base = 0x5fe80000,
.g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
.g1s_interrupt_num = ARRAY_SIZE(g1s_interrupt_array),
.g0_interrupt_array = g0_interrupt_array,
.g1s_interrupt_array = g1s_interrupt_array,
.rdistif_num = PLATFORM_CORE_COUNT,
.rdistif_base_addrs = uniphier_rdistif_base_addrs,
.mpidr_to_core_pos = uniphier_mpidr_to_core_pos,
},
};
void uniphier_gic_driver_init(unsigned int soc)
{
assert(soc < ARRAY_SIZE(uniphier_gic_driver_data));
gicv3_driver_init(&uniphier_gic_driver_data[soc]);
}
void uniphier_gic_init(void)
{
gicv3_distif_init();
gicv3_rdistif_init(plat_my_core_pos());
gicv3_cpuif_enable(plat_my_core_pos());
}
void uniphier_gic_cpuif_enable(void)
{
gicv3_cpuif_enable(plat_my_core_pos());
}
void uniphier_gic_cpuif_disable(void)
{
gicv3_cpuif_disable(plat_my_core_pos());
}
void uniphier_gic_pcpu_init(void)
{
gicv3_rdistif_init(plat_my_core_pos());
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <asm_macros.S>
#include <platform_def.h>
.global uniphier_calc_core_pos
.global plat_my_core_pos
.globl platform_mem_init
/*
* unsigned int uniphier_calc_core_pos(u_register_t mpidr)
* core_pos = (cluster_id * max_cpus_per_cluster) + core_id
*/
func uniphier_calc_core_pos
and x1, x0, #MPIDR_CPU_MASK
and x0, x0, #MPIDR_CLUSTER_MASK
lsr x0, x0, #MPIDR_AFFINITY_BITS
mov x2, #UNIPHIER_MAX_CPUS_PER_CLUSTER
madd x0, x0, x2, x1
ret
endfunc uniphier_calc_core_pos
func plat_my_core_pos
mrs x0, mpidr_el1
b uniphier_calc_core_pos
endfunc plat_my_core_pos
func platform_mem_init
ret
endfunc platform_mem_init
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <assert.h>
#include <desc_image_load.h>
#include <platform_def.h>
#include "uniphier.h"
static struct bl_mem_params_node uniphier_image_descs[] = {
{
.image_id = SCP_BL2_IMAGE_ID,
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t, 0),
.image_info.image_base = UNIPHIER_SCP_BASE,
.image_info.image_max_size = UNIPHIER_SCP_MAX_SIZE,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t,
NON_SECURE | NON_EXECUTABLE),
.next_handoff_image_id = INVALID_IMAGE_ID,
},
{
.image_id = BL31_IMAGE_ID,
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t, 0),
.image_info.image_base = BL31_BASE,
.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t,
SECURE | EXECUTABLE | EP_FIRST_EXE),
.ep_info.pc = BL31_BASE,
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS),
#ifdef UNIPHIER_LOAD_BL32
.next_handoff_image_id = BL32_IMAGE_ID,
#else
.next_handoff_image_id = BL33_IMAGE_ID,
#endif
},
#ifdef UNIPHIER_LOAD_BL32
{
.image_id = BL32_IMAGE_ID,
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t, 0),
.image_info.image_base = BL32_BASE,
.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t,
SECURE | EXECUTABLE),
.ep_info.pc = BL32_BASE,
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS),
.next_handoff_image_id = BL33_IMAGE_ID,
},
#endif
{
.image_id = BL33_IMAGE_ID,
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t, 0),
.image_info.image_base = UNIPHIER_BL33_BASE,
.image_info.image_max_size = UNIPHIER_BL33_MAX_SIZE,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t,
NON_SECURE | EXECUTABLE),
.ep_info.pc = UNIPHIER_BL33_BASE,
.ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS),
.next_handoff_image_id = INVALID_IMAGE_ID,
},
};
REGISTER_BL_IMAGE_DESCS(uniphier_image_descs)
/* SCP is optional. Allow run-time fixup of the descriptor array. */
void uniphier_image_descs_fixup(void)
{
struct bl_mem_params_node *desc;
desc = get_bl_mem_params_node(SCP_BL2_IMAGE_ID);
assert(desc != NULL);
desc->image_info.h.attr |= IMAGE_ATTRIB_SKIP_LOADING;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <firmware_image_package.h>
#include <io/io_block.h>
#include <io/io_driver.h>
#include <io/io_fip.h>
#include <io/io_memmap.h>
#include <platform_def.h>
#include <types.h>
#include <utils_def.h>
#include <xlat_tables_v2.h>
#include "uniphier.h"
#define UNIPHIER_ROM_REGION_BASE 0x00000000
#define UNIPHIER_ROM_REGION_SIZE 0x10000000
static const io_dev_connector_t *uniphier_fip_dev_con;
static uintptr_t uniphier_fip_dev_handle;
static const io_dev_connector_t *uniphier_backend_dev_con;
static uintptr_t uniphier_backend_dev_handle;
static io_block_spec_t uniphier_fip_spec = {
/* .offset will be set by the io_setup func */
.length = 0x00200000,
};
static const io_uuid_spec_t uniphier_bl2_spec = {
.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
};
static const io_uuid_spec_t uniphier_scp_spec = {
.uuid = UUID_SCP_FIRMWARE_SCP_BL2,
};
static const io_uuid_spec_t uniphier_bl31_spec = {
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
};
static const io_uuid_spec_t uniphier_bl32_spec = {
.uuid = UUID_SECURE_PAYLOAD_BL32,
};
static const io_uuid_spec_t uniphier_bl33_spec = {
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
};
#if TRUSTED_BOARD_BOOT
static const io_uuid_spec_t uniphier_tb_fw_cert_spec = {
.uuid = UUID_TRUSTED_BOOT_FW_CERT,
};
static const io_uuid_spec_t uniphier_trusted_key_cert_spec = {
.uuid = UUID_TRUSTED_KEY_CERT,
};
static const io_uuid_spec_t uniphier_scp_fw_key_cert_spec = {
.uuid = UUID_SCP_FW_KEY_CERT,
};
static const io_uuid_spec_t uniphier_soc_fw_key_cert_spec = {
.uuid = UUID_SOC_FW_KEY_CERT,
};
static const io_uuid_spec_t uniphier_tos_fw_key_cert_spec = {
.uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
};
static const io_uuid_spec_t uniphier_nt_fw_key_cert_spec = {
.uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
};
static const io_uuid_spec_t uniphier_scp_fw_cert_spec = {
.uuid = UUID_SCP_FW_CONTENT_CERT,
};
static const io_uuid_spec_t uniphier_soc_fw_cert_spec = {
.uuid = UUID_SOC_FW_CONTENT_CERT,
};
static const io_uuid_spec_t uniphier_tos_fw_cert_spec = {
.uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
};
static const io_uuid_spec_t uniphier_nt_fw_cert_spec = {
.uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
};
#endif /* TRUSTED_BOARD_BOOT */
struct uniphier_io_policy {
uintptr_t *dev_handle;
uintptr_t image_spec;
uintptr_t init_params;
};
static const struct uniphier_io_policy uniphier_io_policies[] = {
[FIP_IMAGE_ID] = {
.dev_handle = &uniphier_backend_dev_handle,
.image_spec = (uintptr_t)&uniphier_fip_spec,
},
[BL2_IMAGE_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_bl2_spec,
.init_params = FIP_IMAGE_ID,
},
[SCP_BL2_IMAGE_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_scp_spec,
.init_params = FIP_IMAGE_ID,
},
[BL31_IMAGE_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_bl31_spec,
.init_params = FIP_IMAGE_ID,
},
[BL32_IMAGE_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_bl32_spec,
.init_params = FIP_IMAGE_ID,
},
[BL33_IMAGE_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_bl33_spec,
.init_params = FIP_IMAGE_ID,
},
#if TRUSTED_BOARD_BOOT
[TRUSTED_BOOT_FW_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_tb_fw_cert_spec,
.init_params = FIP_IMAGE_ID,
},
[TRUSTED_KEY_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_trusted_key_cert_spec,
.init_params = FIP_IMAGE_ID,
},
[SCP_FW_KEY_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_scp_fw_key_cert_spec,
.init_params = FIP_IMAGE_ID,
},
[SOC_FW_KEY_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_soc_fw_key_cert_spec,
.init_params = FIP_IMAGE_ID,
},
[TRUSTED_OS_FW_KEY_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_tos_fw_key_cert_spec,
.init_params = FIP_IMAGE_ID,
},
[NON_TRUSTED_FW_KEY_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_nt_fw_key_cert_spec,
.init_params = FIP_IMAGE_ID,
},
[SCP_FW_CONTENT_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_scp_fw_cert_spec,
.init_params = FIP_IMAGE_ID,
},
[SOC_FW_CONTENT_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_soc_fw_cert_spec,
.init_params = FIP_IMAGE_ID,
},
[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_tos_fw_cert_spec,
.init_params = FIP_IMAGE_ID,
},
[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
.dev_handle = &uniphier_fip_dev_handle,
.image_spec = (uintptr_t)&uniphier_nt_fw_cert_spec,
.init_params = FIP_IMAGE_ID,
},
#endif
};
static int uniphier_io_block_setup(size_t fip_offset, uintptr_t block_dev_spec)
{
int ret;
uniphier_fip_spec.offset = fip_offset;
ret = register_io_dev_block(&uniphier_backend_dev_con);
if (ret)
return ret;
return io_dev_open(uniphier_backend_dev_con, block_dev_spec,
&uniphier_backend_dev_handle);
}
static int uniphier_io_memmap_setup(size_t fip_offset)
{
int ret;
uniphier_fip_spec.offset = fip_offset;
ret = mmap_add_dynamic_region(fip_offset, fip_offset,
uniphier_fip_spec.length,
MT_RO_DATA | MT_SECURE);
if (ret)
return ret;
ret = register_io_dev_memmap(&uniphier_backend_dev_con);
if (ret)
return ret;
return io_dev_open(uniphier_backend_dev_con, 0,
&uniphier_backend_dev_handle);
}
static int uniphier_io_fip_setup(void)
{
int ret;
ret = register_io_dev_fip(&uniphier_fip_dev_con);
if (ret)
return ret;
return io_dev_open(uniphier_fip_dev_con, 0, &uniphier_fip_dev_handle);
}
static int uniphier_io_emmc_setup(unsigned int soc_id)
{
uintptr_t block_dev_spec;
int ret;
ret = uniphier_emmc_init(&block_dev_spec);
if (ret)
return ret;
return uniphier_io_block_setup(0x20000, block_dev_spec);
}
static int uniphier_io_nand_setup(unsigned int soc_id)
{
uintptr_t block_dev_spec;
int ret;
ret = uniphier_nand_init(&block_dev_spec);
if (ret)
return ret;
return uniphier_io_block_setup(0x20000, block_dev_spec);
}
static int uniphier_io_nor_setup(unsigned int soc_id)
{
return uniphier_io_memmap_setup(0x70000);
}
static int uniphier_io_usb_setup(unsigned int soc_id)
{
uintptr_t block_dev_spec;
int ret;
/* use ROM API for loading images from USB storage */
ret = mmap_add_dynamic_region(UNIPHIER_ROM_REGION_BASE,
UNIPHIER_ROM_REGION_BASE,
UNIPHIER_ROM_REGION_SIZE,
MT_CODE | MT_SECURE);
if (ret)
return ret;
ret = uniphier_usb_init(soc_id, &block_dev_spec);
if (ret)
return ret;
return uniphier_io_block_setup(0x20000, block_dev_spec);
}
static int (* const uniphier_io_setup_table[])(unsigned int) = {
[UNIPHIER_BOOT_DEVICE_EMMC] = uniphier_io_emmc_setup,
[UNIPHIER_BOOT_DEVICE_NAND] = uniphier_io_nand_setup,
[UNIPHIER_BOOT_DEVICE_NOR] = uniphier_io_nor_setup,
[UNIPHIER_BOOT_DEVICE_USB] = uniphier_io_usb_setup,
};
int uniphier_io_setup(unsigned int soc_id)
{
int (*io_setup)(unsigned int soc_id);
unsigned int boot_dev;
int ret;
boot_dev = uniphier_get_boot_device(soc_id);
if (boot_dev == UNIPHIER_BOOT_DEVICE_RSV)
return -EINVAL;
io_setup = uniphier_io_setup_table[boot_dev];
ret = io_setup(soc_id);
if (ret)
return ret;
ret = uniphier_io_fip_setup();
if (ret)
return ret;
return 0;
}
int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
uintptr_t *image_spec)
{
uintptr_t init_params;
assert(image_id < ARRAY_SIZE(uniphier_io_policies));
*dev_handle = *(uniphier_io_policies[image_id].dev_handle);
*image_spec = uniphier_io_policies[image_id].image_spec;
init_params = uniphier_io_policies[image_id].init_params;
return io_dev_init(*dev_handle, init_params);
}
int uniphier_check_image(unsigned int image_id)
{
uintptr_t dev_handle, image_spec, image_handle;
int ret;
ret = plat_get_image_source(image_id, &dev_handle, &image_spec);
if (ret)
return ret;
ret = io_open(dev_handle, image_spec, &image_handle);
if (ret)
return ret;
io_close(image_handle);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment