diff options
57 files changed, 5057 insertions, 422 deletions
diff --git a/contributing.md b/contributing.md index 9a253ca7..65d2ca87 100644 --- a/contributing.md +++ b/contributing.md @@ -44,8 +44,22 @@ Making Changes * Where appropriate, please update the documentation. * Consider whether the [User Guide], [Porting Guide], [Firmware Design] or other in-source documentation needs updating. - * If this is your first contribution, you may add your name or your - company name to the [Acknowledgements] file. + * Ensure that each changed file has the correct copyright and license + information. Files that entirely consist of contributions to this + project should have the copyright notice and BSD-3-Clause SPDX license + identifier as shown in [license.md](./license.md). Files that contain + changes to imported Third Party IP should contain a notice as follows, + with the original copyright and license text retained: + ``` + Portions copyright (c) [XXXX-]YYYY, ARM Limited and Contributors. All rights reserved. + ``` + where XXXX is the year of first contribution (if different to YYYY) and + YYYY is the year of most recent contribution. + * If not done previously, you may add your name or your company name to + the [Acknowledgements] file. + * If you are submitting new files that you intend to be the technical + sub-maintainer for (for example, a new platform port), then also update + the [Maintainers] file. * For topics with multiple commits, you should make all documentation changes (and nothing else) in the last commit of the series. Otherwise, include the documentation changes within the single commit. @@ -66,27 +80,28 @@ Submitting Changes * Push your local changes to your fork of the repository. * Submit a [pull request] to the [arm-trusted-firmware] `integration` branch. * The changes in the [pull request] will then undergo further review and - testing. Any review comments will be made as comments on the [pull - request]. This may require you to do some rework. -* When the changes are accepted, ARM will integrate them. - * Typically, ARM will merge the [pull request] into the `integration` - branch within the GitHub UI, creating a merge commit. + testing by the [Maintainers]. Any review comments will be made as + comments on the [pull request]. This may require you to do some rework. +* When the changes are accepted, the [Maintainers] will integrate them. + * Typically, the [Maintainers] will merge the [pull request] into the + `integration` branch within the GitHub UI, creating a merge commit. * Please avoid creating merge commits in the [pull request] itself. - * If the [pull request] is not based on a recent commit, ARM may rebase - it onto the `master` branch first, or ask you to do this. - * If the [pull request] cannot be automatically merged, ARM will ask you - to rebase it onto the `master` branch. - * After final integration testing, ARM will push your merge commit to the - `master` branch. If a problem is found at this stage, the merge commit - will be removed from the `integration` branch and ARM will ask you to - create a new pull request to resolve the problem. + * If the [pull request] is not based on a recent commit, the [Maintainers] + may rebase it onto the `master` branch first, or ask you to do this. + * If the [pull request] cannot be automatically merged, the [Maintainers] + will ask you to rebase it onto the `master` branch. + * After final integration testing, the [Maintainers] will push your merge + commit to the `master` branch. If a problem is found during integration, + the merge commit will be removed from the `integration` branch and the + [Maintainers] will ask you to create a new pull request to resolve the + problem. * Please do not delete your topic branch until it is safely merged into the `master` branch. - - - - - - - - - - - - - - - - - - - - - - - - - - -_Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved._ +_Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved._ [User Guide]: ./docs/user-guide.md @@ -95,6 +110,7 @@ _Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved._ [Firmware Design]: ./docs/firmware-design.md [Acknowledgements]: ./acknowledgements.md "Contributor acknowledgements" [DCO]: ./dco.txt +[Maintainers]: ./maintainers.md [GitHub account]: https://github.com/signup/free [Fork]: https://help.github.com/articles/fork-a-repo diff --git a/docs/plat/hikey960.md b/docs/plat/hikey960.md new file mode 100644 index 00000000..786a54b9 --- /dev/null +++ b/docs/plat/hikey960.md @@ -0,0 +1,134 @@ + +Description +==================== + HiKey960 is one of 96boards. Hisilicon Hi3660 processor is installed on HiKey960. + + More information are listed in [link](http://www.96boards.org/documentation/ConsumerEdition/HiKey960/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/hikey960_v1) + + +2. Build Procedure +------------------ + + * Fetch all the above 5 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 toolchain. + + * If your hikey960 hardware is v1, update _uefi-tools/platform.config_ first. _(optional)_ + <br>__Uncomment the below sentence. Otherwise, UEFI can't output messages on serial + console on hikey960 v1.__</br> + <br>`BUILDFLAGS=-DSERIAL_BASE=0xFDF05000`</br> + <br>If your hikey960 hardware is v2 or newer, nothing to do.</br> + + * Build it as debug mode. Create script file for build. + <br>`BUILD_OPTION=DEBUG`</br> + <br>`export AARCH64_TOOLCHAIN=GCC48`</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/HiKey960/${BUILD_OPTION}_${AARCH64_TOOLCHAIN}`</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 hikey960`</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 ${EDK2_OUTPUT_DIR}/FV/BL33_AP_UEFI.fd`</br> + <br>`python gen_loader.py -o l-loader.bin --img_bl1=bl1.bin --img_ns_bl1u=BL33_AP_UEFI.fd`</br> + + * Generate partition table. + <br>_Make sure that you're using the sgdisk in the l-loader directory._</br> + <br>`$PTABLE=aosp-32g SECTOR_SIZE=4096 SGDISK=./sgdisk bash -x generate_ptable.sh`</br> + + +3. Setup Console +---------------- + + * Install ser2net. Use telnet as the console since UEFI will output window + that fails to display in minicom. + <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. Boot UEFI in recovery mode +----------------------------- + + * Fetch that are used in recovery mode. The code location is in below. + [link](https://github.com/96boards-hikey/tools-images-hikey960) + + * Generate l-loader.bin. + <br>`$cd tools-images-hikey960`</br> + <br>`$ln -sf ${BUILD_PATH}/l-loader/l-loader.bin`</br> + + * Prepare config file. + <br>_$vi config_</br> + <br>_# The content of config file_</br> + <br>`./sec_user_xloader.img 0x00020000`</br> + <br>`./sec_uce_boot.img 0x6A908000`</br> + <br>`./l-loader.bin 0x1AC00000`</br> + + * Remove the modemmanager package. This package may causes hikey_idt tool failure. + <br>`$sudo apt-get purge modemmanager`</br> + + * Run the command to download l-loader.bin into HiKey960. + <br>`$sudo ./hikey_idt -c config -p /dev/ttyUSB1`</br> + + * UEFI running in recovery mode. + <br>When prompt '.' is displayed on console, press hotkey 'f' in keyboard. Then Android fastboot app is running.</br> + <br>The timeout of prompt '.' is 10 seconds.</br> + + * Update images. + <br>`$sudo fastboot flash ptable prm_ptable.img`</br> + <br>`$sudo fastboot flash xloader sec_xloader.img`</br> + <br>`$sudo fastboot flash fastboot l-loader.bin`</br> + <br>`$sudo fastboot flash fip 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> + + * Notice: UEFI could also boot kernel in recovery mode, but BL31 isn't loaded in + recovery mode. + + +5. Boot UEFI in normal mode +----------------------------- + + * Make sure "Boot Mode" switch is OFF for normal boot mode. Then power on HiKey960. + + * Reference [link](https://github.com/96boards-hikey/tools-images-hikey960/blob/master/build-from-source/README-ATF-UEFI-build-from-source.md) diff --git a/drivers/auth/mbedtls/mbedtls_common.c b/drivers/auth/mbedtls/mbedtls_common.c index 3799d418..e9aa409b 100644 --- a/drivers/auth/mbedtls/mbedtls_common.c +++ b/drivers/auth/mbedtls/mbedtls_common.c @@ -9,6 +9,7 @@ /* mbed TLS headers */ #include <mbedtls/memory_buffer_alloc.h> #include <mbedtls/platform.h> +#include <mbedtls_config.h> /* * mbed TLS heap @@ -31,8 +32,10 @@ void mbedtls_init(void) /* Initialize the mbed TLS heap */ mbedtls_memory_buffer_alloc_init(heap, MBEDTLS_HEAP_SIZE); +#ifdef MBEDTLS_PLATFORM_SNPRINTF_ALT /* Use reduced version of snprintf to save space. */ mbedtls_platform_set_snprintf(tf_snprintf); +#endif ready = 1; } diff --git a/include/lib/stdlib/machine/endian.h b/include/lib/stdlib/machine/endian.h new file mode 100644 index 00000000..57e33b17 --- /dev/null +++ b/include/lib/stdlib/machine/endian.h @@ -0,0 +1,168 @@ +/*- + * Copyright (c) 2001 David E. O'Brien + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)endian.h 8.1 (Berkeley) 6/10/93 + * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2017, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#include <sys/_types.h> + +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#define _LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define _BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define _PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +#define _BYTE_ORDER _LITTLE_ENDIAN + +#if __BSD_VISIBLE +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER +#endif + +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 +#define __ntohl(x) (__bswap32(x)) +#define __ntohs(x) (__bswap16(x)) +#define __htonl(x) (__bswap32(x)) +#define __htons(x) (__bswap16(x)) + +#ifdef AARCH32 +static __inline __uint64_t +__bswap64(__uint64_t _x) +{ + + return ((_x >> 56) | ((_x >> 40) & 0xff00) | ((_x >> 24) & 0xff0000) | + ((_x >> 8) & 0xff000000) | ((_x << 8) & ((__uint64_t)0xff << 32)) | + ((_x << 24) & ((__uint64_t)0xff << 40)) | + ((_x << 40) & ((__uint64_t)0xff << 48)) | ((_x << 56))); +} + +static __inline __uint32_t +__bswap32_var(__uint32_t v) +{ + __uint32_t t1; + + __asm __volatile("eor %1, %0, %0, ror #16\n" + "bic %1, %1, #0x00ff0000\n" + "mov %0, %0, ror #8\n" + "eor %0, %0, %1, lsr #8\n" + : "+r" (v), "=r" (t1)); + + return (v); +} + +static __inline __uint16_t +__bswap16_var(__uint16_t v) +{ + __uint32_t ret = v & 0xffff; + + __asm __volatile( + "mov %0, %0, ror #8\n" + "orr %0, %0, %0, lsr #16\n" + "bic %0, %0, %0, lsl #16" + : "+r" (ret)); + + return ((__uint16_t)ret); +} +#elif defined AARCH64 +static __inline __uint64_t +__bswap64(__uint64_t x) +{ + __uint64_t ret; + + __asm __volatile("rev %0, %1\n" + : "=&r" (ret), "+r" (x)); + + return (ret); +} + +static __inline __uint32_t +__bswap32_var(__uint32_t v) +{ + __uint32_t ret; + + __asm __volatile("rev32 %x0, %x1\n" + : "=&r" (ret), "+r" (v)); + + return (ret); +} + +static __inline __uint16_t +__bswap16_var(__uint16_t v) +{ + __uint32_t ret; + + __asm __volatile("rev16 %w0, %w1\n" + : "=&r" (ret), "+r" (v)); + + return ((__uint16_t)ret); +} +#else +#error "Only AArch32 or AArch64 supported" +#endif /* AARCH32 */ + +#ifdef __OPTIMIZE__ + +#define __bswap32_constant(x) \ + ((((x) & 0xff000000U) >> 24) | \ + (((x) & 0x00ff0000U) >> 8) | \ + (((x) & 0x0000ff00U) << 8) | \ + (((x) & 0x000000ffU) << 24)) + +#define __bswap16_constant(x) \ + ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) + +#define __bswap16(x) \ + ((__uint16_t)(__builtin_constant_p(x) ? \ + __bswap16_constant(x) : \ + __bswap16_var(x))) + +#define __bswap32(x) \ + ((__uint32_t)(__builtin_constant_p(x) ? \ + __bswap32_constant(x) : \ + __bswap32_var(x))) + +#else +#define __bswap16(x) __bswap16_var(x) +#define __bswap32(x) __bswap32_var(x) + +#endif /* __OPTIMIZE__ */ +#endif /* !_MACHINE_ENDIAN_H_ */ diff --git a/include/lib/stdlib/sys/endian.h b/include/lib/stdlib/sys/endian.h new file mode 100644 index 00000000..d50110ca --- /dev/null +++ b/include/lib/stdlib/sys/endian.h @@ -0,0 +1,205 @@ +/*- + * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ENDIAN_H_ +#define _SYS_ENDIAN_H_ + +#include <sys/cdefs.h> +#include <sys/_types.h> +#include <machine/endian.h> + +#ifndef _UINT8_T_DECLARED +typedef __uint8_t uint8_t; +#define _UINT8_T_DECLARED +#endif + +#ifndef _UINT16_T_DECLARED +typedef __uint16_t uint16_t; +#define _UINT16_T_DECLARED +#endif + +#ifndef _UINT32_T_DECLARED +typedef __uint32_t uint32_t; +#define _UINT32_T_DECLARED +#endif + +#ifndef _UINT64_T_DECLARED +typedef __uint64_t uint64_t; +#define _UINT64_T_DECLARED +#endif + +/* + * General byte order swapping functions. + */ +#define bswap16(x) __bswap16(x) +#define bswap32(x) __bswap32(x) +#define bswap64(x) __bswap64(x) + +/* + * Host to big endian, host to little endian, big endian to host, and little + * endian to host byte order functions as detailed in byteorder(9). + */ +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define htobe16(x) bswap16((x)) +#define htobe32(x) bswap32((x)) +#define htobe64(x) bswap64((x)) +#define htole16(x) ((uint16_t)(x)) +#define htole32(x) ((uint32_t)(x)) +#define htole64(x) ((uint64_t)(x)) + +#define be16toh(x) bswap16((x)) +#define be32toh(x) bswap32((x)) +#define be64toh(x) bswap64((x)) +#define le16toh(x) ((uint16_t)(x)) +#define le32toh(x) ((uint32_t)(x)) +#define le64toh(x) ((uint64_t)(x)) +#else /* _BYTE_ORDER != _LITTLE_ENDIAN */ +#define htobe16(x) ((uint16_t)(x)) +#define htobe32(x) ((uint32_t)(x)) +#define htobe64(x) ((uint64_t)(x)) +#define htole16(x) bswap16((x)) +#define htole32(x) bswap32((x)) +#define htole64(x) bswap64((x)) + +#define be16toh(x) ((uint16_t)(x)) +#define be32toh(x) ((uint32_t)(x)) +#define be64toh(x) ((uint64_t)(x)) +#define le16toh(x) bswap16((x)) +#define le32toh(x) bswap32((x)) +#define le64toh(x) bswap64((x)) +#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ + +/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */ + +static __inline uint16_t +be16dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return ((p[0] << 8) | p[1]); +} + +static __inline uint32_t +be32dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); +} + +static __inline uint64_t +be64dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4)); +} + +static __inline uint16_t +le16dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return ((p[1] << 8) | p[0]); +} + +static __inline uint32_t +le32dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((unsigned)p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); +} + +static __inline uint64_t +le64dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p)); +} + +static __inline void +be16enc(void *pp, uint16_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = (u >> 8) & 0xff; + p[1] = u & 0xff; +} + +static __inline void +be32enc(void *pp, uint32_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = (u >> 24) & 0xff; + p[1] = (u >> 16) & 0xff; + p[2] = (u >> 8) & 0xff; + p[3] = u & 0xff; +} + +static __inline void +be64enc(void *pp, uint64_t u) +{ + uint8_t *p = (uint8_t *)pp; + + be32enc(p, (uint32_t)(u >> 32)); + be32enc(p + 4, (uint32_t)(u & 0xffffffffU)); +} + +static __inline void +le16enc(void *pp, uint16_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; +} + +static __inline void +le32enc(void *pp, uint32_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; + p[2] = (u >> 16) & 0xff; + p[3] = (u >> 24) & 0xff; +} + +static __inline void +le64enc(void *pp, uint64_t u) +{ + uint8_t *p = (uint8_t *)pp; + + le32enc(p, (uint32_t)(u & 0xffffffffU)); + le32enc(p + 4, (uint32_t)(u >> 32)); +} + +#endif /* _SYS_ENDIAN_H_ */ diff --git a/maintainers.md b/maintainers.md new file mode 100644 index 00000000..c8fc19db --- /dev/null +++ b/maintainers.md @@ -0,0 +1,84 @@ +ARM Trusted Firmware Maintainers +================================ + +ARM Trusted Firmware is an ARM maintained project. All contributions are +ultimately merged by the maintainers listed below. Technical ownership of some +parts of the codebase is delegated to the sub-maintainers listed below. An +acknowledgement from these sub-maintainers may be required before the +maintainers merge a contribution. + + +## Maintainers + +Dan Handley (dan.handley@arm.com, [danh-arm](https://github.com/danh-arm)) + +David Cunado (david.cunado@arm.com, [davidcunado-arm](https://github.com/davidcunado-arm)) + + +## OPTEE and QEMU platform sub-maintainer + +Jens Wiklander (jens.wiklander@linaro.org, [jenswi-linaro](https://github.com/jenswi-linaro)) + +Files: +* docs/spd/optee-dispatcher.md +* docs/plat/qemu.md +* services/spd/opteed/* +* plat/qemu/* + + +## TLK/Trusty SPDs and NVidia platforms sub-maintainer + +Varun Wadekar (vwadekar@nvidia.com, [vwadekar](https://github.com/vwadekar)) + +Files: +* docs/spd/tlk-dispatcher.md +* docs/spd/trusty-dispatcher.md +* include/bl32/payloads/tlk.h +* include/lib/cpus/aarch64/denver.h +* lib/cpus/aarch64/denver.S +* services/spd/tlkd/* +* services/spd/trusty/* +* plat/nvidia/* + + +## eMMC/UFS drivers and HiSilicon platform sub-maintainer + +Haojian Zhuang (haojian.zhuang@linaro.org, [hzhuang1](https://github.com/hzhuang1)) + +Files: +* docs/plat/hikey.md +* docs/plat/hikey960.md +* drivers/emmc/* +* drivers/partition/* +* drivers/synopsys/emmc/* +* drivers/synopsys/ufs/* +* drivers/ufs/* +* include/drivers/dw_ufs.h +* include/drivers/emmc.h +* include/drivers/ufs.h +* include/drivers/synopsys/dw_mmc.h +* plat/hisilicon/* + + +## MediaTek platform sub-maintainer + +Yidi Lin (林以廸 yidi.lin@mediatek.com, [mtk09422](https://github.com/mtk09422)) + +Files: +* plat/mediatek/* + + +## RockChip platform sub-maintainer +Tony Xie (tony.xie@rock-chips.com, [TonyXie06](https://github.com/TonyXie06) +or [rkchrome](https://github.com/rkchrome)) + +Files: +* plat/rockchip/* + + +## Xilinx platform sub-maintainer +Sören Brinkmann (soren.brinkmann@xilinx.com, [sorenb-xlnx](https://github.com/sorenb-xlnx)) + +Files: +* docs/plat/xilinx-zynqmp.md +* plat/xilinx/* diff --git a/plat/hisilicon/hikey/hisi_sip_svc.c b/plat/hisilicon/hikey/hisi_sip_svc.c new file mode 100644 index 00000000..15953af0 --- /dev/null +++ b/plat/hisilicon/hikey/hisi_sip_svc.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <hisi_sip_svc.h> +#include <debug.h> +#include <pmf.h> +#include <runtime_svc.h> +#include <stdint.h> +#include <uuid.h> + + +/* Hisi SiP Service UUID */ +DEFINE_SVC_UUID(hisi_sip_svc_uid, + 0xe599df74, 0x7682, 0x40aa, 0x9f, 0xf8, + 0xc0, 0x85, 0x52, 0xbc, 0x39, 0x3f); + +static int hisi_sip_setup(void) +{ + if (pmf_setup() != 0) + return 1; + return 0; +} + +/* + * This function handles Hisi defined SiP Calls + */ +static uintptr_t hisi_sip_handler(unsigned int smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + int call_count = 0; + + /* + * Dispatch PMF calls to PMF SMC handler and return its return + * value + */ + if (is_pmf_fid(smc_fid)) { + return pmf_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + + switch (smc_fid) { + case HISI_SIP_SVC_CALL_COUNT: + /* PMF calls */ + call_count += PMF_NUM_SMC_CALLS; + + /* State switch call */ + call_count += 1; + + SMC_RET1(handle, call_count); + + case HISI_SIP_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, hisi_sip_svc_uid); + + case HISI_SIP_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, HISI_SIP_SVC_VERSION_MAJOR, HISI_SIP_SVC_VERSION_MINOR); + + default: + WARN("Unimplemented HISI SiP Service Call: 0x%x \n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } + +} + + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + hisi_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + hisi_sip_setup, + hisi_sip_handler +); diff --git a/plat/hisilicon/hikey/include/hisi_sip_svc.h b/plat/hisilicon/hikey/include/hisi_sip_svc.h new file mode 100644 index 00000000..662b6ccc --- /dev/null +++ b/plat/hisilicon/hikey/include/hisi_sip_svc.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __HISI_SIP_SVC_H__ +#define __HISI_SIP_SVC_H__ + +/* SMC function IDs for SiP Service queries */ + +#define HISI_SIP_SVC_CALL_COUNT 0x8200ff00 +#define HISI_SIP_SVC_UID 0x8200ff01 +/* 0x8200ff02 is reserved */ +#define HISI_SIP_SVC_VERSION 0x8200ff03 + +/* HISI SiP Service Calls version numbers */ +#define HISI_SIP_SVC_VERSION_MAJOR 0x0 +#define HISI_SIP_SVC_VERSION_MINOR 0x1 + +#endif /* __ARM_SIP_SVC_H__ */ diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk index fb5f8525..85dc40d1 100644 --- a/plat/hisilicon/hikey/platform.mk +++ b/plat/hisilicon/hikey/platform.mk @@ -77,3 +77,8 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ plat/hisilicon/hikey/hisi_pwrc.c \ plat/hisilicon/hikey/hisi_pwrc_sram.S \ ${HIKEY_GIC_SOURCES} +ifeq (${ENABLE_PMF}, 1) +BL31_SOURCES += plat/hisilicon/hikey/hisi_sip_svc.c \ + lib/pmf/pmf_smc.c +endif + diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_common.c b/plat/hisilicon/hikey960/aarch64/hikey960_common.c new file mode 100644 index 00000000..d7894b3e --- /dev/null +++ b/plat/hisilicon/hikey960/aarch64/hikey960_common.c @@ -0,0 +1,109 @@ +/* + * 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 "../hikey960_def.h" +#include "../hikey960_private.h" + +#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \ + DDR_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \ + DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_BL1_RW MAP_REGION_FLAT(BL1_RW_BASE, \ + BL1_RW_LIMIT - BL1_RW_BASE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_UFS_DATA MAP_REGION_FLAT(HIKEY960_UFS_DATA_BASE, \ + HIKEY960_UFS_DATA_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_UFS_DESC MAP_REGION_FLAT(HIKEY960_UFS_DESC_BASE, \ + HIKEY960_UFS_DESC_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* + * 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 + * hikey960_init_mmu_elx() will give the available subset of that, + */ +#if IMAGE_BL1 +static const mmap_region_t hikey960_mmap[] = { + MAP_UFS_DATA, + MAP_BL1_RW, + MAP_UFS_DESC, + MAP_DEVICE, + {0} +}; +#endif + +#if IMAGE_BL2 +static const mmap_region_t hikey960_mmap[] = { + MAP_DDR, + MAP_DEVICE, + {0} +}; +#endif + +#if IMAGE_BL31 +static const mmap_region_t hikey960_mmap[] = { + MAP_DEVICE, + {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 HIKEY960_CONFIGURE_MMU_EL(_el) \ + void hikey960_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(hikey960_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(0); \ + } + +/* Define EL1 and EL3 variants of the function initialising the MMU */ +HIKEY960_CONFIGURE_MMU_EL(1) +HIKEY960_CONFIGURE_MMU_EL(3) + +unsigned long plat_get_ns_image_entrypoint(void) +{ + return NS_BL1U_BASE; +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return 1920000; +} diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S new file mode 100644 index 00000000..2e24416d --- /dev/null +++ b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S @@ -0,0 +1,198 @@ +/* + * 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 <cortex_a73.h> +#include "../hikey960_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 + .globl set_retention_ticks + .globl clr_retention_ticks + .globl clr_ex + .globl nop + +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, #0x0c + /* 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 + + /* ----------------------------------------------------- + * void set_retention_ticks(unsigned int val); + * Clobber list : x0 + * ----------------------------------------------------- + */ +func set_retention_ticks + mrs x0, CPUECTLR_EL1 + bic x0, x0, #CPUECTLR_CPU_RET_CTRL_MASK + orr x0, x0, #RETENTION_ENTRY_TICKS_8 + msr CPUECTLR_EL1, x0 + isb + dsb sy + ret +endfunc set_retention_ticks + + /* ----------------------------------------------------- + * void clr_retention_ticks(unsigned int val); + * Clobber list : x0 + * ----------------------------------------------------- + */ +func clr_retention_ticks + mrs x0, CPUECTLR_EL1 + bic x0, x0, #CPUECTLR_CPU_RET_CTRL_MASK + msr CPUECTLR_EL1, x0 + isb + dsb sy + ret +endfunc clr_retention_ticks + + /* ----------------------------------------------------- + * void clrex(void); + * ----------------------------------------------------- + */ +func clr_ex + clrex + ret +endfunc clr_ex + + /* ----------------------------------------------------- + * void nop(void); + * ----------------------------------------------------- + */ +func nop + nop + ret +endfunc nop + +.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: " diff --git a/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c b/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c new file mode 100644 index 00000000..8ce1e4ff --- /dev/null +++ b/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <hi3660.h> +#include <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <hisi_ipc.h> +#include <debug.h> + +#include "../../hikey960_private.h" + +#define IPC_MBX_SOURCE_REG(m) (IPC_BASE + ((m) << 6)) +#define IPC_MBX_DSET_REG(m) (IPC_BASE + ((m) << 6) + 0x04) +#define IPC_MBX_DCLEAR_REG(m) (IPC_BASE + ((m) << 6) + 0x08) +#define IPC_MBX_DSTATUS_REG(m) (IPC_BASE + ((m) << 6) + 0x0C) +#define IPC_MBX_MODE_REG(m) (IPC_BASE + ((m) << 6) + 0x10) +#define IPC_MBX_IMASK_REG(m) (IPC_BASE + ((m) << 6) + 0x14) +#define IPC_MBX_ICLR_REG(m) (IPC_BASE + ((m) << 6) + 0x18) +#define IPC_MBX_SEND_REG(m) (IPC_BASE + ((m) << 6) + 0x1C) +#define IPC_MBX_DATA_REG(m, d) (IPC_BASE + ((m) << 6) + 0x20 + \ + ((d) * 4)) +#define IPC_CPU_IMST_REG(m) (IPC_BASE + ((m) << 3)) +#define IPC_LOCK_REG (IPC_BASE + 0xA00) +#define IPC_ACK_BIT_SHIFT (1 << 7) +#define IPC_UNLOCK_VALUE (0x1ACCE551) + +/********************************************************* + *bit[31:24]:0~AP + *bit[23:16]:0x1~A15, 0x2~A7 + *bit[15:8]:0~ON, 1~OFF + *bit[7:0]:0x3 cpu power mode + *********************************************************/ +#define IPC_CMD_TYPE(src_obj, cluster_obj, is_off, mode) \ + ((src_obj << 24) | (((cluster_obj) + 1) << 16) | (is_off << 8) | (mode)) + +/********************************************************* + *bit[15:8]:0~no idle, 1~idle + *bit[7:0]:cpux + *********************************************************/ + +#define IPC_CMD_PARA(is_idle, cpu) \ + ((is_idle << 8) | (cpu)) + +#define IPC_STATE_IDLE 0x10 + +enum src_id { + SRC_IDLE = 0, + SRC_A15 = 1 << 0, + SRC_A7 = 1 << 1, + SRC_IOM3 = 1 << 2, + SRC_LPM3 = 1 << 3 +}; + +/*lpm3's mailboxs are 13~17*/ +enum lpm3_mbox_id { + LPM3_MBX0 = 13, + LPM3_MBX1, + LPM3_MBX2, + LPM3_MBX3, + LPM3_MBX4, +}; + +static void cpu_relax(void) +{ + volatile int i; + + for (i = 0; i < 10; i++) + nop(); +} + +static inline void +hisi_ipc_clear_ack(enum src_id source, enum lpm3_mbox_id mbox) +{ + unsigned int int_status = 0; + + do { + int_status = mmio_read_32(IPC_MBX_MODE_REG(mbox)); + int_status &= 0xF0; + cpu_relax(); + } while (int_status != IPC_ACK_BIT_SHIFT); + + mmio_write_32(IPC_MBX_ICLR_REG(mbox), source); +} + +static void +hisi_ipc_send_cmd_with_ack(enum src_id source, enum lpm3_mbox_id mbox, + unsigned int cmdtype, unsigned int cmdpara) +{ + unsigned int regval; + unsigned int mask; + unsigned int state; + + mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE); + /* wait for idle and occupy */ + do { + state = mmio_read_32(IPC_MBX_MODE_REG(mbox)); + if (state == IPC_STATE_IDLE) { + mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source); + regval = mmio_read_32(IPC_MBX_SOURCE_REG(mbox)); + if (regval == source) + break; + } + cpu_relax(); + + } while (1); + + /* auto answer */ + mmio_write_32(IPC_MBX_MODE_REG(mbox), 0x1); + + mask = (~((int)source | SRC_LPM3) & 0x3F); + /* mask the other cpus */ + mmio_write_32(IPC_MBX_IMASK_REG(mbox), mask); + /* set data */ + mmio_write_32(IPC_MBX_DATA_REG(mbox, 0), cmdtype); + mmio_write_32(IPC_MBX_DATA_REG(mbox, 1), cmdpara); + /* send cmd */ + mmio_write_32(IPC_MBX_SEND_REG(mbox), source); + /* wait ack and clear */ + hisi_ipc_clear_ack(source, mbox); + + /* release mailbox */ + mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source); +} + +void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster, + enum pm_mode mode) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, cluster, mode, 0x3); + cmdpara = IPC_CMD_PARA(0, core); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster, + unsigned int affinity_level) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + if (affinity_level == 0x3) + cmdtype = IPC_CMD_TYPE(0, -1, 0x1, 0x3 + affinity_level); + else + cmdtype = IPC_CMD_TYPE(0, cluster, 0x1, 0x3 + affinity_level); + + cmdpara = IPC_CMD_PARA(1, core); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x1, 0x0); + cmdpara = IPC_CMD_PARA(0, 0); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster, + unsigned int cmd_id) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x0, 0x0); + cmdpara = cmd_id; + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +int hisi_ipc_init(void) +{ + int ret = 0; + enum lpm3_mbox_id i = LPM3_MBX0; + + mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE); + for (i = LPM3_MBX0; i <= LPM3_MBX4; i++) { + mmio_write_32(IPC_MBX_MODE_REG(i), 1); + mmio_write_32(IPC_MBX_IMASK_REG(i), + ((int)SRC_IOM3 | (int)SRC_A15 | (int)SRC_A7)); + mmio_write_32(IPC_MBX_ICLR_REG(i), SRC_A7); + } + + return ret; +} diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c new file mode 100644 index 00000000..f82144a4 --- /dev/null +++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <mmio.h> +#include <platform.h> +#include <platform_def.h> +#include <../hikey960_def.h> +#include <hisi_ipc.h> +#include "hisi_pwrc.h" + + +/* resource lock api */ +#define RES0_LOCK_BASE (SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE)) +#define RES1_LOCK_BASE (SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE)) +#define RES2_LOCK_BASE (SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE)) + +#define LOCK_BIT (0x1 << 28) +#define LOCK_ID_MASK (0x7 << 29) +#define CPUIDLE_LOCK_ID(core) (0x6 - (core)) +#define LOCK_UNLOCK_OFFSET 0x4 +#define LOCK_STAT_OFFSET 0x8 + +#define CLUSTER0_CPUS_ONLINE_MASK (0xF << 16) +#define CLUSTER1_CPUS_ONLINE_MASK (0xF << 20) + +/* cpu hotplug flag api */ +#define SCTRL_BASE (SOC_ACPU_SCTRL_BASE_ADDR) +#define REG_SCBAKDATA3_OFFSET (SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE)) +#define REG_SCBAKDATA8_OFFSET (SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE)) +#define REG_SCBAKDATA9_OFFSET (SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE)) + +#define CPUIDLE_FLAG_REG(cluster) \ + ((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \ + REG_SCBAKDATA9_OFFSET) +#define CLUSTER_IDLE_BIT BIT(8) +#define CLUSTER_IDLE_MASK (CLUSTER_IDLE_BIT | 0x0F) + +#define AP_SUSPEND_FLAG (1 << 16) + +#define CLUSTER_PWDN_IDLE (0<<28) +#define CLUSTER_PWDN_HOTPLUG (1<<28) +#define CLUSTER_PWDN_SR (2<<28) + +#define CLUSTER0_PDC_OFFSET 0x260 +#define CLUSTER1_PDC_OFFSET 0x300 + +#define PDC_EN_OFFSET 0x0 +#define PDC_COREPWRINTEN_OFFSET 0x4 +#define PDC_COREPWRINTSTAT_OFFSET 0x8 +#define PDC_COREGICMASK_OFFSET 0xc +#define PDC_COREPOWERUP_OFFSET 0x10 +#define PDC_COREPOWERDN_OFFSET 0x14 +#define PDC_COREPOWERSTAT_OFFSET 0x18 + +#define PDC_COREPWRSTAT_MASK (0XFFFF) + +enum pdc_gic_mask { + PDC_MASK_GIC_WAKE_IRQ, + PDC_UNMASK_GIC_WAKE_IRQ +}; + +enum pdc_finish_int_mask { + PDC_DISABLE_FINISH_INT, + PDC_ENABLE_FINISH_INT +}; + +static void hisi_resource_lock(unsigned int lockid, unsigned int offset) +{ + unsigned int lock_id = (lockid << 29); + unsigned int lock_val = lock_id | LOCK_BIT; + unsigned int lock_state; + + do { + mmio_write_32(offset, lock_val); + lock_state = mmio_read_32(LOCK_STAT_OFFSET + (uintptr_t)offset); + } while ((lock_state & LOCK_ID_MASK) != lock_id); +} + +static void hisi_resource_unlock(unsigned int lockid, unsigned int offset) +{ + unsigned int lock_val = (lockid << 29) | LOCK_BIT; + + mmio_write_32((LOCK_UNLOCK_OFFSET + (uintptr_t)offset), lock_val); +} + + +static void hisi_cpuhotplug_lock(unsigned int cluster, unsigned int core) +{ + unsigned int lock_id; + + lock_id = (cluster << 2) + core; + + hisi_resource_lock(lock_id, RES2_LOCK_BASE); +} + +static void hisi_cpuhotplug_unlock(unsigned int cluster, unsigned int core) +{ + unsigned int lock_id; + + lock_id = (cluster << 2) + core; + + hisi_resource_unlock(lock_id, RES2_LOCK_BASE); +} + +/* get the resource lock */ +void hisi_cpuidle_lock(unsigned int cluster, unsigned int core) +{ + unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); + + hisi_resource_lock(CPUIDLE_LOCK_ID(core), offset); +} + +/* release the resource lock */ +void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core) +{ + unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); + + hisi_resource_unlock(CPUIDLE_LOCK_ID(core), offset); +} + +unsigned int hisi_get_cpuidle_flag(unsigned int cluster) +{ + unsigned int val; + + val = mmio_read_32(CPUIDLE_FLAG_REG(cluster)); + val &= 0xF; + + return val; +} + +void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core) +{ + mmio_setbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); +} + +void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core) +{ + mmio_clrbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); + +} + +int hisi_test_ap_suspend_flag(unsigned int cluster) +{ + unsigned int val; + + val = mmio_read_32(CPUIDLE_FLAG_REG(cluster)); + val &= AP_SUSPEND_FLAG; + return !!val; +} + +void hisi_set_cluster_pwdn_flag(unsigned int cluster, + unsigned int core, unsigned int value) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val = (value << (cluster << 1)) | (val & 0xFFFFFFF); + mmio_write_32(REG_SCBAKDATA3_OFFSET, val); + + hisi_cpuhotplug_unlock(cluster, core); +} + +unsigned int hisi_get_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val = val >> (16 + (cluster << 2)); + val &= 0xF; + hisi_cpuhotplug_unlock(cluster, core); + + return val; +} + +unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val = val >> (16 + (cluster << 2)); + val &= 0xF; + hisi_cpuhotplug_unlock(cluster, core); + + if (val) + return 0; + else + return 1; +} + +void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int flag = BIT((cluster<<2) + core + 16); + + hisi_cpuhotplug_lock(cluster, core); + + mmio_setbits_32(REG_SCBAKDATA3_OFFSET, flag); + + hisi_cpuhotplug_unlock(cluster, core); +} + +void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int flag = BIT((cluster<<2) + core + 16); + + hisi_cpuhotplug_lock(cluster, core); + + mmio_clrbits_32(REG_SCBAKDATA3_OFFSET, flag); + + hisi_cpuhotplug_unlock(cluster, core); +} + +int cluster_is_powered_on(unsigned int cluster) +{ + unsigned int val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + int ret; + + if (cluster == 0) + ret = val & CLUSTER0_CPUS_ONLINE_MASK; + else + ret = val & CLUSTER1_CPUS_ONLINE_MASK; + + return !!ret; +} + +static void *hisi_get_pdc_addr(unsigned int cluster) +{ + void *pdc_base_addr; + uintptr_t addr; + + if (cluster == 0) + addr = SOC_CRGPERIPH_A53_PDCEN_ADDR(CRG_BASE); + else + addr = SOC_CRGPERIPH_MAIA_PDCEN_ADDR(CRG_BASE); + pdc_base_addr = (void *)addr; + + return pdc_base_addr; +} + +static unsigned int hisi_get_pdc_stat(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPOWERSTAT_OFFSET); + + return val; +} + +int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core) +{ + unsigned int mask = 0xf << (core * 4); + unsigned int pdc_stat = hisi_get_pdc_stat(cluster); + unsigned int boot_flag = hisi_get_cpu_boot_flag(cluster, core); + unsigned int cpuidle_flag = hisi_get_cpuidle_flag(cluster); + + mask = (PDC_COREPWRSTAT_MASK & (~mask)); + pdc_stat &= mask; + + if ((boot_flag ^ cpuidle_flag) || pdc_stat) + return 0; + else + return 1; +} + +void hisi_disable_pdc(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr, 0x0); +} + +void hisi_enable_pdc(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr, 0x1); +} + +static inline void hisi_pdc_set_intmask(void *pdc_base_addr, + unsigned int core, + enum pdc_finish_int_mask intmask) +{ + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET); + if (intmask == PDC_ENABLE_FINISH_INT) + val |= BIT(core); + else + val &= ~BIT(core); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, val); +} + +static inline void hisi_pdc_set_gicmask(void *pdc_base_addr, + unsigned int core, + enum pdc_gic_mask gicmask) +{ + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET); + if (gicmask == PDC_MASK_GIC_WAKE_IRQ) + val |= BIT(core); + else + val &= ~BIT(core); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET, val); +} + +void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster) +{ + int i; + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + for (i = 0; i < 4; i++) + hisi_pdc_set_gicmask(pdc_base_addr, i, PDC_MASK_GIC_WAKE_IRQ); +} + +static void hisi_pdc_powerup_core(unsigned int cluster, unsigned int core, + enum pdc_gic_mask gicmask, + enum pdc_finish_int_mask intmask) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERUP_OFFSET, + BIT(core)); +} + +static void hisi_pdc_powerdn_core(unsigned int cluster, unsigned int core, + enum pdc_gic_mask gicmask, + enum pdc_finish_int_mask intmask) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_powerup_core(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerup_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_powerdn_core(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerdn_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_powerup_cluster(unsigned int cluster, unsigned int core) +{ + hisi_ipc_pm_on_off(core, cluster, PM_ON); +} + +void hisi_powerdn_cluster(unsigned int cluster, unsigned int core) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_HOTPLUG); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, + (0x10001 << core)); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_enter_core_idle(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerdn_core(cluster, core, PDC_UNMASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_IDLE); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, + (0x10001 << core)); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core) +{ + hisi_ipc_pm_suspend(core, cluster, 0x3); +} diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h new file mode 100644 index 00000000..a4d887fb --- /dev/null +++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __HISI_PWRC_H__ +#define __HISI_PWRC_H__ + +#include <hi3660.h> +#include <hi3660_crg.h> + +#define PCTRL_BASE (PCTRL_REG_BASE) +#define CRG_BASE (CRG_REG_BASE) + +#define SOC_CRGPERIPH_A53_PDCEN_ADDR(base) ((base) + (0x260)) +#define SOC_CRGPERIPH_MAIA_PDCEN_ADDR(base) ((base) + (0x300)) + +#define SOC_PCTRL_RESOURCE0_LOCK_ADDR(base) ((base) + (0x400)) +#define SOC_PCTRL_RESOURCE0_UNLOCK_ADDR(base) ((base) + (0x404)) +#define SOC_PCTRL_RESOURCE0_LOCK_ST_ADDR(base) ((base) + (0x408)) +#define SOC_PCTRL_RESOURCE1_LOCK_ADDR(base) ((base) + (0x40C)) +#define SOC_PCTRL_RESOURCE1_UNLOCK_ADDR(base) ((base) + (0x410)) +#define SOC_PCTRL_RESOURCE1_LOCK_ST_ADDR(base) ((base) + (0x414)) +#define SOC_PCTRL_RESOURCE2_LOCK_ADDR(base) ((base) + (0x418)) + +#define SOC_SCTRL_SCBAKDATA3_ADDR(base) ((base) + (0x418)) +#define SOC_SCTRL_SCBAKDATA8_ADDR(base) ((base) + (0x42C)) +#define SOC_SCTRL_SCBAKDATA9_ADDR(base) ((base) + (0x430)) + +#define SOC_ACPU_SCTRL_BASE_ADDR (0xFFF0A000) + +void hisi_cpuidle_lock(unsigned int cluster, unsigned int core); +void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core); +void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core); +void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core); +void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core); +void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core); +int cluster_is_powered_on(unsigned int cluster); +void hisi_enter_core_idle(unsigned int cluster, unsigned int core); +void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core); +int hisi_test_ap_suspend_flag(unsigned int cluster); +void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core); + + +/* pdc api */ +void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster); +int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core); +void hisi_disable_pdc(unsigned int cluster); +void hisi_enable_pdc(unsigned int cluster); +void hisi_powerup_core(unsigned int cluster, unsigned int core); +void hisi_powerdn_core(unsigned int cluster, unsigned int core); +void hisi_powerup_cluster(unsigned int cluster, unsigned int core); +void hisi_powerdn_cluster(unsigned int cluster, unsigned int core); +unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core); + +#endif /* __HISI_PWRC_H__ */ diff --git a/plat/hisilicon/hikey960/hi3660_mailbox.c b/plat/hisilicon/hikey960/hi3660_mailbox.c new file mode 100644 index 00000000..aa12932b --- /dev/null +++ b/plat/hisilicon/hikey960/hi3660_mailbox.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <assert.h> +#include <debug.h> +#include <errno.h> +#include <hi3660_mailbox.h> +#include <mailbox.h> +#include <mmio.h> +#include <string.h> + +typedef struct hi3660_chan { + unsigned char src; + unsigned char dst; + unsigned char used; +} hi3660_chan_t; + +static hi3660_chan_t chan_map[MBX_MAX_CHANNELS]; + +static void hi3660_mbox_check_state(int chan, unsigned int state) +{ + unsigned int data; + + data = mmio_read_32(MBX_MODE(chan)); + assert((data & (MBX_MODE_AUTO_ANSWER | MBX_MODE_AUTO_LINK)) == 0); + + data &= MBX_MODE_STATE_STATUS_MASK; + assert(data == state); + (void)state; +} + +static int hi3660_mbox_send(int chan, void *message, int len) +{ + int i; + unsigned int *buf; + unsigned int data; + + assert((chan >= 0) && (chan < MBX_MAX_CHANNELS) && + (message != NULL) && (len <= MBX_MAX_DATA_LEN)); + assert((chan_map[chan].used != 0) && + (chan_map[chan].src != 0) && + (chan_map[chan].dst != 0)); + + buf = (unsigned int *)message; + len = ((len + 3) >> 2); /* convert to word count */ + for (i = 0; i < len; i++) + mmio_write_32(MBX_DATA0(chan) + (i << 2), *(buf + i)); + /* send out */ + mmio_write_32(MBX_SEND(chan), chan_map[chan].src); + + do { + data = mmio_read_32(MBX_ICLR(chan)); + } while ((data & chan_map[chan].src) == 0); + /* ack */ + mmio_write_32(MBX_ICLR(chan), chan_map[chan].src); + return 0; +} + +static int hi3660_mbox_recv(int chan, void *message, int *len) +{ + unsigned int *buf, data; + int i; + + assert((chan >= 0) && (chan < MBX_MAX_CHANNELS) && + (message != NULL) && (len != NULL)); + assert((chan_map[chan].used != 0) && + (chan_map[chan].src != 0) && + (chan_map[chan].dst != 0)); + /* wait IPC event */ + do { + data = mmio_read_32(MBX_MODE(chan)); + } while ((data & MBX_MODE_STATE_STATUS_MASK) != MBX_MODE_STATE_DEST); + /* wait to clear interrupt */ + do { + data = mmio_read_32(MBX_ICLR(chan)); + } while (data == 0); + do { + mmio_write_32(MBX_ICLR(chan), chan_map[chan].dst); + data = mmio_read_32(MBX_ICLR(chan)); + } while (data); + + /* read data from IPC */ + buf = (unsigned int *)message; + for (i = 0; i < MBX_MAX_DATA_LEN; i += 4) + *(buf + (i >> 2)) = mmio_read_32(MBX_DATA0(chan) + i); + *len = MBX_MAX_DATA_LEN; + /* ack */ + mmio_write_32(MBX_SEND(chan), chan_map[chan].dst); + return 0; +} + +static int hi3660_mbox_request(int chan, int direction) +{ + unsigned int data; + unsigned int src, dst; + + assert((chan >= 0) && (chan < MBX_MAX_CHANNELS)); + + if (direction == MAILBOX_DIR_TX) { + src = CPU_A53; + dst = CPU_LPM3; + } else if (direction == MAILBOX_DIR_RX) { + src = CPU_LPM3; + dst = CPU_A53; + } else + assert(0); + mmio_write_32(MBX_SOURCE(chan), src); + data = mmio_read_32(MBX_SOURCE(chan)); + assert(data == src); + + /* mask all interrupts */ + mmio_write_32(MBX_IMASK(chan), CPU_MASK); + /* unmask interrupt */ + mmio_write_32(MBX_IMASK(chan), ~(src | dst)); + + /* set destination */ + mmio_write_32(MBX_DCLEAR(chan), (~dst) & CPU_MASK); + mmio_write_32(MBX_DSET(chan), dst); + data = mmio_read_32(MBX_DSTATUS(chan)); + assert((data & dst) != 0); + + /* clear auto link & auto answer */ + data = mmio_read_32(MBX_MODE(chan)); + data &= ~(MBX_MODE_AUTO_ANSWER | MBX_MODE_AUTO_LINK); + mmio_write_32(MBX_MODE(chan), data); + + hi3660_mbox_check_state(chan, MBX_MODE_STATE_SOURCE); + chan_map[chan].used = 1; + chan_map[chan].src = src; + chan_map[chan].dst = dst; + return 0; +} + +static void hi3660_mbox_free(int chan) +{ + assert((chan >= 0) && (chan < MBX_MAX_CHANNELS)); +} + +static mbox_ops_t hi3660_mbox_ops = { + .send = hi3660_mbox_send, + .recv = hi3660_mbox_recv, + .request = hi3660_mbox_request, + .free = hi3660_mbox_free, +}; + +int hi3660_mbox_init(mbox_params_t *params) +{ + int result; + unsigned int data; + + assert(params != NULL); + result = mbox_init(&hi3660_mbox_ops, params); + assert(result == 0); + memset(&chan_map, 0, sizeof(chan_map)); + + /* unlock mailbox */ + data = mmio_read_32(IPC_LOCK); + while (data == MBX_IPC_LOCKED) { + mmio_write_32(IPC_LOCK, MBX_IPC_UNLOCK_MAGIC); + data = mmio_read_32(IPC_LOCK); + } + (void)result; + return 0; +} diff --git a/plat/hisilicon/hikey960/hikey960_bl1_setup.c b/plat/hisilicon/hikey960/hikey960_bl1_setup.c new file mode 100644 index 00000000..f9666df1 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_bl1_setup.c @@ -0,0 +1,705 @@ +/* + * 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 <console.h> +#include <debug.h> +#include <delay_timer.h> +#include <dw_ufs.h> +#include <errno.h> +#include <gicv2.h> +#include <hi3660.h> +#include <mmio.h> +#include <generic_delay_timer.h> +#include <platform.h> +#include <platform_def.h> +#include <string.h> +#include <tbbr/tbbr_img_desc.h> +#include <ufs.h> + +#include "../../bl1/bl1_private.h" +#include "hikey960_def.h" +#include "hikey960_private.h" + +enum { + BOOT_MODE_RECOVERY = 0, + BOOT_MODE_NORMAL, + BOOT_MODE_MASK = 1, +}; + +/* + * 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; + +/****************************************************************************** + * 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 +}; + +const gicv2_driver_data_t hikey960_gic_data = { + .gicd_base = GICD_REG_BASE, + .gicc_base = GICC_REG_BASE, + .g0_interrupt_num = ARRAY_SIZE(g0_interrupt_array), + .g0_interrupt_array = g0_interrupt_array, +}; + +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; + unsigned int id, uart_base; + + generic_delay_timer_init(); + hikey960_read_boardid(&id); + if (id == 5300) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + /* Initialize the console to provide early debug support */ + console_init(uart_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) +{ + hikey960_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 hikey960_clk_init(void) +{ + /* change ldi0 sel to ppll2 */ + mmio_write_32(0xfff350b4, 0xf0002000); + /* ldi0 20' */ + mmio_write_32(0xfff350bc, 0xfc004c00); +} + +static void hikey960_pmu_init(void) +{ + /* clear np_xo_abb_dig_START bit in PMIC_CLK_TOP_CTRL7 register */ + mmio_clrbits_32(PMU_SSI0_CLK_TOP_CTRL7_REG, NP_XO_ABB_DIG); +} + +static void hikey960_enable_ppll3(void) +{ + /* enable ppll3 */ + mmio_write_32(PMC_PPLL3_CTRL0_REG, 0x4904305); + mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x2300000); + mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x6300000); +} + +static void bus_idle_clear(unsigned int value) +{ + unsigned int pmc_value, value1, value2; + int timeout = 100; + + pmc_value = value << 16; + pmc_value &= ~value; + mmio_write_32(PMC_NOC_POWER_IDLEREQ_REG, pmc_value); + + for (;;) { + value1 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLEACK_REG); + value2 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLE_REG); + if (((value1 & value) == 0) && ((value2 & value) == 0)) + break; + udelay(1); + timeout--; + if (timeout <= 0) { + WARN("%s timeout\n", __func__); + break; + } + } +} + +static void set_vivobus_power_up(void) +{ + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x00020002); + mmio_write_32(CRG_PEREN0_REG, 0x00001000); +} + +static void set_dss_power_up(void) +{ + /* set edc0 133MHz = 1600MHz / 12 */ + mmio_write_32(CRG_CLKDIV5_REG, 0x003f000b); + /* set ldi0 ppl0 */ + mmio_write_32(CRG_CLKDIV3_REG, 0xf0001000); + /* set ldi0 133MHz, 1600MHz / 12 */ + mmio_write_32(CRG_CLKDIV5_REG, 0xfc002c00); + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000020); + udelay(100); + /* DISP CRG */ + mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000010); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); + mmio_write_32(CRG_PEREN0_REG, 0x00002000); + mmio_write_32(CRG_PEREN3_REG, 0x0003b000); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS3_REG, 0x0003b000); + mmio_write_32(CRG_PERDIS0_REG, 0x00002000); + mmio_write_32(CRG_CLKDIV18_REG, 0x01400000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000040); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000006); + mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000c00); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x01400140); + mmio_write_32(CRG_PEREN0_REG, 0x00002000); + mmio_write_32(CRG_PEREN3_REG, 0x0003b000); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_DSS); + /* set edc0 400MHz for 2K 1600MHz / 4 */ + mmio_write_32(CRG_CLKDIV5_REG, 0x003f0003); + /* set ldi 266MHz, 1600MHz / 6 */ + mmio_write_32(CRG_CLKDIV5_REG, 0xfc001400); +} + +static void set_vcodec_power_up(void) +{ + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x00040004); + mmio_write_32(CRG_PEREN0_REG, 0x00000060); + mmio_write_32(CRG_PEREN2_REG, 0x10000000); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS0_REG, 0x00000018); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VCODEC); +} + +static void set_vdec_power_up(void) +{ + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000004); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); + mmio_write_32(CRG_PEREN2_REG, 0x20080000); + mmio_write_32(CRG_PEREN3_REG, 0x00000800); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS3_REG, 0x00000800); + mmio_write_32(CRG_PERDIS2_REG, 0x20080000); + mmio_write_32(CRG_CLKDIV18_REG, 0x80000000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000004); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000200); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x80008000); + mmio_write_32(CRG_PEREN2_REG, 0x20080000); + mmio_write_32(CRG_PEREN3_REG, 0x00000800); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VDEC); +} + +static void set_venc_power_up(void) +{ + /* set venc ppll3 */ + mmio_write_32(CRG_CLKDIV8_REG, 0x18001000); + /* set venc 258MHz, 1290MHz / 5 */ + mmio_write_32(CRG_CLKDIV8_REG, 0x07c00100); + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000002); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); + mmio_write_32(CRG_PEREN2_REG, 0x40000100); + mmio_write_32(CRG_PEREN3_REG, 0x00000400); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS3_REG, 0x00000400); + mmio_write_32(CRG_PERDIS2_REG, 0x40000100); + mmio_write_32(CRG_CLKDIV19_REG, 0x00010000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000002); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x00010001); + mmio_write_32(CRG_PEREN2_REG, 0x40000100); + mmio_write_32(CRG_PEREN3_REG, 0x00000400); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VENC); + /* set venc 645MHz, 1290MHz / 2 */ + mmio_write_32(CRG_CLKDIV8_REG, 0x07c00040); +} + +static void set_isp_power_up(void) +{ + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00000001); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); + mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); + mmio_write_32(CRG_PEREN5_REG, 0x01000010); + mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS5_REG, 0x01000010); + mmio_write_32(CRG_PERDIS3_REG, 0x0bf00000); + mmio_write_32(CRG_CLKDIV18_REG, 0x70000000); + mmio_write_32(CRG_CLKDIV20_REG, 0x00100000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x00000001); + /* unreset */ + mmio_write_32(CRG_ISP_SEC_RSTDIS_REG, 0x0000002f); + /* clk enable */ + mmio_write_32(CRG_CLKDIV18_REG, 0x70007000); + mmio_write_32(CRG_CLKDIV20_REG, 0x00100010); + mmio_write_32(CRG_PEREN5_REG, 0x01000010); + mmio_write_32(CRG_PEREN3_REG, 0x0bf00000); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_ISP); + /* csi clk enable */ + mmio_write_32(CRG_PEREN3_REG, 0x00700000); +} + +static void set_ivp_power_up(void) +{ + /* set ivp ppll0 */ + mmio_write_32(CRG_CLKDIV0_REG, 0xc0000000); + /* set ivp 267MHz, 1600MHz / 6 */ + mmio_write_32(CRG_CLKDIV0_REG, 0x3c001400); + /* mtcmos on */ + mmio_write_32(CRG_PERPWREN_REG, 0x00200000); + udelay(100); + /* IVP CRG unreset */ + mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000001); + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); + mmio_write_32(CRG_PEREN4_REG, 0x000000a8); + udelay(1); + /* clk disable */ + mmio_write_32(CRG_PERDIS4_REG, 0x000000a8); + mmio_write_32(CRG_CLKDIV20_REG, 0x02000000); + udelay(1); + /* iso disable */ + mmio_write_32(CRG_ISODIS_REG, 0x01000000); + /* unreset */ + mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000002); + /* clk enable */ + mmio_write_32(CRG_CLKDIV20_REG, 0x02000200); + mmio_write_32(CRG_PEREN4_REG, 0x000000a8); + /* bus idle clear */ + bus_idle_clear(PMC_NOC_POWER_IDLEREQ_IVP); + /* set ivp 533MHz, 1600MHz / 3 */ + mmio_write_32(CRG_CLKDIV0_REG, 0x3c000800); +} + +static void set_audio_power_up(void) +{ + unsigned int ret; + int timeout = 100; + /* mtcmos on */ + mmio_write_32(SCTRL_SCPWREN_REG, 0x00000001); + udelay(100); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); + mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); + mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); + mmio_write_32(CRG_PEREN0_REG, 0x04000000); + mmio_write_32(CRG_PEREN5_REG, 0x00000080); + mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); + udelay(1); + /* clk disable */ + mmio_write_32(SCTRL_SCPERDIS1_REG, 0x0000000f); + mmio_write_32(SCTRL_SCPERDIS0_REG, 0x0c000000); + mmio_write_32(CRG_PERDIS5_REG, 0x00000080); + mmio_write_32(CRG_PERDIS0_REG, 0x04000000); + mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010000); + mmio_write_32(CRG_CLKDIV19_REG, 0x80100000); + udelay(1); + /* iso disable */ + mmio_write_32(SCTRL_SCISODIS_REG, 0x00000001); + udelay(1); + /* unreset */ + mmio_write_32(SCTRL_PERRSTDIS1_SEC_REG, 0x00000001); + mmio_write_32(SCTRL_SCPERRSTDIS0_REG, 0x00000780); + /* clk enable */ + mmio_write_32(CRG_CLKDIV19_REG, 0x80108010); + mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001); + mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000); + mmio_write_32(CRG_PEREN0_REG, 0x04000000); + mmio_write_32(CRG_PEREN5_REG, 0x00000080); + mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f); + /* bus idle clear */ + mmio_write_32(SCTRL_SCPERCTRL7_REG, 0x00040000); + for (;;) { + ret = mmio_read_32(SCTRL_SCPERSTAT6_REG); + if (((ret & (1 << 5)) == 0) && ((ret & (1 << 8)) == 0)) + break; + udelay(1); + timeout--; + if (timeout <= 0) { + WARN("%s timeout\n", __func__); + break; + } + } + mmio_write_32(ASP_CFG_MMBUF_CTRL_REG, 0x00ff0000); +} + +static void set_pcie_power_up(void) +{ + /* mtcmos on */ + mmio_write_32(SCTRL_SCPWREN_REG, 0x00000010); + udelay(100); + /* clk enable */ + mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); + mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); + mmio_write_32(CRG_PEREN7_REG, 0x000003a0); + udelay(1); + /* clk disable */ + mmio_write_32(SCTRL_SCPERDIS2_REG, 0x00104000); + mmio_write_32(CRG_PERDIS7_REG, 0x000003a0); + mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000000); + udelay(1); + /* iso disable */ + mmio_write_32(SCTRL_SCISODIS_REG, 0x00000030); + /* unreset */ + mmio_write_32(CRG_PERRSTDIS3_REG, 0x8c000000); + /* clk enable */ + mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800); + mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000); + mmio_write_32(CRG_PEREN7_REG, 0x000003a0); +} + +static void ispfunc_enable(void) +{ + /* enable ispfunc. Otherwise powerup isp_srt causes exception. */ + mmio_write_32(0xfff35000, 0x00000008); + mmio_write_32(0xfff35460, 0xc004ffff); + mmio_write_32(0xfff35030, 0x02000000); + mdelay(10); +} + +static void isps_control_clock(int flag) +{ + unsigned int ret; + + /* flag: 0 -- disable clock, 1 -- enable clock */ + if (flag) { + ret = mmio_read_32(0xe8420364); + ret |= 1; + mmio_write_32(0xe8420364, ret); + } else { + ret = mmio_read_32(0xe8420364); + ret &= ~1; + mmio_write_32(0xe8420364, ret); + } +} + +static void set_isp_srt_power_up(void) +{ + unsigned int ret; + + ispfunc_enable(); + /* reset */ + mmio_write_32(0xe8420374, 0x00000001); + mmio_write_32(0xe8420350, 0x00000000); + mmio_write_32(0xe8420358, 0x00000000); + /* mtcmos on */ + mmio_write_32(0xfff35150, 0x00400000); + udelay(100); + /* clk enable */ + isps_control_clock(1); + udelay(1); + isps_control_clock(0); + udelay(1); + /* iso disable */ + mmio_write_32(0xfff35148, 0x08000000); + /* unreset */ + ret = mmio_read_32(0xe8420374); + ret &= ~0x1; + mmio_write_32(0xe8420374, ret); + /* clk enable */ + isps_control_clock(1); + /* enable clock gating for accessing csi registers */ + mmio_write_32(0xe8420010, ~0); +} + +static void hikey960_regulator_enable(void) +{ + set_vivobus_power_up(); + hikey960_enable_ppll3(); + set_dss_power_up(); + set_vcodec_power_up(); + set_vdec_power_up(); + set_venc_power_up(); + set_isp_power_up(); + set_ivp_power_up(); + set_audio_power_up(); + set_pcie_power_up(); + set_isp_srt_power_up(); +} + +static void hikey960_ufs_reset(void) +{ + unsigned int data, mask; + + mmio_write_32(CRG_PERDIS7_REG, 1 << 14); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + do { + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + } while (data & BIT_SYSCTRL_REF_CLOCK_EN); + /* use abb clk */ + mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN); + mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16)); + mdelay(1); + mmio_write_32(CRG_PEREN7_REG, 1 << 14); + mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN); + + mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while ((data & PERI_UFS_BIT) == 0); + mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN); + mdelay(1); + mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET); + /* clear SC_DIV_UFS_PERIBUS */ + mask = SC_DIV_UFS_PERIBUS << 16; + mmio_write_32(CRG_CLKDIV17_REG, mask); + /* set SC_DIV_UFSPHY_CFG(3) */ + mask = SC_DIV_UFSPHY_CFG_MASK << 16; + data = SC_DIV_UFSPHY_CFG(3); + mmio_write_32(CRG_CLKDIV16_REG, mask | data); + data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG); + data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ; + data |= 0x39; + mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data); + mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL); + mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG, + MASK_UFS_CLK_GATE_BYPASS); + mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS); + + mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN); + mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL); + mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN); + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT); + mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N); + mdelay(1); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET); + mdelay(20); + mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG, + 0x03300330); + + mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT); + do { + data = mmio_read_32(CRG_PERRSTSTAT3_REG); + } while (data & PERI_UFS_BIT); +} + +static void hikey960_ufs_init(void) +{ + dw_ufs_params_t ufs_params; + + memset(&ufs_params, 0, sizeof(ufs_params)); + ufs_params.reg_base = UFS_REG_BASE; + ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; + ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; + + if ((ufs_params.flags & UFS_FLAGS_SKIPINIT) == 0) + hikey960_ufs_reset(); + dw_ufs_init(&ufs_params); +} + +static void hikey960_tzc_init(void) +{ + mmio_write_32(TZC_EN0_REG, 0x7fbff066); + mmio_write_32(TZC_EN1_REG, 0xfffff5fc); + mmio_write_32(TZC_EN2_REG, 0x0007005c); + mmio_write_32(TZC_EN3_REG, 0x37030700); + mmio_write_32(TZC_EN4_REG, 0xf63fefae); + mmio_write_32(TZC_EN5_REG, 0x000410fd); + mmio_write_32(TZC_EN6_REG, 0x0063ff68); + mmio_write_32(TZC_EN7_REG, 0x030000f3); + mmio_write_32(TZC_EN8_REG, 0x00000007); +} + +static void hikey960_peri_init(void) +{ + /* unreset */ + mmio_setbits_32(CRG_PERRSTDIS4_REG, 1); +} + +static void hikey960_pinmux_init(void) +{ + unsigned int id; + + hikey960_read_boardid(&id); + if (id == 5301) { + /* hikey960 hardware v2 */ + /* GPIO150: LED */ + mmio_write_32(IOMG_FIX_006_REG, 0); + /* GPIO151: LED */ + mmio_write_32(IOMG_FIX_007_REG, 0); + /* GPIO189: LED */ + mmio_write_32(IOMG_AO_011_REG, 0); + /* GPIO190: LED */ + mmio_write_32(IOMG_AO_012_REG, 0); + /* GPIO46 */ + mmio_write_32(IOMG_044_REG, 0); + /* GPIO202 */ + mmio_write_32(IOMG_AO_023_REG, 0); + /* GPIO206 */ + mmio_write_32(IOMG_AO_026_REG, 0); + /* GPIO219 - PD pullup */ + mmio_write_32(IOMG_AO_039_REG, 0); + mmio_write_32(IOCG_AO_043_REG, 1 << 0); + } + /* GPIO005 - PMU SSI, 10mA */ + mmio_write_32(IOCG_006_REG, 2 << 4); +} + +/* + * 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) +{ + hikey960_clk_init(); + hikey960_pmu_init(); + hikey960_regulator_enable(); + hikey960_tzc_init(); + hikey960_peri_init(); + hikey960_ufs_init(); + hikey960_pinmux_init(); + hikey960_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) +{ + unsigned int mode, ret; + + mode = mmio_read_32(SCTRL_BAK_DATA0_REG); + switch (mode & BOOT_MODE_MASK) { + case BOOT_MODE_RECOVERY: + ret = NS_BL1U_IMAGE_ID; + break; + case BOOT_MODE_NORMAL: + ret = BL2_IMAGE_ID; + break; + default: + WARN("Invalid boot mode is found:%d\n", 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; + uintptr_t tmp = HIKEY960_NS_TMP_OFFSET; + + if (image_id == BL2_IMAGE_ID) + return; + /* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */ + memcpy((void *)tmp, (void *)HIKEY960_NS_IMAGE_OFFSET, + NS_BL1U_SIZE); + memcpy((void *)NS_BL1U_BASE, (void *)tmp, NS_BL1U_SIZE); + inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE); + /* Initialize the GIC driver, cpu and distributor interfaces */ + gicv2_driver_init(&hikey960_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + /* CNTFRQ is read-only in EL1 */ + write_cntfrq_el0(plat_get_syscnt_freq2()); + data = read_cpacr_el1(); + do { + data |= 3 << 20; + write_cpacr_el1(data); + data = read_cpacr_el1(); + } 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); +} diff --git a/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/plat/hisilicon/hikey960/hikey960_bl2_setup.c new file mode 100644 index 00000000..e2257937 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_bl2_setup.c @@ -0,0 +1,255 @@ +/* + * 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 <errno.h> +#include <generic_delay_timer.h> +#include <hi3660.h> +#include <mmio.h> +#include <platform_def.h> +#include <string.h> +#include <ufs.h> + +#include "hikey960_def.h" +#include "hikey960_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; +} + +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; +} + +/******************************************************************************* + * Populate the extents of memory available for loading SCP_BL2 (if used), + * i.e. anywhere in trusted RAM as long as it doesn't overwrite BL2. + ******************************************************************************/ +void bl2_plat_get_scp_bl2_meminfo(meminfo_t *scp_bl2_meminfo) +{ + ufs_params_t ufs_params; + + memset(&ufs_params, 0, sizeof(ufs_params_t)); + ufs_params.reg_base = UFS_REG_BASE; + ufs_params.desc_base = HIKEY960_UFS_DESC_BASE; + ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE; + ufs_params.flags = UFS_FLAGS_SKIPINIT; + ufs_init(NULL, &ufs_params); + + hikey960_io_setup(); + + *scp_bl2_meminfo = bl2_tzram_layout; +} + +extern int load_lpm3(void); + +int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) +{ + int i; + int *buf; + + assert(scp_bl2_image_info->image_size < SCP_MEM_SIZE); + + INFO("BL2: Initiating SCP_BL2 transfer to SCP\n"); + + INFO("BL2: SCP_BL2: 0x%lx@0x%x\n", + scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + + buf = (int *)scp_bl2_image_info->image_base; + + INFO("BL2: SCP_BL2 HEAD:\n"); + for (i = 0; i < 64; i += 4) + INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n", + buf[i], buf[i+1], buf[i+2], buf[i+3]); + + buf = (int *)(scp_bl2_image_info->image_base + + scp_bl2_image_info->image_size - 256); + + INFO("BL2: SCP_BL2 TAIL:\n"); + for (i = 0; i < 64; i += 4) + INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n", + buf[i], buf[i+1], buf[i+2], buf[i+3]); + + memcpy((void *)SCP_MEM_BASE, + (void *)scp_bl2_image_info->image_base, + scp_bl2_image_info->image_size); + + INFO("BL2: SCP_BL2 transferred to SCP\n"); + + load_lpm3(); + (void)buf; + + return 0; +} + +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; +} + +void bl2_early_platform_setup(meminfo_t *mem_layout) +{ + unsigned int id, uart_base; + + generic_delay_timer_init(); + hikey960_read_boardid(&id); + if (id == 5300) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + + /* Initialize the console to provide early debug support */ + console_init(uart_base, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; +} + +void bl2_plat_arch_setup(void) +{ + hikey960_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) +{ + /* disable WDT0 */ + if (mmio_read_32(WDT0_REG_BASE + WDT_LOCK_OFFSET) == WDT_LOCKED) { + mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, WDT_UNLOCK); + mmio_write_32(WDT0_REG_BASE + WDT_CONTROL_OFFSET, 0); + mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, 0); + } +} diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c new file mode 100644 index 00000000..41c591b1 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c @@ -0,0 +1,129 @@ +/* + * 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 <cci.h> +#include <console.h> +#include <debug.h> +#include <errno.h> +#include <generic_delay_timer.h> +#include <gicv2.h> +#include <hi3660.h> +#include <hisi_ipc.h> +#include <platform_def.h> + +#include "hikey960_def.h" +#include "hikey960_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 +}; + +const gicv2_driver_data_t hikey960_gic_data = { + .gicd_base = GICD_REG_BASE, + .gicc_base = GICC_REG_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) +{ + unsigned int id, uart_base; + + generic_delay_timer_init(); + hikey960_read_boardid(&id); + if (id == 5300) + uart_base = PL011_UART5_BASE; + else + uart_base = PL011_UART6_BASE; + + /* Initialize the console to provide early debug support */ + console_init(uart_base, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE); + + /* Initialize CCI driver */ + cci_init(CCI400_REG_BASE, cci_map, ARRAY_SIZE(cci_map)); + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + /* + * 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) +{ + hikey960_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(&hikey960_gic_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); + + hisi_ipc_init(); +} + +void bl31_plat_runtime_setup(void) +{ +} diff --git a/plat/hisilicon/hikey960/hikey960_boardid.c b/plat/hisilicon/hikey960/hikey960_boardid.c new file mode 100644 index 00000000..ac3e0385 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_boardid.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <debug.h> +#include <delay_timer.h> +#include <errno.h> +#include <hi3660.h> +#include <mmio.h> + +#include "hikey960_private.h" + +#define ADC_ADCIN0 0 +#define ADC_ADCIN1 1 +#define ADC_ADCIN2 2 + +#define HKADC_DATA_GRADE0 0 +#define HKADC_DATA_GRADE1 100 +#define HKADC_DATA_GRADE2 300 +#define HKADC_DATA_GRADE3 500 +#define HKADC_DATA_GRADE4 700 +#define HKADC_DATA_GRADE5 900 +#define HKADC_DATA_GRADE6 1100 +#define HKADC_DATA_GRADE7 1300 +#define HKADC_DATA_GRADE8 1500 +#define HKADC_DATA_GRADE9 1700 +#define HKADC_DATA_GRADE10 1800 + +#define BOARDID_VALUE0 0 +#define BOARDID_VALUE1 1 +#define BOARDID_VALUE2 2 +#define BOARDID_VALUE3 3 +#define BOARDID_VALUE4 4 +#define BOARDID_VALUE5 5 +#define BOARDID_VALUE6 6 +#define BOARDID_VALUE7 7 +#define BOARDID_VALUE8 8 +#define BOARDID_VALUE9 9 +#define BOARDID_UNKNOWN 0xF + +#define BOARDID3_BASE 5 + + +static void init_adc(void) +{ + /* reset hkadc */ + mmio_write_32(CRG_PERRSTEN2_REG, PERRSTEN2_HKADCSSI); + /* wait a few clock cycles */ + udelay(2); + mmio_write_32(CRG_PERRSTDIS2_REG, PERRSTEN2_HKADCSSI); + udelay(2); + /* enable hkadc clock */ + mmio_write_32(CRG_PERDIS2_REG, PEREN2_HKADCSSI); + udelay(2); + mmio_write_32(CRG_PEREN2_REG, PEREN2_HKADCSSI); + udelay(2); +} + +static int get_adc(unsigned int channel, unsigned int *value) +{ + unsigned int data, value1, value0; + + if (channel > HKADC_CHANNEL_MAX) { + WARN("invalid channel:%d\n", channel); + return -EFAULT; + } + /* configure the read/write operation for external HKADC */ + mmio_write_32(HKADC_WR01_DATA_REG, HKADC_WR01_VALUE | channel); + mmio_write_32(HKADC_WR23_DATA_REG, HKADC_WR23_VALUE); + mmio_write_32(HKADC_WR45_DATA_REG, HKADC_WR45_VALUE); + /* configure the number of accessing registers */ + mmio_write_32(HKADC_WR_NUM_REG, HKADC_WR_NUM_VALUE); + /* configure delay of accessing registers */ + mmio_write_32(HKADC_DELAY01_REG, HKADC_CHANNEL0_DELAY01_VALUE); + mmio_write_32(HKADC_DELAY23_REG, HKADC_DELAY23_VALUE); + + /* start HKADC */ + mmio_write_32(HKADC_DSP_START_REG, 1); + do { + data = mmio_read_32(HKADC_DSP_START_REG); + } while (data & 1); + + /* convert AD result */ + value1 = mmio_read_32(HKADC_DSP_RD2_DATA_REG) & 0xffff; + value0 = mmio_read_32(HKADC_DSP_RD3_DATA_REG) & 0xffff; + + data = ((value1 << 4) & HKADC_VALUE_HIGH) | + ((value0 >> 4) & HKADC_VALUE_LOW); + *value = data; + return 0; +} + +static int get_value(unsigned int channel, unsigned int *value) +{ + int ret; + + ret = get_adc(channel, value); + if (ret) + return ret; + + /* convert ADC value to micro-volt */ + ret = ((*value & HKADC_VALID_VALUE) * HKADC_VREF_1V8) / HKADC_ACCURACY; + *value = ret; + return 0; +} + +static int adcin_data_remap(unsigned int adcin_value) +{ + int ret; + + if (adcin_value < HKADC_DATA_GRADE0) + ret = BOARDID_UNKNOWN; + else if (adcin_value < HKADC_DATA_GRADE1) + ret = BOARDID_VALUE0; + else if (adcin_value < HKADC_DATA_GRADE2) + ret = BOARDID_VALUE1; + else if (adcin_value < HKADC_DATA_GRADE3) + ret = BOARDID_VALUE2; + else if (adcin_value < HKADC_DATA_GRADE4) + ret = BOARDID_VALUE3; + else if (adcin_value < HKADC_DATA_GRADE5) + ret = BOARDID_VALUE4; + else if (adcin_value < HKADC_DATA_GRADE6) + ret = BOARDID_VALUE5; + else if (adcin_value < HKADC_DATA_GRADE7) + ret = BOARDID_VALUE6; + else if (adcin_value < HKADC_DATA_GRADE8) + ret = BOARDID_VALUE7; + else if (adcin_value < HKADC_DATA_GRADE9) + ret = BOARDID_VALUE8; + else if (adcin_value < HKADC_DATA_GRADE10) + ret = BOARDID_VALUE9; + else + ret = BOARDID_UNKNOWN; + return ret; +} + +int hikey960_read_boardid(unsigned int *id) +{ + unsigned int adcin0, adcin1, adcin2; + unsigned int adcin0_remap, adcin1_remap, adcin2_remap; + + assert(id != NULL); + + init_adc(); + + /* read ADC channel0 data */ + get_value(ADC_ADCIN0, &adcin0); + adcin0_remap = adcin_data_remap(adcin0); + INFO("[BDID]adcin0:%d adcin0_remap:%d\n", adcin0, adcin0_remap); + if (adcin0_remap == BOARDID_UNKNOWN) + return -EINVAL; + /* read ADC channel1 data */ + get_value(ADC_ADCIN1, &adcin1); + adcin1_remap = adcin_data_remap(adcin1); + INFO("[BDID]adcin1:%d adcin1_remap:%d\n", adcin1, adcin1_remap); + if (adcin1_remap == BOARDID_UNKNOWN) + return -EINVAL; + /* read ADC channel2 data */ + get_value(ADC_ADCIN2, &adcin2); + adcin2_remap = adcin_data_remap(adcin2); + INFO("[BDID]adcin2:%d adcin2_remap:%d\n", adcin2, adcin2_remap); + if (adcin2_remap == BOARDID_UNKNOWN) + return -EINVAL; + *id = BOARDID3_BASE * 1000 + (adcin2_remap * 100) + + (adcin1_remap * 10) + adcin0_remap; + INFO("[BDID]boardid: %d\n", *id); + return 0; +} diff --git a/plat/hisilicon/hikey960/hikey960_def.h b/plat/hisilicon/hikey960/hikey960_def.h new file mode 100644 index 00000000..e713e2e0 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_def.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __HIKEY960_DEF_H__ +#define __HIKEY960_DEF_H__ + +#include <common_def.h> +#include <tbbr_img_def.h> + +#define DDR_BASE 0x0 +#define DDR_SIZE 0xC0000000 + +#define DEVICE_BASE 0xE0000000 +#define DEVICE_SIZE 0x20000000 + +/* + * PL011 related constants + */ +#define PL011_UART5_BASE 0xFDF05000 +#define PL011_UART6_BASE 0xFFF32000 +#define PL011_BAUDRATE 115200 +#define PL011_UART_CLK_IN_HZ 19200000 + +#define UFS_BASE 0 +/* FIP partition */ +#define HIKEY960_FIP_BASE (UFS_BASE + 0x1400000) +#define HIKEY960_FIP_MAX_SIZE (12 << 20) + +#define HIKEY960_UFS_DESC_BASE 0x20000000 +#define HIKEY960_UFS_DESC_SIZE 0x00200000 /* 2MB */ +#define HIKEY960_UFS_DATA_BASE 0x10000000 +#define HIKEY960_UFS_DATA_SIZE 0x0A000000 /* 160MB */ + +#endif /* __HIKEY960_DEF_H__ */ diff --git a/plat/hisilicon/hikey960/hikey960_io_storage.c b/plat/hisilicon/hikey960/hikey960_io_storage.c new file mode 100644 index 00000000..de54e886 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_io_storage.c @@ -0,0 +1,190 @@ +/* + * 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 <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 <ufs.h> + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const io_dev_connector_t *ufs_dev_con, *fip_dev_con; +static uintptr_t ufs_dev_handle, fip_dev_handle; + +static int check_ufs(const uintptr_t spec); +static int check_fip(const uintptr_t spec); +size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size); +size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size); + +static const io_block_spec_t ufs_fip_spec = { + .offset = HIKEY960_FIP_BASE, + .length = HIKEY960_FIP_MAX_SIZE, +}; + +static const io_block_spec_t ufs_data_spec = { + .offset = 0, + .length = 256 << 20, +}; + +static const io_block_dev_spec_t ufs_dev_spec = { + /* It's used as temp buffer in block driver. */ + .buffer = { + .offset = HIKEY960_UFS_DATA_BASE, + .length = HIKEY960_UFS_DATA_SIZE, + }, + .ops = { + .read = ufs_read_lun3_blks, + .write = ufs_write_lun3_blks, + }, + .block_size = UFS_BLOCK_SIZE, +}; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t scp_bl2_uuid_spec = { + .uuid = UUID_SCP_FIRMWARE_SCP_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 struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &ufs_dev_handle, + (uintptr_t)&ufs_fip_spec, + check_ufs + }, + [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 + }, + [BL2U_IMAGE_ID] = { + &ufs_dev_handle, + (uintptr_t)&ufs_data_spec, + check_ufs + } +}; + +static int check_ufs(const uintptr_t spec) +{ + int result; + uintptr_t local_handle; + + result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(ufs_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 hikey960_io_setup(void) +{ + int result; + + result = register_io_dev_block(&ufs_dev_con); + assert(result == 0); + + result = register_io_dev_fip(&fip_dev_con); + assert(result == 0); + + result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec, + &ufs_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; +} + +size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size) +{ + return ufs_read_blocks(3, lba, buf, size); +} + +size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size) +{ + return ufs_write_blocks(3, lba, buf, size); +} diff --git a/plat/hisilicon/hikey960/hikey960_mcu_load.c b/plat/hisilicon/hikey960/hikey960_mcu_load.c new file mode 100644 index 00000000..7bf9a3d0 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_mcu_load.c @@ -0,0 +1,52 @@ +/* + * 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 <debug.h> +#include <delay_timer.h> +#include <errno.h> +#include <hi3660.h> +#include <mmio.h> +#include <string.h> + +#define ADDR_CONVERT(addr) ((addr) < 0x40000 ? \ + (addr) + 0xFFF30000 : \ + (addr) + 0x40000000) + +static void fw_data_init(void) +{ + unsigned long data_head_addr; + unsigned int *data_addr; + + data_head_addr = mmio_read_32((uintptr_t) HISI_DATA_HEAD_BASE) + 0x14; + data_addr = (unsigned int *) ADDR_CONVERT(data_head_addr); + + memcpy((void *)HISI_DATA0_BASE, + (const void *)(unsigned long)ADDR_CONVERT(data_addr[0]), + HISI_DATA0_SIZE); + memcpy((void *)HISI_DATA1_BASE, + (const void *)(unsigned long)ADDR_CONVERT(data_addr[1]), + HISI_DATA1_SIZE); +} + +int load_lpm3(void) +{ + INFO("start fw loading\n"); + + fw_data_init(); + + flush_dcache_range((uintptr_t)HISI_RESERVED_MEM_BASE, + HISI_RESERVED_MEM_SIZE); + + sev(); + sev(); + + INFO("fw load success\n"); + + return 0; +} diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c new file mode 100644 index 00000000..257299e8 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_pm.c @@ -0,0 +1,305 @@ +/* + * 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 <console.h> +#include <debug.h> +#include <gicv2.h> +#include <hi3660.h> +#include <hi3660_crg.h> +#include <mmio.h> +#include <psci.h> +#include "drivers/pwrc/hisi_pwrc.h" + +#include "hikey960_def.h" +#include "hikey960_private.h" + +#define CORE_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL0]) +#define CLUSTER_PWR_STATE(state) \ + ((state)->pwr_domain_state[MPIDR_AFFLVL1]) +#define SYSTEM_PWR_STATE(state) \ + ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) + +#define DMAC_GLB_REG_SEC 0x694 +#define AXI_CONF_BASE 0x820 + +static uintptr_t hikey960_sec_entrypoint; + +static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state) +{ + unsigned long scr; + unsigned int val = 0; + + assert(cpu_state == PLAT_MAX_RET_STATE); + + scr = read_scr_el3(); + + /* Enable Physical IRQ and FIQ to wake the CPU*/ + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + + set_retention_ticks(val); + wfi(); + clr_retention_ticks(val); + + /* + * Restore SCR to the original value, synchronisazion of + * scr_el3 is done by eret while el3_exit to save some + * execution cycles. + */ + write_scr_el3(scr); +} + +static int hikey960_pwr_domain_on(u_register_t mpidr) +{ + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + int cluster_stat = cluster_is_powered_on(cluster); + + hisi_set_cpu_boot_flag(cluster, core); + + mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core), + hikey960_sec_entrypoint >> 2); + + if (cluster_stat) + hisi_powerup_core(cluster, core); + else + hisi_powerup_cluster(cluster, core); + + return PSCI_E_SUCCESS; +} + +static void +hikey960_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +void hikey960_pwr_domain_off(const psci_power_state_t *target_state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + clr_ex(); + isb(); + dsbsy(); + + gicv2_cpuif_disable(); + + hisi_clear_cpu_boot_flag(cluster, core); + hisi_powerdn_core(cluster, core); + + /* check if any core is powered up */ + if (hisi_test_pwrdn_allcores(cluster, core)) { + + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + isb(); + dsbsy(); + + hisi_powerdn_cluster(cluster, core); + } +} + +static void __dead2 hikey960_system_reset(void) +{ + mmio_write_32(SCTRL_SCPEREN1_REG, + SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS); + mmio_write_32(SCTRL_SCSYSSTAT_REG, 0xdeadbeef); + panic(); +} + +int hikey960_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; +} + +static int hikey960_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; +} + +static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + unsigned int core = mpidr & MPIDR_CPU_MASK; + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + clr_ex(); + isb(); + dsbsy(); + + gicv2_cpuif_disable(); + + hisi_cpuidle_lock(cluster, core); + hisi_set_cpuidle_flag(cluster, core); + hisi_cpuidle_unlock(cluster, core); + + mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core), + hikey960_sec_entrypoint >> 2); + + hisi_enter_core_idle(cluster, core); + } + + /* Perform the common cluster specific operations */ + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + hisi_cpuidle_lock(cluster, core); + hisi_disable_pdc(cluster); + + /* check if any core is powered up */ + if (hisi_test_pwrdn_allcores(cluster, core)) { + + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); + + isb(); + dsbsy(); + + /* mask the pdc wakeup irq, then + * enable pdc to power down the core + */ + hisi_pdc_mask_cluster_wakeirq(cluster); + hisi_enable_pdc(cluster); + + hisi_cpuidle_unlock(cluster, core); + + /* check the SR flag bit to determine + * CLUSTER_IDLE_IPC or AP_SR_IPC to send + */ + if (hisi_test_ap_suspend_flag(cluster)) + hisi_enter_ap_suspend(cluster, core); + else + hisi_enter_cluster_idle(cluster, core); + } else { + /* enable pdc */ + hisi_enable_pdc(cluster); + hisi_cpuidle_unlock(cluster, core); + } + } +} + +static void hikey960_sr_dma_reinit(void) +{ + unsigned int ctr = 0; + + mmio_write_32(DMAC_BASE + DMAC_GLB_REG_SEC, 0x3); + + /* 1~15 channel is set non_secure */ + for (ctr = 1; ctr <= 15; ctr++) + mmio_write_32(DMAC_BASE + AXI_CONF_BASE + ctr * (0x40), + (1 << 6) | (1 << 18)); +} + +static void +hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int cluster = + (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; + + /* Nothing to be done on waking up from retention from CPU level */ + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) + return; + + if (hisi_test_ap_suspend_flag(cluster)) { + hikey960_sr_dma_reinit(); + gicv2_cpuif_enable(); + console_init(PL011_UART6_BASE, PL011_UART_CLK_IN_HZ, + PL011_BAUDRATE); + } + + hikey960_pwr_domain_on_finish(target_state); +} + +static void hikey960_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + int i; + + for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; +} + +static const plat_psci_ops_t hikey960_psci_ops = { + .cpu_standby = hikey960_pwr_domain_standby, + .pwr_domain_on = hikey960_pwr_domain_on, + .pwr_domain_on_finish = hikey960_pwr_domain_on_finish, + .pwr_domain_off = hikey960_pwr_domain_off, + .pwr_domain_suspend = hikey960_pwr_domain_suspend, + .pwr_domain_suspend_finish = hikey960_pwr_domain_suspend_finish, + .system_off = NULL, + .system_reset = hikey960_system_reset, + .validate_power_state = hikey960_validate_power_state, + .validate_ns_entrypoint = hikey960_validate_ns_entrypoint, + .get_sys_suspend_power_state = hikey960_get_sys_suspend_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + hikey960_sec_entrypoint = sec_entrypoint; + + INFO("%s: sec_entrypoint=0x%lx\n", __func__, + (unsigned long)hikey960_sec_entrypoint); + + /* + * Initialize PSCI ops struct + */ + *psci_ops = &hikey960_psci_ops; + return 0; +} diff --git a/plat/hisilicon/hikey960/hikey960_private.h b/plat/hisilicon/hikey960/hikey960_private.h new file mode 100644 index 00000000..8f2a842e --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __HIKEY960_PRIVATE_H__ +#define __HIKEY960_PRIVATE_H__ + +#include <bl_common.h> + +/* + * Function and variable prototypes + */ +void hikey960_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 hikey960_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 hikey960_io_setup(void); +int hikey960_read_boardid(unsigned int *id); +void set_retention_ticks(unsigned int val); +void clr_retention_ticks(unsigned int val); +void clr_ex(void); +void nop(void); + +#endif /* __HIKEY960_PRIVATE_H__ */ diff --git a/plat/hisilicon/hikey960/hikey960_topology.c b/plat/hisilicon/hikey960/hikey960_topology.c new file mode 100644 index 00000000..33637246 --- /dev/null +++ b/plat/hisilicon/hikey960/hikey960_topology.c @@ -0,0 +1,64 @@ +/* + * 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 hikey960_power_domain_tree_desc[] = { + /* Number of root nodes */ + 1, + /* Number of clusters */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, + /* Number of children for the second cluster node */ + PLATFORM_CORE_COUNT_PER_CLUSTER, +}; + +/******************************************************************************* + * This function returns the HiKey topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return hikey960_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)); +} diff --git a/plat/hisilicon/hikey960/include/hi3660.h b/plat/hisilicon/hikey960/include/hi3660.h new file mode 100644 index 00000000..83d1b363 --- /dev/null +++ b/plat/hisilicon/hikey960/include/hi3660.h @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __HI3660_H__ +#define __HI3660_H__ + +#include <hi3660_crg.h> +#include <hi3660_hkadc.h> +#include <hi3660_mem_map.h> + +#define ASP_CFG_REG_BASE 0xE804E000 + +#define ASP_CFG_MMBUF_CTRL_REG (ASP_CFG_REG_BASE + 0x148) + +#define LP_RAM_BASE 0xFFF50000 + +#define SCTRL_REG_BASE 0xFFF0A000 + +#define SCTRL_CONTROL_REG (SCTRL_REG_BASE + 0x000) +#define SCTRL_CONTROL_SYS_MODE(x) (((x) & 0xf) << 3) +#define SCTRL_CONTROL_SYS_MODE_NORMAL ((1 << 2) << 3) +#define SCTRL_CONTROL_SYS_MODE_SLOW ((1 << 1) << 3) +#define SCTRL_CONTROL_SYS_MODE_MASK (0xf << 3) +#define SCTRL_CONTROL_MODE_CTRL_NORMAL (1 << 2) +#define SCTRL_CONTROL_MODE_CTRL_SLOW (1 << 1) +#define SCTRL_CONTROL_MODE_CTRL_MASK 0x7 + +#define SCTRL_SCSYSSTAT_REG (SCTRL_REG_BASE + 0x004) + +#define SCTRL_DEEPSLEEPED_REG (SCTRL_REG_BASE + 0x008) +#define SCTRL_EFUSE_USB_MASK (1 << 30) +#define SCTRL_EFUSE_USB_PLL (1 << 30) +#define SCTRL_EFUSE_USB_ABB (0 << 30) +#define SCTRL_EFUSE_UFS_MASK (3 << 6) +#define SCTRL_EFUSE_UFS_PLL (1 << 6) +#define SCTRL_EFUSE_UFS_ABB (0 << 6) + +#define SCTRL_SCISOEN_REG (SCTRL_REG_BASE + 0x040) +#define SCTRL_SCISODIS_REG (SCTRL_REG_BASE + 0x044) +#define SCISO_MMBUFISO (1 << 3) + +#define SCTRL_SCPWREN_REG (SCTRL_REG_BASE + 0x060) +#define SCPWREN_MMBUFPWREN (1 << 3) + +#define SCTRL_PLL_CTRL0_REG (SCTRL_REG_BASE + 0x100) +#define SCTRL_PLL0_POSTDIV2(x) (((x) & 0x7) << 23) +#define SCTRL_PLL0_POSTDIV1(x) (((x) & 0x7) << 20) +#define SCTRL_PLL0_FBDIV(x) (((x) & 0xfff) << 8) +#define SCTRL_PLL0_REFDIV(x) (((x) & 0x3f) << 2) +#define SCTRL_PLL0_EN (1 << 0) + +#define SCTRL_PLL_CTRL1_REG (SCTRL_REG_BASE + 0x104) +#define SCTRL_PLL0_CLK_NO_GATE (1 << 26) +#define SCTRL_PLL0_CFG_VLD (1 << 25) +#define SCTRL_PLL0_FRACDIV(x) ((x) & 0xFFFFFF) + +#define SCTRL_PLL_STAT_REG (SCTRL_REG_BASE + 0x10C) +#define SCTRL_PLL0_STAT (1 << 0) + +#define SCTRL_SCPEREN0_REG (SCTRL_REG_BASE + 0x160) +#define SCTRL_SCPERDIS0_REG (SCTRL_REG_BASE + 0x164) +#define SCTRL_SCPERSTAT0_REG (SCTRL_REG_BASE + 0x168) + +#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170) +#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174) +#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170) +#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174) +#define SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS (1 << 31) +#define SCPEREN_GT_PCLK_MMBUFCFG (1 << 25) +#define SCPEREN_GT_PCLK_MMBUF (1 << 23) +#define SCPEREN_GT_ACLK_MMBUF (1 << 22) +#define SCPEREN_GT_CLK_NOC_AOBUS2MMBUF (1 << 6) + +#define SCTRL_SCPEREN2_REG (SCTRL_REG_BASE + 0x190) +#define SCTRL_SCPERDIS2_REG (SCTRL_REG_BASE + 0x194) +#define SCTRL_SCPERSTAT2_REG (SCTRL_REG_BASE + 0x198) +#define SCTRL_SCPERRSTEN0_REG (SCTRL_REG_BASE + 0x200) +#define SCTRL_SCPERRSTDIS0_REG (SCTRL_REG_BASE + 0x204) +#define SCTRL_SCPERRSTSTAT0_REG (SCTRL_REG_BASE + 0x208) +#define SCTRL_SCPERRSTEN1_REG (SCTRL_REG_BASE + 0x20C) +#define SCTRL_SCPERRSTDIS1_REG (SCTRL_REG_BASE + 0x210) +#define SCTRL_SCPERRSTSTAT1_REG (SCTRL_REG_BASE + 0x214) +#define IP_RST_MMBUFCFG (1 << 12) +#define IP_RST_MMBUF (1 << 11) + +#define SCTRL_SCPERRSTEN2_REG (SCTRL_REG_BASE + 0x218) +#define SCTRL_SCPERRSTDIS2_REG (SCTRL_REG_BASE + 0x21C) +#define SCTRL_SCPERRSTSTAT2_REG (SCTRL_REG_BASE + 0x220) + +#define SCTRL_SCCLKDIV2_REG (SCTRL_REG_BASE + 0x258) +#define SEL_CLK_MMBUF_MASK (0x3 << 8) +#define SEL_CLK_MMBUF_PLL0 (0x3 << 8) +#define SCCLKDIV2_GT_PCLK_MMBUF (1 << 7) + +#define SCTRL_SCCLKDIV4_REG (SCTRL_REG_BASE + 0x260) +#define GT_MMBUF_SYS (1 << 13) +#define GT_MMBUF_FLL (1 << 12) +#define GT_PLL_CLK_MMBUF (1 << 11) + +#define SCTRL_SCCLKDIV6_REG (SCTRL_REG_BASE + 0x268) + +#define SCTRL_SCPERCTRL7_REG (SCTRL_REG_BASE + 0x31C) +#define SCTRL_SCPERSTAT6_REG (SCTRL_REG_BASE + 0x378) + +#define SCTRL_SCINNERSTAT_REG (SCTRL_REG_BASE + 0x3A0) +#define EMMC_UFS_SEL (1 << 15) + +#define SCTRL_BAK_DATA0_REG (SCTRL_REG_BASE + 0x40C) +#define SCTRL_BAK_DATA4_REG (SCTRL_REG_BASE + 0x41C) + +#define SCTRL_LPMCU_CLKEN_REG (SCTRL_REG_BASE + 0x480) +#define SCTRL_LPMCU_CLKDIS_REG (SCTRL_REG_BASE + 0x484) +#define SCTRL_LPMCU_RSTEN_REG (SCTRL_REG_BASE + 0x500) +#define SCTRL_LPMCU_RSTDIS_REG (SCTRL_REG_BASE + 0x504) +#define DDRC_SOFT_BIT (1 << 6) +#define DDRC_CLK_BIT (1 << 5) + +#define SCTRL_SCPEREN0_SEC_REG (SCTRL_REG_BASE + 0x900) +#define SCTRL_SCPERDIS0_SEC_REG (SCTRL_REG_BASE + 0x904) +#define MMBUF_SEC_CTRL_MASK (0xfff << 20) +#define MMBUF_SEC_CTRL(x) (((x) & 0xfff) << 20) + +#define SCTRL_PERRSTEN1_SEC_REG (SCTRL_REG_BASE + 0xA50) +#define SCTRL_PERRSTDIS1_SEC_REG (SCTRL_REG_BASE + 0xA54) +#define SCTRL_PERRSTSTAT1_SEC_REG (SCTRL_REG_BASE + 0xA58) +#define RST_ASP_SUBSYS_BIT (1 << 0) + +#define SCTRL_PERRSTEN2_SEC_REG (SCTRL_REG_BASE + 0xB50) +#define SCTRL_PERRSTDIS2_SEC_REG (SCTRL_REG_BASE + 0xB54) +#define SCTRL_PERRSTSTAT2_SEC_REG (SCTRL_REG_BASE + 0xB58) + +#define SCTRL_HISEECLKDIV_REG (SCTRL_REG_BASE + 0xC28) +#define SC_SEL_HISEE_PLL_MASK (1 << 4) +#define SC_SEL_HISEE_PLL0 (1 << 4) +#define SC_SEL_HISEE_PLL2 (0 << 4) +#define SC_DIV_HISEE_PLL_MASK (7 << 16) +#define SC_DIV_HISEE_PLL(x) ((x) & 0x7) + +#define SCTRL_SCSOCID0_REG (SCTRL_REG_BASE + 0xE00) + +#define PMC_REG_BASE 0xFFF31000 +#define PMC_PPLL1_CTRL0_REG (PMC_REG_BASE + 0x038) +#define PMC_PPLL1_CTRL1_REG (PMC_REG_BASE + 0x03C) +#define PMC_PPLL2_CTRL0_REG (PMC_REG_BASE + 0x040) +#define PMC_PPLL2_CTRL1_REG (PMC_REG_BASE + 0x044) +#define PMC_PPLL3_CTRL0_REG (PMC_REG_BASE + 0x048) +#define PMC_PPLL3_CTRL1_REG (PMC_REG_BASE + 0x04C) +#define PPLLx_LOCK (1 << 26) +#define PPLLx_WITHOUT_CLK_GATE (1 << 26) +#define PPLLx_CFG_VLD (1 << 25) +#define PPLLx_INT_MOD (1 << 24) +#define PPLLx_POSTDIV2_MASK (0x7 << 23) +#define PPLLx_POSTDIV2(x) (((x) & 0x7) << 23) +#define PPLLx_POSTDIV1_MASK (0x7 << 20) +#define PPLLx_POSTDIV1(x) (((x) & 0x7) << 20) +#define PPLLx_FRACDIV_MASK (0x00FFFFFF) +#define PPLLx_FRACDIV(x) ((x) & 0x00FFFFFF) +#define PPLLx_FBDIV_MASK (0xfff << 8) +#define PPLLx_FBDIV(x) (((x) & 0xfff) << 8) +#define PPLLx_REFDIV_MASK (0x3f << 2) +#define PPLLx_REFDIV(x) (((x) & 0x3f) << 2) +#define PPLLx_BP (1 << 1) +#define PPLLx_EN (1 << 0) + +#define PMC_DDRLP_CTRL_REG (PMC_REG_BASE + 0x30C) +#define DDRC_CSYSREQ_CFG(x) ((x) & 0xF) + +#define PMC_NOC_POWER_IDLEREQ_REG (PMC_REG_BASE + 0x380) +#define PMC_NOC_POWER_IDLEREQ_IVP (1 << 14) +#define PMC_NOC_POWER_IDLEREQ_DSS (1 << 13) +#define PMC_NOC_POWER_IDLEREQ_VENC (1 << 11) +#define PMC_NOC_POWER_IDLEREQ_VDEC (1 << 10) +#define PMC_NOC_POWER_IDLEREQ_ISP (1 << 5) +#define PMC_NOC_POWER_IDLEREQ_VCODEC (1 << 4) +#define DDRPHY_BYPASS_MODE (1 << 0) + +#define PMC_NOC_POWER_IDLEACK_REG (PMC_REG_BASE + 0x384) +#define PMC_NOC_POWER_IDLE_REG (PMC_REG_BASE + 0x388) + +#define PMU_SSI0_REG_BASE 0xFFF34000 + +#define PMU_SSI0_LDO8_CTRL0_REG (PMU_SSI0_REG_BASE + (0x68 << 2)) +#define LDO8_CTRL0_EN_1_8V 0x02 + +#define PMU_SSI0_CLK_TOP_CTRL7_REG (PMU_SSI0_REG_BASE + (0x10C << 2)) +#define NP_XO_ABB_DIG (1 << 1) + +#define LP_CONFIG_REG_BASE 0xFFF3F000 + +#define DMAC_BASE 0xFDF30000 + +#define CCI400_REG_BASE 0xE8100000 +#define CCI400_SL_IFACE3_CLUSTER_IX 0 +#define CCI400_SL_IFACE4_CLUSTER_IX 1 + +#define GICD_REG_BASE 0xE82B1000 +#define GICC_REG_BASE 0xE82B2000 +/* + * 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 + +#define IPC_REG_BASE 0xE896A000 +#define IPC_BASE (IPC_REG_BASE) + +#define IOMG_REG_BASE 0xE896C000 + +/* GPIO46: HUB 3.3V enable. active low */ +#define IOMG_044_REG (IOMG_REG_BASE + 0x0B0) +#define IOMG_UART5_RX_REG (IOMG_REG_BASE + 0x0BC) +#define IOMG_UART5_TX_REG (IOMG_REG_BASE + 0x0C0) + +#define IOCG_REG_BASE 0xE896C800 + +/* GPIO005: PMIC SSI. (2 << 4) */ +#define IOCG_006_REG (IOCG_REG_BASE + 0x018) + +#define TIMER9_REG_BASE 0xE8A00000 + +#define WDT0_REG_BASE 0xE8A06000 +#define WDT1_REG_BASE 0xE8A07000 +#define WDT_CONTROL_OFFSET 0x008 +#define WDT_LOCK_OFFSET 0xC00 + +#define WDT_UNLOCK 0x1ACCE551 +#define WDT_LOCKED 1 + +#define PCTRL_REG_BASE 0xE8A09000 +#define PCTRL_PERI_CTRL3_REG (PCTRL_REG_BASE + 0x010) +#define PCTRL_PERI_CTRL24_REG (PCTRL_REG_BASE + 0x064) + +#define TZC_REG_BASE 0xE8A21000 +#define TZC_STAT0_REG (TZC_REG_BASE + 0x800) +#define TZC_EN0_REG (TZC_REG_BASE + 0x804) +#define TZC_DIS0_REG (TZC_REG_BASE + 0x808) +#define TZC_STAT1_REG (TZC_REG_BASE + 0x80C) +#define TZC_EN1_REG (TZC_REG_BASE + 0x810) +#define TZC_DIS1_REG (TZC_REG_BASE + 0x814) +#define TZC_STAT2_REG (TZC_REG_BASE + 0x818) +#define TZC_EN2_REG (TZC_REG_BASE + 0x81C) +#define TZC_DIS2_REG (TZC_REG_BASE + 0x820) +#define TZC_STAT3_REG (TZC_REG_BASE + 0x824) +#define TZC_EN3_REG (TZC_REG_BASE + 0x828) +#define TZC_DIS3_REG (TZC_REG_BASE + 0x82C) +#define TZC_STAT4_REG (TZC_REG_BASE + 0x830) +#define TZC_EN4_REG (TZC_REG_BASE + 0x834) +#define TZC_DIS4_REG (TZC_REG_BASE + 0x838) +#define TZC_STAT5_REG (TZC_REG_BASE + 0x83C) +#define TZC_EN5_REG (TZC_REG_BASE + 0x840) +#define TZC_DIS5_REG (TZC_REG_BASE + 0x844) +#define TZC_STAT6_REG (TZC_REG_BASE + 0x848) +#define TZC_EN6_REG (TZC_REG_BASE + 0x84C) +#define TZC_DIS6_REG (TZC_REG_BASE + 0x850) +#define TZC_STAT7_REG (TZC_REG_BASE + 0x854) +#define TZC_EN7_REG (TZC_REG_BASE + 0x858) +#define TZC_DIS7_REG (TZC_REG_BASE + 0x85C) +#define TZC_STAT8_REG (TZC_REG_BASE + 0x860) +#define TZC_EN8_REG (TZC_REG_BASE + 0x864) +#define TZC_DIS8_REG (TZC_REG_BASE + 0x868) + +#define MMBUF_BASE 0xEA800000 + +#define ACPU_DMCPACK0_BASE 0xEA900000 + +#define ACPU_DMCPACK1_BASE 0xEA920000 + +#define ACPU_DMCPACK2_BASE 0xEA940000 + +#define ACPU_DMCPACK3_BASE 0xEA960000 + +#define UART5_REG_BASE 0xFDF05000 + +#define USB3OTG_REG_BASE 0xFF100000 + +#define UFS_REG_BASE 0xFF3B0000 + +#define UFS_SYS_REG_BASE 0xFF3B1000 + +#define UFS_SYS_PSW_POWER_CTRL_REG (UFS_SYS_REG_BASE + 0x004) +#define UFS_SYS_PHY_ISO_EN_REG (UFS_SYS_REG_BASE + 0x008) +#define UFS_SYS_HC_LP_CTRL_REG (UFS_SYS_REG_BASE + 0x00C) +#define UFS_SYS_PHY_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x010) +#define UFS_SYS_PSW_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x014) +#define UFS_SYS_CLOCK_GATE_BYPASS_REG (UFS_SYS_REG_BASE + 0x018) +#define UFS_SYS_RESET_CTRL_EN_REG (UFS_SYS_REG_BASE + 0x01C) +#define UFS_SYS_MONITOR_HH_REG (UFS_SYS_REG_BASE + 0x03C) +#define UFS_SYS_UFS_SYSCTRL_REG (UFS_SYS_REG_BASE + 0x05C) +#define UFS_SYS_UFS_DEVICE_RESET_CTRL_REG (UFS_SYS_REG_BASE + 0x060) +#define UFS_SYS_UFS_APB_ADDR_MASK_REG (UFS_SYS_REG_BASE + 0x064) + +#define BIT_UFS_PSW_ISO_CTRL (1 << 16) +#define BIT_UFS_PSW_MTCMOS_EN (1 << 0) +#define BIT_UFS_REFCLK_ISO_EN (1 << 16) +#define BIT_UFS_PHY_ISO_CTRL (1 << 0) +#define BIT_SYSCTRL_LP_ISOL_EN (1 << 16) +#define BIT_SYSCTRL_PWR_READY (1 << 8) +#define BIT_SYSCTRL_REF_CLOCK_EN (1 << 24) +#define MASK_SYSCTRL_REF_CLOCK_SEL (3 << 8) +#define MASK_SYSCTRL_CFG_CLOCK_FREQ (0xFF) +#define BIT_SYSCTRL_PSW_CLK_EN (1 << 4) +#define MASK_UFS_CLK_GATE_BYPASS (0x3F) +#define BIT_SYSCTRL_LP_RESET_N (1 << 0) +#define BIT_UFS_REFCLK_SRC_SE1 (1 << 0) +#define MASK_UFS_SYSCTRL_BYPASS (0x3F << 16) +#define MASK_UFS_DEVICE_RESET (1 << 16) +#define BIT_UFS_DEVICE_RESET (1 << 0) + +#define IOMG_FIX_REG_BASE 0xFF3B6000 + +/* GPIO150: LED */ +#define IOMG_FIX_006_REG (IOMG_FIX_REG_BASE + 0x018) +/* GPIO151: LED */ +#define IOMG_FIX_007_REG (IOMG_FIX_REG_BASE + 0x01C) + +#define IOMG_AO_REG_BASE 0xFFF11000 + +/* GPIO189: LED */ +#define IOMG_AO_011_REG (IOMG_AO_REG_BASE + 0x02C) +/* GPIO190: LED */ +#define IOMG_AO_012_REG (IOMG_AO_REG_BASE + 0x030) +/* GPIO202: type C enable. active low */ +#define IOMG_AO_023_REG (IOMG_AO_REG_BASE + 0x05C) +/* GPIO206: USB switch. active low */ +#define IOMG_AO_026_REG (IOMG_AO_REG_BASE + 0x068) +/* GPIO219: PD interrupt. pull up */ +#define IOMG_AO_039_REG (IOMG_AO_REG_BASE + 0x09C) + +#define IOCG_AO_REG_BASE 0xFFF1187C +/* GPIO219: PD interrupt. pull up */ +#define IOCG_AO_043_REG (IOCG_AO_REG_BASE + 0x030) + +#endif /* __HI3660_H__ */ diff --git a/plat/hisilicon/hikey960/include/hi3660_crg.h b/plat/hisilicon/hikey960/include/hi3660_crg.h new file mode 100644 index 00000000..db1df9ed --- /dev/null +++ b/plat/hisilicon/hikey960/include/hi3660_crg.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __HI3660_CRG_H__ +#define __HI3660_CRG_H__ + +#define CRG_REG_BASE 0xFFF35000 + +#define CRG_PEREN0_REG (CRG_REG_BASE + 0x000) +#define CRG_PERDIS0_REG (CRG_REG_BASE + 0x004) +#define CRG_PERSTAT0_REG (CRG_REG_BASE + 0x008) +#define PEREN0_GT_CLK_AOMM (1 << 31) + +#define CRG_PEREN1_REG (CRG_REG_BASE + 0x010) +#define CRG_PERDIS1_REG (CRG_REG_BASE + 0x014) +#define CRG_PERSTAT1_REG (CRG_REG_BASE + 0x018) +#define CRG_PEREN2_REG (CRG_REG_BASE + 0x020) +#define CRG_PERDIS2_REG (CRG_REG_BASE + 0x024) +#define CRG_PERSTAT2_REG (CRG_REG_BASE + 0x028) +#define PEREN2_HKADCSSI (1 << 24) + +#define CRG_PEREN3_REG (CRG_REG_BASE + 0x030) +#define CRG_PERDIS3_REG (CRG_REG_BASE + 0x034) + +#define CRG_PEREN4_REG (CRG_REG_BASE + 0x040) +#define CRG_PERDIS4_REG (CRG_REG_BASE + 0x044) +#define CRG_PERCLKEN4_REG (CRG_REG_BASE + 0x048) +#define CRG_PERSTAT4_REG (CRG_REG_BASE + 0x04C) +#define GT_ACLK_USB3OTG (1 << 1) +#define GT_CLK_USB3OTG_REF (1 << 0) + +#define CRG_PEREN5_REG (CRG_REG_BASE + 0x050) +#define CRG_PERDIS5_REG (CRG_REG_BASE + 0x054) +#define CRG_PERSTAT5_REG (CRG_REG_BASE + 0x058) +#define CRG_PERRSTEN0_REG (CRG_REG_BASE + 0x060) +#define CRG_PERRSTDIS0_REG (CRG_REG_BASE + 0x064) +#define CRG_PERRSTSTAT0_REG (CRG_REG_BASE + 0x068) +#define CRG_PERRSTEN1_REG (CRG_REG_BASE + 0x06C) +#define CRG_PERRSTDIS1_REG (CRG_REG_BASE + 0x070) +#define CRG_PERRSTSTAT1_REG (CRG_REG_BASE + 0x074) +#define CRG_PERRSTEN2_REG (CRG_REG_BASE + 0x078) +#define CRG_PERRSTDIS2_REG (CRG_REG_BASE + 0x07C) +#define CRG_PERRSTSTAT2_REG (CRG_REG_BASE + 0x080) +#define PERRSTEN2_HKADCSSI (1 << 24) + +#define CRG_PERRSTEN3_REG (CRG_REG_BASE + 0x084) +#define CRG_PERRSTDIS3_REG (CRG_REG_BASE + 0x088) +#define CRG_PERRSTSTAT3_REG (CRG_REG_BASE + 0x08C) +#define CRG_PERRSTEN4_REG (CRG_REG_BASE + 0x090) +#define CRG_PERRSTDIS4_REG (CRG_REG_BASE + 0x094) +#define CRG_PERRSTSTAT4_REG (CRG_REG_BASE + 0x098) +#define IP_RST_USB3OTG_MUX (1 << 8) +#define IP_RST_USB3OTG_AHBIF (1 << 7) +#define IP_RST_USB3OTG_32K (1 << 6) +#define IP_RST_USB3OTG (1 << 5) +#define IP_RST_USB3OTGPHY_POR (1 << 3) + +#define CRG_PERRSTEN5_REG (CRG_REG_BASE + 0x09C) +#define CRG_PERRSTDIS5_REG (CRG_REG_BASE + 0x0A0) +#define CRG_PERRSTSTAT5_REG (CRG_REG_BASE + 0x0A4) + +/* bit fields in CRG_PERI */ +#define PERI_PCLK_PCTRL_BIT (1 << 31) +#define PERI_TIMER12_BIT (1 << 25) +#define PERI_TIMER11_BIT (1 << 24) +#define PERI_TIMER10_BIT (1 << 23) +#define PERI_TIMER9_BIT (1 << 22) +#define PERI_UART5_BIT (1 << 15) +#define PERI_UFS_BIT (1 << 12) +#define PERI_ARST_UFS_BIT (1 << 7) +#define PERI_PPLL2_EN_CPU (1 << 3) +#define PERI_PWM_BIT (1 << 0) +#define PERI_DDRC_BIT (1 << 0) +#define PERI_DDRC_D_BIT (1 << 4) +#define PERI_DDRC_C_BIT (1 << 3) +#define PERI_DDRC_B_BIT (1 << 2) +#define PERI_DDRC_A_BIT (1 << 1) +#define PERI_DDRC_DMUX_BIT (1 << 0) + +#define CRG_CLKDIV0_REG (CRG_REG_BASE + 0x0A0) +#define SC_DIV_LPMCU_MASK ((0x1F << 5) << 16) +#define SC_DIV_LPMCU(x) (((x) & 0x1F) << 5) + +#define CRG_CLKDIV1_REG (CRG_REG_BASE + 0x0B0) +#define SEL_LPMCU_PLL_MASK ((1 << 1) << 16) +#define SEL_SYSBUS_MASK ((1 << 0) << 16) +#define SEL_LPMCU_PLL1 (1 << 1) +#define SEL_LPMCU_PLL0 (0 << 1) +#define SEL_SYSBUS_PLL0 (1 << 0) +#define SEL_SYSBUS_PLL1 (0 << 0) + +#define CRG_CLKDIV3_REG (CRG_REG_BASE + 0x0B4) +#define CRG_CLKDIV5_REG (CRG_REG_BASE + 0x0BC) +#define CRG_CLKDIV8_REG (CRG_REG_BASE + 0x0C8) + +#define CRG_CLKDIV12_REG (CRG_REG_BASE + 0x0D8) +#define SC_DIV_A53HPM_MASK (0x7 << 13) +#define SC_DIV_A53HPM(x) (((x) & 0x7) << 13) + +#define CRG_CLKDIV16_REG (CRG_REG_BASE + 0x0E8) +#define DDRC_CLK_SW_REQ_CFG_MASK (0x3 << 12) +#define DDRC_CLK_SW_REQ_CFG(x) (((x) & 0x3) << 12) +#define SC_DIV_UFSPHY_CFG_MASK (0x3 << 9) +#define SC_DIV_UFSPHY_CFG(x) (((x) & 0x3) << 9) +#define DDRCPLL_SW (1 << 8) + +#define CRG_CLKDIV17_REG (CRG_REG_BASE + 0x0EC) +#define SC_DIV_UFS_PERIBUS (1 << 14) + +#define CRG_CLKDIV18_REG (CRG_REG_BASE + 0x0F0) +#define CRG_CLKDIV19_REG (CRG_REG_BASE + 0x0F4) +#define CRG_CLKDIV20_REG (CRG_REG_BASE + 0x0F8) +#define CLKDIV20_GT_CLK_AOMM (1 << 3) + +#define CRG_CLKDIV22_REG (CRG_REG_BASE + 0x100) +#define SEL_PLL_320M_MASK (1 << 16) +#define SEL_PLL2_320M (1 << 0) +#define SEL_PLL0_320M (0 << 0) + +#define CRG_CLKDIV23_REG (CRG_REG_BASE + 0x104) +#define PERI_DDRC_SW_BIT (1 << 13) +#define DIV_CLK_DDRSYS_MASK (0x3 << 10) +#define DIV_CLK_DDRSYS(x) (((x) & 0x3) << 10) +#define GET_DIV_CLK_DDRSYS(x) (((x) & DIV_CLK_DDRSYS_MASK) >> 10) +#define DIV_CLK_DDRCFG_MASK (0x6 << 5) +#define DIV_CLK_DDRCFG(x) (((x) & 0x6) << 5) +#define GET_DIV_CLK_DDRCFG(x) (((x) & DIV_CLK_DDRCFG_MASK) >> 5) +#define DIV_CLK_DDRC_MASK 0x1F +#define DIV_CLK_DDRC(x) ((x) & DIV_CLK_DDRC_MASK) +#define GET_DIV_CLK_DDRC(x) ((x) & DIV_CLK_DDRC_MASK) + +#define CRG_CLKDIV25_REG (CRG_REG_BASE + 0x10C) +#define DIV_SYSBUS_PLL_MASK (0xF << 16) +#define DIV_SYSBUS_PLL(x) ((x) & 0xF) + +#define CRG_PERI_CTRL2_REG (CRG_REG_BASE + 0x128) +#define PERI_TIME_STAMP_CLK_MASK (0x7 << 28) +#define PERI_TIME_STAMP_CLK_DIV(x) (((x) & 0x7) << 22) + +#define CRG_ISODIS_REG (CRG_REG_BASE + 0x148) +#define CRG_PERPWREN_REG (CRG_REG_BASE + 0x150) + +#define CRG_PEREN7_REG (CRG_REG_BASE + 0x420) +#define CRG_PERDIS7_REG (CRG_REG_BASE + 0x424) +#define CRG_PERSTAT7_REG (CRG_REG_BASE + 0x428) +#define GT_CLK_UFSPHY_CFG (1 << 14) + +#define CRG_PEREN8_REG (CRG_REG_BASE + 0x430) +#define CRG_PERDIS8_REG (CRG_REG_BASE + 0x434) +#define CRG_PERSTAT8_REG (CRG_REG_BASE + 0x438) +#define PERI_DMC_D_BIT (1 << 22) +#define PERI_DMC_C_BIT (1 << 21) +#define PERI_DMC_B_BIT (1 << 20) +#define PERI_DMC_A_BIT (1 << 19) +#define PERI_DMC_BIT (1 << 18) + +#define CRG_PEREN11_REG (CRG_REG_BASE + 0x460) +#define PPLL1_GATE_CPU (1 << 18) + +#define CRG_PERSTAT11_REG (CRG_REG_BASE + 0x46C) +#define PPLL3_EN_STAT (1 << 21) +#define PPLL2_EN_STAT (1 << 20) +#define PPLL1_EN_STAT (1 << 19) + +#define CRG_IVP_SEC_RSTDIS_REG (CRG_REG_BASE + 0xC04) +#define CRG_ISP_SEC_RSTDIS_REG (CRG_REG_BASE + 0xC84) + +#define CRG_RVBAR(c, n) (0xE00 + (0x10 * c) + (0x4 * n)) +#define CRG_GENERAL_SEC_RSTEN_REG (CRG_REG_BASE + 0xE20) +#define CRG_GENERAL_SEC_RSTDIS_REG (CRG_REG_BASE + 0xE24) +#define IP_RST_GPIO0_SEC (1 << 2) + +#define CRG_GENERAL_SEC_CLKDIV0_REG (CRG_REG_BASE + 0xE90) +#define SC_DIV_AO_HISE_MASK 3 +#define SC_DIV_AO_HISE(x) ((x) & 0x3) + +#endif /* __HI3660_CRG_H__ */ diff --git a/plat/hisilicon/hikey960/include/hi3660_hkadc.h b/plat/hisilicon/hikey960/include/hi3660_hkadc.h new file mode 100644 index 00000000..6e67114e --- /dev/null +++ b/plat/hisilicon/hikey960/include/hi3660_hkadc.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __HI3660_HKADC_H__ +#define __HI3660_HKADC_H__ + +#define HKADC_SSI_REG_BASE 0xE82B8000 + +#define HKADC_DSP_START_REG (HKADC_SSI_REG_BASE + 0x000) +#define HKADC_WR_NUM_REG (HKADC_SSI_REG_BASE + 0x008) +#define HKADC_DSP_START_CLR_REG (HKADC_SSI_REG_BASE + 0x01C) +#define HKADC_WR01_DATA_REG (HKADC_SSI_REG_BASE + 0x020) + +#define WR1_WRITE_MODE (1 << 31) +#define WR1_READ_MODE (0 << 31) +#define WR1_ADDR(x) (((x) & 0x7F) << 24) +#define WR1_DATA(x) (((x) & 0xFF) << 16) +#define WR0_WRITE_MODE (1 << 15) +#define WR0_READ_MODE (0 << 15) +#define WR0_ADDR(x) (((x) & 0x7F) << 8) +#define WR0_DATA(x) ((x) & 0xFF) + +#define HKADC_WR23_DATA_REG (HKADC_SSI_REG_BASE + 0x024) +#define HKADC_WR45_DATA_REG (HKADC_SSI_REG_BASE + 0x028) +#define HKADC_DELAY01_REG (HKADC_SSI_REG_BASE + 0x030) +#define HKADC_DELAY23_REG (HKADC_SSI_REG_BASE + 0x034) +#define HKADC_DELAY45_REG (HKADC_SSI_REG_BASE + 0x038) +#define HKADC_DSP_RD2_DATA_REG (HKADC_SSI_REG_BASE + 0x048) +#define HKADC_DSP_RD3_DATA_REG (HKADC_SSI_REG_BASE + 0x04C) + +/* HKADC Internal Registers */ +#define HKADC_CTRL_ADDR 0x00 +#define HKADC_START_ADDR 0x01 +#define HKADC_DATA1_ADDR 0x03 /* high 8 bits */ +#define HKADC_DATA0_ADDR 0x04 /* low 8 bits */ +#define HKADC_MODE_CFG 0x0A + +#define HKADC_VALUE_HIGH 0x0FF0 +#define HKADC_VALUE_LOW 0x000F +#define HKADC_VALID_VALUE 0x0FFF + +#define HKADC_CHANNEL_MAX 15 +#define HKADC_VREF_1V8 1800 +#define HKADC_ACCURACY 0x0FFF + +#define HKADC_WR01_VALUE ((HKADC_START_ADDR << 24) | \ + (0x1 << 16)) +#define HKADC_WR23_VALUE ((0x1 << 31) | \ + (HKADC_DATA0_ADDR << 24) | \ + (1 << 15) | \ + (HKADC_DATA1_ADDR << 8)) +#define HKADC_WR45_VALUE (0x80) +#define HKADC_CHANNEL0_DELAY01_VALUE ((0x0700 << 16) | 0xFFFF) +#define HKADC_DELAY01_VALUE ((0x0700 << 16) | 0x0200) +#define HKADC_DELAY23_VALUE ((0x00C8 << 16) | 0x00C8) +#define START_DELAY_TIMEOUT 2000 +#define HKADC_WR_NUM_VALUE 4 + +#endif /* __HI3660_HKADC_H__ */ diff --git a/plat/hisilicon/hikey960/include/hi3660_mem_map.h b/plat/hisilicon/hikey960/include/hi3660_mem_map.h new file mode 100644 index 00000000..db3efaf0 --- /dev/null +++ b/plat/hisilicon/hikey960/include/hi3660_mem_map.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __HI3660_MEM_MAP__ +#define __HI3660_MEM_MAP__ + +#define HISI_DATA_HEAD_BASE (0x89C44400) + +#define HISI_RESERVED_MEM_BASE (0x89C80000) +#define HISI_RESERVED_MEM_SIZE (0x00040000) + +#define HISI_DATA0_BASE (0x89C96180) +#define HISI_DATA0_SIZE (0x000003A0) +#define HISI_DATA1_BASE (0x89C93480) +#define HISI_DATA1_SIZE (0x00002D00) + +#endif /* __HI3660_MEM_MAP__ */ diff --git a/plat/hisilicon/hikey960/include/hisi_ipc.h b/plat/hisilicon/hikey960/include/hisi_ipc.h new file mode 100644 index 00000000..9dda1a57 --- /dev/null +++ b/plat/hisilicon/hikey960/include/hisi_ipc.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __HISI_IPC_H__ +#define __HISI_IPC_H__ + +enum pm_mode { + PM_ON = 0, + PM_OFF, +}; + +void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster, + enum pm_mode mode); +void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster, + unsigned int affinity_level); +void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster); +void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster, + unsigned int cmd_id); +int hisi_ipc_init(void); + +#endif /* __HISI_IPC_H__ */ diff --git a/plat/hisilicon/hikey960/include/plat_macros.S b/plat/hisilicon/hikey960/include/plat_macros.S new file mode 100644 index 00000000..9f1befdc --- /dev/null +++ b/plat/hisilicon/hikey960/include/plat_macros.S @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_MACROS_S__ +#define __PLAT_MACROS_S__ + +#include <cci.h> +#include <hi3660.h> +#include <gic_v2.h> +#include <platform_def.h> + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + +/* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31. + * --------------------------------------------- + */ +.macro plat_crash_print_regs + mov_imm x16, GICD_REG_BASE + mov_imm x17, GICC_REG_BASE + + /* Load the gicc reg list to x6 */ + adr x6, gicc_regs + /* Load the gicc regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] + /* Store to the crash buf and print to cosole */ + bl str_in_crash_buf_print + + /* Print the GICD_ISPENDR regs */ + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +2: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq 1f + bl asm_print_hex + adr x4, spacer + bl asm_print_str + ldr x4, [x7], #8 + bl asm_print_hex + adr x4, newline + bl asm_print_str + b 2b +1: + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (CCI400_REG_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE3_CLUSTER_IX)) + ldr w8, [x7, #SNOOP_CTRL_REG] + /* Store in x7 the base address of the second interface */ + mov_imm x7, (CCI400_REG_BASE + SLAVE_IFACE_OFFSET( \ + CCI400_SL_IFACE4_CLUSTER_IX)) + ldr w9, [x7, #SNOOP_CTRL_REG] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print +.endm + +#endif /* __PLAT_MACROS_S__ */ diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h new file mode 100644 index 00000000..369117b8 --- /dev/null +++ b/plat/hisilicon/hikey960/include/platform_def.h @@ -0,0 +1,101 @@ +/* + * 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 <arch.h> +#include "../hikey960_def.h" + + +/* + * Generic platform constants + */ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x800 + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_CLUSTER_COUNT 2 +#define PLATFORM_CORE_COUNT_PER_CLUSTER 4 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_CORE_COUNT_PER_CLUSTER) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + 1) + +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 +/* UFS RPMB and UFS User Data */ +#define MAX_IO_BLOCK_DEVICES 2 + + +/* + * Platform memory map related constants + */ + +/* + * BL1 specific defines. + */ +#define BL1_RO_BASE (0x1AC00000) +#define BL1_RO_LIMIT (BL1_RO_BASE + 0x10000) +#define BL1_RW_BASE (BL1_RO_LIMIT) /* 1AC1_0000 */ +#define BL1_RW_SIZE (0x00188000) +#define BL1_RW_LIMIT (0x1B000000) + +/* + * BL2 specific defines. + */ +#define BL2_BASE (BL1_RW_BASE + 0x8000) /* 1AC1_8000 */ +#define BL2_LIMIT (BL2_BASE + 0x40000) /* 1AC5_8000 */ + +/* + * BL31 specific defines. + */ +#define BL31_BASE (BL2_LIMIT) /* 1AC5_8000 */ +#define BL31_LIMIT (BL31_BASE + 0x40000) /* 1AC9_8000 */ + +#define NS_BL1U_BASE (BL31_LIMIT) /* 1AC9_8000 */ +#define NS_BL1U_SIZE (0x00100000) +#define NS_BL1U_LIMIT (NS_BL1U_BASE + NS_BL1U_SIZE) + +#define HIKEY960_NS_IMAGE_OFFSET (0x1AC18000) /* offset in l-loader */ +#define HIKEY960_NS_TMP_OFFSET (0x1AE00000) + +#define SCP_BL2_BASE BL31_BASE + +#define SCP_MEM_BASE (0x89C80000) +#define SCP_MEM_SIZE (0x00040000) + +/* + * Platform specific page table and MMU setup constants + */ +#define ADDR_SPACE_SIZE (1ull << 32) + +#if IMAGE_BL1 || IMAGE_BL2 || IMAGE_BL31 +#define MAX_XLAT_TABLES 3 +#endif + +#define MAX_MMAP_REGIONS 16 + +/* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + */ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk new file mode 100644 index 00000000..145eee0e --- /dev/null +++ b/plat/hisilicon/hikey960/platform.mk @@ -0,0 +1,65 @@ +# +# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +CRASH_CONSOLE_BASE := PL011_UART6_BASE +COLD_BOOT_SINGLE_CPU := 1 +PROGRAMMABLE_RESET_ADDRESS := 1 + +# Process flags +$(eval $(call add_define,CRASH_CONSOLE_BASE)) +$(eval $(call FIP_ADD_IMG,SCP_BL2,--scp-fw)) + +ENABLE_PLAT_COMPAT := 0 + +USE_COHERENT_MEM := 1 + +PLAT_INCLUDES := -Iinclude/common/tbbr \ + -Iplat/hisilicon/hikey960/include + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/pl011_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/aarch64/xlat_tables.c \ + plat/hisilicon/hikey960/aarch64/hikey960_common.c \ + plat/hisilicon/hikey960/hikey960_boardid.c + +HIKEY960_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c + +BL1_SOURCES += bl1/tbbr/tbbr_img_desc.c \ + drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/synopsys/ufs/dw_ufs.c \ + drivers/ufs/ufs.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \ + plat/hisilicon/hikey960/hikey960_bl1_setup.c \ + plat/hisilicon/hikey960/hikey960_io_storage.c \ + ${HIKEY960_GIC_SOURCES} + +BL2_SOURCES += drivers/io/io_block.c \ + drivers/io/io_fip.c \ + drivers/io/io_storage.c \ + drivers/ufs/ufs.c \ + plat/hisilicon/hikey960/hikey960_bl2_setup.c \ + plat/hisilicon/hikey960/hikey960_io_storage.c \ + plat/hisilicon/hikey960/hikey960_mcu_load.c + +BL31_SOURCES += drivers/arm/cci/cci.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/cortex_a73.S \ + plat/common/aarch64/plat_psci_common.c \ + plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \ + plat/hisilicon/hikey960/hikey960_bl31_setup.c \ + plat/hisilicon/hikey960/hikey960_pm.c \ + plat/hisilicon/hikey960/hikey960_topology.c \ + plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c \ + plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c \ + ${HIKEY960_GIC_SOURCES} diff --git a/plat/rockchip/common/aarch64/platform_common.c b/plat/rockchip/common/aarch64/platform_common.c index 9c68b3bc..a756f40d 100644 --- a/plat/rockchip/common/aarch64/platform_common.c +++ b/plat/rockchip/common/aarch64/platform_common.c @@ -44,7 +44,7 @@ static const int cci_map[] = { coh_limit - coh_start, \ MT_DEVICE | MT_RW | MT_SECURE); \ mmap_add(plat_rk_mmap); \ - rockchip_plat_sram_mmu_el##_el(); \ + rockchip_plat_mmu_el##_el(); \ init_xlat_tables(); \ \ enable_mmu_el ## _el(0); \ diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c index 71d66c97..f7564e81 100644 --- a/plat/rockchip/common/bl31_plat_setup.c +++ b/plat/rockchip/common/bl31_plat_setup.c @@ -83,8 +83,6 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2, bl32_ep_info = *from_bl2->bl32_ep_info; bl33_ep_info = *from_bl2->bl33_ep_info; - plat_rockchip_pmusram_prepare(); - /* there may have some board sepcific message need to initialize */ params_early_setup(plat_params_from_bl2); } diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h index 867d9add..b9540f23 100644 --- a/plat/rockchip/common/include/plat_private.h +++ b/plat/rockchip/common/include/plat_private.h @@ -15,12 +15,18 @@ #define __sramdata __attribute__((section(".sram.data"))) #define __sramconst __attribute__((section(".sram.rodata"))) -#define __sramfunc __attribute__((section(".sram.text"))) \ - __attribute__((noinline)) +#define __sramfunc __attribute__((section(".sram.text"))) + +#define __pmusramdata __attribute__((section(".pmusram.data"))) +#define __pmusramconst __attribute__((section(".pmusram.rodata"))) +#define __pmusramfunc __attribute__((section(".pmusram.text"))) extern uint32_t __bl31_sram_text_start, __bl31_sram_text_end; extern uint32_t __bl31_sram_data_start, __bl31_sram_data_end; +extern uint32_t __bl31_sram_stack_start, __bl31_sram_stack_end; +extern uint32_t __bl31_sram_text_real_end, __bl31_sram_data_real_end; extern uint32_t __sram_incbin_start, __sram_incbin_end; +extern uint32_t __sram_incbin_real_end; /****************************************************************************** @@ -73,7 +79,6 @@ void plat_rockchip_gic_cpuif_enable(void); void plat_rockchip_gic_cpuif_disable(void); void plat_rockchip_gic_pcpu_init(void); -void plat_rockchip_pmusram_prepare(void); void plat_rockchip_pmu_init(void); void plat_rockchip_soc_init(void); uintptr_t plat_get_sec_entrypoint(void); @@ -110,15 +115,13 @@ void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void); extern const unsigned char rockchip_power_domain_tree_desc[]; -extern void *pmu_cpuson_entrypoint_start; -extern void *pmu_cpuson_entrypoint_end; +extern void *pmu_cpuson_entrypoint; extern uint64_t cpuson_entry_point[PLATFORM_CORE_COUNT]; extern uint32_t cpuson_flags[PLATFORM_CORE_COUNT]; extern const mmap_region_t plat_rk_mmap[]; -void rockchip_plat_sram_mmu_el3(void); -void plat_rockchip_mem_prepare(void); +void rockchip_plat_mmu_el3(void); #endif /* __ASSEMBLY__ */ diff --git a/plat/rockchip/common/pmusram/pmu_sram.c b/plat/rockchip/common/pmusram/pmu_sram.c deleted file mode 100644 index 05ee762e..00000000 --- a/plat/rockchip/common/pmusram/pmu_sram.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <console.h> -#include <debug.h> -#include <platform.h> -#include <plat_private.h> - -/***************************************************************************** - * sram only surpport 32-bits access - ******************************************************************************/ -void u32_align_cpy(uint32_t *dst, const uint32_t *src, size_t bytes) -{ - uint32_t i; - - for (i = 0; i < bytes; i++) - dst[i] = src[i]; -} - -void rockchip_plat_sram_mmu_el3(void) -{ -#ifdef PLAT_EXTRA_LD_SCRIPT - size_t sram_size; - - /* sram.text size */ - sram_size = (char *)&__bl31_sram_text_end - - (char *)&__bl31_sram_text_start; - mmap_add_region((unsigned long)&__bl31_sram_text_start, - (unsigned long)&__bl31_sram_text_start, - sram_size, MT_MEMORY | MT_RO | MT_SECURE); - - /* sram.data size */ - sram_size = (char *)&__bl31_sram_data_end - - (char *)&__bl31_sram_data_start; - mmap_add_region((unsigned long)&__bl31_sram_data_start, - (unsigned long)&__bl31_sram_data_start, - sram_size, MT_MEMORY | MT_RW | MT_SECURE); - - /* sram.incbin size */ - sram_size = (char *)&__sram_incbin_end - (char *)&__sram_incbin_start; - mmap_add_region((unsigned long)&__sram_incbin_start, - (unsigned long)&__sram_incbin_start, - sram_size, MT_NON_CACHEABLE | MT_RW | MT_SECURE); -#else - /* TODO: Support other SoCs, Just support RK3399 now */ - return; -#endif -} - -void plat_rockchip_mem_prepare(void) -{ - /* The code for resuming cpu from suspend must be excuted in pmusram */ - plat_rockchip_pmusram_prepare(); -} diff --git a/plat/rockchip/common/pmusram/pmu_sram.h b/plat/rockchip/common/pmusram/pmu_sram.h deleted file mode 100644 index 24a1c25e..00000000 --- a/plat/rockchip/common/pmusram/pmu_sram.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef __PMU_SRAM_H__ -#define __PMU_SRAM_H__ - -/***************************************************************************** - * define data offset in struct psram_data - *****************************************************************************/ -#define PSRAM_DT_SP 0x0 -#define PSRAM_DT_DDR_FUNC 0x8 -#define PSRAM_DT_DDR_DATA 0x10 -#define PSRAM_DT_DDRFLAG 0x18 -#define PSRAM_DT_MPIDR 0x1c -#define PSRAM_DT_END 0x20 -/****************************************************************************** - * Allocate data region for struct psram_data_t in pmusram - ******************************************************************************/ -/* Needed aligned 16 bytes for sp stack top */ -#define PSRAM_DT_SIZE (((PSRAM_DT_END + 16) / 16) * 16) -#define PSRAM_DT_BASE ((PMUSRAM_BASE + PMUSRAM_RSIZE) - PSRAM_DT_SIZE) -#define PSRAM_SP_TOP PSRAM_DT_BASE - -#ifndef __ASSEMBLY__ - -struct psram_data_t { - uint64_t sp; - uint64_t ddr_func; - uint64_t ddr_data; - uint32_t ddr_flag; - uint32_t boot_mpidr; -}; - -CASSERT(sizeof(struct psram_data_t) <= PSRAM_DT_SIZE, - assert_psram_dt_size_mismatch); -CASSERT(__builtin_offsetof(struct psram_data_t, sp) == PSRAM_DT_SP, - assert_psram_dt_sp_offset_mistmatch); -CASSERT(__builtin_offsetof(struct psram_data_t, ddr_func) == PSRAM_DT_DDR_FUNC, - assert_psram_dt_ddr_func_offset_mistmatch); -CASSERT(__builtin_offsetof(struct psram_data_t, ddr_data) == PSRAM_DT_DDR_DATA, - assert_psram_dt_ddr_data_offset_mistmatch); -CASSERT(__builtin_offsetof(struct psram_data_t, ddr_flag) == PSRAM_DT_DDRFLAG, - assert_psram_dt_ddr_flag_offset_mistmatch); -CASSERT(__builtin_offsetof(struct psram_data_t, boot_mpidr) == PSRAM_DT_MPIDR, - assert_psram_dt_mpidr_offset_mistmatch); -void u32_align_cpy(uint32_t *dst, const uint32_t *src, size_t bytes); - -#endif /* __ASSEMBLY__ */ - -#endif diff --git a/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S index 8f175c3c..22bdffca 100644 --- a/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S +++ b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S @@ -7,23 +7,30 @@ #include <arch.h> #include <asm_macros.S> #include <platform_def.h> -#include <pmu_sram.h> - .globl pmu_cpuson_entrypoint_start - .globl pmu_cpuson_entrypoint_end + .globl pmu_cpuson_entrypoint + .macro pmusram_entry_func _name + .section .pmusram.entry, "ax" + .type \_name, %function + .func \_name + .cfi_startproc + \_name: + .endm -func pmu_cpuson_entrypoint -pmu_cpuson_entrypoint_start: - ldr x5, psram_data +pmusram_entry_func pmu_cpuson_entrypoint + +#if PSRAM_CHECK_WAKEUP_CPU check_wake_cpus: mrs x0, MPIDR_EL1 and x1, x0, #MPIDR_CPU_MASK and x0, x0, #MPIDR_CLUSTER_MASK orr x0, x0, x1 + /* primary_cpu */ - ldr w1, [x5, #PSRAM_DT_MPIDR] + ldr w1, boot_mpidr cmp w0, w1 b.eq sys_wakeup + /* * If the core is not the primary cpu, * force the core into wfe. @@ -32,25 +39,15 @@ wfe_loop: wfe b wfe_loop sys_wakeup: - /* check ddr flag for resume ddr */ - ldr w2, [x5, #PSRAM_DT_DDRFLAG] - cmp w2, #0x0 - b.eq sys_resume +#endif + +#if PSRAM_DO_DDR_RESUME ddr_resume: - ldr x2, [x5, #PSRAM_DT_SP] - mov sp, x2 - ldr x1, [x5, #PSRAM_DT_DDR_FUNC] - ldr x0, [x5, #PSRAM_DT_DDR_DATA] - blr x1 + ldr x2, =__bl31_sram_stack_end + mov sp, x2 + bl dmc_restore +#endif + bl sram_restore sys_resume: - ldr x1, sys_wakeup_entry - br x1 - - .align 3 -psram_data: - .quad PSRAM_DT_BASE -sys_wakeup_entry: - .quad psci_entrypoint -pmu_cpuson_entrypoint_end: - .word 0 + bl psci_entrypoint endfunc pmu_cpuson_entrypoint diff --git a/plat/rockchip/rk3328/drivers/pmu/pmu.c b/plat/rockchip/rk3328/drivers/pmu/pmu.c index 59d399be..60f36d31 100644 --- a/plat/rockchip/rk3328/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3328/drivers/pmu/pmu.c @@ -16,16 +16,12 @@ #include <platform.h> #include <platform_def.h> #include <plat_private.h> -#include <pmu_sram.h> #include <pmu.h> #include <rk3328_def.h> #include <pmu_com.h> DEFINE_BAKERY_LOCK(rockchip_pd_lock); -static struct psram_data_t *psram_sleep_cfg = - (struct psram_data_t *)PSRAM_DT_BASE; - static struct rk3328_sleep_ddr_data ddr_data; static __sramdata struct rk3328_sleep_sram_data sram_data; @@ -34,22 +30,6 @@ static uint32_t cpu_warm_boot_addr; #pragma weak rk3328_pmic_suspend #pragma weak rk3328_pmic_resume -void plat_rockchip_pmusram_prepare(void) -{ - uint32_t *sram_dst, *sram_src; - size_t sram_size = 2; - /* - * pmu sram code and data prepare - */ - sram_dst = (uint32_t *)PMUSRAM_BASE; - sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start; - sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end - - (uint32_t *)sram_src; - u32_align_cpy(sram_dst, sram_src, sram_size); - - psram_sleep_cfg->sp = PSRAM_DT_BASE; -} - static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) { uint32_t pd_reg, apm_reg; @@ -140,6 +120,16 @@ static void nonboot_cpus_off(void) } } +void sram_save(void) +{ + /* TODO: support the sdram save for rk3328 SoCs*/ +} + +void sram_restore(void) +{ + /* TODO: support the sdram restore for rk3328 SoCs */ +} + int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) { uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); @@ -495,11 +485,6 @@ __sramfunc void rk3328_pmic_resume(void) sram_udelay(100); } -static inline void rockchip_set_sram_sp(uint64_t set_sp) -{ - __asm volatile("mov sp, %0\n"::"r" (set_sp) : "sp"); -} - static __sramfunc void ddr_suspend(void) { sram_data.pd_sr_idle_save = mmio_read_32(DDR_UPCTL_BASE + @@ -538,7 +523,7 @@ static __sramfunc void ddr_suspend(void) dpll_suspend(); } -static __sramfunc void ddr_resume(void) +__sramfunc void dmc_restore(void) { dpll_resume(); @@ -574,7 +559,7 @@ static __sramfunc void sram_dbg_uart_suspend(void) mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(2), 0x00040004); } -static __sramfunc void sram_dbg_uart_resume(void) +__sramfunc void sram_dbg_uart_resume(void) { /* restore uart clk and reset fifo */ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(16), 0x20000000); @@ -610,7 +595,7 @@ __sramfunc void sram_suspend(void) disable_mmu_icache_el3(); mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), - (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) | + ((uintptr_t)&pmu_cpuson_entrypoint >> CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); /* ddr self-refresh and gating phy */ @@ -623,28 +608,8 @@ __sramfunc void sram_suspend(void) sram_soc_enter_lp(); } -static __sramfunc void sys_resume_first(void) -{ - sram_dbg_uart_resume(); - - rk3328_pmic_resume(); - - /* ddr self-refresh exit */ - ddr_resume(); - - /* disable apm cfg */ - mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(0), CORES_PM_DISABLE); - - /* the warm booting address of cpus */ - mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), - (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | - CPU_BOOT_ADDR_WMASK); -} - void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void) { - rockchip_set_sram_sp(PSRAM_DT_BASE); - sram_suspend(); /* should never reach here */ @@ -671,6 +636,11 @@ int rockchip_soc_sys_pwr_dm_resume(void) return 0; } +void rockchip_plat_mmu_el3(void) +{ + /* TODO: support the el3 for rk3328 SoCs */ +} + void plat_rockchip_pmu_init(void) { uint32_t cpu; @@ -679,10 +649,6 @@ void plat_rockchip_pmu_init(void) cpuson_flags[cpu] = 0; cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; - psram_sleep_cfg->ddr_func = (uint64_t)sys_resume_first; - psram_sleep_cfg->ddr_data = 0x00; - psram_sleep_cfg->ddr_flag = 0x01; - psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; /* the warm booting address of cpus */ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), diff --git a/plat/rockchip/rk3328/include/plat.ld.S b/plat/rockchip/rk3328/include/plat.ld.S index ff17572d..b3559b20 100644 --- a/plat/rockchip/rk3328/include/plat.ld.S +++ b/plat/rockchip/rk3328/include/plat.ld.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,39 +7,31 @@ #define __ROCKCHIP_PLAT_LD_S__ MEMORY { - SRAM (rwx): ORIGIN = SRAM_LDS_BASE, LENGTH = SRAM_LDS_SIZE + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE } SECTIONS { - . = SRAM_LDS_BASE; - ASSERT(. == ALIGN(4096), - "SRAM_BASE address is not aligned on a page boundary.") + . = PMUSRAM_BASE; /* - * The SRAM space allocation for RK3328 - * ---------------- - * | sram text - * ---------------- - * | sram data - * ---------------- + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram */ - .text_sram : ALIGN(4096) { - __bl31_sram_text_start = .; - *(.sram.text) - *(.sram.rodata) - . = ALIGN(4096); - __bl31_sram_text_end = .; - } >SRAM + .text_pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + *(.pmusram.entry) + __bl31_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl31_pmusram_text_end = .; + __bl31_pmusram_data_start = .; + *(.pmusram.data) + __bl31_pmusram_data_end = .; - .data_sram : ALIGN(4096) { - __bl31_sram_data_start = .; - *(.sram.data) - . = ALIGN(4096); - __bl31_sram_data_end = .; - } >SRAM - __sram_incbin_start = .; - __sram_incbin_end = .; + } >PMUSRAM } #endif /* __ROCKCHIP_PLAT_LD_S__ */ diff --git a/plat/rockchip/rk3328/include/platform_def.h b/plat/rockchip/rk3328/include/platform_def.h index 1f49fcdc..7304dcfa 100644 --- a/plat/rockchip/rk3328/include/platform_def.h +++ b/plat/rockchip/rk3328/include/platform_def.h @@ -120,4 +120,7 @@ #define PLAT_RK_PRIMARY_CPU 0x0 +#define PSRAM_DO_DDR_RESUME 0 +#define PSRAM_CHECK_WAKEUP_CPU 0 + #endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk index b81d746b..8863fb4f 100644 --- a/plat/rockchip/rk3328/platform.mk +++ b/plat/rockchip/rk3328/platform.mk @@ -41,7 +41,6 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ ${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c \ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ ${RK_PLAT_COMMON}/bl31_plat_setup.c \ - ${RK_PLAT_COMMON}/pmusram/pmu_sram.c \ ${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S \ ${RK_PLAT_COMMON}/plat_pm.c \ ${RK_PLAT_COMMON}/plat_topology.c \ diff --git a/plat/rockchip/rk3368/drivers/pmu/pmu.c b/plat/rockchip/rk3368/drivers/pmu/pmu.c index e5e68051..1767967f 100644 --- a/plat/rockchip/rk3368/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3368/drivers/pmu/pmu.c @@ -14,7 +14,6 @@ #include <platform_def.h> #include <plat_private.h> #include <rk3368_def.h> -#include <pmu_sram.h> #include <soc.h> #include <pmu.h> #include <ddr_rk3368.h> @@ -22,9 +21,6 @@ DEFINE_BAKERY_LOCK(rockchip_pd_lock); -static struct psram_data_t *psram_sleep_cfg = - (struct psram_data_t *)PSRAM_DT_BASE; - static uint32_t cpu_warm_boot_addr; void rk3368_flash_l2_b(void) @@ -223,54 +219,19 @@ static void pmu_sleep_mode_config(void) dsb(); } -static void ddr_suspend_save(void) -{ - ddr_reg_save(1, psram_sleep_cfg->ddr_data); -} - static void pmu_set_sleep_mode(void) { - ddr_suspend_save(); pmu_sleep_mode_config(); soc_sleep_config(); regs_updata_bit_set(PMU_BASE + PMU_PWRMD_CORE, pmu_mdcr_global_int_dis); regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_glbl_int_dis_b); pmu_scu_b_pwrdn(); mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), - (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) | - CPU_BOOT_ADDR_WMASK); + ((uintptr_t)&pmu_cpuson_entrypoint >> + CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), - (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) | - CPU_BOOT_ADDR_WMASK); -} - -void plat_rockchip_pmusram_prepare(void) -{ - uint32_t *sram_dst, *sram_src; - size_t sram_size = 2; - uint32_t code_size; - - /* pmu sram code and data prepare */ - sram_dst = (uint32_t *)PMUSRAM_BASE; - sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start; - sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end - - (uint32_t *)sram_src; - u32_align_cpy(sram_dst, sram_src, sram_size); - - /* ddr code */ - sram_dst += sram_size; - sram_src = ddr_get_resume_code_base(); - code_size = ddr_get_resume_code_size(); - u32_align_cpy(sram_dst, sram_src, code_size / 4); - psram_sleep_cfg->ddr_func = (uint64_t)sram_dst; - - /* ddr data */ - sram_dst += (code_size / 4); - psram_sleep_cfg->ddr_data = (uint64_t)sram_dst; - - assert((uint64_t)(sram_dst + ddr_get_resume_data_size() / 4) - < PSRAM_SP_BOTTOM); - psram_sleep_cfg->sp = PSRAM_SP_TOP; + ((uintptr_t)&pmu_cpuson_entrypoint >> + CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); } static int cpus_id_power_domain(uint32_t cluster, @@ -319,6 +280,16 @@ static void nonboot_cpus_off(void) } } +void sram_save(void) +{ + /* TODO: support the sdram save for rk3368 SoCs*/ +} + +void sram_restore(void) +{ + /* TODO: support the sdram restore for rk3368 SoCs */ +} + int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) { uint32_t cpu, cluster; @@ -375,11 +346,14 @@ int rockchip_soc_sys_pwr_dm_suspend(void) nonboot_cpus_off(); pmu_set_sleep_mode(); - psram_sleep_cfg->ddr_flag = 0; - return 0; } +void rockchip_plat_mmu_el3(void) +{ + /* TODO: support the el3 for rk3368 SoCs */ +} + void plat_rockchip_pmu_init(void) { uint32_t cpu; @@ -390,8 +364,6 @@ void plat_rockchip_pmu_init(void) for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) cpuson_flags[cpu] = 0; - psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; - nonboot_cpus_off(); INFO("%s(%d): pd status %x\n", __func__, __LINE__, mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); diff --git a/plat/rockchip/rk3368/include/plat.ld.S b/plat/rockchip/rk3368/include/plat.ld.S new file mode 100644 index 00000000..b3559b20 --- /dev/null +++ b/plat/rockchip/rk3368/include/plat.ld.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __ROCKCHIP_PLAT_LD_S__ +#define __ROCKCHIP_PLAT_LD_S__ + +MEMORY { + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE +} + +SECTIONS +{ + . = PMUSRAM_BASE; + + /* + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram + */ + .text_pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + *(.pmusram.entry) + __bl31_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl31_pmusram_text_end = .; + __bl31_pmusram_data_start = .; + *(.pmusram.data) + __bl31_pmusram_data_end = .; + + } >PMUSRAM +} + +#endif /* __ROCKCHIP_PLAT_LD_S__ */ diff --git a/plat/rockchip/rk3368/include/platform_def.h b/plat/rockchip/rk3368/include/platform_def.h index 053f6fe3..07b91e26 100644 --- a/plat/rockchip/rk3368/include/platform_def.h +++ b/plat/rockchip/rk3368/include/platform_def.h @@ -122,4 +122,7 @@ #define PLAT_RK_PRIMARY_CPU 0x0 +#define PSRAM_DO_DDR_RESUME 0 +#define PSRAM_CHECK_WAKEUP_CPU 0 + #endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk index 7837af98..f6960cf4 100644 --- a/plat/rockchip/rk3368/platform.mk +++ b/plat/rockchip/rk3368/platform.mk @@ -39,7 +39,6 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ ${RK_PLAT_COMMON}/bl31_plat_setup.c \ ${RK_PLAT_COMMON}/params_setup.c \ ${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S \ - ${RK_PLAT_COMMON}/pmusram/pmu_sram.c \ ${RK_PLAT_COMMON}/plat_pm.c \ ${RK_PLAT_COMMON}/plat_topology.c \ ${RK_PLAT_COMMON}/aarch64/platform_common.c \ @@ -50,3 +49,5 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ ${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c \ ENABLE_PLAT_COMPAT := 0 + +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.c b/plat/rockchip/rk3399/drivers/dram/dfs.c index 28d0d6a7..481dcc64 100644 --- a/plat/rockchip/rk3399/drivers/dram/dfs.c +++ b/plat/rockchip/rk3399/drivers/dram/dfs.c @@ -54,6 +54,7 @@ struct rk3399_saved_status { static struct rk3399_dram_status rk3399_dram_status; static struct rk3399_saved_status rk3399_suspend_status; static uint32_t wrdqs_delay_val[2][2][4]; +static uint32_t rddqs_delay_ps; static struct rk3399_sdram_default_config ddr3_default_config = { .bl = 8, @@ -1599,7 +1600,7 @@ static void gen_rk3399_phy_params(struct timing_related_config *timing_config, mmio_clrsetbits_32(PHY_REG(i, 394), 0xf, tmp); /* PHY_GTLVL_LAT_ADJ_START */ /* DENALI_PHY_80/208/336/464 4bits offset_16 */ - tmp = delay_frac_ps / 1000; + tmp = rddqs_delay_ps / (1000000 / pdram_timing->mhz) + 2; mmio_clrsetbits_32(PHY_REG(i, 80), 0xf << 16, tmp << 16); mmio_clrsetbits_32(PHY_REG(i, 208), 0xf << 16, tmp << 16); mmio_clrsetbits_32(PHY_REG(i, 336), 0xf << 16, tmp << 16); @@ -1830,6 +1831,7 @@ static void dram_low_power_config(void) void dram_dfs_init(void) { uint32_t trefi0, trefi1, boot_freq; + uint32_t rddqs_adjust, rddqs_slave; /* get sdram config for os reg */ get_dram_drv_odt_val(sdram_config.dramtype, @@ -1875,8 +1877,31 @@ void dram_dfs_init(void) /* Disable multicast */ mmio_clrbits_32(PHY_REG(0, 896), 1); mmio_clrbits_32(PHY_REG(1, 896), 1); - dram_low_power_config(); + + /* + * If boot_freq isn't in the bypass mode, it can get the + * rddqs_delay_ps from the result of gate training + */ + if (((mmio_read_32(PHY_REG(0, 86)) >> 8) & 0xf) != 0xc) { + + /* + * Select PHY's frequency set to current_index + * index for get the result of gate Training + * from registers + */ + mmio_clrsetbits_32(PHY_REG(0, 896), 0x3 << 8, + rk3399_dram_status.current_index << 8); + rddqs_slave = (mmio_read_32(PHY_REG(0, 77)) >> 16) & 0x3ff; + rddqs_slave = rddqs_slave * 1000000 / boot_freq / 512; + + rddqs_adjust = mmio_read_32(PHY_REG(0, 78)) & 0xf; + rddqs_adjust = rddqs_adjust * 1000000 / boot_freq; + rddqs_delay_ps = rddqs_slave + rddqs_adjust - + (1000000 / boot_freq / 2); + } else { + rddqs_delay_ps = 3500; + } } /* diff --git a/plat/rockchip/rk3399/drivers/dram/dram.c b/plat/rockchip/rk3399/drivers/dram/dram.c index fbf31107..ad79f9ef 100644 --- a/plat/rockchip/rk3399/drivers/dram/dram.c +++ b/plat/rockchip/rk3399/drivers/dram/dram.c @@ -10,7 +10,7 @@ #include <soc.h> #include <rk3399_def.h> -__sramdata struct rk3399_sdram_params sdram_config; +__pmusramdata struct rk3399_sdram_params sdram_config; void dram_init(void) { diff --git a/plat/rockchip/rk3399/drivers/dram/dram.h b/plat/rockchip/rk3399/drivers/dram/dram.h index 08893d4e..fede7eef 100644 --- a/plat/rockchip/rk3399/drivers/dram/dram.h +++ b/plat/rockchip/rk3399/drivers/dram/dram.h @@ -24,7 +24,17 @@ struct rk3399_ddr_pctl_regs { }; struct rk3399_ddr_publ_regs { - uint32_t denali_phy[PHY_REG_NUM]; + /* + * PHY registers from 0 to 511. + * Only registers 0-90 of each 128 register range are used. + */ + uint32_t phy0[4][91]; + /* + * PHY registers from 512 to 895. + * Only registers 0-37 of each 128 register range are used. + */ + uint32_t phy512[3][38]; + uint32_t phy896[63]; }; struct rk3399_ddr_pi_regs { diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.c b/plat/rockchip/rk3399/drivers/dram/suspend.c index 1ed3f546..617e39ba 100644 --- a/plat/rockchip/rk3399/drivers/dram/suspend.c +++ b/plat/rockchip/rk3399/drivers/dram/suspend.c @@ -45,7 +45,8 @@ /* * Copy @num registers from @src to @dst */ -__sramfunc void sram_regcpy(uintptr_t dst, uintptr_t src, uint32_t num) +static __pmusramfunc void sram_regcpy(uintptr_t dst, uintptr_t src, + uint32_t num) { while (num--) { mmio_write_32(dst, mmio_read_32(src)); @@ -54,7 +55,21 @@ __sramfunc void sram_regcpy(uintptr_t dst, uintptr_t src, uint32_t num) } } -static __sramfunc uint32_t sram_get_timer_value(void) +/* + * Copy @num registers from @src to @dst + * This is intentionally a copy of the sram_regcpy function. PMUSRAM functions + * cannot be called from code running in DRAM. + */ +static void dram_regcpy(uintptr_t dst, uintptr_t src, uint32_t num) +{ + while (num--) { + mmio_write_32(dst, mmio_read_32(src)); + dst += sizeof(uint32_t); + src += sizeof(uint32_t); + } +} + +static __pmusramfunc uint32_t sram_get_timer_value(void) { /* * Generic delay timer implementation expects the timer to be a down @@ -64,7 +79,7 @@ static __sramfunc uint32_t sram_get_timer_value(void) return (uint32_t)(~read_cntpct_el0()); } -static __sramfunc void sram_udelay(uint32_t usec) +static __pmusramfunc void sram_udelay(uint32_t usec) { uint32_t start, cnt, delta, delta_us; @@ -81,7 +96,7 @@ static __sramfunc void sram_udelay(uint32_t usec) } while (delta_us < usec); } -static __sramfunc void configure_sgrf(void) +static __pmusramfunc void configure_sgrf(void) { /* * SGRF_DDR_RGN_DPLL_CLK and SGRF_DDR_RGN_RTC_CLK: @@ -98,7 +113,7 @@ static __sramfunc void configure_sgrf(void) SGRF_DDR_RGN_BYPS); } -static __sramfunc void rkclk_ddr_reset(uint32_t channel, uint32_t ctl, +static __pmusramfunc void rkclk_ddr_reset(uint32_t channel, uint32_t ctl, uint32_t phy) { channel &= 0x1; @@ -109,7 +124,7 @@ static __sramfunc void rkclk_ddr_reset(uint32_t channel, uint32_t ctl, CRU_SFTRST_DDR_PHY(channel, phy)); } -static __sramfunc void phy_pctrl_reset(uint32_t ch) +static __pmusramfunc void phy_pctrl_reset(uint32_t ch) { rkclk_ddr_reset(ch, 1, 1); sram_udelay(10); @@ -119,76 +134,45 @@ static __sramfunc void phy_pctrl_reset(uint32_t ch) sram_udelay(10); } -static __sramfunc void phy_dll_bypass_set(uint32_t ch, uint32_t hz) +static __pmusramfunc void set_cs_training_index(uint32_t ch, uint32_t rank) { - if (hz <= 125 * MHz) { - /* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */ - mmio_setbits_32(PHY_REG(ch, 86), (0x3 << 2) << 8); - mmio_setbits_32(PHY_REG(ch, 214), (0x3 << 2) << 8); - mmio_setbits_32(PHY_REG(ch, 342), (0x3 << 2) << 8); - mmio_setbits_32(PHY_REG(ch, 470), (0x3 << 2) << 8); - /* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */ - mmio_setbits_32(PHY_REG(ch, 547), (0x3 << 2) << 16); - mmio_setbits_32(PHY_REG(ch, 675), (0x3 << 2) << 16); - mmio_setbits_32(PHY_REG(ch, 803), (0x3 << 2) << 16); - } else { - /* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */ - mmio_clrbits_32(PHY_REG(ch, 86), (0x3 << 2) << 8); - mmio_clrbits_32(PHY_REG(ch, 214), (0x3 << 2) << 8); - mmio_clrbits_32(PHY_REG(ch, 342), (0x3 << 2) << 8); - mmio_clrbits_32(PHY_REG(ch, 470), (0x3 << 2) << 8); - /* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */ - mmio_clrbits_32(PHY_REG(ch, 547), (0x3 << 2) << 16); - mmio_clrbits_32(PHY_REG(ch, 675), (0x3 << 2) << 16); - mmio_clrbits_32(PHY_REG(ch, 803), (0x3 << 2) << 16); - } -} + uint32_t byte; -static __sramfunc void set_cs_training_index(uint32_t ch, uint32_t rank) -{ /* PHY_8/136/264/392 phy_per_cs_training_index_X 1bit offset_24 */ - mmio_clrsetbits_32(PHY_REG(ch, 8), 0x1 << 24, rank << 24); - mmio_clrsetbits_32(PHY_REG(ch, 136), 0x1 << 24, rank << 24); - mmio_clrsetbits_32(PHY_REG(ch, 264), 0x1 << 24, rank << 24); - mmio_clrsetbits_32(PHY_REG(ch, 392), 0x1 << 24, rank << 24); + for (byte = 0; byte < 4; byte++) + mmio_clrsetbits_32(PHY_REG(ch, 8 + (128 * byte)), 0x1 << 24, + rank << 24); } -static __sramfunc void select_per_cs_training_index(uint32_t ch, uint32_t rank) +static __pmusramfunc void select_per_cs_training_index(uint32_t ch, + uint32_t rank) { /* PHY_84 PHY_PER_CS_TRAINING_EN_0 1bit offset_16 */ if ((mmio_read_32(PHY_REG(ch, 84)) >> 16) & 1) set_cs_training_index(ch, rank); } -static void override_write_leveling_value(uint32_t ch) +static __pmusramfunc void override_write_leveling_value(uint32_t ch) { uint32_t byte; - /* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */ - mmio_setbits_32(PHY_REG(ch, 896), 1); - - /* - * PHY_8/136/264/392 - * phy_per_cs_training_multicast_en_X 1bit offset_16 - */ - mmio_clrsetbits_32(PHY_REG(ch, 8), 0x1 << 16, 1 << 16); - mmio_clrsetbits_32(PHY_REG(ch, 136), 0x1 << 16, 1 << 16); - mmio_clrsetbits_32(PHY_REG(ch, 264), 0x1 << 16, 1 << 16); - mmio_clrsetbits_32(PHY_REG(ch, 392), 0x1 << 16, 1 << 16); - - for (byte = 0; byte < 4; byte++) + for (byte = 0; byte < 4; byte++) { + /* + * PHY_8/136/264/392 + * phy_per_cs_training_multicast_en_X 1bit offset_16 + */ + mmio_clrsetbits_32(PHY_REG(ch, 8 + (128 * byte)), 0x1 << 16, + 1 << 16); mmio_clrsetbits_32(PHY_REG(ch, 63 + (128 * byte)), 0xffff << 16, 0x200 << 16); - - /* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */ - mmio_clrbits_32(PHY_REG(ch, 896), 1); + } /* CTL_200 ctrlupd_req 1bit offset_8 */ mmio_clrsetbits_32(CTL_REG(ch, 200), 0x1 << 8, 0x1 << 8); } -static __sramfunc int data_training(uint32_t ch, +static __pmusramfunc int data_training(uint32_t ch, struct rk3399_sdram_params *sdram_params, uint32_t training_flag) { @@ -433,7 +417,8 @@ static __sramfunc int data_training(uint32_t ch, return 0; } -static __sramfunc void set_ddrconfig(struct rk3399_sdram_params *sdram_params, +static __pmusramfunc void set_ddrconfig( + struct rk3399_sdram_params *sdram_params, unsigned char channel, uint32_t ddrconfig) { /* only need to set ddrconfig */ @@ -455,7 +440,8 @@ static __sramfunc void set_ddrconfig(struct rk3399_sdram_params *sdram_params, ((cs0_cap / 32) & 0xff) | (((cs1_cap / 32) & 0xff) << 8)); } -static __sramfunc void dram_all_config(struct rk3399_sdram_params *sdram_params) +static __pmusramfunc void dram_all_config( + struct rk3399_sdram_params *sdram_params) { unsigned int i; @@ -491,13 +477,13 @@ static __sramfunc void dram_all_config(struct rk3399_sdram_params *sdram_params) mmio_clrsetbits_32(CRU_BASE + CRU_GLB_RST_CON, 0x3, 0x3); } -static __sramfunc void pctl_cfg(uint32_t ch, +static __pmusramfunc void pctl_cfg(uint32_t ch, struct rk3399_sdram_params *sdram_params) { const uint32_t *params_ctl = sdram_params->pctl_regs.denali_ctl; - const uint32_t *params_phy = sdram_params->phy_regs.denali_phy; const uint32_t *params_pi = sdram_params->pi_regs.denali_pi; - uint32_t tmp, tmp1, tmp2; + const struct rk3399_ddr_publ_regs *phy_regs = &sdram_params->phy_regs; + uint32_t tmp, tmp1, tmp2, i; /* * Workaround controller bug: @@ -509,9 +495,8 @@ static __sramfunc void pctl_cfg(uint32_t ch, sram_regcpy(PI_REG(ch, 0), (uintptr_t)¶ms_pi[0], PI_REG_NUM); - mmio_write_32(PHY_REG(ch, 910), params_phy[910]); - mmio_write_32(PHY_REG(ch, 911), params_phy[911]); - mmio_write_32(PHY_REG(ch, 912), params_phy[912]); + sram_regcpy(PHY_REG(ch, 910), (uintptr_t)&phy_regs->phy896[910 - 896], + 3); mmio_clrsetbits_32(CTL_REG(ch, 68), PWRUP_SREFRESH_EXIT, PWRUP_SREFRESH_EXIT); @@ -538,17 +523,18 @@ static __sramfunc void pctl_cfg(uint32_t ch, break; } - sram_regcpy(PHY_REG(ch, 896), (uintptr_t)¶ms_phy[896], 63); - sram_regcpy(PHY_REG(ch, 0), (uintptr_t)¶ms_phy[0], 91); - sram_regcpy(PHY_REG(ch, 128), (uintptr_t)¶ms_phy[128], 91); - sram_regcpy(PHY_REG(ch, 256), (uintptr_t)¶ms_phy[256], 91); - sram_regcpy(PHY_REG(ch, 384), (uintptr_t)¶ms_phy[384], 91); - sram_regcpy(PHY_REG(ch, 512), (uintptr_t)¶ms_phy[512], 38); - sram_regcpy(PHY_REG(ch, 640), (uintptr_t)¶ms_phy[640], 38); - sram_regcpy(PHY_REG(ch, 768), (uintptr_t)¶ms_phy[768], 38); + sram_regcpy(PHY_REG(ch, 896), (uintptr_t)&phy_regs->phy896[0], 63); + + for (i = 0; i < 4; i++) + sram_regcpy(PHY_REG(ch, 128 * i), + (uintptr_t)&phy_regs->phy0[i][0], 91); + + for (i = 0; i < 3; i++) + sram_regcpy(PHY_REG(ch, 512 + 128 * i), + (uintptr_t)&phy_regs->phy512[i][0], 38); } -static __sramfunc int dram_switch_to_next_index( +static __pmusramfunc int dram_switch_to_next_index( struct rk3399_sdram_params *sdram_params) { uint32_t ch, ch_count; @@ -583,7 +569,7 @@ static __sramfunc int dram_switch_to_next_index( * Needs to be done for both channels at once in case of a shared reset signal * between channels. */ -static __sramfunc int pctl_start(uint32_t channel_mask, +static __pmusramfunc int pctl_start(uint32_t channel_mask, struct rk3399_sdram_params *sdram_params) { uint32_t count; @@ -652,15 +638,15 @@ static __sramfunc int pctl_start(uint32_t channel_mask, void dmc_save(void) { struct rk3399_sdram_params *sdram_params = &sdram_config; + struct rk3399_ddr_publ_regs *phy_regs; uint32_t *params_ctl; uint32_t *params_pi; - uint32_t *params_phy; uint32_t refdiv, postdiv2, postdiv1, fbdiv; - uint32_t tmp, ch, byte; + uint32_t tmp, ch, byte, i; + phy_regs = &sdram_params->phy_regs; params_ctl = sdram_params->pctl_regs.denali_ctl; params_pi = sdram_params->pi_regs.denali_pi; - params_phy = sdram_params->phy_regs.denali_phy; fbdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 0)) & 0xfff; tmp = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)); @@ -676,25 +662,26 @@ void dmc_save(void) 0x7) != 0) ? 1 : 0; /* copy the registers CTL PI and PHY */ - sram_regcpy((uintptr_t)¶ms_ctl[0], CTL_REG(0, 0), CTL_REG_NUM); + dram_regcpy((uintptr_t)¶ms_ctl[0], CTL_REG(0, 0), CTL_REG_NUM); /* mask DENALI_CTL_00_DATA.START, only copy here, will trigger later */ params_ctl[0] &= ~(0x1 << 0); - sram_regcpy((uintptr_t)¶ms_pi[0], PI_REG(0, 0), + dram_regcpy((uintptr_t)¶ms_pi[0], PI_REG(0, 0), PI_REG_NUM); /* mask DENALI_PI_00_DATA.START, only copy here, will trigger later*/ params_pi[0] &= ~(0x1 << 0); - sram_regcpy((uintptr_t)¶ms_phy[0], PHY_REG(0, 0), 91); - sram_regcpy((uintptr_t)¶ms_phy[128], PHY_REG(0, 128), 91); - sram_regcpy((uintptr_t)¶ms_phy[256], PHY_REG(0, 256), 91); - sram_regcpy((uintptr_t)¶ms_phy[384], PHY_REG(0, 384), 91); - sram_regcpy((uintptr_t)¶ms_phy[512], PHY_REG(0, 512), 38); - sram_regcpy((uintptr_t)¶ms_phy[640], PHY_REG(0, 640), 38); - sram_regcpy((uintptr_t)¶ms_phy[768], PHY_REG(0, 768), 38); - sram_regcpy((uintptr_t)¶ms_phy[896], PHY_REG(0, 896), 63); + for (i = 0; i < 4; i++) + dram_regcpy((uintptr_t)&phy_regs->phy0[i][0], + PHY_REG(0, 128 * i), 91); + + for (i = 0; i < 3; i++) + dram_regcpy((uintptr_t)&phy_regs->phy512[i][0], + PHY_REG(0, 512 + 128 * i), 38); + + dram_regcpy((uintptr_t)&phy_regs->phy896[0], PHY_REG(0, 896), 63); for (ch = 0; ch < sdram_params->num_channels; ch++) { for (byte = 0; byte < 4; byte++) @@ -703,13 +690,13 @@ void dmc_save(void) } /* set DENALI_PHY_957_DATA.PHY_DLL_RST_EN = 0x1 */ - params_phy[957] &= ~(0x3 << 24); - params_phy[957] |= 1 << 24; - params_phy[896] |= 1; - params_phy[896] &= ~(0x3 << 8); + phy_regs->phy896[957 - 896] &= ~(0x3 << 24); + phy_regs->phy896[957 - 896] |= 1 << 24; + phy_regs->phy896[0] |= 1; + phy_regs->phy896[0] &= ~(0x3 << 8); } -__sramfunc void dmc_restore(void) +__pmusramfunc void dmc_restore(void) { struct rk3399_sdram_params *sdram_params = &sdram_config; uint32_t channel_mask = 0; @@ -720,10 +707,6 @@ __sramfunc void dmc_restore(void) retry: for (channel = 0; channel < sdram_params->num_channels; channel++) { phy_pctrl_reset(channel); - phy_dll_bypass_set(channel, sdram_params->ddr_freq); - if (channel >= sdram_params->num_channels) - continue; - pctl_cfg(channel, sdram_params); } diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.h b/plat/rockchip/rk3399/drivers/dram/suspend.h index 03df421f..77f9c317 100644 --- a/plat/rockchip/rk3399/drivers/dram/suspend.h +++ b/plat/rockchip/rk3399/drivers/dram/suspend.h @@ -20,7 +20,6 @@ #define PI_FULL_TRAINING (0xff) void dmc_save(void); -__sramfunc void dmc_restore(void); -__sramfunc void sram_regcpy(uintptr_t dst, uintptr_t src, uint32_t num); +__pmusramfunc void dmc_restore(void); #endif /* __DRAM_H__ */ diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index 9c0a29c1..f6c47f43 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -19,9 +19,9 @@ #include <plat_params.h> #include <plat_private.h> #include <rk3399_def.h> -#include <pmu_sram.h> #include <secure.h> #include <soc.h> +#include <string.h> #include <pmu.h> #include <pmu_com.h> #include <pwm.h> @@ -30,10 +30,8 @@ DEFINE_BAKERY_LOCK(rockchip_pd_lock); -static struct psram_data_t *psram_sleep_cfg = - (struct psram_data_t *)PSRAM_DT_BASE; - static uint32_t cpu_warm_boot_addr; +static char store_sram[SRAM_BIN_LIMIT + SRAM_TEXT_LIMIT + SRAM_DATA_LIMIT]; /* * There are two ways to powering on or off on core. @@ -411,24 +409,6 @@ static void pmu_scu_b_pwrup(void) mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); } -void plat_rockchip_pmusram_prepare(void) -{ - uint32_t *sram_dst, *sram_src; - size_t sram_size; - - /* - * pmu sram code and data prepare - */ - sram_dst = (uint32_t *)PMUSRAM_BASE; - sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start; - sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end - - (uint32_t *)sram_src; - - u32_align_cpy(sram_dst, sram_src, sram_size); - - psram_sleep_cfg->sp = PSRAM_DT_BASE; -} - static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) { assert(cpu_id < PLATFORM_CORE_COUNT); @@ -782,14 +762,24 @@ static void init_pmu_counts(void) mmio_write_32(PMU_BASE + PMU_CENTER_PWRUP_CNT, CYCL_24M_CNT_MS(1)); /* + * when we enable PMU_CLR_PERILP, it will shut down the SRAM, but + * M0 code run in SRAM, and we need it to check whether cpu enter + * FSM status, so we must wait M0 finish their code and enter WFI, + * then we can shutdown SRAM, according FSM order: + * ST_NORMAL->..->ST_SCU_L_PWRDN->..->ST_CENTER_PWRDN->ST_PERILP_PWRDN + * we can add delay when shutdown ST_SCU_L_PWRDN to guarantee M0 get + * the FSM status and enter WFI, then enable PMU_CLR_PERILP. + */ + mmio_write_32(PMU_BASE + PMU_SCU_L_PWRDN_CNT, CYCL_24M_CNT_MS(5)); + mmio_write_32(PMU_BASE + PMU_SCU_L_PWRUP_CNT, CYCL_24M_CNT_US(1)); + + /* * Set CPU/GPU to 1 us. * * NOTE: Even though ATF doesn't configure the GPU we'll still setup * counts here. After all ATF controls all these other bits and also * chooses which clock these counters use. */ - mmio_write_32(PMU_BASE + PMU_SCU_L_PWRDN_CNT, CYCL_24M_CNT_US(1)); - mmio_write_32(PMU_BASE + PMU_SCU_L_PWRUP_CNT, CYCL_24M_CNT_US(1)); mmio_write_32(PMU_BASE + PMU_SCU_B_PWRDN_CNT, CYCL_24M_CNT_US(1)); mmio_write_32(PMU_BASE + PMU_SCU_B_PWRUP_CNT, CYCL_24M_CNT_US(1)); mmio_write_32(PMU_BASE + PMU_GPU_PWRDN_CNT, CYCL_24M_CNT_US(1)); @@ -837,6 +827,8 @@ static void sys_slp_config(void) BIT(PMU_DDRIO1_RET_EN) | BIT(PMU_DDRIO_RET_HW_DE_REQ) | BIT(PMU_CENTER_PD_EN) | + BIT(PMU_PERILP_PD_EN) | + BIT(PMU_CLK_PERILP_SRC_GATE_EN) | BIT(PMU_PLL_PD_EN) | BIT(PMU_CLK_CENTER_SRC_GATE_EN) | BIT(PMU_OSC_DIS) | @@ -1050,6 +1042,36 @@ static void m0_configure_suspend(void) mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_SUSPEND); } +void sram_save(void) +{ + size_t text_size = (char *)&__bl31_sram_text_real_end - + (char *)&__bl31_sram_text_start; + size_t data_size = (char *)&__bl31_sram_data_real_end - + (char *)&__bl31_sram_data_start; + size_t incbin_size = (char *)&__sram_incbin_real_end - + (char *)&__sram_incbin_start; + + memcpy(&store_sram[0], &__bl31_sram_text_start, text_size); + memcpy(&store_sram[text_size], &__bl31_sram_data_start, data_size); + memcpy(&store_sram[text_size + data_size], &__sram_incbin_start, + incbin_size); +} + +void sram_restore(void) +{ + size_t text_size = (char *)&__bl31_sram_text_real_end - + (char *)&__bl31_sram_text_start; + size_t data_size = (char *)&__bl31_sram_data_real_end - + (char *)&__bl31_sram_data_start; + size_t incbin_size = (char *)&__sram_incbin_real_end - + (char *)&__sram_incbin_start; + + memcpy(&__bl31_sram_text_start, &store_sram[0], text_size); + memcpy(&__bl31_sram_data_start, &store_sram[text_size], data_size); + memcpy(&__sram_incbin_start, &store_sram[text_size + data_size], + incbin_size); +} + int rockchip_soc_sys_pwr_dm_suspend(void) { uint32_t wait_cnt = 0; @@ -1067,6 +1089,8 @@ int rockchip_soc_sys_pwr_dm_suspend(void) BIT(PMU_CLR_CCIM0) | BIT(PMU_CLR_CCIM1) | BIT(PMU_CLR_CENTER) | + BIT(PMU_CLR_PERILP) | + BIT(PMU_CLR_PERILPM0) | BIT(PMU_CLR_GIC)); sys_slp_config(); @@ -1077,8 +1101,8 @@ int rockchip_soc_sys_pwr_dm_suspend(void) pmu_sgrf_rst_hld(); mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), - (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) | - CPU_BOOT_ADDR_WMASK); + ((uintptr_t)&pmu_cpuson_entrypoint >> + CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); mmio_write_32(PMU_BASE + PMU_ADB400_CON, BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | @@ -1112,6 +1136,7 @@ int rockchip_soc_sys_pwr_dm_suspend(void) suspend_apio(); suspend_gpio(); + sram_save(); return 0; } @@ -1193,6 +1218,8 @@ int rockchip_soc_sys_pwr_dm_resume(void) BIT(PMU_CLR_CCIM0) | BIT(PMU_CLR_CCIM1) | BIT(PMU_CLR_CENTER) | + BIT(PMU_CLR_PERILP) | + BIT(PMU_CLR_PERILPM0) | BIT(PMU_CLR_GIC)); plat_rockchip_gic_cpuif_enable(); @@ -1245,6 +1272,36 @@ void __dead2 rockchip_soc_system_off(void) ; } +void rockchip_plat_mmu_el3(void) +{ + size_t sram_size; + + /* sram.text size */ + sram_size = (char *)&__bl31_sram_text_end - + (char *)&__bl31_sram_text_start; + mmap_add_region((unsigned long)&__bl31_sram_text_start, + (unsigned long)&__bl31_sram_text_start, + sram_size, MT_MEMORY | MT_RO | MT_SECURE); + + /* sram.data size */ + sram_size = (char *)&__bl31_sram_data_end - + (char *)&__bl31_sram_data_start; + mmap_add_region((unsigned long)&__bl31_sram_data_start, + (unsigned long)&__bl31_sram_data_start, + sram_size, MT_MEMORY | MT_RW | MT_SECURE); + + sram_size = (char *)&__bl31_sram_stack_end - + (char *)&__bl31_sram_stack_start; + mmap_add_region((unsigned long)&__bl31_sram_stack_start, + (unsigned long)&__bl31_sram_stack_start, + sram_size, MT_MEMORY | MT_RW | MT_SECURE); + + sram_size = (char *)&__sram_incbin_end - (char *)&__sram_incbin_start; + mmap_add_region((unsigned long)&__sram_incbin_start, + (unsigned long)&__sram_incbin_start, + sram_size, MT_NON_CACHEABLE | MT_RW | MT_SECURE); +} + void plat_rockchip_pmu_init(void) { uint32_t cpu; @@ -1260,12 +1317,6 @@ void plat_rockchip_pmu_init(void) for (cpu = 0; cpu < PLATFORM_CLUSTER_COUNT; cpu++) clst_warmboot_data[cpu] = 0; - psram_sleep_cfg->ddr_func = (uint64_t)dmc_restore; - psram_sleep_cfg->ddr_data = (uint64_t)&sdram_config; - psram_sleep_cfg->ddr_flag = 0x01; - - psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; - /* config cpu's warm boot address */ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | diff --git a/plat/rockchip/rk3399/include/plat.ld.S b/plat/rockchip/rk3399/include/plat.ld.S index 49206bea..c42d9a9a 100644 --- a/plat/rockchip/rk3399/include/plat.ld.S +++ b/plat/rockchip/rk3399/include/plat.ld.S @@ -8,6 +8,7 @@ MEMORY { SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE } SECTIONS @@ -29,24 +30,60 @@ SECTIONS .incbin_sram : ALIGN(4096) { __sram_incbin_start = .; *(.sram.incbin) + __sram_incbin_real_end = .; . = ALIGN(4096); __sram_incbin_end = .; } >SRAM + ASSERT((__sram_incbin_real_end - __sram_incbin_start) <= + SRAM_BIN_LIMIT, ".incbin_sram has exceeded its limit") .text_sram : ALIGN(4096) { __bl31_sram_text_start = .; *(.sram.text) *(.sram.rodata) + __bl31_sram_text_real_end = .; . = ALIGN(4096); __bl31_sram_text_end = .; } >SRAM + ASSERT((__bl31_sram_text_real_end - __bl31_sram_text_start) <= + SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit") .data_sram : ALIGN(4096) { __bl31_sram_data_start = .; *(.sram.data) + __bl31_sram_data_real_end = .; . = ALIGN(4096); __bl31_sram_data_end = .; } >SRAM + ASSERT((__bl31_sram_data_real_end - __bl31_sram_data_start) <= + SRAM_DATA_LIMIT, ".data_sram has exceeded its limit") + + .stack_sram : ALIGN(4096) { + __bl31_sram_stack_start = .; + . += 4096; + __bl31_sram_stack_end = .; + } >SRAM + + . = PMUSRAM_BASE; + + /* + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram + */ + .pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + *(.pmusram.entry) + __bl31_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl31_pmusram_text_end = .; + __bl31_pmusram_data_start = .; + *(.pmusram.data) + __bl31_pmusram_data_end = .; + + } >PMUSRAM } #endif /* __ROCKCHIP_PLAT_LD_S__ */ diff --git a/plat/rockchip/rk3399/include/platform_def.h b/plat/rockchip/rk3399/include/platform_def.h index f4427d01..3df2f7dc 100644 --- a/plat/rockchip/rk3399/include/platform_def.h +++ b/plat/rockchip/rk3399/include/platform_def.h @@ -107,4 +107,7 @@ #define PLAT_RK_PRIMARY_CPU 0x0 +#define PSRAM_DO_DDR_RESUME 1 +#define PSRAM_CHECK_WAKEUP_CPU 0 + #endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/rockchip/rk3399/include/shared/addressmap_shared.h b/plat/rockchip/rk3399/include/shared/addressmap_shared.h index d72633e5..fe23e569 100644 --- a/plat/rockchip/rk3399/include/shared/addressmap_shared.h +++ b/plat/rockchip/rk3399/include/shared/addressmap_shared.h @@ -9,6 +9,9 @@ #define SIZE_K(n) ((n) * 1024) #define SIZE_M(n) ((n) * 1024 * 1024) +#define SRAM_TEXT_LIMIT (4 * 1024) +#define SRAM_DATA_LIMIT (4 * 1024) +#define SRAM_BIN_LIMIT (4 * 1024) /* * The parts of the shared defined registers address with AP and M0, diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index be3e11b9..cb7999b5 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -44,7 +44,6 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ ${RK_PLAT_COMMON}/bl31_plat_setup.c \ ${RK_PLAT_COMMON}/params_setup.c \ ${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S \ - ${RK_PLAT_COMMON}/pmusram/pmu_sram.c \ ${RK_PLAT_COMMON}/plat_pm.c \ ${RK_PLAT_COMMON}/plat_topology.c \ ${RK_PLAT_COMMON}/aarch64/platform_common.c \ |