Commit 562aef8e authored by davidcunado-arm's avatar davidcunado-arm Committed by GitHub
Browse files

Merge pull request #950 from danh-arm/hz/hikey

HiKey v3
parents c8640565 3d3b02d9
Description
====================
HiKey is one of 96boards. Hisilicon Kirin6220 processor is installed on HiKey.
More information are listed in [link](https://github.com/96boards/documentation/blob/master/ConsumerEdition/HiKey/Quickstart/README.md).
How to build
====================
1. Code Locations
-----------------
* ARM Trusted Firmware:
[link](https://github.com/ARM-software/arm-trusted-firmware)
* edk2:
[link](https://github.com/96boards-hikey/edk2/tree/testing/hikey960_v2.5)
* OpenPlatformPkg:
[link](https://github.com/96boards-hikey/OpenPlatformPkg/tree/testing/hikey960_v1.3.4)
* l-loader:
[link](https://github.com/96boards-hikey/l-loader/tree/testing/hikey960_v1.2)
* uefi-tools:
[link](https://github.com/96boards-hikey/uefi-tools/tree/testing/hikey960_v1)
* atf-fastboot:
[link](https://github.com/96boards-hikey/atf-fastboot/tree/master)
2. Build Procedure
------------------
* Fetch all the above repositories into local host.
Make all the repositories in the same ${BUILD_PATH}.
* Create the symbol link to OpenPlatformPkg in edk2.
<br>`$cd ${BUILD_PATH}/edk2`</br>
<br>`$ln -sf ../OpenPlatformPkg`</br>
* Prepare AARCH64 && AARCH32 toolchain. Prepare python.
* If your hikey hardware is built by CircuitCo, update _uefi-tools/platform.config_ first. _(optional)_
<br>__Uncomment the below sentence. Otherwise, UEFI can't output messages on serial
console on hikey.__</br>
<br>`BUILDFLAGS=-DSERIAL_BASE=0xF8015000`</br>
<br>If your hikey hardware is built by LeMarker, nothing to do.</br>
* Build it as debug mode. Create your own build script file or you could refer to __build_uefi.sh__ in l-loader git repository.
<br>`BUILD_OPTION=DEBUG`</br>
<br>`export AARCH64_TOOLCHAIN=GCC5`</br>
<br>`export UEFI_TOOLS_DIR=${BUILD_PATH}/uefi-tools`<br>
<br>`export EDK2_DIR=${BUILD_PATH}/edk2`</br>
<br>`EDK2_OUTPUT_DIR=${EDK2_DIR}/Build/HiKey/${BUILD_OPTION}_${AARCH64_TOOLCHAIN}`</br>
<br>`# Build fastboot for ARM Trust Firmware. It's used for recovery mode.`</br>
<br>`cd ${BUILD_PATH}/atf-fastboot`</br>
<br>`CROSS_COMPILE=aarch64-linux-gnu- make PLAT=hikey DEBUG=1`</br>
<br>`# Convert DEBUG/RELEASE to debug/release`</br>
<br>`FASTBOOT_BUILD_OPTION=$(echo ${BUILD_OPTION} | tr '[A-Z]' '[a-z]')`</br>
<br>`cd ${EDK2_DIR}`</br>
<br>`# Build UEFI & ARM Trust Firmware`</br>
<br>`${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware hikey`</br>
<br>`# Generate l-loader.bin`</br>
<br>`cd ${BUILD_PATH}/l-loader`</br>
<br>`ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin`</br>
<br>`ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin`</br>
<br>`ln -sf ${BUILD_PATH}/atf-fastboot/build/hikey/${FASTBOOT_BUILD_OPTION}/bl1.bin fastboot.bin`</br>
<br>`python gen_loader.py -o l-loader.bin --img_bl1=bl1.bin --img_ns_bl1u=BL33_AP_UEFI.fd`</br>
<br>`arm-linux-gnueabihf-gcc -c -o start.o start.S`</br>
<br>`arm-linux-gnueabihf-ld -Bstatic -Tl-loader.lds -Ttext 0xf9800800 start.o -o loader`</br>
<br>`arm-linux-gnueabihf-objcopy -O binary loader temp`</br>
<br>`python gen_loader_hikey.py -o l-loader.bin --img_loader=temp --img_bl1=bl1.bin --img_ns_bl1u=fastboot.bin`</br>
* Generate partition table for aosp. The eMMC capacity is either 4GB or 8GB. Just change "aosp-4g" to "linux-4g" for debian.
<br>`$PTABLE=aosp-4g SECTOR_SIZE=512 bash -x generate_ptable.sh`</br>
3. Setup Console
----------------
* Install ser2net. Use telnet as the console since UEFI fails to display Boot Manager GUI in minicom. __If you don't need Boot Manager GUI, just ignore this section.__
<br>`$sudo apt-get install ser2net`</br>
* Configure ser2net.
<br>`$sudo vi /etc/ser2net.conf`</br>
<br>Append one line for serial-over-USB in below.</br>
<br>_#ser2net.conf_</br>
<br>`2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner`</br>
* Open the console.
<br>`$telnet localhost 2004`</br>
<br>And you could open the console remotely, too.</br>
4. Flush images in recovery mode
-----------------------------
* Make sure Pin3-Pin4 on J15 are connected for recovery mode. Then power on HiKey.
* Remove the modemmanager package. This package may cause the idt tool failure.
<br>`$sudo apt-get purge modemmanager`</br>
* Run the command to download l-loader.bin into HiKey.
<br>`$sudo python hisi-idt.py -d /dev/ttyUSB1 --img1 l-loader.bin`</br>
* Update images. All aosp or debian images could be fetched from [link](https://builds.96boards.org/).
<br>`$sudo fastboot flash ptable prm_ptable.img`</br>
<br>`$sudo fastboot flash fastboot fip.bin`</br>
<br>`$sudo fastboot flash boot boot.img`</br>
<br>`$sudo fastboot flash cache cache.img`</br>
<br>`$sudo fastboot flash system system.img`</br>
<br>`$sudo fastboot flash userdata userdata.img`</br>
5. Boot UEFI in normal mode
-----------------------------
* Make sure Pin3-Pin4 on J15 are open for normal boot mode. Then power on HiKey.
* Reference [link](https://github.com/96boards-hikey/tools-images-hikey960/blob/master/build-from-source/README-ATF-UEFI-build-from-source.md)
......@@ -42,8 +42,14 @@
******************************************************************************/
#define CPUACTLR_EL1 S3_1_C15_C2_0 /* Instruction def. */
#define CPUACTLR_DTAH (1 << 24)
#define CPUACTLR_ENDCCASCI (1 << 44)
#define CPUACTLR_ENDCCASCI_SHIFT 44
#define CPUACTLR_ENDCCASCI (1 << CPUACTLR_ENDCCASCI_SHIFT)
#define CPUACTLR_RADIS_SHIFT 27
#define CPUACTLR_RADIS (3 << CPUACTLR_RADIS_SHIFT)
#define CPUACTLR_L1RADIS_SHIFT 25
#define CPUACTLR_L1RADIS (3 << CPUACTLR_L1RADIS_SHIFT)
#define CPUACTLR_DTAH_SHIFT 24
#define CPUACTLR_DTAH (1 << CPUACTLR_DTAH_SHIFT)
/*******************************************************************************
* L2 Auxiliary Control register specific definitions.
......
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <arm_gic.h>
#include <assert.h>
#include <bl_common.h>
#include <debug.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <xlat_tables.h>
#include "../hikey_def.h"
#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \
DDR_SIZE, \
MT_DEVICE | MT_RW | MT_NS)
#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \
DEVICE_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
#define MAP_ROM_PARAM MAP_REGION_FLAT(XG2RAM0_BASE, \
BL1_XG2RAM0_OFFSET, \
MT_DEVICE | MT_RO | MT_SECURE)
#define MAP_SRAM MAP_REGION_FLAT(SRAM_BASE, \
SRAM_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
/*
* BL1 needs to access the areas of MMC_SRAM.
* BL1 loads BL2 from eMMC into SRAM before DDR initialized.
*/
#define MAP_MMC_SRAM MAP_REGION_FLAT(HIKEY_BL1_MMC_DESC_BASE, \
HIKEY_BL1_MMC_DESC_SIZE + \
HIKEY_BL1_MMC_DATA_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
/*
* Table of regions for different BL stages to map using the MMU.
* This doesn't include Trusted RAM as the 'mem_layout' argument passed to
* hikey_init_mmu_elx() will give the available subset of that,
*/
#if IMAGE_BL1
static const mmap_region_t hikey_mmap[] = {
MAP_DEVICE,
MAP_ROM_PARAM,
MAP_MMC_SRAM,
{0}
};
#endif
#if IMAGE_BL2
static const mmap_region_t hikey_mmap[] = {
MAP_DDR,
MAP_DEVICE,
{0}
};
#endif
#if IMAGE_BL31
static const mmap_region_t hikey_mmap[] = {
MAP_DEVICE,
MAP_SRAM,
{0}
};
#endif
/*
* Macro generating the code for the function setting up the pagetables as per
* the platform memory map & initialize the mmu, for the given exception level
*/
#define HIKEY_CONFIGURE_MMU_EL(_el) \
void hikey_init_mmu_el##_el(unsigned long total_base, \
unsigned long total_size, \
unsigned long ro_start, \
unsigned long ro_limit, \
unsigned long coh_start, \
unsigned long coh_limit) \
{ \
mmap_add_region(total_base, total_base, \
total_size, \
MT_MEMORY | MT_RW | MT_SECURE); \
mmap_add_region(ro_start, ro_start, \
ro_limit - ro_start, \
MT_MEMORY | MT_RO | MT_SECURE); \
mmap_add_region(coh_start, coh_start, \
coh_limit - coh_start, \
MT_DEVICE | MT_RW | MT_SECURE); \
mmap_add(hikey_mmap); \
init_xlat_tables(); \
\
enable_mmu_el##_el(0); \
}
/* Define EL1 and EL3 variants of the function initialising the MMU */
HIKEY_CONFIGURE_MMU_EL(1)
HIKEY_CONFIGURE_MMU_EL(3)
unsigned long plat_get_ns_image_entrypoint(void)
{
return HIKEY_NS_IMAGE_OFFSET;
}
unsigned int plat_get_syscnt_freq2(void)
{
return 1200000;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include "../hikey_def.h"
.globl plat_my_core_pos
.globl platform_mem_init
.globl plat_crash_console_init
.globl plat_crash_console_putc
.globl plat_report_exception
.globl plat_reset_handler
func plat_my_core_pos
mrs x0, mpidr_el1
and x1, x0, #MPIDR_CPU_MASK
and x0, x0, #MPIDR_CLUSTER_MASK
add x0, x1, x0, LSR #6
ret
endfunc plat_my_core_pos
/* -----------------------------------------------------
* void platform_mem_init(void);
*
* We don't need to carry out any memory initialization
* on HIKEY. The Secure RAM is accessible straight away.
* -----------------------------------------------------
*/
func platform_mem_init
ret
endfunc platform_mem_init
/* ---------------------------------------------
* int plat_crash_console_init(void)
* Function to initialize the crash console
* without a C Runtime to print crash report.
* Clobber list : x0, x1, x2
* ---------------------------------------------
*/
func plat_crash_console_init
mov_imm x0, CRASH_CONSOLE_BASE
mov_imm x1, PL011_UART_CLK_IN_HZ
mov_imm x2, PL011_BAUDRATE
b console_core_init
endfunc plat_crash_console_init
/* ---------------------------------------------
* int plat_crash_console_putc(int c)
* Function to print a character on the crash
* console without a C Runtime.
* Clobber list : x1, x2
* ---------------------------------------------
*/
func plat_crash_console_putc
mov_imm x1, CRASH_CONSOLE_BASE
b console_core_putc
endfunc plat_crash_console_putc
/* ---------------------------------------------
* void plat_report_exception(unsigned int type)
* Function to report an unhandled exception
* with platform-specific means.
* On HIKEY platform, it updates the LEDs
* to indicate where we are
* ---------------------------------------------
*/
func plat_report_exception
mov x8, x30
/* Turn on LED according to x0 (0 -- f) */
ldr x2, =0xf7020000
and x1, x0, #1
str w1, [x2, #4]
and x1, x0, #2
str w1, [x2, #8]
and x1, x0, #4
str w1, [x2, #16]
and x1, x0, #8
str w1, [x2, #32]
mrs x2, currentel
and x2, x2, #0xc0
/* Check EL1 */
cmp x2, #0x04
beq plat_report_el1
adr x4, plat_err_str
bl asm_print_str
adr x4, esr_el3_str
bl asm_print_str
mrs x4, esr_el3
bl asm_print_hex
adr x4, elr_el3_str
bl asm_print_str
mrs x4, elr_el3
bl asm_print_hex
b plat_report_end
plat_report_el1:
adr x4, plat_err_str
bl asm_print_str
adr x4, esr_el1_str
bl asm_print_str
mrs x4, esr_el1
bl asm_print_hex
adr x4, elr_el1_str
bl asm_print_str
mrs x4, elr_el1
bl asm_print_hex
plat_report_end:
mov x30, x8
ret
endfunc plat_report_exception
/* -----------------------------------------------------
* void plat_reset_handler(void);
* -----------------------------------------------------
*/
func plat_reset_handler
ret
endfunc plat_reset_handler
.section .rodata.rev_err_str, "aS"
plat_err_str:
.asciz "\nPlatform exception reporting:"
esr_el3_str:
.asciz "\nESR_EL3: "
elr_el3_str:
.asciz "\nELR_EL3: "
esr_el1_str:
.asciz "\nESR_EL1: "
elr_el1_str:
.asciz "\nELR_EL1: "
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <console.h>
#include <debug.h>
#include <dw_mmc.h>
#include <emmc.h>
#include <errno.h>
#include <gpio.h>
#include <hi6220.h>
#include <hi6553.h>
#include <mmio.h>
#include <pl061_gpio.h>
#include <platform.h>
#include <platform_def.h>
#include <sp804_delay_timer.h>
#include <string.h>
#include <tbbr/tbbr_img_desc.h>
#include "../../bl1/bl1_private.h"
#include "hikey_def.h"
#include "hikey_private.h"
/*
* Declarations of linker defined symbols which will help us find the layout
* of trusted RAM
*/
extern unsigned long __COHERENT_RAM_START__;
extern unsigned long __COHERENT_RAM_END__;
/*
* The next 2 constants identify the extents of the coherent memory region.
* These addresses are used by the MMU setup code and therefore they must be
* page-aligned. It is the responsibility of the linker script to ensure that
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
* page-aligned addresses.
*/
#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
/* Data structure which holds the extents of the trusted RAM for BL1 */
static meminfo_t bl1_tzram_layout;
enum {
BOOT_NORMAL = 0,
BOOT_USB_DOWNLOAD,
BOOT_UART_DOWNLOAD,
};
meminfo_t *bl1_plat_sec_mem_layout(void)
{
return &bl1_tzram_layout;
}
/*
* Perform any BL1 specific platform actions.
*/
void bl1_early_platform_setup(void)
{
const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
/* Initialize the console to provide early debug support */
console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
/* Allow BL1 to see the whole Trusted RAM */
bl1_tzram_layout.total_base = BL1_RW_BASE;
bl1_tzram_layout.total_size = BL1_RW_SIZE;
/* Calculate how much RAM BL1 is using and how much remains free */
bl1_tzram_layout.free_base = BL1_RW_BASE;
bl1_tzram_layout.free_size = BL1_RW_SIZE;
reserve_mem(&bl1_tzram_layout.free_base,
&bl1_tzram_layout.free_size,
BL1_RAM_BASE,
bl1_size);
INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
bl1_size);
}
/*
* Perform the very early platform specific architecture setup here. At the
* moment this only does basic initialization. Later architectural setup
* (bl1_arch_setup()) does not do anything platform specific.
*/
void bl1_plat_arch_setup(void)
{
hikey_init_mmu_el3(bl1_tzram_layout.total_base,
bl1_tzram_layout.total_size,
BL1_RO_BASE,
BL1_RO_LIMIT,
BL1_COHERENT_RAM_BASE,
BL1_COHERENT_RAM_LIMIT);
}
static void hikey_sp804_init(void)
{
uint32_t data;
/* select the clock of dual timer0 */
data = mmio_read_32(AO_SC_TIMER_EN0);
while (data & 3) {
data &= ~3;
data |= 3 << 16;
mmio_write_32(AO_SC_TIMER_EN0, data);
data = mmio_read_32(AO_SC_TIMER_EN0);
}
/* enable the pclk of dual timer0 */
data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) {
mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0);
data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
}
/* reset dual timer0 */
data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0);
do {
data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
} while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0));
/* unreset dual timer0 */
mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0);
do {
data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
} while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0));
sp804_timer_init(SP804_TIMER0_BASE, 10, 192);
}
static void hikey_gpio_init(void)
{
pl061_gpio_init();
pl061_gpio_register(GPIO0_BASE, 0);
pl061_gpio_register(GPIO1_BASE, 1);
pl061_gpio_register(GPIO2_BASE, 2);
pl061_gpio_register(GPIO3_BASE, 3);
pl061_gpio_register(GPIO4_BASE, 4);
pl061_gpio_register(GPIO5_BASE, 5);
pl061_gpio_register(GPIO6_BASE, 6);
pl061_gpio_register(GPIO7_BASE, 7);
pl061_gpio_register(GPIO8_BASE, 8);
pl061_gpio_register(GPIO9_BASE, 9);
pl061_gpio_register(GPIO10_BASE, 10);
pl061_gpio_register(GPIO11_BASE, 11);
pl061_gpio_register(GPIO12_BASE, 12);
pl061_gpio_register(GPIO13_BASE, 13);
pl061_gpio_register(GPIO14_BASE, 14);
pl061_gpio_register(GPIO15_BASE, 15);
pl061_gpio_register(GPIO16_BASE, 16);
pl061_gpio_register(GPIO17_BASE, 17);
pl061_gpio_register(GPIO18_BASE, 18);
pl061_gpio_register(GPIO19_BASE, 19);
/* Power on indicator LED (USER_LED1). */
gpio_set_direction(32, GPIO_DIR_OUT); /* LED1 */
gpio_set_value(32, GPIO_LEVEL_HIGH);
gpio_set_direction(33, GPIO_DIR_OUT); /* LED2 */
gpio_set_value(33, GPIO_LEVEL_LOW);
gpio_set_direction(34, GPIO_DIR_OUT); /* LED3 */
gpio_set_direction(35, GPIO_DIR_OUT); /* LED4 */
}
static void hikey_pmussi_init(void)
{
uint32_t data;
/* Initialize PWR_HOLD GPIO */
gpio_set_direction(0, GPIO_DIR_OUT);
gpio_set_value(0, GPIO_LEVEL_LOW);
/*
* After reset, PMUSSI stays in reset mode.
* Now make it out of reset.
*/
mmio_write_32(AO_SC_PERIPH_RSTDIS4,
AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
do {
data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
} while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
/* Set PMUSSI clock latency for read operation. */
data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3);
data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK;
data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3;
mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data);
/* enable PMUSSI clock */
data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU |
AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU;
mmio_write_32(AO_SC_PERIPH_CLKEN5, data);
data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI;
mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
gpio_set_value(0, GPIO_LEVEL_HIGH);
}
static void hikey_hi6553_init(void)
{
uint8_t data;
mmio_write_8(HI6553_PERI_EN_MARK, 0x1e);
mmio_write_8(HI6553_NP_REG_ADJ1, 0);
data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC |
DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2;
mmio_write_8(HI6553_DISABLE6_XO_CLK, data);
/* configure BUCK0 & BUCK1 */
mmio_write_8(HI6553_BUCK01_CTRL2, 0x5e);
mmio_write_8(HI6553_BUCK0_CTRL7, 0x10);
mmio_write_8(HI6553_BUCK1_CTRL7, 0x10);
mmio_write_8(HI6553_BUCK0_CTRL5, 0x1e);
mmio_write_8(HI6553_BUCK1_CTRL5, 0x1e);
mmio_write_8(HI6553_BUCK0_CTRL1, 0xfc);
mmio_write_8(HI6553_BUCK1_CTRL1, 0xfc);
/* configure BUCK2 */
mmio_write_8(HI6553_BUCK2_REG1, 0x4f);
mmio_write_8(HI6553_BUCK2_REG5, 0x99);
mmio_write_8(HI6553_BUCK2_REG6, 0x45);
mdelay(1);
mmio_write_8(HI6553_VSET_BUCK2_ADJ, 0x22);
mdelay(1);
/* configure BUCK3 */
mmio_write_8(HI6553_BUCK3_REG3, 0x02);
mmio_write_8(HI6553_BUCK3_REG5, 0x99);
mmio_write_8(HI6553_BUCK3_REG6, 0x41);
mmio_write_8(HI6553_VSET_BUCK3_ADJ, 0x02);
mdelay(1);
/* configure BUCK4 */
mmio_write_8(HI6553_BUCK4_REG2, 0x9a);
mmio_write_8(HI6553_BUCK4_REG5, 0x99);
mmio_write_8(HI6553_BUCK4_REG6, 0x45);
/* configure LDO20 */
mmio_write_8(HI6553_LDO20_REG_ADJ, 0x50);
mmio_write_8(HI6553_NP_REG_CHG, 0x0f);
mmio_write_8(HI6553_CLK_TOP0, 0x06);
mmio_write_8(HI6553_CLK_TOP3, 0xc0);
mmio_write_8(HI6553_CLK_TOP4, 0x00);
/* configure LDO7 & LDO10 for SD slot */
/* enable LDO7 */
data = mmio_read_8(HI6553_LDO7_REG_ADJ);
data = (data & 0xf8) | 0x2;
mmio_write_8(HI6553_LDO7_REG_ADJ, data);
mdelay(5);
mmio_write_8(HI6553_ENABLE2_LDO1_8, 1 << 6);
mdelay(5);
/* enable LDO10 */
data = mmio_read_8(HI6553_LDO10_REG_ADJ);
data = (data & 0xf8) | 0x5;
mmio_write_8(HI6553_LDO10_REG_ADJ, data);
mdelay(5);
mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 1);
mdelay(5);
/* enable LDO15 */
data = mmio_read_8(HI6553_LDO15_REG_ADJ);
data = (data & 0xf8) | 0x4;
mmio_write_8(HI6553_LDO15_REG_ADJ, data);
mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 6);
mdelay(5);
/* enable LDO19 */
data = mmio_read_8(HI6553_LDO19_REG_ADJ);
data |= 0x7;
mmio_write_8(HI6553_LDO19_REG_ADJ, data);
mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 2);
mdelay(5);
/* enable LDO21 */
data = mmio_read_8(HI6553_LDO21_REG_ADJ);
data = (data & 0xf8) | 0x3;
mmio_write_8(HI6553_LDO21_REG_ADJ, data);
mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 4);
mdelay(5);
/* enable LDO22 */
data = mmio_read_8(HI6553_LDO22_REG_ADJ);
data = (data & 0xf8) | 0x7;
mmio_write_8(HI6553_LDO22_REG_ADJ, data);
mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 5);
mdelay(5);
/* select 32.764KHz */
mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01);
}
static void init_mmc0_pll(void)
{
unsigned int data;
/* select SYSPLL as the source of MMC0 */
/* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21);
do {
data = mmio_read_32(PERI_SC_CLK_SEL0);
} while (!(data & (1 << 5)));
/* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29);
do {
data = mmio_read_32(PERI_SC_CLK_SEL0);
} while (data & (1 << 13));
mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0));
do {
data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
} while (!(data & (1 << 0)));
data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
data |= 1 << 1;
mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
do {
mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb);
data = mmio_read_32(PERI_SC_CLKCFG8BIT1);
} while ((data & 0xb) != 0xb);
}
static void reset_mmc0_clk(void)
{
unsigned int data;
/* disable mmc0 bus clock */
mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
do {
data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
} while (data & PERI_CLK0_MMC0);
/* enable mmc0 bus clock */
mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
do {
data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
} while (!(data & PERI_CLK0_MMC0));
/* reset mmc0 clock domain */
mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
/* bypass mmc0 clock phase */
data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
data |= 3;
mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
/* disable low power */
data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
data |= 1 << 3;
mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
do {
data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
} while (!(data & PERI_RST0_MMC0));
/* unreset mmc0 clock domain */
mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
do {
data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
} while (data & PERI_RST0_MMC0);
}
static void init_media_clk(void)
{
unsigned int data, value;
data = mmio_read_32(PMCTRL_MEDPLLCTRL);
data |= 1;
mmio_write_32(PMCTRL_MEDPLLCTRL, data);
for (;;) {
data = mmio_read_32(PMCTRL_MEDPLLCTRL);
value = 1 << 28;
if ((data & value) == value)
break;
}
data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
data = 1 << 10;
mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
}
static void init_mmc1_pll(void)
{
uint32_t data;
/* select SYSPLL as the source of MMC1 */
/* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27);
do {
data = mmio_read_32(PERI_SC_CLK_SEL0);
} while (!(data & (1 << 11)));
/* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30);
do {
data = mmio_read_32(PERI_SC_CLK_SEL0);
} while (data & (1 << 14));
mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1));
do {
data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
} while (!(data & (1 << 1)));
data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
data |= 1 << 2;
mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
do {
/* 1.2GHz / 50 = 24MHz */
mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7));
data = mmio_read_32(PERI_SC_CLKCFG8BIT2);
} while ((data & 0x31) != 0x31);
}
static void reset_mmc1_clk(void)
{
unsigned int data;
/* disable mmc1 bus clock */
mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1);
do {
data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
} while (data & PERI_CLK0_MMC1);
/* enable mmc1 bus clock */
mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1);
do {
data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
} while (!(data & PERI_CLK0_MMC1));
/* reset mmc1 clock domain */
mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1);
/* bypass mmc1 clock phase */
data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
data |= 3 << 2;
mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
/* disable low power */
data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
data |= 1 << 4;
mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
do {
data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
} while (!(data & PERI_RST0_MMC1));
/* unreset mmc0 clock domain */
mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1);
do {
data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
} while (data & PERI_RST0_MMC1);
}
/* Initialize PLL of both eMMC and SD controllers. */
static void hikey_mmc_pll_init(void)
{
init_mmc0_pll();
reset_mmc0_clk();
init_media_clk();
dsb();
init_mmc1_pll();
reset_mmc1_clk();
}
/*
* Function which will perform any remaining platform-specific setup that can
* occur after the MMU and data cache have been enabled.
*/
void bl1_platform_setup(void)
{
dw_mmc_params_t params;
assert((HIKEY_BL1_MMC_DESC_BASE >= SRAM_BASE) &&
((SRAM_BASE + SRAM_SIZE) >=
(HIKEY_BL1_MMC_DATA_BASE + HIKEY_BL1_MMC_DATA_SIZE)));
hikey_sp804_init();
hikey_gpio_init();
hikey_pmussi_init();
hikey_hi6553_init();
hikey_mmc_pll_init();
memset(&params, 0, sizeof(dw_mmc_params_t));
params.reg_base = DWMMC0_BASE;
params.desc_base = HIKEY_BL1_MMC_DESC_BASE;
params.desc_size = 1 << 20;
params.clk_rate = 24 * 1000 * 1000;
params.bus_width = EMMC_BUS_WIDTH_8;
params.flags = EMMC_FLAG_CMD23;
dw_mmc_init(&params);
hikey_io_setup();
}
/*
* The following function checks if Firmware update is needed,
* by checking if TOC in FIP image is valid or not.
*/
unsigned int bl1_plat_get_next_image_id(void)
{
int32_t boot_mode;
unsigned int ret;
boot_mode = mmio_read_32(ONCHIPROM_PARAM_BASE);
switch (boot_mode) {
case BOOT_NORMAL:
ret = BL2_IMAGE_ID;
break;
case BOOT_USB_DOWNLOAD:
case BOOT_UART_DOWNLOAD:
ret = NS_BL1U_IMAGE_ID;
break;
default:
WARN("Invalid boot mode is found:%d\n", boot_mode);
panic();
}
return ret;
}
image_desc_t *bl1_plat_get_image_desc(unsigned int image_id)
{
unsigned int index = 0;
while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) {
if (bl1_tbbr_image_descs[index].image_id == image_id)
return &bl1_tbbr_image_descs[index];
index++;
}
return NULL;
}
void bl1_plat_set_ep_info(unsigned int image_id,
entry_point_info_t *ep_info)
{
unsigned int data = 0;
if (image_id == BL2_IMAGE_ID)
return;
inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE);
__asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data));
do {
data |= 3 << 20;
__asm__ volatile ("msr cpacr_el1, %0" : : "r"(data));
__asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data));
} while ((data & (3 << 20)) != (3 << 20));
INFO("cpacr_el1:0x%x\n", data);
ep_info->args.arg0 = 0xffff & read_mpidr();
ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS);
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <console.h>
#include <debug.h>
#include <dw_mmc.h>
#include <emmc.h>
#include <errno.h>
#include <hi6220.h>
#include <hisi_mcu.h>
#include <hisi_sram_map.h>
#include <mmio.h>
#include <platform_def.h>
#include <sp804_delay_timer.h>
#include <string.h>
#include "hikey_def.h"
#include "hikey_private.h"
/*
* The next 2 constants identify the extents of the code & RO data region.
* These addresses are used by the MMU setup code and therefore they must be
* page-aligned. It is the responsibility of the linker script to ensure that
* __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
*/
#define BL2_RO_BASE (unsigned long)(&__RO_START__)
#define BL2_RO_LIMIT (unsigned long)(&__RO_END__)
/*
* The next 2 constants identify the extents of the coherent memory region.
* These addresses are used by the MMU setup code and therefore they must be
* page-aligned. It is the responsibility of the linker script to ensure that
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
* page-aligned addresses.
*/
#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
typedef struct bl2_to_bl31_params_mem {
bl31_params_t bl31_params;
image_info_t bl31_image_info;
image_info_t bl32_image_info;
image_info_t bl33_image_info;
entry_point_info_t bl33_ep_info;
entry_point_info_t bl32_ep_info;
entry_point_info_t bl31_ep_info;
} bl2_to_bl31_params_mem_t;
static bl2_to_bl31_params_mem_t bl31_params_mem;
meminfo_t *bl2_plat_sec_mem_layout(void)
{
return &bl2_tzram_layout;
}
void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo)
{
scp_bl2_meminfo->total_base = SCP_BL2_BASE;
scp_bl2_meminfo->total_size = SCP_BL2_SIZE;
scp_bl2_meminfo->free_base = SCP_BL2_BASE;
scp_bl2_meminfo->free_size = SCP_BL2_SIZE;
}
int bl2_plat_handle_scp_bl2(struct image_info *scp_bl2_image_info)
{
/* Enable MCU SRAM */
hisi_mcu_enable_sram();
/* Load MCU binary into SRAM */
hisi_mcu_load_image(scp_bl2_image_info->image_base,
scp_bl2_image_info->image_size);
/* Let MCU running */
hisi_mcu_start_run();
INFO("%s: MCU PC is at 0x%x\n",
__func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2));
INFO("%s: AO_SC_PERIPH_CLKSTAT4 is 0x%x\n",
__func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4));
return 0;
}
bl31_params_t *bl2_plat_get_bl31_params(void)
{
bl31_params_t *bl2_to_bl31_params = NULL;
/*
* Initialise the memory for all the arguments that needs to
* be passed to BL3-1
*/
memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t));
/* Assign memory for TF related information */
bl2_to_bl31_params = &bl31_params_mem.bl31_params;
SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0);
/* Fill BL3-1 related information */
bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info;
SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY,
VERSION_1, 0);
/* Fill BL3-2 related information if it exists */
#if BL32_BASE
bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP,
VERSION_1, 0);
bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY,
VERSION_1, 0);
#endif
/* Fill BL3-3 related information */
bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info,
PARAM_EP, VERSION_1, 0);
/* BL3-3 expects to receive the primary CPU MPID (through x0) */
bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info;
SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY,
VERSION_1, 0);
return bl2_to_bl31_params;
}
struct entry_point_info *bl2_plat_get_bl31_ep_info(void)
{
return &bl31_params_mem.bl31_ep_info;
}
void bl2_plat_set_bl31_ep_info(image_info_t *image,
entry_point_info_t *bl31_ep_info)
{
SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE);
bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS);
}
void bl2_plat_set_bl33_ep_info(image_info_t *image,
entry_point_info_t *bl33_ep_info)
{
unsigned long el_status;
unsigned int mode;
/* Figure out what mode we enter the non-secure world in */
el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
el_status &= ID_AA64PFR0_ELX_MASK;
if (el_status)
mode = MODE_EL2;
else
mode = MODE_EL1;
/*
* TODO: Consider the possibility of specifying the SPSR in
* the FIP ToC and allowing the platform to have a say as
* well.
*/
bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS);
SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE);
}
void bl2_plat_flush_bl31_params(void)
{
flush_dcache_range((unsigned long)&bl31_params_mem,
sizeof(bl2_to_bl31_params_mem_t));
}
void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
{
bl33_meminfo->total_base = DDR_BASE;
bl33_meminfo->total_size = DDR_SIZE;
bl33_meminfo->free_base = DDR_BASE;
bl33_meminfo->free_size = DDR_SIZE;
}
static void reset_dwmmc_clk(void)
{
unsigned int data;
/* disable mmc0 bus clock */
mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
do {
data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
} while (data & PERI_CLK0_MMC0);
/* enable mmc0 bus clock */
mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
do {
data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
} while (!(data & PERI_CLK0_MMC0));
/* reset mmc0 clock domain */
mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
/* bypass mmc0 clock phase */
data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
data |= 3;
mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
/* disable low power */
data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
data |= 1 << 3;
mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
do {
data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
} while (!(data & PERI_RST0_MMC0));
/* unreset mmc0 clock domain */
mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
do {
data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
} while (data & PERI_RST0_MMC0);
}
static void hikey_boardid_init(void)
{
u_register_t midr;
midr = read_midr();
mmio_write_32(MEMORY_AXI_CHIP_ADDR, midr);
INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR,
(unsigned int)midr);
mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0);
mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b);
mmio_write_32(ACPU_ARM64_FLAGA, 0x1234);
mmio_write_32(ACPU_ARM64_FLAGB, 0x5678);
}
static void hikey_sd_init(void)
{
/* switch pinmux to SD */
mmio_write_32(IOMG_SD_CLK, IOMG_MUX_FUNC0);
mmio_write_32(IOMG_SD_CMD, IOMG_MUX_FUNC0);
mmio_write_32(IOMG_SD_DATA0, IOMG_MUX_FUNC0);
mmio_write_32(IOMG_SD_DATA1, IOMG_MUX_FUNC0);
mmio_write_32(IOMG_SD_DATA2, IOMG_MUX_FUNC0);
mmio_write_32(IOMG_SD_DATA3, IOMG_MUX_FUNC0);
mmio_write_32(IOCG_SD_CLK, IOCG_INPUT_16MA);
mmio_write_32(IOCG_SD_CMD, IOCG_INPUT_12MA);
mmio_write_32(IOCG_SD_DATA0, IOCG_INPUT_12MA);
mmio_write_32(IOCG_SD_DATA1, IOCG_INPUT_12MA);
mmio_write_32(IOCG_SD_DATA2, IOCG_INPUT_12MA);
mmio_write_32(IOCG_SD_DATA3, IOCG_INPUT_12MA);
/* set SD Card detect as nopull */
mmio_write_32(IOCG_GPIO8, 0);
}
static void hikey_jumper_init(void)
{
/* set jumper detect as nopull */
mmio_write_32(IOCG_GPIO24, 0);
/* set jumper detect as GPIO */
mmio_write_32(IOMG_GPIO24, IOMG_MUX_FUNC0);
}
void bl2_early_platform_setup(meminfo_t *mem_layout)
{
dw_mmc_params_t params;
/* Initialize the console to provide early debug support */
console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
/* Setup the BL2 memory layout */
bl2_tzram_layout = *mem_layout;
/* Clear SRAM since it'll be used by MCU right now. */
memset((void *)SRAM_BASE, 0, SRAM_SIZE);
sp804_timer_init(SP804_TIMER0_BASE, 10, 192);
dsb();
hikey_ddr_init();
hikey_boardid_init();
init_acpu_dvfs();
hikey_sd_init();
hikey_jumper_init();
reset_dwmmc_clk();
memset(&params, 0, sizeof(dw_mmc_params_t));
params.reg_base = DWMMC0_BASE;
params.desc_base = HIKEY_MMC_DESC_BASE;
params.desc_size = 1 << 20;
params.clk_rate = 24 * 1000 * 1000;
params.bus_width = EMMC_BUS_WIDTH_8;
params.flags = EMMC_FLAG_CMD23;
dw_mmc_init(&params);
hikey_io_setup();
}
void bl2_plat_arch_setup(void)
{
hikey_init_mmu_el1(bl2_tzram_layout.total_base,
bl2_tzram_layout.total_size,
BL2_RO_BASE,
BL2_RO_LIMIT,
BL2_COHERENT_RAM_BASE,
BL2_COHERENT_RAM_LIMIT);
}
void bl2_platform_setup(void)
{
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arm_gic.h>
#include <assert.h>
#include <bl_common.h>
#include <cci.h>
#include <console.h>
#include <debug.h>
#include <errno.h>
#include <gicv2.h>
#include <hi6220.h>
#include <hisi_ipc.h>
#include <hisi_pwrc.h>
#include <platform_def.h>
#include "hikey_def.h"
#include "hikey_private.h"
/*
* The next 2 constants identify the extents of the code & RO data region.
* These addresses are used by the MMU setup code and therefore they must be
* page-aligned. It is the responsibility of the linker script to ensure that
* __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
*/
#define BL31_RO_BASE (unsigned long)(&__RO_START__)
#define BL31_RO_LIMIT (unsigned long)(&__RO_END__)
/*
* The next 2 constants identify the extents of the coherent memory region.
* These addresses are used by the MMU setup code and therefore they must be
* page-aligned. It is the responsibility of the linker script to ensure that
* __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
* page-aligned addresses.
*/
#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
static entry_point_info_t bl32_ep_info;
static entry_point_info_t bl33_ep_info;
/******************************************************************************
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
* interrupts.
*****************************************************************************/
const unsigned int g0_interrupt_array[] = {
IRQ_SEC_PHY_TIMER,
IRQ_SEC_SGI_0
};
/*
* Ideally `arm_gic_data` structure definition should be a `const` but it is
* kept as modifiable for overwriting with different GICD and GICC base when
* running on FVP with VE memory map.
*/
gicv2_driver_data_t hikey_gic_data = {
.gicd_base = PLAT_ARM_GICD_BASE,
.gicc_base = PLAT_ARM_GICC_BASE,
.g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array),
.g0_interrupt_array = g0_interrupt_array,
};
static const int cci_map[] = {
CCI400_SL_IFACE3_CLUSTER_IX,
CCI400_SL_IFACE4_CLUSTER_IX
};
entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
{
entry_point_info_t *next_image_info;
next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
/* None of the images on this platform can have 0x0 as the entrypoint */
if (next_image_info->pc)
return next_image_info;
return NULL;
}
void bl31_early_platform_setup(bl31_params_t *from_bl2,
void *plat_params_from_bl2)
{
/* Initialize the console to provide early debug support */
console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
/* Initialize CCI driver */
cci_init(CCI400_BASE, cci_map, ARRAY_SIZE(cci_map));
/*
* Copy BL3-2 and BL3-3 entry point information.
* They are stored in Secure RAM, in BL2's address space.
*/
bl32_ep_info = *from_bl2->bl32_ep_info;
bl33_ep_info = *from_bl2->bl33_ep_info;
}
void bl31_plat_arch_setup(void)
{
hikey_init_mmu_el3(BL31_BASE,
BL31_LIMIT - BL31_BASE,
BL31_RO_BASE,
BL31_RO_LIMIT,
BL31_COHERENT_RAM_BASE,
BL31_COHERENT_RAM_LIMIT);
}
void bl31_platform_setup(void)
{
/* Initialize the GIC driver, cpu and distributor interfaces */
gicv2_driver_init(&hikey_gic_data);
gicv2_distif_init();
gicv2_pcpu_distif_init();
gicv2_cpuif_enable();
hisi_ipc_init();
hisi_pwrc_setup();
}
void bl31_plat_runtime_setup(void)
{
}
This diff is collapsed.
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __HIKEY_DEF_H__
#define __HIKEY_DEF_H__
#include <common_def.h>
#include <tbbr_img_def.h>
/* Always assume DDR is 1GB size. */
#define DDR_BASE 0x0
#define DDR_SIZE 0x80000000
#define DEVICE_BASE 0xF4000000
#define DEVICE_SIZE 0x05800000
#define XG2RAM0_BASE 0xF9800000
#define XG2RAM0_SIZE 0x00400000
#define SRAM_BASE 0xFFF80000
#define SRAM_SIZE 0x00012000
/*
* BL1 is stored in XG2RAM0_HIRQ that is 784KB large (0xF980_0000~0xF98C_4000).
*/
#define ONCHIPROM_PARAM_BASE (XG2RAM0_BASE + 0x700)
#define LOADER_RAM_BASE (XG2RAM0_BASE + 0x800)
#define BL1_XG2RAM0_OFFSET 0x1000
/*
* PL011 related constants
*/
#define PL011_UART0_BASE 0xF8015000
#define PL011_UART3_BASE 0xF7113000
#define PL011_BAUDRATE 115200
#define PL011_UART_CLK_IN_HZ 19200000
#define HIKEY_USB_DESC_BASE (DDR_BASE + 0x00800000)
#define HIKEY_USB_DESC_SIZE 0x00100000
#define HIKEY_USB_DATA_BASE (DDR_BASE + 0x10000000)
#define HIKEY_USB_DATA_SIZE 0x10000000
#define HIKEY_FB_BUFFER_BASE (HIKEY_USB_DATA_BASE)
#define HIKEY_FB_BUFFER_SIZE HIKEY_USB_DATA_SIZE
#define HIKEY_FB_DOWNLOAD_BASE (HIKEY_FB_BUFFER_BASE + \
HIKEY_FB_BUFFER_SIZE)
#define HIKEY_FB_DOWNLOAD_SIZE HIKEY_USB_DATA_SIZE
#define HIKEY_USB_DESC_IN_BASE (DDR_BASE + 0x00800000)
#define HIKEY_USB_DESC_IN_SIZE 0x00040000
#define HIKEY_USB_DESC_EP0_OUT_BASE (HIKEY_USB_DESC_IN_BASE + \
HIKEY_USB_DESC_IN_SIZE)
#define HIKEY_USB_DESC_EP0_OUT_SIZE 0x00040000
#define HIKEY_USB_DESC_EPX_OUT_BASE (HIKEY_USB_DESC_EP0_OUT_BASE + \
HIKEY_USB_DESC_EP0_OUT_SIZE)
#define HIKEY_USB_DESC_EPX_OUT_SIZE 0x00080000
#define HIKEY_MMC_DESC_BASE (DDR_BASE + 0x03000000)
#define HIKEY_MMC_DESC_SIZE 0x00100000
/*
* HIKEY_MMC_DATA_BASE & HIKEY_MMC_DATA_SIZE are shared between fastboot
* and eMMC driver. Since it could avoid to memory copy.
* So this SRAM region is used twice. First, it's used in BL1 as temporary
* buffer in eMMC driver. Second, it's used by MCU in BL2. The SRAM region
* needs to be clear before used in BL2.
*/
#define HIKEY_MMC_DATA_BASE (DDR_BASE + 0x10000000)
#define HIKEY_MMC_DATA_SIZE 0x20000000
#define HIKEY_NS_IMAGE_OFFSET (DDR_BASE + 0x35000000)
#define HIKEY_BL1_MMC_DESC_BASE (SRAM_BASE)
#define HIKEY_BL1_MMC_DESC_SIZE 0x00001000
#define HIKEY_BL1_MMC_DATA_BASE (HIKEY_BL1_MMC_DESC_BASE + \
HIKEY_BL1_MMC_DESC_SIZE)
#define HIKEY_BL1_MMC_DATA_SIZE 0x0000B000
#define EMMC_BASE 0
#define HIKEY_FIP_BASE (EMMC_BASE + (4 << 20))
#define HIKEY_FIP_MAX_SIZE (8 << 20)
#define HIKEY_EMMC_RPMB_BASE (EMMC_BASE + 0)
#define HIKEY_EMMC_RPMB_MAX_SIZE (128 << 10)
#define HIKEY_EMMC_USERDATA_BASE (EMMC_BASE + 0)
#define HIKEY_EMMC_USERDATA_MAX_SIZE (4 << 30)
/*
* GIC400 interrupt handling related constants
*/
#define IRQ_SEC_PHY_TIMER 29
#define IRQ_SEC_SGI_0 8
#define IRQ_SEC_SGI_1 9
#define IRQ_SEC_SGI_2 10
#define IRQ_SEC_SGI_3 11
#define IRQ_SEC_SGI_4 12
#define IRQ_SEC_SGI_5 13
#define IRQ_SEC_SGI_6 14
#define IRQ_SEC_SGI_7 15
#define IRQ_SEC_SGI_8 16
#endif /* __HIKEY_DEF_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <debug.h>
#include <emmc.h>
#include <errno.h>
#include <firmware_image_package.h>
#include <io_block.h>
#include <io_driver.h>
#include <io_fip.h>
#include <io_memmap.h>
#include <io_storage.h>
#include <mmio.h>
#include <platform_def.h>
#include <semihosting.h> /* For FOPEN_MODE_... */
#include <string.h>
#include "hikey_private.h"
#define EMMC_BLOCK_SHIFT 9
/* Page 1024, since only a few pages before 2048 are used as partition table */
#define SERIALNO_EMMC_OFFSET (1024 * 512)
struct plat_io_policy {
uintptr_t *dev_handle;
uintptr_t image_spec;
int (*check)(const uintptr_t spec);
};
static const io_dev_connector_t *emmc_dev_con;
static uintptr_t emmc_dev_handle;
static const io_dev_connector_t *fip_dev_con;
static uintptr_t fip_dev_handle;
static int check_emmc(const uintptr_t spec);
static int check_fip(const uintptr_t spec);
static const io_block_spec_t emmc_fip_spec = {
.offset = HIKEY_FIP_BASE,
.length = HIKEY_FIP_MAX_SIZE,
};
static const io_block_dev_spec_t emmc_dev_spec = {
/* It's used as temp buffer in block driver. */
#if IMAGE_BL1
.buffer = {
.offset = HIKEY_BL1_MMC_DATA_BASE,
.length = HIKEY_BL1_MMC_DATA_SIZE,
},
#else
.buffer = {
.offset = HIKEY_MMC_DATA_BASE,
.length = HIKEY_MMC_DATA_SIZE,
},
#endif
.ops = {
.read = emmc_read_blocks,
.write = emmc_write_blocks,
},
.block_size = EMMC_BLOCK_SIZE,
};
static const io_uuid_spec_t bl2_uuid_spec = {
.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
};
static const io_uuid_spec_t bl31_uuid_spec = {
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
};
static const io_uuid_spec_t bl33_uuid_spec = {
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
};
static const io_uuid_spec_t scp_bl2_uuid_spec = {
.uuid = UUID_SCP_FIRMWARE_SCP_BL2,
};
static const struct plat_io_policy policies[] = {
[FIP_IMAGE_ID] = {
&emmc_dev_handle,
(uintptr_t)&emmc_fip_spec,
check_emmc
},
[BL2_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl2_uuid_spec,
check_fip
},
[SCP_BL2_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&scp_bl2_uuid_spec,
check_fip
},
[BL31_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl31_uuid_spec,
check_fip
},
[BL33_IMAGE_ID] = {
&fip_dev_handle,
(uintptr_t)&bl33_uuid_spec,
check_fip
}
};
static int check_emmc(const uintptr_t spec)
{
int result;
uintptr_t local_handle;
result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL);
if (result == 0) {
result = io_open(emmc_dev_handle, spec, &local_handle);
if (result == 0)
io_close(local_handle);
}
return result;
}
static int check_fip(const uintptr_t spec)
{
int result;
uintptr_t local_image_handle;
/* See if a Firmware Image Package is available */
result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
if (result == 0) {
result = io_open(fip_dev_handle, spec, &local_image_handle);
if (result == 0) {
VERBOSE("Using FIP\n");
io_close(local_image_handle);
}
}
return result;
}
void hikey_io_setup(void)
{
int result;
result = register_io_dev_block(&emmc_dev_con);
assert(result == 0);
result = register_io_dev_fip(&fip_dev_con);
assert(result == 0);
result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec,
&emmc_dev_handle);
assert(result == 0);
result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle);
assert(result == 0);
/* Ignore improbable errors in release builds */
(void)result;
}
/* Return an IO device handle and specification which can be used to access
* an image. Use this to enforce platform load policy
*/
int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
uintptr_t *image_spec)
{
int result;
const struct plat_io_policy *policy;
assert(image_id < ARRAY_SIZE(policies));
policy = &policies[image_id];
result = policy->check(policy->image_spec);
assert(result == 0);
*image_spec = policy->image_spec;
*dev_handle = *(policy->dev_handle);
return result;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <cci.h>
#include <debug.h>
#include <gicv2.h>
#include <hi6220.h>
#include <hisi_ipc.h>
#include <hisi_pwrc.h>
#include <hisi_sram_map.h>
#include <mmio.h>
#include <psci.h>
#include "hikey_def.h"
#define HIKEY_CLUSTER_STATE_ON 0
#define HIKEY_CLUSTER_STATE_OFF 1
static uintptr_t hikey_sec_entrypoint;
/* There're two clusters in HiKey. */
static int hikey_cluster_state[] = {HIKEY_CLUSTER_STATE_OFF,
HIKEY_CLUSTER_STATE_OFF};
/*******************************************************************************
* Handler called when a power domain is about to be turned on. The
* level and mpidr determine the affinity instance.
******************************************************************************/
static int hikey_pwr_domain_on(u_register_t mpidr)
{
int cpu, cluster;
int curr_cluster;
cluster = MPIDR_AFFLVL1_VAL(mpidr);
cpu = MPIDR_AFFLVL0_VAL(mpidr);
curr_cluster = MPIDR_AFFLVL1_VAL(read_mpidr());
if (cluster != curr_cluster)
hisi_ipc_cluster_on(cpu, cluster);
hisi_pwrc_set_core_bx_addr(cpu, cluster, hikey_sec_entrypoint);
hisi_ipc_cpu_on(cpu, cluster);
return 0;
}
static void hikey_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
unsigned long mpidr;
int cpu, cluster;
mpidr = read_mpidr();
cluster = MPIDR_AFFLVL1_VAL(mpidr);
cpu = MPIDR_AFFLVL0_VAL(mpidr);
if (hikey_cluster_state[cluster] == HIKEY_CLUSTER_STATE_OFF) {
/*
* Enable CCI coherency for this cluster.
* No need for locks as no other cpu is active at the moment.
*/
cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
hikey_cluster_state[cluster] = HIKEY_CLUSTER_STATE_ON;
}
/* Zero the jump address in the mailbox for this cpu */
hisi_pwrc_set_core_bx_addr(cpu, cluster, 0);
/* Program the GIC per-cpu distributor or re-distributor interface */
gicv2_pcpu_distif_init();
/* Enable the GIC cpu interface */
gicv2_cpuif_enable();
}
/*******************************************************************************
* 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 hikey_pwr_domain_off(const psci_power_state_t *target_state)
{
unsigned long mpidr;
int cpu, cluster;
gicv2_cpuif_disable();
mpidr = read_mpidr();
cluster = MPIDR_AFFLVL1_VAL(mpidr);
cpu = MPIDR_AFFLVL0_VAL(mpidr);
if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
PLAT_MAX_OFF_STATE) {
hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
hisi_ipc_cluster_off(cpu, cluster);
hikey_cluster_state[cluster] = HIKEY_CLUSTER_STATE_OFF;
}
hisi_ipc_cpu_off(cpu, cluster);
}
/*******************************************************************************
* Handler to reboot the system.
******************************************************************************/
static void __dead2 hikey_system_reset(void)
{
/* Send the system reset request */
mmio_write_32(AO_SC_SYS_STAT0, 0x48698284);
isb();
dsb();
wfi();
panic();
}
/*******************************************************************************
* Handler called to check the validity of the power state parameter.
******************************************************************************/
int hikey_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
int pstate = psci_get_pstate_type(power_state);
int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
int i;
assert(req_state);
if (pwr_lvl > PLAT_MAX_PWR_LVL)
return PSCI_E_INVALID_PARAMS;
/* Sanity check the requested state */
if (pstate == PSTATE_TYPE_STANDBY) {
/*
* It's possible to enter standby only on power level 0
* Ignore any other power level.
*/
if (pwr_lvl != MPIDR_AFFLVL0)
return PSCI_E_INVALID_PARAMS;
req_state->pwr_domain_state[MPIDR_AFFLVL0] =
PLAT_MAX_RET_STATE;
} else {
for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
req_state->pwr_domain_state[i] =
PLAT_MAX_OFF_STATE;
}
/*
* We expect the 'state id' to be zero.
*/
if (psci_get_pstate_id(power_state))
return PSCI_E_INVALID_PARAMS;
return PSCI_E_SUCCESS;
}
/*******************************************************************************
* Handler called to check the validity of the non secure entrypoint.
******************************************************************************/
static int hikey_validate_ns_entrypoint(uintptr_t entrypoint)
{
/*
* Check if the non secure entrypoint lies within the non
* secure DRAM.
*/
if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
return PSCI_E_SUCCESS;
return PSCI_E_INVALID_ADDRESS;
}
/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
******************************************************************************/
static const plat_psci_ops_t hikey_psci_ops = {
.cpu_standby = NULL,
.pwr_domain_on = hikey_pwr_domain_on,
.pwr_domain_on_finish = hikey_pwr_domain_on_finish,
.pwr_domain_off = hikey_pwr_domain_off,
.pwr_domain_suspend = NULL,
.pwr_domain_suspend_finish = NULL,
.system_off = NULL,
.system_reset = hikey_system_reset,
.validate_power_state = hikey_validate_power_state,
.validate_ns_entrypoint = hikey_validate_ns_entrypoint,
.get_sys_suspend_power_state = NULL,
};
/*******************************************************************************
* Export the platform specific power ops and initialize Power Controller
******************************************************************************/
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
hikey_sec_entrypoint = sec_entrypoint;
/*
* Initialize PSCI ops struct
*/
*psci_ops = &hikey_psci_ops;
return 0;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __HIKEY_PRIVATE_H__
#define __HIKEY_PRIVATE_H__
#include <bl_common.h>
#define RANDOM_MAX 0x7fffffffffffffff
#define RANDOM_MAGIC 0x9a4dbeaf
struct random_serial_num {
uint64_t magic;
uint64_t data;
char serialno[32];
};
/*
* Function and variable prototypes
*/
void hikey_init_mmu_el1(unsigned long total_base,
unsigned long total_size,
unsigned long ro_start,
unsigned long ro_limit,
unsigned long coh_start,
unsigned long coh_limit);
void hikey_init_mmu_el3(unsigned long total_base,
unsigned long total_size,
unsigned long ro_start,
unsigned long ro_limit,
unsigned long coh_start,
unsigned long coh_limit);
void hikey_ddr_init(void);
void hikey_io_setup(void);
int hikey_get_partition_size(const char *arg, int left, char *response);
int hikey_get_partition_type(const char *arg, int left, char *response);
int hikey_erase(const char *arg);
int hikey_flash(const char *arg);
int hikey_oem(const char *arg);
int hikey_reboot(const char *arg);
const char *hikey_init_serialno(void);
int hikey_read_serialno(struct random_serial_num *serialno);
int hikey_write_serialno(struct random_serial_num *serialno);
void init_acpu_dvfs(void);
#endif /* __HIKEY_PRIVATE_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <platform_def.h>
#include <psci.h>
/*
* The HiKey power domain tree descriptor. The cluster power domains
* are arranged so that when the PSCI generic code creates the power
* domain tree, the indices of the CPU power domain nodes it allocates
* match the linear indices returned by plat_core_pos_by_mpidr().
*/
const unsigned char hikey_power_domain_tree_desc[] = {
/* Number of root nodes */
1,
/* Number of clusters */
PLATFORM_CLUSTER_COUNT,
/* Number of CPU cores */
PLATFORM_CORE_COUNT
};
/*******************************************************************************
* This function returns the HiKey topology tree information.
******************************************************************************/
const unsigned char *plat_get_power_domain_tree_desc(void)
{
return hikey_power_domain_tree_desc;
}
/*******************************************************************************
* This function implements a part of the critical interface between the psci
* generic layer and the platform that allows the former to query the platform
* to convert an MPIDR to a unique linear index. An error code (-1) is returned
* in case the MPIDR is invalid.
******************************************************************************/
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
unsigned int cluster_id, cpu_id;
mpidr &= MPIDR_AFFINITY_MASK;
if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
return -1;
cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
if (cluster_id >= PLATFORM_CLUSTER_COUNT)
return -1;
/*
* Validate cpu_id by checking whether it represents a CPU in
* one of the two clusters present on the platform.
*/
if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER)
return -1;
return (cpu_id + (cluster_id * 4));
}
This diff is collapsed.
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <hisi_ipc.h>
#include <hisi_sram_map.h>
#include <mmio.h>
#include <platform_def.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
static int ipc_init;
static unsigned int cpu_ipc_num[PLATFORM_CLUSTER_COUNT][PLATFORM_CORE_COUNT_PER_CLUSTER] = {
{
HISI_IPC_MCU_INT_SRC_ACPU0_PD,
HISI_IPC_MCU_INT_SRC_ACPU1_PD,
HISI_IPC_MCU_INT_SRC_ACPU2_PD,
HISI_IPC_MCU_INT_SRC_ACPU3_PD,
},
{
HISI_IPC_MCU_INT_SRC_ACPU4_PD,
HISI_IPC_MCU_INT_SRC_ACPU5_PD,
HISI_IPC_MCU_INT_SRC_ACPU6_PD,
HISI_IPC_MCU_INT_SRC_ACPU7_PD,
}
};
int hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu,
unsigned int cluster)
{
unsigned int val = 0, cpu_val = 0;
int i;
val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
val = val >> (cluster * 16);
for (i = 0; i < PLATFORM_CORE_COUNT_PER_CLUSTER; i++) {
if (cpu == i)
continue;
cpu_val = (val >> (i * 4)) & 0xF;
if (cpu_val == 0x8)
return 0;
}
return 1;
}
int hisi_cpus_powered_off_besides_curr(unsigned int cpu)
{
unsigned int val;
val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
return (val == (0x8 << (cpu * 4)));
}
static void hisi_ipc_send(unsigned int ipc_num)
{
if (!ipc_init) {
printf("error ipc base is null!!!\n");
return;
}
mmio_write_32(HISI_IPC_CPU_RAW_INT_ADDR, 1 << ipc_num);
}
void hisi_ipc_spin_lock(unsigned int signal)
{
unsigned int hs_ctrl;
if (signal >= HISI_IPC_INT_SRC_NUM)
return;
do {
hs_ctrl = mmio_read_32(HISI_IPC_ACPU_CTRL(signal));
} while (hs_ctrl);
}
void hisi_ipc_spin_unlock(unsigned int signal)
{
if (signal >= HISI_IPC_INT_SRC_NUM)
return;
mmio_write_32(HISI_IPC_ACPU_CTRL(signal), 0);
}
void hisi_ipc_cpu_on_off(unsigned int cpu, unsigned int cluster,
unsigned int mode)
{
unsigned int val = 0;
unsigned int offset;
if (mode == HISI_IPC_PM_ON)
offset = cluster * 16 + cpu * 4;
else
offset = cluster * 16 + cpu * 4 + 1;
hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
val |= (0x01 << offset);
mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
isb();
dsb();
hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
}
void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster)
{
hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_ON);
}
void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster)
{
hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_OFF);
}
void hisi_ipc_cluster_on_off(unsigned int cpu, unsigned int cluster,
unsigned int mode)
{
unsigned int val = 0;
unsigned int offset;
if (mode == HISI_IPC_PM_ON)
offset = cluster * 4;
else
offset = cluster * 4 + 1;
hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
val |= (0x01 << offset);
mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
isb();
dsb();
hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
}
void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster)
{
hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_ON);
}
void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster)
{
hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_OFF);
}
void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster)
{
unsigned int val = 0;
unsigned int offset;
offset = cluster * 16 + cpu * 4 + 2;
hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
val |= (0x01 << offset);
mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
}
void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster)
{
unsigned int val;
unsigned int offset;
offset = cluster * 4 + 1;
hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
if (hisi_cpus_pd_in_cluster_besides_curr(cpu, cluster)) {
val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
val |= (0x01 << offset);
mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
}
hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
}
void hisi_ipc_psci_system_off(void)
{
hisi_ipc_send(HISI_IPC_MCU_INT_SRC_ACPU_PD);
}
int hisi_ipc_init(void)
{
ipc_init = 1;
mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, 0x8);
mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, 0x8);
return 0;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <console.h>
#include <debug.h>
#include <hi6220.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <string.h>
#define MCU_SECTION_MAX 30
enum MCU_IMAGE_SEC_TYPE_ENUM {
MCU_IMAGE_SEC_TYPE_TEXT = 0, /* text section */
MCU_IMAGE_SEC_TYPE_DATA, /* data section */
MCU_IMAGE_SEC_TYPE_BUTT
};
enum MCU_IMAGE_SEC_LOAD_ENUM {
MCU_IMAGE_SEC_LOAD_STATIC = 0,
MCU_IMAGE_SEC_LOAD_DYNAMIC,
MCU_IMAGE_SEC_LOAD_BUFFER,
MCU_IMAGE_SEC_LOAD_MODEM_ENTRY,
MCU_IMAGE_SEC_LOAD_BUTT
};
struct mcu_image_sec {
unsigned short serial;
char type;
char load_attr;
uint32_t src_offset; /* offset in image */
uint32_t dst_offset; /* offset in memory */
uint32_t size;
};
struct mcu_image_head {
char time_stamp[24];
uint32_t image_size;
uint32_t secs_num;
struct mcu_image_sec secs[MCU_SECTION_MAX];
};
#define SOC_SRAM_M3_BASE_ADDR (0xF6000000)
#define MCU_SRAM_SIZE (0x0000C000)
#define MCU_CACHE_SIZE (0x00004000)
#define MCU_CODE_SIZE (MCU_SRAM_SIZE - MCU_CACHE_SIZE)
#define MCU_SYS_MEM_ADDR (0x05E00000)
#define MCU_SYS_MEM_SIZE (0x00100000)
static uint32_t mcu2ap_addr(uint32_t mcu_addr)
{
if (mcu_addr < MCU_CODE_SIZE)
return (mcu_addr + SOC_SRAM_M3_BASE_ADDR);
else if ((mcu_addr >= MCU_SRAM_SIZE) &&
(mcu_addr < MCU_SRAM_SIZE + MCU_SYS_MEM_SIZE))
return mcu_addr - MCU_SRAM_SIZE + MCU_SYS_MEM_ADDR;
else
return mcu_addr;
}
static int is_binary_header_invalid(struct mcu_image_head *head,
unsigned int length)
{
/* invalid cases */
if ((head->image_size == 0) ||
(head->image_size > length) ||
(head->secs_num > MCU_SECTION_MAX) ||
(head->secs_num == 0))
return 1;
return 0;
}
static int is_binary_section_invalid(struct mcu_image_sec *sec,
struct mcu_image_head *head)
{
unsigned long ap_dst_offset = 0;
if ((sec->serial >= head->secs_num) ||
(sec->src_offset + sec->size > head->image_size))
return 1;
if ((sec->type >= MCU_IMAGE_SEC_TYPE_BUTT) ||
(sec->load_attr >= MCU_IMAGE_SEC_LOAD_BUTT))
return 1;
ap_dst_offset = mcu2ap_addr(sec->dst_offset);
if ((ap_dst_offset >= SOC_SRAM_M3_BASE_ADDR) &&
(ap_dst_offset < SOC_SRAM_M3_BASE_ADDR + 0x20000 - sec->size))
return 0;
else if ((ap_dst_offset >= MCU_SYS_MEM_ADDR) &&
(ap_dst_offset < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE - sec->size))
return 0;
else if ((ap_dst_offset >= 0xfff8e000) &&
(ap_dst_offset < 0xfff91c00 - sec->size))
return 0;
ERROR("%s: mcu destination address invalid.\n", __func__);
ERROR("%s: number=%d, dst offset=%d size=%d\n",
__func__, sec->serial, sec->dst_offset, sec->size);
return 1;
}
void hisi_mcu_enable_sram(void)
{
mmio_write_32(AO_SC_PERIPH_CLKEN4,
AO_SC_PERIPH_CLKEN4_HCLK_IPC_S |
AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS);
/* set register to enable dvfs which is used by mcu */
mmio_write_32(PERI_SC_RESERVED8_ADDR, 0x0A001022);
/* mcu mem is powered on, need de-assert reset */
mmio_write_32(AO_SC_PERIPH_RSTDIS4,
AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N);
/* enable mcu hclk */
mmio_write_32(AO_SC_PERIPH_CLKEN4,
AO_SC_PERIPH_CLKEN4_HCLK_MCU |
AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP);
}
void hisi_mcu_start_run(void)
{
unsigned int val;
/* set mcu ddr remap configuration */
mmio_write_32(AO_SC_MCU_SUBSYS_CTRL2, MCU_SYS_MEM_ADDR);
/* de-assert reset for mcu and to run */
mmio_write_32(AO_SC_PERIPH_RSTDIS4,
AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N |
AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N |
AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N |
AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N);
val = mmio_read_32(AO_SC_SYS_CTRL2);
mmio_write_32(AO_SC_SYS_CTRL2,
val | AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR);
INFO("%s: AO_SC_SYS_CTRL2=%x\n", __func__,
mmio_read_32(AO_SC_SYS_CTRL2));
}
int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size)
{
unsigned int i;
struct mcu_image_head *head;
char *buf;
head = (struct mcu_image_head *)image_base;
if (is_binary_header_invalid(head, image_size)) {
ERROR("Invalid %s image header.\n", head->time_stamp);
return -1;
}
buf = (char *)head;
for (i = 0; i < head->secs_num; i++) {
int *src, *dst;
/* check the sections */
if (is_binary_section_invalid(&head->secs[i], head)) {
ERROR("Invalid mcu section.\n");
return -1;
}
/* check if the section is static-loaded */
if (head->secs[i].load_attr != MCU_IMAGE_SEC_LOAD_STATIC)
continue;
/* copy the sections */
src = (int *)(intptr_t)(buf + head->secs[i].src_offset);
dst = (int *)(intptr_t)mcu2ap_addr(head->secs[i].dst_offset);
memcpy((void *)dst, (void *)src, head->secs[i].size);
INFO("%s: mcu sections %d:\n", __func__, i);
INFO("%s: src = 0x%x\n",
__func__, (unsigned int)(uintptr_t)src);
INFO("%s: dst = 0x%x\n",
__func__, (unsigned int)(uintptr_t)dst);
INFO("%s: size = %d\n", __func__, head->secs[i].size);
INFO("%s: [SRC 0x%x] 0x%x 0x%x 0x%x 0x%x\n",
__func__, (unsigned int)(uintptr_t)src,
src[0], src[1], src[2], src[3]);
INFO("%s: [DST 0x%x] 0x%x 0x%x 0x%x 0x%x\n",
__func__, (unsigned int)(uintptr_t)dst,
dst[0], dst[1], dst[2], dst[3]);
}
return 0;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include <mmio.h>
#include <hisi_ipc.h>
#include <hisi_pwrc.h>
#include <hisi_sram_map.h>
#include <hi6220_regs_acpu.h>
#include <hi6220_regs_ao.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <platform_def.h>
#define CLUSTER_CORE_COUNT (4)
#define CLUSTER_CORE_MASK ((1 << CLUSTER_CORE_COUNT) - 1)
void hisi_pwrc_set_core_bx_addr(unsigned int core, unsigned int cluster,
uintptr_t entry_point)
{
uintptr_t *core_entry = (uintptr_t *)PWRCTRL_ACPU_ASM_D_ARM_PARA_AD;
unsigned int i;
if (!core_entry) {
INFO("%s: core entry point is null!\n", __func__);
return;
}
i = cluster * CLUSTER_CORE_COUNT + core;
mmio_write_64((uintptr_t)(core_entry + i), entry_point);
}
void hisi_pwrc_set_cluster_wfi(unsigned int cluster)
{
unsigned int reg = 0;
if (cluster == 0) {
reg = mmio_read_32(ACPU_SC_SNOOP_PWD);
reg |= PD_DETECT_START0;
mmio_write_32(ACPU_SC_SNOOP_PWD, reg);
} else if (cluster == 1) {
reg = mmio_read_32(ACPU_SC_SNOOP_PWD);
reg |= PD_DETECT_START1;
mmio_write_32(ACPU_SC_SNOOP_PWD, reg);
}
}
int hisi_pwrc_setup(void)
{
unsigned int reg, sec_entrypoint;
extern char pm_asm_code[], pm_asm_code_end[];
extern char v7_asm[], v7_asm_end[];
sec_entrypoint = PWRCTRL_ACPU_ASM_CODE_BASE;
mmio_write_32(ACPU_SC_CPUx_RVBARADDR(0), sec_entrypoint >> 2);
mmio_write_32(ACPU_SC_CPUx_RVBARADDR(1), sec_entrypoint >> 2);
mmio_write_32(ACPU_SC_CPUx_RVBARADDR(2), sec_entrypoint >> 2);
mmio_write_32(ACPU_SC_CPUx_RVBARADDR(3), sec_entrypoint >> 2);
mmio_write_32(ACPU_SC_CPUx_RVBARADDR(4), sec_entrypoint >> 2);
mmio_write_32(ACPU_SC_CPUx_RVBARADDR(5), sec_entrypoint >> 2);
mmio_write_32(ACPU_SC_CPUx_RVBARADDR(6), sec_entrypoint >> 2);
mmio_write_32(ACPU_SC_CPUx_RVBARADDR(7), sec_entrypoint >> 2);
memset((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, 0, 0x400);
memcpy((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, (void *)v7_asm,
v7_asm_end - v7_asm);
memcpy((void *)PWRCTRL_ACPU_ASM_CODE_BASE, (void *)pm_asm_code,
pm_asm_code_end - pm_asm_code);
reg = mmio_read_32(AO_SC_SYS_CTRL1);
reg |= AO_SC_SYS_CTRL1_REMAP_SRAM_AARM |
AO_SC_SYS_CTRL1_REMAP_SRAM_AARM_MSK;
mmio_write_32(AO_SC_SYS_CTRL1, reg);
return 0;
}
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <cortex_a53.h>
#include <hi6220.h>
#include <hisi_sram_map.h>
.global pm_asm_code
.global pm_asm_code_end
.global v7_asm
.global v7_asm_end
.align 3
func pm_asm_code
mov x0, 0
msr oslar_el1, x0
mrs x0, CPUACTLR_EL1
bic x0, x0, #(CPUACTLR_RADIS | CPUACTLR_L1RADIS)
orr x0, x0, #0x180000
orr x0, x0, #0xe000
msr CPUACTLR_EL1, x0
mrs x3, actlr_el3
orr x3, x3, #ACTLR_EL3_L2ECTLR_BIT
msr actlr_el3, x3
mrs x3, actlr_el2
orr x3, x3, #ACTLR_EL2_L2ECTLR_BIT
msr actlr_el2, x3
ldr x3, =PWRCTRL_ACPU_ASM_D_ARM_PARA_AD
mrs x0, mpidr_el1
and x1, x0, #MPIDR_CPU_MASK
and x0, x0, #MPIDR_CLUSTER_MASK
add x0, x1, x0, LSR #6
pen: ldr x4, [x3, x0, LSL #3]
cbz x4, pen
mov x0, #0x0
mov x1, #0x0
mov x2, #0x0
mov x3, #0x0
br x4
.ltorg
pm_asm_code_end:
endfunc pm_asm_code
/*
* By default, all cores in Hi6220 reset with aarch32 mode.
* Now hardcode ARMv7 instructions to execute warm reset for
* switching aarch64 mode.
*/
.align 3
.section .rodata.v7_asm, "aS"
v7_asm:
.word 0xE1A00000 // nop
.word 0xE3A02003 // mov r2, #3
.word 0xEE0C2F50 // mcr 15, 0, r2, cr12, cr0, {2}
.word 0xE320F003 // wfi
.ltorg
v7_asm_end:
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __HI6220_H__
#define __HI6220_H__
#include <hi6220_regs_acpu.h>
#include <hi6220_regs_ao.h>
#include <hi6220_regs_peri.h>
#include <hi6220_regs_pin.h>
#include <hi6220_regs_pmctrl.h>
/*******************************************************************************
* Implementation defined ACTLR_EL2 bit definitions
******************************************************************************/
#define ACTLR_EL2_L2ACTLR_BIT (1 << 6)
#define ACTLR_EL2_L2ECTLR_BIT (1 << 5)
#define ACTLR_EL2_L2CTLR_BIT (1 << 4)
#define ACTLR_EL2_CPUECTLR_BIT (1 << 1)
#define ACTLR_EL2_CPUACTLR_BIT (1 << 0)
/*******************************************************************************
* Implementation defined ACTLR_EL3 bit definitions
******************************************************************************/
#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
#define ACTLR_EL3_L2ECTLR_BIT (1 << 5)
#define ACTLR_EL3_L2CTLR_BIT (1 << 4)
#define ACTLR_EL3_CPUECTLR_BIT (1 << 1)
#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
/*******************************************************************************
* CCI-400 related constants
******************************************************************************/
#define CCI400_BASE 0xF6E90000
#define CCI400_SL_IFACE3_CLUSTER_IX 3
#define CCI400_SL_IFACE4_CLUSTER_IX 4
#define DWMMC0_BASE 0xF723D000
#define DWUSB_BASE 0xF72C0000
#define PMUSSI_BASE 0xF8000000
#define SP804_TIMER0_BASE 0xF8008000
#define GPIO0_BASE 0xF8011000
#define GPIO1_BASE 0xF8012000
#define GPIO2_BASE 0xF8013000
#define GPIO3_BASE 0xF8014000
#define GPIO4_BASE 0xF7020000
#define GPIO5_BASE 0xF7021000
#define GPIO6_BASE 0xF7022000
#define GPIO7_BASE 0xF7023000
#define GPIO8_BASE 0xF7024000
#define GPIO9_BASE 0xF7025000
#define GPIO10_BASE 0xF7026000
#define GPIO11_BASE 0xF7027000
#define GPIO12_BASE 0xF7028000
#define GPIO13_BASE 0xF7029000
#define GPIO14_BASE 0xF702A000
#define GPIO15_BASE 0xF702B000
#define GPIO16_BASE 0xF702C000
#define GPIO17_BASE 0xF702D000
#define GPIO18_BASE 0xF702E000
#define GPIO19_BASE 0xF702F000
#endif /* __HI6220_H__ */
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __HI6220_REGS_ACPU_H__
#define __HI6220_REGS_ACPU_H__
#define ACPU_CTRL_BASE 0xF6504000
#define ACPU_SC_CPU_CTRL (ACPU_CTRL_BASE + 0x000)
#define ACPU_SC_CPU_STAT (ACPU_CTRL_BASE + 0x008)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2 (1 << 0)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2_SHIFT (0)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0 (1 << 1)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0_SHIFT (1)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1 (1 << 2)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1_SHIFT (2)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2 (1 << 3)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2_SHIFT (3)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3 (1 << 4)
#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3_SHIFT (4)
#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2 (1 << 8)
#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2_SHIFT (8)
#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI (1 << 9)
#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI_SHIFT (9)
#define ACPU_SC_CPU_STAT_L2FLSHUDONE0 (1 << 16)
#define ACPU_SC_CPU_STAT_L2FLSHUDONE0_SHIFT (16)
#define ACPU_SC_CPU_STAT_L2FLSHUDONE1 (1 << 17)
#define ACPU_SC_CPU_STAT_L2FLSHUDONE1_SHIFT (17)
#define ACPU_SC_CPU_STAT_CCI400_ACTIVE (1 << 18)
#define ACPU_SC_CPU_STAT_CCI400_ACTIVE_SHIFT (18)
#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD (1 << 20)
#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT (20)
#define ACPU_SC_CLKEN (ACPU_CTRL_BASE + 0x00c)
#define HPM_L2_1_CLKEN (1 << 9)
#define G_CPU_1_CLKEN (1 << 8)
#define HPM_L2_CLKEN (1 << 1)
#define G_CPU_CLKEN (1 << 0)
#define ACPU_SC_CLKDIS (ACPU_CTRL_BASE + 0x010)
#define ACPU_SC_CLK_STAT (ACPU_CTRL_BASE + 0x014)
#define ACPU_SC_RSTEN (ACPU_CTRL_BASE + 0x018)
#define SRST_PRESET1_RSTEN (1 << 11)
#define SRST_PRESET0_RSTEN (1 << 10)
#define SRST_CLUSTER1_RSTEN (1 << 9)
#define SRST_CLUSTER0_RSTEN (1 << 8)
#define SRST_L2_HPM_1_RSTEN (1 << 5)
#define SRST_AARM_L2_1_RSTEN (1 << 4)
#define SRST_L2_HPM_0_RSTEN (1 << 3)
#define SRST_AARM_L2_0_RSTEN (1 << 1)
#define SRST_CLUSTER1 (SRST_PRESET1_RSTEN | \
SRST_CLUSTER1_RSTEN | \
SRST_L2_HPM_1_RSTEN | \
SRST_AARM_L2_1_RSTEN)
#define SRST_CLUSTER0 (SRST_PRESET0_RSTEN | \
SRST_CLUSTER0_RSTEN | \
SRST_L2_HPM_0_RSTEN | \
SRST_AARM_L2_0_RSTEN)
#define ACPU_SC_RSTDIS (ACPU_CTRL_BASE + 0x01c)
#define ACPU_SC_RST_STAT (ACPU_CTRL_BASE + 0x020)
#define ACPU_SC_PDBGUP_MBIST (ACPU_CTRL_BASE + 0x02c)
#define PDBGUP_CLUSTER1_SHIFT 8
#define ACPU_SC_VD_CTRL (ACPU_CTRL_BASE + 0x054)
#define ACPU_SC_VD_MASK_PATTERN_CTRL (ACPU_CTRL_BASE + 0x058)
#define ACPU_SC_VD_MASK_PATTERN_VAL (0xCCB << 12)
#define ACPU_SC_VD_MASK_PATTERN_MASK ((0x1 << 13) - 1)
#define ACPU_SC_VD_DLY_FIXED_CTRL (ACPU_CTRL_BASE + 0x05c)
#define ACPU_SC_VD_DLY_TABLE0_CTRL (ACPU_CTRL_BASE + 0x060)
#define ACPU_SC_VD_DLY_TABLE1_CTRL (ACPU_CTRL_BASE + 0x064)
#define ACPU_SC_VD_DLY_TABLE2_CTRL (ACPU_CTRL_BASE + 0x068)
#define ACPU_SC_VD_HPM_CTRL (ACPU_CTRL_BASE + 0x06c)
#define ACPU_SC_A53_CLUSTER_MTCMOS_EN (ACPU_CTRL_BASE + 0x088)
#define PW_MTCMOS_EN_A53_1_EN (1 << 1)
#define PW_MTCMOS_EN_A53_0_EN (1 << 0)
#define ACPU_SC_A53_CLUSTER_MTCMOS_STA (ACPU_CTRL_BASE + 0x090)
#define ACPU_SC_A53_CLUSTER_ISO_EN (ACPU_CTRL_BASE + 0x098)
#define PW_ISO_A53_1_EN (1 << 1)
#define PW_ISO_A53_0_EN (1 << 0)
#define ACPU_SC_A53_CLUSTER_ISO_DIS (ACPU_CTRL_BASE + 0x09c)
#define ACPU_SC_A53_CLUSTER_ISO_STA (ACPU_CTRL_BASE + 0x0a0)
#define ACPU_SC_A53_1_MTCMOS_TIMER (ACPU_CTRL_BASE + 0x0b4)
#define ACPU_SC_A53_0_MTCMOS_TIMER (ACPU_CTRL_BASE + 0x0bc)
#define ACPU_SC_A53_x_MTCMOS_TIMER(x) ((x) ? ACPU_SC_A53_1_MTCMOS_TIMER : ACPU_SC_A53_0_MTCMOS_TIMER)
#define ACPU_SC_SNOOP_PWD (ACPU_CTRL_BASE + 0xe4)
#define PD_DETECT_START1 (1 << 16)
#define PD_DETECT_START0 (1 << 0)
#define ACPU_SC_CPU0_CTRL (ACPU_CTRL_BASE + 0x100)
#define CPU_CTRL_AARCH64_MODE (1 << 7)
#define ACPU_SC_CPU0_STAT (ACPU_CTRL_BASE + 0x104)
#define ACPU_SC_CPU0_CLKEN (ACPU_CTRL_BASE + 0x108)
#define CPU_CLKEN_HPM (1 << 1)
#define ACPU_SC_CPU0_CLK_STAT (ACPU_CTRL_BASE + 0x110)
#define ACPU_SC_CPU0_RSTEN (ACPU_CTRL_BASE + 0x114)
#define ACPU_SC_CPU0_RSTDIS (ACPU_CTRL_BASE + 0x118)
#define ACPU_SC_CPU0_MTCMOS_EN (ACPU_CTRL_BASE + 0x120)
#define CPU_MTCMOS_PW (1 << 0)
#define ACPU_SC_CPU0_PW_ISOEN (ACPU_CTRL_BASE + 0x130)
#define CPU_PW_ISO (1 << 0)
#define ACPU_SC_CPU0_PW_ISODIS (ACPU_CTRL_BASE + 0x134)
#define ACPU_SC_CPU0_PW_ISO_STAT (ACPU_CTRL_BASE + 0x138)
#define ACPU_SC_CPU0_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x154)
#define CPU_MTCMOS_TIMER_STA (1 << 0)
#define ACPU_SC_CPU0_RVBARADDR (ACPU_CTRL_BASE + 0x158)
#define ACPU_SC_CPU1_CTRL (ACPU_CTRL_BASE + 0x200)
#define ACPU_SC_CPU1_STAT (ACPU_CTRL_BASE + 0x204)
#define ACPU_SC_CPU1_CLKEN (ACPU_CTRL_BASE + 0x208)
#define ACPU_SC_CPU1_CLK_STAT (ACPU_CTRL_BASE + 0x210)
#define ACPU_SC_CPU1_RSTEN (ACPU_CTRL_BASE + 0x214)
#define ACPU_SC_CPU1_RSTDIS (ACPU_CTRL_BASE + 0x218)
#define ACPU_SC_CPU1_MTCMOS_EN (ACPU_CTRL_BASE + 0x220)
#define ACPU_SC_CPU1_PW_ISODIS (ACPU_CTRL_BASE + 0x234)
#define ACPU_SC_CPU1_PW_ISO_STAT (ACPU_CTRL_BASE + 0x238)
#define ACPU_SC_CPU1_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x254)
#define ACPU_SC_CPU1_RVBARADDR (ACPU_CTRL_BASE + 0x258)
#define ACPU_SC_CPU2_CTRL (ACPU_CTRL_BASE + 0x300)
#define ACPU_SC_CPU2_STAT (ACPU_CTRL_BASE + 0x304)
#define ACPU_SC_CPU2_CLKEN (ACPU_CTRL_BASE + 0x308)
#define ACPU_SC_CPU2_CLK_STAT (ACPU_CTRL_BASE + 0x310)
#define ACPU_SC_CPU2_RSTEN (ACPU_CTRL_BASE + 0x314)
#define ACPU_SC_CPU2_RSTDIS (ACPU_CTRL_BASE + 0x318)
#define ACPU_SC_CPU2_MTCMOS_EN (ACPU_CTRL_BASE + 0x320)
#define ACPU_SC_CPU2_PW_ISODIS (ACPU_CTRL_BASE + 0x334)
#define ACPU_SC_CPU2_PW_ISO_STAT (ACPU_CTRL_BASE + 0x338)
#define ACPU_SC_CPU2_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x354)
#define ACPU_SC_CPU2_RVBARADDR (ACPU_CTRL_BASE + 0x358)
#define ACPU_SC_CPU3_CTRL (ACPU_CTRL_BASE + 0x400)
#define ACPU_SC_CPU3_STAT (ACPU_CTRL_BASE + 0x404)
#define ACPU_SC_CPU3_CLKEN (ACPU_CTRL_BASE + 0x408)
#define ACPU_SC_CPU3_CLK_STAT (ACPU_CTRL_BASE + 0x410)
#define ACPU_SC_CPU3_RSTEN (ACPU_CTRL_BASE + 0x414)
#define ACPU_SC_CPU3_RSTDIS (ACPU_CTRL_BASE + 0x418)
#define ACPU_SC_CPU3_MTCMOS_EN (ACPU_CTRL_BASE + 0x420)
#define ACPU_SC_CPU3_PW_ISODIS (ACPU_CTRL_BASE + 0x434)
#define ACPU_SC_CPU3_PW_ISO_STAT (ACPU_CTRL_BASE + 0x438)
#define ACPU_SC_CPU3_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x454)
#define ACPU_SC_CPU3_RVBARADDR (ACPU_CTRL_BASE + 0x458)
#define ACPU_SC_CPU4_CTRL (ACPU_CTRL_BASE + 0x500)
#define ACPU_SC_CPU4_STAT (ACPU_CTRL_BASE + 0x504)
#define ACPU_SC_CPU4_CLKEN (ACPU_CTRL_BASE + 0x508)
#define ACPU_SC_CPU4_CLK_STAT (ACPU_CTRL_BASE + 0x510)
#define ACPU_SC_CPU4_RSTEN (ACPU_CTRL_BASE + 0x514)
#define ACPU_SC_CPU4_RSTDIS (ACPU_CTRL_BASE + 0x518)
#define ACPU_SC_CPU4_MTCMOS_EN (ACPU_CTRL_BASE + 0x520)
#define ACPU_SC_CPU4_PW_ISODIS (ACPU_CTRL_BASE + 0x534)
#define ACPU_SC_CPU4_PW_ISO_STAT (ACPU_CTRL_BASE + 0x538)
#define ACPU_SC_CPU4_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x554)
#define ACPU_SC_CPU4_RVBARADDR (ACPU_CTRL_BASE + 0x558)
#define ACPU_SC_CPU5_CTRL (ACPU_CTRL_BASE + 0x600)
#define ACPU_SC_CPU5_STAT (ACPU_CTRL_BASE + 0x604)
#define ACPU_SC_CPU5_CLKEN (ACPU_CTRL_BASE + 0x608)
#define ACPU_SC_CPU5_CLK_STAT (ACPU_CTRL_BASE + 0x610)
#define ACPU_SC_CPU5_RSTEN (ACPU_CTRL_BASE + 0x614)
#define ACPU_SC_CPU5_RSTDIS (ACPU_CTRL_BASE + 0x618)
#define ACPU_SC_CPU5_MTCMOS_EN (ACPU_CTRL_BASE + 0x620)
#define ACPU_SC_CPU5_PW_ISODIS (ACPU_CTRL_BASE + 0x634)
#define ACPU_SC_CPU5_PW_ISO_STAT (ACPU_CTRL_BASE + 0x638)
#define ACPU_SC_CPU5_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x654)
#define ACPU_SC_CPU5_RVBARADDR (ACPU_CTRL_BASE + 0x658)
#define ACPU_SC_CPU6_CTRL (ACPU_CTRL_BASE + 0x700)
#define ACPU_SC_CPU6_STAT (ACPU_CTRL_BASE + 0x704)
#define ACPU_SC_CPU6_CLKEN (ACPU_CTRL_BASE + 0x708)
#define ACPU_SC_CPU6_CLK_STAT (ACPU_CTRL_BASE + 0x710)
#define ACPU_SC_CPU6_RSTEN (ACPU_CTRL_BASE + 0x714)
#define ACPU_SC_CPU6_RSTDIS (ACPU_CTRL_BASE + 0x718)
#define ACPU_SC_CPU6_MTCMOS_EN (ACPU_CTRL_BASE + 0x720)
#define ACPU_SC_CPU6_PW_ISODIS (ACPU_CTRL_BASE + 0x734)
#define ACPU_SC_CPU6_PW_ISO_STAT (ACPU_CTRL_BASE + 0x738)
#define ACPU_SC_CPU6_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x754)
#define ACPU_SC_CPU6_RVBARADDR (ACPU_CTRL_BASE + 0x758)
#define ACPU_SC_CPU7_CTRL (ACPU_CTRL_BASE + 0x800)
#define ACPU_SC_CPU7_STAT (ACPU_CTRL_BASE + 0x804)
#define ACPU_SC_CPU7_CLKEN (ACPU_CTRL_BASE + 0x808)
#define ACPU_SC_CPU7_CLK_STAT (ACPU_CTRL_BASE + 0x810)
#define ACPU_SC_CPU7_RSTEN (ACPU_CTRL_BASE + 0x814)
#define ACPU_SC_CPU7_RSTDIS (ACPU_CTRL_BASE + 0x818)
#define ACPU_SC_CPU7_MTCMOS_EN (ACPU_CTRL_BASE + 0x820)
#define ACPU_SC_CPU7_PW_ISODIS (ACPU_CTRL_BASE + 0x834)
#define ACPU_SC_CPU7_PW_ISO_STAT (ACPU_CTRL_BASE + 0x838)
#define ACPU_SC_CPU7_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x854)
#define ACPU_SC_CPU7_RVBARADDR (ACPU_CTRL_BASE + 0x858)
#define ACPU_SC_CPUx_CTRL(x) ((x < 8) ? (ACPU_SC_CPU0_CTRL + 0x100 * x) : ACPU_SC_CPU0_CTRL)
#define ACPU_SC_CPUx_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_STAT + 0x100 * x) : ACPU_SC_CPU0_STAT)
#define ACPU_SC_CPUx_CLKEN(x) ((x < 8) ? (ACPU_SC_CPU0_CLKEN + 0x100 * x) : ACPU_SC_CPU0_CLKEN)
#define ACPU_SC_CPUx_CLK_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_CLK_STAT + 0x100 * x) : ACPU_SC_CPU0_CLK_STAT)
#define ACPU_SC_CPUx_RSTEN(x) ((x < 8) ? (ACPU_SC_CPU0_RSTEN + 0x100 * x) : ACPU_SC_CPU0_RSTEN)
#define ACPU_SC_CPUx_RSTDIS(x) ((x < 8) ? (ACPU_SC_CPU0_RSTDIS + 0x100 * x) : ACPU_SC_CPU0_RSTDIS)
#define ACPU_SC_CPUx_MTCMOS_EN(x) ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_EN + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_EN)
#define ACPU_SC_CPUx_PW_ISODIS(x) ((x < 8) ? (ACPU_SC_CPU0_PW_ISODIS + 0x100 * x) : ACPU_SC_CPU0_PW_ISODIS)
#define ACPU_SC_CPUx_PW_ISO_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_PW_ISO_STAT + 0x100 * x) : ACPU_SC_CPU0_PW_ISO_STAT)
#define ACPU_SC_CPUx_MTCMOS_TIMER_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_TIMER_STAT + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_TIMER_STAT)
#define ACPU_SC_CPUx_RVBARADDR(x) ((x < 8) ? (ACPU_SC_CPU0_RVBARADDR + 0x100 * x) : ACPU_SC_CPU0_RVBARADDR)
#define ACPU_SC_CPU_STAT_CLKDIV_VD_MASK (3 << 20)
#define ACPU_SC_VD_CTRL_TUNE_EN_DIF (1 << 0)
#define ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT (0)
#define ACPU_SC_VD_CTRL_TUNE (1 << 1)
#define ACPU_SC_VD_CTRL_TUNE_SHIFT (1)
#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF (1 << 7)
#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT (7)
#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI (1 << 8)
#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT (8)
#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR (1 << 9)
#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR_SHIFT (9)
#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN (1 << 10)
#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT (10)
#define ACPU_SC_VD_CTRL_TUNE_EN_INT (1 << 11)
#define ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT (11)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE0 (1 << 12)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_MASK (0xf << 12)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT (12)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE1 (1 << 16)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_MASK (0xf << 16)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT (16)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE2 (1 << 20)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_MASK (0xf << 20)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT (20)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE3 (1 << 24)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_MASK (0xf << 24)
#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT (24)
#define ACPU_SC_VD_CTRL_FORCE_CLK_EN (1 << 28)
#define ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT (28)
#define ACPU_SC_VD_CTRL_DIV_EN_DIF (1 << 29)
#define ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT (29)
#define ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL \
((0x1 << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) | \
(0x3 << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) | \
(0x5 << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) | \
(0x6 << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) | \
(0x7 << ACPU_SC_VD_CTRL_TUNE_SHIFT))
#define ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK \
((0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) | \
(0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) | \
(0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) | \
(0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) | \
(0x3F << ACPU_SC_VD_CTRL_TUNE_SHIFT))
#define ACPU_SC_VD_HPM_CTRL_OSC_DIV (1 << 0)
#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT (0)
#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK (0x000000FF)
#define ACPU_SC_VD_HPM_CTRL_DLY_EXP (1 << 8)
#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT (8)
#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK (0x001FFF00)
#define HPM_OSC_DIV_VAL \
(0x56 << ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT)
#define HPM_OSC_DIV_MASK \
(ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK)
#define HPM_DLY_EXP_VAL \
(0xC7A << ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT)
#define HPM_DLY_EXP_MASK \
(ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK)
#define ACPU_SC_VD_EN_ASIC_VAL \
((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \
(0X0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \
(0X0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT))
#define ACPU_SC_VD_EN_SFT_VAL \
((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \
(0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT))
#define ACPU_SC_VD_EN_MASK \
((0x1 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \
(0x1 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \
(0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \
(0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \
(0x1 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \
(0x1 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \
(0x1 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT))
#endif /* __HI6220_REGS_ACPU_H__ */
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